1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
* Copyright (C) 2008 Sun Microsystems
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; version 2 of the License.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25
This file defines all time functions
28
Move month and days to language files
30
#include <drizzled/server_includes.h>
32
#include <drizzled/error.h>
33
#include <drizzled/tztime.h>
35
/** Day number for Dec 31st, 9999. */
36
#define MAX_DAY_NUMBER 3652424L
41
- Replace the switch with a function that should be called for each
43
- Remove sprintf and opencode the conversion, like we do in
46
The reason for this functions existence is that as we don't have a
47
way to know if a datetime/time value has microseconds in them
48
we are now only adding microseconds to the output if the
49
value has microseconds.
51
We can't use a standard make_date_time() for this as we don't know
52
if someone will use %f in the format specifier in which case we would get
53
the microseconds twice.
56
static bool make_datetime(date_time_format_types format, DRIZZLE_TIME *ltime,
60
const CHARSET_INFO * const cs= &my_charset_bin;
61
uint32_t length= MAX_DATE_STRING_REP_LENGTH;
63
if (str->alloc(length))
65
buff= (char*) str->ptr();
69
length= cs->cset->snprintf(cs, buff, length, "%s%02d:%02d:%02d",
70
ltime->neg ? "-" : "",
71
ltime->hour, ltime->minute, ltime->second);
73
case TIME_MICROSECOND:
74
length= cs->cset->snprintf(cs, buff, length, "%s%02d:%02d:%02d.%06ld",
75
ltime->neg ? "-" : "",
76
ltime->hour, ltime->minute, ltime->second,
80
length= cs->cset->snprintf(cs, buff, length, "%04d-%02d-%02d",
81
ltime->year, ltime->month, ltime->day);
84
length= cs->cset->snprintf(cs, buff, length,
85
"%04d-%02d-%02d %02d:%02d:%02d",
86
ltime->year, ltime->month, ltime->day,
87
ltime->hour, ltime->minute, ltime->second);
89
case DATE_TIME_MICROSECOND:
90
length= cs->cset->snprintf(cs, buff, length,
91
"%04d-%02d-%02d %02d:%02d:%02d.%06ld",
92
ltime->year, ltime->month, ltime->day,
93
ltime->hour, ltime->minute, ltime->second,
105
Wrapper over make_datetime() with validation of the input DRIZZLE_TIME value
108
see make_datetime() for more information
111
1 if there was an error during converion
115
static bool make_datetime_with_warn(date_time_format_types format, DRIZZLE_TIME *ltime,
120
if (make_datetime(format, ltime, str))
122
if (check_time_range(ltime, &warning))
127
make_truncated_value_warning(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
128
str->ptr(), str->length(),
129
DRIZZLE_TIMESTAMP_TIME, NULL);
130
return make_datetime(format, ltime, str);
135
Wrapper over make_time() with validation of the input DRIZZLE_TIME value
138
see make_time() for more info
141
1 if there was an error during conversion
145
static bool make_time_with_warn(const DATE_TIME_FORMAT *format,
146
DRIZZLE_TIME *l_time, String *str)
149
make_time(format, l_time, str);
150
if (check_time_range(l_time, &warning))
154
make_truncated_value_warning(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
155
str->ptr(), str->length(),
156
DRIZZLE_TIMESTAMP_TIME, NULL);
157
make_time(format, l_time, str);
165
Convert seconds to DRIZZLE_TIME value with overflow checking
169
seconds number of seconds
170
unsigned_flag 1, if 'seconds' is unsigned, 0, otherwise
171
ltime output DRIZZLE_TIME value
174
If the 'seconds' argument is inside DRIZZLE_TIME data range, convert it to a
176
Otherwise, truncate the resulting value to the nearest endpoint, and
177
produce a warning message.
180
1 if the value was truncated during conversion
184
static bool sec_to_time(int64_t seconds, bool unsigned_flag, DRIZZLE_TIME *ltime)
188
memset(ltime, 0, sizeof(*ltime));
193
if (seconds < -3020399)
197
else if (seconds > 3020399)
200
sec= (uint) ((uint64_t) seconds % 3600);
201
ltime->hour= (uint) (seconds/3600);
202
ltime->minute= sec/60;
203
ltime->second= sec % 60;
208
ltime->hour= TIME_MAX_HOUR;
209
ltime->minute= TIME_MAX_MINUTE;
210
ltime->second= TIME_MAX_SECOND;
213
int len= (int)(int64_t10_to_str(seconds, buf, unsigned_flag ? 10 : -10)
215
make_truncated_value_warning(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
216
buf, len, DRIZZLE_TIMESTAMP_TIME,
224
Date formats corresponding to compound %r and %T conversion specifiers
226
Note: We should init at least first element of "positions" array
227
(first member) or hpux11 compiler will die horribly.
229
static DATE_TIME_FORMAT time_ampm_format= {{0}, '\0', 0,
230
{(char *)"%I:%i:%S %p", 11}};
231
static DATE_TIME_FORMAT time_24hrs_format= {{0}, '\0', 0,
232
{(char *)"%H:%i:%S", 8}};
235
Extract datetime value to DRIZZLE_TIME struct from string value
236
according to format string.
238
@param format date/time format specification
239
@param val String to decode
240
@param length Length of string
241
@param l_time Store result here
242
@param cached_timestamp_type It uses to get an appropriate warning
243
in the case when the value is truncated.
244
@param sub_pattern_end if non-zero then we are parsing string which
245
should correspond compound specifier (like %T or
246
%r) and this parameter is pointer to place where
247
pointer to end of string matching this specifier
251
Possibility to parse strings matching to patterns equivalent to compound
252
specifiers is mainly intended for use from inside of this function in
253
order to understand %T and %r conversion specifiers, so number of
254
conversion specifiers that can be used in such sub-patterns is limited.
255
Also most of checks are skipped in this case.
258
If one adds new format specifiers to this function he should also
259
consider adding them to get_date_time_result_type() function.
267
static bool extract_date_time(DATE_TIME_FORMAT *format,
268
const char *val, uint32_t length, DRIZZLE_TIME *l_time,
269
enum enum_drizzle_timestamp_type cached_timestamp_type,
270
const char **sub_pattern_end,
271
const char *date_time_type)
273
int weekday= 0, yearday= 0, daypart= 0;
276
int strict_week_number_year= -1;
279
bool sunday_first_n_first_week_non_iso= false;
280
bool strict_week_number= false;
281
bool strict_week_number_year_type= false;
282
const char *val_begin= val;
283
const char *val_end= val + length;
284
const char *ptr= format->format.str;
285
const char *end= ptr + format->format.length;
286
const CHARSET_INFO * const cs= &my_charset_bin;
288
if (!sub_pattern_end)
289
memset(l_time, 0, sizeof(*l_time));
291
for (; ptr != end && val != val_end; ptr++)
293
/* Skip pre-space between each argument */
294
while (val != val_end && my_isspace(cs, *val))
297
if (*ptr == '%' && ptr+1 != end)
304
val_len= (uint) (val_end - val);
308
tmp= (char*) val + cmin(4, val_len);
309
l_time->year= (int) my_strtoll10(val, &tmp, &error);
310
if ((int) (tmp-val) <= 2)
311
l_time->year= year_2000_handling(l_time->year);
315
tmp= (char*) val + cmin(2, val_len);
316
l_time->year= (int) my_strtoll10(val, &tmp, &error);
318
l_time->year= year_2000_handling(l_time->year);
324
tmp= (char*) val + cmin(2, val_len);
325
l_time->month= (int) my_strtoll10(val, &tmp, &error);
329
if ((l_time->month= check_word(my_locale_en_US.month_names,
330
val, val_end, &val)) <= 0)
334
if ((l_time->month= check_word(my_locale_en_US.ab_month_names,
335
val, val_end, &val)) <= 0)
341
tmp= (char*) val + cmin(2, val_len);
342
l_time->day= (int) my_strtoll10(val, &tmp, &error);
346
tmp= (char*) val + cmin(2, val_len);
347
l_time->day= (int) my_strtoll10(val, &tmp, &error);
348
/* Skip 'st, 'nd, 'th .. */
349
val= tmp + cmin((int) (val_end-tmp), 2);
360
tmp= (char*) val + cmin(2, val_len);
361
l_time->hour= (int) my_strtoll10(val, &tmp, &error);
367
tmp= (char*) val + cmin(2, val_len);
368
l_time->minute= (int) my_strtoll10(val, &tmp, &error);
375
tmp= (char*) val + cmin(2, val_len);
376
l_time->second= (int) my_strtoll10(val, &tmp, &error);
382
tmp= (char*) val_end;
384
tmp= (char*) val + 6;
385
l_time->second_part= (int) my_strtoll10(val, &tmp, &error);
386
frac_part= 6 - (tmp - val);
388
l_time->second_part*= (ulong) log_10_int[frac_part];
394
if (val_len < 2 || ! usa_time)
396
if (!my_strnncoll(&my_charset_utf8_general_ci,
397
(const unsigned char *) val, 2,
398
(const unsigned char *) "PM", 2))
400
else if (my_strnncoll(&my_charset_utf8_general_ci,
401
(const unsigned char *) val, 2,
402
(const unsigned char *) "AM", 2))
409
if ((weekday= check_word(my_locale_en_US.day_names, val, val_end, &val)) <= 0)
413
if ((weekday= check_word(my_locale_en_US.ab_day_names, val, val_end, &val)) <= 0)
417
tmp= (char*) val + 1;
418
if ((weekday= (int) my_strtoll10(val, &tmp, &error)) < 0 ||
421
/* We should use the same 1 - 7 scale for %w as for %W */
427
tmp= (char*) val + cmin(val_len, 3);
428
yearday= (int) my_strtoll10(val, &tmp, &error);
437
sunday_first_n_first_week_non_iso= (*ptr=='U' || *ptr== 'V');
438
strict_week_number= (*ptr=='V' || *ptr=='v');
439
tmp= (char*) val + cmin(val_len, 2);
440
if ((week_number= (int) my_strtoll10(val, &tmp, &error)) < 0 ||
441
(strict_week_number && !week_number) ||
447
/* Year used with 'strict' %V and %v week numbers */
450
strict_week_number_year_type= (*ptr=='X');
451
tmp= (char*) val + cmin(4, val_len);
452
strict_week_number_year= (int) my_strtoll10(val, &tmp, &error);
456
/* Time in AM/PM notation */
459
We can't just set error here, as we don't want to generate two
460
warnings in case of errors
462
if (extract_date_time(&time_ampm_format, val,
463
(uint)(val_end - val), l_time,
464
cached_timestamp_type, &val, "time"))
468
/* Time in 24-hour notation */
470
if (extract_date_time(&time_24hrs_format, val,
471
(uint)(val_end - val), l_time,
472
cached_timestamp_type, &val, "time"))
476
/* Conversion specifiers that match classes of characters */
478
while (my_ispunct(cs, *val) && val != val_end)
482
while (my_isalpha(cs, *val) && val != val_end)
486
while (my_isdigit(cs, *val) && val != val_end)
492
if (error) // Error from my_strtoll10
495
else if (!my_isspace(cs, *ptr))
504
if (l_time->hour > 12 || l_time->hour < 1)
506
l_time->hour= l_time->hour%12+daypart;
510
If we are recursively called for parsing string matching compound
511
specifiers we are already done.
515
*sub_pattern_end= val;
522
days= calc_daynr(l_time->year,1,1) + yearday - 1;
523
if (days <= 0 || days > MAX_DAY_NUMBER)
525
get_date_from_daynr(days,&l_time->year,&l_time->month,&l_time->day);
528
if (week_number >= 0 && weekday)
534
%V,%v require %X,%x resprectively,
535
%U,%u should be used with %Y and not %X or %x
537
if ((strict_week_number &&
538
(strict_week_number_year < 0 || (strict_week_number_year_type != sunday_first_n_first_week_non_iso))) ||
539
(!strict_week_number && strict_week_number_year >= 0))
542
/* Number of days since year 0 till 1st Jan of this year */
543
days= calc_daynr((strict_week_number ? strict_week_number_year :
546
/* Which day of week is 1st Jan of this year */
547
weekday_b= calc_weekday(days, sunday_first_n_first_week_non_iso);
550
Below we are going to sum:
551
1) number of days since year 0 till 1st day of 1st week of this year
552
2) number of days between 1st week and our week
553
3) and position of our day in the week
555
if (sunday_first_n_first_week_non_iso)
557
days+= ((weekday_b == 0) ? 0 : 7) - weekday_b +
558
(week_number - 1) * 7 +
563
days+= ((weekday_b <= 3) ? 0 : 7) - weekday_b +
564
(week_number - 1) * 7 +
568
if (days <= 0 || days > MAX_DAY_NUMBER)
570
get_date_from_daynr(days,&l_time->year,&l_time->month,&l_time->day);
573
if (l_time->month > 12 || l_time->day > 31 || l_time->hour > 23 ||
574
l_time->minute > 59 || l_time->second > 59)
581
if (!my_isspace(&my_charset_utf8_general_ci,*val))
583
make_truncated_value_warning(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
585
cached_timestamp_type, NULL);
588
} while (++val != val_end);
595
strmake(buff, val_begin, cmin(length, (uint)sizeof(buff)-1));
596
push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
597
ER_WRONG_VALUE_FOR_TYPE, ER(ER_WRONG_VALUE_FOR_TYPE),
598
date_time_type, buff, "str_to_date");
605
Create a formated date/time value in a string.
608
bool make_date_time(DATE_TIME_FORMAT *format, DRIZZLE_TIME *l_time,
609
enum enum_drizzle_timestamp_type type, String *str)
615
const char *ptr, *end;
616
Session *session= current_session;
617
MY_LOCALE *locale= session->variables.lc_time_names;
624
end= (ptr= format->format.str) + format->format.length;
625
for (; ptr != end ; ptr++)
627
if (*ptr != '%' || ptr+1 == end)
635
str->append(locale->month_names->type_names[l_time->month-1],
636
strlen(locale->month_names->type_names[l_time->month-1]),
637
system_charset_info);
642
str->append(locale->ab_month_names->type_names[l_time->month-1],
643
strlen(locale->ab_month_names->type_names[l_time->month-1]),
644
system_charset_info);
647
if (type == DRIZZLE_TIMESTAMP_TIME)
649
weekday= calc_weekday(calc_daynr(l_time->year,l_time->month,
651
str->append(locale->day_names->type_names[weekday],
652
strlen(locale->day_names->type_names[weekday]),
653
system_charset_info);
656
if (type == DRIZZLE_TIMESTAMP_TIME)
658
weekday=calc_weekday(calc_daynr(l_time->year,l_time->month,
660
str->append(locale->ab_day_names->type_names[weekday],
661
strlen(locale->ab_day_names->type_names[weekday]),
662
system_charset_info);
665
if (type == DRIZZLE_TIMESTAMP_TIME)
667
length= int10_to_str(l_time->day, intbuff, 10) - intbuff;
668
str->append_with_prefill(intbuff, length, 1, '0');
669
if (l_time->day >= 10 && l_time->day <= 19)
670
str->append(STRING_WITH_LEN("th"));
673
switch (l_time->day %10) {
675
str->append(STRING_WITH_LEN("st"));
678
str->append(STRING_WITH_LEN("nd"));
681
str->append(STRING_WITH_LEN("rd"));
684
str->append(STRING_WITH_LEN("th"));
690
length= int10_to_str(l_time->year, intbuff, 10) - intbuff;
691
str->append_with_prefill(intbuff, length, 4, '0');
694
length= int10_to_str(l_time->year%100, intbuff, 10) - intbuff;
695
str->append_with_prefill(intbuff, length, 2, '0');
698
length= int10_to_str(l_time->month, intbuff, 10) - intbuff;
699
str->append_with_prefill(intbuff, length, 2, '0');
702
length= int10_to_str(l_time->month, intbuff, 10) - intbuff;
703
str->append_with_prefill(intbuff, length, 1, '0');
706
length= int10_to_str(l_time->day, intbuff, 10) - intbuff;
707
str->append_with_prefill(intbuff, length, 2, '0');
710
length= int10_to_str(l_time->day, intbuff, 10) - intbuff;
711
str->append_with_prefill(intbuff, length, 1, '0');
714
length= int10_to_str(l_time->second_part, intbuff, 10) - intbuff;
715
str->append_with_prefill(intbuff, length, 6, '0');
718
length= int10_to_str(l_time->hour, intbuff, 10) - intbuff;
719
str->append_with_prefill(intbuff, length, 2, '0');
723
hours_i= (l_time->hour%24 + 11)%12+1;
724
length= int10_to_str(hours_i, intbuff, 10) - intbuff;
725
str->append_with_prefill(intbuff, length, 2, '0');
727
case 'i': /* minutes */
728
length= int10_to_str(l_time->minute, intbuff, 10) - intbuff;
729
str->append_with_prefill(intbuff, length, 2, '0');
732
if (type == DRIZZLE_TIMESTAMP_TIME)
734
length= int10_to_str(calc_daynr(l_time->year,l_time->month,
736
calc_daynr(l_time->year,1,1) + 1, intbuff, 10) - intbuff;
737
str->append_with_prefill(intbuff, length, 3, '0');
740
length= int10_to_str(l_time->hour, intbuff, 10) - intbuff;
741
str->append_with_prefill(intbuff, length, 1, '0');
744
hours_i= (l_time->hour%24 + 11)%12+1;
745
length= int10_to_str(hours_i, intbuff, 10) - intbuff;
746
str->append_with_prefill(intbuff, length, 1, '0');
749
hours_i= l_time->hour%24;
750
str->append(hours_i < 12 ? "AM" : "PM",2);
753
length= sprintf(intbuff,
754
((l_time->hour % 24) < 12) ?
755
"%02d:%02d:%02d AM" : "%02d:%02d:%02d PM",
756
(l_time->hour+11)%12+1,
759
str->append(intbuff, length);
763
length= int10_to_str(l_time->second, intbuff, 10) - intbuff;
764
str->append_with_prefill(intbuff, length, 2, '0');
767
length= sprintf(intbuff,
772
str->append(intbuff, length);
778
if (type == DRIZZLE_TIMESTAMP_TIME)
780
length= int10_to_str(calc_week(l_time,
782
WEEK_FIRST_WEEKDAY : WEEK_MONDAY_FIRST,
784
intbuff, 10) - intbuff;
785
str->append_with_prefill(intbuff, length, 2, '0');
792
if (type == DRIZZLE_TIMESTAMP_TIME)
794
length= int10_to_str(calc_week(l_time,
796
(WEEK_YEAR | WEEK_FIRST_WEEKDAY) :
797
(WEEK_YEAR | WEEK_MONDAY_FIRST)),
799
intbuff, 10) - intbuff;
800
str->append_with_prefill(intbuff, length, 2, '0');
807
if (type == DRIZZLE_TIMESTAMP_TIME)
809
(void) calc_week(l_time,
811
WEEK_YEAR | WEEK_FIRST_WEEKDAY :
812
WEEK_YEAR | WEEK_MONDAY_FIRST),
814
length= int10_to_str(year, intbuff, 10) - intbuff;
815
str->append_with_prefill(intbuff, length, 4, '0');
819
if (type == DRIZZLE_TIMESTAMP_TIME)
821
weekday=calc_weekday(calc_daynr(l_time->year,l_time->month,
823
length= int10_to_str(weekday, intbuff, 10) - intbuff;
824
str->append_with_prefill(intbuff, length, 1, '0');
839
Get a array of positive numbers from a string object.
840
Each number is separated by 1 non digit character
841
Return error if there is too many numbers.
842
If there is too few numbers, assume that the numbers are left out
843
from the high end. This allows one to give:
844
DAY_TO_SECOND as "D MM:HH:SS", "MM:HH:SS" "HH:SS" or as seconds.
846
@param length: length of str
847
@param cs: charset of str
848
@param values: array of results
849
@param count: count of elements in result array
850
@param transform_msec: if value is true we suppose
851
that the last part of string value is microseconds
852
and we should transform value to six digit value.
853
For example, '1.1' -> '1.100000'
856
static bool get_interval_info(const char *str,uint32_t length, const CHARSET_INFO * const cs,
857
uint32_t count, uint64_t *values,
860
const char *end=str+length;
862
while (str != end && !my_isdigit(cs,*str))
865
for (i=0 ; i < count ; i++)
868
const char *start= str;
869
for (value=0; str != end && my_isdigit(cs,*str) ; str++)
870
value= value * 10L + (int64_t) (*str - '0');
871
if (transform_msec && i == count - 1) // microseconds always last
873
long msec_length= 6 - (str - start);
875
value*= (long) log_10_int[msec_length];
878
while (str != end && !my_isdigit(cs,*str))
880
if (str == end && i != count-1)
883
/* Change values[0...i-1] -> values[0...count-1] */
884
bmove_upp((unsigned char*) (values+count), (unsigned char*) (values+i),
886
memset(values, 0, sizeof(*values)*(count-i));
894
Convert a string to a interval value.
896
To make code easy, allow interval objects without separators.
899
bool get_interval_value(Item *args,interval_type int_type,
900
String *str_value, INTERVAL *interval)
904
const char *str= NULL;
906
const CHARSET_INFO * const cs= str_value->charset();
908
memset(interval, 0, sizeof(*interval));
909
if ((int) int_type <= INTERVAL_MICROSECOND)
911
value= args->val_int();
912
if (args->null_value)
923
if (!(res=args->val_str(str_value)))
926
/* record negative intervalls in interval->neg */
928
const char *end=str+res->length();
929
while (str != end && my_isspace(cs,*str))
931
if (str != end && *str == '-')
936
length= (size_t) (end-str); // Set up pointers to new str
941
interval->year= (ulong) value;
943
case INTERVAL_QUARTER:
944
interval->month= (ulong)(value*3);
947
interval->month= (ulong) value;
950
interval->day= (ulong)(value*7);
953
interval->day= (ulong) value;
956
interval->hour= (ulong) value;
958
case INTERVAL_MICROSECOND:
959
interval->second_part=value;
961
case INTERVAL_MINUTE:
962
interval->minute=value;
964
case INTERVAL_SECOND:
965
interval->second=value;
967
case INTERVAL_YEAR_MONTH: // Allow YEAR-MONTH YYYYYMM
968
if (get_interval_info(str,length,cs,2,array,0))
970
interval->year= (ulong) array[0];
971
interval->month= (ulong) array[1];
973
case INTERVAL_DAY_HOUR:
974
if (get_interval_info(str,length,cs,2,array,0))
976
interval->day= (ulong) array[0];
977
interval->hour= (ulong) array[1];
979
case INTERVAL_DAY_MICROSECOND:
980
if (get_interval_info(str,length,cs,5,array,1))
982
interval->day= (ulong) array[0];
983
interval->hour= (ulong) array[1];
984
interval->minute= array[2];
985
interval->second= array[3];
986
interval->second_part= array[4];
988
case INTERVAL_DAY_MINUTE:
989
if (get_interval_info(str,length,cs,3,array,0))
991
interval->day= (ulong) array[0];
992
interval->hour= (ulong) array[1];
993
interval->minute= array[2];
995
case INTERVAL_DAY_SECOND:
996
if (get_interval_info(str,length,cs,4,array,0))
998
interval->day= (ulong) array[0];
999
interval->hour= (ulong) array[1];
1000
interval->minute= array[2];
1001
interval->second= array[3];
1003
case INTERVAL_HOUR_MICROSECOND:
1004
if (get_interval_info(str,length,cs,4,array,1))
1006
interval->hour= (ulong) array[0];
1007
interval->minute= array[1];
1008
interval->second= array[2];
1009
interval->second_part= array[3];
1011
case INTERVAL_HOUR_MINUTE:
1012
if (get_interval_info(str,length,cs,2,array,0))
1014
interval->hour= (ulong) array[0];
1015
interval->minute= array[1];
1017
case INTERVAL_HOUR_SECOND:
1018
if (get_interval_info(str,length,cs,3,array,0))
1020
interval->hour= (ulong) array[0];
1021
interval->minute= array[1];
1022
interval->second= array[2];
1024
case INTERVAL_MINUTE_MICROSECOND:
1025
if (get_interval_info(str,length,cs,3,array,1))
1027
interval->minute= array[0];
1028
interval->second= array[1];
1029
interval->second_part= array[2];
1031
case INTERVAL_MINUTE_SECOND:
1032
if (get_interval_info(str,length,cs,2,array,0))
1034
interval->minute= array[0];
1035
interval->second= array[1];
1037
case INTERVAL_SECOND_MICROSECOND:
1038
if (get_interval_info(str,length,cs,2,array,1))
1040
interval->second= array[0];
1041
interval->second_part= array[1];
1043
case INTERVAL_LAST: /* purecov: begin deadcode */
1045
break; /* purecov: end */
1051
String *Item_func_sec_to_time::val_str(String *str)
1055
int64_t arg_val= args[0]->val_int();
1057
if ((null_value=args[0]->null_value) ||
1058
str->alloc(MAX_DATE_STRING_REP_LENGTH))
1064
sec_to_time(arg_val, args[0]->unsigned_flag, <ime);
1066
make_time((DATE_TIME_FORMAT *) 0, <ime, str);
1071
int64_t Item_func_sec_to_time::val_int()
1075
int64_t arg_val= args[0]->val_int();
1077
if ((null_value=args[0]->null_value))
1080
sec_to_time(arg_val, args[0]->unsigned_flag, <ime);
1082
return (ltime.neg ? -1 : 1) *
1083
((ltime.hour)*10000 + ltime.minute*100 + ltime.second);
1087
void Item_func_date_format::fix_length_and_dec()
1089
Session* session= current_session;
1091
Must use this_item() in case it's a local SP variable
1092
(for ->max_length and ->str_value)
1094
Item *arg1= args[1]->this_item();
1097
const CHARSET_INFO * const cs= session->variables.collation_connection;
1098
uint32_t repertoire= arg1->collation.repertoire;
1099
if (!session->variables.lc_time_names->is_ascii)
1100
repertoire|= MY_REPERTOIRE_EXTENDED;
1101
collation.set(cs, arg1->collation.derivation, repertoire);
1102
if (arg1->type() == STRING_ITEM)
1103
{ // Optimize the normal case
1105
max_length= format_length(&arg1->str_value) *
1106
collation.collation->mbmaxlen;
1111
max_length=cmin(arg1->max_length,(uint32_t) MAX_BLOB_WIDTH) * 10 *
1112
collation.collation->mbmaxlen;
1113
set_if_smaller(max_length,MAX_BLOB_WIDTH);
1115
maybe_null=1; // If wrong date
1119
bool Item_func_date_format::eq(const Item *item, bool binary_cmp) const
1121
Item_func_date_format *item_func;
1123
if (item->type() != FUNC_ITEM)
1125
if (func_name() != ((Item_func*) item)->func_name())
1129
item_func= (Item_func_date_format*) item;
1130
if (!args[0]->eq(item_func->args[0], binary_cmp))
1133
We must compare format string case sensitive.
1134
This needed because format modifiers with different case,
1135
for example %m and %M, have different meaning.
1137
if (!args[1]->eq(item_func->args[1], 1))
1144
uint32_t Item_func_date_format::format_length(const String *format)
1147
const char *ptr=format->ptr();
1148
const char *end=ptr+format->length();
1150
for (; ptr != end ; ptr++)
1152
if (*ptr != '%' || ptr == end-1)
1157
case 'M': /* month, textual */
1158
case 'W': /* day (of the week), textual */
1159
size += 64; /* large for UTF8 locale data */
1161
case 'D': /* day (of the month), numeric plus english suffix */
1162
case 'Y': /* year, numeric, 4 digits */
1163
case 'x': /* Year, used with 'v' */
1164
case 'X': /* Year, used with 'v, where week starts with Monday' */
1167
case 'a': /* locale's abbreviated weekday name (Sun..Sat) */
1168
case 'b': /* locale's abbreviated month name (Jan.Dec) */
1169
size += 32; /* large for UTF8 locale data */
1171
case 'j': /* day of year (001..366) */
1174
case 'U': /* week (00..52) */
1175
case 'u': /* week (00..52), where week starts with Monday */
1176
case 'V': /* week 1..53 used with 'x' */
1177
case 'v': /* week 1..53 used with 'x', where week starts with Monday */
1178
case 'y': /* year, numeric, 2 digits */
1179
case 'm': /* month, numeric */
1180
case 'd': /* day (of the month), numeric */
1181
case 'h': /* hour (01..12) */
1182
case 'I': /* --||-- */
1183
case 'i': /* minutes, numeric */
1184
case 'l': /* hour ( 1..12) */
1185
case 'p': /* locale's AM or PM */
1186
case 'S': /* second (00..61) */
1187
case 's': /* seconds, numeric */
1188
case 'c': /* month (0..12) */
1189
case 'e': /* day (0..31) */
1192
case 'k': /* hour ( 0..23) */
1193
case 'H': /* hour (00..23; value > 23 OK, padding always 2-digit) */
1194
size += 7; /* docs allow > 23, range depends on sizeof(unsigned int) */
1196
case 'r': /* time, 12-hour (hh:mm:ss [AP]M) */
1199
case 'T': /* time, 24-hour (hh:mm:ss) */
1202
case 'f': /* microseconds */
1205
case 'w': /* day (of the week), numeric */
1217
String *Item_func_date_format::val_str(String *str)
1220
DRIZZLE_TIME l_time;
1224
if (!is_time_format)
1226
if (get_arg0_date(&l_time, TIME_FUZZY_DATE))
1232
if (!(res=args[0]->val_str(str)) ||
1233
(str_to_time_with_warn(res->ptr(), res->length(), &l_time)))
1236
l_time.year=l_time.month=l_time.day=0;
1240
if (!(format = args[1]->val_str(str)) || !format->length())
1246
size=format_length(format);
1248
if (size < MAX_DATE_STRING_REP_LENGTH)
1249
size= MAX_DATE_STRING_REP_LENGTH;
1252
str= &value; // Save result here
1253
if (str->alloc(size))
1256
DATE_TIME_FORMAT date_time_format;
1257
date_time_format.format.str= (char*) format->ptr();
1258
date_time_format.format.length= format->length();
1260
/* Create the result string */
1261
str->set_charset(collation.collation);
1262
if (!make_date_time(&date_time_format, &l_time,
1263
is_time_format ? DRIZZLE_TIMESTAMP_TIME :
1264
DRIZZLE_TIMESTAMP_DATE,
1274
void Item_func_from_unixtime::fix_length_and_dec()
1276
session= current_session;
1277
collation.set(&my_charset_bin);
1278
decimals= DATETIME_DEC;
1279
max_length=MAX_DATETIME_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
1281
session->time_zone_used= 1;
1285
String *Item_func_from_unixtime::val_str(String *str)
1287
DRIZZLE_TIME time_tmp;
1291
if (get_date(&time_tmp, 0))
1294
if (str->alloc(MAX_DATE_STRING_REP_LENGTH))
1300
make_datetime((DATE_TIME_FORMAT *) 0, &time_tmp, str);
1306
int64_t Item_func_from_unixtime::val_int()
1308
DRIZZLE_TIME time_tmp;
1312
if (get_date(&time_tmp, 0))
1315
return (int64_t) TIME_to_uint64_t_datetime(&time_tmp);
1318
bool Item_func_from_unixtime::get_date(DRIZZLE_TIME *ltime,
1319
uint32_t fuzzy_date __attribute__((unused)))
1321
uint64_t tmp= (uint64_t)(args[0]->val_int());
1323
"tmp > TIMESTAMP_MAX_VALUE" check also covers case of negative
1324
from_unixtime() argument since tmp is unsigned.
1326
if ((null_value= (args[0]->null_value || tmp > TIMESTAMP_MAX_VALUE)))
1329
session->variables.time_zone->gmt_sec_to_TIME(ltime, (my_time_t)tmp);
1335
void Item_date_add_interval::fix_length_and_dec()
1337
enum_field_types arg0_field_type;
1339
collation.set(&my_charset_bin);
1341
max_length=MAX_DATETIME_FULL_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
1342
value.alloc(max_length);
1345
The field type for the result of an Item_date function is defined as
1348
- If first arg is a DRIZZLE_TYPE_DATETIME result is DRIZZLE_TYPE_DATETIME
1349
- If first arg is a DRIZZLE_TYPE_NEWDATE and the interval type uses hours,
1350
minutes or seconds then type is DRIZZLE_TYPE_DATETIME.
1351
- Otherwise the result is DRIZZLE_TYPE_VARCHAR
1352
(This is because you can't know if the string contains a DATE, DRIZZLE_TIME or
1355
cached_field_type= DRIZZLE_TYPE_VARCHAR;
1356
arg0_field_type= args[0]->field_type();
1357
if (arg0_field_type == DRIZZLE_TYPE_DATETIME ||
1358
arg0_field_type == DRIZZLE_TYPE_TIMESTAMP)
1359
cached_field_type= DRIZZLE_TYPE_DATETIME;
1360
else if (arg0_field_type == DRIZZLE_TYPE_NEWDATE)
1362
if (int_type <= INTERVAL_DAY || int_type == INTERVAL_YEAR_MONTH)
1363
cached_field_type= arg0_field_type;
1365
cached_field_type= DRIZZLE_TYPE_DATETIME;
1370
/* Here arg[1] is a Item_interval object */
1372
bool Item_date_add_interval::get_date(DRIZZLE_TIME *ltime, uint32_t fuzzy_date __attribute__((unused)))
1376
if (args[0]->get_date(ltime, TIME_NO_ZERO_DATE) ||
1377
get_interval_value(args[1], int_type, &value, &interval))
1378
return (null_value=1);
1380
if (date_sub_interval)
1381
interval.neg = !interval.neg;
1383
if ((null_value= date_add_interval(ltime, int_type, interval)))
1389
String *Item_date_add_interval::val_str(String *str)
1393
enum date_time_format_types format;
1395
if (Item_date_add_interval::get_date(<ime, TIME_NO_ZERO_DATE))
1398
if (ltime.time_type == DRIZZLE_TIMESTAMP_DATE)
1400
else if (ltime.second_part)
1401
format= DATE_TIME_MICROSECOND;
1405
if (!make_datetime(format, <ime, str))
1413
int64_t Item_date_add_interval::val_int()
1418
if (Item_date_add_interval::get_date(<ime, TIME_NO_ZERO_DATE))
1420
date = (ltime.year*100L + ltime.month)*100L + ltime.day;
1421
return ltime.time_type == DRIZZLE_TIMESTAMP_DATE ? date :
1422
((date*100L + ltime.hour)*100L+ ltime.minute)*100L + ltime.second;
1427
bool Item_date_add_interval::eq(const Item *item, bool binary_cmp) const
1429
Item_date_add_interval *other= (Item_date_add_interval*) item;
1430
if (!Item_func::eq(item, binary_cmp))
1432
return ((int_type == other->int_type) &&
1433
(date_sub_interval == other->date_sub_interval));
1437
'interval_names' reflects the order of the enumeration interval_type.
1441
static const char *interval_names[]=
1443
"year", "quarter", "month", "week", "day",
1444
"hour", "minute", "second", "microsecond",
1445
"year_month", "day_hour", "day_minute",
1446
"day_second", "hour_minute", "hour_second",
1447
"minute_second", "day_microsecond",
1448
"hour_microsecond", "minute_microsecond",
1449
"second_microsecond"
1452
void Item_date_add_interval::print(String *str, enum_query_type query_type)
1455
args[0]->print(str, query_type);
1456
str->append(date_sub_interval?" - interval ":" + interval ");
1457
args[1]->print(str, query_type);
1459
str->append(interval_names[int_type]);
1463
void Item_extract::print(String *str, enum_query_type query_type)
1465
str->append(STRING_WITH_LEN("extract("));
1466
str->append(interval_names[int_type]);
1467
str->append(STRING_WITH_LEN(" from "));
1468
args[0]->print(str, query_type);
1472
void Item_extract::fix_length_and_dec()
1474
value.alloc(32); // alloc buffer
1476
maybe_null=1; // If wrong date
1478
case INTERVAL_YEAR: max_length=4; date_value=1; break;
1479
case INTERVAL_YEAR_MONTH: max_length=6; date_value=1; break;
1480
case INTERVAL_QUARTER: max_length=2; date_value=1; break;
1481
case INTERVAL_MONTH: max_length=2; date_value=1; break;
1482
case INTERVAL_WEEK: max_length=2; date_value=1; break;
1483
case INTERVAL_DAY: max_length=2; date_value=1; break;
1484
case INTERVAL_DAY_HOUR: max_length=9; date_value=0; break;
1485
case INTERVAL_DAY_MINUTE: max_length=11; date_value=0; break;
1486
case INTERVAL_DAY_SECOND: max_length=13; date_value=0; break;
1487
case INTERVAL_HOUR: max_length=2; date_value=0; break;
1488
case INTERVAL_HOUR_MINUTE: max_length=4; date_value=0; break;
1489
case INTERVAL_HOUR_SECOND: max_length=6; date_value=0; break;
1490
case INTERVAL_MINUTE: max_length=2; date_value=0; break;
1491
case INTERVAL_MINUTE_SECOND: max_length=4; date_value=0; break;
1492
case INTERVAL_SECOND: max_length=2; date_value=0; break;
1493
case INTERVAL_MICROSECOND: max_length=2; date_value=0; break;
1494
case INTERVAL_DAY_MICROSECOND: max_length=20; date_value=0; break;
1495
case INTERVAL_HOUR_MICROSECOND: max_length=13; date_value=0; break;
1496
case INTERVAL_MINUTE_MICROSECOND: max_length=11; date_value=0; break;
1497
case INTERVAL_SECOND_MICROSECOND: max_length=9; date_value=0; break;
1498
case INTERVAL_LAST: assert(0); break; /* purecov: deadcode */
1503
int64_t Item_extract::val_int()
1512
if (get_arg0_date(<ime, TIME_FUZZY_DATE))
1518
String *res= args[0]->val_str(&value);
1519
if (!res || str_to_time_with_warn(res->ptr(), res->length(), <ime))
1524
neg= ltime.neg ? -1 : 1;
1528
case INTERVAL_YEAR: return ltime.year;
1529
case INTERVAL_YEAR_MONTH: return ltime.year*100L+ltime.month;
1530
case INTERVAL_QUARTER: return (ltime.month+2)/3;
1531
case INTERVAL_MONTH: return ltime.month;
1534
week_format= current_session->variables.default_week_format;
1535
return calc_week(<ime, week_mode(week_format), &year);
1537
case INTERVAL_DAY: return ltime.day;
1538
case INTERVAL_DAY_HOUR: return (long) (ltime.day*100L+ltime.hour)*neg;
1539
case INTERVAL_DAY_MINUTE: return (long) (ltime.day*10000L+
1542
case INTERVAL_DAY_SECOND: return ((int64_t) ltime.day*1000000L+
1543
(int64_t) (ltime.hour*10000L+
1546
case INTERVAL_HOUR: return (long) ltime.hour*neg;
1547
case INTERVAL_HOUR_MINUTE: return (long) (ltime.hour*100+ltime.minute)*neg;
1548
case INTERVAL_HOUR_SECOND: return (long) (ltime.hour*10000+ltime.minute*100+
1550
case INTERVAL_MINUTE: return (long) ltime.minute*neg;
1551
case INTERVAL_MINUTE_SECOND: return (long) (ltime.minute*100+ltime.second)*neg;
1552
case INTERVAL_SECOND: return (long) ltime.second*neg;
1553
case INTERVAL_MICROSECOND: return (long) ltime.second_part*neg;
1554
case INTERVAL_DAY_MICROSECOND: return (((int64_t)ltime.day*1000000L +
1555
(int64_t)ltime.hour*10000L +
1557
ltime.second)*1000000L +
1558
ltime.second_part)*neg;
1559
case INTERVAL_HOUR_MICROSECOND: return (((int64_t)ltime.hour*10000L +
1561
ltime.second)*1000000L +
1562
ltime.second_part)*neg;
1563
case INTERVAL_MINUTE_MICROSECOND: return (((int64_t)(ltime.minute*100+
1564
ltime.second))*1000000L+
1565
ltime.second_part)*neg;
1566
case INTERVAL_SECOND_MICROSECOND: return ((int64_t)ltime.second*1000000L+
1567
ltime.second_part)*neg;
1568
case INTERVAL_LAST: assert(0); break; /* purecov: deadcode */
1570
return 0; // Impossible
1573
bool Item_extract::eq(const Item *item, bool binary_cmp) const
1577
if (item->type() != FUNC_ITEM ||
1578
functype() != ((Item_func*)item)->functype())
1581
Item_extract* ie= (Item_extract*)item;
1582
if (ie->int_type != int_type)
1585
if (!args[0]->eq(ie->args[0], binary_cmp))
1591
bool Item_char_typecast::eq(const Item *item, bool binary_cmp) const
1595
if (item->type() != FUNC_ITEM ||
1596
functype() != ((Item_func*)item)->functype())
1599
Item_char_typecast *cast= (Item_char_typecast*)item;
1600
if (cast_length != cast->cast_length ||
1601
cast_cs != cast->cast_cs)
1604
if (!args[0]->eq(cast->args[0], binary_cmp))
1609
void Item_typecast::print(String *str, enum_query_type query_type)
1611
str->append(STRING_WITH_LEN("cast("));
1612
args[0]->print(str, query_type);
1613
str->append(STRING_WITH_LEN(" as "));
1614
str->append(cast_type());
1619
void Item_char_typecast::print(String *str, enum_query_type query_type)
1621
str->append(STRING_WITH_LEN("cast("));
1622
args[0]->print(str, query_type);
1623
str->append(STRING_WITH_LEN(" as char"));
1624
if (cast_length >= 0)
1628
// my_charset_bin is good enough for numbers
1629
String st(buffer, sizeof(buffer), &my_charset_bin);
1630
st.set((uint64_t)cast_length, &my_charset_bin);
1636
str->append(STRING_WITH_LEN(" charset "));
1637
str->append(cast_cs->csname);
1642
String *Item_char_typecast::val_str(String *str)
1648
if (!charset_conversion)
1650
if (!(res= args[0]->val_str(str)))
1658
// Convert character set if differ
1659
uint32_t dummy_errors;
1660
if (!(res= args[0]->val_str(&tmp_value)) ||
1661
str->copy(res->ptr(), res->length(), from_cs,
1662
cast_cs, &dummy_errors))
1670
res->set_charset(cast_cs);
1673
Cut the tail if cast with length
1674
and the result is longer than cast length, e.g.
1675
CAST('string' AS CHAR(1))
1677
if (cast_length >= 0)
1679
if (res->length() > (length= (uint32_t) res->charpos(cast_length)))
1680
{ // Safe even if const arg
1682
snprintf(char_type, sizeof(char_type), "%s(%lu)",
1683
cast_cs == &my_charset_bin ? "BINARY" : "CHAR",
1686
if (!res->alloced_length())
1687
{ // Don't change const str
1688
str_value= *res; // Not malloced string
1691
push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
1692
ER_TRUNCATED_WRONG_VALUE,
1693
ER(ER_TRUNCATED_WRONG_VALUE), char_type,
1695
res->length((uint) length);
1697
else if (cast_cs == &my_charset_bin && res->length() < (uint) cast_length)
1699
if (res->alloced_length() < (uint) cast_length)
1701
str->alloc(cast_length);
1705
memset(res->ptr() + res->length(), 0,
1706
(uint) cast_length - res->length());
1707
res->length(cast_length);
1715
void Item_char_typecast::fix_length_and_dec()
1717
uint32_t char_length;
1719
We always force character set conversion if cast_cs
1720
is a multi-byte character set. It garantees that the
1721
result of CAST is a well-formed string.
1722
For single-byte character sets we allow just to copy
1723
from the argument. A single-byte character sets string
1724
is always well-formed.
1726
There is a special trick to convert form a number to ucs2.
1727
As numbers have my_charset_bin as their character set,
1728
it wouldn't do conversion to ucs2 without an additional action.
1729
To force conversion, we should pretend to be non-binary.
1730
Let's choose from_cs this way:
1731
- If the argument in a number and cast_cs is ucs2 (i.e. mbminlen > 1),
1732
then from_cs is set to latin1, to perform latin1 -> ucs2 conversion.
1733
- If the argument is a number and cast_cs is ASCII-compatible
1734
(i.e. mbminlen == 1), then from_cs is set to cast_cs,
1735
which allows just to take over the args[0]->val_str() result
1736
and thus avoid unnecessary character set conversion.
1737
- If the argument is not a number, then from_cs is set to
1738
the argument's charset.
1740
from_cs= (args[0]->result_type() == INT_RESULT ||
1741
args[0]->result_type() == DECIMAL_RESULT ||
1742
args[0]->result_type() == REAL_RESULT) ?
1743
(cast_cs->mbminlen == 1 ? cast_cs : &my_charset_utf8_general_ci) :
1744
args[0]->collation.collation;
1745
charset_conversion= (cast_cs->mbmaxlen > 1) ||
1746
(!my_charset_same(from_cs, cast_cs) && from_cs != &my_charset_bin && cast_cs != &my_charset_bin);
1747
collation.set(cast_cs, DERIVATION_IMPLICIT);
1748
char_length= (cast_length >= 0) ? cast_length :
1749
args[0]->max_length/from_cs->mbmaxlen;
1750
max_length= char_length * cast_cs->mbmaxlen;
1754
String *Item_datetime_typecast::val_str(String *str)
1759
if (!get_arg0_date(<ime, TIME_FUZZY_DATE) &&
1760
!make_datetime(ltime.second_part ? DATE_TIME_MICROSECOND : DATE_TIME,
1769
int64_t Item_datetime_typecast::val_int()
1773
if (get_arg0_date(<ime,1))
1779
return TIME_to_uint64_t_datetime(<ime);
1783
bool Item_time_typecast::get_time(DRIZZLE_TIME *ltime)
1785
bool res= get_arg0_time(ltime);
1787
For DRIZZLE_TIMESTAMP_TIME value we can have non-zero day part,
1788
which we should not lose.
1790
if (ltime->time_type == DRIZZLE_TIMESTAMP_DATETIME)
1791
ltime->year= ltime->month= ltime->day= 0;
1792
ltime->time_type= DRIZZLE_TIMESTAMP_TIME;
1797
int64_t Item_time_typecast::val_int()
1800
if (get_time(<ime))
1805
return ltime.hour * 10000L + ltime.minute * 100 + ltime.second;
1808
String *Item_time_typecast::val_str(String *str)
1813
if (!get_arg0_time(<ime) &&
1814
!make_datetime(ltime.second_part ? TIME_MICROSECOND : TIME_ONLY,
1823
bool Item_date_typecast::get_date(DRIZZLE_TIME *ltime, uint32_t fuzzy_date __attribute__((unused)))
1825
bool res= get_arg0_date(ltime, TIME_FUZZY_DATE);
1826
ltime->hour= ltime->minute= ltime->second= ltime->second_part= 0;
1827
ltime->time_type= DRIZZLE_TIMESTAMP_DATE;
1832
bool Item_date_typecast::get_time(DRIZZLE_TIME *ltime)
1834
memset(ltime, 0, sizeof(DRIZZLE_TIME));
1835
return args[0]->null_value;
1839
String *Item_date_typecast::val_str(String *str)
1844
if (!get_arg0_date(<ime, TIME_FUZZY_DATE) &&
1845
!str->alloc(MAX_DATE_STRING_REP_LENGTH))
1847
make_date((DATE_TIME_FORMAT *) 0, <ime, str);
1855
int64_t Item_date_typecast::val_int()
1859
if ((null_value= args[0]->get_date(<ime, TIME_FUZZY_DATE)))
1861
return (int64_t) (ltime.year * 10000L + ltime.month * 100 + ltime.day);
1865
MAKEDATE(a,b) is a date function that creates a date value
1866
from a year and day value.
1869
As arguments are integers, we can't know if the year is a 2 digit or 4 digit year.
1870
In this case we treat all years < 100 as 2 digit years. Ie, this is not safe
1871
for dates between 0000-01-01 and 0099-12-31
1874
String *Item_func_makedate::val_str(String *str)
1877
DRIZZLE_TIME l_time;
1878
long daynr= (long) args[1]->val_int();
1879
long year= (long) args[0]->val_int();
1882
if (args[0]->null_value || args[1]->null_value ||
1883
year < 0 || daynr <= 0)
1887
year= year_2000_handling(year);
1889
days= calc_daynr(year,1,1) + daynr - 1;
1890
/* Day number from year 0 to 9999-12-31 */
1891
if (days >= 0 && days <= MAX_DAY_NUMBER)
1894
get_date_from_daynr(days,&l_time.year,&l_time.month,&l_time.day);
1895
if (str->alloc(MAX_DATE_STRING_REP_LENGTH))
1897
make_date((DATE_TIME_FORMAT *) 0, &l_time, str);
1908
MAKEDATE(a,b) is a date function that creates a date value
1909
from a year and day value.
1912
As arguments are integers, we can't know if the year is a 2 digit or 4 digit year.
1913
In this case we treat all years < 100 as 2 digit years. Ie, this is not safe
1914
for dates between 0000-01-01 and 0099-12-31
1917
int64_t Item_func_makedate::val_int()
1920
DRIZZLE_TIME l_time;
1921
long daynr= (long) args[1]->val_int();
1922
long year= (long) args[0]->val_int();
1925
if (args[0]->null_value || args[1]->null_value ||
1926
year < 0 || daynr <= 0)
1930
year= year_2000_handling(year);
1932
days= calc_daynr(year,1,1) + daynr - 1;
1933
/* Day number from year 0 to 9999-12-31 */
1934
if (days >= 0 && days < MAX_DAY_NUMBER)
1937
get_date_from_daynr(days,&l_time.year,&l_time.month,&l_time.day);
1938
return (int64_t) (l_time.year * 10000L + l_time.month * 100 + l_time.day);
1947
void Item_func_add_time::fix_length_and_dec()
1949
enum_field_types arg0_field_type;
1951
max_length=MAX_DATETIME_FULL_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
1955
The field type for the result of an Item_func_add_time function is defined
1958
- If first arg is a DRIZZLE_TYPE_DATETIME or DRIZZLE_TYPE_TIMESTAMP
1959
result is DRIZZLE_TYPE_DATETIME
1960
- If first arg is a DRIZZLE_TYPE_TIME result is DRIZZLE_TYPE_TIME
1961
- Otherwise the result is DRIZZLE_TYPE_VARCHAR
1964
cached_field_type= DRIZZLE_TYPE_VARCHAR;
1965
arg0_field_type= args[0]->field_type();
1966
if (arg0_field_type == DRIZZLE_TYPE_NEWDATE ||
1967
arg0_field_type == DRIZZLE_TYPE_DATETIME ||
1968
arg0_field_type == DRIZZLE_TYPE_TIMESTAMP)
1969
cached_field_type= DRIZZLE_TYPE_DATETIME;
1970
else if (arg0_field_type == DRIZZLE_TYPE_TIME)
1971
cached_field_type= DRIZZLE_TYPE_TIME;
1975
ADDTIME(t,a) and SUBTIME(t,a) are time functions that calculate a
1978
t: time_or_datetime_expression
1981
Result: Time value or datetime value
1984
String *Item_func_add_time::val_str(String *str)
1987
DRIZZLE_TIME l_time1, l_time2, l_time3;
1989
long days, microseconds;
1994
if (is_date) // TIMESTAMP function
1996
if (get_arg0_date(&l_time1, TIME_FUZZY_DATE) ||
1997
args[1]->get_time(&l_time2) ||
1998
l_time1.time_type == DRIZZLE_TIMESTAMP_TIME ||
1999
l_time2.time_type != DRIZZLE_TIMESTAMP_TIME)
2002
else // ADDTIME function
2004
if (args[0]->get_time(&l_time1) ||
2005
args[1]->get_time(&l_time2) ||
2006
l_time2.time_type == DRIZZLE_TIMESTAMP_DATETIME)
2008
is_time= (l_time1.time_type == DRIZZLE_TIMESTAMP_TIME);
2010
if (l_time1.neg != l_time2.neg)
2013
memset(&l_time3, 0, sizeof(l_time3));
2015
l_time3.neg= calc_time_diff(&l_time1, &l_time2, -l_sign,
2016
&seconds, µseconds);
2019
If first argument was negative and diff between arguments
2020
is non-zero we need to swap sign to get proper result.
2022
if (l_time1.neg && (seconds || microseconds))
2023
l_time3.neg= 1-l_time3.neg; // Swap sign of result
2025
if (!is_time && l_time3.neg)
2028
days= (long)(seconds/86400L);
2030
calc_time_from_sec(&l_time3, (long)(seconds%86400L), microseconds);
2034
get_date_from_daynr(days,&l_time3.year,&l_time3.month,&l_time3.day);
2036
!make_datetime(l_time1.second_part || l_time2.second_part ?
2037
DATE_TIME_MICROSECOND : DATE_TIME,
2043
l_time3.hour+= days*24;
2044
if (!make_datetime_with_warn(l_time1.second_part || l_time2.second_part ?
2045
TIME_MICROSECOND : TIME_ONLY,
2055
void Item_func_add_time::print(String *str, enum_query_type query_type)
2060
str->append(STRING_WITH_LEN("timestamp("));
2065
str->append(STRING_WITH_LEN("addtime("));
2067
str->append(STRING_WITH_LEN("subtime("));
2069
args[0]->print(str, query_type);
2071
args[1]->print(str, query_type);
2077
TIMEDIFF(t,s) is a time function that calculates the
2078
time value between a start and end time.
2080
t and s: time_or_datetime_expression
2084
String *Item_func_timediff::val_str(String *str)
2090
DRIZZLE_TIME l_time1 ,l_time2, l_time3;
2093
if (args[0]->get_time(&l_time1) ||
2094
args[1]->get_time(&l_time2) ||
2095
l_time1.time_type != l_time2.time_type)
2098
if (l_time1.neg != l_time2.neg)
2101
memset(&l_time3, 0, sizeof(l_time3));
2103
l_time3.neg= calc_time_diff(&l_time1, &l_time2, l_sign,
2104
&seconds, µseconds);
2107
For DRIZZLE_TIMESTAMP_TIME only:
2108
If first argument was negative and diff between arguments
2109
is non-zero we need to swap sign to get proper result.
2111
if (l_time1.neg && (seconds || microseconds))
2112
l_time3.neg= 1-l_time3.neg; // Swap sign of result
2114
calc_time_from_sec(&l_time3, (long) seconds, microseconds);
2116
if (!make_datetime_with_warn(l_time1.second_part || l_time2.second_part ?
2117
TIME_MICROSECOND : TIME_ONLY,
2127
MAKETIME(h,m,s) is a time function that calculates a time value
2128
from the total number of hours, minutes, and seconds.
2132
String *Item_func_maketime::val_str(String *str)
2138
int64_t hour= args[0]->val_int();
2139
int64_t minute= args[1]->val_int();
2140
int64_t second= args[2]->val_int();
2142
if ((null_value=(args[0]->null_value ||
2143
args[1]->null_value ||
2144
args[2]->null_value ||
2145
minute < 0 || minute > 59 ||
2146
second < 0 || second > 59 ||
2147
str->alloc(MAX_DATE_STRING_REP_LENGTH))))
2150
memset(<ime, 0, sizeof(ltime));
2153
/* Check for integer overflows */
2157
if (-hour > UINT_MAX || hour > UINT_MAX)
2162
ltime.hour= (uint) ((hour < 0 ? -hour : hour));
2163
ltime.minute= (uint) minute;
2164
ltime.second= (uint) second;
2168
ltime.hour= TIME_MAX_HOUR;
2169
ltime.minute= TIME_MAX_MINUTE;
2170
ltime.second= TIME_MAX_SECOND;
2172
char *ptr= int64_t10_to_str(hour, buf, args[0]->unsigned_flag ? 10 : -10);
2173
int len = (int)(ptr - buf) +
2174
sprintf(ptr, ":%02u:%02u", (uint)minute, (uint)second);
2175
make_truncated_value_warning(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
2176
buf, len, DRIZZLE_TIMESTAMP_TIME,
2180
if (make_time_with_warn((DATE_TIME_FORMAT *) 0, <ime, str))
2190
MICROSECOND(a) is a function ( extraction) that extracts the microseconds
2193
a: Datetime or time value
2197
int64_t Item_func_microsecond::val_int()
2201
if (!get_arg0_time(<ime))
2202
return ltime.second_part;
2207
int64_t Item_func_timestamp_diff::val_int()
2209
DRIZZLE_TIME ltime1, ltime2;
2216
if (args[0]->get_date(<ime1, TIME_NO_ZERO_DATE) ||
2217
args[1]->get_date(<ime2, TIME_NO_ZERO_DATE))
2220
if (calc_time_diff(<ime2,<ime1, 1,
2221
&seconds, µseconds))
2224
if (int_type == INTERVAL_YEAR ||
2225
int_type == INTERVAL_QUARTER ||
2226
int_type == INTERVAL_MONTH)
2228
uint32_t year_beg, year_end, month_beg, month_end, day_beg, day_end;
2230
uint32_t second_beg, second_end, microsecond_beg, microsecond_end;
2234
year_beg= ltime2.year;
2235
year_end= ltime1.year;
2236
month_beg= ltime2.month;
2237
month_end= ltime1.month;
2238
day_beg= ltime2.day;
2239
day_end= ltime1.day;
2240
second_beg= ltime2.hour * 3600 + ltime2.minute * 60 + ltime2.second;
2241
second_end= ltime1.hour * 3600 + ltime1.minute * 60 + ltime1.second;
2242
microsecond_beg= ltime2.second_part;
2243
microsecond_end= ltime1.second_part;
2247
year_beg= ltime1.year;
2248
year_end= ltime2.year;
2249
month_beg= ltime1.month;
2250
month_end= ltime2.month;
2251
day_beg= ltime1.day;
2252
day_end= ltime2.day;
2253
second_beg= ltime1.hour * 3600 + ltime1.minute * 60 + ltime1.second;
2254
second_end= ltime2.hour * 3600 + ltime2.minute * 60 + ltime2.second;
2255
microsecond_beg= ltime1.second_part;
2256
microsecond_end= ltime2.second_part;
2260
years= year_end - year_beg;
2261
if (month_end < month_beg || (month_end == month_beg && day_end < day_beg))
2266
if (month_end < month_beg || (month_end == month_beg && day_end < day_beg))
2267
months+= 12 - (month_beg - month_end);
2269
months+= (month_end - month_beg);
2271
if (day_end < day_beg)
2273
else if ((day_end == day_beg) &&
2274
((second_end < second_beg) ||
2275
(second_end == second_beg && microsecond_end < microsecond_beg)))
2281
return months/12*neg;
2282
case INTERVAL_QUARTER:
2283
return months/3*neg;
2284
case INTERVAL_MONTH:
2287
return seconds/86400L/7L*neg;
2289
return seconds/86400L*neg;
2291
return seconds/3600L*neg;
2292
case INTERVAL_MINUTE:
2293
return seconds/60L*neg;
2294
case INTERVAL_SECOND:
2296
case INTERVAL_MICROSECOND:
2298
In MySQL difference between any two valid datetime values
2299
in microseconds fits into int64_t.
2301
return (seconds*1000000L+microseconds)*neg;
2312
void Item_func_timestamp_diff::print(String *str, enum_query_type query_type)
2314
str->append(func_name());
2319
str->append(STRING_WITH_LEN("YEAR"));
2321
case INTERVAL_QUARTER:
2322
str->append(STRING_WITH_LEN("QUARTER"));
2324
case INTERVAL_MONTH:
2325
str->append(STRING_WITH_LEN("MONTH"));
2328
str->append(STRING_WITH_LEN("WEEK"));
2331
str->append(STRING_WITH_LEN("DAY"));
2334
str->append(STRING_WITH_LEN("HOUR"));
2336
case INTERVAL_MINUTE:
2337
str->append(STRING_WITH_LEN("MINUTE"));
2339
case INTERVAL_SECOND:
2340
str->append(STRING_WITH_LEN("SECOND"));
2342
case INTERVAL_MICROSECOND:
2343
str->append(STRING_WITH_LEN("SECOND_FRAC"));
2349
for (uint32_t i=0 ; i < 2 ; i++)
2352
args[i]->print(str, query_type);
2358
String *Item_func_get_format::val_str(String *str)
2361
const char *format_name;
2362
KNOWN_DATE_TIME_FORMAT *format;
2363
String *val= args[0]->val_str(str);
2366
if ((null_value= args[0]->null_value))
2369
val_len= val->length();
2370
for (format= &known_date_time_formats[0];
2371
(format_name= format->format_name);
2374
uint32_t format_name_len;
2375
format_name_len= strlen(format_name);
2376
if (val_len == format_name_len &&
2377
!my_strnncoll(&my_charset_utf8_general_ci,
2378
(const unsigned char *) val->ptr(), val_len,
2379
(const unsigned char *) format_name, val_len))
2381
const char *format_str= get_date_time_format_str(format, type);
2382
str->set(format_str, strlen(format_str), &my_charset_bin);
2392
void Item_func_get_format::print(String *str, enum_query_type query_type)
2394
str->append(func_name());
2398
case DRIZZLE_TIMESTAMP_DATE:
2399
str->append(STRING_WITH_LEN("DATE, "));
2401
case DRIZZLE_TIMESTAMP_DATETIME:
2402
str->append(STRING_WITH_LEN("DATETIME, "));
2404
case DRIZZLE_TIMESTAMP_TIME:
2405
str->append(STRING_WITH_LEN("TIME, "));
2410
args[0]->print(str, query_type);
2416
Get type of datetime value (DATE/TIME/...) which will be produced
2417
according to format string.
2419
@param format format string
2420
@param length length of format string
2423
We don't process day format's characters('D', 'd', 'e') because day
2424
may be a member of all date/time types.
2427
Format specifiers supported by this function should be in sync with
2428
specifiers supported by extract_date_time() function.
2431
One of date_time_format_types values:
2432
- DATE_TIME_MICROSECOND
2439
static date_time_format_types
2440
get_date_time_result_type(const char *format, uint32_t length)
2442
const char *time_part_frms= "HISThiklrs";
2443
const char *date_part_frms= "MVUXYWabcjmvuxyw";
2444
bool date_part_used= 0, time_part_used= 0, frac_second_used= 0;
2446
const char *val= format;
2447
const char *end= format + length;
2449
for (; val != end && val != end; val++)
2451
if (*val == '%' && val+1 != end)
2455
frac_second_used= time_part_used= 1;
2456
else if (!time_part_used && strchr(time_part_frms, *val))
2458
else if (!date_part_used && strchr(date_part_frms, *val))
2460
if (date_part_used && frac_second_used)
2463
frac_second_used implies time_part_used, and thus we already
2464
have all types of date-time components and can end our search.
2466
return DATE_TIME_MICROSECOND;
2471
/* We don't have all three types of date-time components */
2472
if (frac_second_used)
2473
return TIME_MICROSECOND;
2484
void Item_func_str_to_date::fix_length_and_dec()
2488
cached_field_type= DRIZZLE_TYPE_DATETIME;
2489
max_length= MAX_DATETIME_FULL_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
2490
cached_timestamp_type= DRIZZLE_TIMESTAMP_NONE;
2491
if ((const_item= args[1]->const_item()))
2493
char format_buff[64];
2494
String format_str(format_buff, sizeof(format_buff), &my_charset_bin);
2495
String *format= args[1]->val_str(&format_str);
2496
if (!args[1]->null_value)
2498
cached_format_type= get_date_time_result_type(format->ptr(),
2500
switch (cached_format_type) {
2502
cached_timestamp_type= DRIZZLE_TIMESTAMP_DATE;
2503
cached_field_type= DRIZZLE_TYPE_NEWDATE;
2504
max_length= MAX_DATE_WIDTH * MY_CHARSET_BIN_MB_MAXLEN;
2507
case TIME_MICROSECOND:
2508
cached_timestamp_type= DRIZZLE_TIMESTAMP_TIME;
2509
cached_field_type= DRIZZLE_TYPE_TIME;
2510
max_length= MAX_TIME_WIDTH * MY_CHARSET_BIN_MB_MAXLEN;
2513
cached_timestamp_type= DRIZZLE_TIMESTAMP_DATETIME;
2514
cached_field_type= DRIZZLE_TYPE_DATETIME;
2522
bool Item_func_str_to_date::get_date(DRIZZLE_TIME *ltime, uint32_t fuzzy_date)
2524
DATE_TIME_FORMAT date_time_format;
2525
char val_buff[64], format_buff[64];
2526
String val_string(val_buff, sizeof(val_buff), &my_charset_bin), *val;
2527
String format_str(format_buff, sizeof(format_buff), &my_charset_bin), *format;
2529
val= args[0]->val_str(&val_string);
2530
format= args[1]->val_str(&format_str);
2531
if (args[0]->null_value || args[1]->null_value)
2535
memset(ltime, 0, sizeof(*ltime));
2536
date_time_format.format.str= (char*) format->ptr();
2537
date_time_format.format.length= format->length();
2538
if (extract_date_time(&date_time_format, val->ptr(), val->length(),
2539
ltime, cached_timestamp_type, 0, "datetime") ||
2540
((fuzzy_date & TIME_NO_ZERO_DATE) &&
2541
(ltime->year == 0 || ltime->month == 0 || ltime->day == 0)))
2543
if (cached_timestamp_type == DRIZZLE_TIMESTAMP_TIME && ltime->day)
2546
Day part for time type can be nonzero value and so
2547
we should add hours from day part to hour part to
2548
keep valid time value.
2550
ltime->hour+= ltime->day*24;
2556
return (null_value=1);
2560
String *Item_func_str_to_date::val_str(String *str)
2565
if (Item_func_str_to_date::get_date(<ime, TIME_FUZZY_DATE))
2568
if (!make_datetime((const_item ? cached_format_type :
2569
(ltime.second_part ? DATE_TIME_MICROSECOND : DATE_TIME)),
2576
bool Item_func_last_day::get_date(DRIZZLE_TIME *ltime, uint32_t fuzzy_date)
2578
if (get_arg0_date(ltime, fuzzy_date & ~TIME_FUZZY_DATE) ||
2579
(ltime->month == 0))
2585
uint32_t month_idx= ltime->month-1;
2586
ltime->day= days_in_month[month_idx];
2587
if ( month_idx == 1 && calc_days_in_year(ltime->year) == 366)
2589
ltime->hour= ltime->minute= ltime->second= 0;
2590
ltime->second_part= 0;
2591
ltime->time_type= DRIZZLE_TIMESTAMP_DATE;