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>
34
#include <drizzled/item/timefunc.h>
35
#include <drizzled/sql_locale.h>
36
#include <drizzled/session.h>
39
Date formats corresponding to compound %r and %T conversion specifiers
41
Note: We should init at least first element of "positions" array
42
(first member) or hpux11 compiler will die horribly.
44
static DATE_TIME_FORMAT time_ampm_format= {{0}, '\0', 0,
45
{(char *)"%I:%i:%S %p", 11}};
46
static DATE_TIME_FORMAT time_24hrs_format= {{0}, '\0', 0,
47
{(char *)"%H:%i:%S", 8}};
50
Extract datetime value to DRIZZLE_TIME struct from string value
51
according to format string.
53
@param format date/time format specification
54
@param val String to decode
55
@param length Length of string
56
@param l_time Store result here
57
@param cached_timestamp_type It uses to get an appropriate warning
58
in the case when the value is truncated.
59
@param sub_pattern_end if non-zero then we are parsing string which
60
should correspond compound specifier (like %T or
61
%r) and this parameter is pointer to place where
62
pointer to end of string matching this specifier
66
Possibility to parse strings matching to patterns equivalent to compound
67
specifiers is mainly intended for use from inside of this function in
68
order to understand %T and %r conversion specifiers, so number of
69
conversion specifiers that can be used in such sub-patterns is limited.
70
Also most of checks are skipped in this case.
73
If one adds new format specifiers to this function he should also
74
consider adding them to get_date_time_result_type() function.
82
static bool extract_date_time(DATE_TIME_FORMAT *format,
83
const char *val, uint32_t length, DRIZZLE_TIME *l_time,
84
enum enum_drizzle_timestamp_type cached_timestamp_type,
85
const char **sub_pattern_end,
86
const char *date_time_type)
88
int weekday= 0, yearday= 0, daypart= 0;
91
int strict_week_number_year= -1;
94
bool sunday_first_n_first_week_non_iso= false;
95
bool strict_week_number= false;
96
bool strict_week_number_year_type= false;
97
const char *val_begin= val;
98
const char *val_end= val + length;
99
const char *ptr= format->format.str;
100
const char *end= ptr + format->format.length;
101
const CHARSET_INFO * const cs= &my_charset_bin;
103
if (!sub_pattern_end)
104
memset(l_time, 0, sizeof(*l_time));
106
for (; ptr != end && val != val_end; ptr++)
108
/* Skip pre-space between each argument */
109
while (val != val_end && my_isspace(cs, *val))
112
if (*ptr == '%' && ptr+1 != end)
119
val_len= (uint) (val_end - val);
123
tmp= (char*) val + cmin(4, val_len);
124
l_time->year= (int) my_strtoll10(val, &tmp, &error);
125
if ((int) (tmp-val) <= 2)
126
l_time->year= year_2000_handling(l_time->year);
130
tmp= (char*) val + cmin(2, val_len);
131
l_time->year= (int) my_strtoll10(val, &tmp, &error);
133
l_time->year= year_2000_handling(l_time->year);
139
tmp= (char*) val + cmin(2, val_len);
140
l_time->month= (int) my_strtoll10(val, &tmp, &error);
144
if ((l_time->month= check_word(my_locale_en_US.month_names,
145
val, val_end, &val)) <= 0)
149
if ((l_time->month= check_word(my_locale_en_US.ab_month_names,
150
val, val_end, &val)) <= 0)
156
tmp= (char*) val + cmin(2, val_len);
157
l_time->day= (int) my_strtoll10(val, &tmp, &error);
161
tmp= (char*) val + cmin(2, val_len);
162
l_time->day= (int) my_strtoll10(val, &tmp, &error);
163
/* Skip 'st, 'nd, 'th .. */
164
val= tmp + cmin((int) (val_end-tmp), 2);
175
tmp= (char*) val + cmin(2, val_len);
176
l_time->hour= (int) my_strtoll10(val, &tmp, &error);
182
tmp= (char*) val + cmin(2, val_len);
183
l_time->minute= (int) my_strtoll10(val, &tmp, &error);
190
tmp= (char*) val + cmin(2, val_len);
191
l_time->second= (int) my_strtoll10(val, &tmp, &error);
197
tmp= (char*) val_end;
199
tmp= (char*) val + 6;
200
l_time->second_part= (int) my_strtoll10(val, &tmp, &error);
201
frac_part= 6 - (tmp - val);
203
l_time->second_part*= (ulong) log_10_int[frac_part];
209
if (val_len < 2 || ! usa_time)
211
if (!my_strnncoll(&my_charset_utf8_general_ci,
212
(const unsigned char *) val, 2,
213
(const unsigned char *) "PM", 2))
215
else if (my_strnncoll(&my_charset_utf8_general_ci,
216
(const unsigned char *) val, 2,
217
(const unsigned char *) "AM", 2))
224
if ((weekday= check_word(my_locale_en_US.day_names, val, val_end, &val)) <= 0)
228
if ((weekday= check_word(my_locale_en_US.ab_day_names, val, val_end, &val)) <= 0)
232
tmp= (char*) val + 1;
233
if ((weekday= (int) my_strtoll10(val, &tmp, &error)) < 0 ||
236
/* We should use the same 1 - 7 scale for %w as for %W */
242
tmp= (char*) val + cmin(val_len, 3);
243
yearday= (int) my_strtoll10(val, &tmp, &error);
252
sunday_first_n_first_week_non_iso= (*ptr=='U' || *ptr== 'V');
253
strict_week_number= (*ptr=='V' || *ptr=='v');
254
tmp= (char*) val + cmin(val_len, 2);
255
if ((week_number= (int) my_strtoll10(val, &tmp, &error)) < 0 ||
256
(strict_week_number && !week_number) ||
262
/* Year used with 'strict' %V and %v week numbers */
265
strict_week_number_year_type= (*ptr=='X');
266
tmp= (char*) val + cmin(4, val_len);
267
strict_week_number_year= (int) my_strtoll10(val, &tmp, &error);
271
/* Time in AM/PM notation */
274
We can't just set error here, as we don't want to generate two
275
warnings in case of errors
277
if (extract_date_time(&time_ampm_format, val,
278
(uint)(val_end - val), l_time,
279
cached_timestamp_type, &val, "time"))
283
/* Time in 24-hour notation */
285
if (extract_date_time(&time_24hrs_format, val,
286
(uint)(val_end - val), l_time,
287
cached_timestamp_type, &val, "time"))
291
/* Conversion specifiers that match classes of characters */
293
while (my_ispunct(cs, *val) && val != val_end)
297
while (my_isalpha(cs, *val) && val != val_end)
301
while (my_isdigit(cs, *val) && val != val_end)
307
if (error) // Error from my_strtoll10
310
else if (!my_isspace(cs, *ptr))
319
if (l_time->hour > 12 || l_time->hour < 1)
321
l_time->hour= l_time->hour%12+daypart;
325
If we are recursively called for parsing string matching compound
326
specifiers we are already done.
330
*sub_pattern_end= val;
337
days= calc_daynr(l_time->year,1,1) + yearday - 1;
338
if (days <= 0 || days > MAX_DAY_NUMBER)
340
get_date_from_daynr(days,&l_time->year,&l_time->month,&l_time->day);
343
if (week_number >= 0 && weekday)
349
%V,%v require %X,%x resprectively,
350
%U,%u should be used with %Y and not %X or %x
352
if ((strict_week_number &&
353
(strict_week_number_year < 0 || (strict_week_number_year_type != sunday_first_n_first_week_non_iso))) ||
354
(!strict_week_number && strict_week_number_year >= 0))
357
/* Number of days since year 0 till 1st Jan of this year */
358
days= calc_daynr((strict_week_number ? strict_week_number_year :
361
/* Which day of week is 1st Jan of this year */
362
weekday_b= calc_weekday(days, sunday_first_n_first_week_non_iso);
365
Below we are going to sum:
366
1) number of days since year 0 till 1st day of 1st week of this year
367
2) number of days between 1st week and our week
368
3) and position of our day in the week
370
if (sunday_first_n_first_week_non_iso)
372
days+= ((weekday_b == 0) ? 0 : 7) - weekday_b +
373
(week_number - 1) * 7 +
378
days+= ((weekday_b <= 3) ? 0 : 7) - weekday_b +
379
(week_number - 1) * 7 +
383
if (days <= 0 || days > MAX_DAY_NUMBER)
385
get_date_from_daynr(days,&l_time->year,&l_time->month,&l_time->day);
388
if (l_time->month > 12 || l_time->day > 31 || l_time->hour > 23 ||
389
l_time->minute > 59 || l_time->second > 59)
396
if (!my_isspace(&my_charset_utf8_general_ci,*val))
398
make_truncated_value_warning(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
400
cached_timestamp_type, NULL);
403
} while (++val != val_end);
410
strmake(buff, val_begin, cmin(length, (uint)sizeof(buff)-1));
411
push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
412
ER_WRONG_VALUE_FOR_TYPE, ER(ER_WRONG_VALUE_FOR_TYPE),
413
date_time_type, buff, "str_to_date");
420
Create a formated date/time value in a string.
423
bool make_date_time(DATE_TIME_FORMAT *format, DRIZZLE_TIME *l_time,
424
enum enum_drizzle_timestamp_type type, String *str)
430
const char *ptr, *end;
431
Session *session= current_session;
432
MY_LOCALE *locale= session->variables.lc_time_names;
439
end= (ptr= format->format.str) + format->format.length;
440
for (; ptr != end ; ptr++)
442
if (*ptr != '%' || ptr+1 == end)
450
str->append(locale->month_names->type_names[l_time->month-1],
451
strlen(locale->month_names->type_names[l_time->month-1]),
452
system_charset_info);
457
str->append(locale->ab_month_names->type_names[l_time->month-1],
458
strlen(locale->ab_month_names->type_names[l_time->month-1]),
459
system_charset_info);
462
if (type == DRIZZLE_TIMESTAMP_TIME)
464
weekday= calc_weekday(calc_daynr(l_time->year,l_time->month,
466
str->append(locale->day_names->type_names[weekday],
467
strlen(locale->day_names->type_names[weekday]),
468
system_charset_info);
471
if (type == DRIZZLE_TIMESTAMP_TIME)
473
weekday=calc_weekday(calc_daynr(l_time->year,l_time->month,
475
str->append(locale->ab_day_names->type_names[weekday],
476
strlen(locale->ab_day_names->type_names[weekday]),
477
system_charset_info);
480
if (type == DRIZZLE_TIMESTAMP_TIME)
482
length= int10_to_str(l_time->day, intbuff, 10) - intbuff;
483
str->append_with_prefill(intbuff, length, 1, '0');
484
if (l_time->day >= 10 && l_time->day <= 19)
485
str->append(STRING_WITH_LEN("th"));
488
switch (l_time->day %10) {
490
str->append(STRING_WITH_LEN("st"));
493
str->append(STRING_WITH_LEN("nd"));
496
str->append(STRING_WITH_LEN("rd"));
499
str->append(STRING_WITH_LEN("th"));
505
length= int10_to_str(l_time->year, intbuff, 10) - intbuff;
506
str->append_with_prefill(intbuff, length, 4, '0');
509
length= int10_to_str(l_time->year%100, intbuff, 10) - intbuff;
510
str->append_with_prefill(intbuff, length, 2, '0');
513
length= int10_to_str(l_time->month, intbuff, 10) - intbuff;
514
str->append_with_prefill(intbuff, length, 2, '0');
517
length= int10_to_str(l_time->month, intbuff, 10) - intbuff;
518
str->append_with_prefill(intbuff, length, 1, '0');
521
length= int10_to_str(l_time->day, intbuff, 10) - intbuff;
522
str->append_with_prefill(intbuff, length, 2, '0');
525
length= int10_to_str(l_time->day, intbuff, 10) - intbuff;
526
str->append_with_prefill(intbuff, length, 1, '0');
529
length= int10_to_str(l_time->second_part, intbuff, 10) - intbuff;
530
str->append_with_prefill(intbuff, length, 6, '0');
533
length= int10_to_str(l_time->hour, intbuff, 10) - intbuff;
534
str->append_with_prefill(intbuff, length, 2, '0');
538
hours_i= (l_time->hour%24 + 11)%12+1;
539
length= int10_to_str(hours_i, intbuff, 10) - intbuff;
540
str->append_with_prefill(intbuff, length, 2, '0');
542
case 'i': /* minutes */
543
length= int10_to_str(l_time->minute, intbuff, 10) - intbuff;
544
str->append_with_prefill(intbuff, length, 2, '0');
547
if (type == DRIZZLE_TIMESTAMP_TIME)
549
length= int10_to_str(calc_daynr(l_time->year,l_time->month,
551
calc_daynr(l_time->year,1,1) + 1, intbuff, 10) - intbuff;
552
str->append_with_prefill(intbuff, length, 3, '0');
555
length= int10_to_str(l_time->hour, intbuff, 10) - intbuff;
556
str->append_with_prefill(intbuff, length, 1, '0');
559
hours_i= (l_time->hour%24 + 11)%12+1;
560
length= int10_to_str(hours_i, intbuff, 10) - intbuff;
561
str->append_with_prefill(intbuff, length, 1, '0');
564
hours_i= l_time->hour%24;
565
str->append(hours_i < 12 ? "AM" : "PM",2);
568
length= sprintf(intbuff,
569
((l_time->hour % 24) < 12) ?
570
"%02d:%02d:%02d AM" : "%02d:%02d:%02d PM",
571
(l_time->hour+11)%12+1,
574
str->append(intbuff, length);
578
length= int10_to_str(l_time->second, intbuff, 10) - intbuff;
579
str->append_with_prefill(intbuff, length, 2, '0');
582
length= sprintf(intbuff,
587
str->append(intbuff, length);
593
if (type == DRIZZLE_TIMESTAMP_TIME)
595
length= int10_to_str(calc_week(l_time,
597
WEEK_FIRST_WEEKDAY : WEEK_MONDAY_FIRST,
599
intbuff, 10) - intbuff;
600
str->append_with_prefill(intbuff, length, 2, '0');
607
if (type == DRIZZLE_TIMESTAMP_TIME)
609
length= int10_to_str(calc_week(l_time,
611
(WEEK_YEAR | WEEK_FIRST_WEEKDAY) :
612
(WEEK_YEAR | WEEK_MONDAY_FIRST)),
614
intbuff, 10) - intbuff;
615
str->append_with_prefill(intbuff, length, 2, '0');
622
if (type == DRIZZLE_TIMESTAMP_TIME)
624
(void) calc_week(l_time,
626
WEEK_YEAR | WEEK_FIRST_WEEKDAY :
627
WEEK_YEAR | WEEK_MONDAY_FIRST),
629
length= int10_to_str(year, intbuff, 10) - intbuff;
630
str->append_with_prefill(intbuff, length, 4, '0');
634
if (type == DRIZZLE_TIMESTAMP_TIME)
636
weekday=calc_weekday(calc_daynr(l_time->year,l_time->month,
638
length= int10_to_str(weekday, intbuff, 10) - intbuff;
639
str->append_with_prefill(intbuff, length, 1, '0');
654
Get a array of positive numbers from a string object.
655
Each number is separated by 1 non digit character
656
Return error if there is too many numbers.
657
If there is too few numbers, assume that the numbers are left out
658
from the high end. This allows one to give:
659
DAY_TO_SECOND as "D MM:HH:SS", "MM:HH:SS" "HH:SS" or as seconds.
661
@param length: length of str
662
@param cs: charset of str
663
@param values: array of results
664
@param count: count of elements in result array
665
@param transform_msec: if value is true we suppose
666
that the last part of string value is microseconds
667
and we should transform value to six digit value.
668
For example, '1.1' -> '1.100000'
671
static bool get_interval_info(const char *str,uint32_t length, const CHARSET_INFO * const cs,
672
uint32_t count, uint64_t *values,
675
const char *end=str+length;
677
while (str != end && !my_isdigit(cs,*str))
680
for (i=0 ; i < count ; i++)
683
const char *start= str;
684
for (value=0; str != end && my_isdigit(cs,*str) ; str++)
685
value= value * 10L + (int64_t) (*str - '0');
686
if (transform_msec && i == count - 1) // microseconds always last
688
long msec_length= 6 - (str - start);
690
value*= (long) log_10_int[msec_length];
693
while (str != end && !my_isdigit(cs,*str))
695
if (str == end && i != count-1)
698
/* Change values[0...i-1] -> values[0...count-1] */
699
bmove_upp((unsigned char*) (values+count), (unsigned char*) (values+i),
701
memset(values, 0, sizeof(*values)*(count-i));
709
Convert a string to a interval value.
711
To make code easy, allow interval objects without separators.
714
bool get_interval_value(Item *args,interval_type int_type,
715
String *str_value, INTERVAL *interval)
719
const char *str= NULL;
721
const CHARSET_INFO * const cs= str_value->charset();
723
memset(interval, 0, sizeof(*interval));
724
if ((int) int_type <= INTERVAL_MICROSECOND)
726
value= args->val_int();
727
if (args->null_value)
738
if (!(res=args->val_str(str_value)))
741
/* record negative intervalls in interval->neg */
743
const char *end=str+res->length();
744
while (str != end && my_isspace(cs,*str))
746
if (str != end && *str == '-')
751
length= (size_t) (end-str); // Set up pointers to new str
756
interval->year= (ulong) value;
758
case INTERVAL_QUARTER:
759
interval->month= (ulong)(value*3);
762
interval->month= (ulong) value;
765
interval->day= (ulong)(value*7);
768
interval->day= (ulong) value;
771
interval->hour= (ulong) value;
773
case INTERVAL_MICROSECOND:
774
interval->second_part=value;
776
case INTERVAL_MINUTE:
777
interval->minute=value;
779
case INTERVAL_SECOND:
780
interval->second=value;
782
case INTERVAL_YEAR_MONTH: // Allow YEAR-MONTH YYYYYMM
783
if (get_interval_info(str,length,cs,2,array,0))
785
interval->year= (ulong) array[0];
786
interval->month= (ulong) array[1];
788
case INTERVAL_DAY_HOUR:
789
if (get_interval_info(str,length,cs,2,array,0))
791
interval->day= (ulong) array[0];
792
interval->hour= (ulong) array[1];
794
case INTERVAL_DAY_MICROSECOND:
795
if (get_interval_info(str,length,cs,5,array,1))
797
interval->day= (ulong) array[0];
798
interval->hour= (ulong) array[1];
799
interval->minute= array[2];
800
interval->second= array[3];
801
interval->second_part= array[4];
803
case INTERVAL_DAY_MINUTE:
804
if (get_interval_info(str,length,cs,3,array,0))
806
interval->day= (ulong) array[0];
807
interval->hour= (ulong) array[1];
808
interval->minute= array[2];
810
case INTERVAL_DAY_SECOND:
811
if (get_interval_info(str,length,cs,4,array,0))
813
interval->day= (ulong) array[0];
814
interval->hour= (ulong) array[1];
815
interval->minute= array[2];
816
interval->second= array[3];
818
case INTERVAL_HOUR_MICROSECOND:
819
if (get_interval_info(str,length,cs,4,array,1))
821
interval->hour= (ulong) array[0];
822
interval->minute= array[1];
823
interval->second= array[2];
824
interval->second_part= array[3];
826
case INTERVAL_HOUR_MINUTE:
827
if (get_interval_info(str,length,cs,2,array,0))
829
interval->hour= (ulong) array[0];
830
interval->minute= array[1];
832
case INTERVAL_HOUR_SECOND:
833
if (get_interval_info(str,length,cs,3,array,0))
835
interval->hour= (ulong) array[0];
836
interval->minute= array[1];
837
interval->second= array[2];
839
case INTERVAL_MINUTE_MICROSECOND:
840
if (get_interval_info(str,length,cs,3,array,1))
842
interval->minute= array[0];
843
interval->second= array[1];
844
interval->second_part= array[2];
846
case INTERVAL_MINUTE_SECOND:
847
if (get_interval_info(str,length,cs,2,array,0))
849
interval->minute= array[0];
850
interval->second= array[1];
852
case INTERVAL_SECOND_MICROSECOND:
853
if (get_interval_info(str,length,cs,2,array,1))
855
interval->second= array[0];
856
interval->second_part= array[1];
858
case INTERVAL_LAST: /* purecov: begin deadcode */
860
break; /* purecov: end */
866
void Item_date_add_interval::fix_length_and_dec()
868
enum_field_types arg0_field_type;
870
collation.set(&my_charset_bin);
872
max_length=MAX_DATETIME_FULL_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
873
value.alloc(max_length);
876
The field type for the result of an Item_date function is defined as
879
- If first arg is a DRIZZLE_TYPE_DATETIME result is DRIZZLE_TYPE_DATETIME
880
- If first arg is a DRIZZLE_TYPE_DATE and the interval type uses hours,
881
minutes or seconds then type is DRIZZLE_TYPE_DATETIME.
882
- Otherwise the result is DRIZZLE_TYPE_VARCHAR
883
(This is because you can't know if the string contains a DATE, DRIZZLE_TIME or
886
cached_field_type= DRIZZLE_TYPE_VARCHAR;
887
arg0_field_type= args[0]->field_type();
888
if (arg0_field_type == DRIZZLE_TYPE_DATETIME ||
889
arg0_field_type == DRIZZLE_TYPE_TIMESTAMP)
890
cached_field_type= DRIZZLE_TYPE_DATETIME;
891
else if (arg0_field_type == DRIZZLE_TYPE_DATE)
893
if (int_type <= INTERVAL_DAY || int_type == INTERVAL_YEAR_MONTH)
894
cached_field_type= arg0_field_type;
896
cached_field_type= DRIZZLE_TYPE_DATETIME;
901
/* Here arg[1] is a Item_interval object */
903
bool Item_date_add_interval::get_date(DRIZZLE_TIME *ltime, uint32_t fuzzy_date __attribute__((unused)))
907
if (args[0]->get_date(ltime, TIME_NO_ZERO_DATE) ||
908
get_interval_value(args[1], int_type, &value, &interval))
909
return (null_value=1);
911
if (date_sub_interval)
912
interval.neg = !interval.neg;
914
if ((null_value= date_add_interval(ltime, int_type, interval)))
920
String *Item_date_add_interval::val_str(String *str)
924
enum date_time_format_types format;
926
if (Item_date_add_interval::get_date(<ime, TIME_NO_ZERO_DATE))
929
if (ltime.time_type == DRIZZLE_TIMESTAMP_DATE)
931
else if (ltime.second_part)
932
format= DATE_TIME_MICROSECOND;
936
if (!make_datetime(format, <ime, str))
944
int64_t Item_date_add_interval::val_int()
949
if (Item_date_add_interval::get_date(<ime, TIME_NO_ZERO_DATE))
951
date = (ltime.year*100L + ltime.month)*100L + ltime.day;
952
return ltime.time_type == DRIZZLE_TIMESTAMP_DATE ? date :
953
((date*100L + ltime.hour)*100L+ ltime.minute)*100L + ltime.second;
958
bool Item_date_add_interval::eq(const Item *item, bool binary_cmp) const
960
Item_date_add_interval *other= (Item_date_add_interval*) item;
961
if (!Item_func::eq(item, binary_cmp))
963
return ((int_type == other->int_type) &&
964
(date_sub_interval == other->date_sub_interval));
968
'interval_names' reflects the order of the enumeration interval_type.
972
static const char *interval_names[]=
974
"year", "quarter", "month", "week", "day",
975
"hour", "minute", "second", "microsecond",
976
"year_month", "day_hour", "day_minute",
977
"day_second", "hour_minute", "hour_second",
978
"minute_second", "day_microsecond",
979
"hour_microsecond", "minute_microsecond",
983
void Item_date_add_interval::print(String *str, enum_query_type query_type)
986
args[0]->print(str, query_type);
987
str->append(date_sub_interval?" - interval ":" + interval ");
988
args[1]->print(str, query_type);
990
str->append(interval_names[int_type]);
994
void Item_extract::print(String *str, enum_query_type query_type)
996
str->append(STRING_WITH_LEN("extract("));
997
str->append(interval_names[int_type]);
998
str->append(STRING_WITH_LEN(" from "));
999
args[0]->print(str, query_type);
1003
void Item_extract::fix_length_and_dec()
1005
value.alloc(32); // alloc buffer
1007
maybe_null=1; // If wrong date
1009
case INTERVAL_YEAR: max_length=4; date_value=1; break;
1010
case INTERVAL_YEAR_MONTH: max_length=6; date_value=1; break;
1011
case INTERVAL_QUARTER: max_length=2; date_value=1; break;
1012
case INTERVAL_MONTH: max_length=2; date_value=1; break;
1013
case INTERVAL_WEEK: max_length=2; date_value=1; break;
1014
case INTERVAL_DAY: max_length=2; date_value=1; break;
1015
case INTERVAL_DAY_HOUR: max_length=9; date_value=0; break;
1016
case INTERVAL_DAY_MINUTE: max_length=11; date_value=0; break;
1017
case INTERVAL_DAY_SECOND: max_length=13; date_value=0; break;
1018
case INTERVAL_HOUR: max_length=2; date_value=0; break;
1019
case INTERVAL_HOUR_MINUTE: max_length=4; date_value=0; break;
1020
case INTERVAL_HOUR_SECOND: max_length=6; date_value=0; break;
1021
case INTERVAL_MINUTE: max_length=2; date_value=0; break;
1022
case INTERVAL_MINUTE_SECOND: max_length=4; date_value=0; break;
1023
case INTERVAL_SECOND: max_length=2; date_value=0; break;
1024
case INTERVAL_MICROSECOND: max_length=2; date_value=0; break;
1025
case INTERVAL_DAY_MICROSECOND: max_length=20; date_value=0; break;
1026
case INTERVAL_HOUR_MICROSECOND: max_length=13; date_value=0; break;
1027
case INTERVAL_MINUTE_MICROSECOND: max_length=11; date_value=0; break;
1028
case INTERVAL_SECOND_MICROSECOND: max_length=9; date_value=0; break;
1029
case INTERVAL_LAST: assert(0); break; /* purecov: deadcode */
1034
int64_t Item_extract::val_int()
1043
if (get_arg0_date(<ime, TIME_FUZZY_DATE))
1049
String *res= args[0]->val_str(&value);
1050
if (!res || str_to_time_with_warn(res->ptr(), res->length(), <ime))
1055
neg= ltime.neg ? -1 : 1;
1059
case INTERVAL_YEAR: return ltime.year;
1060
case INTERVAL_YEAR_MONTH: return ltime.year*100L+ltime.month;
1061
case INTERVAL_QUARTER: return (ltime.month+2)/3;
1062
case INTERVAL_MONTH: return ltime.month;
1065
week_format= current_session->variables.default_week_format;
1066
return calc_week(<ime, week_mode(week_format), &year);
1068
case INTERVAL_DAY: return ltime.day;
1069
case INTERVAL_DAY_HOUR: return (long) (ltime.day*100L+ltime.hour)*neg;
1070
case INTERVAL_DAY_MINUTE: return (long) (ltime.day*10000L+
1073
case INTERVAL_DAY_SECOND: return ((int64_t) ltime.day*1000000L+
1074
(int64_t) (ltime.hour*10000L+
1077
case INTERVAL_HOUR: return (long) ltime.hour*neg;
1078
case INTERVAL_HOUR_MINUTE: return (long) (ltime.hour*100+ltime.minute)*neg;
1079
case INTERVAL_HOUR_SECOND: return (long) (ltime.hour*10000+ltime.minute*100+
1081
case INTERVAL_MINUTE: return (long) ltime.minute*neg;
1082
case INTERVAL_MINUTE_SECOND: return (long) (ltime.minute*100+ltime.second)*neg;
1083
case INTERVAL_SECOND: return (long) ltime.second*neg;
1084
case INTERVAL_MICROSECOND: return (long) ltime.second_part*neg;
1085
case INTERVAL_DAY_MICROSECOND: return (((int64_t)ltime.day*1000000L +
1086
(int64_t)ltime.hour*10000L +
1088
ltime.second)*1000000L +
1089
ltime.second_part)*neg;
1090
case INTERVAL_HOUR_MICROSECOND: return (((int64_t)ltime.hour*10000L +
1092
ltime.second)*1000000L +
1093
ltime.second_part)*neg;
1094
case INTERVAL_MINUTE_MICROSECOND: return (((int64_t)(ltime.minute*100+
1095
ltime.second))*1000000L+
1096
ltime.second_part)*neg;
1097
case INTERVAL_SECOND_MICROSECOND: return ((int64_t)ltime.second*1000000L+
1098
ltime.second_part)*neg;
1099
case INTERVAL_LAST: assert(0); break; /* purecov: deadcode */
1101
return 0; // Impossible
1104
bool Item_extract::eq(const Item *item, bool binary_cmp) const
1108
if (item->type() != FUNC_ITEM ||
1109
functype() != ((Item_func*)item)->functype())
1112
Item_extract* ie= (Item_extract*)item;
1113
if (ie->int_type != int_type)
1116
if (!args[0]->eq(ie->args[0], binary_cmp))
1122
bool Item_char_typecast::eq(const Item *item, bool binary_cmp) const
1126
if (item->type() != FUNC_ITEM ||
1127
functype() != ((Item_func*)item)->functype())
1130
Item_char_typecast *cast= (Item_char_typecast*)item;
1131
if (cast_length != cast->cast_length ||
1132
cast_cs != cast->cast_cs)
1135
if (!args[0]->eq(cast->args[0], binary_cmp))
1140
void Item_typecast::print(String *str, enum_query_type query_type)
1142
str->append(STRING_WITH_LEN("cast("));
1143
args[0]->print(str, query_type);
1144
str->append(STRING_WITH_LEN(" as "));
1145
str->append(cast_type());
1150
void Item_char_typecast::print(String *str, enum_query_type query_type)
1152
str->append(STRING_WITH_LEN("cast("));
1153
args[0]->print(str, query_type);
1154
str->append(STRING_WITH_LEN(" as char"));
1155
if (cast_length >= 0)
1159
// my_charset_bin is good enough for numbers
1160
String st(buffer, sizeof(buffer), &my_charset_bin);
1161
st.set((uint64_t)cast_length, &my_charset_bin);
1167
str->append(STRING_WITH_LEN(" charset "));
1168
str->append(cast_cs->csname);
1173
String *Item_char_typecast::val_str(String *str)
1179
if (!charset_conversion)
1181
if (!(res= args[0]->val_str(str)))
1189
// Convert character set if differ
1190
uint32_t dummy_errors;
1191
if (!(res= args[0]->val_str(&tmp_value)) ||
1192
str->copy(res->ptr(), res->length(), from_cs,
1193
cast_cs, &dummy_errors))
1201
res->set_charset(cast_cs);
1204
Cut the tail if cast with length
1205
and the result is longer than cast length, e.g.
1206
CAST('string' AS CHAR(1))
1208
if (cast_length >= 0)
1210
if (res->length() > (length= (uint32_t) res->charpos(cast_length)))
1211
{ // Safe even if const arg
1213
snprintf(char_type, sizeof(char_type), "%s(%lu)",
1214
cast_cs == &my_charset_bin ? "BINARY" : "CHAR",
1217
if (!res->alloced_length())
1218
{ // Don't change const str
1219
str_value= *res; // Not malloced string
1222
push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
1223
ER_TRUNCATED_WRONG_VALUE,
1224
ER(ER_TRUNCATED_WRONG_VALUE), char_type,
1226
res->length((uint) length);
1228
else if (cast_cs == &my_charset_bin && res->length() < (uint) cast_length)
1230
if (res->alloced_length() < (uint) cast_length)
1232
str->alloc(cast_length);
1236
memset(res->ptr() + res->length(), 0,
1237
(uint) cast_length - res->length());
1238
res->length(cast_length);
1246
void Item_char_typecast::fix_length_and_dec()
1248
uint32_t char_length;
1250
We always force character set conversion if cast_cs
1251
is a multi-byte character set. It garantees that the
1252
result of CAST is a well-formed string.
1253
For single-byte character sets we allow just to copy
1254
from the argument. A single-byte character sets string
1255
is always well-formed.
1257
There is a special trick to convert form a number to ucs2.
1258
As numbers have my_charset_bin as their character set,
1259
it wouldn't do conversion to ucs2 without an additional action.
1260
To force conversion, we should pretend to be non-binary.
1261
Let's choose from_cs this way:
1262
- If the argument in a number and cast_cs is ucs2 (i.e. mbminlen > 1),
1263
then from_cs is set to latin1, to perform latin1 -> ucs2 conversion.
1264
- If the argument is a number and cast_cs is ASCII-compatible
1265
(i.e. mbminlen == 1), then from_cs is set to cast_cs,
1266
which allows just to take over the args[0]->val_str() result
1267
and thus avoid unnecessary character set conversion.
1268
- If the argument is not a number, then from_cs is set to
1269
the argument's charset.
1271
from_cs= (args[0]->result_type() == INT_RESULT ||
1272
args[0]->result_type() == DECIMAL_RESULT ||
1273
args[0]->result_type() == REAL_RESULT) ?
1274
(cast_cs->mbminlen == 1 ? cast_cs : &my_charset_utf8_general_ci) :
1275
args[0]->collation.collation;
1276
charset_conversion= (cast_cs->mbmaxlen > 1) ||
1277
(!my_charset_same(from_cs, cast_cs) && from_cs != &my_charset_bin && cast_cs != &my_charset_bin);
1278
collation.set(cast_cs, DERIVATION_IMPLICIT);
1279
char_length= (cast_length >= 0) ? cast_length :
1280
args[0]->max_length/from_cs->mbmaxlen;
1281
max_length= char_length * cast_cs->mbmaxlen;
1285
String *Item_datetime_typecast::val_str(String *str)
1290
if (!get_arg0_date(<ime, TIME_FUZZY_DATE) &&
1291
!make_datetime(ltime.second_part ? DATE_TIME_MICROSECOND : DATE_TIME,
1300
int64_t Item_datetime_typecast::val_int()
1304
if (get_arg0_date(<ime,1))
1310
return TIME_to_uint64_t_datetime(<ime);
1314
bool Item_time_typecast::get_time(DRIZZLE_TIME *ltime)
1316
bool res= get_arg0_time(ltime);
1318
For DRIZZLE_TIMESTAMP_TIME value we can have non-zero day part,
1319
which we should not lose.
1321
if (ltime->time_type == DRIZZLE_TIMESTAMP_DATETIME)
1322
ltime->year= ltime->month= ltime->day= 0;
1323
ltime->time_type= DRIZZLE_TIMESTAMP_TIME;
1328
int64_t Item_time_typecast::val_int()
1331
if (get_time(<ime))
1336
return ltime.hour * 10000L + ltime.minute * 100 + ltime.second;
1339
String *Item_time_typecast::val_str(String *str)
1344
if (!get_arg0_time(<ime) &&
1345
!make_datetime(ltime.second_part ? TIME_MICROSECOND : TIME_ONLY,
1354
bool Item_date_typecast::get_date(DRIZZLE_TIME *ltime, uint32_t fuzzy_date __attribute__((unused)))
1356
bool res= get_arg0_date(ltime, TIME_FUZZY_DATE);
1357
ltime->hour= ltime->minute= ltime->second= ltime->second_part= 0;
1358
ltime->time_type= DRIZZLE_TIMESTAMP_DATE;
1363
bool Item_date_typecast::get_time(DRIZZLE_TIME *ltime)
1365
memset(ltime, 0, sizeof(DRIZZLE_TIME));
1366
return args[0]->null_value;
1370
String *Item_date_typecast::val_str(String *str)
1375
if (!get_arg0_date(<ime, TIME_FUZZY_DATE) &&
1376
!str->alloc(MAX_DATE_STRING_REP_LENGTH))
1378
make_date((DATE_TIME_FORMAT *) 0, <ime, str);
1386
int64_t Item_date_typecast::val_int()
1390
if ((null_value= args[0]->get_date(<ime, TIME_FUZZY_DATE)))
1392
return (int64_t) (ltime.year * 10000L + ltime.month * 100 + ltime.day);
1396
Get type of datetime value (DATE/TIME/...) which will be produced
1397
according to format string.
1399
@param format format string
1400
@param length length of format string
1403
We don't process day format's characters('D', 'd', 'e') because day
1404
may be a member of all date/time types.
1407
Format specifiers supported by this function should be in sync with
1408
specifiers supported by extract_date_time() function.
1411
One of date_time_format_types values:
1412
- DATE_TIME_MICROSECOND
1419
static date_time_format_types
1420
get_date_time_result_type(const char *format, uint32_t length)
1422
const char *time_part_frms= "HISThiklrs";
1423
const char *date_part_frms= "MVUXYWabcjmvuxyw";
1424
bool date_part_used= 0, time_part_used= 0, frac_second_used= 0;
1426
const char *val= format;
1427
const char *end= format + length;
1429
for (; val != end && val != end; val++)
1431
if (*val == '%' && val+1 != end)
1435
frac_second_used= time_part_used= 1;
1436
else if (!time_part_used && strchr(time_part_frms, *val))
1438
else if (!date_part_used && strchr(date_part_frms, *val))
1440
if (date_part_used && frac_second_used)
1443
frac_second_used implies time_part_used, and thus we already
1444
have all types of date-time components and can end our search.
1446
return DATE_TIME_MICROSECOND;
1451
/* We don't have all three types of date-time components */
1452
if (frac_second_used)
1453
return TIME_MICROSECOND;
1464
void Item_func_str_to_date::fix_length_and_dec()
1468
cached_field_type= DRIZZLE_TYPE_DATETIME;
1469
max_length= MAX_DATETIME_FULL_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
1470
cached_timestamp_type= DRIZZLE_TIMESTAMP_NONE;
1471
if ((const_item= args[1]->const_item()))
1473
char format_buff[64];
1474
String format_str(format_buff, sizeof(format_buff), &my_charset_bin);
1475
String *format= args[1]->val_str(&format_str);
1476
if (!args[1]->null_value)
1478
cached_format_type= get_date_time_result_type(format->ptr(),
1480
switch (cached_format_type) {
1482
cached_timestamp_type= DRIZZLE_TIMESTAMP_DATE;
1483
cached_field_type= DRIZZLE_TYPE_DATE;
1484
max_length= MAX_DATE_WIDTH * MY_CHARSET_BIN_MB_MAXLEN;
1487
case TIME_MICROSECOND:
1488
cached_timestamp_type= DRIZZLE_TIMESTAMP_TIME;
1489
cached_field_type= DRIZZLE_TYPE_TIME;
1490
max_length= MAX_TIME_WIDTH * MY_CHARSET_BIN_MB_MAXLEN;
1493
cached_timestamp_type= DRIZZLE_TIMESTAMP_DATETIME;
1494
cached_field_type= DRIZZLE_TYPE_DATETIME;
1502
bool Item_func_str_to_date::get_date(DRIZZLE_TIME *ltime, uint32_t fuzzy_date)
1504
DATE_TIME_FORMAT date_time_format;
1505
char val_buff[64], format_buff[64];
1506
String val_string(val_buff, sizeof(val_buff), &my_charset_bin), *val;
1507
String format_str(format_buff, sizeof(format_buff), &my_charset_bin), *format;
1509
val= args[0]->val_str(&val_string);
1510
format= args[1]->val_str(&format_str);
1511
if (args[0]->null_value || args[1]->null_value)
1515
memset(ltime, 0, sizeof(*ltime));
1516
date_time_format.format.str= (char*) format->ptr();
1517
date_time_format.format.length= format->length();
1518
if (extract_date_time(&date_time_format, val->ptr(), val->length(),
1519
ltime, cached_timestamp_type, 0, "datetime") ||
1520
((fuzzy_date & TIME_NO_ZERO_DATE) &&
1521
(ltime->year == 0 || ltime->month == 0 || ltime->day == 0)))
1523
if (cached_timestamp_type == DRIZZLE_TIMESTAMP_TIME && ltime->day)
1526
Day part for time type can be nonzero value and so
1527
we should add hours from day part to hour part to
1528
keep valid time value.
1530
ltime->hour+= ltime->day*24;
1536
return (null_value=1);
1540
String *Item_func_str_to_date::val_str(String *str)
1545
if (Item_func_str_to_date::get_date(<ime, TIME_FUZZY_DATE))
1548
if (!make_datetime((const_item ? cached_format_type :
1549
(ltime.second_part ? DATE_TIME_MICROSECOND : DATE_TIME)),
1556
bool Item_func_last_day::get_date(DRIZZLE_TIME *ltime, uint32_t fuzzy_date)
1558
if (get_arg0_date(ltime, fuzzy_date & ~TIME_FUZZY_DATE) ||
1559
(ltime->month == 0))
1565
uint32_t month_idx= ltime->month-1;
1566
ltime->day= days_in_month[month_idx];
1567
if ( month_idx == 1 && calc_days_in_year(ltime->year) == 366)
1569
ltime->hour= ltime->minute= ltime->second= 0;
1570
ltime->second_part= 0;
1571
ltime->time_type= DRIZZLE_TIMESTAMP_DATE;