Drizzled Public API Documentation

temporal_interval.cc
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, Inc.
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  */
19 
20 #include <config.h>
21 
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>
29 
30 namespace drizzled
31 {
32 
34  interval_type int_type,
35  String *str_value)
36 {
37  uint64_t array[MAX_STRING_ELEMENTS];
38  int64_t value= 0;
39  const char *str= NULL;
40  size_t length= 0;
41  const charset_info_st * const cs= str_value->charset();
42 
43 
44  // Types <= microsecond can be converted as an integer
45  if (static_cast<int>(int_type) <= INTERVAL_MICROSECOND)
46  {
47  value= args->val_int();
48  if (args->null_value)
49  return true;
50  if (value < 0)
51  {
52  neg= true;
53  value= -value;
54  }
55  }
56  else
57  {
58  // Otherwise we must convert to a string and extract the multiple parts
59  String *res;
60  if (!(res= args->val_str(str_value)))
61  return true;
62 
63  // record negative intervalls in interval->neg
64  str= res->ptr();
65  const char *end= str+res->length();
66  // Skip the whitespace
67  while (str != end && cs->isspace(*str))
68  str++;
69  if (str != end && *str == '-')
70  {
71  neg= true;
72  // skip the -
73  str++;
74  }
75  length= static_cast<size_t>(end-str); // Set up pointers to new str
76  }
77 
78  switch (int_type)
79  {
80  case INTERVAL_YEAR:
81  year= static_cast<uint32_t>(value);
82  break;
83  case INTERVAL_QUARTER:
84  month= static_cast<uint32_t>(value*3);
85  break;
86  case INTERVAL_MONTH:
87  month= static_cast<uint32_t>(value);
88  break;
89  case INTERVAL_WEEK:
90  day= static_cast<uint32_t>(value*7);
91  break;
92  case INTERVAL_DAY:
93  day= static_cast<uint32_t>(value);
94  break;
95  case INTERVAL_HOUR:
96  hour= static_cast<uint32_t>(value);
97  break;
98  case INTERVAL_MICROSECOND:
99  second_part= value;
100  break;
101  case INTERVAL_MINUTE:
102  minute= value;
103  break;
104  case INTERVAL_SECOND:
105  second= value;
106  break;
107  case INTERVAL_YEAR_MONTH: // Allow YEAR-MONTH YYYYYMM
108  if (getIntervalFromString(str,length,cs,NUM_YEAR_MONTH_STRING_ELEMENTS,array,false))
109  return true;
110  year= static_cast<uint32_t>(array[0]);
111  month= static_cast<uint32_t>(array[1]);
112  break;
113  case INTERVAL_DAY_HOUR:
114  if (getIntervalFromString(str,length,cs,NUM_DAY_HOUR_STRING_ELEMENTS,array,false))
115  return true;
116  day= static_cast<uint32_t>(array[0]);
117  hour= static_cast<uint32_t>(array[1]);
118  break;
119  case INTERVAL_DAY_MICROSECOND:
120  if (getIntervalFromString(str,length,cs,NUM_DAY_MICROSECOND_STRING_ELEMENTS,array,true))
121  return true;
122  day= static_cast<uint32_t>(array[0]);
123  hour= static_cast<uint32_t>(array[1]);
124  minute= array[2];
125  second= array[3];
126  second_part= array[4];
127  break;
128  case INTERVAL_DAY_MINUTE:
129  if (getIntervalFromString(str,length,cs,NUM_DAY_MINUTE_STRING_ELEMENTS,array,false))
130  return true;
131  day= static_cast<uint32_t>(array[0]);
132  hour= static_cast<uint32_t>(array[1]);
133  minute= array[2];
134  break;
135  case INTERVAL_DAY_SECOND:
136  if (getIntervalFromString(str,length,cs,NUM_DAY_SECOND_STRING_ELEMENTS,array,false))
137  return true;
138  day= static_cast<uint32_t>(array[0]);
139  hour= static_cast<uint32_t>(array[1]);
140  minute= array[2];
141  second= array[3];
142  break;
143  case INTERVAL_HOUR_MICROSECOND:
144  if (getIntervalFromString(str,length,cs,NUM_HOUR_MICROSECOND_STRING_ELEMENTS,array,true))
145  return true;
146  hour= static_cast<uint32_t>(array[0]);
147  minute= array[1];
148  second= array[2];
149  second_part= array[3];
150  break;
151  case INTERVAL_HOUR_MINUTE:
152  if (getIntervalFromString(str,length,cs,NUM_HOUR_MINUTE_STRING_ELEMENTS,array,false))
153  return true;
154  hour= static_cast<uint32_t>(array[0]);
155  minute= array[1];
156  break;
157  case INTERVAL_HOUR_SECOND:
158  if (getIntervalFromString(str,length,cs,NUM_HOUR_SECOND_STRING_ELEMENTS,array,false))
159  return true;
160  hour= static_cast<uint32_t>(array[0]);
161  minute= array[1];
162  second= array[2];
163  break;
164  case INTERVAL_MINUTE_MICROSECOND:
165  if (getIntervalFromString(str,length,cs,NUM_MINUTE_MICROSECOND_STRING_ELEMENTS,array,true))
166  return true;
167  minute= array[0];
168  second= array[1];
169  second_part= array[2];
170  break;
171  case INTERVAL_MINUTE_SECOND:
172  if (getIntervalFromString(str,length,cs,NUM_MINUTE_SECOND_STRING_ELEMENTS,array,false))
173  return true;
174  minute= array[0];
175  second= array[1];
176  break;
177  case INTERVAL_SECOND_MICROSECOND:
178  if (getIntervalFromString(str,length,cs,NUM_SECOND_MICROSECOND_STRING_ELEMENTS,array,true))
179  return true;
180  second= array[0];
181  second_part= array[1];
182  break;
183  case INTERVAL_LAST:
184  assert(0);
185  break;
186  }
187  return false;
188 }
189 
190 bool TemporalInterval::addDate(type::Time *ltime, interval_type int_type)
191 {
192  long period, sign;
193 
194  ltime->neg= 0;
195 
196  sign= (neg ? -1 : 1);
197 
198  switch (int_type)
199  {
200  case INTERVAL_SECOND:
201  case INTERVAL_SECOND_MICROSECOND:
202  case INTERVAL_MICROSECOND:
203  case INTERVAL_MINUTE:
204  case INTERVAL_HOUR:
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;
219 
220  sec= ((ltime->day-1)*3600*24L+ltime->hour*3600+ltime->minute*60+
221  ltime->second +
222  sign* (int64_t) (day*3600*24L +
223  hour*3600L+minute*60L+
224  second))+ extra_sec;
225  if (microseconds < 0)
226  {
227  microseconds+= 1000000L;
228  sec--;
229  }
230  days= sec/(3600*24L);
231  sec-= days*3600*24L;
232  if (sec < 0)
233  {
234  days--;
235  sec+= 3600*24L;
236  }
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)
244  goto invalid_date;
245  get_date_from_daynr((long) daynr, &ltime->year, &ltime->month, &ltime->day);
246  break;
247  case INTERVAL_DAY:
248  case INTERVAL_WEEK:
249  period= (calc_daynr(ltime->year,ltime->month,ltime->day) +
250  sign * (long) day);
251  /* Daynumber from year 0 to 9999-12-31 */
252  if (period > MAX_DAY_NUMBER)
253  goto invalid_date;
254  get_date_from_daynr((long) period,&ltime->year,&ltime->month,&ltime->day);
255  break;
256  case INTERVAL_YEAR:
257  ltime->year+= sign * (long) year;
258  if (ltime->year >= 10000L)
259  goto invalid_date;
260  if (ltime->month == 2 && ltime->day == 29 &&
261  calc_days_in_year(ltime->year) != 366)
262  ltime->day= 28; // Was leap-year
263  break;
264  case INTERVAL_YEAR_MONTH:
265  case INTERVAL_QUARTER:
266  case INTERVAL_MONTH:
267  period= (ltime->year*12 + sign * (long) year*12 +
268  ltime->month-1 + sign * (long) month);
269  if (period >= 120000L)
270  goto invalid_date;
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])
275  {
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
279  }
280  break;
281  default:
282  goto null_date;
283  }
284 
285  return 0; // Ok
286 
287 invalid_date:
288  push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
289  ER_DATETIME_FUNCTION_OVERFLOW,
290  ER(ER_DATETIME_FUNCTION_OVERFLOW),
291  "datetime");
292 null_date:
293  return 1;
294 }
295 
297  uint32_t length,
298  const charset_info_st * const cs,
299  uint32_t count, uint64_t *values,
300  bool transform_msec)
301 {
302  const char *end= str+length;
303  uint32_t x;
304 
305  while (str != end && !cs->isdigit(*str))
306  str++;
307 
308  for (x= 0 ; x < count ; x++)
309  {
310  int64_t value;
311  const char *start= str;
312  for (value= 0 ; str != end && cs->isdigit(*str) ; str++)
313  value= value * 10L + (int64_t) (*str - '0');
314  if (transform_msec && (x == count - 1 || str == end)) // microseconds always last
315  {
316  long msec_length= 6 - (str - start);
317  if (msec_length > 0)
318  value*= (long) log_10_int[msec_length];
319  }
320  values[x]= value;
321  while (str != end && !cs->isdigit(*str))
322  str++;
323  if (str == end && x != count-1)
324  {
325  x++;
326  /* Change values[0...x-1] -> values[count-x...count-1] */
327  internal::bmove_upp((unsigned char*) (values+count),
328  (unsigned char*) (values+x),
329  sizeof(*values)*x);
330  memset(values, 0, sizeof(*values)*(count-x));
331  break;
332  }
333  }
334  return (str != end);
335 }
336 
337 } /* namespace drizzled */
bool getIntervalFromString(const char *str, uint32_t length, const charset_info_st *const cs, uint32_t count, uint64_t *values, bool transform_msec)
bool initFromItem(Item *args, interval_type int_type, String *str_value)
virtual int64_t val_int()=0
bool addDate(type::Time *ltime, interval_type int_type)
bool null_value
Definition: item.h:122
static const uint32_t NUM_YEAR_MONTH_STRING_ELEMENTS
static const uint32_t MAX_STRING_ELEMENTS
virtual String * val_str(String *str)=0