~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/time.cc

  • Committer: Monty Taylor
  • Date: 2009-05-09 22:13:47 UTC
  • mto: This revision was merged to the branch mainline in revision 1009.
  • Revision ID: mordred@inaugust.com-20090509221347-l712szviusbobro0
Re-added bitset<> as a replacement for Bitmap<>

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2000-2006 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 */
 
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
 
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
 
3
 *
 
4
 *  Copyright (C) 2008 Sun Microsystems
 
5
 *
 
6
 *  This program is free software; you can redistribute it and/or modify
 
7
 *  it under the terms of the GNU General Public License as published by
 
8
 *  the Free Software Foundation; version 2 of the License.
 
9
 *
 
10
 *  This program is distributed in the hope that it will be useful,
 
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 *  GNU General Public License for more details.
 
14
 *
 
15
 *  You should have received a copy of the GNU General Public License
 
16
 *  along with this program; if not, write to the Free Software
 
17
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
18
 */
15
19
 
16
20
 
17
21
/* Functions to handle date and time */
18
22
 
19
23
#include <drizzled/server_includes.h>
20
 
#include <drizzled/drizzled_error_messages.h>
21
 
 
22
 
 
23
 
        /* Some functions to calculate dates */
 
24
#include <drizzled/error.h>
 
25
#include <drizzled/util/test.h>
 
26
#include <drizzled/tztime.h>
 
27
#include <drizzled/session.h>
 
28
 
 
29
/* Some functions to calculate dates */
24
30
 
25
31
#ifndef TESTTIME
26
32
 
29
35
 
30
36
  'interval_type_to_name' is ordered and sorted on interval size and
31
37
  interval complexity.
32
 
  Order of elements in 'interval_type_to_name' should correspond to 
 
38
  Order of elements in 'interval_type_to_name' should correspond to
33
39
  the order of elements in 'interval_type' enum
34
 
  
 
40
 
35
41
  See also interval_type, interval_names
36
42
*/
37
43
 
56
62
  { C_STRING_WITH_LEN("HOUR_MICROSECOND")},
57
63
  { C_STRING_WITH_LEN("MINUTE_MICROSECOND")},
58
64
  { C_STRING_WITH_LEN("SECOND_MICROSECOND")}
59
 
}; 
 
65
};
60
66
 
61
67
        /* Calc weekday from daynr */
62
68
        /* Returns 0 for monday, 1 for tuesday .... */
88
94
                                        to ISO 8601:1988
89
95
                          If set        The week that contains the first
90
96
                                        'first-day-of-week' is week 1.
91
 
        
 
97
 
92
98
        ISO 8601:1988 means that if the week containing January 1 has
93
99
        four or more days in the new year, then it is week 1;
94
100
        Otherwise it is the last week of the previous year, and the
98
104
uint32_t calc_week(DRIZZLE_TIME *l_time, uint32_t week_behaviour, uint32_t *year)
99
105
{
100
106
  uint32_t days;
101
 
  ulong daynr=calc_daynr(l_time->year,l_time->month,l_time->day);
102
 
  ulong first_daynr=calc_daynr(l_time->year,1,1);
 
107
  uint32_t daynr= calc_daynr(l_time->year,l_time->month,l_time->day);
 
108
  uint32_t first_daynr= calc_daynr(l_time->year,1,1);
103
109
  bool monday_first= test(week_behaviour & WEEK_MONDAY_FIRST);
104
110
  bool week_year= test(week_behaviour & WEEK_YEAR);
105
111
  bool first_weekday= test(week_behaviour & WEEK_FIRST_WEEKDAY);
150
156
  }
151
157
  else
152
158
  {
153
 
    year= (uint) (daynr*100 / 36525L);
 
159
    year= (uint32_t) (daynr*100 / 36525L);
154
160
    temp=(((year-1)/100+1)*3)/4;
155
 
    day_of_year=(uint) (daynr - (long) year * 365L) - (year-1)/4 +temp;
 
161
    day_of_year=(uint32_t) (daynr - (long) year * 365L) - (year-1)/4 +temp;
156
162
    while (day_of_year > (days_in_year= calc_days_in_year(year)))
157
163
    {
158
164
      day_of_year-=days_in_year;
170
176
    }
171
177
    *ret_month=1;
172
178
    for (month_pos= days_in_month ;
173
 
         day_of_year > (uint) *month_pos ;
 
179
         day_of_year > (uint32_t) *month_pos ;
174
180
         day_of_year-= *(month_pos++), (*ret_month)++)
175
181
      ;
176
182
    *ret_year=year;
179
185
  return;
180
186
}
181
187
 
182
 
        /* Functions to handle periods */
183
 
 
184
 
ulong convert_period_to_month(ulong period)
185
 
{
186
 
  ulong a,b;
187
 
  if (period == 0)
188
 
    return 0L;
189
 
  if ((a=period/100) < YY_PART_YEAR)
190
 
    a+=2000;
191
 
  else if (a < 100)
192
 
    a+=1900;
193
 
  b=period%100;
194
 
  return a*12+b-1;
195
 
}
196
 
 
197
 
 
198
 
ulong convert_month_to_period(ulong month)
199
 
{
200
 
  ulong year;
201
 
  if (month == 0L)
202
 
    return 0L;
203
 
  if ((year=month/12) < 100)
204
 
  {
205
 
    year+=(year < YY_PART_YEAR) ? 2000 : 1900;
206
 
  }
207
 
  return year*100+month%12+1;
208
 
}
209
 
 
210
 
 
211
188
/*
212
 
  Convert a timestamp string to a DRIZZLE_TIME value and produce a warning 
 
189
  Convert a timestamp string to a DRIZZLE_TIME value and produce a warning
213
190
  if string was truncated during conversion.
214
191
 
215
192
  NOTE
221
198
                          uint32_t flags)
222
199
{
223
200
  int was_cut;
224
 
  THD *thd= current_thd;
 
201
  Session *session= current_session;
225
202
  enum enum_drizzle_timestamp_type ts_type;
226
 
  
 
203
 
227
204
  ts_type= str_to_datetime(str, length, l_time,
228
 
                           (flags | (thd->variables.sql_mode &
 
205
                           (flags | (session->variables.sql_mode &
229
206
                                     (MODE_INVALID_DATES |
230
207
                                      MODE_NO_ZERO_DATE))),
231
208
                           &was_cut);
232
209
  if (was_cut || ts_type <= DRIZZLE_TIMESTAMP_ERROR)
233
 
    make_truncated_value_warning(current_thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
210
    make_truncated_value_warning(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
234
211
                                 str, length, ts_type,  NULL);
235
212
  return ts_type;
236
213
}
237
214
 
238
 
 
239
 
/*
240
 
  Convert a datetime from broken-down DRIZZLE_TIME representation to corresponding 
241
 
  TIMESTAMP value.
242
 
 
243
 
  SYNOPSIS
244
 
    TIME_to_timestamp()
245
 
      thd             - current thread
246
 
      t               - datetime in broken-down representation, 
247
 
      in_dst_time_gap - pointer to bool which is set to true if t represents
248
 
                        value which doesn't exists (falls into the spring 
249
 
                        time-gap) or to false otherwise.
250
 
   
251
 
  RETURN
252
 
     Number seconds in UTC since start of Unix Epoch corresponding to t.
253
 
     0 - t contains datetime value which is out of TIMESTAMP range.
254
 
     
255
 
*/
256
 
my_time_t TIME_to_timestamp(THD *thd, const DRIZZLE_TIME *t, bool *in_dst_time_gap)
257
 
{
258
 
  my_time_t timestamp;
259
 
 
260
 
  *in_dst_time_gap= 0;
261
 
  thd->time_zone_used= 1;
262
 
 
263
 
  timestamp= thd->variables.time_zone->TIME_to_gmt_sec(t, in_dst_time_gap);
264
 
  if (timestamp)
265
 
  {
266
 
    return timestamp;
267
 
  }
268
 
 
269
 
  /* If we are here we have range error. */
270
 
  return(0);
271
 
}
272
 
 
273
 
 
274
215
/*
275
216
  Convert a time string to a DRIZZLE_TIME struct and produce a warning
276
217
  if string was cut during conversion.
284
225
  int warning;
285
226
  bool ret_val= str_to_time(str, length, l_time, &warning);
286
227
  if (ret_val || warning)
287
 
    make_truncated_value_warning(current_thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
228
    make_truncated_value_warning(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
288
229
                                 str, length, DRIZZLE_TIMESTAMP_TIME, NULL);
289
230
  return ret_val;
290
231
}
321
262
  to->second_part= microseconds;
322
263
}
323
264
 
324
 
 
325
 
/*
326
 
  Parse a format string specification
327
 
 
328
 
  SYNOPSIS
329
 
    parse_date_time_format()
330
 
    format_type         Format of string (time, date or datetime)
331
 
    format_str          String to parse
332
 
    format_length       Length of string
333
 
    date_time_format    Format to fill in
334
 
 
335
 
  NOTES
336
 
    Fills in date_time_format->positions for all date time parts.
337
 
 
338
 
    positions marks the position for a datetime element in the format string.
339
 
    The position array elements are in the following order:
340
 
    YYYY-DD-MM HH-MM-DD.FFFFFF AM
341
 
    0    1  2  3  4  5  6      7
342
 
 
343
 
    If positions[0]= 5, it means that year will be the forth element to
344
 
    read from the parsed date string.
345
 
 
346
 
  RETURN
347
 
    0   ok
348
 
    1   error
349
 
*/
350
 
 
351
 
bool parse_date_time_format(enum enum_drizzle_timestamp_type format_type, 
352
 
                            const char *format, uint32_t format_length,
353
 
                            DATE_TIME_FORMAT *date_time_format)
354
 
{
355
 
  uint32_t offset= 0, separators= 0;
356
 
  const char *ptr= format, *format_str;
357
 
  const char *end= ptr+format_length;
358
 
  unsigned char *dt_pos= date_time_format->positions;
359
 
  /* need_p is set if we are using AM/PM format */
360
 
  bool need_p= 0, allow_separator= 0;
361
 
  uint32_t part_map= 0, separator_map= 0;
362
 
  const char *parts[16];
363
 
 
364
 
  date_time_format->time_separator= 0;
365
 
  date_time_format->flag= 0;                    // For future
366
 
 
367
 
  /*
368
 
    Fill position with 'dummy' arguments to found out if a format tag is
369
 
    used twice (This limit's the format to 255 characters, but this is ok)
370
 
  */
371
 
  dt_pos[0]= dt_pos[1]= dt_pos[2]= dt_pos[3]=
372
 
    dt_pos[4]= dt_pos[5]= dt_pos[6]= dt_pos[7]= 255;
373
 
 
374
 
  for (; ptr != end; ptr++)
375
 
  {
376
 
    if (*ptr == '%' && ptr+1 != end)
377
 
    {
378
 
      uint32_t position;
379
 
      switch (*++ptr) {
380
 
      case 'y':                                 // Year
381
 
      case 'Y':
382
 
        position= 0;
383
 
        break;
384
 
      case 'c':                                 // Month
385
 
      case 'm':
386
 
        position= 1;
387
 
        break;
388
 
      case 'd':
389
 
      case 'e':
390
 
        position= 2;
391
 
        break;
392
 
      case 'h':
393
 
      case 'I':
394
 
      case 'l':
395
 
        need_p= 1;                              // Need AM/PM
396
 
        /* Fall through */
397
 
      case 'k':
398
 
      case 'H':
399
 
        position= 3;
400
 
        break;
401
 
      case 'i':
402
 
        position= 4;
403
 
        break;
404
 
      case 's':
405
 
      case 'S':
406
 
        position= 5;
407
 
        break;
408
 
      case 'f':
409
 
        position= 6;
410
 
        if (dt_pos[5] != offset-1 || ptr[-2] != '.')
411
 
          return 1;                             // Wrong usage of %f
412
 
        break;
413
 
      case 'p':                                 // AM/PM
414
 
        if (offset == 0)                        // Can't be first
415
 
          return 0;
416
 
        position= 7;
417
 
        break;
418
 
      default:
419
 
        return 1;                               // Unknown controll char
420
 
      }
421
 
      if (dt_pos[position] != 255)              // Don't allow same tag twice
422
 
        return 1;
423
 
      parts[position]= ptr-1;
424
 
 
425
 
      /*
426
 
        If switching from time to date, ensure that all time parts
427
 
        are used
428
 
      */
429
 
      if (part_map && position <= 2 && !(part_map & (1 | 2 | 4)))
430
 
        offset=5;
431
 
      part_map|= UINT32_C(1) << position;
432
 
      dt_pos[position]= offset++;
433
 
      allow_separator= 1;
434
 
    }
435
 
    else
436
 
    {
437
 
      /*
438
 
        Don't allow any characters in format as this could easily confuse
439
 
        the date reader
440
 
      */
441
 
      if (!allow_separator)
442
 
        return 1;                               // No separator here
443
 
      allow_separator= 0;                       // Don't allow two separators
444
 
      separators++;
445
 
      /* Store in separator_map which parts are punct characters */
446
 
      if (my_ispunct(&my_charset_utf8_general_ci, *ptr))
447
 
        separator_map|= (ulong) 1 << (offset-1);
448
 
      else if (!my_isspace(&my_charset_utf8_general_ci, *ptr))
449
 
        return 1;
450
 
    }
451
 
  }
452
 
 
453
 
  /* If no %f, specify it after seconds.  Move %p up, if necessary */
454
 
  if ((part_map & 32) && !(part_map & 64))
455
 
  {
456
 
    dt_pos[6]= dt_pos[5] +1;
457
 
    parts[6]= parts[5];                         // For later test in (need_p)
458
 
    if (dt_pos[6] == dt_pos[7])                 // Move %p one step up if used
459
 
      dt_pos[7]++;
460
 
  }
461
 
 
462
 
  /*
463
 
    Check that we have not used a non legal format specifier and that all
464
 
    format specifiers have been used
465
 
 
466
 
    The last test is to ensure that %p is used if and only if
467
 
    it's needed.
468
 
  */
469
 
  if ((format_type == DRIZZLE_TIMESTAMP_DATETIME &&
470
 
       !test_all_bits(part_map, (uint32_t) (1 | 2 | 4 | 8 | 16 | 32))) ||
471
 
      (format_type == DRIZZLE_TIMESTAMP_DATE && part_map != (1 | 2 | 4)) ||
472
 
      (format_type == DRIZZLE_TIMESTAMP_TIME &&
473
 
       !test_all_bits(part_map, (uint32_t) (8 | 16 | 32))) ||
474
 
      !allow_separator ||                       // %option should be last
475
 
      (need_p && dt_pos[6] +1 != dt_pos[7]) ||
476
 
      (need_p ^ (dt_pos[7] != 255)))
477
 
    return 1;
478
 
 
479
 
  if (dt_pos[6] != 255)                         // If fractional seconds
480
 
  {
481
 
    /* remove fractional seconds from later tests */
482
 
    uint32_t pos= dt_pos[6] -1;
483
 
    /* Remove separator before %f from sep map */
484
 
    separator_map= ((separator_map & ((ulong) (1 << pos)-1)) |
485
 
                    ((separator_map & ~((ulong) (1 << pos)-1)) >> 1));
486
 
    if (part_map & 64)                        
487
 
    {
488
 
      separators--;                             // There is always a separator
489
 
      need_p= 1;                                // force use of separators
490
 
    }
491
 
  }
492
 
 
493
 
  /*
494
 
    Remove possible separator before %p from sep_map
495
 
    (This can either be at position 3, 4, 6 or 7) h.m.d.%f %p
496
 
  */
497
 
  if (dt_pos[7] != 255)
498
 
  {
499
 
    if (need_p && parts[7] != parts[6]+2)
500
 
      separators--;
501
 
  }     
502
 
  /*
503
 
    Calculate if %p is in first or last part of the datetime field
504
 
 
505
 
    At this point we have either %H-%i-%s %p 'year parts' or
506
 
    'year parts' &H-%i-%s %p" as %f was removed above
507
 
  */
508
 
  offset= dt_pos[6] <= 3 ? 3 : 6;
509
 
  /* Remove separator before %p from sep map */
510
 
  separator_map= ((separator_map & ((ulong) (1 << offset)-1)) |
511
 
                  ((separator_map & ~((ulong) (1 << offset)-1)) >> 1));
512
 
 
513
 
  format_str= 0;
514
 
  switch (format_type) {
515
 
  case DRIZZLE_TIMESTAMP_DATE:
516
 
    format_str= known_date_time_formats[INTERNAL_FORMAT].date_format;
517
 
    /* fall through */
518
 
  case DRIZZLE_TIMESTAMP_TIME:
519
 
    if (!format_str)
520
 
      format_str=known_date_time_formats[INTERNAL_FORMAT].time_format;
521
 
 
522
 
    /*
523
 
      If there is no separators, allow the internal format as we can read
524
 
      this.  If separators are used, they must be between each part
525
 
    */
526
 
    if (format_length == 6 && !need_p &&
527
 
        !my_strnncoll(&my_charset_bin,
528
 
                      (const unsigned char *) format, 6, 
529
 
                      (const unsigned char *) format_str, 6))
530
 
      return 0;
531
 
    if (separator_map == (1 | 2))
532
 
    {
533
 
      if (format_type == DRIZZLE_TIMESTAMP_TIME)
534
 
      {
535
 
        if (*(format+2) != *(format+5))
536
 
          break;                                // Error
537
 
        /* Store the character used for time formats */
538
 
        date_time_format->time_separator= *(format+2);
539
 
      }
540
 
      return 0;
541
 
    }
542
 
    break;
543
 
  case DRIZZLE_TIMESTAMP_DATETIME:
544
 
    /*
545
 
      If there is no separators, allow the internal format as we can read
546
 
      this.  If separators are used, they must be between each part.
547
 
      Between DATE and TIME we also allow space as separator
548
 
    */
549
 
    if ((format_length == 12 && !need_p &&
550
 
         !my_strnncoll(&my_charset_bin, 
551
 
                       (const unsigned char *) format, 12,
552
 
                       (const unsigned char*) known_date_time_formats[INTERNAL_FORMAT].datetime_format,
553
 
                       12)) ||
554
 
        (separators == 5 && separator_map == (1 | 2 | 8 | 16)))
555
 
      return 0;
556
 
    break;
557
 
  default:
558
 
    assert(1);
559
 
    break;
560
 
  }
561
 
  return 1;                                     // Error
562
 
}
563
 
 
564
 
 
565
 
/*
566
 
  Create a DATE_TIME_FORMAT object from a format string specification
567
 
 
568
 
  SYNOPSIS
569
 
    date_time_format_make()
570
 
    format_type         Format to parse (time, date or datetime)
571
 
    format_str          String to parse
572
 
    format_length       Length of string
573
 
 
574
 
  NOTES
575
 
    The returned object should be freed with free()
576
 
 
577
 
  RETURN
578
 
    NULL ponter:        Error
579
 
    new object
580
 
*/
581
 
 
582
 
DATE_TIME_FORMAT
583
 
*date_time_format_make(enum enum_drizzle_timestamp_type format_type,
584
 
                       const char *format_str, uint32_t format_length)
585
 
{
586
 
  DATE_TIME_FORMAT tmp;
587
 
 
588
 
  if (format_length && format_length < 255 &&
589
 
      !parse_date_time_format(format_type, format_str,
590
 
                              format_length, &tmp))
591
 
  {
592
 
    tmp.format.str=    (char*) format_str;
593
 
    tmp.format.length= format_length;
594
 
    return date_time_format_copy((THD *)0, &tmp);
595
 
  }
596
 
  return 0;
597
 
}
598
 
 
599
 
 
600
 
/*
601
 
  Create a copy of a DATE_TIME_FORMAT object
602
 
 
603
 
  SYNOPSIS
604
 
    date_and_time_format_copy()
605
 
    thd                 Set if variable should be allocated in thread mem
606
 
    format              format to copy
607
 
 
608
 
  NOTES
609
 
    The returned object should be freed with free()
610
 
 
611
 
  RETURN
612
 
    NULL ponter:        Error
613
 
    new object
614
 
*/
615
 
 
616
 
DATE_TIME_FORMAT *date_time_format_copy(THD *thd, DATE_TIME_FORMAT *format)
617
 
{
618
 
  DATE_TIME_FORMAT *new_format;
619
 
  ulong length= sizeof(*format) + format->format.length + 1;
620
 
 
621
 
  if (thd)
622
 
    new_format= (DATE_TIME_FORMAT *) thd->alloc(length);
623
 
  else
624
 
    new_format=  (DATE_TIME_FORMAT *) my_malloc(length, MYF(MY_WME));
625
 
  if (new_format)
626
 
  {
627
 
    /* Put format string after current pos */
628
 
    new_format->format.str= (char*) (new_format+1);
629
 
    memcpy(new_format->positions, format->positions,
630
 
           sizeof(format->positions));
631
 
    new_format->time_separator= format->time_separator;
632
 
    /* We make the string null terminated for easy printf in SHOW VARIABLES */
633
 
    memcpy(new_format->format.str, format->format.str,
634
 
           format->format.length);
635
 
    new_format->format.str[format->format.length]= 0;
636
 
    new_format->format.length= format->format.length;
637
 
  }
638
 
  return new_format;
639
 
}
640
 
 
641
 
 
642
 
KNOWN_DATE_TIME_FORMAT known_date_time_formats[6]=
643
 
{
644
 
  {"USA", "%m.%d.%Y", "%Y-%m-%d %H.%i.%s", "%h:%i:%s %p" },
645
 
  {"JIS", "%Y-%m-%d", "%Y-%m-%d %H:%i:%s", "%H:%i:%s" },
646
 
  {"ISO", "%Y-%m-%d", "%Y-%m-%d %H:%i:%s", "%H:%i:%s" },
647
 
  {"EUR", "%d.%m.%Y", "%Y-%m-%d %H.%i.%s", "%H.%i.%s" },
648
 
  {"INTERNAL", "%Y%m%d",   "%Y%m%d%H%i%s", "%H%i%s" },
649
 
  { 0, 0, 0, 0 }
650
 
};
651
 
 
652
 
 
653
 
/*
654
 
   Return format string according format name.
655
 
   If name is unknown, result is NULL
656
 
*/
657
 
 
658
 
const char *get_date_time_format_str(KNOWN_DATE_TIME_FORMAT *format,
659
 
                                     enum enum_drizzle_timestamp_type type)
660
 
{
661
 
  switch (type) {
662
 
  case DRIZZLE_TIMESTAMP_DATE:
663
 
    return format->date_format;
664
 
  case DRIZZLE_TIMESTAMP_DATETIME:
665
 
    return format->datetime_format;
666
 
  case DRIZZLE_TIMESTAMP_TIME:
667
 
    return format->time_format;
668
 
  default:
669
 
    assert(0);                          // Impossible
670
 
    return 0;
671
 
  }
672
 
}
673
 
 
674
 
/****************************************************************************
675
 
  Functions to create default time/date/datetime strings
676
 
 
677
 
  NOTE:
678
 
    For the moment the DATE_TIME_FORMAT argument is ignored becasue
679
 
    MySQL doesn't support comparing of date/time/datetime strings that
680
 
    are not in arbutary order as dates are compared as strings in some
681
 
    context)
682
 
    This functions don't check that given DRIZZLE_TIME structure members are
683
 
    in valid range. If they are not, return value won't reflect any 
684
 
    valid date either. Additionally, make_time doesn't take into
685
 
    account time->day member: it's assumed that days have been converted
686
 
    to hours already.
687
 
****************************************************************************/
688
 
 
689
 
void make_time(const DATE_TIME_FORMAT *format __attribute__((unused)),
690
 
               const DRIZZLE_TIME *l_time, String *str)
691
 
{
692
 
  uint32_t length= (uint) my_time_to_str(l_time, (char*) str->ptr());
693
 
  str->length(length);
694
 
  str->set_charset(&my_charset_bin);
695
 
}
696
 
 
697
 
 
698
 
void make_date(const DATE_TIME_FORMAT *format __attribute__((unused)),
699
 
               const DRIZZLE_TIME *l_time, String *str)
700
 
{
701
 
  uint32_t length= (uint) my_date_to_str(l_time, (char*) str->ptr());
702
 
  str->length(length);
703
 
  str->set_charset(&my_charset_bin);
704
 
}
705
 
 
706
 
 
707
 
void make_datetime(const DATE_TIME_FORMAT *format __attribute__((unused)),
708
 
                   const DRIZZLE_TIME *l_time, String *str)
709
 
{
710
 
  uint32_t length= (uint) my_datetime_to_str(l_time, (char*) str->ptr());
711
 
  str->length(length);
712
 
  str->set_charset(&my_charset_bin);
713
 
}
714
 
 
715
 
 
716
 
void make_truncated_value_warning(THD *thd, DRIZZLE_ERROR::enum_warning_level level,
 
265
void make_time(const DRIZZLE_TIME *l_time, String *str)
 
266
{
 
267
  str->alloc(MAX_DATE_STRING_REP_LENGTH);
 
268
  uint32_t length= (uint32_t) my_time_to_str(l_time, str->c_ptr());
 
269
  str->length(length);
 
270
  str->set_charset(&my_charset_bin);
 
271
}
 
272
 
 
273
 
 
274
void make_date(const DRIZZLE_TIME *l_time, String *str)
 
275
{
 
276
  str->alloc(MAX_DATE_STRING_REP_LENGTH);
 
277
  uint32_t length= (uint32_t) my_date_to_str(l_time, str->c_ptr());
 
278
  str->length(length);
 
279
  str->set_charset(&my_charset_bin);
 
280
}
 
281
 
 
282
 
 
283
void make_datetime(const DRIZZLE_TIME *l_time, String *str)
 
284
{
 
285
  str->alloc(MAX_DATE_STRING_REP_LENGTH);
 
286
  uint32_t length= (uint32_t) my_datetime_to_str(l_time, str->c_ptr());
 
287
  str->length(length);
 
288
  str->set_charset(&my_charset_bin);
 
289
}
 
290
 
 
291
 
 
292
void make_truncated_value_warning(Session *session, DRIZZLE_ERROR::enum_warning_level level,
717
293
                                  const char *str_val,
718
294
                                  uint32_t str_length,
719
295
                                  enum enum_drizzle_timestamp_type time_type,
728
304
  str[str_length]= 0;               // Ensure we have end 0 for snprintf
729
305
 
730
306
  switch (time_type) {
731
 
    case DRIZZLE_TIMESTAMP_DATE: 
 
307
    case DRIZZLE_TIMESTAMP_DATE:
732
308
      type_str= "date";
733
309
      break;
734
310
    case DRIZZLE_TIMESTAMP_TIME:
743
319
    cs->cset->snprintf(cs, warn_buff, sizeof(warn_buff),
744
320
                       ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
745
321
                       type_str, str.c_ptr(), field_name,
746
 
                       (ulong) thd->row_count);
 
322
                       (uint32_t) session->row_count);
747
323
  else
748
324
  {
749
325
    if (time_type > DRIZZLE_TIMESTAMP_ERROR)
754
330
      cs->cset->snprintf(cs, warn_buff, sizeof(warn_buff),
755
331
                         ER(ER_WRONG_VALUE), type_str, str.c_ptr());
756
332
  }
757
 
  push_warning(thd, level,
 
333
  push_warning(session, level,
758
334
               ER_TRUNCATED_WRONG_VALUE, warn_buff);
759
335
}
760
336
 
761
 
/* Daynumber from year 0 to 9999-12-31 */
762
 
#define MAX_DAY_NUMBER 3652424L
763
 
 
764
337
bool date_add_interval(DRIZZLE_TIME *ltime, interval_type int_type, INTERVAL interval)
765
338
{
766
339
  long period, sign;
808
381
      days--;
809
382
      sec+= 3600*24L;
810
383
    }
811
 
    ltime->second_part= (uint) microseconds;
812
 
    ltime->second= (uint) (sec % 60);
813
 
    ltime->minute= (uint) (sec/60 % 60);
814
 
    ltime->hour=   (uint) (sec/3600);
 
384
    ltime->second_part= (uint32_t) microseconds;
 
385
    ltime->second= (uint32_t) (sec % 60);
 
386
    ltime->minute= (uint32_t) (sec/60 % 60);
 
387
    ltime->hour=   (uint32_t) (sec/3600);
815
388
    daynr= calc_daynr(ltime->year,ltime->month,1) + days;
816
389
    /* Day number from year 0 to 9999-12-31 */
817
390
    if ((uint64_t) daynr > MAX_DAY_NUMBER)
825
398
    period= (calc_daynr(ltime->year,ltime->month,ltime->day) +
826
399
             sign * (long) interval.day);
827
400
    /* Daynumber from year 0 to 9999-12-31 */
828
 
    if ((ulong) period > MAX_DAY_NUMBER)
 
401
    if (period > MAX_DAY_NUMBER)
829
402
      goto invalid_date;
830
403
    get_date_from_daynr((long) period,&ltime->year,&ltime->month,&ltime->day);
831
404
    break;
832
405
  case INTERVAL_YEAR:
833
406
    ltime->year+= sign * (long) interval.year;
834
 
    if ((ulong) ltime->year >= 10000L)
 
407
    if (ltime->year >= 10000L)
835
408
      goto invalid_date;
836
409
    if (ltime->month == 2 && ltime->day == 29 &&
837
410
        calc_days_in_year(ltime->year) != 366)
842
415
  case INTERVAL_MONTH:
843
416
    period= (ltime->year*12 + sign * (long) interval.year*12 +
844
417
             ltime->month-1 + sign * (long) interval.month);
845
 
    if ((ulong) period >= 120000L)
 
418
    if (period >= 120000L)
846
419
      goto invalid_date;
847
 
    ltime->year= (uint) (period / 12);
848
 
    ltime->month= (uint) (period % 12L)+1;
 
420
    ltime->year= (uint32_t) (period / 12);
 
421
    ltime->month= (uint32_t) (period % 12L)+1;
849
422
    /* Adjust day if the new month doesn't have enough days */
850
423
    if (ltime->day > days_in_month[ltime->month-1])
851
424
    {
861
434
  return 0;                                     // Ok
862
435
 
863
436
invalid_date:
864
 
  push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
437
  push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
865
438
                      ER_DATETIME_FUNCTION_OVERFLOW,
866
439
                      ER(ER_DATETIME_FUNCTION_OVERFLOW),
867
440
                      "datetime");
913
486
    days= (long)l_time1->day - l_sign * (long)l_time2->day;
914
487
  else
915
488
  {
916
 
    days= calc_daynr((uint) l_time1->year,
917
 
                     (uint) l_time1->month,
918
 
                     (uint) l_time1->day);
 
489
    days= calc_daynr((uint32_t) l_time1->year,
 
490
                     (uint32_t) l_time1->month,
 
491
                     (uint32_t) l_time1->day);
919
492
    if (l_time2->time_type == DRIZZLE_TIMESTAMP_TIME)
920
493
      days-= l_sign * (long)l_time2->day;
921
494
    else
922
 
      days-= l_sign*calc_daynr((uint) l_time2->year,
923
 
                               (uint) l_time2->month,
924
 
                               (uint) l_time2->day);
 
495
      days-= l_sign*calc_daynr((uint32_t) l_time2->year,
 
496
                               (uint32_t) l_time2->month,
 
497
                               (uint32_t) l_time2->day);
925
498
  }
926
499
 
927
500
  microseconds= ((int64_t)days*86400L +