~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/item_timefunc.cc

  • Committer: Monty Taylor
  • Date: 2008-10-16 09:12:23 UTC
  • mto: (511.1.6 codestyle)
  • mto: This revision was merged to the branch mainline in revision 521.
  • Revision ID: monty@inaugust.com-20081016091223-17ngih0qu9vssjs3
We pass -Wunused-macros now!

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