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, Inc.
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
22
#include <drizzled/internal/m_string.h>
23
#include <drizzled/error.h>
24
#include <drizzled/session.h>
25
#include <drizzled/current_session.h>
26
#include <drizzled/function/time/date.h>
27
#include <drizzled/temporal_interval.h>
28
#include <drizzled/time_functions.h>
33
bool TemporalInterval::initFromItem(Item *args,
34
interval_type int_type,
37
uint64_t array[MAX_STRING_ELEMENTS];
39
const char *str= NULL;
41
const CHARSET_INFO * const cs= str_value->charset();
44
// Types <= microsecond can be converted as an integer
45
if (static_cast<int>(int_type) <= INTERVAL_MICROSECOND)
47
value= args->val_int();
58
// Otherwise we must convert to a string and extract the multiple parts
60
if (!(res= args->val_str(str_value)))
63
// record negative intervalls in interval->neg
65
const char *end= str+res->length();
66
// Skip the whitespace
67
while (str != end && my_isspace(cs,*str))
69
if (str != end && *str == '-')
75
length= static_cast<size_t>(end-str); // Set up pointers to new str
81
year= static_cast<uint32_t>(value);
83
case INTERVAL_QUARTER:
84
month= static_cast<uint32_t>(value*3);
87
month= static_cast<uint32_t>(value);
90
day= static_cast<uint32_t>(value*7);
93
day= static_cast<uint32_t>(value);
96
hour= static_cast<uint32_t>(value);
98
case INTERVAL_MICROSECOND:
101
case INTERVAL_MINUTE:
104
case INTERVAL_SECOND:
107
case INTERVAL_YEAR_MONTH: // Allow YEAR-MONTH YYYYYMM
108
if (getIntervalFromString(str,length,cs,NUM_YEAR_MONTH_STRING_ELEMENTS,array,false))
110
year= static_cast<uint32_t>(array[0]);
111
month= static_cast<uint32_t>(array[1]);
113
case INTERVAL_DAY_HOUR:
114
if (getIntervalFromString(str,length,cs,NUM_DAY_HOUR_STRING_ELEMENTS,array,false))
116
day= static_cast<uint32_t>(array[0]);
117
hour= static_cast<uint32_t>(array[1]);
119
case INTERVAL_DAY_MICROSECOND:
120
if (getIntervalFromString(str,length,cs,NUM_DAY_MICROSECOND_STRING_ELEMENTS,array,true))
122
day= static_cast<uint32_t>(array[0]);
123
hour= static_cast<uint32_t>(array[1]);
126
second_part= array[4];
128
case INTERVAL_DAY_MINUTE:
129
if (getIntervalFromString(str,length,cs,NUM_DAY_MINUTE_STRING_ELEMENTS,array,false))
131
day= static_cast<uint32_t>(array[0]);
132
hour= static_cast<uint32_t>(array[1]);
135
case INTERVAL_DAY_SECOND:
136
if (getIntervalFromString(str,length,cs,NUM_DAY_SECOND_STRING_ELEMENTS,array,false))
138
day= static_cast<uint32_t>(array[0]);
139
hour= static_cast<uint32_t>(array[1]);
143
case INTERVAL_HOUR_MICROSECOND:
144
if (getIntervalFromString(str,length,cs,NUM_HOUR_MICROSECOND_STRING_ELEMENTS,array,true))
146
hour= static_cast<uint32_t>(array[0]);
149
second_part= array[3];
151
case INTERVAL_HOUR_MINUTE:
152
if (getIntervalFromString(str,length,cs,NUM_HOUR_MINUTE_STRING_ELEMENTS,array,false))
154
hour= static_cast<uint32_t>(array[0]);
157
case INTERVAL_HOUR_SECOND:
158
if (getIntervalFromString(str,length,cs,NUM_HOUR_SECOND_STRING_ELEMENTS,array,false))
160
hour= static_cast<uint32_t>(array[0]);
164
case INTERVAL_MINUTE_MICROSECOND:
165
if (getIntervalFromString(str,length,cs,NUM_MINUTE_MICROSECOND_STRING_ELEMENTS,array,true))
169
second_part= array[2];
171
case INTERVAL_MINUTE_SECOND:
172
if (getIntervalFromString(str,length,cs,NUM_MINUTE_SECOND_STRING_ELEMENTS,array,false))
177
case INTERVAL_SECOND_MICROSECOND:
178
if (getIntervalFromString(str,length,cs,NUM_SECOND_MICROSECOND_STRING_ELEMENTS,array,true))
181
second_part= array[1];
190
bool TemporalInterval::addDate(type::Time *ltime, interval_type int_type)
196
sign= (neg ? -1 : 1);
200
case INTERVAL_SECOND:
201
case INTERVAL_SECOND_MICROSECOND:
202
case INTERVAL_MICROSECOND:
203
case INTERVAL_MINUTE:
205
case INTERVAL_MINUTE_MICROSECOND:
206
case INTERVAL_MINUTE_SECOND:
207
case INTERVAL_HOUR_MICROSECOND:
208
case INTERVAL_HOUR_SECOND:
209
case INTERVAL_HOUR_MINUTE:
210
case INTERVAL_DAY_MICROSECOND:
211
case INTERVAL_DAY_SECOND:
212
case INTERVAL_DAY_MINUTE:
213
case INTERVAL_DAY_HOUR:
214
int64_t sec, days, daynr, microseconds, extra_sec;
215
ltime->time_type= type::DRIZZLE_TIMESTAMP_DATETIME; // Return full date
216
microseconds= ltime->second_part + sign*second_part;
217
extra_sec= microseconds/1000000L;
218
microseconds= microseconds%1000000L;
220
sec= ((ltime->day-1)*3600*24L+ltime->hour*3600+ltime->minute*60+
222
sign* (int64_t) (day*3600*24L +
223
hour*3600L+minute*60L+
225
if (microseconds < 0)
227
microseconds+= 1000000L;
230
days= sec/(3600*24L);
237
ltime->second_part= (uint32_t) microseconds;
238
ltime->second= (uint32_t) (sec % 60);
239
ltime->minute= (uint32_t) (sec/60 % 60);
240
ltime->hour= (uint32_t) (sec/3600);
241
daynr= calc_daynr(ltime->year,ltime->month,1) + days;
242
/* Day number from year 0 to 9999-12-31 */
243
if ((uint64_t) daynr > MAX_DAY_NUMBER)
245
get_date_from_daynr((long) daynr, <ime->year, <ime->month, <ime->day);
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 || str == end)) // 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[count-x...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 */