~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/time.cc

  • Committer: Eric Herman
  • Date: 2008-12-07 12:17:49 UTC
  • mto: (656.1.14 devel)
  • mto: This revision was merged to the branch mainline in revision 670.
  • Revision ID: eric@mysql.com-20081207121749-kv5yp8o1u3fxb0lz
added some essential notes to the README

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
 
#include "mysql_priv.h"
20
 
#include <m_ctype.h>
21
 
 
22
 
 
23
 
        /* Some functions to calculate dates */
 
23
#include <drizzled/server_includes.h>
 
24
#include <drizzled/error.h>
 
25
#include <drizzled/util/test.h>
 
26
#include <drizzled/tztime.h>
 
27
#include <drizzled/item/timefunc.h>
 
28
#include <drizzled/session.h>
 
29
 
 
30
/* Some functions to calculate dates */
24
31
 
25
32
#ifndef TESTTIME
26
33
 
29
36
 
30
37
  'interval_type_to_name' is ordered and sorted on interval size and
31
38
  interval complexity.
32
 
  Order of elements in 'interval_type_to_name' should correspond to 
 
39
  Order of elements in 'interval_type_to_name' should correspond to
33
40
  the order of elements in 'interval_type' enum
34
 
  
 
41
 
35
42
  See also interval_type, interval_names
36
43
*/
37
44
 
56
63
  { C_STRING_WITH_LEN("HOUR_MICROSECOND")},
57
64
  { C_STRING_WITH_LEN("MINUTE_MICROSECOND")},
58
65
  { C_STRING_WITH_LEN("SECOND_MICROSECOND")}
59
 
}; 
 
66
};
60
67
 
61
68
        /* Calc weekday from daynr */
62
69
        /* Returns 0 for monday, 1 for tuesday .... */
88
95
                                        to ISO 8601:1988
89
96
                          If set        The week that contains the first
90
97
                                        'first-day-of-week' is week 1.
91
 
        
 
98
 
92
99
        ISO 8601:1988 means that if the week containing January 1 has
93
100
        four or more days in the new year, then it is week 1;
94
101
        Otherwise it is the last week of the previous year, and the
95
102
        next week is week 1.
96
103
*/
97
104
 
98
 
uint calc_week(MYSQL_TIME *l_time, uint week_behaviour, uint *year)
 
105
uint32_t calc_week(DRIZZLE_TIME *l_time, uint32_t week_behaviour, uint32_t *year)
99
106
{
100
 
  uint 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 days;
 
108
  uint32_t daynr= calc_daynr(l_time->year,l_time->month,l_time->day);
 
109
  uint32_t first_daynr= calc_daynr(l_time->year,1,1);
103
110
  bool monday_first= test(week_behaviour & WEEK_MONDAY_FIRST);
104
111
  bool week_year= test(week_behaviour & WEEK_YEAR);
105
112
  bool first_weekday= test(week_behaviour & WEEK_FIRST_WEEKDAY);
106
113
 
107
 
  uint weekday=calc_weekday(first_daynr, !monday_first);
 
114
  uint32_t weekday=calc_weekday(first_daynr, !monday_first);
108
115
  *year=l_time->year;
109
116
 
110
117
  if (l_time->month == 1 && l_time->day <= 7-weekday)
138
145
        /* Change a daynr to year, month and day */
139
146
        /* Daynr 0 is returned as date 00.00.00 */
140
147
 
141
 
void get_date_from_daynr(long daynr,uint *ret_year,uint *ret_month,
142
 
                         uint *ret_day)
 
148
void get_date_from_daynr(long daynr,uint32_t *ret_year,uint32_t *ret_month,
 
149
                         uint32_t *ret_day)
143
150
{
144
 
  uint year,temp,leap_day,day_of_year,days_in_year;
145
 
  uchar *month_pos;
 
151
  uint32_t year,temp,leap_day,day_of_year,days_in_year;
 
152
  unsigned char *month_pos;
146
153
 
147
154
  if (daynr <= 365L || daynr >= 3652500)
148
155
  {                                             /* Fix if wrong daynr */
181
188
 
182
189
        /* Functions to handle periods */
183
190
 
184
 
ulong convert_period_to_month(ulong period)
 
191
uint32_t convert_period_to_month(uint32_t period)
185
192
{
186
 
  ulong a,b;
 
193
  uint32_t a,b;
187
194
  if (period == 0)
188
195
    return 0L;
189
196
  if ((a=period/100) < YY_PART_YEAR)
195
202
}
196
203
 
197
204
 
198
 
ulong convert_month_to_period(ulong month)
 
205
uint32_t convert_month_to_period(uint32_t month)
199
206
{
200
 
  ulong year;
 
207
  uint32_t year;
201
208
  if (month == 0L)
202
209
    return 0L;
203
210
  if ((year=month/12) < 100)
209
216
 
210
217
 
211
218
/*
212
 
  Convert a timestamp string to a MYSQL_TIME value and produce a warning 
 
219
  Convert a timestamp string to a DRIZZLE_TIME value and produce a warning
213
220
  if string was truncated during conversion.
214
221
 
215
222
  NOTE
216
223
    See description of str_to_datetime() for more information.
217
224
*/
218
225
 
219
 
timestamp_type
220
 
str_to_datetime_with_warn(const char *str, uint length, MYSQL_TIME *l_time,
221
 
                          uint flags)
 
226
enum enum_drizzle_timestamp_type
 
227
str_to_datetime_with_warn(const char *str, uint32_t length, DRIZZLE_TIME *l_time,
 
228
                          uint32_t flags)
222
229
{
223
230
  int was_cut;
224
 
  THD *thd= current_thd;
225
 
  timestamp_type ts_type;
226
 
  
 
231
  Session *session= current_session;
 
232
  enum enum_drizzle_timestamp_type ts_type;
 
233
 
227
234
  ts_type= str_to_datetime(str, length, l_time,
228
 
                           (flags | (thd->variables.sql_mode &
 
235
                           (flags | (session->variables.sql_mode &
229
236
                                     (MODE_INVALID_DATES |
230
237
                                      MODE_NO_ZERO_DATE))),
231
238
                           &was_cut);
232
 
  if (was_cut || ts_type <= MYSQL_TIMESTAMP_ERROR)
233
 
    make_truncated_value_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
234
 
                                 str, length, ts_type,  NullS);
 
239
  if (was_cut || ts_type <= DRIZZLE_TIMESTAMP_ERROR)
 
240
    make_truncated_value_warning(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
241
                                 str, length, ts_type,  NULL);
235
242
  return ts_type;
236
243
}
237
244
 
238
245
 
239
246
/*
240
 
  Convert a datetime from broken-down MYSQL_TIME representation to corresponding 
 
247
  Convert a datetime from broken-down DRIZZLE_TIME representation to corresponding
241
248
  TIMESTAMP value.
242
249
 
243
250
  SYNOPSIS
244
251
    TIME_to_timestamp()
245
 
      thd             - current thread
246
 
      t               - datetime in broken-down representation, 
 
252
      session             - current thread
 
253
      t               - datetime in broken-down representation,
247
254
      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 
 
255
                        value which doesn't exists (falls into the spring
249
256
                        time-gap) or to false otherwise.
250
 
   
 
257
 
251
258
  RETURN
252
259
     Number seconds in UTC since start of Unix Epoch corresponding to t.
253
260
     0 - t contains datetime value which is out of TIMESTAMP range.
254
 
     
 
261
 
255
262
*/
256
 
my_time_t TIME_to_timestamp(THD *thd, const MYSQL_TIME *t, bool *in_dst_time_gap)
 
263
my_time_t TIME_to_timestamp(Session *session, const DRIZZLE_TIME *t,
 
264
                            bool *in_dst_time_gap)
257
265
{
258
266
  my_time_t timestamp;
259
267
 
260
268
  *in_dst_time_gap= 0;
261
 
  thd->time_zone_used= 1;
262
269
 
263
 
  timestamp= thd->variables.time_zone->TIME_to_gmt_sec(t, in_dst_time_gap);
 
270
  timestamp= session->variables.time_zone->TIME_to_gmt_sec(t, in_dst_time_gap);
264
271
  if (timestamp)
265
272
  {
266
273
    return timestamp;
272
279
 
273
280
 
274
281
/*
275
 
  Convert a time string to a MYSQL_TIME struct and produce a warning
 
282
  Convert a time string to a DRIZZLE_TIME struct and produce a warning
276
283
  if string was cut during conversion.
277
284
 
278
285
  NOTE
279
286
    See str_to_time() for more info.
280
287
*/
281
288
bool
282
 
str_to_time_with_warn(const char *str, uint length, MYSQL_TIME *l_time)
 
289
str_to_time_with_warn(const char *str, uint32_t length, DRIZZLE_TIME *l_time)
283
290
{
284
291
  int warning;
285
292
  bool ret_val= str_to_time(str, length, l_time, &warning);
286
293
  if (ret_val || warning)
287
 
    make_truncated_value_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
288
 
                                 str, length, MYSQL_TIMESTAMP_TIME, NullS);
 
294
    make_truncated_value_warning(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
295
                                 str, length, DRIZZLE_TIMESTAMP_TIME, NULL);
289
296
  return ret_val;
290
297
}
291
298
 
294
301
  Convert a system time structure to TIME
295
302
*/
296
303
 
297
 
void localtime_to_TIME(MYSQL_TIME *to, struct tm *from)
 
304
void localtime_to_TIME(DRIZZLE_TIME *to, struct tm *from)
298
305
{
299
306
  to->neg=0;
300
307
  to->second_part=0;
306
313
  to->second=   (int) from->tm_sec;
307
314
}
308
315
 
309
 
void calc_time_from_sec(MYSQL_TIME *to, long seconds, long microseconds)
 
316
void calc_time_from_sec(DRIZZLE_TIME *to, long seconds, long microseconds)
310
317
{
311
318
  long t_seconds;
312
319
  // to->neg is not cleared, it may already be set to a useful value
313
 
  to->time_type= MYSQL_TIMESTAMP_TIME;
 
320
  to->time_type= DRIZZLE_TIMESTAMP_TIME;
314
321
  to->year= 0;
315
322
  to->month= 0;
316
323
  to->day= 0;
348
355
    1   error
349
356
*/
350
357
 
351
 
bool parse_date_time_format(timestamp_type format_type, 
352
 
                            const char *format, uint format_length,
 
358
bool parse_date_time_format(enum enum_drizzle_timestamp_type format_type,
 
359
                            const char *format, uint32_t format_length,
353
360
                            DATE_TIME_FORMAT *date_time_format)
354
361
{
355
 
  uint offset= 0, separators= 0;
 
362
  uint32_t offset= 0, separators= 0;
356
363
  const char *ptr= format, *format_str;
357
364
  const char *end= ptr+format_length;
358
 
  uchar *dt_pos= date_time_format->positions;
 
365
  unsigned char *dt_pos= date_time_format->positions;
359
366
  /* need_p is set if we are using AM/PM format */
360
367
  bool need_p= 0, allow_separator= 0;
361
 
  ulong part_map= 0, separator_map= 0;
 
368
  uint32_t part_map= 0, separator_map= 0;
362
369
  const char *parts[16];
363
370
 
364
371
  date_time_format->time_separator= 0;
375
382
  {
376
383
    if (*ptr == '%' && ptr+1 != end)
377
384
    {
378
 
      uint position;
 
385
      uint32_t position;
379
386
      switch (*++ptr) {
380
387
      case 'y':                                 // Year
381
388
      case 'Y':
428
435
      */
429
436
      if (part_map && position <= 2 && !(part_map & (1 | 2 | 4)))
430
437
        offset=5;
431
 
      part_map|= (ulong) 1 << position;
 
438
      part_map|= UINT32_C(1) << position;
432
439
      dt_pos[position]= offset++;
433
440
      allow_separator= 1;
434
441
    }
443
450
      allow_separator= 0;                       // Don't allow two separators
444
451
      separators++;
445
452
      /* Store in separator_map which parts are punct characters */
446
 
      if (my_ispunct(&my_charset_latin1, *ptr))
447
 
        separator_map|= (ulong) 1 << (offset-1);
448
 
      else if (!my_isspace(&my_charset_latin1, *ptr))
 
453
      if (my_ispunct(&my_charset_utf8_general_ci, *ptr))
 
454
        separator_map|= 1 << (offset-1);
 
455
      else if (!my_isspace(&my_charset_utf8_general_ci, *ptr))
449
456
        return 1;
450
457
    }
451
458
  }
466
473
    The last test is to ensure that %p is used if and only if
467
474
    it's needed.
468
475
  */
469
 
  if ((format_type == MYSQL_TIMESTAMP_DATETIME &&
470
 
       !test_all_bits(part_map, (1 | 2 | 4 | 8 | 16 | 32))) ||
471
 
      (format_type == MYSQL_TIMESTAMP_DATE && part_map != (1 | 2 | 4)) ||
472
 
      (format_type == MYSQL_TIMESTAMP_TIME &&
473
 
       !test_all_bits(part_map, 8 | 16 | 32)) ||
 
476
  if ((format_type == DRIZZLE_TIMESTAMP_DATETIME &&
 
477
       !test_all_bits(part_map, (uint32_t) (1 | 2 | 4 | 8 | 16 | 32))) ||
 
478
      (format_type == DRIZZLE_TIMESTAMP_DATE && part_map != (1 | 2 | 4)) ||
 
479
      (format_type == DRIZZLE_TIMESTAMP_TIME &&
 
480
       !test_all_bits(part_map, (uint32_t) (8 | 16 | 32))) ||
474
481
      !allow_separator ||                       // %option should be last
475
482
      (need_p && dt_pos[6] +1 != dt_pos[7]) ||
476
483
      (need_p ^ (dt_pos[7] != 255)))
479
486
  if (dt_pos[6] != 255)                         // If fractional seconds
480
487
  {
481
488
    /* remove fractional seconds from later tests */
482
 
    uint pos= dt_pos[6] -1;
 
489
    uint32_t pos= dt_pos[6] -1;
483
490
    /* 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)                        
 
491
    separator_map= ((separator_map & ((1 << pos)-1)) |
 
492
                    ((separator_map & ~((1 << pos)-1)) >> 1));
 
493
    if (part_map & 64)
487
494
    {
488
495
      separators--;                             // There is always a separator
489
496
      need_p= 1;                                // force use of separators
498
505
  {
499
506
    if (need_p && parts[7] != parts[6]+2)
500
507
      separators--;
501
 
  }     
 
508
  }
502
509
  /*
503
510
    Calculate if %p is in first or last part of the datetime field
504
511
 
507
514
  */
508
515
  offset= dt_pos[6] <= 3 ? 3 : 6;
509
516
  /* Remove separator before %p from sep map */
510
 
  separator_map= ((separator_map & ((ulong) (1 << offset)-1)) |
511
 
                  ((separator_map & ~((ulong) (1 << offset)-1)) >> 1));
 
517
  separator_map= ((separator_map & ((1 << offset)-1)) |
 
518
                  ((separator_map & ~((1 << offset)-1)) >> 1));
512
519
 
513
520
  format_str= 0;
514
521
  switch (format_type) {
515
 
  case MYSQL_TIMESTAMP_DATE:
 
522
  case DRIZZLE_TIMESTAMP_DATE:
516
523
    format_str= known_date_time_formats[INTERNAL_FORMAT].date_format;
517
524
    /* fall through */
518
 
  case MYSQL_TIMESTAMP_TIME:
 
525
  case DRIZZLE_TIMESTAMP_TIME:
519
526
    if (!format_str)
520
527
      format_str=known_date_time_formats[INTERNAL_FORMAT].time_format;
521
528
 
525
532
    */
526
533
    if (format_length == 6 && !need_p &&
527
534
        !my_strnncoll(&my_charset_bin,
528
 
                      (const uchar *) format, 6, 
529
 
                      (const uchar *) format_str, 6))
 
535
                      (const unsigned char *) format, 6,
 
536
                      (const unsigned char *) format_str, 6))
530
537
      return 0;
531
538
    if (separator_map == (1 | 2))
532
539
    {
533
 
      if (format_type == MYSQL_TIMESTAMP_TIME)
 
540
      if (format_type == DRIZZLE_TIMESTAMP_TIME)
534
541
      {
535
542
        if (*(format+2) != *(format+5))
536
543
          break;                                // Error
540
547
      return 0;
541
548
    }
542
549
    break;
543
 
  case MYSQL_TIMESTAMP_DATETIME:
 
550
  case DRIZZLE_TIMESTAMP_DATETIME:
544
551
    /*
545
552
      If there is no separators, allow the internal format as we can read
546
553
      this.  If separators are used, they must be between each part.
547
554
      Between DATE and TIME we also allow space as separator
548
555
    */
549
556
    if ((format_length == 12 && !need_p &&
550
 
         !my_strnncoll(&my_charset_bin, 
551
 
                       (const uchar *) format, 12,
552
 
                       (const uchar*) known_date_time_formats[INTERNAL_FORMAT].datetime_format,
 
557
         !my_strnncoll(&my_charset_bin,
 
558
                       (const unsigned char *) format, 12,
 
559
                       (const unsigned char*) known_date_time_formats[INTERNAL_FORMAT].datetime_format,
553
560
                       12)) ||
554
561
        (separators == 5 && separator_map == (1 | 2 | 8 | 16)))
555
562
      return 0;
572
579
    format_length       Length of string
573
580
 
574
581
  NOTES
575
 
    The returned object should be freed with my_free()
 
582
    The returned object should be freed with free()
576
583
 
577
584
  RETURN
578
585
    NULL ponter:        Error
580
587
*/
581
588
 
582
589
DATE_TIME_FORMAT
583
 
*date_time_format_make(timestamp_type format_type,
584
 
                       const char *format_str, uint format_length)
 
590
*date_time_format_make(enum enum_drizzle_timestamp_type format_type,
 
591
                       const char *format_str, uint32_t format_length)
585
592
{
586
593
  DATE_TIME_FORMAT tmp;
587
594
 
591
598
  {
592
599
    tmp.format.str=    (char*) format_str;
593
600
    tmp.format.length= format_length;
594
 
    return date_time_format_copy((THD *)0, &tmp);
 
601
    return date_time_format_copy((Session *)0, &tmp);
595
602
  }
596
603
  return 0;
597
604
}
602
609
 
603
610
  SYNOPSIS
604
611
    date_and_time_format_copy()
605
 
    thd                 Set if variable should be allocated in thread mem
 
612
    session                     Set if variable should be allocated in thread mem
606
613
    format              format to copy
607
614
 
608
615
  NOTES
609
 
    The returned object should be freed with my_free()
 
616
    The returned object should be freed with free()
610
617
 
611
618
  RETURN
612
619
    NULL ponter:        Error
613
620
    new object
614
621
*/
615
622
 
616
 
DATE_TIME_FORMAT *date_time_format_copy(THD *thd, DATE_TIME_FORMAT *format)
 
623
DATE_TIME_FORMAT *date_time_format_copy(Session *session, DATE_TIME_FORMAT *format)
617
624
{
618
625
  DATE_TIME_FORMAT *new_format;
619
 
  ulong length= sizeof(*format) + format->format.length + 1;
 
626
  uint32_t length= sizeof(*format) + format->format.length + 1;
620
627
 
621
 
  if (thd)
622
 
    new_format= (DATE_TIME_FORMAT *) thd->alloc(length);
 
628
  if (session)
 
629
    new_format= (DATE_TIME_FORMAT *) session->alloc(length);
623
630
  else
624
 
    new_format=  (DATE_TIME_FORMAT *) my_malloc(length, MYF(MY_WME));
 
631
    new_format=  (DATE_TIME_FORMAT *) malloc(length);
625
632
  if (new_format)
626
633
  {
627
634
    /* Put format string after current pos */
628
635
    new_format->format.str= (char*) (new_format+1);
629
 
    memcpy((char*) new_format->positions, (char*) format->positions,
 
636
    memcpy(new_format->positions, format->positions,
630
637
           sizeof(format->positions));
631
638
    new_format->time_separator= format->time_separator;
632
639
    /* We make the string null terminated for easy printf in SHOW VARIABLES */
633
 
    memcpy((char*) new_format->format.str, format->format.str,
 
640
    memcpy(new_format->format.str, format->format.str,
634
641
           format->format.length);
635
642
    new_format->format.str[format->format.length]= 0;
636
643
    new_format->format.length= format->format.length;
656
663
*/
657
664
 
658
665
const char *get_date_time_format_str(KNOWN_DATE_TIME_FORMAT *format,
659
 
                                     timestamp_type type)
 
666
                                     enum enum_drizzle_timestamp_type type)
660
667
{
661
668
  switch (type) {
662
 
  case MYSQL_TIMESTAMP_DATE:
 
669
  case DRIZZLE_TIMESTAMP_DATE:
663
670
    return format->date_format;
664
 
  case MYSQL_TIMESTAMP_DATETIME:
 
671
  case DRIZZLE_TIMESTAMP_DATETIME:
665
672
    return format->datetime_format;
666
 
  case MYSQL_TIMESTAMP_TIME:
 
673
  case DRIZZLE_TIMESTAMP_TIME:
667
674
    return format->time_format;
668
675
  default:
669
676
    assert(0);                          // Impossible
673
680
 
674
681
/****************************************************************************
675
682
  Functions to create default time/date/datetime strings
676
 
 
 
683
 
677
684
  NOTE:
678
685
    For the moment the DATE_TIME_FORMAT argument is ignored becasue
679
686
    MySQL doesn't support comparing of date/time/datetime strings that
680
687
    are not in arbutary order as dates are compared as strings in some
681
688
    context)
682
 
    This functions don't check that given MYSQL_TIME structure members are
683
 
    in valid range. If they are not, return value won't reflect any 
 
689
    This functions don't check that given DRIZZLE_TIME structure members are
 
690
    in valid range. If they are not, return value won't reflect any
684
691
    valid date either. Additionally, make_time doesn't take into
685
692
    account time->day member: it's assumed that days have been converted
686
693
    to hours already.
687
694
****************************************************************************/
688
695
 
689
696
void make_time(const DATE_TIME_FORMAT *format __attribute__((unused)),
690
 
               const MYSQL_TIME *l_time, String *str)
 
697
               const DRIZZLE_TIME *l_time, String *str)
691
698
{
692
 
  uint length= (uint) my_time_to_str(l_time, (char*) str->ptr());
 
699
  uint32_t length= (uint) my_time_to_str(l_time, (char*) str->ptr());
693
700
  str->length(length);
694
701
  str->set_charset(&my_charset_bin);
695
702
}
696
703
 
697
704
 
698
705
void make_date(const DATE_TIME_FORMAT *format __attribute__((unused)),
699
 
               const MYSQL_TIME *l_time, String *str)
 
706
               const DRIZZLE_TIME *l_time, String *str)
700
707
{
701
 
  uint length= (uint) my_date_to_str(l_time, (char*) str->ptr());
 
708
  uint32_t length= (uint) my_date_to_str(l_time, (char*) str->ptr());
702
709
  str->length(length);
703
710
  str->set_charset(&my_charset_bin);
704
711
}
705
712
 
706
713
 
707
714
void make_datetime(const DATE_TIME_FORMAT *format __attribute__((unused)),
708
 
                   const MYSQL_TIME *l_time, String *str)
 
715
                   const DRIZZLE_TIME *l_time, String *str)
709
716
{
710
 
  uint length= (uint) my_datetime_to_str(l_time, (char*) str->ptr());
 
717
  uint32_t length= (uint) my_datetime_to_str(l_time, (char*) str->ptr());
711
718
  str->length(length);
712
719
  str->set_charset(&my_charset_bin);
713
720
}
714
721
 
715
722
 
716
 
void make_truncated_value_warning(THD *thd, MYSQL_ERROR::enum_warning_level level,
 
723
void make_truncated_value_warning(Session *session, DRIZZLE_ERROR::enum_warning_level level,
717
724
                                  const char *str_val,
718
 
                                  uint str_length, timestamp_type time_type,
 
725
                                  uint32_t str_length,
 
726
                                  enum enum_drizzle_timestamp_type time_type,
719
727
                                  const char *field_name)
720
728
{
721
 
  char warn_buff[MYSQL_ERRMSG_SIZE];
 
729
  char warn_buff[DRIZZLE_ERRMSG_SIZE];
722
730
  const char *type_str;
723
 
  CHARSET_INFO *cs= &my_charset_latin1;
 
731
  CHARSET_INFO *cs= &my_charset_utf8_general_ci;
724
732
  char buff[128];
725
733
  String str(buff,(uint32_t) sizeof(buff), system_charset_info);
726
734
  str.copy(str_val, str_length, system_charset_info);
727
735
  str[str_length]= 0;               // Ensure we have end 0 for snprintf
728
736
 
729
737
  switch (time_type) {
730
 
    case MYSQL_TIMESTAMP_DATE: 
 
738
    case DRIZZLE_TIMESTAMP_DATE:
731
739
      type_str= "date";
732
740
      break;
733
 
    case MYSQL_TIMESTAMP_TIME:
 
741
    case DRIZZLE_TIMESTAMP_TIME:
734
742
      type_str= "time";
735
743
      break;
736
 
    case MYSQL_TIMESTAMP_DATETIME:  // FALLTHROUGH
 
744
    case DRIZZLE_TIMESTAMP_DATETIME:  // FALLTHROUGH
737
745
    default:
738
746
      type_str= "datetime";
739
747
      break;
742
750
    cs->cset->snprintf(cs, warn_buff, sizeof(warn_buff),
743
751
                       ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
744
752
                       type_str, str.c_ptr(), field_name,
745
 
                       (ulong) thd->row_count);
 
753
                       (uint32_t) session->row_count);
746
754
  else
747
755
  {
748
 
    if (time_type > MYSQL_TIMESTAMP_ERROR)
 
756
    if (time_type > DRIZZLE_TIMESTAMP_ERROR)
749
757
      cs->cset->snprintf(cs, warn_buff, sizeof(warn_buff),
750
758
                         ER(ER_TRUNCATED_WRONG_VALUE),
751
759
                         type_str, str.c_ptr());
753
761
      cs->cset->snprintf(cs, warn_buff, sizeof(warn_buff),
754
762
                         ER(ER_WRONG_VALUE), type_str, str.c_ptr());
755
763
  }
756
 
  push_warning(thd, level,
 
764
  push_warning(session, level,
757
765
               ER_TRUNCATED_WRONG_VALUE, warn_buff);
758
766
}
759
767
 
760
 
/* Daynumber from year 0 to 9999-12-31 */
761
 
#define MAX_DAY_NUMBER 3652424L
762
 
 
763
 
bool date_add_interval(MYSQL_TIME *ltime, interval_type int_type, INTERVAL interval)
 
768
bool date_add_interval(DRIZZLE_TIME *ltime, interval_type int_type, INTERVAL interval)
764
769
{
765
770
  long period, sign;
766
771
 
785
790
  case INTERVAL_DAY_HOUR:
786
791
  {
787
792
    int64_t sec, days, daynr, microseconds, extra_sec;
788
 
    ltime->time_type= MYSQL_TIMESTAMP_DATETIME; // Return full date
 
793
    ltime->time_type= DRIZZLE_TIMESTAMP_DATETIME; // Return full date
789
794
    microseconds= ltime->second_part + sign*interval.second_part;
790
795
    extra_sec= microseconds/1000000L;
791
796
    microseconds= microseconds%1000000L;
793
798
    sec=((ltime->day-1)*3600*24L+ltime->hour*3600+ltime->minute*60+
794
799
         ltime->second +
795
800
         sign* (int64_t) (interval.day*3600*24L +
796
 
                           interval.hour*3600LL+interval.minute*60LL+
 
801
                           interval.hour*3600L+interval.minute*60L+
797
802
                           interval.second))+ extra_sec;
798
803
    if (microseconds < 0)
799
804
    {
800
 
      microseconds+= 1000000LL;
 
805
      microseconds+= 1000000L;
801
806
      sec--;
802
807
    }
803
 
    days= sec/(3600*24LL);
804
 
    sec-= days*3600*24LL;
 
808
    days= sec/(3600*24L);
 
809
    sec-= days*3600*24L;
805
810
    if (sec < 0)
806
811
    {
807
812
      days--;
808
 
      sec+= 3600*24LL;
 
813
      sec+= 3600*24L;
809
814
    }
810
815
    ltime->second_part= (uint) microseconds;
811
816
    ltime->second= (uint) (sec % 60);
824
829
    period= (calc_daynr(ltime->year,ltime->month,ltime->day) +
825
830
             sign * (long) interval.day);
826
831
    /* Daynumber from year 0 to 9999-12-31 */
827
 
    if ((ulong) period > MAX_DAY_NUMBER)
 
832
    if (period > MAX_DAY_NUMBER)
828
833
      goto invalid_date;
829
834
    get_date_from_daynr((long) period,&ltime->year,&ltime->month,&ltime->day);
830
835
    break;
831
836
  case INTERVAL_YEAR:
832
837
    ltime->year+= sign * (long) interval.year;
833
 
    if ((ulong) ltime->year >= 10000L)
 
838
    if (ltime->year >= 10000L)
834
839
      goto invalid_date;
835
840
    if (ltime->month == 2 && ltime->day == 29 &&
836
841
        calc_days_in_year(ltime->year) != 366)
841
846
  case INTERVAL_MONTH:
842
847
    period= (ltime->year*12 + sign * (long) interval.year*12 +
843
848
             ltime->month-1 + sign * (long) interval.month);
844
 
    if ((ulong) period >= 120000L)
 
849
    if (period >= 120000L)
845
850
      goto invalid_date;
846
851
    ltime->year= (uint) (period / 12);
847
852
    ltime->month= (uint) (period % 12L)+1;
860
865
  return 0;                                     // Ok
861
866
 
862
867
invalid_date:
863
 
  push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
 
868
  push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
864
869
                      ER_DATETIME_FUNCTION_OVERFLOW,
865
870
                      ER(ER_DATETIME_FUNCTION_OVERFLOW),
866
871
                      "datetime");
886
891
  NOTE
887
892
    This function calculates difference between l_time1 and l_time2 absolute
888
893
    values. So one should set l_sign and correct result if he want to take
889
 
    signs into account (i.e. for MYSQL_TIME values).
 
894
    signs into account (i.e. for DRIZZLE_TIME values).
890
895
 
891
896
  RETURN VALUES
892
897
    Returns sign of difference.
896
901
*/
897
902
 
898
903
bool
899
 
calc_time_diff(MYSQL_TIME *l_time1, MYSQL_TIME *l_time2, int l_sign, int64_t *seconds_out,
 
904
calc_time_diff(DRIZZLE_TIME *l_time1, DRIZZLE_TIME *l_time2, int l_sign, int64_t *seconds_out,
900
905
               long *microseconds_out)
901
906
{
902
907
  long days;
904
909
  int64_t microseconds;
905
910
 
906
911
  /*
907
 
    We suppose that if first argument is MYSQL_TIMESTAMP_TIME
 
912
    We suppose that if first argument is DRIZZLE_TIMESTAMP_TIME
908
913
    the second argument should be TIMESTAMP_TIME also.
909
914
    We should check it before calc_time_diff call.
910
915
  */
911
 
  if (l_time1->time_type == MYSQL_TIMESTAMP_TIME)  // Time value
 
916
  if (l_time1->time_type == DRIZZLE_TIMESTAMP_TIME)  // Time value
912
917
    days= (long)l_time1->day - l_sign * (long)l_time2->day;
913
918
  else
914
919
  {
915
920
    days= calc_daynr((uint) l_time1->year,
916
921
                     (uint) l_time1->month,
917
922
                     (uint) l_time1->day);
918
 
    if (l_time2->time_type == MYSQL_TIMESTAMP_TIME)
 
923
    if (l_time2->time_type == DRIZZLE_TIMESTAMP_TIME)
919
924
      days-= l_sign * (long)l_time2->day;
920
925
    else
921
926
      days-= l_sign*calc_daynr((uint) l_time2->year,
923
928
                               (uint) l_time2->day);
924
929
  }
925
930
 
926
 
  microseconds= ((int64_t)days*86400LL +
 
931
  microseconds= ((int64_t)days*86400L +
927
932
                 (int64_t)(l_time1->hour*3600L +
928
933
                            l_time1->minute*60L +
929
934
                            l_time1->second) -
930
935
                 l_sign*(int64_t)(l_time2->hour*3600L +
931
936
                                   l_time2->minute*60L +
932
 
                                   l_time2->second)) * 1000000LL +
 
937
                                   l_time2->second)) * 1000000L +
933
938
                (int64_t)l_time1->second_part -
934
939
                l_sign*(int64_t)l_time2->second_part;
935
940
 
946
951
 
947
952
 
948
953
/*
949
 
  Compares 2 MYSQL_TIME structures
 
954
  Compares 2 DRIZZLE_TIME structures
950
955
 
951
956
  SYNOPSIS
952
957
    my_time_compare()
964
969
*/
965
970
 
966
971
int
967
 
my_time_compare(MYSQL_TIME *a, MYSQL_TIME *b)
 
972
my_time_compare(DRIZZLE_TIME *a, DRIZZLE_TIME *b)
968
973
{
969
974
  uint64_t a_t= TIME_to_uint64_t_datetime(a);
970
975
  uint64_t b_t= TIME_to_uint64_t_datetime(b);