~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/item_timefunc.cc

  • Committer: Monty Taylor
  • Date: 2008-11-16 05:36:13 UTC
  • mto: (584.1.9 devel)
  • mto: This revision was merged to the branch mainline in revision 589.
  • Revision ID: monty@inaugust.com-20081116053613-bld4rqxhlkb49c02
Split out cache_row and type_holder.

Show diffs side-by-side

added added

removed removed

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