~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/time.cc

  • Committer: Monty Taylor
  • Date: 2008-11-16 23:47:43 UTC
  • mto: (584.1.10 devel)
  • mto: This revision was merged to the branch mainline in revision 589.
  • Revision ID: monty@inaugust.com-20081116234743-c38gmv0pa2kdefaj
BrokeĀ outĀ cached_item.

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