~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/item_timefunc.cc

MergedĀ inĀ trunk.

Show diffs side-by-side

added added

removed removed

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