~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/item_timefunc.cc

Merged vcol stuff.

Show diffs side-by-side

added added

removed removed

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