1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
* Copyright (C) 2008 Sun Microsystems
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.
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.
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
21
#include "drizzled/internal/m_string.h"
22
#include "drizzled/error.h"
23
#include "drizzled/session.h"
25
#include "drizzled/function/time/date.h"
26
#include "drizzled/temporal_interval.h"
27
#include "drizzled/time_functions.h"
32
bool TemporalInterval::initFromItem(Item *args,
33
interval_type int_type,
36
uint64_t array[MAX_STRING_ELEMENTS];
38
const char *str= NULL;
40
const CHARSET_INFO * const cs= str_value->charset();
43
// Types <= microsecond can be converted as an integer
44
if (static_cast<int>(int_type) <= INTERVAL_MICROSECOND)
46
value= args->val_int();
57
// Otherwise we must convert to a string and extract the multiple parts
59
if (!(res= args->val_str(str_value)))
62
// record negative intervalls in interval->neg
64
const char *end= str+res->length();
65
// Skip the whitespace
66
while (str != end && my_isspace(cs,*str))
68
if (str != end && *str == '-')
74
length= static_cast<size_t>(end-str); // Set up pointers to new str
80
year= static_cast<uint32_t>(value);
82
case INTERVAL_QUARTER:
83
month= static_cast<uint32_t>(value*3);
86
month= static_cast<uint32_t>(value);
89
day= static_cast<uint32_t>(value*7);
92
day= static_cast<uint32_t>(value);
95
hour= static_cast<uint32_t>(value);
97
case INTERVAL_MICROSECOND:
100
case INTERVAL_MINUTE:
103
case INTERVAL_SECOND:
106
case INTERVAL_YEAR_MONTH: // Allow YEAR-MONTH YYYYYMM
107
if (getIntervalFromString(str,length,cs,NUM_YEAR_MONTH_STRING_ELEMENTS,array,false))
109
year= static_cast<uint32_t>(array[0]);
110
month= static_cast<uint32_t>(array[1]);
112
case INTERVAL_DAY_HOUR:
113
if (getIntervalFromString(str,length,cs,NUM_DAY_HOUR_STRING_ELEMENTS,array,false))
115
day= static_cast<uint32_t>(array[0]);
116
hour= static_cast<uint32_t>(array[1]);
118
case INTERVAL_DAY_MICROSECOND:
119
if (getIntervalFromString(str,length,cs,NUM_DAY_MICROSECOND_STRING_ELEMENTS,array,true))
121
day= static_cast<uint32_t>(array[0]);
122
hour= static_cast<uint32_t>(array[1]);
125
second_part= array[4];
127
case INTERVAL_DAY_MINUTE:
128
if (getIntervalFromString(str,length,cs,NUM_DAY_MINUTE_STRING_ELEMENTS,array,false))
130
day= static_cast<uint32_t>(array[0]);
131
hour= static_cast<uint32_t>(array[1]);
134
case INTERVAL_DAY_SECOND:
135
if (getIntervalFromString(str,length,cs,NUM_DAY_SECOND_STRING_ELEMENTS,array,false))
137
day= static_cast<uint32_t>(array[0]);
138
hour= static_cast<uint32_t>(array[1]);
142
case INTERVAL_HOUR_MICROSECOND:
143
if (getIntervalFromString(str,length,cs,NUM_HOUR_MICROSECOND_STRING_ELEMENTS,array,true))
145
hour= static_cast<uint32_t>(array[0]);
148
second_part= array[3];
150
case INTERVAL_HOUR_MINUTE:
151
if (getIntervalFromString(str,length,cs,NUM_HOUR_MINUTE_STRING_ELEMENTS,array,false))
153
hour= static_cast<uint32_t>(array[0]);
156
case INTERVAL_HOUR_SECOND:
157
if (getIntervalFromString(str,length,cs,NUM_HOUR_SECOND_STRING_ELEMENTS,array,false))
159
hour= static_cast<uint32_t>(array[0]);
163
case INTERVAL_MINUTE_MICROSECOND:
164
if (getIntervalFromString(str,length,cs,NUM_MINUTE_MICROSECOND_STRING_ELEMENTS,array,true))
168
second_part= array[2];
170
case INTERVAL_MINUTE_SECOND:
171
if (getIntervalFromString(str,length,cs,NUM_MINUTE_SECOND_STRING_ELEMENTS,array,false))
176
case INTERVAL_SECOND_MICROSECOND:
177
if (getIntervalFromString(str,length,cs,NUM_SECOND_MICROSECOND_STRING_ELEMENTS,array,true))
180
second_part= array[1];
189
bool TemporalInterval::addDate(DRIZZLE_TIME *ltime, interval_type int_type)
195
sign= (neg ? -1 : 1);
199
case INTERVAL_SECOND:
200
case INTERVAL_SECOND_MICROSECOND:
201
case INTERVAL_MICROSECOND:
202
case INTERVAL_MINUTE:
204
case INTERVAL_MINUTE_MICROSECOND:
205
case INTERVAL_MINUTE_SECOND:
206
case INTERVAL_HOUR_MICROSECOND:
207
case INTERVAL_HOUR_SECOND:
208
case INTERVAL_HOUR_MINUTE:
209
case INTERVAL_DAY_MICROSECOND:
210
case INTERVAL_DAY_SECOND:
211
case INTERVAL_DAY_MINUTE:
212
case INTERVAL_DAY_HOUR:
213
int64_t sec, days, daynr, microseconds, extra_sec;
214
ltime->time_type= DRIZZLE_TIMESTAMP_DATETIME; // Return full date
215
microseconds= ltime->second_part + sign*second_part;
216
extra_sec= microseconds/1000000L;
217
microseconds= microseconds%1000000L;
219
sec= ((ltime->day-1)*3600*24L+ltime->hour*3600+ltime->minute*60+
221
sign* (int64_t) (day*3600*24L +
222
hour*3600L+minute*60L+
224
if (microseconds < 0)
226
microseconds+= 1000000L;
229
days= sec/(3600*24L);
236
ltime->second_part= (uint32_t) microseconds;
237
ltime->second= (uint32_t) (sec % 60);
238
ltime->minute= (uint32_t) (sec/60 % 60);
239
ltime->hour= (uint32_t) (sec/3600);
240
daynr= calc_daynr(ltime->year,ltime->month,1) + days;
241
/* Day number from year 0 to 9999-12-31 */
242
if ((uint64_t) daynr > MAX_DAY_NUMBER)
244
get_date_from_daynr((long) daynr, <ime->year, <ime->month,
249
period= (calc_daynr(ltime->year,ltime->month,ltime->day) +
251
/* Daynumber from year 0 to 9999-12-31 */
252
if (period > MAX_DAY_NUMBER)
254
get_date_from_daynr((long) period,<ime->year,<ime->month,<ime->day);
257
ltime->year+= sign * (long) year;
258
if (ltime->year >= 10000L)
260
if (ltime->month == 2 && ltime->day == 29 &&
261
calc_days_in_year(ltime->year) != 366)
262
ltime->day= 28; // Was leap-year
264
case INTERVAL_YEAR_MONTH:
265
case INTERVAL_QUARTER:
267
period= (ltime->year*12 + sign * (long) year*12 +
268
ltime->month-1 + sign * (long) month);
269
if (period >= 120000L)
271
ltime->year= (uint32_t) (period / 12);
272
ltime->month= (uint32_t) (period % 12L)+1;
273
/* Adjust day if the new month doesn't have enough days */
274
if (ltime->day > days_in_month[ltime->month-1])
276
ltime->day= days_in_month[ltime->month-1];
277
if (ltime->month == 2 && calc_days_in_year(ltime->year) == 366)
278
ltime->day++; // Leap-year
288
push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
289
ER_DATETIME_FUNCTION_OVERFLOW,
290
ER(ER_DATETIME_FUNCTION_OVERFLOW),
296
bool TemporalInterval::getIntervalFromString(const char *str,
298
const CHARSET_INFO * const cs,
299
uint32_t count, uint64_t *values,
302
const char *end= str+length;
305
while (str != end && !my_isdigit(cs,*str))
308
for (x= 0 ; x < count ; x++)
311
const char *start= str;
312
for (value= 0 ; str != end && my_isdigit(cs,*str) ; str++)
313
value= value * 10L + (int64_t) (*str - '0');
314
if (transform_msec && x == count - 1) // microseconds always last
316
long msec_length= 6 - (str - start);
318
value*= (long) log_10_int[msec_length];
321
while (str != end && !my_isdigit(cs,*str))
323
if (str == end && x != count-1)
326
/* Change values[0...x-1] -> values[0...count-1] */
327
internal::bmove_upp((unsigned char*) (values+count),
328
(unsigned char*) (values+x),
330
memset(values, 0, sizeof(*values)*(count-x));
337
} /* namespace drizzled */