~drizzle-trunk/drizzle/development

1 by brian
clean slate
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
*/
243.1.17 by Jay Pipes
FINAL PHASE removal of mysql_priv.h (Bye, bye my friend.)
26
#include <drizzled/server_includes.h>
1 by brian
clean slate
27
#include <time.h>
202.3.6 by Monty Taylor
First pass at gettexizing the error messages.
28
#include <drizzled/drizzled_error_messages.h>
1 by brian
clean slate
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
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
51
static bool make_datetime(date_time_format_types format, DRIZZLE_TIME *ltime,
1 by brian
clean slate
52
			  String *str)
53
{
54
  char *buff;
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
55
  const CHARSET_INFO * const cs= &my_charset_bin;
482 by Brian Aker
Remove uint.
56
  uint32_t length= MAX_DATE_STRING_REP_LENGTH;
1 by brian
clean slate
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
/*
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
100
  Wrapper over make_datetime() with validation of the input DRIZZLE_TIME value
1 by brian
clean slate
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
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
110
static bool make_datetime_with_warn(date_time_format_types format, DRIZZLE_TIME *ltime,
1 by brian
clean slate
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
261.4.1 by Felipe
- Renamed MYSQL_ERROR to DRIZZLE_ERROR.
122
  make_truncated_value_warning(current_thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
1 by brian
clean slate
123
                               str->ptr(), str->length(),
461 by Monty Taylor
Removed NullS. bu-bye.
124
                               DRIZZLE_TIMESTAMP_TIME, NULL);
1 by brian
clean slate
125
  return make_datetime(format, ltime, str);
126
}
127
128
129
/*
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
130
  Wrapper over make_time() with validation of the input DRIZZLE_TIME value
1 by brian
clean slate
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,
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
141
                                DRIZZLE_TIME *l_time, String *str)
1 by brian
clean slate
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
  {
261.4.1 by Felipe
- Renamed MYSQL_ERROR to DRIZZLE_ERROR.
149
    make_truncated_value_warning(current_thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
1 by brian
clean slate
150
                                 str->ptr(), str->length(),
461 by Monty Taylor
Removed NullS. bu-bye.
151
                                 DRIZZLE_TIMESTAMP_TIME, NULL);
1 by brian
clean slate
152
    make_time(format, l_time, str);
153
  }
154
155
  return 0;
156
}
157
158
159
/*
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
160
  Convert seconds to DRIZZLE_TIME value with overflow checking
1 by brian
clean slate
161
162
  SYNOPSIS:
163
    sec_to_time()
164
    seconds          number of seconds
165
    unsigned_flag    1, if 'seconds' is unsigned, 0, otherwise
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
166
    ltime            output DRIZZLE_TIME value
1 by brian
clean slate
167
168
  DESCRIPTION
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
169
    If the 'seconds' argument is inside DRIZZLE_TIME data range, convert it to a
1 by brian
clean slate
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
  
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
179
static bool sec_to_time(int64_t seconds, bool unsigned_flag, DRIZZLE_TIME *ltime)
1 by brian
clean slate
180
{
482 by Brian Aker
Remove uint.
181
  uint32_t sec;
1 by brian
clean slate
182
212.6.6 by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove().
183
  memset(ltime, 0, sizeof(*ltime));
1 by brian
clean slate
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
  
151 by Brian Aker
Ulonglong to uint64_t
197
  sec= (uint) ((uint64_t) seconds % 3600);
1 by brian
clean slate
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];
152 by Brian Aker
longlong replacement
210
  int len= (int)(int64_t10_to_str(seconds, buf, unsigned_flag ? 10 : -10)
1 by brian
clean slate
211
                 - buf);
261.4.1 by Felipe
- Renamed MYSQL_ERROR to DRIZZLE_ERROR.
212
  make_truncated_value_warning(current_thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
213
                               buf, len, DRIZZLE_TIMESTAMP_TIME,
461 by Monty Taylor
Removed NullS. bu-bye.
214
                               NULL);
1 by brian
clean slate
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
/**
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
232
  Extract datetime value to DRIZZLE_TIME struct from string value
1 by brian
clean slate
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,
482 by Brian Aker
Remove uint.
265
			      const char *val, uint32_t length, DRIZZLE_TIME *l_time,
398.1.1 by Monty Taylor
Remove typedef enum enum_drizzle_timestamp_type timestamp_type;
266
                              enum enum_drizzle_timestamp_type cached_timestamp_type,
1 by brian
clean slate
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;
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
283
  const CHARSET_INFO * const cs= &my_charset_bin;
1 by brian
clean slate
284
285
  if (!sub_pattern_end)
212.6.6 by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove().
286
    memset(l_time, 0, sizeof(*l_time));
1 by brian
clean slate
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':
398.1.4 by Monty Taylor
Renamed max/min.
305
	tmp= (char*) val + cmin(4, val_len);
1 by brian
clean slate
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':
398.1.4 by Monty Taylor
Renamed max/min.
312
	tmp= (char*) val + cmin(2, val_len);
1 by brian
clean slate
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':
398.1.4 by Monty Taylor
Renamed max/min.
321
	tmp= (char*) val + cmin(2, val_len);
1 by brian
clean slate
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':
398.1.4 by Monty Taylor
Renamed max/min.
338
	tmp= (char*) val + cmin(2, val_len);
1 by brian
clean slate
339
	l_time->day= (int) my_strtoll10(val, &tmp, &error);
340
	val= tmp;
341
	break;
342
      case 'D':
398.1.4 by Monty Taylor
Renamed max/min.
343
	tmp= (char*) val + cmin(2, val_len);
1 by brian
clean slate
344
	l_time->day= (int) my_strtoll10(val, &tmp, &error);
345
	/* Skip 'st, 'nd, 'th .. */
398.1.4 by Monty Taylor
Renamed max/min.
346
	val= tmp + cmin((int) (val_end-tmp), 2);
1 by brian
clean slate
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':
398.1.4 by Monty Taylor
Renamed max/min.
357
	tmp= (char*) val + cmin(2, val_len);
1 by brian
clean slate
358
	l_time->hour= (int) my_strtoll10(val, &tmp, &error);
359
	val= tmp;
360
	break;
361
362
	/* Minute */
363
      case 'i':
398.1.4 by Monty Taylor
Renamed max/min.
364
	tmp= (char*) val + cmin(2, val_len);
1 by brian
clean slate
365
	l_time->minute= (int) my_strtoll10(val, &tmp, &error);
366
	val= tmp;
367
	break;
368
369
	/* Second */
370
      case 's':
371
      case 'S':
398.1.4 by Monty Taylor
Renamed max/min.
372
	tmp= (char*) val + cmin(2, val_len);
1 by brian
clean slate
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;
383.1.12 by Brian Aker
Much closer toward UTF8 being around all the time...
393
	if (!my_strnncoll(&my_charset_utf8_general_ci,
481 by Brian Aker
Remove all of uchar.
394
			  (const unsigned char *) val, 2, 
395
			  (const unsigned char *) "PM", 2))
1 by brian
clean slate
396
	  daypart= 12;
383.1.12 by Brian Aker
Much closer toward UTF8 being around all the time...
397
	else if (my_strnncoll(&my_charset_utf8_general_ci,
481 by Brian Aker
Remove all of uchar.
398
			      (const unsigned char *) val, 2, 
399
			      (const unsigned char *) "AM", 2))
1 by brian
clean slate
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':
398.1.4 by Monty Taylor
Renamed max/min.
424
	tmp= (char*) val + cmin(val_len, 3);
1 by brian
clean slate
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');
398.1.4 by Monty Taylor
Renamed max/min.
436
	tmp= (char*) val + cmin(val_len, 2);
1 by brian
clean slate
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');
398.1.4 by Monty Taylor
Renamed max/min.
448
        tmp= (char*) val + cmin(4, val_len);
1 by brian
clean slate
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"))
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
462
          return(1);
1 by brian
clean slate
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"))
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
470
          return(1);
1 by brian
clean slate
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;
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
513
    return(0);
1 by brian
clean slate
514
  }
515
516
  if (yearday > 0)
517
  {
482 by Brian Aker
Remove uint.
518
    uint32_t days;
1 by brian
clean slate
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;
482 by Brian Aker
Remove uint.
528
    uint32_t weekday_b;
1 by brian
clean slate
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
    {
383.1.12 by Brian Aker
Much closer toward UTF8 being around all the time...
578
      if (!my_isspace(&my_charset_utf8_general_ci,*val))
1 by brian
clean slate
579
      {
261.4.1 by Felipe
- Renamed MYSQL_ERROR to DRIZZLE_ERROR.
580
	make_truncated_value_warning(current_thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
1 by brian
clean slate
581
                                     val_begin, length,
461 by Monty Taylor
Removed NullS. bu-bye.
582
				     cached_timestamp_type, NULL);
1 by brian
clean slate
583
	break;
584
      }
585
    } while (++val != val_end);
586
  }
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
587
  return(0);
1 by brian
clean slate
588
589
err:
590
  {
591
    char buff[128];
398.1.4 by Monty Taylor
Renamed max/min.
592
    strmake(buff, val_begin, cmin(length, (uint)sizeof(buff)-1));
261.4.1 by Felipe
- Renamed MYSQL_ERROR to DRIZZLE_ERROR.
593
    push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
1 by brian
clean slate
594
                        ER_WRONG_VALUE_FOR_TYPE, ER(ER_WRONG_VALUE_FOR_TYPE),
595
                        date_time_type, buff, "str_to_date");
596
  }
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
597
  return(1);
1 by brian
clean slate
598
}
599
600
601
/**
602
  Create a formated date/time value in a string.
603
*/
604
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
605
bool make_date_time(DATE_TIME_FORMAT *format, DRIZZLE_TIME *l_time,
398.1.1 by Monty Taylor
Remove typedef enum enum_drizzle_timestamp_type timestamp_type;
606
		    enum enum_drizzle_timestamp_type type, String *str)
1 by brian
clean slate
607
{
608
  char intbuff[15];
482 by Brian Aker
Remove uint.
609
  uint32_t hours_i;
610
  uint32_t weekday;
1 by brian
clean slate
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':
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
644
        if (type == DRIZZLE_TIMESTAMP_TIME)
1 by brian
clean slate
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':
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
653
        if (type == DRIZZLE_TIMESTAMP_TIME)
1 by brian
clean slate
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':
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
662
	if (type == DRIZZLE_TIMESTAMP_TIME)
1 by brian
clean slate
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':
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
729
	if (type == DRIZZLE_TIMESTAMP_TIME)
1 by brian
clean slate
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':
171.1.1 by Patrick Galbraith
Dar, I forgot to commit this earlier.
750
	length= sprintf(intbuff, 
1 by brian
clean slate
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,
171.1.1 by Patrick Galbraith
Dar, I forgot to commit this earlier.
755
		    l_time->second);
1 by brian
clean slate
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':
171.1.1 by Patrick Galbraith
Dar, I forgot to commit this earlier.
764
	length= sprintf(intbuff, 
1 by brian
clean slate
765
		    "%02d:%02d:%02d", 
766
		    l_time->hour, 
767
		    l_time->minute,
171.1.1 by Patrick Galbraith
Dar, I forgot to commit this earlier.
768
		    l_time->second);
1 by brian
clean slate
769
	str->append(intbuff, length);
770
	break;
771
      case 'U':
772
      case 'u':
773
      {
482 by Brian Aker
Remove uint.
774
	uint32_t year;
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
775
	if (type == DRIZZLE_TIMESTAMP_TIME)
1 by brian
clean slate
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
      {
482 by Brian Aker
Remove uint.
788
	uint32_t year;
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
789
	if (type == DRIZZLE_TIMESTAMP_TIME)
1 by brian
clean slate
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
      {
482 by Brian Aker
Remove uint.
803
	uint32_t year;
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
804
	if (type == DRIZZLE_TIMESTAMP_TIME)
1 by brian
clean slate
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':
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
816
	if (type == DRIZZLE_TIMESTAMP_TIME)
1 by brian
clean slate
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
482 by Brian Aker
Remove uint.
853
static bool get_interval_info(const char *str,uint32_t length, const CHARSET_INFO * const cs,
854
                              uint32_t count, uint64_t *values,
1 by brian
clean slate
855
                              bool transform_msec)
856
{
857
  const char *end=str+length;
482 by Brian Aker
Remove uint.
858
  uint32_t i;
1 by brian
clean slate
859
  while (str != end && !my_isdigit(cs,*str))
860
    str++;
861
862
  for (i=0 ; i < count ; i++)
863
  {
152 by Brian Aker
longlong replacement
864
    int64_t value;
1 by brian
clean slate
865
    const char *start= str;
866
    for (value=0; str != end && my_isdigit(cs,*str) ; str++)
398.1.8 by Monty Taylor
Enabled -Wlong-long.
867
      value= value * 10L + (int64_t) (*str - '0');
1 by brian
clean slate
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] */
481 by Brian Aker
Remove all of uchar.
881
      bmove_upp((unsigned char*) (values+count), (unsigned char*) (values+i),
1 by brian
clean slate
882
		sizeof(*values)*i);
212.6.6 by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove().
883
      memset(values, 0, sizeof(*values)*(count-i));
1 by brian
clean slate
884
      break;
885
    }
886
  }
887
  return (str != end);
888
}
889
890
152 by Brian Aker
longlong replacement
891
int64_t Item_func_period_add::val_int()
1 by brian
clean slate
892
{
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
893
  assert(fixed == 1);
1 by brian
clean slate
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 */
152 by Brian Aker
longlong replacement
900
  return (int64_t)
1 by brian
clean slate
901
    convert_month_to_period((uint) ((int) convert_period_to_month(period)+
902
				    months));
903
}
904
905
152 by Brian Aker
longlong replacement
906
int64_t Item_func_period_diff::val_int()
1 by brian
clean slate
907
{
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
908
  assert(fixed == 1);
1 by brian
clean slate
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 */
152 by Brian Aker
longlong replacement
914
  return (int64_t) ((long) convert_period_to_month(period1)-
1 by brian
clean slate
915
		     (long) convert_period_to_month(period2));
916
}
917
918
919
152 by Brian Aker
longlong replacement
920
int64_t Item_func_to_days::val_int()
1 by brian
clean slate
921
{
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
922
  assert(fixed == 1);
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
923
  DRIZZLE_TIME ltime;
1 by brian
clean slate
924
  if (get_arg0_date(&ltime, TIME_NO_ZERO_DATE))
925
    return 0;
152 by Brian Aker
longlong replacement
926
  return (int64_t) calc_daynr(ltime.year,ltime.month,ltime.day);
1 by brian
clean slate
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
  {
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
948
    if (args[0]->field_type() == DRIZZLE_TYPE_NEWDATE)
1 by brian
clean slate
949
      return MONOTONIC_STRICT_INCREASING;
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
950
    if (args[0]->field_type() == DRIZZLE_TYPE_DATETIME)
1 by brian
clean slate
951
      return MONOTONIC_INCREASING;
952
  }
953
  return NON_MONOTONIC;
954
}
955
956
152 by Brian Aker
longlong replacement
957
int64_t Item_func_to_days::val_int_endpoint(bool left_endp, bool *incl_endp)
1 by brian
clean slate
958
{
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
959
  assert(fixed == 1);
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
960
  DRIZZLE_TIME ltime;
152 by Brian Aker
longlong replacement
961
  int64_t res;
1 by brian
clean slate
962
  if (get_arg0_date(&ltime, TIME_NO_ZERO_DATE))
963
  {
964
    /* got NULL, leave the incl_endp intact */
163 by Brian Aker
Merge Monty's code.
965
    return INT64_MIN;
1 by brian
clean slate
966
  }
152 by Brian Aker
longlong replacement
967
  res=(int64_t) calc_daynr(ltime.year,ltime.month,ltime.day);
1 by brian
clean slate
968
  
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
969
  if (args[0]->field_type() == DRIZZLE_TYPE_NEWDATE)
1 by brian
clean slate
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
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
990
    *incl_endp= true;
1 by brian
clean slate
991
  return res;
992
}
993
994
152 by Brian Aker
longlong replacement
995
int64_t Item_func_dayofyear::val_int()
1 by brian
clean slate
996
{
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
997
  assert(fixed == 1);
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
998
  DRIZZLE_TIME ltime;
1 by brian
clean slate
999
  if (get_arg0_date(&ltime,TIME_NO_ZERO_DATE))
1000
    return 0;
152 by Brian Aker
longlong replacement
1001
  return (int64_t) calc_daynr(ltime.year,ltime.month,ltime.day) -
1 by brian
clean slate
1002
    calc_daynr(ltime.year,1,1) + 1;
1003
}
1004
152 by Brian Aker
longlong replacement
1005
int64_t Item_func_dayofmonth::val_int()
1 by brian
clean slate
1006
{
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
1007
  assert(fixed == 1);
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
1008
  DRIZZLE_TIME ltime;
1 by brian
clean slate
1009
  (void) get_arg0_date(&ltime, TIME_FUZZY_DATE);
152 by Brian Aker
longlong replacement
1010
  return (int64_t) ltime.day;
1 by brian
clean slate
1011
}
1012
152 by Brian Aker
longlong replacement
1013
int64_t Item_func_month::val_int()
1 by brian
clean slate
1014
{
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
1015
  assert(fixed == 1);
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
1016
  DRIZZLE_TIME ltime;
1 by brian
clean slate
1017
  (void) get_arg0_date(&ltime, TIME_FUZZY_DATE);
152 by Brian Aker
longlong replacement
1018
  return (int64_t) ltime.month;
1 by brian
clean slate
1019
}
1020
1021
1022
String* Item_func_monthname::val_str(String* str)
1023
{
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
1024
  assert(fixed == 1);
1 by brian
clean slate
1025
  const char *month_name;
482 by Brian Aker
Remove uint.
1026
  uint32_t   month= (uint) val_int();
1 by brian
clean slate
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
152 by Brian Aker
longlong replacement
1045
int64_t Item_func_quarter::val_int()
1 by brian
clean slate
1046
{
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
1047
  assert(fixed == 1);
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
1048
  DRIZZLE_TIME ltime;
1 by brian
clean slate
1049
  if (get_arg0_date(&ltime, TIME_FUZZY_DATE))
1050
    return 0;
152 by Brian Aker
longlong replacement
1051
  return (int64_t) ((ltime.month+2)/3);
1 by brian
clean slate
1052
}
1053
152 by Brian Aker
longlong replacement
1054
int64_t Item_func_hour::val_int()
1 by brian
clean slate
1055
{
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
1056
  assert(fixed == 1);
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
1057
  DRIZZLE_TIME ltime;
1 by brian
clean slate
1058
  (void) get_arg0_time(&ltime);
1059
  return ltime.hour;
1060
}
1061
152 by Brian Aker
longlong replacement
1062
int64_t Item_func_minute::val_int()
1 by brian
clean slate
1063
{
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
1064
  assert(fixed == 1);
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
1065
  DRIZZLE_TIME ltime;
1 by brian
clean slate
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
*/
152 by Brian Aker
longlong replacement
1073
int64_t Item_func_second::val_int()
1 by brian
clean slate
1074
{
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
1075
  assert(fixed == 1);
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
1076
  DRIZZLE_TIME ltime;
1 by brian
clean slate
1077
  (void) get_arg0_time(&ltime);
1078
  return ltime.second;
1079
}
1080
1081
482 by Brian Aker
Remove uint.
1082
uint32_t week_mode(uint32_t mode)
1 by brian
clean slate
1083
{
482 by Brian Aker
Remove uint.
1084
  uint32_t week_format= (mode & 7);
1 by brian
clean slate
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
152 by Brian Aker
longlong replacement
1121
int64_t Item_func_week::val_int()
1 by brian
clean slate
1122
{
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
1123
  assert(fixed == 1);
482 by Brian Aker
Remove uint.
1124
  uint32_t year;
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
1125
  DRIZZLE_TIME ltime;
1 by brian
clean slate
1126
  if (get_arg0_date(&ltime, TIME_NO_ZERO_DATE))
1127
    return 0;
152 by Brian Aker
longlong replacement
1128
  return (int64_t) calc_week(&ltime,
1 by brian
clean slate
1129
			      week_mode((uint) args[1]->val_int()),
1130
			      &year);
1131
}
1132
1133
152 by Brian Aker
longlong replacement
1134
int64_t Item_func_yearweek::val_int()
1 by brian
clean slate
1135
{
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
1136
  assert(fixed == 1);
482 by Brian Aker
Remove uint.
1137
  uint32_t year,week;
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
1138
  DRIZZLE_TIME ltime;
1 by brian
clean slate
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
152 by Brian Aker
longlong replacement
1148
int64_t Item_func_weekday::val_int()
1 by brian
clean slate
1149
{
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
1150
  assert(fixed == 1);
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
1151
  DRIZZLE_TIME ltime;
1 by brian
clean slate
1152
  
1153
  if (get_arg0_date(&ltime, TIME_NO_ZERO_DATE))
1154
    return 0;
1155
152 by Brian Aker
longlong replacement
1156
  return (int64_t) calc_weekday(calc_daynr(ltime.year, ltime.month,
1 by brian
clean slate
1157
                                            ltime.day),
1158
                                 odbc_type) + test(odbc_type);
1159
}
1160
1161
1162
String* Item_func_dayname::val_str(String* str)
1163
{
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
1164
  assert(fixed == 1);
482 by Brian Aker
Remove uint.
1165
  uint32_t weekday=(uint) val_int();		// Always Item_func_daynr()
1 by brian
clean slate
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
152 by Brian Aker
longlong replacement
1178
int64_t Item_func_year::val_int()
1 by brian
clean slate
1179
{
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
1180
  assert(fixed == 1);
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
1181
  DRIZZLE_TIME ltime;
1 by brian
clean slate
1182
  (void) get_arg0_date(&ltime, TIME_FUZZY_DATE);
152 by Brian Aker
longlong replacement
1183
  return (int64_t) ltime.year;
1 by brian
clean slate
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 &&
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
1204
      (args[0]->field_type() == DRIZZLE_TYPE_NEWDATE ||
1205
       args[0]->field_type() == DRIZZLE_TYPE_DATETIME))
1 by brian
clean slate
1206
    return MONOTONIC_INCREASING;
1207
  return NON_MONOTONIC;
1208
}
1209
1210
152 by Brian Aker
longlong replacement
1211
int64_t Item_func_year::val_int_endpoint(bool left_endp, bool *incl_endp)
1 by brian
clean slate
1212
{
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
1213
  assert(fixed == 1);
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
1214
  DRIZZLE_TIME ltime;
1 by brian
clean slate
1215
  if (get_arg0_date(&ltime, TIME_FUZZY_DATE))
1216
  {
1217
    /* got NULL, leave the incl_endp intact */
163 by Brian Aker
Merge Monty's code.
1218
    return INT64_MIN;
1 by brian
clean slate
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
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
1236
    *incl_endp= true;
1 by brian
clean slate
1237
  return ltime.year;
1238
}
1239
1240
152 by Brian Aker
longlong replacement
1241
int64_t Item_func_unix_timestamp::val_int()
1 by brian
clean slate
1242
{
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
1243
  DRIZZLE_TIME ltime;
93 by Brian Aker
Convert tztime.cc to bool from my_bool.
1244
  bool not_used;
1 by brian
clean slate
1245
  
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
1246
  assert(fixed == 1);
1 by brian
clean slate
1247
  if (arg_count == 0)
152 by Brian Aker
longlong replacement
1248
    return (int64_t) current_thd->query_start();
1 by brian
clean slate
1249
  if (args[0]->type() == FIELD_ITEM)
1250
  {						// Optimize timestamp field
1251
    Field *field=((Item_field*) args[0])->field;
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
1252
    if (field->type() == DRIZZLE_TYPE_TIMESTAMP)
1 by brian
clean slate
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
  
152 by Brian Aker
longlong replacement
1267
  return (int64_t) TIME_to_timestamp(current_thd, &ltime, &not_used);
1 by brian
clean slate
1268
}
1269
1270
152 by Brian Aker
longlong replacement
1271
int64_t Item_func_time_to_sec::val_int()
1 by brian
clean slate
1272
{
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
1273
  assert(fixed == 1);
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
1274
  DRIZZLE_TIME ltime;
152 by Brian Aker
longlong replacement
1275
  int64_t seconds;
1 by brian
clean slate
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
{
151 by Brian Aker
Ulonglong to uint64_t
1291
  uint64_t array[5];
152 by Brian Aker
longlong replacement
1292
  int64_t value= 0;
1 by brian
clean slate
1293
  const char *str= NULL;
1294
  size_t length= 0;
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
1295
  const CHARSET_INFO * const cs= str_value->charset();
1 by brian
clean slate
1296
212.6.6 by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove().
1297
  memset(interval, 0, sizeof(*interval));
1 by brian
clean slate
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 */
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
1433
    assert(0); 
1 by brian
clean slate
1434
    break;            /* purecov: end */
1435
  }
1436
  return 0;
1437
}
1438
1439
1440
String *Item_date::val_str(String *str)
1441
{
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
1442
  assert(fixed == 1);
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
1443
  DRIZZLE_TIME ltime;
1 by brian
clean slate
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
152 by Brian Aker
longlong replacement
1456
int64_t Item_date::val_int()
1 by brian
clean slate
1457
{
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
1458
  assert(fixed == 1);
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
1459
  DRIZZLE_TIME ltime;
1 by brian
clean slate
1460
  if (get_date(&ltime, TIME_FUZZY_DATE))
1461
    return 0;
152 by Brian Aker
longlong replacement
1462
  return (int64_t) (ltime.year*10000L+ltime.month*100+ltime.day);
1 by brian
clean slate
1463
}
1464
1465
482 by Brian Aker
Remove uint.
1466
bool Item_func_from_days::get_date(DRIZZLE_TIME *ltime, uint32_t fuzzy_date __attribute__((unused)))
1 by brian
clean slate
1467
{
152 by Brian Aker
longlong replacement
1468
  int64_t value=args[0]->val_int();
1 by brian
clean slate
1469
  if ((null_value=args[0]->null_value))
1470
    return 1;
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
1471
  memset(ltime, 0, sizeof(DRIZZLE_TIME));
1 by brian
clean slate
1472
  get_date_from_daynr((long) value, &ltime->year, &ltime->month, &ltime->day);
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
1473
  ltime->time_type= DRIZZLE_TIMESTAMP_DATE;
1 by brian
clean slate
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;
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
1488
  ltime.time_type= DRIZZLE_TIMESTAMP_DATE;
152 by Brian Aker
longlong replacement
1489
  value= (int64_t) TIME_to_uint64_t_date(&ltime);
1 by brian
clean slate
1490
}
1491
1492
String *Item_func_curdate::val_str(String *str)
1493
{
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
1494
  assert(fixed == 1);
1 by brian
clean slate
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
/**
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
1505
    Converts current time in my_time_t to DRIZZLE_TIME represenatation for local
1 by brian
clean slate
1506
    time zone. Defines time zone (local) used for whole CURDATE function.
1507
*/
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
1508
void Item_func_curdate_local::store_now_in_TIME(DRIZZLE_TIME *now_time)
1 by brian
clean slate
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
/**
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
1518
    Converts current time in my_time_t to DRIZZLE_TIME represenatation for UTC
1 by brian
clean slate
1519
    time zone. Defines time zone (UTC) used for whole UTC_DATE function.
1520
*/
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
1521
void Item_func_curdate_utc::store_now_in_TIME(DRIZZLE_TIME *now_time)
1 by brian
clean slate
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
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
1532
bool Item_func_curdate::get_date(DRIZZLE_TIME *res,
482 by Brian Aker
Remove uint.
1533
				 uint32_t fuzzy_date __attribute__((unused)))
1 by brian
clean slate
1534
{
1535
  *res=ltime;
1536
  return 0;
1537
}
1538
1539
212.1.3 by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)).
1540
String *Item_func_curtime::val_str(String *str __attribute__((unused)))
1 by brian
clean slate
1541
{
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
1542
  assert(fixed == 1);
1 by brian
clean slate
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
{
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
1550
  DRIZZLE_TIME ltime;
1 by brian
clean slate
1551
1552
  decimals= DATETIME_DEC;
1553
  collation.set(&my_charset_bin);
1554
  store_now_in_TIME(&ltime);
151 by Brian Aker
Ulonglong to uint64_t
1555
  value= TIME_to_uint64_t_time(&ltime);
1 by brian
clean slate
1556
  buff_length= (uint) my_time_to_str(&ltime, buff);
1557
  max_length= buff_length;
1558
}
1559
1560
1561
/**
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
1562
    Converts current time in my_time_t to DRIZZLE_TIME represenatation for local
1 by brian
clean slate
1563
    time zone. Defines time zone (local) used for whole CURTIME function.
1564
*/
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
1565
void Item_func_curtime_local::store_now_in_TIME(DRIZZLE_TIME *now_time)
1 by brian
clean slate
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
/**
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
1575
    Converts current time in my_time_t to DRIZZLE_TIME represenatation for UTC
1 by brian
clean slate
1576
    time zone. Defines time zone (UTC) used for whole UTC_TIME function.
1577
*/
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
1578
void Item_func_curtime_utc::store_now_in_TIME(DRIZZLE_TIME *now_time)
1 by brian
clean slate
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
212.1.3 by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)).
1589
String *Item_func_now::val_str(String *str __attribute__((unused)))
1 by brian
clean slate
1590
{
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
1591
  assert(fixed == 1);
1 by brian
clean slate
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);
152 by Brian Aker
longlong replacement
1603
  value= (int64_t) TIME_to_uint64_t_datetime(&ltime);
1 by brian
clean slate
1604
1605
  buff_length= (uint) my_datetime_to_str(&ltime, buff);
1606
  max_length= buff_length;
1607
}
1608
1609
1610
/**
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
1611
    Converts current time in my_time_t to DRIZZLE_TIME represenatation for local
1 by brian
clean slate
1612
    time zone. Defines time zone (local) used for whole NOW function.
1613
*/
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
1614
void Item_func_now_local::store_now_in_TIME(DRIZZLE_TIME *now_time)
1 by brian
clean slate
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
/**
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
1624
    Converts current time in my_time_t to DRIZZLE_TIME represenatation for UTC
1 by brian
clean slate
1625
    time zone. Defines time zone (UTC) used for whole UTC_TIMESTAMP function.
1626
*/
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
1627
void Item_func_now_utc::store_now_in_TIME(DRIZZLE_TIME *now_time)
1 by brian
clean slate
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
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
1638
bool Item_func_now::get_date(DRIZZLE_TIME *res,
482 by Brian Aker
Remove uint.
1639
                             uint32_t fuzzy_date __attribute__((unused)))
1 by brian
clean slate
1640
{
1641
  *res= ltime;
1642
  return 0;
1643
}
1644
1645
212.1.3 by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)).
1646
int Item_func_now::save_in_field(Field *to, bool no_conversions __attribute__((unused)))
1 by brian
clean slate
1647
{
1648
  to->set_notnull();
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
1649
  return to->store_time(&ltime, DRIZZLE_TIMESTAMP_DATETIME);
1 by brian
clean slate
1650
}
1651
1652
1653
/**
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
1654
    Converts current time in my_time_t to DRIZZLE_TIME represenatation for local
1 by brian
clean slate
1655
    time zone. Defines time zone (local) used for whole SYSDATE function.
1656
*/
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
1657
void Item_func_sysdate_local::store_now_in_TIME(DRIZZLE_TIME *now_time)
1 by brian
clean slate
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
212.1.3 by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)).
1665
String *Item_func_sysdate_local::val_str(String *str __attribute__((unused)))
1 by brian
clean slate
1666
{
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
1667
  assert(fixed == 1);
1 by brian
clean slate
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
152 by Brian Aker
longlong replacement
1675
int64_t Item_func_sysdate_local::val_int()
1 by brian
clean slate
1676
{
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
1677
  assert(fixed == 1);
1 by brian
clean slate
1678
  store_now_in_TIME(&ltime);
152 by Brian Aker
longlong replacement
1679
  return (int64_t) TIME_to_uint64_t_datetime(&ltime);
1 by brian
clean slate
1680
}
1681
1682
1683
double Item_func_sysdate_local::val_real()
1684
{
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
1685
  assert(fixed == 1);
1 by brian
clean slate
1686
  store_now_in_TIME(&ltime);
151 by Brian Aker
Ulonglong to uint64_t
1687
  return uint64_t2double(TIME_to_uint64_t_datetime(&ltime));
1 by brian
clean slate
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
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
1699
bool Item_func_sysdate_local::get_date(DRIZZLE_TIME *res,
482 by Brian Aker
Remove uint.
1700
                                       uint32_t fuzzy_date __attribute__((unused)))
1 by brian
clean slate
1701
{
1702
  store_now_in_TIME(&ltime);
1703
  *res= ltime;
1704
  return 0;
1705
}
1706
1707
212.1.3 by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)).
1708
int Item_func_sysdate_local::save_in_field(Field *to, bool no_conversions __attribute__((unused)))
1 by brian
clean slate
1709
{
1710
  store_now_in_TIME(&ltime);
1711
  to->set_notnull();
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
1712
  to->store_time(&ltime, DRIZZLE_TIMESTAMP_DATETIME);
1 by brian
clean slate
1713
  return 0;
1714
}
1715
1716
1717
String *Item_func_sec_to_time::val_str(String *str)
1718
{
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
1719
  assert(fixed == 1);
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
1720
  DRIZZLE_TIME ltime;
152 by Brian Aker
longlong replacement
1721
  int64_t arg_val= args[0]->val_int(); 
1 by brian
clean slate
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
152 by Brian Aker
longlong replacement
1737
int64_t Item_func_sec_to_time::val_int()
1 by brian
clean slate
1738
{
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
1739
  assert(fixed == 1);
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
1740
  DRIZZLE_TIME ltime;
152 by Brian Aker
longlong replacement
1741
  int64_t arg_val= args[0]->val_int(); 
1 by brian
clean slate
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;
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
1763
  const CHARSET_INFO * const cs= thd->variables.collation_connection;
205 by Brian Aker
uint32 -> uin32_t
1764
  uint32_t repertoire= arg1->collation.repertoire;
1 by brian
clean slate
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;
398.1.4 by Monty Taylor
Renamed max/min.
1777
    max_length=cmin(arg1->max_length,(uint32_t) MAX_BLOB_WIDTH) * 10 *
1 by brian
clean slate
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
482 by Brian Aker
Remove uint.
1810
uint32_t Item_func_date_format::format_length(const String *format)
1 by brian
clean slate
1811
{
482 by Brian Aker
Remove uint.
1812
  uint32_t size=0;
1 by brian
clean slate
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;
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
1886
  DRIZZLE_TIME l_time;
482 by Brian Aker
Remove uint.
1887
  uint32_t size;
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
1888
  assert(fixed == 1);
1 by brian
clean slate
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,
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
1929
                      is_time_format ? DRIZZLE_TIMESTAMP_TIME :
1930
                                       DRIZZLE_TIMESTAMP_DATE,
1 by brian
clean slate
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
{
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
1953
  DRIZZLE_TIME time_tmp;
1 by brian
clean slate
1954
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
1955
  assert(fixed == 1);
1 by brian
clean slate
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
152 by Brian Aker
longlong replacement
1972
int64_t Item_func_from_unixtime::val_int()
1 by brian
clean slate
1973
{
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
1974
  DRIZZLE_TIME time_tmp;
1 by brian
clean slate
1975
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
1976
  assert(fixed == 1);
1 by brian
clean slate
1977
1978
  if (get_date(&time_tmp, 0))
1979
    return 0;
1980
152 by Brian Aker
longlong replacement
1981
  return (int64_t) TIME_to_uint64_t_datetime(&time_tmp);
1 by brian
clean slate
1982
}
1983
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
1984
bool Item_func_from_unixtime::get_date(DRIZZLE_TIME *ltime,
482 by Brian Aker
Remove uint.
1985
				       uint32_t fuzzy_date __attribute__((unused)))
1 by brian
clean slate
1986
{
151 by Brian Aker
Ulonglong to uint64_t
1987
  uint64_t tmp= (uint64_t)(args[0]->val_int());
1 by brian
clean slate
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
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
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.
241 by Brian Aker
First pass of CHAR removal.
2017
    - Otherwise the result is DRIZZLE_TYPE_VARCHAR
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
2018
      (This is because you can't know if the string contains a DATE, DRIZZLE_TIME or
1 by brian
clean slate
2019
      DATETIME argument)
2020
  */
241 by Brian Aker
First pass of CHAR removal.
2021
  cached_field_type= DRIZZLE_TYPE_VARCHAR;
1 by brian
clean slate
2022
  arg0_field_type= args[0]->field_type();
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_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)
1 by brian
clean slate
2027
  {
2028
    if (int_type <= INTERVAL_DAY || int_type == INTERVAL_YEAR_MONTH)
2029
      cached_field_type= arg0_field_type;
2030
    else
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
2031
      cached_field_type= DRIZZLE_TYPE_DATETIME;
1 by brian
clean slate
2032
  }
2033
}
2034
2035
2036
/* Here arg[1] is a Item_interval object */
2037
482 by Brian Aker
Remove uint.
2038
bool Item_date_add_interval::get_date(DRIZZLE_TIME *ltime, uint32_t fuzzy_date __attribute__((unused)))
1 by brian
clean slate
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
{
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
2057
  assert(fixed == 1);
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
2058
  DRIZZLE_TIME ltime;
1 by brian
clean slate
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
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
2064
  if (ltime.time_type == DRIZZLE_TIMESTAMP_DATE)
1 by brian
clean slate
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
152 by Brian Aker
longlong replacement
2079
int64_t Item_date_add_interval::val_int()
1 by brian
clean slate
2080
{
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
2081
  assert(fixed == 1);
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
2082
  DRIZZLE_TIME ltime;
152 by Brian Aker
longlong replacement
2083
  int64_t date;
1 by brian
clean slate
2084
  if (Item_date_add_interval::get_date(&ltime, TIME_NO_ZERO_DATE))
152 by Brian Aker
longlong replacement
2085
    return (int64_t) 0;
1 by brian
clean slate
2086
  date = (ltime.year*100L + ltime.month)*100L + ltime.day;
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
2087
  return ltime.time_type == DRIZZLE_TIMESTAMP_DATE ? date :
1 by brian
clean slate
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;
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
2164
  case INTERVAL_LAST: assert(0); break; /* purecov: deadcode */
1 by brian
clean slate
2165
  }
2166
}
2167
2168
152 by Brian Aker
longlong replacement
2169
int64_t Item_extract::val_int()
1 by brian
clean slate
2170
{
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
2171
  assert(fixed == 1);
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
2172
  DRIZZLE_TIME ltime;
482 by Brian Aker
Remove uint.
2173
  uint32_t year;
1 by brian
clean slate
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;
152 by Brian Aker
longlong replacement
2208
  case INTERVAL_DAY_SECOND:	 return ((int64_t) ltime.day*1000000L+
2209
					 (int64_t) (ltime.hour*10000L+
1 by brian
clean slate
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;
152 by Brian Aker
longlong replacement
2220
  case INTERVAL_DAY_MICROSECOND: return (((int64_t)ltime.day*1000000L +
2221
					  (int64_t)ltime.hour*10000L +
1 by brian
clean slate
2222
					  ltime.minute*100 +
2223
					  ltime.second)*1000000L +
2224
					 ltime.second_part)*neg;
152 by Brian Aker
longlong replacement
2225
  case INTERVAL_HOUR_MICROSECOND: return (((int64_t)ltime.hour*10000L +
1 by brian
clean slate
2226
					   ltime.minute*100 +
2227
					   ltime.second)*1000000L +
2228
					  ltime.second_part)*neg;
152 by Brian Aker
longlong replacement
2229
  case INTERVAL_MINUTE_MICROSECOND: return (((int64_t)(ltime.minute*100+
1 by brian
clean slate
2230
							ltime.second))*1000000L+
2231
					    ltime.second_part)*neg;
152 by Brian Aker
longlong replacement
2232
  case INTERVAL_SECOND_MICROSECOND: return ((int64_t)ltime.second*1000000L+
1 by brian
clean slate
2233
					    ltime.second_part)*neg;
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
2234
  case INTERVAL_LAST: assert(0); break;  /* purecov: deadcode */
1 by brian
clean slate
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);
151 by Brian Aker
Ulonglong to uint64_t
2296
    st.set((uint64_t)cast_length, &my_charset_bin);
1 by brian
clean slate
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
{
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
2310
  assert(fixed == 1);
1 by brian
clean slate
2311
  String *res;
205 by Brian Aker
uint32 -> uin32_t
2312
  uint32_t length;
1 by brian
clean slate
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
482 by Brian Aker
Remove uint.
2325
    uint32_t dummy_errors;
1 by brian
clean slate
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
  {
205 by Brian Aker
uint32 -> uin32_t
2345
    if (res->length() > (length= (uint32_t) res->charpos(cast_length)))
1 by brian
clean slate
2346
    {                                           // Safe even if const arg
2347
      char char_type[40];
77.1.18 by Monty Taylor
Removed my_vsnprintf and my_snprintf.
2348
      snprintf(char_type, sizeof(char_type), "%s(%lu)",
2349
               cast_cs == &my_charset_bin ? "BINARY" : "CHAR",
2350
               (ulong) length);
1 by brian
clean slate
2351
2352
      if (!res->alloced_length())
2353
      {                                         // Don't change const str
2354
        str_value= *res;                        // Not malloced string
2355
        res= &str_value;
2356
      }
261.4.1 by Felipe
- Renamed MYSQL_ERROR to DRIZZLE_ERROR.
2357
      push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
1 by brian
clean slate
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
      }
212.6.6 by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove().
2371
      memset(res->ptr() + res->length(), 0,
212.6.1 by Mats Kindahl
Replacing all bzero() calls with memset() calls and removing the bzero.c file.
2372
             (uint) cast_length - res->length());
1 by brian
clean slate
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
{
205 by Brian Aker
uint32 -> uin32_t
2383
  uint32_t char_length;
1 by brian
clean slate
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) ?
383.1.12 by Brian Aker
Much closer toward UTF8 being around all the time...
2409
           (cast_cs->mbminlen == 1 ? cast_cs : &my_charset_utf8_general_ci) :
1 by brian
clean slate
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
{
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
2422
  assert(fixed == 1);
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
2423
  DRIZZLE_TIME ltime;
1 by brian
clean slate
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
152 by Brian Aker
longlong replacement
2435
int64_t Item_datetime_typecast::val_int()
1 by brian
clean slate
2436
{
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
2437
  assert(fixed == 1);
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
2438
  DRIZZLE_TIME ltime;
1 by brian
clean slate
2439
  if (get_arg0_date(&ltime,1))
2440
  {
2441
    null_value= 1;
2442
    return 0;
2443
  }
2444
151 by Brian Aker
Ulonglong to uint64_t
2445
  return TIME_to_uint64_t_datetime(&ltime);
1 by brian
clean slate
2446
}
2447
2448
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
2449
bool Item_time_typecast::get_time(DRIZZLE_TIME *ltime)
1 by brian
clean slate
2450
{
2451
  bool res= get_arg0_time(ltime);
2452
  /*
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
2453
    For DRIZZLE_TIMESTAMP_TIME value we can have non-zero day part,
1 by brian
clean slate
2454
    which we should not lose.
2455
  */
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
2456
  if (ltime->time_type == DRIZZLE_TIMESTAMP_DATETIME)
1 by brian
clean slate
2457
    ltime->year= ltime->month= ltime->day= 0;
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
2458
  ltime->time_type= DRIZZLE_TIMESTAMP_TIME;
1 by brian
clean slate
2459
  return res;
2460
}
2461
2462
152 by Brian Aker
longlong replacement
2463
int64_t Item_time_typecast::val_int()
1 by brian
clean slate
2464
{
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
2465
  DRIZZLE_TIME ltime;
1 by brian
clean slate
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
{
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
2476
  assert(fixed == 1);
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
2477
  DRIZZLE_TIME ltime;
1 by brian
clean slate
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
482 by Brian Aker
Remove uint.
2489
bool Item_date_typecast::get_date(DRIZZLE_TIME *ltime, uint32_t fuzzy_date __attribute__((unused)))
1 by brian
clean slate
2490
{
2491
  bool res= get_arg0_date(ltime, TIME_FUZZY_DATE);
2492
  ltime->hour= ltime->minute= ltime->second= ltime->second_part= 0;
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
2493
  ltime->time_type= DRIZZLE_TIMESTAMP_DATE;
1 by brian
clean slate
2494
  return res;
2495
}
2496
2497
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
2498
bool Item_date_typecast::get_time(DRIZZLE_TIME *ltime)
1 by brian
clean slate
2499
{
261.2.7 by Monty Taylor
Merged from Mats.
2500
  memset(ltime, 0, sizeof(DRIZZLE_TIME));
1 by brian
clean slate
2501
  return args[0]->null_value;
2502
}
2503
2504
2505
String *Item_date_typecast::val_str(String *str)
2506
{
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
2507
  assert(fixed == 1);
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
2508
  DRIZZLE_TIME ltime;
1 by brian
clean slate
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
152 by Brian Aker
longlong replacement
2521
int64_t Item_date_typecast::val_int()
1 by brian
clean slate
2522
{
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
2523
  assert(fixed == 1);
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
2524
  DRIZZLE_TIME ltime;
1 by brian
clean slate
2525
  if ((null_value= args[0]->get_date(&ltime, TIME_FUZZY_DATE)))
2526
    return 0;
152 by Brian Aker
longlong replacement
2527
  return (int64_t) (ltime.year * 10000L + ltime.month * 100 + ltime.day);
1 by brian
clean slate
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
{
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
2542
  assert(fixed == 1);
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
2543
  DRIZZLE_TIME l_time;
1 by brian
clean slate
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
152 by Brian Aker
longlong replacement
2583
int64_t Item_func_makedate::val_int()
1 by brian
clean slate
2584
{
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
2585
  assert(fixed == 1);
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
2586
  DRIZZLE_TIME l_time;
1 by brian
clean slate
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);
152 by Brian Aker
longlong replacement
2604
    return (int64_t) (l_time.year * 10000L + l_time.month * 100 + l_time.day);
1 by brian
clean slate
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
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
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
241 by Brian Aker
First pass of CHAR removal.
2627
    - Otherwise the result is DRIZZLE_TYPE_VARCHAR
1 by brian
clean slate
2628
  */
2629
241 by Brian Aker
First pass of CHAR removal.
2630
  cached_field_type= DRIZZLE_TYPE_VARCHAR;
1 by brian
clean slate
2631
  arg0_field_type= args[0]->field_type();
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_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;
1 by brian
clean slate
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
{
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
2652
  assert(fixed == 1);
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
2653
  DRIZZLE_TIME l_time1, l_time2, l_time3;
1 by brian
clean slate
2654
  bool is_time= 0;
2655
  long days, microseconds;
152 by Brian Aker
longlong replacement
2656
  int64_t seconds;
1 by brian
clean slate
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) ||
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
2664
        l_time1.time_type == DRIZZLE_TIMESTAMP_TIME || 
2665
        l_time2.time_type != DRIZZLE_TIMESTAMP_TIME)
1 by brian
clean slate
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) ||
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
2672
        l_time2.time_type == DRIZZLE_TIMESTAMP_DATETIME)
1 by brian
clean slate
2673
      goto null_date;
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
2674
    is_time= (l_time1.time_type == DRIZZLE_TIMESTAMP_TIME);
1 by brian
clean slate
2675
  }
2676
  if (l_time1.neg != l_time2.neg)
2677
    l_sign= -l_sign;
2678
  
212.6.6 by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove().
2679
  memset(&l_time3, 0, sizeof(l_time3));
1 by brian
clean slate
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
  {
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
2725
    assert(sign > 0);
1 by brian
clean slate
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
{
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
2752
  assert(fixed == 1);
152 by Brian Aker
longlong replacement
2753
  int64_t seconds;
1 by brian
clean slate
2754
  long microseconds;
2755
  int l_sign= 1;
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
2756
  DRIZZLE_TIME l_time1 ,l_time2, l_time3;
1 by brian
clean slate
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
212.6.6 by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove().
2767
  memset(&l_time3, 0, sizeof(l_time3));
1 by brian
clean slate
2768
  
2769
  l_time3.neg= calc_time_diff(&l_time1, &l_time2, l_sign,
2770
			      &seconds, &microseconds);
2771
2772
  /*
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
2773
    For DRIZZLE_TIMESTAMP_TIME only:
1 by brian
clean slate
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
{
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
2800
  assert(fixed == 1);
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
2801
  DRIZZLE_TIME ltime;
1 by brian
clean slate
2802
  bool overflow= 0;
2803
152 by Brian Aker
longlong replacement
2804
  int64_t hour=   args[0]->val_int();
2805
  int64_t minute= args[1]->val_int();
2806
  int64_t second= args[2]->val_int();
1 by brian
clean slate
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
212.6.6 by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove().
2816
  memset(&ltime, 0, sizeof(ltime));
1 by brian
clean slate
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];
152 by Brian Aker
longlong replacement
2842
    char *ptr= int64_t10_to_str(hour, buf, args[0]->unsigned_flag ? 10 : -10);
1 by brian
clean slate
2843
    int len = (int)(ptr - buf) +
171.1.1 by Patrick Galbraith
Dar, I forgot to commit this earlier.
2844
      sprintf(ptr, ":%02u:%02u", (uint)minute, (uint)second);
261.4.1 by Felipe
- Renamed MYSQL_ERROR to DRIZZLE_ERROR.
2845
    make_truncated_value_warning(current_thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
2846
                                 buf, len, DRIZZLE_TIMESTAMP_TIME,
461 by Monty Taylor
Removed NullS. bu-bye.
2847
                                 NULL);
1 by brian
clean slate
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
152 by Brian Aker
longlong replacement
2867
int64_t Item_func_microsecond::val_int()
1 by brian
clean slate
2868
{
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
2869
  assert(fixed == 1);
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
2870
  DRIZZLE_TIME ltime;
1 by brian
clean slate
2871
  if (!get_arg0_time(&ltime))
2872
    return ltime.second_part;
2873
  return 0;
2874
}
2875
2876
152 by Brian Aker
longlong replacement
2877
int64_t Item_func_timestamp_diff::val_int()
1 by brian
clean slate
2878
{
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
2879
  DRIZZLE_TIME ltime1, ltime2;
152 by Brian Aker
longlong replacement
2880
  int64_t seconds;
1 by brian
clean slate
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
  {
482 by Brian Aker
Remove uint.
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;
1 by brian
clean slate
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
152 by Brian Aker
longlong replacement
2969
      in microseconds fits into int64_t.
1 by brian
clean slate
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
482 by Brian Aker
Remove uint.
3019
  for (uint32_t i=0 ; i < 2 ; i++)
1 by brian
clean slate
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
{
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
3030
  assert(fixed == 1);
1 by brian
clean slate
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
  {
482 by Brian Aker
Remove uint.
3044
    uint32_t format_name_len;
1 by brian
clean slate
3045
    format_name_len= strlen(format_name);
3046
    if (val_len == format_name_len &&
383.1.12 by Brian Aker
Much closer toward UTF8 being around all the time...
3047
	!my_strnncoll(&my_charset_utf8_general_ci, 
481 by Brian Aker
Remove all of uchar.
3048
		      (const unsigned char *) val->ptr(), val_len, 
3049
		      (const unsigned char *) format_name, val_len))
1 by brian
clean slate
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) {
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
3068
  case DRIZZLE_TIMESTAMP_DATE:
1 by brian
clean slate
3069
    str->append(STRING_WITH_LEN("DATE, "));
3070
    break;
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
3071
  case DRIZZLE_TIMESTAMP_DATETIME:
1 by brian
clean slate
3072
    str->append(STRING_WITH_LEN("DATETIME, "));
3073
    break;
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
3074
  case DRIZZLE_TIMESTAMP_TIME:
1 by brian
clean slate
3075
    str->append(STRING_WITH_LEN("TIME, "));
3076
    break;
3077
  default:
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
3078
    assert(0);
1 by brian
clean slate
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
482 by Brian Aker
Remove uint.
3110
get_date_time_result_type(const char *format, uint32_t length)
1 by brian
clean slate
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;
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
3158
  cached_field_type= DRIZZLE_TYPE_DATETIME;
1 by brian
clean slate
3159
  max_length= MAX_DATETIME_FULL_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
3160
  cached_timestamp_type= DRIZZLE_TIMESTAMP_NONE;
1 by brian
clean slate
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:
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
3172
        cached_timestamp_type= DRIZZLE_TIMESTAMP_DATE;
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
3173
        cached_field_type= DRIZZLE_TYPE_NEWDATE; 
1 by brian
clean slate
3174
        max_length= MAX_DATE_WIDTH * MY_CHARSET_BIN_MB_MAXLEN;
3175
        break;
3176
      case TIME_ONLY:
3177
      case TIME_MICROSECOND:
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
3178
        cached_timestamp_type= DRIZZLE_TIMESTAMP_TIME;
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
3179
        cached_field_type= DRIZZLE_TYPE_TIME; 
1 by brian
clean slate
3180
        max_length= MAX_TIME_WIDTH * MY_CHARSET_BIN_MB_MAXLEN;
3181
        break;
3182
      default:
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
3183
        cached_timestamp_type= DRIZZLE_TIMESTAMP_DATETIME;
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
3184
        cached_field_type= DRIZZLE_TYPE_DATETIME; 
1 by brian
clean slate
3185
        break;
3186
      }
3187
    }
3188
  }
3189
}
3190
3191
482 by Brian Aker
Remove uint.
3192
bool Item_func_str_to_date::get_date(DRIZZLE_TIME *ltime, uint32_t fuzzy_date)
1 by brian
clean slate
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;
212.6.6 by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove().
3205
  memset(ltime, 0, sizeof(*ltime));
1 by brian
clean slate
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;
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
3213
  if (cached_timestamp_type == DRIZZLE_TIMESTAMP_TIME && ltime->day)
1 by brian
clean slate
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
{
51.1.26 by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE
3232
  assert(fixed == 1);
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
3233
  DRIZZLE_TIME ltime;
1 by brian
clean slate
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
482 by Brian Aker
Remove uint.
3246
bool Item_func_last_day::get_date(DRIZZLE_TIME *ltime, uint32_t fuzzy_date)
1 by brian
clean slate
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;
482 by Brian Aker
Remove uint.
3255
  uint32_t month_idx= ltime->month-1;
1 by brian
clean slate
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;
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
3261
  ltime->time_type= DRIZZLE_TIMESTAMP_DATE;
1 by brian
clean slate
3262
  return 0;
3263
}