MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
item_timefunc.cc
Go to the documentation of this file.
1 /*
2  Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; version 2 of the License.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
16 
17 
28 #include "sql_priv.h"
29 /*
30  It is necessary to include set_var.h instead of item.h because there
31  are dependencies on include order for set_var.h and item.h. This
32  will be resolved later.
33 */
34 #include "sql_class.h" // set_var.h: THD
35 #include "set_var.h"
36 #include "sql_locale.h" // MY_LOCALE my_locale_en_US
37 #include "strfunc.h" // check_word
38 #include "sql_time.h" // make_truncated_value_warning,
39  // make_time, get_date_from_daynr,
40  // calc_weekday, calc_week,
41  // convert_month_to_period,
42  // convert_period_to_month,
43  // TIME_to_timestamp, make_date,
44  // calc_time_diff,
45  // calc_time_from_sec,
46  // known_date_time_format,
47  // get_date_time_format_str
48 #include "tztime.h" // struct Time_zone
49 #include "sql_class.h" // THD
50 #include <m_ctype.h>
51 #include <time.h>
52 
53 using std::min;
54 using std::max;
55 
57 #define MAX_DAY_NUMBER 3652424L
58 
59 
67 static void
68 adjust_time_range_with_warn(MYSQL_TIME *ltime, uint8 decimals)
69 {
70  /* Fatally bad value should not come here */
71  if (check_time_range_quick(ltime))
72  {
73  int warning= 0;
74  make_truncated_value_warning(ErrConvString(ltime, decimals),
75  MYSQL_TIMESTAMP_TIME);
76  adjust_time_range(ltime, &warning);
77  }
78 }
79 
80 
81 /*
82  Convert seconds to MYSQL_TIME value with overflow checking.
83 
84  SYNOPSIS:
85  sec_to_time()
86  seconds number of seconds
87  ltime output MYSQL_TIME value
88 
89  DESCRIPTION
90  If the 'seconds' argument is inside MYSQL_TIME data range, convert it to a
91  corresponding value.
92  Otherwise, truncate the resulting value to the nearest endpoint.
93  Note: Truncation in this context means setting the result to the MAX/MIN
94  value of TIME type if value is outside the allowed range.
95  If the number of decimals exceeds what is supported, the value
96  is rounded to the supported number of decimals.
97 
98  RETURN
99  1 if the value was truncated during conversion
100  0 otherwise
101 */
102 
103 static bool sec_to_time(lldiv_t seconds, MYSQL_TIME *ltime)
104 {
105  int warning= 0;
106 
107  set_zero_time(ltime, MYSQL_TIMESTAMP_TIME);
108 
109  if (seconds.quot < 0 || seconds.rem < 0)
110  {
111  ltime->neg= 1;
112  seconds.quot= -seconds.quot;
113  seconds.rem= -seconds.rem;
114  }
115 
116  if (seconds.quot > TIME_MAX_VALUE_SECONDS)
117  {
118  set_max_hhmmss(ltime);
119  return true;
120  }
121 
122  ltime->hour= (uint) (seconds.quot / 3600);
123  uint sec= (uint) (seconds.quot % 3600);
124  ltime->minute= sec / 60;
125  ltime->second= sec % 60;
126  time_add_nanoseconds_with_round(ltime, seconds.rem, &warning);
127 
128  adjust_time_range(ltime, &warning);
129 
130  return warning ? true : false;
131 }
132 
133 
134 /*
135  Date formats corresponding to compound %r and %T conversion specifiers
136 
137  Note: We should init at least first element of "positions" array
138  (first member) or hpux11 compiler will die horribly.
139 */
140 static DATE_TIME_FORMAT time_ampm_format= {{0}, '\0', 0,
141  {(char *)"%I:%i:%S %p", 11}};
142 static DATE_TIME_FORMAT time_24hrs_format= {{0}, '\0', 0,
143  {(char *)"%H:%i:%S", 8}};
144 
178 static bool extract_date_time(DATE_TIME_FORMAT *format,
179  const char *val, uint length, MYSQL_TIME *l_time,
180  timestamp_type cached_timestamp_type,
181  const char **sub_pattern_end,
182  const char *date_time_type)
183 {
184  int weekday= 0, yearday= 0, daypart= 0;
185  int week_number= -1;
186  int error= 0;
187  int strict_week_number_year= -1;
188  int frac_part;
189  bool usa_time= 0;
190  bool UNINIT_VAR(sunday_first_n_first_week_non_iso);
191  bool UNINIT_VAR(strict_week_number);
192  bool UNINIT_VAR(strict_week_number_year_type);
193  const char *val_begin= val;
194  const char *val_end= val + length;
195  const char *ptr= format->format.str;
196  const char *end= ptr + format->format.length;
197  const CHARSET_INFO *cs= &my_charset_bin;
198  DBUG_ENTER("extract_date_time");
199 
200  if (!sub_pattern_end)
201  memset(l_time, 0, sizeof(*l_time));
202 
203  for (; ptr != end && val != val_end; ptr++)
204  {
205  /* Skip pre-space between each argument */
206  if ((val+= cs->cset->scan(cs, val, val_end, MY_SEQ_SPACES)) >= val_end)
207  break;
208 
209  if (*ptr == '%' && ptr+1 != end)
210  {
211  int val_len;
212  char *tmp;
213 
214  error= 0;
215 
216  val_len= (uint) (val_end - val);
217  switch (*++ptr) {
218  /* Year */
219  case 'Y':
220  tmp= (char*) val + MY_MIN(4, val_len);
221  l_time->year= (int) my_strtoll10(val, &tmp, &error);
222  if ((int) (tmp-val) <= 2)
223  l_time->year= year_2000_handling(l_time->year);
224  val= tmp;
225  break;
226  case 'y':
227  tmp= (char*) val + MY_MIN(2, val_len);
228  l_time->year= (int) my_strtoll10(val, &tmp, &error);
229  val= tmp;
230  l_time->year= year_2000_handling(l_time->year);
231  break;
232 
233  /* Month */
234  case 'm':
235  case 'c':
236  tmp= (char*) val + MY_MIN(2, val_len);
237  l_time->month= (int) my_strtoll10(val, &tmp, &error);
238  val= tmp;
239  break;
240  case 'M':
241  if ((l_time->month= check_word(my_locale_en_US.month_names,
242  val, val_end, &val)) <= 0)
243  goto err;
244  break;
245  case 'b':
246  if ((l_time->month= check_word(my_locale_en_US.ab_month_names,
247  val, val_end, &val)) <= 0)
248  goto err;
249  break;
250  /* Day */
251  case 'd':
252  case 'e':
253  tmp= (char*) val + MY_MIN(2, val_len);
254  l_time->day= (int) my_strtoll10(val, &tmp, &error);
255  val= tmp;
256  break;
257  case 'D':
258  tmp= (char*) val + MY_MIN(2, val_len);
259  l_time->day= (int) my_strtoll10(val, &tmp, &error);
260  /* Skip 'st, 'nd, 'th .. */
261  val= tmp + MY_MIN((int) (val_end-tmp), 2);
262  break;
263 
264  /* Hour */
265  case 'h':
266  case 'I':
267  case 'l':
268  usa_time= 1;
269  /* fall through */
270  case 'k':
271  case 'H':
272  tmp= (char*) val + MY_MIN(2, val_len);
273  l_time->hour= (int) my_strtoll10(val, &tmp, &error);
274  val= tmp;
275  break;
276 
277  /* Minute */
278  case 'i':
279  tmp= (char*) val + MY_MIN(2, val_len);
280  l_time->minute= (int) my_strtoll10(val, &tmp, &error);
281  val= tmp;
282  break;
283 
284  /* Second */
285  case 's':
286  case 'S':
287  tmp= (char*) val + MY_MIN(2, val_len);
288  l_time->second= (int) my_strtoll10(val, &tmp, &error);
289  val= tmp;
290  break;
291 
292  /* Second part */
293  case 'f':
294  tmp= (char*) val_end;
295  if (tmp - val > 6)
296  tmp= (char*) val + 6;
297  l_time->second_part= (int) my_strtoll10(val, &tmp, &error);
298  frac_part= 6 - (int) (tmp - val);
299  if (frac_part > 0)
300  l_time->second_part*= (ulong) log_10_int[frac_part];
301  val= tmp;
302  break;
303 
304  /* AM / PM */
305  case 'p':
306  if (val_len < 2 || ! usa_time)
307  goto err;
308  if (!my_strnncoll(&my_charset_latin1,
309  (const uchar *) val, 2,
310  (const uchar *) "PM", 2))
311  daypart= 12;
312  else if (my_strnncoll(&my_charset_latin1,
313  (const uchar *) val, 2,
314  (const uchar *) "AM", 2))
315  goto err;
316  val+= 2;
317  break;
318 
319  /* Exotic things */
320  case 'W':
321  if ((weekday= check_word(my_locale_en_US.day_names, val, val_end, &val)) <= 0)
322  goto err;
323  break;
324  case 'a':
325  if ((weekday= check_word(my_locale_en_US.ab_day_names, val, val_end, &val)) <= 0)
326  goto err;
327  break;
328  case 'w':
329  tmp= (char*) val + 1;
330  if ((weekday= (int) my_strtoll10(val, &tmp, &error)) < 0 ||
331  weekday >= 7)
332  goto err;
333  /* We should use the same 1 - 7 scale for %w as for %W */
334  if (!weekday)
335  weekday= 7;
336  val= tmp;
337  break;
338  case 'j':
339  tmp= (char*) val + MY_MIN(val_len, 3);
340  yearday= (int) my_strtoll10(val, &tmp, &error);
341  val= tmp;
342  break;
343 
344  /* Week numbers */
345  case 'V':
346  case 'U':
347  case 'v':
348  case 'u':
349  sunday_first_n_first_week_non_iso= (*ptr=='U' || *ptr== 'V');
350  strict_week_number= (*ptr=='V' || *ptr=='v');
351  tmp= (char*) val + MY_MIN(val_len, 2);
352  if ((week_number= (int) my_strtoll10(val, &tmp, &error)) < 0 ||
353  (strict_week_number && !week_number) ||
354  week_number > 53)
355  goto err;
356  val= tmp;
357  break;
358 
359  /* Year used with 'strict' %V and %v week numbers */
360  case 'X':
361  case 'x':
362  strict_week_number_year_type= (*ptr=='X');
363  tmp= (char*) val + MY_MIN(4, val_len);
364  strict_week_number_year= (int) my_strtoll10(val, &tmp, &error);
365  val= tmp;
366  break;
367 
368  /* Time in AM/PM notation */
369  case 'r':
370  /*
371  We can't just set error here, as we don't want to generate two
372  warnings in case of errors
373  */
374  if (extract_date_time(&time_ampm_format, val,
375  (uint)(val_end - val), l_time,
376  cached_timestamp_type, &val, "time"))
377  DBUG_RETURN(1);
378  break;
379 
380  /* Time in 24-hour notation */
381  case 'T':
382  if (extract_date_time(&time_24hrs_format, val,
383  (uint)(val_end - val), l_time,
384  cached_timestamp_type, &val, "time"))
385  DBUG_RETURN(1);
386  break;
387 
388  /* Conversion specifiers that match classes of characters */
389  case '.':
390  while (my_ispunct(cs, *val) && val != val_end)
391  val++;
392  break;
393  case '@':
394  while (my_isalpha(cs, *val) && val != val_end)
395  val++;
396  break;
397  case '#':
398  while (my_isdigit(cs, *val) && val != val_end)
399  val++;
400  break;
401  default:
402  goto err;
403  }
404  if (error) // Error from my_strtoll10
405  goto err;
406  }
407  else if (!my_isspace(cs, *ptr))
408  {
409  if (*val != *ptr)
410  goto err;
411  val++;
412  }
413  }
414  if (usa_time)
415  {
416  if (l_time->hour > 12 || l_time->hour < 1)
417  goto err;
418  l_time->hour= l_time->hour%12+daypart;
419  }
420 
421  /*
422  If we are recursively called for parsing string matching compound
423  specifiers we are already done.
424  */
425  if (sub_pattern_end)
426  {
427  *sub_pattern_end= val;
428  DBUG_RETURN(0);
429  }
430 
431  if (yearday > 0)
432  {
433  uint days;
434  days= calc_daynr(l_time->year,1,1) + yearday - 1;
435  if (days <= 0 || days > MAX_DAY_NUMBER)
436  goto err;
437  get_date_from_daynr(days,&l_time->year,&l_time->month,&l_time->day);
438  }
439 
440  if (week_number >= 0 && weekday)
441  {
442  int days;
443  uint weekday_b;
444 
445  /*
446  %V,%v require %X,%x resprectively,
447  %U,%u should be used with %Y and not %X or %x
448  */
449  if ((strict_week_number &&
450  (strict_week_number_year < 0 ||
451  strict_week_number_year_type != sunday_first_n_first_week_non_iso)) ||
452  (!strict_week_number && strict_week_number_year >= 0))
453  goto err;
454 
455  /* Number of days since year 0 till 1st Jan of this year */
456  days= calc_daynr((strict_week_number ? strict_week_number_year :
457  l_time->year),
458  1, 1);
459  /* Which day of week is 1st Jan of this year */
460  weekday_b= calc_weekday(days, sunday_first_n_first_week_non_iso);
461 
462  /*
463  Below we are going to sum:
464  1) number of days since year 0 till 1st day of 1st week of this year
465  2) number of days between 1st week and our week
466  3) and position of our day in the week
467  */
468  if (sunday_first_n_first_week_non_iso)
469  {
470  days+= ((weekday_b == 0) ? 0 : 7) - weekday_b +
471  (week_number - 1) * 7 +
472  weekday % 7;
473  }
474  else
475  {
476  days+= ((weekday_b <= 3) ? 0 : 7) - weekday_b +
477  (week_number - 1) * 7 +
478  (weekday - 1);
479  }
480 
481  if (days <= 0 || days > MAX_DAY_NUMBER)
482  goto err;
483  get_date_from_daynr(days,&l_time->year,&l_time->month,&l_time->day);
484  }
485 
486  if (l_time->month > 12 || l_time->day > 31 || l_time->hour > 23 ||
487  l_time->minute > 59 || l_time->second > 59)
488  goto err;
489 
490  if (val != val_end)
491  {
492  do
493  {
494  if (!my_isspace(&my_charset_latin1,*val))
495  {
496  // TS-TODO: extract_date_time is not UCS2 safe
497  make_truncated_value_warning(ErrConvString(val_begin, length),
498  cached_timestamp_type);
499  break;
500  }
501  } while (++val != val_end);
502  }
503  DBUG_RETURN(0);
504 
505 err:
506  {
507  char buff[128];
508  strmake(buff, val_begin, min<size_t>(length, sizeof(buff)-1));
509  push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
510  ER_WRONG_VALUE_FOR_TYPE, ER(ER_WRONG_VALUE_FOR_TYPE),
511  date_time_type, buff, "str_to_date");
512  }
513  DBUG_RETURN(1);
514 }
515 
516 
522  timestamp_type type, String *str)
523 {
524  char intbuff[15];
525  uint hours_i;
526  uint weekday;
527  ulong length;
528  const char *ptr, *end;
529  THD *thd= current_thd;
530  MY_LOCALE *locale= thd->variables.lc_time_names;
531 
532  str->length(0);
533 
534  if (l_time->neg)
535  str->append('-');
536 
537  end= (ptr= format->format.str) + format->format.length;
538  for (; ptr != end ; ptr++)
539  {
540  if (*ptr != '%' || ptr+1 == end)
541  str->append(*ptr);
542  else
543  {
544  switch (*++ptr) {
545  case 'M':
546  if (!l_time->month)
547  return 1;
548  str->append(locale->month_names->type_names[l_time->month-1],
549  (uint) strlen(locale->month_names->type_names[l_time->month-1]),
550  system_charset_info);
551  break;
552  case 'b':
553  if (!l_time->month)
554  return 1;
555  str->append(locale->ab_month_names->type_names[l_time->month-1],
556  (uint) strlen(locale->ab_month_names->type_names[l_time->month-1]),
557  system_charset_info);
558  break;
559  case 'W':
560  if (type == MYSQL_TIMESTAMP_TIME || !(l_time->month || l_time->year))
561  return 1;
562  weekday= calc_weekday(calc_daynr(l_time->year,l_time->month,
563  l_time->day),0);
564  str->append(locale->day_names->type_names[weekday],
565  (uint) strlen(locale->day_names->type_names[weekday]),
566  system_charset_info);
567  break;
568  case 'a':
569  if (type == MYSQL_TIMESTAMP_TIME || !(l_time->month || l_time->year))
570  return 1;
571  weekday=calc_weekday(calc_daynr(l_time->year,l_time->month,
572  l_time->day),0);
573  str->append(locale->ab_day_names->type_names[weekday],
574  (uint) strlen(locale->ab_day_names->type_names[weekday]),
575  system_charset_info);
576  break;
577  case 'D':
578  if (type == MYSQL_TIMESTAMP_TIME)
579  return 1;
580  length= (uint) (int10_to_str(l_time->day, intbuff, 10) - intbuff);
581  str->append_with_prefill(intbuff, length, 1, '0');
582  if (l_time->day >= 10 && l_time->day <= 19)
583  str->append(STRING_WITH_LEN("th"));
584  else
585  {
586  switch (l_time->day %10) {
587  case 1:
588  str->append(STRING_WITH_LEN("st"));
589  break;
590  case 2:
591  str->append(STRING_WITH_LEN("nd"));
592  break;
593  case 3:
594  str->append(STRING_WITH_LEN("rd"));
595  break;
596  default:
597  str->append(STRING_WITH_LEN("th"));
598  break;
599  }
600  }
601  break;
602  case 'Y':
603  length= (uint) (int10_to_str(l_time->year, intbuff, 10) - intbuff);
604  str->append_with_prefill(intbuff, length, 4, '0');
605  break;
606  case 'y':
607  length= (uint) (int10_to_str(l_time->year%100, intbuff, 10) - intbuff);
608  str->append_with_prefill(intbuff, length, 2, '0');
609  break;
610  case 'm':
611  length= (uint) (int10_to_str(l_time->month, intbuff, 10) - intbuff);
612  str->append_with_prefill(intbuff, length, 2, '0');
613  break;
614  case 'c':
615  length= (uint) (int10_to_str(l_time->month, intbuff, 10) - intbuff);
616  str->append_with_prefill(intbuff, length, 1, '0');
617  break;
618  case 'd':
619  length= (uint) (int10_to_str(l_time->day, intbuff, 10) - intbuff);
620  str->append_with_prefill(intbuff, length, 2, '0');
621  break;
622  case 'e':
623  length= (uint) (int10_to_str(l_time->day, intbuff, 10) - intbuff);
624  str->append_with_prefill(intbuff, length, 1, '0');
625  break;
626  case 'f':
627  length= (uint) (int10_to_str(l_time->second_part, intbuff, 10) - intbuff);
628  str->append_with_prefill(intbuff, length, 6, '0');
629  break;
630  case 'H':
631  length= (uint) (int10_to_str(l_time->hour, intbuff, 10) - intbuff);
632  str->append_with_prefill(intbuff, length, 2, '0');
633  break;
634  case 'h':
635  case 'I':
636  hours_i= (l_time->hour%24 + 11)%12+1;
637  length= (uint) (int10_to_str(hours_i, intbuff, 10) - intbuff);
638  str->append_with_prefill(intbuff, length, 2, '0');
639  break;
640  case 'i': /* minutes */
641  length= (uint) (int10_to_str(l_time->minute, intbuff, 10) - intbuff);
642  str->append_with_prefill(intbuff, length, 2, '0');
643  break;
644  case 'j':
645  if (type == MYSQL_TIMESTAMP_TIME)
646  return 1;
647  length= (uint) (int10_to_str(calc_daynr(l_time->year,l_time->month,
648  l_time->day) -
649  calc_daynr(l_time->year,1,1) + 1, intbuff, 10) - intbuff);
650  str->append_with_prefill(intbuff, length, 3, '0');
651  break;
652  case 'k':
653  length= (uint) (int10_to_str(l_time->hour, intbuff, 10) - intbuff);
654  str->append_with_prefill(intbuff, length, 1, '0');
655  break;
656  case 'l':
657  hours_i= (l_time->hour%24 + 11)%12+1;
658  length= (uint) (int10_to_str(hours_i, intbuff, 10) - intbuff);
659  str->append_with_prefill(intbuff, length, 1, '0');
660  break;
661  case 'p':
662  hours_i= l_time->hour%24;
663  str->append(hours_i < 12 ? "AM" : "PM",2);
664  break;
665  case 'r':
666  length= sprintf(intbuff, ((l_time->hour % 24) < 12) ?
667  "%02d:%02d:%02d AM" : "%02d:%02d:%02d PM",
668  (l_time->hour+11)%12+1,
669  l_time->minute,
670  l_time->second);
671  str->append(intbuff, length);
672  break;
673  case 'S':
674  case 's':
675  length= (uint) (int10_to_str(l_time->second, intbuff, 10) - intbuff);
676  str->append_with_prefill(intbuff, length, 2, '0');
677  break;
678  case 'T':
679  length= sprintf(intbuff, "%02d:%02d:%02d",
680  l_time->hour, l_time->minute, l_time->second);
681  str->append(intbuff, length);
682  break;
683  case 'U':
684  case 'u':
685  {
686  uint year;
687  if (type == MYSQL_TIMESTAMP_TIME)
688  return 1;
689  length= (uint) (int10_to_str(calc_week(l_time,
690  (*ptr) == 'U' ?
691  WEEK_FIRST_WEEKDAY : WEEK_MONDAY_FIRST,
692  &year),
693  intbuff, 10) - intbuff);
694  str->append_with_prefill(intbuff, length, 2, '0');
695  }
696  break;
697  case 'v':
698  case 'V':
699  {
700  uint year;
701  if (type == MYSQL_TIMESTAMP_TIME)
702  return 1;
703  length= (uint) (int10_to_str(calc_week(l_time,
704  ((*ptr) == 'V' ?
705  (WEEK_YEAR | WEEK_FIRST_WEEKDAY) :
706  (WEEK_YEAR | WEEK_MONDAY_FIRST)),
707  &year),
708  intbuff, 10) - intbuff);
709  str->append_with_prefill(intbuff, length, 2, '0');
710  }
711  break;
712  case 'x':
713  case 'X':
714  {
715  uint year;
716  if (type == MYSQL_TIMESTAMP_TIME)
717  return 1;
718  (void) calc_week(l_time,
719  ((*ptr) == 'X' ?
720  WEEK_YEAR | WEEK_FIRST_WEEKDAY :
721  WEEK_YEAR | WEEK_MONDAY_FIRST),
722  &year);
723  length= (uint) (int10_to_str(year, intbuff, 10) - intbuff);
724  str->append_with_prefill(intbuff, length, 4, '0');
725  }
726  break;
727  case 'w':
728  if (type == MYSQL_TIMESTAMP_TIME || !(l_time->month || l_time->year))
729  return 1;
730  weekday=calc_weekday(calc_daynr(l_time->year,l_time->month,
731  l_time->day),1);
732  length= (uint) (int10_to_str(weekday, intbuff, 10) - intbuff);
733  str->append_with_prefill(intbuff, length, 1, '0');
734  break;
735 
736  default:
737  str->append(*ptr);
738  break;
739  }
740  }
741  }
742  return 0;
743 }
744 
745 
766 static bool get_interval_info(Item *args,
767  String *str_value,
768  bool *is_negative,
769  uint count, ulonglong *values,
770  bool transform_msec)
771 {
772  String *res;
773  if (!(res= args->val_str_ascii(str_value)))
774  return true;
775 
776  const CHARSET_INFO *cs= res->charset();
777  const char *str= res->ptr();
778  const char *end= str + res->length();
779 
780  str+= cs->cset->scan(cs, str, end, MY_SEQ_SPACES);
781  if (str < end && *str == '-')
782  {
783  *is_negative= true;
784  str++;
785  }
786 
787  while (str < end && !my_isdigit(cs,*str))
788  str++;
789 
790  long msec_length= 0;
791  for (uint i=0 ; i < count ; i++)
792  {
793  longlong value;
794  const char *start= str;
795  for (value=0; str != end && my_isdigit(cs,*str) ; str++)
796  value= value*LL(10) + (longlong) (*str - '0');
797  msec_length= 6 - (str - start);
798  values[i]= value;
799  while (str != end && !my_isdigit(cs,*str))
800  str++;
801  if (str == end && i != count-1)
802  {
803  i++;
804  /* Change values[0...i-1] -> values[0...count-1] */
805  bmove_upp((uchar*) (values+count), (uchar*) (values+i),
806  sizeof(*values)*i);
807  memset(values, 0, sizeof(*values)*(count-i));
808  break;
809  }
810  }
811 
812  if (transform_msec && msec_length > 0)
813  values[count - 1] *= (long) log_10_int[msec_length];
814 
815  return (str != end);
816 }
817 
818 
819 /*** Abstract classes ****************************************/
820 
821 bool Item_temporal_func::check_precision()
822 {
823  if (decimals > DATETIME_MAX_DECIMALS)
824  {
825  my_error(ER_TOO_BIG_PRECISION, MYF(0),
826  (int) decimals, func_name(), DATETIME_MAX_DECIMALS);
827  return true;
828  }
829  return false;
830 }
831 
832 
833 type_conversion_status
835 {
836  if (cached_field_type == MYSQL_TYPE_TIME)
837  return save_time_in_field(field);
838  if (is_temporal_type_with_date(cached_field_type))
839  return save_date_in_field(field);
840  return Item_str_func::save_in_field(field, no_conversions);
841 }
842 
843 
844 my_decimal *Item_temporal_hybrid_func::val_decimal(my_decimal *decimal_value)
845 {
846  DBUG_ASSERT(fixed == 1);
847  if (cached_field_type == MYSQL_TYPE_TIME)
848  return val_decimal_from_time(decimal_value);
849  else if (cached_field_type == MYSQL_TYPE_DATETIME)
850  return val_decimal_from_date(decimal_value);
851  else
852  {
853  MYSQL_TIME ltime;
854  val_datetime(&ltime, TIME_FUZZY_DATE | sql_mode);
855  return null_value ? 0:
856  ltime.time_type == MYSQL_TIMESTAMP_TIME ?
857  time2my_decimal(&ltime, decimal_value) :
858  date2my_decimal(&ltime, decimal_value);
859  }
860 }
861 
862 
863 bool Item_temporal_hybrid_func::get_date(MYSQL_TIME *ltime, uint fuzzy_date)
864 {
865  MYSQL_TIME tm;
866  if (val_datetime(&tm, fuzzy_date))
867  {
868  DBUG_ASSERT(null_value == true);
869  return true;
870  }
871  if (cached_field_type == MYSQL_TYPE_TIME ||
872  tm.time_type == MYSQL_TIMESTAMP_TIME)
873  time_to_datetime(current_thd, &tm, ltime);
874  else
875  *ltime= tm;
876  return false;
877 }
878 
879 
880 bool Item_temporal_hybrid_func::get_time(MYSQL_TIME *ltime)
881 {
882  if (val_datetime(ltime, TIME_FUZZY_DATE))
883  {
884  DBUG_ASSERT(null_value == true);
885  return true;
886  }
887  if (cached_field_type == MYSQL_TYPE_TIME &&
888  ltime->time_type != MYSQL_TIMESTAMP_TIME)
889  datetime_to_time(ltime);
890  return false;
891 }
892 
893 
895 {
896  DBUG_ASSERT(fixed == 1);
897  MYSQL_TIME ltime;
898 
899  if (val_datetime(&ltime, TIME_FUZZY_DATE) ||
900  (null_value= my_TIME_to_str(&ltime, str,
901  cached_field_type == MYSQL_TYPE_STRING ?
902  (ltime.second_part ?
903  DATETIME_MAX_DECIMALS : 0) :
904  decimals)))
905  return (String *) 0;
906 
907  /* Check that the returned timestamp type matches to the function type */
908  DBUG_ASSERT((cached_field_type == MYSQL_TYPE_TIME &&
909  ltime.time_type == MYSQL_TIMESTAMP_TIME) ||
910  (cached_field_type == MYSQL_TYPE_DATE &&
911  ltime.time_type == MYSQL_TIMESTAMP_DATE) ||
912  (cached_field_type == MYSQL_TYPE_DATETIME &&
913  ltime.time_type == MYSQL_TIMESTAMP_DATETIME) ||
914  cached_field_type == MYSQL_TYPE_STRING ||
915  ltime.time_type == MYSQL_TIMESTAMP_NONE);
916  return str;
917 }
918 
919 
921 {
922  DBUG_ASSERT(fixed == 1);
923  MYSQL_TIME ltime;
924  return get_time(&ltime) ? 0LL : TIME_to_longlong_time_packed(&ltime);
925 }
926 
927 
929 {
930  DBUG_ASSERT(fixed == 1);
931  MYSQL_TIME ltime;
932  return get_date(&ltime, TIME_FUZZY_DATE) ?
933  0LL : TIME_to_longlong_date_packed(&ltime);
934 }
935 
936 
938 {
939  DBUG_ASSERT(fixed == 1);
940  MYSQL_TIME ltime;
941  return get_date(&ltime, TIME_FUZZY_DATE) ?
942  0LL : TIME_to_longlong_datetime_packed(&ltime);
943 }
944 
945 
946 bool Item_date_literal::eq(const Item *item, bool binary_cmp) const
947 {
948  return
949  item->basic_const_item() && type() == item->type() &&
950  func_name() == ((Item_func *) item)->func_name() &&
951  cached_time.eq(((Item_date_literal *) item)->cached_time);
952 }
953 
954 
955 void Item_date_literal::print(String *str, enum_query_type query_type)
956 {
957  str->append("DATE'");
958  str->append(cached_time.cptr());
959  str->append('\'');
960 }
961 
962 
963 bool Item_datetime_literal::eq(const Item *item, bool binary_cmp) const
964 {
965  return
966  item->basic_const_item() && type() == item->type() &&
967  func_name() == ((Item_func *) item)->func_name() &&
968  cached_time.eq(((Item_datetime_literal *) item)->cached_time);
969 }
970 
971 
972 void Item_datetime_literal::print(String *str, enum_query_type query_type)
973 {
974  str->append("TIMESTAMP'");
975  str->append(cached_time.cptr());
976  str->append('\'');
977 }
978 
979 
980 bool Item_time_literal::eq(const Item *item, bool binary_cmp) const
981 {
982  return
983  item->basic_const_item() && type() == item->type() &&
984  func_name() == ((Item_func *) item)->func_name() &&
985  cached_time.eq(((Item_time_literal *) item)->cached_time);
986 }
987 
988 
989 void Item_time_literal::print(String *str, enum_query_type query_type)
990 {
991  str->append("TIME'");
992  str->append(cached_time.cptr());
993  str->append('\'');
994 }
995 
996 
997 longlong Item_func_period_add::val_int()
998 {
999  DBUG_ASSERT(fixed == 1);
1000  ulong period=(ulong) args[0]->val_int();
1001  int months=(int) args[1]->val_int();
1002 
1003  if ((null_value=args[0]->null_value || args[1]->null_value) ||
1004  period == 0L)
1005  return 0; /* purecov: inspected */
1006  return (longlong)
1007  convert_month_to_period((uint) ((int) convert_period_to_month(period)+
1008  months));
1009 }
1010 
1011 
1012 longlong Item_func_period_diff::val_int()
1013 {
1014  DBUG_ASSERT(fixed == 1);
1015  ulong period1=(ulong) args[0]->val_int();
1016  ulong period2=(ulong) args[1]->val_int();
1017 
1018  if ((null_value=args[0]->null_value || args[1]->null_value))
1019  return 0; /* purecov: inspected */
1020  return (longlong) ((long) convert_period_to_month(period1)-
1021  (long) convert_period_to_month(period2));
1022 }
1023 
1024 
1025 
1026 longlong Item_func_to_days::val_int()
1027 {
1028  DBUG_ASSERT(fixed == 1);
1029  MYSQL_TIME ltime;
1030  if (get_arg0_date(&ltime, TIME_NO_ZERO_DATE))
1031  return 0;
1032  return (longlong) calc_daynr(ltime.year,ltime.month,ltime.day);
1033 }
1034 
1035 
1036 longlong Item_func_to_seconds::val_int_endpoint(bool left_endp,
1037  bool *incl_endp)
1038 {
1039  DBUG_ASSERT(fixed == 1);
1040  MYSQL_TIME ltime;
1041  longlong seconds;
1042  longlong days;
1043  int dummy; /* unused */
1044  if (get_arg0_date(&ltime, TIME_FUZZY_DATE))
1045  {
1046  /* got NULL, leave the incl_endp intact */
1047  return LONGLONG_MIN;
1048  }
1049  seconds= ltime.hour * 3600L + ltime.minute * 60 + ltime.second;
1050  seconds= ltime.neg ? -seconds : seconds;
1051  days= (longlong) calc_daynr(ltime.year, ltime.month, ltime.day);
1052  seconds+= days * 24L * 3600L;
1053  /* Set to NULL if invalid date, but keep the value */
1054  null_value= check_date(&ltime, non_zero_date(&ltime),
1055  (TIME_NO_ZERO_IN_DATE | TIME_NO_ZERO_DATE),
1056  &dummy);
1057  /*
1058  Even if the evaluation return NULL, seconds is useful for pruning
1059  */
1060  return seconds;
1061 }
1062 
1063 longlong Item_func_to_seconds::val_int()
1064 {
1065  DBUG_ASSERT(fixed == 1);
1066  MYSQL_TIME ltime;
1067  longlong seconds;
1068  longlong days;
1069  if (get_arg0_date(&ltime, TIME_NO_ZERO_DATE))
1070  return 0;
1071  seconds= ltime.hour * 3600L + ltime.minute * 60 + ltime.second;
1072  seconds=ltime.neg ? -seconds : seconds;
1073  days= (longlong) calc_daynr(ltime.year, ltime.month, ltime.day);
1074  return seconds + days * 24L * 3600L;
1075 }
1076 
1077 /*
1078  Get information about this Item tree monotonicity
1079 
1080  SYNOPSIS
1081  Item_func_to_days::get_monotonicity_info()
1082 
1083  DESCRIPTION
1084  Get information about monotonicity of the function represented by this item
1085  tree.
1086 
1087  RETURN
1088  See enum_monotonicity_info.
1089 */
1090 
1091 enum_monotonicity_info Item_func_to_days::get_monotonicity_info() const
1092 {
1093  if (args[0]->type() == Item::FIELD_ITEM)
1094  {
1095  if (args[0]->field_type() == MYSQL_TYPE_DATE)
1096  return MONOTONIC_STRICT_INCREASING_NOT_NULL;
1097  if (args[0]->field_type() == MYSQL_TYPE_DATETIME)
1098  return MONOTONIC_INCREASING_NOT_NULL;
1099  }
1100  return NON_MONOTONIC;
1101 }
1102 
1103 enum_monotonicity_info Item_func_to_seconds::get_monotonicity_info() const
1104 {
1105  if (args[0]->type() == Item::FIELD_ITEM)
1106  {
1107  if (args[0]->field_type() == MYSQL_TYPE_DATE ||
1108  args[0]->field_type() == MYSQL_TYPE_DATETIME)
1109  return MONOTONIC_STRICT_INCREASING_NOT_NULL;
1110  }
1111  return NON_MONOTONIC;
1112 }
1113 
1114 
1115 longlong Item_func_to_days::val_int_endpoint(bool left_endp, bool *incl_endp)
1116 {
1117  DBUG_ASSERT(fixed == 1);
1118  MYSQL_TIME ltime;
1119  longlong res;
1120  int dummy; /* unused */
1121  if (get_arg0_date(&ltime, TIME_FUZZY_DATE))
1122  {
1123  /* got NULL, leave the incl_endp intact */
1124  return LONGLONG_MIN;
1125  }
1126  res=(longlong) calc_daynr(ltime.year,ltime.month,ltime.day);
1127  /* Set to NULL if invalid date, but keep the value */
1128  null_value= check_date(&ltime, non_zero_date(&ltime),
1129  (TIME_NO_ZERO_IN_DATE | TIME_NO_ZERO_DATE),
1130  &dummy);
1131  if (null_value)
1132  {
1133  /*
1134  Even if the evaluation return NULL, the calc_daynr is useful for pruning
1135  */
1136  if (args[0]->field_type() != MYSQL_TYPE_DATE)
1137  *incl_endp= TRUE;
1138  return res;
1139  }
1140 
1141  if (args[0]->field_type() == MYSQL_TYPE_DATE)
1142  {
1143  // TO_DAYS() is strictly monotonic for dates, leave incl_endp intact
1144  return res;
1145  }
1146 
1147  /*
1148  Handle the special but practically useful case of datetime values that
1149  point to day bound ("strictly less" comparison stays intact):
1150 
1151  col < '2007-09-15 00:00:00' -> TO_DAYS(col) < TO_DAYS('2007-09-15')
1152  col > '2007-09-15 23:59:59' -> TO_DAYS(col) > TO_DAYS('2007-09-15')
1153 
1154  which is different from the general case ("strictly less" changes to
1155  "less or equal"):
1156 
1157  col < '2007-09-15 12:34:56' -> TO_DAYS(col) <= TO_DAYS('2007-09-15')
1158  */
1159  if ((!left_endp && !(ltime.hour || ltime.minute || ltime.second ||
1160  ltime.second_part)) ||
1161  (left_endp && ltime.hour == 23 && ltime.minute == 59 &&
1162  ltime.second == 59))
1163  /* do nothing */
1164  ;
1165  else
1166  *incl_endp= TRUE;
1167  return res;
1168 }
1169 
1170 
1171 longlong Item_func_dayofyear::val_int()
1172 {
1173  DBUG_ASSERT(fixed == 1);
1174  MYSQL_TIME ltime;
1175  if (get_arg0_date(&ltime,TIME_NO_ZERO_DATE))
1176  return 0;
1177  return (longlong) calc_daynr(ltime.year,ltime.month,ltime.day) -
1178  calc_daynr(ltime.year,1,1) + 1;
1179 }
1180 
1181 longlong Item_func_dayofmonth::val_int()
1182 {
1183  DBUG_ASSERT(fixed == 1);
1184  MYSQL_TIME ltime;
1185  return get_arg0_date(&ltime, TIME_FUZZY_DATE) ? 0 : (longlong) ltime.day;
1186 }
1187 
1188 longlong Item_func_month::val_int()
1189 {
1190  DBUG_ASSERT(fixed == 1);
1191  MYSQL_TIME ltime;
1192  return get_arg0_date(&ltime, TIME_FUZZY_DATE) ? 0 : (longlong) ltime.month;
1193 }
1194 
1195 
1196 void Item_func_monthname::fix_length_and_dec()
1197 {
1198  THD* thd= current_thd;
1199  const CHARSET_INFO *cs= thd->variables.collation_connection;
1200  uint32 repertoire= my_charset_repertoire(cs);
1201  locale= thd->variables.lc_time_names;
1202  collation.set(cs, DERIVATION_COERCIBLE, repertoire);
1203  decimals=0;
1204  max_length= locale->max_month_name_length * collation.collation->mbmaxlen;
1205  maybe_null=1;
1206 }
1207 
1208 
1209 String* Item_func_monthname::val_str(String* str)
1210 {
1211  DBUG_ASSERT(fixed == 1);
1212  const char *month_name;
1213  uint err;
1214  MYSQL_TIME ltime;
1215 
1216  if ((null_value= (get_arg0_date(&ltime, TIME_FUZZY_DATE) || !ltime.month)))
1217  return (String *) 0;
1218 
1219  month_name= locale->month_names->type_names[ltime.month - 1];
1220  str->copy(month_name, (uint) strlen(month_name), &my_charset_utf8_bin,
1221  collation.collation, &err);
1222  return str;
1223 }
1224 
1225 
1231 {
1232  DBUG_ASSERT(fixed == 1);
1233  MYSQL_TIME ltime;
1234  if (get_arg0_date(&ltime, TIME_FUZZY_DATE))
1235  return 0;
1236  return (longlong) ((ltime.month+2)/3);
1237 }
1238 
1239 longlong Item_func_hour::val_int()
1240 {
1241  DBUG_ASSERT(fixed == 1);
1242  MYSQL_TIME ltime;
1243  return get_arg0_time(&ltime) ? 0 : ltime.hour;
1244 }
1245 
1246 longlong Item_func_minute::val_int()
1247 {
1248  DBUG_ASSERT(fixed == 1);
1249  MYSQL_TIME ltime;
1250  return get_arg0_time(&ltime) ? 0 : ltime.minute;
1251 }
1252 
1257 {
1258  DBUG_ASSERT(fixed == 1);
1259  MYSQL_TIME ltime;
1260  return get_arg0_time(&ltime) ? 0 : ltime.second;
1261 }
1262 
1263 
1264 uint week_mode(uint mode)
1265 {
1266  uint week_format= (mode & 7);
1267  if (!(week_format & WEEK_MONDAY_FIRST))
1268  week_format^= WEEK_FIRST_WEEKDAY;
1269  return week_format;
1270 }
1271 
1304 {
1305  DBUG_ASSERT(fixed == 1);
1306  uint year;
1307  MYSQL_TIME ltime;
1308  if (get_arg0_date(&ltime, TIME_NO_ZERO_DATE))
1309  return 0;
1310  return (longlong) calc_week(&ltime,
1311  week_mode((uint) args[1]->val_int()),
1312  &year);
1313 }
1314 
1315 
1316 longlong Item_func_yearweek::val_int()
1317 {
1318  DBUG_ASSERT(fixed == 1);
1319  uint year,week;
1320  MYSQL_TIME ltime;
1321  if (get_arg0_date(&ltime, TIME_NO_ZERO_DATE))
1322  return 0;
1323  week= calc_week(&ltime,
1324  (week_mode((uint) args[1]->val_int()) | WEEK_YEAR),
1325  &year);
1326  return week+year*100;
1327 }
1328 
1329 
1330 longlong Item_func_weekday::val_int()
1331 {
1332  DBUG_ASSERT(fixed == 1);
1333  MYSQL_TIME ltime;
1334 
1335  if (get_arg0_date(&ltime, TIME_NO_ZERO_DATE))
1336  return 0;
1337 
1338  return (longlong) calc_weekday(calc_daynr(ltime.year, ltime.month,
1339  ltime.day),
1340  odbc_type) + test(odbc_type);
1341 }
1342 
1343 void Item_func_dayname::fix_length_and_dec()
1344 {
1345  THD* thd= current_thd;
1346  const CHARSET_INFO *cs= thd->variables.collation_connection;
1347  uint32 repertoire= my_charset_repertoire(cs);
1348  locale= thd->variables.lc_time_names;
1349  collation.set(cs, DERIVATION_COERCIBLE, repertoire);
1350  decimals=0;
1351  max_length= locale->max_day_name_length * collation.collation->mbmaxlen;
1352  maybe_null=1;
1353 }
1354 
1355 
1356 String* Item_func_dayname::val_str(String* str)
1357 {
1358  DBUG_ASSERT(fixed == 1);
1359  uint weekday=(uint) val_int(); // Always Item_func_daynr()
1360  const char *day_name;
1361  uint err;
1362 
1363  if (null_value)
1364  return (String*) 0;
1365 
1366  day_name= locale->day_names->type_names[weekday];
1367  str->copy(day_name, (uint) strlen(day_name), &my_charset_utf8_bin,
1368  collation.collation, &err);
1369  return str;
1370 }
1371 
1372 
1373 longlong Item_func_year::val_int()
1374 {
1375  DBUG_ASSERT(fixed == 1);
1376  MYSQL_TIME ltime;
1377  return get_arg0_date(&ltime, TIME_FUZZY_DATE) ? 0 : (longlong) ltime.year;
1378 }
1379 
1380 
1381 /*
1382  Get information about this Item tree monotonicity
1383 
1384  SYNOPSIS
1385  Item_func_year::get_monotonicity_info()
1386 
1387  DESCRIPTION
1388  Get information about monotonicity of the function represented by this item
1389  tree.
1390 
1391  RETURN
1392  See enum_monotonicity_info.
1393 */
1394 
1395 enum_monotonicity_info Item_func_year::get_monotonicity_info() const
1396 {
1397  if (args[0]->type() == Item::FIELD_ITEM &&
1398  (args[0]->field_type() == MYSQL_TYPE_DATE ||
1399  args[0]->field_type() == MYSQL_TYPE_DATETIME))
1400  return MONOTONIC_INCREASING;
1401  return NON_MONOTONIC;
1402 }
1403 
1404 
1405 longlong Item_func_year::val_int_endpoint(bool left_endp, bool *incl_endp)
1406 {
1407  DBUG_ASSERT(fixed == 1);
1408  MYSQL_TIME ltime;
1409  if (get_arg0_date(&ltime, TIME_FUZZY_DATE))
1410  {
1411  /* got NULL, leave the incl_endp intact */
1412  return LONGLONG_MIN;
1413  }
1414 
1415  /*
1416  Handle the special but practically useful case of datetime values that
1417  point to year bound ("strictly less" comparison stays intact) :
1418 
1419  col < '2007-01-01 00:00:00' -> YEAR(col) < 2007
1420 
1421  which is different from the general case ("strictly less" changes to
1422  "less or equal"):
1423 
1424  col < '2007-09-15 23:00:00' -> YEAR(col) <= 2007
1425  */
1426  if (!left_endp && ltime.day == 1 && ltime.month == 1 &&
1427  !(ltime.hour || ltime.minute || ltime.second || ltime.second_part))
1428  ; /* do nothing */
1429  else
1430  *incl_endp= TRUE;
1431  return ltime.year;
1432 }
1433 
1434 
1435 longlong Item_timeval_func::val_int()
1436 {
1437  struct timeval tm;
1438  return val_timeval(&tm) ? 0 : tm.tv_sec;
1439 }
1440 
1441 
1442 my_decimal *Item_timeval_func::val_decimal(my_decimal *decimal_value)
1443 {
1444  struct timeval tm;
1445  return val_timeval(&tm) ? NULL : timeval2my_decimal(&tm, decimal_value);
1446 }
1447 
1448 
1449 double Item_timeval_func::val_real()
1450 {
1451  struct timeval tm;
1452  return val_timeval(&tm) ? 0 :
1453  (double) tm.tv_sec + (double) tm.tv_usec / (double) 1000000;
1454 }
1455 
1456 
1457 String *Item_timeval_func::val_str(String *str)
1458 {
1459  struct timeval tm;
1460  if (val_timeval(&tm) || (null_value= str->alloc(MAX_DATE_STRING_REP_LENGTH)))
1461  return (String*) 0;
1462  str->length(my_timeval_to_str(&tm, (char*) str->ptr(), decimals));
1463  str->set_charset(collation.collation);
1464  return str;
1465 }
1466 
1467 
1469 {
1470  DBUG_ASSERT(fixed == 1);
1471  if (arg_count == 0)
1472  {
1473  tm->tv_sec= current_thd->query_start();
1474  tm->tv_usec= 0;
1475  return false; // no args: null_value is set in constructor and is always 0.
1476  }
1477  int warnings= 0;
1478  return (null_value= args[0]->get_timeval(tm, &warnings));
1479 }
1480 
1481 
1482 enum_monotonicity_info Item_func_unix_timestamp::get_monotonicity_info() const
1483 {
1484  if (args[0]->type() == Item::FIELD_ITEM &&
1485  (args[0]->field_type() == MYSQL_TYPE_TIMESTAMP))
1486  return MONOTONIC_INCREASING;
1487  return NON_MONOTONIC;
1488 }
1489 
1490 
1491 longlong Item_func_unix_timestamp::val_int_endpoint(bool left_endp, bool *incl_endp)
1492 {
1493  DBUG_ASSERT(fixed == 1);
1494  DBUG_ASSERT(arg_count == 1 &&
1495  args[0]->type() == Item::FIELD_ITEM &&
1496  args[0]->field_type() == MYSQL_TYPE_TIMESTAMP);
1497  /* Leave the incl_endp intact */
1498  struct timeval tm;
1499  return val_timeval(&tm) ? 0 : tm.tv_sec;
1500 }
1501 
1502 
1503 longlong Item_func_time_to_sec::val_int()
1504 {
1505  DBUG_ASSERT(fixed == 1);
1506  MYSQL_TIME ltime;
1507  longlong seconds;
1508  if (get_arg0_time(&ltime))
1509  return 0;
1510  seconds= ltime.hour * 3600L + ltime.minute * 60 + ltime.second;
1511  return ltime.neg ? -seconds : seconds;
1512 }
1513 
1514 
1521 bool get_interval_value(Item *args, interval_type int_type,
1522  String *str_value, INTERVAL *interval)
1523 {
1524  ulonglong array[5];
1525  longlong UNINIT_VAR(value);
1526 
1527  memset(interval, 0, sizeof(*interval));
1528  if (int_type == INTERVAL_SECOND && args->decimals)
1529  {
1530  my_decimal decimal_value, *val;
1531  lldiv_t tmp;
1532  if (!(val= args->val_decimal(&decimal_value)) ||
1533  my_decimal2lldiv_t(E_DEC_FATAL_ERROR, val, &tmp))
1534  return false;
1535 
1536  if (tmp.quot >= 0 && tmp.rem >= 0)
1537  {
1538  interval->neg= false;
1539  interval->second= tmp.quot;
1540  interval->second_part= tmp.rem / 1000;
1541  }
1542  else
1543  {
1544  interval->neg= true;
1545  interval->second= -tmp.quot;
1546  interval->second_part= -tmp.rem / 1000;
1547  }
1548  return false;
1549  }
1550  else if (int_type <= INTERVAL_MICROSECOND)
1551  {
1552  value= args->val_int();
1553  if (args->null_value)
1554  return true;
1555  if (value < 0)
1556  {
1557  interval->neg= true;
1558  value= -value;
1559  }
1560  }
1561 
1562  switch (int_type) {
1563  case INTERVAL_YEAR:
1564  interval->year= (ulong) value;
1565  break;
1566  case INTERVAL_QUARTER:
1567  interval->month= (ulong)(value*3);
1568  break;
1569  case INTERVAL_MONTH:
1570  interval->month= (ulong) value;
1571  break;
1572  case INTERVAL_WEEK:
1573  interval->day= (ulong)(value*7);
1574  break;
1575  case INTERVAL_DAY:
1576  interval->day= (ulong) value;
1577  break;
1578  case INTERVAL_HOUR:
1579  interval->hour= (ulong) value;
1580  break;
1581  case INTERVAL_MINUTE:
1582  interval->minute=value;
1583  break;
1584  case INTERVAL_SECOND:
1585  interval->second=value;
1586  break;
1587  case INTERVAL_MICROSECOND:
1588  interval->second_part=value;
1589  break;
1590  case INTERVAL_YEAR_MONTH: // Allow YEAR-MONTH YYYYYMM
1591  if (get_interval_info(args, str_value, &interval->neg, 2, array, false))
1592  return true;
1593  interval->year= (ulong) array[0];
1594  interval->month= (ulong) array[1];
1595  break;
1596  case INTERVAL_DAY_HOUR:
1597  if (get_interval_info(args, str_value, &interval->neg, 2, array, false))
1598  return true;
1599  interval->day= (ulong) array[0];
1600  interval->hour= (ulong) array[1];
1601  break;
1602  case INTERVAL_DAY_MINUTE:
1603  if (get_interval_info(args, str_value, &interval->neg, 3, array, false))
1604  return true;
1605  interval->day= (ulong) array[0];
1606  interval->hour= (ulong) array[1];
1607  interval->minute= array[2];
1608  break;
1609  case INTERVAL_DAY_SECOND:
1610  if (get_interval_info(args, str_value, &interval->neg, 4, array, false))
1611  return true;
1612  interval->day= (ulong) array[0];
1613  interval->hour= (ulong) array[1];
1614  interval->minute= array[2];
1615  interval->second= array[3];
1616  break;
1617  case INTERVAL_HOUR_MINUTE:
1618  if (get_interval_info(args, str_value, &interval->neg, 2, array, false))
1619  return true;
1620  interval->hour= (ulong) array[0];
1621  interval->minute= array[1];
1622  break;
1623  case INTERVAL_HOUR_SECOND:
1624  if (get_interval_info(args, str_value, &interval->neg, 3, array, false))
1625  return true;
1626  interval->hour= (ulong) array[0];
1627  interval->minute= array[1];
1628  interval->second= array[2];
1629  break;
1630  case INTERVAL_MINUTE_SECOND:
1631  if (get_interval_info(args, str_value, &interval->neg, 2, array, false))
1632  return true;
1633  interval->minute= array[0];
1634  interval->second= array[1];
1635  break;
1636  case INTERVAL_DAY_MICROSECOND:
1637  if (get_interval_info(args, str_value, &interval->neg, 5, array, true))
1638  return true;
1639  interval->day= (ulong) array[0];
1640  interval->hour= (ulong) array[1];
1641  interval->minute= array[2];
1642  interval->second= array[3];
1643  interval->second_part= array[4];
1644  break;
1645  case INTERVAL_HOUR_MICROSECOND:
1646  if (get_interval_info(args, str_value, &interval->neg, 4, array, true))
1647  return true;
1648  interval->hour= (ulong) array[0];
1649  interval->minute= array[1];
1650  interval->second= array[2];
1651  interval->second_part= array[3];
1652  break;
1653  case INTERVAL_MINUTE_MICROSECOND:
1654  if (get_interval_info(args, str_value, &interval->neg, 3, array, true))
1655  return true;
1656  interval->minute= array[0];
1657  interval->second= array[1];
1658  interval->second_part= array[2];
1659  break;
1660  case INTERVAL_SECOND_MICROSECOND:
1661  if (get_interval_info(args, str_value, &interval->neg, 2, array, true))
1662  return true;
1663  interval->second= array[0];
1664  interval->second_part= array[1];
1665  break;
1666  case INTERVAL_LAST: /* purecov: begin deadcode */
1667  DBUG_ASSERT(0);
1668  break; /* purecov: end */
1669  }
1670  return false;
1671 }
1672 
1673 
1674 bool Item_func_from_days::get_date(MYSQL_TIME *ltime, uint fuzzy_date)
1675 {
1676  longlong value=args[0]->val_int();
1677  if ((null_value=args[0]->null_value))
1678  return 1;
1679  memset(ltime, 0, sizeof(MYSQL_TIME));
1680  get_date_from_daynr((long) value, &ltime->year, &ltime->month, &ltime->day);
1681 
1682  if ((null_value= (fuzzy_date & TIME_NO_ZERO_DATE) &&
1683  (ltime->year == 0 || ltime->month == 0 || ltime->day == 0)))
1684  return TRUE;
1685 
1686  ltime->time_type= MYSQL_TIMESTAMP_DATE;
1687  return 0;
1688 }
1689 
1690 
1691 void MYSQL_TIME_cache::set_time(MYSQL_TIME *ltime, uint8 dec_arg)
1692 {
1693  DBUG_ASSERT(ltime->time_type == MYSQL_TIMESTAMP_TIME);
1694  time= *ltime;
1695  time_packed= TIME_to_longlong_time_packed(&time);
1696  dec= dec_arg;
1697  reset_string();
1698 }
1699 
1700 
1702 {
1703  DBUG_ASSERT(ltime->time_type == MYSQL_TIMESTAMP_DATE);
1704  time= *ltime;
1705  time_packed= TIME_to_longlong_date_packed(&time);
1706  dec= 0;
1707  reset_string();
1708 }
1709 
1710 
1711 void MYSQL_TIME_cache::set_datetime(MYSQL_TIME *ltime, uint8 dec_arg)
1712 {
1713  DBUG_ASSERT(ltime->time_type == MYSQL_TIMESTAMP_DATETIME);
1714  time= *ltime;
1715  time_packed= TIME_to_longlong_datetime_packed(&time);
1716  dec= dec_arg;
1717  reset_string();
1718 }
1719 
1720 
1721 void MYSQL_TIME_cache::set_datetime(struct timeval tv, uint8 dec_arg,
1722  Time_zone *tz)
1723 {
1724  tz->gmt_sec_to_TIME(&time, tv);
1725  time_packed= TIME_to_longlong_datetime_packed(&time);
1726  dec= dec_arg;
1727  reset_string();
1728 }
1729 
1730 
1732 {
1733  tz->gmt_sec_to_TIME(&time, (my_time_t) tv.tv_sec);
1734  time.time_type= MYSQL_TIMESTAMP_DATE;
1735  /* We don't need to set second_part and neg because they are already 0 */
1736  time.hour= time.minute= time.second= 0;
1737  time_packed= TIME_to_longlong_date_packed(&time);
1738  dec= 0;
1739  reset_string();
1740 }
1741 
1742 
1743 void MYSQL_TIME_cache::set_time(struct timeval tv, uint8 dec_arg,
1744  Time_zone *tz)
1745 {
1746  tz->gmt_sec_to_TIME(&time, tv);
1747  datetime_to_time(&time);
1748  time_packed= TIME_to_longlong_time_packed(&time);
1749  dec= dec_arg;
1750  reset_string();
1751 }
1752 
1753 
1754 void MYSQL_TIME_cache::cache_string()
1755 {
1756  DBUG_ASSERT(time.time_type != MYSQL_TIMESTAMP_NONE);
1757  if (string_length == 0)
1758  string_length= my_TIME_to_str(&time, string_buff, decimals());
1759 }
1760 
1761 
1763 {
1764  cache_string();
1765  return string_buff;
1766 }
1767 
1768 
1769 bool MYSQL_TIME_cache::get_date(MYSQL_TIME *ltime, uint fuzzydate) const
1770 {
1771  int warnings;
1772  get_TIME(ltime);
1773  return check_date(ltime, non_zero_date(ltime), fuzzydate, &warnings);
1774 }
1775 
1776 
1778 {
1779  cache_string();
1780  str->set(string_buff, string_length, &my_charset_latin1);
1781  return str;
1782 }
1783 
1784 
1785 /* CURDATE() and UTC_DATE() */
1786 void Item_func_curdate::fix_length_and_dec()
1787 {
1788  THD *thd= current_thd;
1789  Item_date_func::fix_length_and_dec();
1790  cached_time.set_date(thd->query_start_timeval_trunc(decimals), time_zone());
1791 }
1792 
1793 
1794 Time_zone *Item_func_curdate_local::time_zone()
1795 {
1796  return current_thd->time_zone();
1797 }
1798 
1799 
1800 Time_zone *Item_func_curdate_utc::time_zone()
1801 {
1802  return my_tz_UTC;
1803 }
1804 
1805 
1806 /* CURTIME() and UTC_TIME() */
1807 void Item_func_curtime::fix_length_and_dec()
1808 {
1809  if (check_precision())
1810  return;
1811  THD *thd= current_thd;
1812  cached_time.set_time(thd->query_start_timeval_trunc(decimals), decimals,
1813  time_zone());
1814  /*
1815  We use 8 instead of MAX_TIME_WIDTH (which is 10) because:
1816  - there is no sign
1817  - hour is in the 2-digit range
1818  */
1819  fix_length_and_dec_and_charset_datetime(8, decimals);
1820 }
1821 
1822 
1823 Time_zone *Item_func_curtime_local::time_zone()
1824 {
1825  return current_thd->time_zone();
1826 }
1827 
1828 
1829 Time_zone *Item_func_curtime_utc::time_zone()
1830 {
1831  return my_tz_UTC;
1832 }
1833 
1834 
1835 /* NOW() and UTC_TIMESTAMP () */
1836 
1837 void Item_func_now::fix_length_and_dec()
1838 {
1839  if (check_precision())
1840  return;
1841  THD *thd= current_thd;
1842  cached_time.set_datetime(thd->query_start_timeval_trunc(decimals), decimals,
1843  time_zone());
1844  fix_length_and_dec_and_charset_datetime(MAX_DATETIME_WIDTH, decimals);
1845 }
1846 
1847 
1849 {
1850  THD *thd= field->table != NULL ? field->table->in_use : current_thd;
1851  const timeval tm= thd->query_start_timeval_trunc(field->decimals());
1852  field->set_notnull();
1853  return field->store_timestamp(&tm);
1854 }
1855 
1856 
1857 Time_zone *Item_func_now_local::time_zone()
1858 {
1859  return current_thd->time_zone();
1860 }
1861 
1862 
1863 Time_zone *Item_func_now_utc::time_zone()
1864 {
1865  return my_tz_UTC;
1866 }
1867 
1868 
1869 type_conversion_status
1870 Item_func_now::save_in_field(Field *to, bool no_conversions)
1871 {
1872  to->set_notnull();
1873  return to->store_time(cached_time.get_TIME_ptr(), decimals);
1874 }
1875 
1876 
1882  uint fuzzy_date __attribute__((unused)))
1883 {
1884  THD *thd= current_thd;
1885  ulonglong tmp= my_micro_time();
1886  thd->time_zone()->gmt_sec_to_TIME(now_time,
1887  (my_time_t) (tmp / 1000000));
1888  if (decimals)
1889  {
1890  now_time->second_part= tmp % 1000000;
1891  my_datetime_trunc(now_time, decimals);
1892  }
1893  return false;
1894 }
1895 
1896 
1897 void Item_func_sysdate_local::fix_length_and_dec()
1898 {
1899  if (check_precision())
1900  return;
1901  fix_length_and_dec_and_charset_datetime(MAX_DATETIME_WIDTH, decimals);
1902 }
1903 
1904 
1905 bool Item_func_sec_to_time::get_time(MYSQL_TIME *ltime)
1906 {
1907  my_decimal tmp, *val= args[0]->val_decimal(&tmp);
1908  lldiv_t seconds;
1909  if ((null_value= args[0]->null_value))
1910  return true;
1911  if (my_decimal2lldiv_t(0, val, &seconds))
1912  {
1913  set_max_time(ltime, val->sign());
1914  make_truncated_value_warning(ErrConvString(val), MYSQL_TIMESTAMP_TIME);
1915  return false;
1916  }
1917  if (sec_to_time(seconds, ltime))
1918  make_truncated_value_warning(ErrConvString(val),
1919  MYSQL_TIMESTAMP_TIME);
1920  return false;
1921 }
1922 
1923 
1924 void Item_func_date_format::fix_length_and_dec()
1925 {
1926  THD* thd= current_thd;
1927  /*
1928  Must use this_item() in case it's a local SP variable
1929  (for ->max_length and ->str_value)
1930  */
1931  Item *arg1= args[1]->this_item();
1932 
1933  decimals=0;
1934  const CHARSET_INFO *cs= thd->variables.collation_connection;
1935  uint32 repertoire= arg1->collation.repertoire;
1936  if (!thd->variables.lc_time_names->is_ascii)
1937  repertoire|= MY_REPERTOIRE_EXTENDED;
1938  collation.set(cs, arg1->collation.derivation, repertoire);
1939  if (arg1->type() == STRING_ITEM)
1940  { // Optimize the normal case
1941  fixed_length=1;
1942  max_length= format_length(&arg1->str_value) *
1943  collation.collation->mbmaxlen;
1944  }
1945  else
1946  {
1947  fixed_length=0;
1948  max_length= min<uint32>(arg1->max_length, MAX_BLOB_WIDTH) * 10 *
1949  collation.collation->mbmaxlen;
1950  set_if_smaller(max_length,MAX_BLOB_WIDTH);
1951  }
1952  maybe_null=1; // If wrong date
1953 }
1954 
1955 
1956 bool Item_func_date_format::eq(const Item *item, bool binary_cmp) const
1957 {
1958  Item_func_date_format *item_func;
1959 
1960  if (item->type() != FUNC_ITEM)
1961  return 0;
1962  if (func_name() != ((Item_func*) item)->func_name())
1963  return 0;
1964  if (this == item)
1965  return 1;
1966  item_func= (Item_func_date_format*) item;
1967  if (!args[0]->eq(item_func->args[0], binary_cmp))
1968  return 0;
1969  /*
1970  We must compare format string case sensitive.
1971  This needed because format modifiers with different case,
1972  for example %m and %M, have different meaning.
1973  */
1974  if (!args[1]->eq(item_func->args[1], 1))
1975  return 0;
1976  return 1;
1977 }
1978 
1979 
1980 
1981 uint Item_func_date_format::format_length(const String *format)
1982 {
1983  uint size=0;
1984  const char *ptr=format->ptr();
1985  const char *end=ptr+format->length();
1986 
1987  for (; ptr != end ; ptr++)
1988  {
1989  if (*ptr != '%' || ptr == end-1)
1990  size++;
1991  else
1992  {
1993  switch(*++ptr) {
1994  case 'M': /* month, textual */
1995  case 'W': /* day (of the week), textual */
1996  size += 64; /* large for UTF8 locale data */
1997  break;
1998  case 'D': /* day (of the month), numeric plus english suffix */
1999  case 'Y': /* year, numeric, 4 digits */
2000  case 'x': /* Year, used with 'v' */
2001  case 'X': /* Year, used with 'v, where week starts with Monday' */
2002  size += 4;
2003  break;
2004  case 'a': /* locale's abbreviated weekday name (Sun..Sat) */
2005  case 'b': /* locale's abbreviated month name (Jan.Dec) */
2006  size += 32; /* large for UTF8 locale data */
2007  break;
2008  case 'j': /* day of year (001..366) */
2009  size += 3;
2010  break;
2011  case 'U': /* week (00..52) */
2012  case 'u': /* week (00..52), where week starts with Monday */
2013  case 'V': /* week 1..53 used with 'x' */
2014  case 'v': /* week 1..53 used with 'x', where week starts with Monday */
2015  case 'y': /* year, numeric, 2 digits */
2016  case 'm': /* month, numeric */
2017  case 'd': /* day (of the month), numeric */
2018  case 'h': /* hour (01..12) */
2019  case 'I': /* --||-- */
2020  case 'i': /* minutes, numeric */
2021  case 'l': /* hour ( 1..12) */
2022  case 'p': /* locale's AM or PM */
2023  case 'S': /* second (00..61) */
2024  case 's': /* seconds, numeric */
2025  case 'c': /* month (0..12) */
2026  case 'e': /* day (0..31) */
2027  size += 2;
2028  break;
2029  case 'k': /* hour ( 0..23) */
2030  case 'H': /* hour (00..23; value > 23 OK, padding always 2-digit) */
2031  size += 7; /* docs allow > 23, range depends on sizeof(unsigned int) */
2032  break;
2033  case 'r': /* time, 12-hour (hh:mm:ss [AP]M) */
2034  size += 11;
2035  break;
2036  case 'T': /* time, 24-hour (hh:mm:ss) */
2037  size += 8;
2038  break;
2039  case 'f': /* microseconds */
2040  size += 6;
2041  break;
2042  case 'w': /* day (of the week), numeric */
2043  case '%':
2044  default:
2045  size++;
2046  break;
2047  }
2048  }
2049  }
2050  return size;
2051 }
2052 
2053 
2054 String *Item_func_date_format::val_str(String *str)
2055 {
2056  String *format;
2057  MYSQL_TIME l_time;
2058  uint size;
2059  DBUG_ASSERT(fixed == 1);
2060 
2061  if (!is_time_format)
2062  {
2063  if (get_arg0_date(&l_time, TIME_FUZZY_DATE))
2064  return 0;
2065  }
2066  else
2067  {
2068  if (get_arg0_time(&l_time))
2069  return 0;
2070  l_time.year=l_time.month=l_time.day=0;
2071  }
2072 
2073  if (!(format = args[1]->val_str(str)) || !format->length())
2074  goto null_date;
2075 
2076  if (fixed_length)
2077  size=max_length;
2078  else
2079  size=format_length(format);
2080 
2081  if (size < MAX_DATE_STRING_REP_LENGTH)
2082  size= MAX_DATE_STRING_REP_LENGTH;
2083 
2084  if (format == str)
2085  str= &value; // Save result here
2086  if (str->alloc(size))
2087  goto null_date;
2088 
2089  DATE_TIME_FORMAT date_time_format;
2090  date_time_format.format.str= (char*) format->ptr();
2091  date_time_format.format.length= format->length();
2092 
2093  /* Create the result string */
2094  str->set_charset(collation.collation);
2095  if (!make_date_time(&date_time_format, &l_time,
2096  is_time_format ? MYSQL_TIMESTAMP_TIME :
2097  MYSQL_TIMESTAMP_DATE,
2098  str))
2099  return str;
2100 
2101 null_date:
2102  null_value=1;
2103  return 0;
2104 }
2105 
2106 
2107 void Item_func_from_unixtime::fix_length_and_dec()
2108 {
2109  thd= current_thd;
2110  uint8 dec= MY_MIN(args[0]->decimals, DATETIME_MAX_DECIMALS);
2111  fix_length_and_dec_and_charset_datetime(MAX_DATETIME_WIDTH, dec);
2112  maybe_null= 1;
2113  thd->time_zone_used= 1;
2114 }
2115 
2116 
2117 bool Item_func_from_unixtime::get_date(MYSQL_TIME *ltime,
2118  uint fuzzy_date __attribute__((unused)))
2119 {
2120  lldiv_t lld;
2121  if (decimals)
2122  {
2123  my_decimal *val, decimal_value;
2124  if (!(val= args[0]->val_decimal(&decimal_value)) ||
2125  my_decimal2lldiv_t(E_DEC_FATAL_ERROR, val, &lld))
2126  {
2127  null_value= 1;
2128  return true;
2129  }
2130  }
2131  else
2132  {
2133  lld.quot= args[0]->val_int();
2134  lld.rem= 0;
2135  }
2136 
2137  if ((null_value= (args[0]->null_value ||
2138  lld.quot > TIMESTAMP_MAX_VALUE) || lld.quot < 0 || lld.rem < 0))
2139  return 1;
2140 
2141  thd->variables.time_zone->gmt_sec_to_TIME(ltime, (my_time_t) lld.quot);
2142  int warnings= 0;
2143  ltime->second_part= decimals ? lld.rem / 1000 : 0;
2144  return datetime_add_nanoseconds_with_round(ltime, lld.rem % 1000, &warnings);
2145 }
2146 
2147 
2148 void Item_func_convert_tz::fix_length_and_dec()
2149 {
2150  fix_length_and_dec_and_charset_datetime(MAX_DATETIME_WIDTH,
2151  args[0]->datetime_precision());
2152  maybe_null= 1;
2153 }
2154 
2155 
2156 bool Item_func_convert_tz::get_date(MYSQL_TIME *ltime,
2157  uint fuzzy_date __attribute__((unused)))
2158 {
2159  my_time_t my_time_tmp;
2160  String str;
2161  THD *thd= current_thd;
2162 
2163  if (!from_tz_cached)
2164  {
2165  from_tz= my_tz_find(thd, args[1]->val_str_ascii(&str));
2166  from_tz_cached= args[1]->const_item();
2167  }
2168 
2169  if (!to_tz_cached)
2170  {
2171  to_tz= my_tz_find(thd, args[2]->val_str_ascii(&str));
2172  to_tz_cached= args[2]->const_item();
2173  }
2174 
2175  if (from_tz==0 || to_tz==0 || get_arg0_date(ltime, TIME_NO_ZERO_DATE))
2176  {
2177  null_value= 1;
2178  return 1;
2179  }
2180 
2181  {
2182  my_bool not_used;
2183  uint second_part= ltime->second_part;
2184  my_time_tmp= from_tz->TIME_to_gmt_sec(ltime, &not_used);
2185  /* my_time_tmp is guranteed to be in the allowed range */
2186  if (my_time_tmp)
2187  {
2188  to_tz->gmt_sec_to_TIME(ltime, my_time_tmp);
2189  ltime->second_part= second_part;
2190  }
2191  }
2192 
2193  null_value= 0;
2194  return 0;
2195 }
2196 
2197 
2198 void Item_func_convert_tz::cleanup()
2199 {
2200  from_tz_cached= to_tz_cached= 0;
2201  Item_datetime_func::cleanup();
2202 }
2203 
2204 
2205 void Item_date_add_interval::fix_length_and_dec()
2206 {
2207  enum_field_types arg0_field_type;
2208 
2209  maybe_null=1;
2210 
2211  /*
2212  The field type for the result of an Item_date function is defined as
2213  follows:
2214 
2215  - If first arg is a MYSQL_TYPE_DATETIME result is MYSQL_TYPE_DATETIME
2216  - If first arg is a MYSQL_TYPE_DATE and the interval type uses hours,
2217  minutes or seconds then type is MYSQL_TYPE_DATETIME.
2218  - Otherwise the result is MYSQL_TYPE_STRING
2219  (This is because you can't know if the string contains a DATE, MYSQL_TIME or
2220  DATETIME argument)
2221  */
2222  arg0_field_type= args[0]->field_type();
2223  uint8 interval_dec= 0;
2224  if (int_type == INTERVAL_MICROSECOND ||
2225  (int_type >= INTERVAL_DAY_MICROSECOND &&
2226  int_type <= INTERVAL_SECOND_MICROSECOND))
2227  interval_dec= DATETIME_MAX_DECIMALS;
2228  else if (int_type == INTERVAL_SECOND && args[1]->decimals > 0)
2229  interval_dec= MY_MIN(args[1]->decimals, DATETIME_MAX_DECIMALS);
2230 
2231  if (arg0_field_type == MYSQL_TYPE_DATETIME ||
2232  arg0_field_type == MYSQL_TYPE_TIMESTAMP)
2233  {
2234  uint8 dec= MY_MAX(args[0]->datetime_precision(), interval_dec);
2235  fix_length_and_dec_and_charset_datetime(MAX_DATETIME_WIDTH, dec);
2236  cached_field_type= MYSQL_TYPE_DATETIME;
2237  }
2238  else if (arg0_field_type == MYSQL_TYPE_DATE)
2239  {
2240  if (int_type <= INTERVAL_DAY || int_type == INTERVAL_YEAR_MONTH)
2241  {
2242  cached_field_type= MYSQL_TYPE_DATE;
2243  fix_length_and_dec_and_charset_datetime(MAX_DATE_WIDTH, 0);
2244  }
2245  else
2246  {
2247  cached_field_type= MYSQL_TYPE_DATETIME;
2248  fix_length_and_dec_and_charset_datetime(MAX_DATE_WIDTH, interval_dec);
2249  }
2250  }
2251  else if (arg0_field_type == MYSQL_TYPE_TIME)
2252  {
2253  uint8 dec= MY_MAX(args[0]->time_precision(), interval_dec);
2254  cached_field_type= MYSQL_TYPE_TIME;
2255  fix_length_and_dec_and_charset_datetime(MAX_TIME_WIDTH, dec);
2256  }
2257  else
2258  {
2259  cached_field_type= MYSQL_TYPE_STRING;
2260  /* Behave as a usual string function when return type is VARCHAR. */
2261  fix_length_and_charset(MAX_DATETIME_FULL_WIDTH, default_charset());
2262  }
2263  value.alloc(max_length);
2264 }
2265 
2266 
2267 /* Here arg[1] is a Item_interval object */
2268 bool Item_date_add_interval::get_date_internal(MYSQL_TIME *ltime,
2269  uint fuzzy_date)
2270 {
2271  INTERVAL interval;
2272 
2273  if (args[0]->get_date(ltime, TIME_NO_ZERO_DATE) ||
2274  get_interval_value(args[1], int_type, &value, &interval))
2275  return (null_value= true);
2276 
2277  if (date_sub_interval)
2278  interval.neg = !interval.neg;
2279 
2280  /*
2281  Make sure we return proper time_type.
2282  It's important for val_str().
2283  */
2284  if (cached_field_type == MYSQL_TYPE_DATE &&
2285  ltime->time_type == MYSQL_TIMESTAMP_DATETIME)
2286  datetime_to_date(ltime);
2287  else if (cached_field_type == MYSQL_TYPE_DATETIME &&
2288  ltime->time_type == MYSQL_TIMESTAMP_DATE)
2289  date_to_datetime(ltime);
2290 
2291  if ((null_value= date_add_interval(ltime, int_type, interval)))
2292  return true;
2293  return false;
2294 }
2295 
2296 
2297 bool Item_date_add_interval::get_time_internal(MYSQL_TIME *ltime)
2298 {
2299  INTERVAL interval;
2300 
2301  if ((null_value= args[0]->get_time(ltime) ||
2302  get_interval_value(args[1], int_type, &value, &interval)))
2303  return true;
2304 
2305  if (date_sub_interval)
2306  interval.neg= !interval.neg;
2307 
2308  DBUG_ASSERT(!check_time_range_quick(ltime));
2309 
2310  longlong usec1= ((((ltime->day * 24 + ltime->hour) * 60 +
2311  ltime->minute) * 60 + ltime->second) * 1000000LL +
2312  ltime->second_part) *
2313  (ltime->neg ? -1 : 1);
2314  longlong usec2= ((((interval.day * 24 + interval.hour) * 60 +
2315  interval.minute) * 60 + interval.second) * 1000000LL +
2316  interval.second_part) *
2317  (interval.neg ? -1 : 1);
2318  longlong diff= usec1 + usec2;
2319  lldiv_t seconds;
2320  seconds.quot= diff / 1000000;
2321  seconds.rem= diff % 1000000 * 1000; /* time->second_part= lldiv.rem / 1000 */
2322  if ((null_value= (interval.year || interval.month ||
2323  sec_to_time(seconds, ltime))))
2324  {
2325  push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
2326  ER_DATETIME_FUNCTION_OVERFLOW,
2327  ER(ER_DATETIME_FUNCTION_OVERFLOW),
2328  "time");
2329  return true;
2330  }
2331  return false;
2332 }
2333 
2334 
2336 {
2337  if (cached_field_type != MYSQL_TYPE_TIME)
2338  return get_date_internal(ltime, fuzzy_date | TIME_NO_ZERO_DATE);
2339  return get_time_internal(ltime);
2340 }
2341 
2342 
2343 bool Item_date_add_interval::eq(const Item *item, bool binary_cmp) const
2344 {
2346  if (!Item_func::eq(item, binary_cmp))
2347  return 0;
2348  return ((int_type == other->int_type) &&
2349  (date_sub_interval == other->date_sub_interval));
2350 }
2351 
2352 /*
2353  'interval_names' reflects the order of the enumeration interval_type.
2354  See item_timefunc.h
2355  */
2356 
2357 static const char *interval_names[]=
2358 {
2359  "year", "quarter", "month", "week", "day",
2360  "hour", "minute", "second", "microsecond",
2361  "year_month", "day_hour", "day_minute",
2362  "day_second", "hour_minute", "hour_second",
2363  "minute_second", "day_microsecond",
2364  "hour_microsecond", "minute_microsecond",
2365  "second_microsecond"
2366 };
2367 
2368 void Item_date_add_interval::print(String *str, enum_query_type query_type)
2369 {
2370  str->append('(');
2371  args[0]->print(str, query_type);
2372  str->append(date_sub_interval?" - interval ":" + interval ");
2373  args[1]->print(str, query_type);
2374  str->append(' ');
2375  str->append(interval_names[int_type]);
2376  str->append(')');
2377 }
2378 
2379 void Item_extract::print(String *str, enum_query_type query_type)
2380 {
2381  str->append(STRING_WITH_LEN("extract("));
2382  str->append(interval_names[int_type]);
2383  str->append(STRING_WITH_LEN(" from "));
2384  args[0]->print(str, query_type);
2385  str->append(')');
2386 }
2387 
2388 void Item_extract::fix_length_and_dec()
2389 {
2390  maybe_null=1; // If wrong date
2391  switch (int_type) {
2392  case INTERVAL_YEAR: max_length=4; date_value=1; break;
2393  case INTERVAL_YEAR_MONTH: max_length=6; date_value=1; break;
2394  case INTERVAL_QUARTER: max_length=2; date_value=1; break;
2395  case INTERVAL_MONTH: max_length=2; date_value=1; break;
2396  case INTERVAL_WEEK: max_length=2; date_value=1; break;
2397  case INTERVAL_DAY: max_length=2; date_value=1; break;
2398  case INTERVAL_DAY_HOUR: max_length=9; date_value=0; break;
2399  case INTERVAL_DAY_MINUTE: max_length=11; date_value=0; break;
2400  case INTERVAL_DAY_SECOND: max_length=13; date_value=0; break;
2401  case INTERVAL_HOUR: max_length=2; date_value=0; break;
2402  case INTERVAL_HOUR_MINUTE: max_length=4; date_value=0; break;
2403  case INTERVAL_HOUR_SECOND: max_length=6; date_value=0; break;
2404  case INTERVAL_MINUTE: max_length=2; date_value=0; break;
2405  case INTERVAL_MINUTE_SECOND: max_length=4; date_value=0; break;
2406  case INTERVAL_SECOND: max_length=2; date_value=0; break;
2407  case INTERVAL_MICROSECOND: max_length=2; date_value=0; break;
2408  case INTERVAL_DAY_MICROSECOND: max_length=20; date_value=0; break;
2409  case INTERVAL_HOUR_MICROSECOND: max_length=13; date_value=0; break;
2410  case INTERVAL_MINUTE_MICROSECOND: max_length=11; date_value=0; break;
2411  case INTERVAL_SECOND_MICROSECOND: max_length=9; date_value=0; break;
2412  case INTERVAL_LAST: DBUG_ASSERT(0); break; /* purecov: deadcode */
2413  }
2414 }
2415 
2416 
2417 longlong Item_extract::val_int()
2418 {
2419  DBUG_ASSERT(fixed == 1);
2420  MYSQL_TIME ltime;
2421  uint year;
2422  ulong week_format;
2423  long neg;
2424  if (date_value)
2425  {
2426  if (get_arg0_date(&ltime, TIME_FUZZY_DATE))
2427  return 0;
2428  neg=1;
2429  }
2430  else
2431  {
2432  if (get_arg0_time(&ltime))
2433  return 0;
2434  neg= ltime.neg ? -1 : 1;
2435  }
2436  switch (int_type) {
2437  case INTERVAL_YEAR: return ltime.year;
2438  case INTERVAL_YEAR_MONTH: return ltime.year*100L+ltime.month;
2439  case INTERVAL_QUARTER: return (ltime.month+2)/3;
2440  case INTERVAL_MONTH: return ltime.month;
2441  case INTERVAL_WEEK:
2442  {
2443  week_format= current_thd->variables.default_week_format;
2444  return calc_week(&ltime, week_mode(week_format), &year);
2445  }
2446  case INTERVAL_DAY: return ltime.day;
2447  case INTERVAL_DAY_HOUR: return (long) (ltime.day*100L+ltime.hour)*neg;
2448  case INTERVAL_DAY_MINUTE: return (long) (ltime.day*10000L+
2449  ltime.hour*100L+
2450  ltime.minute)*neg;
2451  case INTERVAL_DAY_SECOND: return ((longlong) ltime.day*1000000L+
2452  (longlong) (ltime.hour*10000L+
2453  ltime.minute*100+
2454  ltime.second))*neg;
2455  case INTERVAL_HOUR: return (long) ltime.hour*neg;
2456  case INTERVAL_HOUR_MINUTE: return (long) (ltime.hour*100+ltime.minute)*neg;
2457  case INTERVAL_HOUR_SECOND: return (long) (ltime.hour*10000+ltime.minute*100+
2458  ltime.second)*neg;
2459  case INTERVAL_MINUTE: return (long) ltime.minute*neg;
2460  case INTERVAL_MINUTE_SECOND: return (long) (ltime.minute*100+ltime.second)*neg;
2461  case INTERVAL_SECOND: return (long) ltime.second*neg;
2462  case INTERVAL_MICROSECOND: return (long) ltime.second_part*neg;
2463  case INTERVAL_DAY_MICROSECOND: return (((longlong)ltime.day*1000000L +
2464  (longlong)ltime.hour*10000L +
2465  ltime.minute*100 +
2466  ltime.second)*1000000L +
2467  ltime.second_part)*neg;
2468  case INTERVAL_HOUR_MICROSECOND: return (((longlong)ltime.hour*10000L +
2469  ltime.minute*100 +
2470  ltime.second)*1000000L +
2471  ltime.second_part)*neg;
2472  case INTERVAL_MINUTE_MICROSECOND: return (((longlong)(ltime.minute*100+
2473  ltime.second))*1000000L+
2474  ltime.second_part)*neg;
2475  case INTERVAL_SECOND_MICROSECOND: return ((longlong)ltime.second*1000000L+
2476  ltime.second_part)*neg;
2477  case INTERVAL_LAST: DBUG_ASSERT(0); break; /* purecov: deadcode */
2478  }
2479  return 0; // Impossible
2480 }
2481 
2482 bool Item_extract::eq(const Item *item, bool binary_cmp) const
2483 {
2484  if (this == item)
2485  return 1;
2486  if (item->type() != FUNC_ITEM ||
2487  functype() != ((Item_func*)item)->functype())
2488  return 0;
2489 
2490  Item_extract* ie= (Item_extract*)item;
2491  if (ie->int_type != int_type)
2492  return 0;
2493 
2494  if (!args[0]->eq(ie->args[0], binary_cmp))
2495  return 0;
2496  return 1;
2497 }
2498 
2499 
2500 void Item_datetime_typecast::print(String *str, enum_query_type query_type)
2501 {
2502  str->append(STRING_WITH_LEN("cast("));
2503  args[0]->print(str, query_type);
2504  str->append(STRING_WITH_LEN(" as "));
2505  str->append(cast_type());
2506  if (decimals)
2507  str->append_parenthesized(decimals);
2508  str->append(')');
2509 }
2510 
2511 
2512 bool Item_datetime_typecast::get_date(MYSQL_TIME *ltime, uint fuzzy_date)
2513 {
2514  if ((null_value= args[0]->get_date(ltime, fuzzy_date | TIME_NO_DATE_FRAC_WARN)))
2515  return true;
2516  DBUG_ASSERT(ltime->time_type != MYSQL_TIMESTAMP_TIME);
2517  ltime->time_type= MYSQL_TIMESTAMP_DATETIME; // In case it was DATE
2518  int warnings= 0;
2519  return (null_value= my_datetime_round(ltime, decimals, &warnings));
2520 }
2521 
2522 
2523 void Item_time_typecast::print(String *str, enum_query_type query_type)
2524 {
2525  str->append(STRING_WITH_LEN("cast("));
2526  args[0]->print(str, query_type);
2527  str->append(STRING_WITH_LEN(" as "));
2528  str->append(cast_type());
2529  if (decimals)
2530  str->append_parenthesized(decimals);
2531  str->append(')');
2532 }
2533 
2534 
2535 bool Item_time_typecast::get_time(MYSQL_TIME *ltime)
2536 {
2537  if (get_arg0_time(ltime))
2538  return true;
2539  my_time_round(ltime, decimals);
2540  /*
2541  For MYSQL_TIMESTAMP_TIME value we can have non-zero day part,
2542  which we should not lose.
2543  */
2544  if (ltime->time_type != MYSQL_TIMESTAMP_TIME)
2545  datetime_to_time(ltime);
2546  return false;
2547 }
2548 
2549 
2550 void Item_date_typecast::print(String *str, enum_query_type query_type)
2551 {
2552  str->append(STRING_WITH_LEN("cast("));
2553  args[0]->print(str, query_type);
2554  str->append(STRING_WITH_LEN(" as "));
2555  str->append(cast_type());
2556  str->append(')');
2557 }
2558 
2559 
2560 bool Item_date_typecast::get_date(MYSQL_TIME *ltime, uint fuzzy_date)
2561 {
2562  bool res= get_arg0_date(ltime, fuzzy_date | TIME_NO_DATE_FRAC_WARN);
2563  ltime->hour= ltime->minute= ltime->second= ltime->second_part= 0;
2564  ltime->time_type= MYSQL_TIMESTAMP_DATE;
2565  return res;
2566 }
2567 
2568 
2579 bool Item_func_makedate::get_date(MYSQL_TIME *ltime, uint fuzzy_date)
2580 {
2581  DBUG_ASSERT(fixed == 1);
2582  long daynr= (long) args[1]->val_int();
2583  long year= (long) args[0]->val_int();
2584  long days;
2585 
2586  if (args[0]->null_value || args[1]->null_value ||
2587  year < 0 || year > 9999 || daynr <= 0)
2588  goto err;
2589 
2590  if (year < 100)
2591  year= year_2000_handling(year);
2592 
2593  days= calc_daynr(year, 1, 1) + daynr - 1;
2594  /* Day number from year 0 to 9999-12-31 */
2595  if (days >= 0 && days <= MAX_DAY_NUMBER)
2596  {
2597  null_value= 0;
2598  get_date_from_daynr(days, &ltime->year, &ltime->month, &ltime->day);
2599  ltime->neg= 0;
2600  ltime->hour= ltime->minute= ltime->second= ltime->second_part= 0;
2601  ltime->time_type= MYSQL_TIMESTAMP_DATE;
2602  return false;
2603  }
2604 
2605 err:
2606  null_value= 1;
2607  return true;
2608 }
2609 
2610 
2611 void Item_func_add_time::fix_length_and_dec()
2612 {
2613  /*
2614  The field type for the result of an Item_func_add_time function is defined
2615  as follows:
2616 
2617  - If first arg is a MYSQL_TYPE_DATETIME or MYSQL_TYPE_TIMESTAMP
2618  result is MYSQL_TYPE_DATETIME
2619  - If first arg is a MYSQL_TYPE_TIME result is MYSQL_TYPE_TIME
2620  - Otherwise the result is MYSQL_TYPE_STRING
2621 
2622  TODO: perhaps it should also return MYSQL_TYPE_DATETIME
2623  when the first argument is MYSQL_TYPE_DATE.
2624  */
2625  if (args[0]->field_type() == MYSQL_TYPE_TIME && !is_date)
2626  {
2627  cached_field_type= MYSQL_TYPE_TIME;
2628  uint8 dec= MY_MAX(args[0]->time_precision(), args[1]->time_precision());
2629  fix_length_and_dec_and_charset_datetime(MAX_TIME_WIDTH, dec);
2630  }
2631  else if (args[0]->is_temporal_with_date_and_time() || is_date)
2632  {
2633  cached_field_type= MYSQL_TYPE_DATETIME;
2634  uint8 dec= MY_MAX(args[0]->datetime_precision(), args[1]->time_precision());
2635  fix_length_and_dec_and_charset_datetime(MAX_DATETIME_WIDTH, dec);
2636  }
2637  else
2638  {
2639  cached_field_type= MYSQL_TYPE_STRING;
2640  fix_length_and_charset(MAX_DATETIME_FULL_WIDTH, default_charset());
2641  }
2642  maybe_null= 1;
2643 }
2644 
2645 
2657 bool Item_func_add_time::val_datetime(MYSQL_TIME *time, uint fuzzy_date)
2658 {
2659  DBUG_ASSERT(fixed == 1);
2660  MYSQL_TIME l_time1, l_time2;
2661  bool is_time= 0;
2662  long days, microseconds;
2663  longlong seconds;
2664  int l_sign= sign;
2665 
2666  null_value=0;
2667  if (cached_field_type == MYSQL_TYPE_DATETIME) // TIMESTAMP function
2668  {
2669  if (get_arg0_date(&l_time1, fuzzy_date) ||
2670  args[1]->get_time(&l_time2) ||
2671  l_time1.time_type == MYSQL_TIMESTAMP_TIME ||
2672  l_time2.time_type != MYSQL_TIMESTAMP_TIME)
2673  goto null_date;
2674  }
2675  else // ADDTIME function
2676  {
2677  if (args[0]->get_time(&l_time1) ||
2678  args[1]->get_time(&l_time2) ||
2679  l_time2.time_type == MYSQL_TIMESTAMP_DATETIME)
2680  goto null_date;
2681  is_time= (l_time1.time_type == MYSQL_TIMESTAMP_TIME);
2682  }
2683  if (l_time1.neg != l_time2.neg)
2684  l_sign= -l_sign;
2685 
2686  memset(time, 0, sizeof(MYSQL_TIME));
2687 
2688  time->neg= calc_time_diff(&l_time1, &l_time2, -l_sign,
2689  &seconds, &microseconds);
2690 
2691  /*
2692  If first argument was negative and diff between arguments
2693  is non-zero we need to swap sign to get proper result.
2694  */
2695  if (l_time1.neg && (seconds || microseconds))
2696  time->neg= 1 - time->neg; // Swap sign of result
2697 
2698  if (!is_time && time->neg)
2699  goto null_date;
2700 
2701  days= (long) (seconds / SECONDS_IN_24H);
2702 
2703  calc_time_from_sec(time, seconds % SECONDS_IN_24H, microseconds);
2704 
2705  if (!is_time)
2706  {
2707  get_date_from_daynr(days, &time->year, &time->month, &time->day);
2708  time->time_type= MYSQL_TIMESTAMP_DATETIME;
2709  if (time->day)
2710  return false;
2711  goto null_date;
2712  }
2713  time->time_type= MYSQL_TIMESTAMP_TIME;
2714  time->hour+= days*24;
2715  adjust_time_range_with_warn(time, 0);
2716  return false;
2717 
2718 null_date:
2719  null_value= 1;
2720  return true;
2721 }
2722 
2723 
2724 void Item_func_add_time::print(String *str, enum_query_type query_type)
2725 {
2726  if (is_date)
2727  {
2728  DBUG_ASSERT(sign > 0);
2729  str->append(STRING_WITH_LEN("timestamp("));
2730  }
2731  else
2732  {
2733  if (sign > 0)
2734  str->append(STRING_WITH_LEN("addtime("));
2735  else
2736  str->append(STRING_WITH_LEN("subtime("));
2737  }
2738  args[0]->print(str, query_type);
2739  str->append(',');
2740  args[1]->print(str, query_type);
2741  str->append(')');
2742 }
2743 
2744 
2759 {
2760  DBUG_ASSERT(fixed == 1);
2761  longlong seconds;
2762  long microseconds;
2763  int l_sign= 1;
2764  MYSQL_TIME l_time1, l_time2;
2765 
2766  null_value= 0;
2767 
2768  if ((args[0]->is_temporal_with_date() &&
2769  args[1]->field_type() == MYSQL_TYPE_TIME) ||
2770  (args[1]->is_temporal_with_date() &&
2771  args[0]->field_type() == MYSQL_TYPE_TIME))
2772  goto null_date; // Incompatible types
2773 
2774  if (args[0]->is_temporal_with_date() ||
2775  args[1]->is_temporal_with_date())
2776  {
2777  if (args[0]->get_date(&l_time1, TIME_FUZZY_DATE) ||
2778  args[1]->get_date(&l_time2, TIME_FUZZY_DATE))
2779  goto null_date;
2780  }
2781  else
2782  {
2783  if (args[0]->get_time(&l_time1) ||
2784  args[1]->get_time(&l_time2))
2785  goto null_date;
2786  }
2787 
2788  if (l_time1.time_type != l_time2.time_type)
2789  goto null_date; // Incompatible types
2790 
2791  if (l_time1.neg != l_time2.neg)
2792  l_sign= -l_sign;
2793 
2794  memset(l_time3, 0, sizeof(*l_time3));
2795 
2796  l_time3->neg= calc_time_diff(&l_time1, &l_time2, l_sign,
2797  &seconds, &microseconds);
2798 
2799  /*
2800  For MYSQL_TIMESTAMP_TIME only:
2801  If first argument was negative and diff between arguments
2802  is non-zero we need to swap sign to get proper result.
2803  */
2804  if (l_time1.neg && (seconds || microseconds))
2805  l_time3->neg= 1 - l_time3->neg; // Swap sign of result
2806 
2807  calc_time_from_sec(l_time3, seconds, microseconds);
2808  adjust_time_range_with_warn(l_time3, decimals);
2809  return false;
2810 
2811 null_date:
2812  return (null_value= 1);
2813 }
2814 
2815 
2823 {
2824  DBUG_ASSERT(fixed == 1);
2825  bool overflow= 0;
2826  longlong hour= args[0]->val_int();
2827  longlong minute= args[1]->val_int();
2828  my_decimal tmp, *sec= args[2]->val_decimal(&tmp);
2829  lldiv_t second;
2830 
2831  if ((null_value= (args[0]->null_value ||
2832  args[1]->null_value ||
2833  args[2]->null_value ||
2834  my_decimal2lldiv_t(E_DEC_FATAL_ERROR, sec, &second) ||
2835  minute < 0 || minute > 59 ||
2836  second.quot < 0 || second.quot > 59 || second.rem < 0)))
2837  return true;
2838 
2839  set_zero_time(ltime, MYSQL_TIMESTAMP_TIME);
2840 
2841  /* Check for integer overflows */
2842  if (hour < 0)
2843  {
2844  if (args[0]->unsigned_flag)
2845  overflow= 1;
2846  else
2847  ltime->neg= 1;
2848  }
2849  if (-hour > UINT_MAX || hour > UINT_MAX)
2850  overflow= 1;
2851 
2852  if (!overflow)
2853  {
2854  ltime->hour= (uint) ((hour < 0 ? -hour : hour));
2855  ltime->minute= (uint) minute;
2856  ltime->second= (uint) second.quot;
2857  int warnings= 0;
2858  ltime->second_part= second.rem / 1000;
2859  adjust_time_range_with_warn(ltime, decimals);
2860  time_add_nanoseconds_with_round(ltime, second.rem % 1000, &warnings);
2861  if (!warnings)
2862  return false;
2863  }
2864 
2865  // Return maximum value (positive or negative)
2866  set_max_hhmmss(ltime);
2867  char buf[MAX_BIGINT_WIDTH /* hh */ + 6 /* :mm:ss */ + 10 /* .fffffffff */ +1];
2868  char *ptr= longlong10_to_str(hour, buf, args[0]->unsigned_flag ? 10 : -10);
2869  int len = (int)(ptr - buf) +
2870  sprintf(ptr, ":%02u:%02u", (uint) minute, (uint) second.quot);
2871  if (second.rem)
2872  {
2873  /*
2874  Display fractional part up to nanoseconds (9 digits),
2875  which is the maximum precision of my_decimal2lldiv_t().
2876  */
2877  int dec= MY_MIN(args[2]->decimals, 9);
2878  len+= sprintf(buf + len, ".%0*lld", dec,
2879  second.rem / (ulong) log_10_int[9 - dec]);
2880  }
2881  DBUG_ASSERT(strlen(buf) < sizeof(buf));
2882  make_truncated_value_warning(ErrConvString(buf, len), MYSQL_TIMESTAMP_TIME);
2883  return false;
2884 }
2885 
2886 
2896 {
2897  DBUG_ASSERT(fixed == 1);
2898  MYSQL_TIME ltime;
2899  return get_arg0_time(&ltime) ? 0 : ltime.second_part;
2900 }
2901 
2902 
2903 longlong Item_func_timestamp_diff::val_int()
2904 {
2905  MYSQL_TIME ltime1, ltime2;
2906  longlong seconds;
2907  long microseconds;
2908  long months= 0;
2909  int neg= 1;
2910 
2911  null_value= 0;
2912  if (args[0]->get_date(&ltime1, TIME_NO_ZERO_DATE) ||
2913  args[1]->get_date(&ltime2, TIME_NO_ZERO_DATE))
2914  goto null_date;
2915 
2916  if (calc_time_diff(&ltime2,&ltime1, 1,
2917  &seconds, &microseconds))
2918  neg= -1;
2919 
2920  if (int_type == INTERVAL_YEAR ||
2921  int_type == INTERVAL_QUARTER ||
2922  int_type == INTERVAL_MONTH)
2923  {
2924  uint year_beg, year_end, month_beg, month_end, day_beg, day_end;
2925  uint years= 0;
2926  uint second_beg, second_end, microsecond_beg, microsecond_end;
2927 
2928  if (neg == -1)
2929  {
2930  year_beg= ltime2.year;
2931  year_end= ltime1.year;
2932  month_beg= ltime2.month;
2933  month_end= ltime1.month;
2934  day_beg= ltime2.day;
2935  day_end= ltime1.day;
2936  second_beg= ltime2.hour * 3600 + ltime2.minute * 60 + ltime2.second;
2937  second_end= ltime1.hour * 3600 + ltime1.minute * 60 + ltime1.second;
2938  microsecond_beg= ltime2.second_part;
2939  microsecond_end= ltime1.second_part;
2940  }
2941  else
2942  {
2943  year_beg= ltime1.year;
2944  year_end= ltime2.year;
2945  month_beg= ltime1.month;
2946  month_end= ltime2.month;
2947  day_beg= ltime1.day;
2948  day_end= ltime2.day;
2949  second_beg= ltime1.hour * 3600 + ltime1.minute * 60 + ltime1.second;
2950  second_end= ltime2.hour * 3600 + ltime2.minute * 60 + ltime2.second;
2951  microsecond_beg= ltime1.second_part;
2952  microsecond_end= ltime2.second_part;
2953  }
2954 
2955  /* calc years */
2956  years= year_end - year_beg;
2957  if (month_end < month_beg || (month_end == month_beg && day_end < day_beg))
2958  years-= 1;
2959 
2960  /* calc months */
2961  months= 12*years;
2962  if (month_end < month_beg || (month_end == month_beg && day_end < day_beg))
2963  months+= 12 - (month_beg - month_end);
2964  else
2965  months+= (month_end - month_beg);
2966 
2967  if (day_end < day_beg)
2968  months-= 1;
2969  else if ((day_end == day_beg) &&
2970  ((second_end < second_beg) ||
2971  (second_end == second_beg && microsecond_end < microsecond_beg)))
2972  months-= 1;
2973  }
2974 
2975  switch (int_type) {
2976  case INTERVAL_YEAR:
2977  return months/12*neg;
2978  case INTERVAL_QUARTER:
2979  return months/3*neg;
2980  case INTERVAL_MONTH:
2981  return months*neg;
2982  case INTERVAL_WEEK:
2983  return seconds / SECONDS_IN_24H / 7L * neg;
2984  case INTERVAL_DAY:
2985  return seconds / SECONDS_IN_24H * neg;
2986  case INTERVAL_HOUR:
2987  return seconds/3600L*neg;
2988  case INTERVAL_MINUTE:
2989  return seconds/60L*neg;
2990  case INTERVAL_SECOND:
2991  return seconds*neg;
2992  case INTERVAL_MICROSECOND:
2993  /*
2994  In MySQL difference between any two valid datetime values
2995  in microseconds fits into longlong.
2996  */
2997  return (seconds*1000000L+microseconds)*neg;
2998  default:
2999  break;
3000  }
3001 
3002 null_date:
3003  null_value=1;
3004  return 0;
3005 }
3006 
3007 
3008 void Item_func_timestamp_diff::print(String *str, enum_query_type query_type)
3009 {
3010  str->append(func_name());
3011  str->append('(');
3012 
3013  switch (int_type) {
3014  case INTERVAL_YEAR:
3015  str->append(STRING_WITH_LEN("YEAR"));
3016  break;
3017  case INTERVAL_QUARTER:
3018  str->append(STRING_WITH_LEN("QUARTER"));
3019  break;
3020  case INTERVAL_MONTH:
3021  str->append(STRING_WITH_LEN("MONTH"));
3022  break;
3023  case INTERVAL_WEEK:
3024  str->append(STRING_WITH_LEN("WEEK"));
3025  break;
3026  case INTERVAL_DAY:
3027  str->append(STRING_WITH_LEN("DAY"));
3028  break;
3029  case INTERVAL_HOUR:
3030  str->append(STRING_WITH_LEN("HOUR"));
3031  break;
3032  case INTERVAL_MINUTE:
3033  str->append(STRING_WITH_LEN("MINUTE"));
3034  break;
3035  case INTERVAL_SECOND:
3036  str->append(STRING_WITH_LEN("SECOND"));
3037  break;
3038  case INTERVAL_MICROSECOND:
3039  str->append(STRING_WITH_LEN("SECOND_FRAC"));
3040  break;
3041  default:
3042  break;
3043  }
3044 
3045  for (uint i=0 ; i < 2 ; i++)
3046  {
3047  str->append(',');
3048  args[i]->print(str, query_type);
3049  }
3050  str->append(')');
3051 }
3052 
3053 
3054 String *Item_func_get_format::val_str_ascii(String *str)
3055 {
3056  DBUG_ASSERT(fixed == 1);
3057  const char *format_name;
3058  KNOWN_DATE_TIME_FORMAT *format;
3059  String *val= args[0]->val_str_ascii(str);
3060  ulong val_len;
3061 
3062  if ((null_value= args[0]->null_value))
3063  return 0;
3064 
3065  val_len= val->length();
3066  for (format= &known_date_time_formats[0];
3067  (format_name= format->format_name);
3068  format++)
3069  {
3070  uint format_name_len;
3071  format_name_len= (uint) strlen(format_name);
3072  if (val_len == format_name_len &&
3073  !my_strnncoll(&my_charset_latin1,
3074  (const uchar *) val->ptr(), val_len,
3075  (const uchar *) format_name, val_len))
3076  {
3077  const char *format_str= get_date_time_format_str(format, type);
3078  str->set(format_str, (uint) strlen(format_str), &my_charset_numeric);
3079  return str;
3080  }
3081  }
3082 
3083  null_value= 1;
3084  return 0;
3085 }
3086 
3087 
3088 void Item_func_get_format::print(String *str, enum_query_type query_type)
3089 {
3090  str->append(func_name());
3091  str->append('(');
3092 
3093  switch (type) {
3094  case MYSQL_TIMESTAMP_DATE:
3095  str->append(STRING_WITH_LEN("DATE, "));
3096  break;
3097  case MYSQL_TIMESTAMP_DATETIME:
3098  str->append(STRING_WITH_LEN("DATETIME, "));
3099  break;
3100  case MYSQL_TIMESTAMP_TIME:
3101  str->append(STRING_WITH_LEN("TIME, "));
3102  break;
3103  default:
3104  DBUG_ASSERT(0);
3105  }
3106  args[0]->print(str, query_type);
3107  str->append(')');
3108 }
3109 
3110 
3126 void Item_func_str_to_date::fix_from_format(const char *format, uint length)
3127 {
3128  const char *time_part_frms= "HISThiklrs";
3129  const char *date_part_frms= "MVUXYWabcjmvuxyw";
3130  bool date_part_used= 0, time_part_used= 0, frac_second_used= 0;
3131  const char *val= format;
3132  const char *end= format + length;
3133 
3134  for (; val != end && val != end; val++)
3135  {
3136  if (*val == '%' && val + 1 != end)
3137  {
3138  val++;
3139  if (*val == 'f')
3140  frac_second_used= time_part_used= 1;
3141  else if (!time_part_used && strchr(time_part_frms, *val))
3142  time_part_used= 1;
3143  else if (!date_part_used && strchr(date_part_frms, *val))
3144  date_part_used= 1;
3145  if (date_part_used && frac_second_used)
3146  {
3147  /*
3148  frac_second_used implies time_part_used, and thus we already
3149  have all types of date-time components and can end our search.
3150  */
3151  cached_timestamp_type= MYSQL_TIMESTAMP_DATETIME;
3152  cached_field_type= MYSQL_TYPE_DATETIME;
3153  fix_length_and_dec_and_charset_datetime(MAX_DATETIME_WIDTH,
3154  DATETIME_MAX_DECIMALS);
3155  return;
3156  }
3157  }
3158  }
3159 
3160  /* We don't have all three types of date-time components */
3161  if (frac_second_used) /* TIME with microseconds */
3162  {
3163  cached_timestamp_type= MYSQL_TIMESTAMP_TIME;
3164  cached_field_type= MYSQL_TYPE_TIME;
3165  fix_length_and_dec_and_charset_datetime(MAX_TIME_FULL_WIDTH,
3166  DATETIME_MAX_DECIMALS);
3167  }
3168  else if (time_part_used)
3169  {
3170  if (date_part_used) /* DATETIME, no microseconds */
3171  {
3172  cached_timestamp_type= MYSQL_TIMESTAMP_DATETIME;
3173  cached_field_type= MYSQL_TYPE_DATETIME;
3174  fix_length_and_dec_and_charset_datetime(MAX_DATETIME_WIDTH, 0);
3175  }
3176  else /* TIME, no microseconds */
3177  {
3178  cached_timestamp_type= MYSQL_TIMESTAMP_TIME;
3179  cached_field_type= MYSQL_TYPE_TIME;
3180  fix_length_and_dec_and_charset_datetime(MAX_TIME_WIDTH, 0);
3181  }
3182  }
3183  else /* DATE */
3184  {
3185  cached_timestamp_type= MYSQL_TIMESTAMP_DATE;
3186  cached_field_type= MYSQL_TYPE_DATE;
3187  fix_length_and_dec_and_charset_datetime(MAX_DATE_WIDTH, 0);
3188  }
3189 }
3190 
3191 
3192 void Item_func_str_to_date::fix_length_and_dec()
3193 {
3194  maybe_null= 1;
3195  cached_field_type= MYSQL_TYPE_DATETIME;
3196  cached_timestamp_type= MYSQL_TIMESTAMP_DATETIME;
3197  fix_length_and_dec_and_charset_datetime(MAX_DATETIME_WIDTH,
3198  DATETIME_MAX_DECIMALS);
3199  sql_mode= current_thd->datetime_flags();
3200  if ((const_item= args[1]->const_item()))
3201  {
3202  char format_buff[64];
3203  String format_str(format_buff, sizeof(format_buff), &my_charset_bin);
3204  String *format= args[1]->val_str(&format_str);
3205  if (!args[1]->null_value)
3206  fix_from_format(format->ptr(), format->length());
3207  }
3208 }
3209 
3210 
3212 {
3213  DATE_TIME_FORMAT date_time_format;
3214  char val_buff[64], format_buff[64];
3215  String val_string(val_buff, sizeof(val_buff), &my_charset_bin), *val;
3216  String format_str(format_buff, sizeof(format_buff), &my_charset_bin), *format;
3217 
3218  fuzzy_date|= sql_mode;
3219  val= args[0]->val_str(&val_string);
3220  format= args[1]->val_str(&format_str);
3221  if (args[0]->null_value || args[1]->null_value)
3222  goto null_date;
3223 
3224  null_value= 0;
3225  memset(ltime, 0, sizeof(*ltime));
3226  date_time_format.format.str= (char*) format->ptr();
3227  date_time_format.format.length= format->length();
3228  if (extract_date_time(&date_time_format, val->ptr(), val->length(),
3229  ltime, cached_timestamp_type, 0, "datetime") ||
3230  ((fuzzy_date & TIME_NO_ZERO_DATE) &&
3231  (ltime->year == 0 || ltime->month == 0 || ltime->day == 0)))
3232  goto null_date;
3233  ltime->time_type= cached_timestamp_type;
3234  if (cached_timestamp_type == MYSQL_TIMESTAMP_TIME && ltime->day)
3235  {
3236  /*
3237  Day part for time type can be nonzero value and so
3238  we should add hours from day part to hour part to
3239  keep valid time value.
3240  */
3241  ltime->hour+= ltime->day*24;
3242  ltime->day= 0;
3243  }
3244  return 0;
3245 
3246 null_date:
3247  if (val && (fuzzy_date & TIME_NO_ZERO_DATE) /*warnings*/)
3248  {
3249  char buff[128];
3250  strmake(buff, val->ptr(), min<size_t>(val->length(), sizeof(buff)-1));
3251  push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
3252  ER_WRONG_VALUE_FOR_TYPE, ER(ER_WRONG_VALUE_FOR_TYPE),
3253  "datetime", buff, "str_to_date");
3254  }
3255  return (null_value= 1);
3256 }
3257 
3258 
3259 bool Item_func_last_day::get_date(MYSQL_TIME *ltime, uint fuzzy_date)
3260 {
3261  if ((null_value= get_arg0_date(ltime, fuzzy_date)))
3262  return true;
3263 
3264  if (ltime->month == 0)
3265  {
3266  /*
3267  Cannot calculate last day for zero month.
3268  Let's print a warning and return NULL.
3269  */
3270  ltime->time_type= MYSQL_TIMESTAMP_DATE;
3271  ErrConvString str(ltime, 0);
3272  make_truncated_value_warning(ErrConvString(str), MYSQL_TIMESTAMP_ERROR);
3273  return (null_value= true);
3274  }
3275 
3276  uint month_idx= ltime->month - 1;
3277  ltime->day= days_in_month[month_idx];
3278  if (month_idx == 1 && calc_days_in_year(ltime->year) == 366)
3279  ltime->day= 29;
3280  datetime_to_date(ltime);
3281  return false;
3282 }