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
20
#include <drizzled/global.h>
21
#include <drizzled/error.h>
22
#include <drizzled/session.h>
23
#include <drizzled/server_includes.h>
24
#include <drizzled/function/time/date.h>
25
#include <drizzled/temporal_interval.h>
27
bool drizzled::TemporalInterval::initFromItem(Item *args, interval_type int_type, String *str_value)
29
uint64_t array[MAX_STRING_ELEMENTS];
31
const char *str= NULL;
33
const CHARSET_INFO * const cs= str_value->charset();
36
// Types <= microsecond can be converted as an integer
37
if (static_cast<int>(int_type) <= INTERVAL_MICROSECOND)
39
value= args->val_int();
50
// Otherwise we must convert to a string and extract the multiple parts
52
if (!(res= args->val_str(str_value)))
55
// record negative intervalls in interval->neg
57
const char *end= str+res->length();
58
// Skip the whitespace
59
while (str != end && my_isspace(cs,*str))
61
if (str != end && *str == '-')
67
length= static_cast<size_t>(end-str); // Set up pointers to new str
73
year= static_cast<uint32_t>(value);
75
case INTERVAL_QUARTER:
76
month= static_cast<uint32_t>(value*3);
79
month= static_cast<uint32_t>(value);
82
day= static_cast<uint32_t>(value*7);
85
day= static_cast<uint32_t>(value);
88
hour= static_cast<uint32_t>(value);
90
case INTERVAL_MICROSECOND:
99
case INTERVAL_YEAR_MONTH: // Allow YEAR-MONTH YYYYYMM
100
if (getIntervalFromString(str,length,cs,NUM_YEAR_MONTH_STRING_ELEMENTS,array,false))
102
year= static_cast<uint32_t>(array[0]);
103
month= static_cast<uint32_t>(array[1]);
105
case INTERVAL_DAY_HOUR:
106
if (getIntervalFromString(str,length,cs,NUM_DAY_HOUR_STRING_ELEMENTS,array,false))
108
day= static_cast<uint32_t>(array[0]);
109
hour= static_cast<uint32_t>(array[1]);
111
case INTERVAL_DAY_MICROSECOND:
112
if (getIntervalFromString(str,length,cs,NUM_DAY_MICROSECOND_STRING_ELEMENTS,array,true))
114
day= static_cast<uint32_t>(array[0]);
115
hour= static_cast<uint32_t>(array[1]);
118
second_part= array[4];
120
case INTERVAL_DAY_MINUTE:
121
if (getIntervalFromString(str,length,cs,NUM_DAY_MINUTE_STRING_ELEMENTS,array,false))
123
day= static_cast<uint32_t>(array[0]);
124
hour= static_cast<uint32_t>(array[1]);
127
case INTERVAL_DAY_SECOND:
128
if (getIntervalFromString(str,length,cs,NUM_DAY_SECOND_STRING_ELEMENTS,array,false))
130
day= static_cast<uint32_t>(array[0]);
131
hour= static_cast<uint32_t>(array[1]);
135
case INTERVAL_HOUR_MICROSECOND:
136
if (getIntervalFromString(str,length,cs,NUM_HOUR_MICROSECOND_STRING_ELEMENTS,array,true))
138
hour= static_cast<uint32_t>(array[0]);
141
second_part= array[3];
143
case INTERVAL_HOUR_MINUTE:
144
if (getIntervalFromString(str,length,cs,NUM_HOUR_MINUTE_STRING_ELEMENTS,array,false))
146
hour= static_cast<uint32_t>(array[0]);
149
case INTERVAL_HOUR_SECOND:
150
if (getIntervalFromString(str,length,cs,NUM_HOUR_SECOND_STRING_ELEMENTS,array,false))
152
hour= static_cast<uint32_t>(array[0]);
156
case INTERVAL_MINUTE_MICROSECOND:
157
if (getIntervalFromString(str,length,cs,NUM_MINUTE_MICROSECOND_STRING_ELEMENTS,array,true))
161
second_part= array[2];
163
case INTERVAL_MINUTE_SECOND:
164
if (getIntervalFromString(str,length,cs,NUM_MINUTE_SECOND_STRING_ELEMENTS,array,false))
169
case INTERVAL_SECOND_MICROSECOND:
170
if (getIntervalFromString(str,length,cs,NUM_SECOND_MICROSECOND_STRING_ELEMENTS,array,true))
173
second_part= array[1];
182
bool drizzled::TemporalInterval::addDate(DRIZZLE_TIME *ltime, interval_type int_type)
188
sign= (neg ? -1 : 1);
192
case INTERVAL_SECOND:
193
case INTERVAL_SECOND_MICROSECOND:
194
case INTERVAL_MICROSECOND:
195
case INTERVAL_MINUTE:
197
case INTERVAL_MINUTE_MICROSECOND:
198
case INTERVAL_MINUTE_SECOND:
199
case INTERVAL_HOUR_MICROSECOND:
200
case INTERVAL_HOUR_SECOND:
201
case INTERVAL_HOUR_MINUTE:
202
case INTERVAL_DAY_MICROSECOND:
203
case INTERVAL_DAY_SECOND:
204
case INTERVAL_DAY_MINUTE:
205
case INTERVAL_DAY_HOUR:
206
int64_t sec, days, daynr, microseconds, extra_sec;
207
ltime->time_type= DRIZZLE_TIMESTAMP_DATETIME; // Return full date
208
microseconds= ltime->second_part + sign*second_part;
209
extra_sec= microseconds/1000000L;
210
microseconds= microseconds%1000000L;
212
sec= ((ltime->day-1)*3600*24L+ltime->hour*3600+ltime->minute*60+
214
sign* (int64_t) (day*3600*24L +
215
hour*3600L+minute*60L+
217
if (microseconds < 0)
219
microseconds+= 1000000L;
222
days= sec/(3600*24L);
229
ltime->second_part= (uint32_t) microseconds;
230
ltime->second= (uint32_t) (sec % 60);
231
ltime->minute= (uint32_t) (sec/60 % 60);
232
ltime->hour= (uint32_t) (sec/3600);
233
daynr= calc_daynr(ltime->year,ltime->month,1) + days;
234
/* Day number from year 0 to 9999-12-31 */
235
if ((uint64_t) daynr > MAX_DAY_NUMBER)
237
get_date_from_daynr((long) daynr, <ime->year, <ime->month,
242
period= (calc_daynr(ltime->year,ltime->month,ltime->day) +
244
/* Daynumber from year 0 to 9999-12-31 */
245
if (period > MAX_DAY_NUMBER)
247
get_date_from_daynr((long) period,<ime->year,<ime->month,<ime->day);
250
ltime->year+= sign * (long) year;
251
if (ltime->year >= 10000L)
253
if (ltime->month == 2 && ltime->day == 29 &&
254
calc_days_in_year(ltime->year) != 366)
255
ltime->day= 28; // Was leap-year
257
case INTERVAL_YEAR_MONTH:
258
case INTERVAL_QUARTER:
260
period= (ltime->year*12 + sign * (long) year*12 +
261
ltime->month-1 + sign * (long) month);
262
if (period >= 120000L)
264
ltime->year= (uint32_t) (period / 12);
265
ltime->month= (uint32_t) (period % 12L)+1;
266
/* Adjust day if the new month doesn't have enough days */
267
if (ltime->day > days_in_month[ltime->month-1])
269
ltime->day= days_in_month[ltime->month-1];
270
if (ltime->month == 2 && calc_days_in_year(ltime->year) == 366)
271
ltime->day++; // Leap-year
281
push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
282
ER_DATETIME_FUNCTION_OVERFLOW,
283
ER(ER_DATETIME_FUNCTION_OVERFLOW),
289
bool drizzled::TemporalInterval::getIntervalFromString(const char *str,uint32_t length, const CHARSET_INFO * const cs,
290
uint32_t count, uint64_t *values,
293
const char *end= str+length;
296
while (str != end && !my_isdigit(cs,*str))
299
for (x= 0 ; x < count ; x++)
302
const char *start= str;
303
for (value= 0 ; str != end && my_isdigit(cs,*str) ; str++)
304
value= value * 10L + (int64_t) (*str - '0');
305
if (transform_msec && x == count - 1) // microseconds always last
307
long msec_length= 6 - (str - start);
309
value*= (long) log_10_int[msec_length];
312
while (str != end && !my_isdigit(cs,*str))
314
if (str == end && x != count-1)
317
/* Change values[0...x-1] -> values[0...count-1] */
318
bmove_upp((unsigned char*) (values+count), (unsigned char*) (values+x),
320
memset(values, 0, sizeof(*values)*(count-x));