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
26
#include <drizzled/server_includes.h>
28
#include <drizzled/drizzled_error_messages.h>
30
/** Day number for Dec 31st, 9999. */
31
#define MAX_DAY_NUMBER 3652424L
36
- Replace the switch with a function that should be called for each
38
- Remove sprintf and opencode the conversion, like we do in
41
The reason for this functions existence is that as we don't have a
42
way to know if a datetime/time value has microseconds in them
43
we are now only adding microseconds to the output if the
44
value has microseconds.
46
We can't use a standard make_date_time() for this as we don't know
47
if someone will use %f in the format specifier in which case we would get
48
the microseconds twice.
51
static bool make_datetime(date_time_format_types format, DRIZZLE_TIME *ltime,
55
const CHARSET_INFO * const cs= &my_charset_bin;
56
uint32_t length= MAX_DATE_STRING_REP_LENGTH;
58
if (str->alloc(length))
60
buff= (char*) str->ptr();
64
length= cs->cset->snprintf(cs, buff, length, "%s%02d:%02d:%02d",
65
ltime->neg ? "-" : "",
66
ltime->hour, ltime->minute, ltime->second);
68
case TIME_MICROSECOND:
69
length= cs->cset->snprintf(cs, buff, length, "%s%02d:%02d:%02d.%06ld",
70
ltime->neg ? "-" : "",
71
ltime->hour, ltime->minute, ltime->second,
75
length= cs->cset->snprintf(cs, buff, length, "%04d-%02d-%02d",
76
ltime->year, ltime->month, ltime->day);
79
length= cs->cset->snprintf(cs, buff, length,
80
"%04d-%02d-%02d %02d:%02d:%02d",
81
ltime->year, ltime->month, ltime->day,
82
ltime->hour, ltime->minute, ltime->second);
84
case DATE_TIME_MICROSECOND:
85
length= cs->cset->snprintf(cs, buff, length,
86
"%04d-%02d-%02d %02d:%02d:%02d.%06ld",
87
ltime->year, ltime->month, ltime->day,
88
ltime->hour, ltime->minute, ltime->second,
100
Wrapper over make_datetime() with validation of the input DRIZZLE_TIME value
103
see make_datetime() for more information
106
1 if there was an error during converion
110
static bool make_datetime_with_warn(date_time_format_types format, DRIZZLE_TIME *ltime,
115
if (make_datetime(format, ltime, str))
117
if (check_time_range(ltime, &warning))
122
make_truncated_value_warning(current_thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
123
str->ptr(), str->length(),
124
DRIZZLE_TIMESTAMP_TIME, NULL);
125
return make_datetime(format, ltime, str);
130
Wrapper over make_time() with validation of the input DRIZZLE_TIME value
133
see make_time() for more info
136
1 if there was an error during conversion
140
static bool make_time_with_warn(const DATE_TIME_FORMAT *format,
141
DRIZZLE_TIME *l_time, String *str)
144
make_time(format, l_time, str);
145
if (check_time_range(l_time, &warning))
149
make_truncated_value_warning(current_thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
150
str->ptr(), str->length(),
151
DRIZZLE_TIMESTAMP_TIME, NULL);
152
make_time(format, l_time, str);
160
Convert seconds to DRIZZLE_TIME value with overflow checking
164
seconds number of seconds
165
unsigned_flag 1, if 'seconds' is unsigned, 0, otherwise
166
ltime output DRIZZLE_TIME value
169
If the 'seconds' argument is inside DRIZZLE_TIME data range, convert it to a
171
Otherwise, truncate the resulting value to the nearest endpoint, and
172
produce a warning message.
175
1 if the value was truncated during conversion
179
static bool sec_to_time(int64_t seconds, bool unsigned_flag, DRIZZLE_TIME *ltime)
183
memset(ltime, 0, sizeof(*ltime));
188
if (seconds < -3020399)
192
else if (seconds > 3020399)
195
sec= (uint) ((uint64_t) seconds % 3600);
196
ltime->hour= (uint) (seconds/3600);
197
ltime->minute= sec/60;
198
ltime->second= sec % 60;
203
ltime->hour= TIME_MAX_HOUR;
204
ltime->minute= TIME_MAX_MINUTE;
205
ltime->second= TIME_MAX_SECOND;
208
int len= (int)(int64_t10_to_str(seconds, buf, unsigned_flag ? 10 : -10)
210
make_truncated_value_warning(current_thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
211
buf, len, DRIZZLE_TIMESTAMP_TIME,
219
Date formats corresponding to compound %r and %T conversion specifiers
221
Note: We should init at least first element of "positions" array
222
(first member) or hpux11 compiler will die horribly.
224
static DATE_TIME_FORMAT time_ampm_format= {{0}, '\0', 0,
225
{(char *)"%I:%i:%S %p", 11}};
226
static DATE_TIME_FORMAT time_24hrs_format= {{0}, '\0', 0,
227
{(char *)"%H:%i:%S", 8}};
230
Extract datetime value to DRIZZLE_TIME struct from string value
231
according to format string.
233
@param format date/time format specification
234
@param val String to decode
235
@param length Length of string
236
@param l_time Store result here
237
@param cached_timestamp_type It uses to get an appropriate warning
238
in the case when the value is truncated.
239
@param sub_pattern_end if non-zero then we are parsing string which
240
should correspond compound specifier (like %T or
241
%r) and this parameter is pointer to place where
242
pointer to end of string matching this specifier
246
Possibility to parse strings matching to patterns equivalent to compound
247
specifiers is mainly intended for use from inside of this function in
248
order to understand %T and %r conversion specifiers, so number of
249
conversion specifiers that can be used in such sub-patterns is limited.
250
Also most of checks are skipped in this case.
253
If one adds new format specifiers to this function he should also
254
consider adding them to get_date_time_result_type() function.
262
static bool extract_date_time(DATE_TIME_FORMAT *format,
263
const char *val, uint32_t length, DRIZZLE_TIME *l_time,
264
enum enum_drizzle_timestamp_type cached_timestamp_type,
265
const char **sub_pattern_end,
266
const char *date_time_type)
268
int weekday= 0, yearday= 0, daypart= 0;
271
int strict_week_number_year= -1;
274
bool sunday_first_n_first_week_non_iso= false;
275
bool strict_week_number= false;
276
bool strict_week_number_year_type= false;
277
const char *val_begin= val;
278
const char *val_end= val + length;
279
const char *ptr= format->format.str;
280
const char *end= ptr + format->format.length;
281
const CHARSET_INFO * const cs= &my_charset_bin;
283
if (!sub_pattern_end)
284
memset(l_time, 0, sizeof(*l_time));
286
for (; ptr != end && val != val_end; ptr++)
288
/* Skip pre-space between each argument */
289
while (val != val_end && my_isspace(cs, *val))
292
if (*ptr == '%' && ptr+1 != end)
299
val_len= (uint) (val_end - val);
303
tmp= (char*) val + cmin(4, val_len);
304
l_time->year= (int) my_strtoll10(val, &tmp, &error);
305
if ((int) (tmp-val) <= 2)
306
l_time->year= year_2000_handling(l_time->year);
310
tmp= (char*) val + cmin(2, val_len);
311
l_time->year= (int) my_strtoll10(val, &tmp, &error);
313
l_time->year= year_2000_handling(l_time->year);
319
tmp= (char*) val + cmin(2, val_len);
320
l_time->month= (int) my_strtoll10(val, &tmp, &error);
324
if ((l_time->month= check_word(my_locale_en_US.month_names,
325
val, val_end, &val)) <= 0)
329
if ((l_time->month= check_word(my_locale_en_US.ab_month_names,
330
val, val_end, &val)) <= 0)
336
tmp= (char*) val + cmin(2, val_len);
337
l_time->day= (int) my_strtoll10(val, &tmp, &error);
341
tmp= (char*) val + cmin(2, val_len);
342
l_time->day= (int) my_strtoll10(val, &tmp, &error);
343
/* Skip 'st, 'nd, 'th .. */
344
val= tmp + cmin((int) (val_end-tmp), 2);
355
tmp= (char*) val + cmin(2, val_len);
356
l_time->hour= (int) my_strtoll10(val, &tmp, &error);
362
tmp= (char*) val + cmin(2, val_len);
363
l_time->minute= (int) my_strtoll10(val, &tmp, &error);
370
tmp= (char*) val + cmin(2, val_len);
371
l_time->second= (int) my_strtoll10(val, &tmp, &error);
377
tmp= (char*) val_end;
379
tmp= (char*) val + 6;
380
l_time->second_part= (int) my_strtoll10(val, &tmp, &error);
381
frac_part= 6 - (tmp - val);
383
l_time->second_part*= (ulong) log_10_int[frac_part];
389
if (val_len < 2 || ! usa_time)
391
if (!my_strnncoll(&my_charset_utf8_general_ci,
392
(const unsigned char *) val, 2,
393
(const unsigned char *) "PM", 2))
395
else if (my_strnncoll(&my_charset_utf8_general_ci,
396
(const unsigned char *) val, 2,
397
(const unsigned char *) "AM", 2))
404
if ((weekday= check_word(my_locale_en_US.day_names, val, val_end, &val)) <= 0)
408
if ((weekday= check_word(my_locale_en_US.ab_day_names, val, val_end, &val)) <= 0)
412
tmp= (char*) val + 1;
413
if ((weekday= (int) my_strtoll10(val, &tmp, &error)) < 0 ||
416
/* We should use the same 1 - 7 scale for %w as for %W */
422
tmp= (char*) val + cmin(val_len, 3);
423
yearday= (int) my_strtoll10(val, &tmp, &error);
432
sunday_first_n_first_week_non_iso= (*ptr=='U' || *ptr== 'V');
433
strict_week_number= (*ptr=='V' || *ptr=='v');
434
tmp= (char*) val + cmin(val_len, 2);
435
if ((week_number= (int) my_strtoll10(val, &tmp, &error)) < 0 ||
436
(strict_week_number && !week_number) ||
442
/* Year used with 'strict' %V and %v week numbers */
445
strict_week_number_year_type= (*ptr=='X');
446
tmp= (char*) val + cmin(4, val_len);
447
strict_week_number_year= (int) my_strtoll10(val, &tmp, &error);
451
/* Time in AM/PM notation */
454
We can't just set error here, as we don't want to generate two
455
warnings in case of errors
457
if (extract_date_time(&time_ampm_format, val,
458
(uint)(val_end - val), l_time,
459
cached_timestamp_type, &val, "time"))
463
/* Time in 24-hour notation */
465
if (extract_date_time(&time_24hrs_format, val,
466
(uint)(val_end - val), l_time,
467
cached_timestamp_type, &val, "time"))
471
/* Conversion specifiers that match classes of characters */
473
while (my_ispunct(cs, *val) && val != val_end)
477
while (my_isalpha(cs, *val) && val != val_end)
481
while (my_isdigit(cs, *val) && val != val_end)
487
if (error) // Error from my_strtoll10
490
else if (!my_isspace(cs, *ptr))
499
if (l_time->hour > 12 || l_time->hour < 1)
501
l_time->hour= l_time->hour%12+daypart;
505
If we are recursively called for parsing string matching compound
506
specifiers we are already done.
510
*sub_pattern_end= val;
517
days= calc_daynr(l_time->year,1,1) + yearday - 1;
518
if (days <= 0 || days > MAX_DAY_NUMBER)
520
get_date_from_daynr(days,&l_time->year,&l_time->month,&l_time->day);
523
if (week_number >= 0 && weekday)
529
%V,%v require %X,%x resprectively,
530
%U,%u should be used with %Y and not %X or %x
532
if ((strict_week_number &&
533
(strict_week_number_year < 0 || (strict_week_number_year_type != sunday_first_n_first_week_non_iso))) ||
534
(!strict_week_number && strict_week_number_year >= 0))
537
/* Number of days since year 0 till 1st Jan of this year */
538
days= calc_daynr((strict_week_number ? strict_week_number_year :
541
/* Which day of week is 1st Jan of this year */
542
weekday_b= calc_weekday(days, sunday_first_n_first_week_non_iso);
545
Below we are going to sum:
546
1) number of days since year 0 till 1st day of 1st week of this year
547
2) number of days between 1st week and our week
548
3) and position of our day in the week
550
if (sunday_first_n_first_week_non_iso)
552
days+= ((weekday_b == 0) ? 0 : 7) - weekday_b +
553
(week_number - 1) * 7 +
558
days+= ((weekday_b <= 3) ? 0 : 7) - weekday_b +
559
(week_number - 1) * 7 +
563
if (days <= 0 || days > MAX_DAY_NUMBER)
565
get_date_from_daynr(days,&l_time->year,&l_time->month,&l_time->day);
568
if (l_time->month > 12 || l_time->day > 31 || l_time->hour > 23 ||
569
l_time->minute > 59 || l_time->second > 59)
576
if (!my_isspace(&my_charset_utf8_general_ci,*val))
578
make_truncated_value_warning(current_thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
580
cached_timestamp_type, NULL);
583
} while (++val != val_end);
590
strmake(buff, val_begin, cmin(length, (uint)sizeof(buff)-1));
591
push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
592
ER_WRONG_VALUE_FOR_TYPE, ER(ER_WRONG_VALUE_FOR_TYPE),
593
date_time_type, buff, "str_to_date");
600
Create a formated date/time value in a string.
603
bool make_date_time(DATE_TIME_FORMAT *format, DRIZZLE_TIME *l_time,
604
enum enum_drizzle_timestamp_type type, String *str)
610
const char *ptr, *end;
611
THD *thd= current_thd;
612
MY_LOCALE *locale= thd->variables.lc_time_names;
619
end= (ptr= format->format.str) + format->format.length;
620
for (; ptr != end ; ptr++)
622
if (*ptr != '%' || ptr+1 == end)
630
str->append(locale->month_names->type_names[l_time->month-1],
631
strlen(locale->month_names->type_names[l_time->month-1]),
632
system_charset_info);
637
str->append(locale->ab_month_names->type_names[l_time->month-1],
638
strlen(locale->ab_month_names->type_names[l_time->month-1]),
639
system_charset_info);
642
if (type == DRIZZLE_TIMESTAMP_TIME)
644
weekday= calc_weekday(calc_daynr(l_time->year,l_time->month,
646
str->append(locale->day_names->type_names[weekday],
647
strlen(locale->day_names->type_names[weekday]),
648
system_charset_info);
651
if (type == DRIZZLE_TIMESTAMP_TIME)
653
weekday=calc_weekday(calc_daynr(l_time->year,l_time->month,
655
str->append(locale->ab_day_names->type_names[weekday],
656
strlen(locale->ab_day_names->type_names[weekday]),
657
system_charset_info);
660
if (type == DRIZZLE_TIMESTAMP_TIME)
662
length= int10_to_str(l_time->day, intbuff, 10) - intbuff;
663
str->append_with_prefill(intbuff, length, 1, '0');
664
if (l_time->day >= 10 && l_time->day <= 19)
665
str->append(STRING_WITH_LEN("th"));
668
switch (l_time->day %10) {
670
str->append(STRING_WITH_LEN("st"));
673
str->append(STRING_WITH_LEN("nd"));
676
str->append(STRING_WITH_LEN("rd"));
679
str->append(STRING_WITH_LEN("th"));
685
length= int10_to_str(l_time->year, intbuff, 10) - intbuff;
686
str->append_with_prefill(intbuff, length, 4, '0');
689
length= int10_to_str(l_time->year%100, intbuff, 10) - intbuff;
690
str->append_with_prefill(intbuff, length, 2, '0');
693
length= int10_to_str(l_time->month, intbuff, 10) - intbuff;
694
str->append_with_prefill(intbuff, length, 2, '0');
697
length= int10_to_str(l_time->month, intbuff, 10) - intbuff;
698
str->append_with_prefill(intbuff, length, 1, '0');
701
length= int10_to_str(l_time->day, intbuff, 10) - intbuff;
702
str->append_with_prefill(intbuff, length, 2, '0');
705
length= int10_to_str(l_time->day, intbuff, 10) - intbuff;
706
str->append_with_prefill(intbuff, length, 1, '0');
709
length= int10_to_str(l_time->second_part, intbuff, 10) - intbuff;
710
str->append_with_prefill(intbuff, length, 6, '0');
713
length= int10_to_str(l_time->hour, intbuff, 10) - intbuff;
714
str->append_with_prefill(intbuff, length, 2, '0');
718
hours_i= (l_time->hour%24 + 11)%12+1;
719
length= int10_to_str(hours_i, intbuff, 10) - intbuff;
720
str->append_with_prefill(intbuff, length, 2, '0');
722
case 'i': /* minutes */
723
length= int10_to_str(l_time->minute, intbuff, 10) - intbuff;
724
str->append_with_prefill(intbuff, length, 2, '0');
727
if (type == DRIZZLE_TIMESTAMP_TIME)
729
length= int10_to_str(calc_daynr(l_time->year,l_time->month,
731
calc_daynr(l_time->year,1,1) + 1, intbuff, 10) - intbuff;
732
str->append_with_prefill(intbuff, length, 3, '0');
735
length= int10_to_str(l_time->hour, intbuff, 10) - intbuff;
736
str->append_with_prefill(intbuff, length, 1, '0');
739
hours_i= (l_time->hour%24 + 11)%12+1;
740
length= int10_to_str(hours_i, intbuff, 10) - intbuff;
741
str->append_with_prefill(intbuff, length, 1, '0');
744
hours_i= l_time->hour%24;
745
str->append(hours_i < 12 ? "AM" : "PM",2);
748
length= sprintf(intbuff,
749
((l_time->hour % 24) < 12) ?
750
"%02d:%02d:%02d AM" : "%02d:%02d:%02d PM",
751
(l_time->hour+11)%12+1,
754
str->append(intbuff, length);
758
length= int10_to_str(l_time->second, intbuff, 10) - intbuff;
759
str->append_with_prefill(intbuff, length, 2, '0');
762
length= sprintf(intbuff,
767
str->append(intbuff, length);
773
if (type == DRIZZLE_TIMESTAMP_TIME)
775
length= int10_to_str(calc_week(l_time,
777
WEEK_FIRST_WEEKDAY : WEEK_MONDAY_FIRST,
779
intbuff, 10) - intbuff;
780
str->append_with_prefill(intbuff, length, 2, '0');
787
if (type == DRIZZLE_TIMESTAMP_TIME)
789
length= int10_to_str(calc_week(l_time,
791
(WEEK_YEAR | WEEK_FIRST_WEEKDAY) :
792
(WEEK_YEAR | WEEK_MONDAY_FIRST)),
794
intbuff, 10) - intbuff;
795
str->append_with_prefill(intbuff, length, 2, '0');
802
if (type == DRIZZLE_TIMESTAMP_TIME)
804
(void) calc_week(l_time,
806
WEEK_YEAR | WEEK_FIRST_WEEKDAY :
807
WEEK_YEAR | WEEK_MONDAY_FIRST),
809
length= int10_to_str(year, intbuff, 10) - intbuff;
810
str->append_with_prefill(intbuff, length, 4, '0');
814
if (type == DRIZZLE_TIMESTAMP_TIME)
816
weekday=calc_weekday(calc_daynr(l_time->year,l_time->month,
818
length= int10_to_str(weekday, intbuff, 10) - intbuff;
819
str->append_with_prefill(intbuff, length, 1, '0');
834
Get a array of positive numbers from a string object.
835
Each number is separated by 1 non digit character
836
Return error if there is too many numbers.
837
If there is too few numbers, assume that the numbers are left out
838
from the high end. This allows one to give:
839
DAY_TO_SECOND as "D MM:HH:SS", "MM:HH:SS" "HH:SS" or as seconds.
841
@param length: length of str
842
@param cs: charset of str
843
@param values: array of results
844
@param count: count of elements in result array
845
@param transform_msec: if value is true we suppose
846
that the last part of string value is microseconds
847
and we should transform value to six digit value.
848
For example, '1.1' -> '1.100000'
851
static bool get_interval_info(const char *str,uint32_t length, const CHARSET_INFO * const cs,
852
uint32_t count, uint64_t *values,
855
const char *end=str+length;
857
while (str != end && !my_isdigit(cs,*str))
860
for (i=0 ; i < count ; i++)
863
const char *start= str;
864
for (value=0; str != end && my_isdigit(cs,*str) ; str++)
865
value= value * 10L + (int64_t) (*str - '0');
866
if (transform_msec && i == count - 1) // microseconds always last
868
long msec_length= 6 - (str - start);
870
value*= (long) log_10_int[msec_length];
873
while (str != end && !my_isdigit(cs,*str))
875
if (str == end && i != count-1)
878
/* Change values[0...i-1] -> values[0...count-1] */
879
bmove_upp((unsigned char*) (values+count), (unsigned char*) (values+i),
881
memset(values, 0, sizeof(*values)*(count-i));
889
int64_t Item_func_period_add::val_int()
892
ulong period=(ulong) args[0]->val_int();
893
int months=(int) args[1]->val_int();
895
if ((null_value=args[0]->null_value || args[1]->null_value) ||
897
return 0; /* purecov: inspected */
899
convert_month_to_period((uint) ((int) convert_period_to_month(period)+
904
int64_t Item_func_period_diff::val_int()
907
ulong period1=(ulong) args[0]->val_int();
908
ulong period2=(ulong) args[1]->val_int();
910
if ((null_value=args[0]->null_value || args[1]->null_value))
911
return 0; /* purecov: inspected */
912
return (int64_t) ((long) convert_period_to_month(period1)-
913
(long) convert_period_to_month(period2));
918
int64_t Item_func_to_days::val_int()
922
if (get_arg0_date(<ime, TIME_NO_ZERO_DATE))
924
return (int64_t) calc_daynr(ltime.year,ltime.month,ltime.day);
929
Get information about this Item tree monotonicity
932
Item_func_to_days::get_monotonicity_info()
935
Get information about monotonicity of the function represented by this item
939
See enum_monotonicity_info.
942
enum_monotonicity_info Item_func_to_days::get_monotonicity_info() const
944
if (args[0]->type() == Item::FIELD_ITEM)
946
if (args[0]->field_type() == DRIZZLE_TYPE_NEWDATE)
947
return MONOTONIC_STRICT_INCREASING;
948
if (args[0]->field_type() == DRIZZLE_TYPE_DATETIME)
949
return MONOTONIC_INCREASING;
951
return NON_MONOTONIC;
955
int64_t Item_func_to_days::val_int_endpoint(bool left_endp, bool *incl_endp)
960
if (get_arg0_date(<ime, TIME_NO_ZERO_DATE))
962
/* got NULL, leave the incl_endp intact */
965
res=(int64_t) calc_daynr(ltime.year,ltime.month,ltime.day);
967
if (args[0]->field_type() == DRIZZLE_TYPE_NEWDATE)
969
// TO_DAYS() is strictly monotonic for dates, leave incl_endp intact
974
Handle the special but practically useful case of datetime values that
975
point to day bound ("strictly less" comparison stays intact):
977
col < '2007-09-15 00:00:00' -> TO_DAYS(col) < TO_DAYS('2007-09-15')
979
which is different from the general case ("strictly less" changes to
982
col < '2007-09-15 12:34:56' -> TO_DAYS(col) <= TO_DAYS('2007-09-15')
984
if (!left_endp && !(ltime.hour || ltime.minute || ltime.second ||
993
int64_t Item_func_dayofyear::val_int()
997
if (get_arg0_date(<ime,TIME_NO_ZERO_DATE))
999
return (int64_t) calc_daynr(ltime.year,ltime.month,ltime.day) -
1000
calc_daynr(ltime.year,1,1) + 1;
1003
int64_t Item_func_dayofmonth::val_int()
1007
(void) get_arg0_date(<ime, TIME_FUZZY_DATE);
1008
return (int64_t) ltime.day;
1011
int64_t Item_func_month::val_int()
1015
(void) get_arg0_date(<ime, TIME_FUZZY_DATE);
1016
return (int64_t) ltime.month;
1020
String* Item_func_monthname::val_str(String* str)
1023
const char *month_name;
1024
uint32_t month= (uint) val_int();
1025
THD *thd= current_thd;
1027
if (null_value || !month)
1033
month_name= thd->variables.lc_time_names->month_names->type_names[month-1];
1034
str->set(month_name, strlen(month_name), system_charset_info);
1040
Returns the quarter of the year.
1043
int64_t Item_func_quarter::val_int()
1047
if (get_arg0_date(<ime, TIME_FUZZY_DATE))
1049
return (int64_t) ((ltime.month+2)/3);
1052
int64_t Item_func_hour::val_int()
1056
(void) get_arg0_time(<ime);
1060
int64_t Item_func_minute::val_int()
1064
(void) get_arg0_time(<ime);
1065
return ltime.minute;
1069
Returns the second in time_exp in the range of 0 - 59.
1071
int64_t Item_func_second::val_int()
1075
(void) get_arg0_time(<ime);
1076
return ltime.second;
1080
uint32_t week_mode(uint32_t mode)
1082
uint32_t week_format= (mode & 7);
1083
if (!(week_format & WEEK_MONDAY_FIRST))
1084
week_format^= WEEK_FIRST_WEEKDAY;
1090
The bits in week_format(for calc_week() function) has the following meaning:
1091
WEEK_MONDAY_FIRST (0) If not set Sunday is first day of week
1092
If set Monday is first day of week
1093
WEEK_YEAR (1) If not set Week is in range 0-53
1095
Week 0 is returned for the the last week of the previous year (for
1096
a date at start of january) In this case one can get 53 for the
1097
first week of next year. This flag ensures that the week is
1098
relevant for the given year. Note that this flag is only
1099
releveant if WEEK_JANUARY is not set.
1101
If set Week is in range 1-53.
1103
In this case one may get week 53 for a date in January (when
1104
the week is that last week of previous year) and week 1 for a
1107
WEEK_FIRST_WEEKDAY (2) If not set Weeks are numbered according
1109
If set The week that contains the first
1110
'first-day-of-week' is week 1.
1112
ISO 8601:1988 means that if the week containing January 1 has
1113
four or more days in the new year, then it is week 1;
1114
Otherwise it is the last week of the previous year, and the
1115
next week is week 1.
1119
int64_t Item_func_week::val_int()
1124
if (get_arg0_date(<ime, TIME_NO_ZERO_DATE))
1126
return (int64_t) calc_week(<ime,
1127
week_mode((uint) args[1]->val_int()),
1132
int64_t Item_func_yearweek::val_int()
1137
if (get_arg0_date(<ime, TIME_NO_ZERO_DATE))
1139
week= calc_week(<ime,
1140
(week_mode((uint) args[1]->val_int()) | WEEK_YEAR),
1142
return week+year*100;
1146
int64_t Item_func_weekday::val_int()
1151
if (get_arg0_date(<ime, TIME_NO_ZERO_DATE))
1154
return (int64_t) calc_weekday(calc_daynr(ltime.year, ltime.month,
1156
odbc_type) + test(odbc_type);
1160
String* Item_func_dayname::val_str(String* str)
1163
uint32_t weekday=(uint) val_int(); // Always Item_func_daynr()
1164
const char *day_name;
1165
THD *thd= current_thd;
1170
day_name= thd->variables.lc_time_names->day_names->type_names[weekday];
1171
str->set(day_name, strlen(day_name), system_charset_info);
1176
int64_t Item_func_year::val_int()
1180
(void) get_arg0_date(<ime, TIME_FUZZY_DATE);
1181
return (int64_t) ltime.year;
1186
Get information about this Item tree monotonicity
1189
Item_func_year::get_monotonicity_info()
1192
Get information about monotonicity of the function represented by this item
1196
See enum_monotonicity_info.
1199
enum_monotonicity_info Item_func_year::get_monotonicity_info() const
1201
if (args[0]->type() == Item::FIELD_ITEM &&
1202
(args[0]->field_type() == DRIZZLE_TYPE_NEWDATE ||
1203
args[0]->field_type() == DRIZZLE_TYPE_DATETIME))
1204
return MONOTONIC_INCREASING;
1205
return NON_MONOTONIC;
1209
int64_t Item_func_year::val_int_endpoint(bool left_endp, bool *incl_endp)
1213
if (get_arg0_date(<ime, TIME_FUZZY_DATE))
1215
/* got NULL, leave the incl_endp intact */
1220
Handle the special but practically useful case of datetime values that
1221
point to year bound ("strictly less" comparison stays intact) :
1223
col < '2007-01-01 00:00:00' -> YEAR(col) < 2007
1225
which is different from the general case ("strictly less" changes to
1228
col < '2007-09-15 23:00:00' -> YEAR(col) <= 2007
1230
if (!left_endp && ltime.day == 1 && ltime.month == 1 &&
1231
!(ltime.hour || ltime.minute || ltime.second || ltime.second_part))
1239
int64_t Item_func_unix_timestamp::val_int()
1246
return (int64_t) current_thd->query_start();
1247
if (args[0]->type() == FIELD_ITEM)
1248
{ // Optimize timestamp field
1249
Field *field=((Item_field*) args[0])->field;
1250
if (field->type() == DRIZZLE_TYPE_TIMESTAMP)
1251
return ((Field_timestamp*) field)->get_timestamp(&null_value);
1254
if (get_arg0_date(<ime, 0))
1257
We have to set null_value again because get_arg0_date will also set it
1258
to true if we have wrong datetime parameter (and we should return 0 in
1261
null_value= args[0]->null_value;
1265
return (int64_t) TIME_to_timestamp(current_thd, <ime, ¬_used);
1269
int64_t Item_func_time_to_sec::val_int()
1274
(void) get_arg0_time(<ime);
1275
seconds=ltime.hour*3600L+ltime.minute*60+ltime.second;
1276
return ltime.neg ? -seconds : seconds;
1281
Convert a string to a interval value.
1283
To make code easy, allow interval objects without separators.
1286
bool get_interval_value(Item *args,interval_type int_type,
1287
String *str_value, INTERVAL *interval)
1291
const char *str= NULL;
1293
const CHARSET_INFO * const cs= str_value->charset();
1295
memset(interval, 0, sizeof(*interval));
1296
if ((int) int_type <= INTERVAL_MICROSECOND)
1298
value= args->val_int();
1299
if (args->null_value)
1310
if (!(res=args->val_str(str_value)))
1313
/* record negative intervalls in interval->neg */
1315
const char *end=str+res->length();
1316
while (str != end && my_isspace(cs,*str))
1318
if (str != end && *str == '-')
1323
length= (size_t) (end-str); // Set up pointers to new str
1328
interval->year= (ulong) value;
1330
case INTERVAL_QUARTER:
1331
interval->month= (ulong)(value*3);
1333
case INTERVAL_MONTH:
1334
interval->month= (ulong) value;
1337
interval->day= (ulong)(value*7);
1340
interval->day= (ulong) value;
1343
interval->hour= (ulong) value;
1345
case INTERVAL_MICROSECOND:
1346
interval->second_part=value;
1348
case INTERVAL_MINUTE:
1349
interval->minute=value;
1351
case INTERVAL_SECOND:
1352
interval->second=value;
1354
case INTERVAL_YEAR_MONTH: // Allow YEAR-MONTH YYYYYMM
1355
if (get_interval_info(str,length,cs,2,array,0))
1357
interval->year= (ulong) array[0];
1358
interval->month= (ulong) array[1];
1360
case INTERVAL_DAY_HOUR:
1361
if (get_interval_info(str,length,cs,2,array,0))
1363
interval->day= (ulong) array[0];
1364
interval->hour= (ulong) array[1];
1366
case INTERVAL_DAY_MICROSECOND:
1367
if (get_interval_info(str,length,cs,5,array,1))
1369
interval->day= (ulong) array[0];
1370
interval->hour= (ulong) array[1];
1371
interval->minute= array[2];
1372
interval->second= array[3];
1373
interval->second_part= array[4];
1375
case INTERVAL_DAY_MINUTE:
1376
if (get_interval_info(str,length,cs,3,array,0))
1378
interval->day= (ulong) array[0];
1379
interval->hour= (ulong) array[1];
1380
interval->minute= array[2];
1382
case INTERVAL_DAY_SECOND:
1383
if (get_interval_info(str,length,cs,4,array,0))
1385
interval->day= (ulong) array[0];
1386
interval->hour= (ulong) array[1];
1387
interval->minute= array[2];
1388
interval->second= array[3];
1390
case INTERVAL_HOUR_MICROSECOND:
1391
if (get_interval_info(str,length,cs,4,array,1))
1393
interval->hour= (ulong) array[0];
1394
interval->minute= array[1];
1395
interval->second= array[2];
1396
interval->second_part= array[3];
1398
case INTERVAL_HOUR_MINUTE:
1399
if (get_interval_info(str,length,cs,2,array,0))
1401
interval->hour= (ulong) array[0];
1402
interval->minute= array[1];
1404
case INTERVAL_HOUR_SECOND:
1405
if (get_interval_info(str,length,cs,3,array,0))
1407
interval->hour= (ulong) array[0];
1408
interval->minute= array[1];
1409
interval->second= array[2];
1411
case INTERVAL_MINUTE_MICROSECOND:
1412
if (get_interval_info(str,length,cs,3,array,1))
1414
interval->minute= array[0];
1415
interval->second= array[1];
1416
interval->second_part= array[2];
1418
case INTERVAL_MINUTE_SECOND:
1419
if (get_interval_info(str,length,cs,2,array,0))
1421
interval->minute= array[0];
1422
interval->second= array[1];
1424
case INTERVAL_SECOND_MICROSECOND:
1425
if (get_interval_info(str,length,cs,2,array,1))
1427
interval->second= array[0];
1428
interval->second_part= array[1];
1430
case INTERVAL_LAST: /* purecov: begin deadcode */
1432
break; /* purecov: end */
1438
String *Item_date::val_str(String *str)
1442
if (get_date(<ime, TIME_FUZZY_DATE))
1443
return (String *) 0;
1444
if (str->alloc(MAX_DATE_STRING_REP_LENGTH))
1447
return (String *) 0;
1449
make_date((DATE_TIME_FORMAT *) 0, <ime, str);
1454
int64_t Item_date::val_int()
1458
if (get_date(<ime, TIME_FUZZY_DATE))
1460
return (int64_t) (ltime.year*10000L+ltime.month*100+ltime.day);
1464
bool Item_func_from_days::get_date(DRIZZLE_TIME *ltime, uint32_t fuzzy_date __attribute__((unused)))
1466
int64_t value=args[0]->val_int();
1467
if ((null_value=args[0]->null_value))
1469
memset(ltime, 0, sizeof(DRIZZLE_TIME));
1470
get_date_from_daynr((long) value, <ime->year, <ime->month, <ime->day);
1471
ltime->time_type= DRIZZLE_TIMESTAMP_DATE;
1476
void Item_func_curdate::fix_length_and_dec()
1478
collation.set(&my_charset_bin);
1480
max_length=MAX_DATE_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
1482
store_now_in_TIME(<ime);
1484
/* We don't need to set second_part and neg because they already 0 */
1485
ltime.hour= ltime.minute= ltime.second= 0;
1486
ltime.time_type= DRIZZLE_TIMESTAMP_DATE;
1487
value= (int64_t) TIME_to_uint64_t_date(<ime);
1490
String *Item_func_curdate::val_str(String *str)
1493
if (str->alloc(MAX_DATE_STRING_REP_LENGTH))
1496
return (String *) 0;
1498
make_date((DATE_TIME_FORMAT *) 0, <ime, str);
1503
Converts current time in my_time_t to DRIZZLE_TIME represenatation for local
1504
time zone. Defines time zone (local) used for whole CURDATE function.
1506
void Item_func_curdate_local::store_now_in_TIME(DRIZZLE_TIME *now_time)
1508
THD *thd= current_thd;
1509
thd->variables.time_zone->gmt_sec_to_TIME(now_time,
1510
(my_time_t)thd->query_start());
1511
thd->time_zone_used= 1;
1516
Converts current time in my_time_t to DRIZZLE_TIME represenatation for UTC
1517
time zone. Defines time zone (UTC) used for whole UTC_DATE function.
1519
void Item_func_curdate_utc::store_now_in_TIME(DRIZZLE_TIME *now_time)
1521
my_tz_UTC->gmt_sec_to_TIME(now_time,
1522
(my_time_t)(current_thd->query_start()));
1524
We are not flagging this query as using time zone, since it uses fixed
1525
UTC-SYSTEM time-zone.
1530
bool Item_func_curdate::get_date(DRIZZLE_TIME *res,
1531
uint32_t fuzzy_date __attribute__((unused)))
1538
String *Item_func_curtime::val_str(String *str __attribute__((unused)))
1541
str_value.set(buff, buff_length, &my_charset_bin);
1546
void Item_func_curtime::fix_length_and_dec()
1550
decimals= DATETIME_DEC;
1551
collation.set(&my_charset_bin);
1552
store_now_in_TIME(<ime);
1553
value= TIME_to_uint64_t_time(<ime);
1554
buff_length= (uint) my_time_to_str(<ime, buff);
1555
max_length= buff_length;
1560
Converts current time in my_time_t to DRIZZLE_TIME represenatation for local
1561
time zone. Defines time zone (local) used for whole CURTIME function.
1563
void Item_func_curtime_local::store_now_in_TIME(DRIZZLE_TIME *now_time)
1565
THD *thd= current_thd;
1566
thd->variables.time_zone->gmt_sec_to_TIME(now_time,
1567
(my_time_t)thd->query_start());
1568
thd->time_zone_used= 1;
1573
Converts current time in my_time_t to DRIZZLE_TIME represenatation for UTC
1574
time zone. Defines time zone (UTC) used for whole UTC_TIME function.
1576
void Item_func_curtime_utc::store_now_in_TIME(DRIZZLE_TIME *now_time)
1578
my_tz_UTC->gmt_sec_to_TIME(now_time,
1579
(my_time_t)(current_thd->query_start()));
1581
We are not flagging this query as using time zone, since it uses fixed
1582
UTC-SYSTEM time-zone.
1587
String *Item_func_now::val_str(String *str __attribute__((unused)))
1590
str_value.set(buff,buff_length, &my_charset_bin);
1595
void Item_func_now::fix_length_and_dec()
1597
decimals= DATETIME_DEC;
1598
collation.set(&my_charset_bin);
1600
store_now_in_TIME(<ime);
1601
value= (int64_t) TIME_to_uint64_t_datetime(<ime);
1603
buff_length= (uint) my_datetime_to_str(<ime, buff);
1604
max_length= buff_length;
1609
Converts current time in my_time_t to DRIZZLE_TIME represenatation for local
1610
time zone. Defines time zone (local) used for whole NOW function.
1612
void Item_func_now_local::store_now_in_TIME(DRIZZLE_TIME *now_time)
1614
THD *thd= current_thd;
1615
thd->variables.time_zone->gmt_sec_to_TIME(now_time,
1616
(my_time_t)thd->query_start());
1617
thd->time_zone_used= 1;
1622
Converts current time in my_time_t to DRIZZLE_TIME represenatation for UTC
1623
time zone. Defines time zone (UTC) used for whole UTC_TIMESTAMP function.
1625
void Item_func_now_utc::store_now_in_TIME(DRIZZLE_TIME *now_time)
1627
my_tz_UTC->gmt_sec_to_TIME(now_time,
1628
(my_time_t)(current_thd->query_start()));
1630
We are not flagging this query as using time zone, since it uses fixed
1631
UTC-SYSTEM time-zone.
1636
bool Item_func_now::get_date(DRIZZLE_TIME *res,
1637
uint32_t fuzzy_date __attribute__((unused)))
1644
int Item_func_now::save_in_field(Field *to, bool no_conversions __attribute__((unused)))
1647
return to->store_time(<ime, DRIZZLE_TIMESTAMP_DATETIME);
1652
Converts current time in my_time_t to DRIZZLE_TIME represenatation for local
1653
time zone. Defines time zone (local) used for whole SYSDATE function.
1655
void Item_func_sysdate_local::store_now_in_TIME(DRIZZLE_TIME *now_time)
1657
THD *thd= current_thd;
1658
thd->variables.time_zone->gmt_sec_to_TIME(now_time, (my_time_t) my_time(0));
1659
thd->time_zone_used= 1;
1663
String *Item_func_sysdate_local::val_str(String *str __attribute__((unused)))
1666
store_now_in_TIME(<ime);
1667
buff_length= (uint) my_datetime_to_str(<ime, buff);
1668
str_value.set(buff, buff_length, &my_charset_bin);
1673
int64_t Item_func_sysdate_local::val_int()
1676
store_now_in_TIME(<ime);
1677
return (int64_t) TIME_to_uint64_t_datetime(<ime);
1681
double Item_func_sysdate_local::val_real()
1684
store_now_in_TIME(<ime);
1685
return uint64_t2double(TIME_to_uint64_t_datetime(<ime));
1689
void Item_func_sysdate_local::fix_length_and_dec()
1692
collation.set(&my_charset_bin);
1693
max_length= MAX_DATETIME_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
1697
bool Item_func_sysdate_local::get_date(DRIZZLE_TIME *res,
1698
uint32_t fuzzy_date __attribute__((unused)))
1700
store_now_in_TIME(<ime);
1706
int Item_func_sysdate_local::save_in_field(Field *to, bool no_conversions __attribute__((unused)))
1708
store_now_in_TIME(<ime);
1710
to->store_time(<ime, DRIZZLE_TIMESTAMP_DATETIME);
1715
String *Item_func_sec_to_time::val_str(String *str)
1719
int64_t arg_val= args[0]->val_int();
1721
if ((null_value=args[0]->null_value) ||
1722
str->alloc(MAX_DATE_STRING_REP_LENGTH))
1728
sec_to_time(arg_val, args[0]->unsigned_flag, <ime);
1730
make_time((DATE_TIME_FORMAT *) 0, <ime, str);
1735
int64_t Item_func_sec_to_time::val_int()
1739
int64_t arg_val= args[0]->val_int();
1741
if ((null_value=args[0]->null_value))
1744
sec_to_time(arg_val, args[0]->unsigned_flag, <ime);
1746
return (ltime.neg ? -1 : 1) *
1747
((ltime.hour)*10000 + ltime.minute*100 + ltime.second);
1751
void Item_func_date_format::fix_length_and_dec()
1753
THD* thd= current_thd;
1755
Must use this_item() in case it's a local SP variable
1756
(for ->max_length and ->str_value)
1758
Item *arg1= args[1]->this_item();
1761
const CHARSET_INFO * const cs= thd->variables.collation_connection;
1762
uint32_t repertoire= arg1->collation.repertoire;
1763
if (!thd->variables.lc_time_names->is_ascii)
1764
repertoire|= MY_REPERTOIRE_EXTENDED;
1765
collation.set(cs, arg1->collation.derivation, repertoire);
1766
if (arg1->type() == STRING_ITEM)
1767
{ // Optimize the normal case
1769
max_length= format_length(&arg1->str_value) *
1770
collation.collation->mbmaxlen;
1775
max_length=cmin(arg1->max_length,(uint32_t) MAX_BLOB_WIDTH) * 10 *
1776
collation.collation->mbmaxlen;
1777
set_if_smaller(max_length,MAX_BLOB_WIDTH);
1779
maybe_null=1; // If wrong date
1783
bool Item_func_date_format::eq(const Item *item, bool binary_cmp) const
1785
Item_func_date_format *item_func;
1787
if (item->type() != FUNC_ITEM)
1789
if (func_name() != ((Item_func*) item)->func_name())
1793
item_func= (Item_func_date_format*) item;
1794
if (!args[0]->eq(item_func->args[0], binary_cmp))
1797
We must compare format string case sensitive.
1798
This needed because format modifiers with different case,
1799
for example %m and %M, have different meaning.
1801
if (!args[1]->eq(item_func->args[1], 1))
1808
uint32_t Item_func_date_format::format_length(const String *format)
1811
const char *ptr=format->ptr();
1812
const char *end=ptr+format->length();
1814
for (; ptr != end ; ptr++)
1816
if (*ptr != '%' || ptr == end-1)
1821
case 'M': /* month, textual */
1822
case 'W': /* day (of the week), textual */
1823
size += 64; /* large for UTF8 locale data */
1825
case 'D': /* day (of the month), numeric plus english suffix */
1826
case 'Y': /* year, numeric, 4 digits */
1827
case 'x': /* Year, used with 'v' */
1828
case 'X': /* Year, used with 'v, where week starts with Monday' */
1831
case 'a': /* locale's abbreviated weekday name (Sun..Sat) */
1832
case 'b': /* locale's abbreviated month name (Jan.Dec) */
1833
size += 32; /* large for UTF8 locale data */
1835
case 'j': /* day of year (001..366) */
1838
case 'U': /* week (00..52) */
1839
case 'u': /* week (00..52), where week starts with Monday */
1840
case 'V': /* week 1..53 used with 'x' */
1841
case 'v': /* week 1..53 used with 'x', where week starts with Monday */
1842
case 'y': /* year, numeric, 2 digits */
1843
case 'm': /* month, numeric */
1844
case 'd': /* day (of the month), numeric */
1845
case 'h': /* hour (01..12) */
1846
case 'I': /* --||-- */
1847
case 'i': /* minutes, numeric */
1848
case 'l': /* hour ( 1..12) */
1849
case 'p': /* locale's AM or PM */
1850
case 'S': /* second (00..61) */
1851
case 's': /* seconds, numeric */
1852
case 'c': /* month (0..12) */
1853
case 'e': /* day (0..31) */
1856
case 'k': /* hour ( 0..23) */
1857
case 'H': /* hour (00..23; value > 23 OK, padding always 2-digit) */
1858
size += 7; /* docs allow > 23, range depends on sizeof(unsigned int) */
1860
case 'r': /* time, 12-hour (hh:mm:ss [AP]M) */
1863
case 'T': /* time, 24-hour (hh:mm:ss) */
1866
case 'f': /* microseconds */
1869
case 'w': /* day (of the week), numeric */
1881
String *Item_func_date_format::val_str(String *str)
1884
DRIZZLE_TIME l_time;
1888
if (!is_time_format)
1890
if (get_arg0_date(&l_time, TIME_FUZZY_DATE))
1896
if (!(res=args[0]->val_str(str)) ||
1897
(str_to_time_with_warn(res->ptr(), res->length(), &l_time)))
1900
l_time.year=l_time.month=l_time.day=0;
1904
if (!(format = args[1]->val_str(str)) || !format->length())
1910
size=format_length(format);
1912
if (size < MAX_DATE_STRING_REP_LENGTH)
1913
size= MAX_DATE_STRING_REP_LENGTH;
1916
str= &value; // Save result here
1917
if (str->alloc(size))
1920
DATE_TIME_FORMAT date_time_format;
1921
date_time_format.format.str= (char*) format->ptr();
1922
date_time_format.format.length= format->length();
1924
/* Create the result string */
1925
str->set_charset(collation.collation);
1926
if (!make_date_time(&date_time_format, &l_time,
1927
is_time_format ? DRIZZLE_TIMESTAMP_TIME :
1928
DRIZZLE_TIMESTAMP_DATE,
1938
void Item_func_from_unixtime::fix_length_and_dec()
1941
collation.set(&my_charset_bin);
1942
decimals= DATETIME_DEC;
1943
max_length=MAX_DATETIME_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
1945
thd->time_zone_used= 1;
1949
String *Item_func_from_unixtime::val_str(String *str)
1951
DRIZZLE_TIME time_tmp;
1955
if (get_date(&time_tmp, 0))
1958
if (str->alloc(MAX_DATE_STRING_REP_LENGTH))
1964
make_datetime((DATE_TIME_FORMAT *) 0, &time_tmp, str);
1970
int64_t Item_func_from_unixtime::val_int()
1972
DRIZZLE_TIME time_tmp;
1976
if (get_date(&time_tmp, 0))
1979
return (int64_t) TIME_to_uint64_t_datetime(&time_tmp);
1982
bool Item_func_from_unixtime::get_date(DRIZZLE_TIME *ltime,
1983
uint32_t fuzzy_date __attribute__((unused)))
1985
uint64_t tmp= (uint64_t)(args[0]->val_int());
1987
"tmp > TIMESTAMP_MAX_VALUE" check also covers case of negative
1988
from_unixtime() argument since tmp is unsigned.
1990
if ((null_value= (args[0]->null_value || tmp > TIMESTAMP_MAX_VALUE)))
1993
thd->variables.time_zone->gmt_sec_to_TIME(ltime, (my_time_t)tmp);
1999
void Item_date_add_interval::fix_length_and_dec()
2001
enum_field_types arg0_field_type;
2003
collation.set(&my_charset_bin);
2005
max_length=MAX_DATETIME_FULL_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
2006
value.alloc(max_length);
2009
The field type for the result of an Item_date function is defined as
2012
- If first arg is a DRIZZLE_TYPE_DATETIME result is DRIZZLE_TYPE_DATETIME
2013
- If first arg is a DRIZZLE_TYPE_NEWDATE and the interval type uses hours,
2014
minutes or seconds then type is DRIZZLE_TYPE_DATETIME.
2015
- Otherwise the result is DRIZZLE_TYPE_VARCHAR
2016
(This is because you can't know if the string contains a DATE, DRIZZLE_TIME or
2019
cached_field_type= DRIZZLE_TYPE_VARCHAR;
2020
arg0_field_type= args[0]->field_type();
2021
if (arg0_field_type == DRIZZLE_TYPE_DATETIME ||
2022
arg0_field_type == DRIZZLE_TYPE_TIMESTAMP)
2023
cached_field_type= DRIZZLE_TYPE_DATETIME;
2024
else if (arg0_field_type == DRIZZLE_TYPE_NEWDATE)
2026
if (int_type <= INTERVAL_DAY || int_type == INTERVAL_YEAR_MONTH)
2027
cached_field_type= arg0_field_type;
2029
cached_field_type= DRIZZLE_TYPE_DATETIME;
2034
/* Here arg[1] is a Item_interval object */
2036
bool Item_date_add_interval::get_date(DRIZZLE_TIME *ltime, uint32_t fuzzy_date __attribute__((unused)))
2040
if (args[0]->get_date(ltime, TIME_NO_ZERO_DATE) ||
2041
get_interval_value(args[1], int_type, &value, &interval))
2042
return (null_value=1);
2044
if (date_sub_interval)
2045
interval.neg = !interval.neg;
2047
if ((null_value= date_add_interval(ltime, int_type, interval)))
2053
String *Item_date_add_interval::val_str(String *str)
2057
enum date_time_format_types format;
2059
if (Item_date_add_interval::get_date(<ime, TIME_NO_ZERO_DATE))
2062
if (ltime.time_type == DRIZZLE_TIMESTAMP_DATE)
2064
else if (ltime.second_part)
2065
format= DATE_TIME_MICROSECOND;
2069
if (!make_datetime(format, <ime, str))
2077
int64_t Item_date_add_interval::val_int()
2082
if (Item_date_add_interval::get_date(<ime, TIME_NO_ZERO_DATE))
2084
date = (ltime.year*100L + ltime.month)*100L + ltime.day;
2085
return ltime.time_type == DRIZZLE_TIMESTAMP_DATE ? date :
2086
((date*100L + ltime.hour)*100L+ ltime.minute)*100L + ltime.second;
2091
bool Item_date_add_interval::eq(const Item *item, bool binary_cmp) const
2093
Item_date_add_interval *other= (Item_date_add_interval*) item;
2094
if (!Item_func::eq(item, binary_cmp))
2096
return ((int_type == other->int_type) &&
2097
(date_sub_interval == other->date_sub_interval));
2101
'interval_names' reflects the order of the enumeration interval_type.
2105
static const char *interval_names[]=
2107
"year", "quarter", "month", "week", "day",
2108
"hour", "minute", "second", "microsecond",
2109
"year_month", "day_hour", "day_minute",
2110
"day_second", "hour_minute", "hour_second",
2111
"minute_second", "day_microsecond",
2112
"hour_microsecond", "minute_microsecond",
2113
"second_microsecond"
2116
void Item_date_add_interval::print(String *str, enum_query_type query_type)
2119
args[0]->print(str, query_type);
2120
str->append(date_sub_interval?" - interval ":" + interval ");
2121
args[1]->print(str, query_type);
2123
str->append(interval_names[int_type]);
2127
void Item_extract::print(String *str, enum_query_type query_type)
2129
str->append(STRING_WITH_LEN("extract("));
2130
str->append(interval_names[int_type]);
2131
str->append(STRING_WITH_LEN(" from "));
2132
args[0]->print(str, query_type);
2136
void Item_extract::fix_length_and_dec()
2138
value.alloc(32); // alloc buffer
2140
maybe_null=1; // If wrong date
2142
case INTERVAL_YEAR: max_length=4; date_value=1; break;
2143
case INTERVAL_YEAR_MONTH: max_length=6; date_value=1; break;
2144
case INTERVAL_QUARTER: max_length=2; date_value=1; break;
2145
case INTERVAL_MONTH: max_length=2; date_value=1; break;
2146
case INTERVAL_WEEK: max_length=2; date_value=1; break;
2147
case INTERVAL_DAY: max_length=2; date_value=1; break;
2148
case INTERVAL_DAY_HOUR: max_length=9; date_value=0; break;
2149
case INTERVAL_DAY_MINUTE: max_length=11; date_value=0; break;
2150
case INTERVAL_DAY_SECOND: max_length=13; date_value=0; break;
2151
case INTERVAL_HOUR: max_length=2; date_value=0; break;
2152
case INTERVAL_HOUR_MINUTE: max_length=4; date_value=0; break;
2153
case INTERVAL_HOUR_SECOND: max_length=6; date_value=0; break;
2154
case INTERVAL_MINUTE: max_length=2; date_value=0; break;
2155
case INTERVAL_MINUTE_SECOND: max_length=4; date_value=0; break;
2156
case INTERVAL_SECOND: max_length=2; date_value=0; break;
2157
case INTERVAL_MICROSECOND: max_length=2; date_value=0; break;
2158
case INTERVAL_DAY_MICROSECOND: max_length=20; date_value=0; break;
2159
case INTERVAL_HOUR_MICROSECOND: max_length=13; date_value=0; break;
2160
case INTERVAL_MINUTE_MICROSECOND: max_length=11; date_value=0; break;
2161
case INTERVAL_SECOND_MICROSECOND: max_length=9; date_value=0; break;
2162
case INTERVAL_LAST: assert(0); break; /* purecov: deadcode */
2167
int64_t Item_extract::val_int()
2176
if (get_arg0_date(<ime, TIME_FUZZY_DATE))
2182
String *res= args[0]->val_str(&value);
2183
if (!res || str_to_time_with_warn(res->ptr(), res->length(), <ime))
2188
neg= ltime.neg ? -1 : 1;
2192
case INTERVAL_YEAR: return ltime.year;
2193
case INTERVAL_YEAR_MONTH: return ltime.year*100L+ltime.month;
2194
case INTERVAL_QUARTER: return (ltime.month+2)/3;
2195
case INTERVAL_MONTH: return ltime.month;
2198
week_format= current_thd->variables.default_week_format;
2199
return calc_week(<ime, week_mode(week_format), &year);
2201
case INTERVAL_DAY: return ltime.day;
2202
case INTERVAL_DAY_HOUR: return (long) (ltime.day*100L+ltime.hour)*neg;
2203
case INTERVAL_DAY_MINUTE: return (long) (ltime.day*10000L+
2206
case INTERVAL_DAY_SECOND: return ((int64_t) ltime.day*1000000L+
2207
(int64_t) (ltime.hour*10000L+
2210
case INTERVAL_HOUR: return (long) ltime.hour*neg;
2211
case INTERVAL_HOUR_MINUTE: return (long) (ltime.hour*100+ltime.minute)*neg;
2212
case INTERVAL_HOUR_SECOND: return (long) (ltime.hour*10000+ltime.minute*100+
2214
case INTERVAL_MINUTE: return (long) ltime.minute*neg;
2215
case INTERVAL_MINUTE_SECOND: return (long) (ltime.minute*100+ltime.second)*neg;
2216
case INTERVAL_SECOND: return (long) ltime.second*neg;
2217
case INTERVAL_MICROSECOND: return (long) ltime.second_part*neg;
2218
case INTERVAL_DAY_MICROSECOND: return (((int64_t)ltime.day*1000000L +
2219
(int64_t)ltime.hour*10000L +
2221
ltime.second)*1000000L +
2222
ltime.second_part)*neg;
2223
case INTERVAL_HOUR_MICROSECOND: return (((int64_t)ltime.hour*10000L +
2225
ltime.second)*1000000L +
2226
ltime.second_part)*neg;
2227
case INTERVAL_MINUTE_MICROSECOND: return (((int64_t)(ltime.minute*100+
2228
ltime.second))*1000000L+
2229
ltime.second_part)*neg;
2230
case INTERVAL_SECOND_MICROSECOND: return ((int64_t)ltime.second*1000000L+
2231
ltime.second_part)*neg;
2232
case INTERVAL_LAST: assert(0); break; /* purecov: deadcode */
2234
return 0; // Impossible
2237
bool Item_extract::eq(const Item *item, bool binary_cmp) const
2241
if (item->type() != FUNC_ITEM ||
2242
functype() != ((Item_func*)item)->functype())
2245
Item_extract* ie= (Item_extract*)item;
2246
if (ie->int_type != int_type)
2249
if (!args[0]->eq(ie->args[0], binary_cmp))
2255
bool Item_char_typecast::eq(const Item *item, bool binary_cmp) const
2259
if (item->type() != FUNC_ITEM ||
2260
functype() != ((Item_func*)item)->functype())
2263
Item_char_typecast *cast= (Item_char_typecast*)item;
2264
if (cast_length != cast->cast_length ||
2265
cast_cs != cast->cast_cs)
2268
if (!args[0]->eq(cast->args[0], binary_cmp))
2273
void Item_typecast::print(String *str, enum_query_type query_type)
2275
str->append(STRING_WITH_LEN("cast("));
2276
args[0]->print(str, query_type);
2277
str->append(STRING_WITH_LEN(" as "));
2278
str->append(cast_type());
2283
void Item_char_typecast::print(String *str, enum_query_type query_type)
2285
str->append(STRING_WITH_LEN("cast("));
2286
args[0]->print(str, query_type);
2287
str->append(STRING_WITH_LEN(" as char"));
2288
if (cast_length >= 0)
2292
// my_charset_bin is good enough for numbers
2293
String st(buffer, sizeof(buffer), &my_charset_bin);
2294
st.set((uint64_t)cast_length, &my_charset_bin);
2300
str->append(STRING_WITH_LEN(" charset "));
2301
str->append(cast_cs->csname);
2306
String *Item_char_typecast::val_str(String *str)
2312
if (!charset_conversion)
2314
if (!(res= args[0]->val_str(str)))
2322
// Convert character set if differ
2323
uint32_t dummy_errors;
2324
if (!(res= args[0]->val_str(&tmp_value)) ||
2325
str->copy(res->ptr(), res->length(), from_cs,
2326
cast_cs, &dummy_errors))
2334
res->set_charset(cast_cs);
2337
Cut the tail if cast with length
2338
and the result is longer than cast length, e.g.
2339
CAST('string' AS CHAR(1))
2341
if (cast_length >= 0)
2343
if (res->length() > (length= (uint32_t) res->charpos(cast_length)))
2344
{ // Safe even if const arg
2346
snprintf(char_type, sizeof(char_type), "%s(%lu)",
2347
cast_cs == &my_charset_bin ? "BINARY" : "CHAR",
2350
if (!res->alloced_length())
2351
{ // Don't change const str
2352
str_value= *res; // Not malloced string
2355
push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
2356
ER_TRUNCATED_WRONG_VALUE,
2357
ER(ER_TRUNCATED_WRONG_VALUE), char_type,
2359
res->length((uint) length);
2361
else if (cast_cs == &my_charset_bin && res->length() < (uint) cast_length)
2363
if (res->alloced_length() < (uint) cast_length)
2365
str->alloc(cast_length);
2369
memset(res->ptr() + res->length(), 0,
2370
(uint) cast_length - res->length());
2371
res->length(cast_length);
2379
void Item_char_typecast::fix_length_and_dec()
2381
uint32_t char_length;
2383
We always force character set conversion if cast_cs
2384
is a multi-byte character set. It garantees that the
2385
result of CAST is a well-formed string.
2386
For single-byte character sets we allow just to copy
2387
from the argument. A single-byte character sets string
2388
is always well-formed.
2390
There is a special trick to convert form a number to ucs2.
2391
As numbers have my_charset_bin as their character set,
2392
it wouldn't do conversion to ucs2 without an additional action.
2393
To force conversion, we should pretend to be non-binary.
2394
Let's choose from_cs this way:
2395
- If the argument in a number and cast_cs is ucs2 (i.e. mbminlen > 1),
2396
then from_cs is set to latin1, to perform latin1 -> ucs2 conversion.
2397
- If the argument is a number and cast_cs is ASCII-compatible
2398
(i.e. mbminlen == 1), then from_cs is set to cast_cs,
2399
which allows just to take over the args[0]->val_str() result
2400
and thus avoid unnecessary character set conversion.
2401
- If the argument is not a number, then from_cs is set to
2402
the argument's charset.
2404
from_cs= (args[0]->result_type() == INT_RESULT ||
2405
args[0]->result_type() == DECIMAL_RESULT ||
2406
args[0]->result_type() == REAL_RESULT) ?
2407
(cast_cs->mbminlen == 1 ? cast_cs : &my_charset_utf8_general_ci) :
2408
args[0]->collation.collation;
2409
charset_conversion= (cast_cs->mbmaxlen > 1) ||
2410
(!my_charset_same(from_cs, cast_cs) && from_cs != &my_charset_bin && cast_cs != &my_charset_bin);
2411
collation.set(cast_cs, DERIVATION_IMPLICIT);
2412
char_length= (cast_length >= 0) ? cast_length :
2413
args[0]->max_length/from_cs->mbmaxlen;
2414
max_length= char_length * cast_cs->mbmaxlen;
2418
String *Item_datetime_typecast::val_str(String *str)
2423
if (!get_arg0_date(<ime, TIME_FUZZY_DATE) &&
2424
!make_datetime(ltime.second_part ? DATE_TIME_MICROSECOND : DATE_TIME,
2433
int64_t Item_datetime_typecast::val_int()
2437
if (get_arg0_date(<ime,1))
2443
return TIME_to_uint64_t_datetime(<ime);
2447
bool Item_time_typecast::get_time(DRIZZLE_TIME *ltime)
2449
bool res= get_arg0_time(ltime);
2451
For DRIZZLE_TIMESTAMP_TIME value we can have non-zero day part,
2452
which we should not lose.
2454
if (ltime->time_type == DRIZZLE_TIMESTAMP_DATETIME)
2455
ltime->year= ltime->month= ltime->day= 0;
2456
ltime->time_type= DRIZZLE_TIMESTAMP_TIME;
2461
int64_t Item_time_typecast::val_int()
2464
if (get_time(<ime))
2469
return ltime.hour * 10000L + ltime.minute * 100 + ltime.second;
2472
String *Item_time_typecast::val_str(String *str)
2477
if (!get_arg0_time(<ime) &&
2478
!make_datetime(ltime.second_part ? TIME_MICROSECOND : TIME_ONLY,
2487
bool Item_date_typecast::get_date(DRIZZLE_TIME *ltime, uint32_t fuzzy_date __attribute__((unused)))
2489
bool res= get_arg0_date(ltime, TIME_FUZZY_DATE);
2490
ltime->hour= ltime->minute= ltime->second= ltime->second_part= 0;
2491
ltime->time_type= DRIZZLE_TIMESTAMP_DATE;
2496
bool Item_date_typecast::get_time(DRIZZLE_TIME *ltime)
2498
memset(ltime, 0, sizeof(DRIZZLE_TIME));
2499
return args[0]->null_value;
2503
String *Item_date_typecast::val_str(String *str)
2508
if (!get_arg0_date(<ime, TIME_FUZZY_DATE) &&
2509
!str->alloc(MAX_DATE_STRING_REP_LENGTH))
2511
make_date((DATE_TIME_FORMAT *) 0, <ime, str);
2519
int64_t Item_date_typecast::val_int()
2523
if ((null_value= args[0]->get_date(<ime, TIME_FUZZY_DATE)))
2525
return (int64_t) (ltime.year * 10000L + ltime.month * 100 + ltime.day);
2529
MAKEDATE(a,b) is a date function that creates a date value
2530
from a year and day value.
2533
As arguments are integers, we can't know if the year is a 2 digit or 4 digit year.
2534
In this case we treat all years < 100 as 2 digit years. Ie, this is not safe
2535
for dates between 0000-01-01 and 0099-12-31
2538
String *Item_func_makedate::val_str(String *str)
2541
DRIZZLE_TIME l_time;
2542
long daynr= (long) args[1]->val_int();
2543
long year= (long) args[0]->val_int();
2546
if (args[0]->null_value || args[1]->null_value ||
2547
year < 0 || daynr <= 0)
2551
year= year_2000_handling(year);
2553
days= calc_daynr(year,1,1) + daynr - 1;
2554
/* Day number from year 0 to 9999-12-31 */
2555
if (days >= 0 && days <= MAX_DAY_NUMBER)
2558
get_date_from_daynr(days,&l_time.year,&l_time.month,&l_time.day);
2559
if (str->alloc(MAX_DATE_STRING_REP_LENGTH))
2561
make_date((DATE_TIME_FORMAT *) 0, &l_time, str);
2572
MAKEDATE(a,b) is a date function that creates a date value
2573
from a year and day value.
2576
As arguments are integers, we can't know if the year is a 2 digit or 4 digit year.
2577
In this case we treat all years < 100 as 2 digit years. Ie, this is not safe
2578
for dates between 0000-01-01 and 0099-12-31
2581
int64_t Item_func_makedate::val_int()
2584
DRIZZLE_TIME l_time;
2585
long daynr= (long) args[1]->val_int();
2586
long year= (long) args[0]->val_int();
2589
if (args[0]->null_value || args[1]->null_value ||
2590
year < 0 || daynr <= 0)
2594
year= year_2000_handling(year);
2596
days= calc_daynr(year,1,1) + daynr - 1;
2597
/* Day number from year 0 to 9999-12-31 */
2598
if (days >= 0 && days < MAX_DAY_NUMBER)
2601
get_date_from_daynr(days,&l_time.year,&l_time.month,&l_time.day);
2602
return (int64_t) (l_time.year * 10000L + l_time.month * 100 + l_time.day);
2611
void Item_func_add_time::fix_length_and_dec()
2613
enum_field_types arg0_field_type;
2615
max_length=MAX_DATETIME_FULL_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
2619
The field type for the result of an Item_func_add_time function is defined
2622
- If first arg is a DRIZZLE_TYPE_DATETIME or DRIZZLE_TYPE_TIMESTAMP
2623
result is DRIZZLE_TYPE_DATETIME
2624
- If first arg is a DRIZZLE_TYPE_TIME result is DRIZZLE_TYPE_TIME
2625
- Otherwise the result is DRIZZLE_TYPE_VARCHAR
2628
cached_field_type= DRIZZLE_TYPE_VARCHAR;
2629
arg0_field_type= args[0]->field_type();
2630
if (arg0_field_type == DRIZZLE_TYPE_NEWDATE ||
2631
arg0_field_type == DRIZZLE_TYPE_DATETIME ||
2632
arg0_field_type == DRIZZLE_TYPE_TIMESTAMP)
2633
cached_field_type= DRIZZLE_TYPE_DATETIME;
2634
else if (arg0_field_type == DRIZZLE_TYPE_TIME)
2635
cached_field_type= DRIZZLE_TYPE_TIME;
2639
ADDTIME(t,a) and SUBTIME(t,a) are time functions that calculate a
2642
t: time_or_datetime_expression
2645
Result: Time value or datetime value
2648
String *Item_func_add_time::val_str(String *str)
2651
DRIZZLE_TIME l_time1, l_time2, l_time3;
2653
long days, microseconds;
2658
if (is_date) // TIMESTAMP function
2660
if (get_arg0_date(&l_time1, TIME_FUZZY_DATE) ||
2661
args[1]->get_time(&l_time2) ||
2662
l_time1.time_type == DRIZZLE_TIMESTAMP_TIME ||
2663
l_time2.time_type != DRIZZLE_TIMESTAMP_TIME)
2666
else // ADDTIME function
2668
if (args[0]->get_time(&l_time1) ||
2669
args[1]->get_time(&l_time2) ||
2670
l_time2.time_type == DRIZZLE_TIMESTAMP_DATETIME)
2672
is_time= (l_time1.time_type == DRIZZLE_TIMESTAMP_TIME);
2674
if (l_time1.neg != l_time2.neg)
2677
memset(&l_time3, 0, sizeof(l_time3));
2679
l_time3.neg= calc_time_diff(&l_time1, &l_time2, -l_sign,
2680
&seconds, µseconds);
2683
If first argument was negative and diff between arguments
2684
is non-zero we need to swap sign to get proper result.
2686
if (l_time1.neg && (seconds || microseconds))
2687
l_time3.neg= 1-l_time3.neg; // Swap sign of result
2689
if (!is_time && l_time3.neg)
2692
days= (long)(seconds/86400L);
2694
calc_time_from_sec(&l_time3, (long)(seconds%86400L), microseconds);
2698
get_date_from_daynr(days,&l_time3.year,&l_time3.month,&l_time3.day);
2700
!make_datetime(l_time1.second_part || l_time2.second_part ?
2701
DATE_TIME_MICROSECOND : DATE_TIME,
2707
l_time3.hour+= days*24;
2708
if (!make_datetime_with_warn(l_time1.second_part || l_time2.second_part ?
2709
TIME_MICROSECOND : TIME_ONLY,
2719
void Item_func_add_time::print(String *str, enum_query_type query_type)
2724
str->append(STRING_WITH_LEN("timestamp("));
2729
str->append(STRING_WITH_LEN("addtime("));
2731
str->append(STRING_WITH_LEN("subtime("));
2733
args[0]->print(str, query_type);
2735
args[1]->print(str, query_type);
2741
TIMEDIFF(t,s) is a time function that calculates the
2742
time value between a start and end time.
2744
t and s: time_or_datetime_expression
2748
String *Item_func_timediff::val_str(String *str)
2754
DRIZZLE_TIME l_time1 ,l_time2, l_time3;
2757
if (args[0]->get_time(&l_time1) ||
2758
args[1]->get_time(&l_time2) ||
2759
l_time1.time_type != l_time2.time_type)
2762
if (l_time1.neg != l_time2.neg)
2765
memset(&l_time3, 0, sizeof(l_time3));
2767
l_time3.neg= calc_time_diff(&l_time1, &l_time2, l_sign,
2768
&seconds, µseconds);
2771
For DRIZZLE_TIMESTAMP_TIME only:
2772
If first argument was negative and diff between arguments
2773
is non-zero we need to swap sign to get proper result.
2775
if (l_time1.neg && (seconds || microseconds))
2776
l_time3.neg= 1-l_time3.neg; // Swap sign of result
2778
calc_time_from_sec(&l_time3, (long) seconds, microseconds);
2780
if (!make_datetime_with_warn(l_time1.second_part || l_time2.second_part ?
2781
TIME_MICROSECOND : TIME_ONLY,
2791
MAKETIME(h,m,s) is a time function that calculates a time value
2792
from the total number of hours, minutes, and seconds.
2796
String *Item_func_maketime::val_str(String *str)
2802
int64_t hour= args[0]->val_int();
2803
int64_t minute= args[1]->val_int();
2804
int64_t second= args[2]->val_int();
2806
if ((null_value=(args[0]->null_value ||
2807
args[1]->null_value ||
2808
args[2]->null_value ||
2809
minute < 0 || minute > 59 ||
2810
second < 0 || second > 59 ||
2811
str->alloc(MAX_DATE_STRING_REP_LENGTH))))
2814
memset(<ime, 0, sizeof(ltime));
2817
/* Check for integer overflows */
2821
if (-hour > UINT_MAX || hour > UINT_MAX)
2826
ltime.hour= (uint) ((hour < 0 ? -hour : hour));
2827
ltime.minute= (uint) minute;
2828
ltime.second= (uint) second;
2832
ltime.hour= TIME_MAX_HOUR;
2833
ltime.minute= TIME_MAX_MINUTE;
2834
ltime.second= TIME_MAX_SECOND;
2836
char *ptr= int64_t10_to_str(hour, buf, args[0]->unsigned_flag ? 10 : -10);
2837
int len = (int)(ptr - buf) +
2838
sprintf(ptr, ":%02u:%02u", (uint)minute, (uint)second);
2839
make_truncated_value_warning(current_thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
2840
buf, len, DRIZZLE_TIMESTAMP_TIME,
2844
if (make_time_with_warn((DATE_TIME_FORMAT *) 0, <ime, str))
2854
MICROSECOND(a) is a function ( extraction) that extracts the microseconds
2857
a: Datetime or time value
2861
int64_t Item_func_microsecond::val_int()
2865
if (!get_arg0_time(<ime))
2866
return ltime.second_part;
2871
int64_t Item_func_timestamp_diff::val_int()
2873
DRIZZLE_TIME ltime1, ltime2;
2880
if (args[0]->get_date(<ime1, TIME_NO_ZERO_DATE) ||
2881
args[1]->get_date(<ime2, TIME_NO_ZERO_DATE))
2884
if (calc_time_diff(<ime2,<ime1, 1,
2885
&seconds, µseconds))
2888
if (int_type == INTERVAL_YEAR ||
2889
int_type == INTERVAL_QUARTER ||
2890
int_type == INTERVAL_MONTH)
2892
uint32_t year_beg, year_end, month_beg, month_end, day_beg, day_end;
2894
uint32_t second_beg, second_end, microsecond_beg, microsecond_end;
2898
year_beg= ltime2.year;
2899
year_end= ltime1.year;
2900
month_beg= ltime2.month;
2901
month_end= ltime1.month;
2902
day_beg= ltime2.day;
2903
day_end= ltime1.day;
2904
second_beg= ltime2.hour * 3600 + ltime2.minute * 60 + ltime2.second;
2905
second_end= ltime1.hour * 3600 + ltime1.minute * 60 + ltime1.second;
2906
microsecond_beg= ltime2.second_part;
2907
microsecond_end= ltime1.second_part;
2911
year_beg= ltime1.year;
2912
year_end= ltime2.year;
2913
month_beg= ltime1.month;
2914
month_end= ltime2.month;
2915
day_beg= ltime1.day;
2916
day_end= ltime2.day;
2917
second_beg= ltime1.hour * 3600 + ltime1.minute * 60 + ltime1.second;
2918
second_end= ltime2.hour * 3600 + ltime2.minute * 60 + ltime2.second;
2919
microsecond_beg= ltime1.second_part;
2920
microsecond_end= ltime2.second_part;
2924
years= year_end - year_beg;
2925
if (month_end < month_beg || (month_end == month_beg && day_end < day_beg))
2930
if (month_end < month_beg || (month_end == month_beg && day_end < day_beg))
2931
months+= 12 - (month_beg - month_end);
2933
months+= (month_end - month_beg);
2935
if (day_end < day_beg)
2937
else if ((day_end == day_beg) &&
2938
((second_end < second_beg) ||
2939
(second_end == second_beg && microsecond_end < microsecond_beg)))
2945
return months/12*neg;
2946
case INTERVAL_QUARTER:
2947
return months/3*neg;
2948
case INTERVAL_MONTH:
2951
return seconds/86400L/7L*neg;
2953
return seconds/86400L*neg;
2955
return seconds/3600L*neg;
2956
case INTERVAL_MINUTE:
2957
return seconds/60L*neg;
2958
case INTERVAL_SECOND:
2960
case INTERVAL_MICROSECOND:
2962
In MySQL difference between any two valid datetime values
2963
in microseconds fits into int64_t.
2965
return (seconds*1000000L+microseconds)*neg;
2976
void Item_func_timestamp_diff::print(String *str, enum_query_type query_type)
2978
str->append(func_name());
2983
str->append(STRING_WITH_LEN("YEAR"));
2985
case INTERVAL_QUARTER:
2986
str->append(STRING_WITH_LEN("QUARTER"));
2988
case INTERVAL_MONTH:
2989
str->append(STRING_WITH_LEN("MONTH"));
2992
str->append(STRING_WITH_LEN("WEEK"));
2995
str->append(STRING_WITH_LEN("DAY"));
2998
str->append(STRING_WITH_LEN("HOUR"));
3000
case INTERVAL_MINUTE:
3001
str->append(STRING_WITH_LEN("MINUTE"));
3003
case INTERVAL_SECOND:
3004
str->append(STRING_WITH_LEN("SECOND"));
3006
case INTERVAL_MICROSECOND:
3007
str->append(STRING_WITH_LEN("SECOND_FRAC"));
3013
for (uint32_t i=0 ; i < 2 ; i++)
3016
args[i]->print(str, query_type);
3022
String *Item_func_get_format::val_str(String *str)
3025
const char *format_name;
3026
KNOWN_DATE_TIME_FORMAT *format;
3027
String *val= args[0]->val_str(str);
3030
if ((null_value= args[0]->null_value))
3033
val_len= val->length();
3034
for (format= &known_date_time_formats[0];
3035
(format_name= format->format_name);
3038
uint32_t format_name_len;
3039
format_name_len= strlen(format_name);
3040
if (val_len == format_name_len &&
3041
!my_strnncoll(&my_charset_utf8_general_ci,
3042
(const unsigned char *) val->ptr(), val_len,
3043
(const unsigned char *) format_name, val_len))
3045
const char *format_str= get_date_time_format_str(format, type);
3046
str->set(format_str, strlen(format_str), &my_charset_bin);
3056
void Item_func_get_format::print(String *str, enum_query_type query_type)
3058
str->append(func_name());
3062
case DRIZZLE_TIMESTAMP_DATE:
3063
str->append(STRING_WITH_LEN("DATE, "));
3065
case DRIZZLE_TIMESTAMP_DATETIME:
3066
str->append(STRING_WITH_LEN("DATETIME, "));
3068
case DRIZZLE_TIMESTAMP_TIME:
3069
str->append(STRING_WITH_LEN("TIME, "));
3074
args[0]->print(str, query_type);
3080
Get type of datetime value (DATE/TIME/...) which will be produced
3081
according to format string.
3083
@param format format string
3084
@param length length of format string
3087
We don't process day format's characters('D', 'd', 'e') because day
3088
may be a member of all date/time types.
3091
Format specifiers supported by this function should be in sync with
3092
specifiers supported by extract_date_time() function.
3095
One of date_time_format_types values:
3096
- DATE_TIME_MICROSECOND
3103
static date_time_format_types
3104
get_date_time_result_type(const char *format, uint32_t length)
3106
const char *time_part_frms= "HISThiklrs";
3107
const char *date_part_frms= "MVUXYWabcjmvuxyw";
3108
bool date_part_used= 0, time_part_used= 0, frac_second_used= 0;
3110
const char *val= format;
3111
const char *end= format + length;
3113
for (; val != end && val != end; val++)
3115
if (*val == '%' && val+1 != end)
3119
frac_second_used= time_part_used= 1;
3120
else if (!time_part_used && strchr(time_part_frms, *val))
3122
else if (!date_part_used && strchr(date_part_frms, *val))
3124
if (date_part_used && frac_second_used)
3127
frac_second_used implies time_part_used, and thus we already
3128
have all types of date-time components and can end our search.
3130
return DATE_TIME_MICROSECOND;
3135
/* We don't have all three types of date-time components */
3136
if (frac_second_used)
3137
return TIME_MICROSECOND;
3148
void Item_func_str_to_date::fix_length_and_dec()
3152
cached_field_type= DRIZZLE_TYPE_DATETIME;
3153
max_length= MAX_DATETIME_FULL_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
3154
cached_timestamp_type= DRIZZLE_TIMESTAMP_NONE;
3155
if ((const_item= args[1]->const_item()))
3157
char format_buff[64];
3158
String format_str(format_buff, sizeof(format_buff), &my_charset_bin);
3159
String *format= args[1]->val_str(&format_str);
3160
if (!args[1]->null_value)
3162
cached_format_type= get_date_time_result_type(format->ptr(),
3164
switch (cached_format_type) {
3166
cached_timestamp_type= DRIZZLE_TIMESTAMP_DATE;
3167
cached_field_type= DRIZZLE_TYPE_NEWDATE;
3168
max_length= MAX_DATE_WIDTH * MY_CHARSET_BIN_MB_MAXLEN;
3171
case TIME_MICROSECOND:
3172
cached_timestamp_type= DRIZZLE_TIMESTAMP_TIME;
3173
cached_field_type= DRIZZLE_TYPE_TIME;
3174
max_length= MAX_TIME_WIDTH * MY_CHARSET_BIN_MB_MAXLEN;
3177
cached_timestamp_type= DRIZZLE_TIMESTAMP_DATETIME;
3178
cached_field_type= DRIZZLE_TYPE_DATETIME;
3186
bool Item_func_str_to_date::get_date(DRIZZLE_TIME *ltime, uint32_t fuzzy_date)
3188
DATE_TIME_FORMAT date_time_format;
3189
char val_buff[64], format_buff[64];
3190
String val_string(val_buff, sizeof(val_buff), &my_charset_bin), *val;
3191
String format_str(format_buff, sizeof(format_buff), &my_charset_bin), *format;
3193
val= args[0]->val_str(&val_string);
3194
format= args[1]->val_str(&format_str);
3195
if (args[0]->null_value || args[1]->null_value)
3199
memset(ltime, 0, sizeof(*ltime));
3200
date_time_format.format.str= (char*) format->ptr();
3201
date_time_format.format.length= format->length();
3202
if (extract_date_time(&date_time_format, val->ptr(), val->length(),
3203
ltime, cached_timestamp_type, 0, "datetime") ||
3204
((fuzzy_date & TIME_NO_ZERO_DATE) &&
3205
(ltime->year == 0 || ltime->month == 0 || ltime->day == 0)))
3207
if (cached_timestamp_type == DRIZZLE_TIMESTAMP_TIME && ltime->day)
3210
Day part for time type can be nonzero value and so
3211
we should add hours from day part to hour part to
3212
keep valid time value.
3214
ltime->hour+= ltime->day*24;
3220
return (null_value=1);
3224
String *Item_func_str_to_date::val_str(String *str)
3229
if (Item_func_str_to_date::get_date(<ime, TIME_FUZZY_DATE))
3232
if (!make_datetime((const_item ? cached_format_type :
3233
(ltime.second_part ? DATE_TIME_MICROSECOND : DATE_TIME)),
3240
bool Item_func_last_day::get_date(DRIZZLE_TIME *ltime, uint32_t fuzzy_date)
3242
if (get_arg0_date(ltime, fuzzy_date & ~TIME_FUZZY_DATE) ||
3243
(ltime->month == 0))
3249
uint32_t month_idx= ltime->month-1;
3250
ltime->day= days_in_month[month_idx];
3251
if ( month_idx == 1 && calc_days_in_year(ltime->year) == 366)
3253
ltime->hour= ltime->minute= ltime->second= 0;
3254
ltime->second_part= 0;
3255
ltime->time_type= DRIZZLE_TIMESTAMP_DATE;