Drizzled Public API Documentation

to_days.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/function/time/to_days.h>
23 #include <drizzled/error.h>
24 #include <drizzled/temporal.h>
25 
26 namespace drizzled
27 {
28 
29 /*
30  * We intepret the first argument as a DateTime and then convert
31  * it to a Julian Day Number and return it.
32  */
34 {
35  assert(fixed);
36 
37  /* We return NULL from FROM_DAYS() only when supplied a NULL argument */
38  if (args[0]->null_value)
39  {
40  null_value= true;
41  return false;
42  }
43 
44  /*
45  * We attempt to convert the first argument into a
46  * temporal value. If the conversion is successful,
47  * we know that a conversion to a Julian Day Number
48  * is always possible. Upon successful conversion,
49  * we return the Julian Day Number. If no conversion
50  * was possible into a temporal value, we throw an
51  * error and return 0, setting the null_value flag to true.
52  */
53  /* Grab the first argument as a DateTime object */
54  DateTime temporal;
55  Item_result arg0_result_type= args[0]->result_type();
56 
57  switch (arg0_result_type)
58  {
59  case REAL_RESULT:
60  case DECIMAL_RESULT:
61  /*
62  * For doubles supplied, interpret the arg as a string,
63  * so intentionally fall-through here...
64  * This allows us to accept double parameters like
65  * 19971231235959.01 and interpret it the way MySQL does:
66  * as a TIMESTAMP-like thing with a microsecond component.
67  * Ugh, but need to keep backwards-compat.
68  */
69  case STRING_RESULT:
70  {
71  char buff[DRIZZLE_MAX_LENGTH_DATETIME_AS_STRING];
72  String tmp(buff,sizeof(buff), &my_charset_utf8_bin);
73  String *res= args[0]->val_str(&tmp);
74 
75  if (! res)
76  {
77  /*
78  * Likely a nested function issue where the nested
79  * function had bad input. We rely on the nested
80  * function my_error() and simply return false here.
81  */
82  return false;
83  }
84 
85  if (res != &tmp)
86  {
87  tmp.copy(*res);
88  }
89 
90  if (! temporal.from_string(tmp.c_ptr(), tmp.length()))
91  {
92  /*
93  * Could not interpret the function argument as a temporal value,
94  * so throw an error and return 0
95  */
96  my_error(ER_INVALID_DATETIME_VALUE, MYF(0), tmp.c_ptr());
97  return 0;
98  }
99  }
100  break;
101  case INT_RESULT:
102  if (temporal.from_int64_t(args[0]->val_int()))
103  break;
104  /* Intentionally fall-through on invalid conversion from integer */
105  default:
106  {
107  /*
108  * Could not interpret the function argument as a temporal value,
109  * so throw an error and return 0
110  */
111  null_value= true;
112  char buff[DRIZZLE_MAX_LENGTH_DATETIME_AS_STRING];
113  String tmp(buff,sizeof(buff), &my_charset_utf8_bin);
114  String *res;
115 
116  res= args[0]->val_str(&tmp);
117 
118  if (! res)
119  {
120  /*
121  * Likely a nested function issue where the nested
122  * function had bad input. We rely on the nested
123  * function my_error() and simply return false here.
124  */
125  return false;
126  }
127 
128  if (res != &tmp)
129  {
130  tmp.copy(*res);
131  }
132 
133  my_error(ER_INVALID_DATETIME_VALUE, MYF(0), tmp.c_ptr());
134  return 0;
135  }
136  }
137  int64_t julian_day_number;
138  temporal.to_julian_day_number(&julian_day_number);
139  return julian_day_number;
140 }
141 
142 int64_t Item_func_to_days::val_int_endpoint(bool left_endp, bool *incl_endp)
143 {
144  assert(fixed);
145 
146  /*
147  * We attempt to convert the first argument into a
148  * temporal value. If the conversion is successful,
149  * we know that a conversion to a Julian Day Number
150  * is always possible. Depending on whether the
151  * first argument is a Date, or a DateTime with no
152  * time-portion, we return the Julian Day Number or
153  * the appropriate end-point integer.
154  */
155  /* Grab the first argument as a DateTime object */
156  DateTime temporal;
157  Item_result arg0_result_type= args[0]->result_type();
158 
159  switch (arg0_result_type)
160  {
161  case REAL_RESULT:
162  case DECIMAL_RESULT:
163  /*
164  * For doubles supplied, interpret the arg as a string,
165  * so intentionally fall-through here...
166  * This allows us to accept double parameters like
167  * 19971231235959.01 and interpret it the way MySQL does:
168  * as a TIMESTAMP-like thing with a microsecond component.
169  * Ugh, but need to keep backwards-compat.
170  */
171  case STRING_RESULT:
172  {
173  char buff[DRIZZLE_MAX_LENGTH_DATETIME_AS_STRING];
174  String tmp(buff,sizeof(buff), &my_charset_utf8_bin);
175  String *res= args[0]->val_str(&tmp);
176 
177  if (! res)
178  {
179  /*
180  * Likely a nested function issue where the nested
181  * function had bad input. We rely on the nested
182  * function my_error() and simply return false here.
183  */
184  return 0;
185  }
186 
187  if (res != &tmp)
188  {
189  tmp.copy(*res);
190  }
191 
192  if (! temporal.from_string(tmp.c_ptr(), tmp.length()))
193  {
194  /*
195  * Could not interpret the function argument as a temporal value,
196  * so throw an error and return 0
197  */
198  my_error(ER_INVALID_DATETIME_VALUE, MYF(0), tmp.c_ptr());
199  return 0;
200  }
201  }
202  break;
203  case INT_RESULT:
204  if (temporal.from_int64_t(args[0]->val_int()))
205  break;
206  /* Intentionally fall-through on invalid conversion from integer */
207  default:
208  {
209  /*
210  * Could not interpret the function argument as a temporal value,
211  * so throw an error and return 0
212  */
213  null_value= true;
214  char buff[DRIZZLE_MAX_LENGTH_DATETIME_AS_STRING];
215  String tmp(buff,sizeof(buff), &my_charset_utf8_bin);
216  String *res;
217 
218  res= args[0]->val_str(&tmp);
219 
220  if (! res)
221  {
222  /*
223  * Likely a nested function issue where the nested
224  * function had bad input. We rely on the nested
225  * function my_error() and simply return false here.
226  */
227  return 0;
228  }
229 
230  if (res != &tmp)
231  {
232  tmp.copy(*res);
233  }
234 
235  my_error(ER_INVALID_DATETIME_VALUE, MYF(0), tmp.c_ptr());
236  return 0;
237  }
238  }
239 
240  if (null_value == true)
241  {
242  /* got NULL, leave the incl_endp intact */
243  return INT64_MIN;
244  }
245 
246  int64_t julian_day_number;
247  temporal.to_julian_day_number(&julian_day_number);
248 
249  if (args[0]->field_type() == DRIZZLE_TYPE_DATE)
250  {
251  /* TO_DAYS() is strictly monotonic for dates, leave incl_endp intact */
252  return julian_day_number;
253  }
254 
255  /*
256  Handle the special but practically useful case of datetime values that
257  point to day bound ("strictly less" comparison stays intact):
258 
259  col < '2007-09-15 00:00:00' -> TO_DAYS(col) < TO_DAYS('2007-09-15')
260 
261  which is different from the general case ("strictly less" changes to
262  "less or equal"):
263 
264  col < '2007-09-15 12:34:56' -> TO_DAYS(col) <= TO_DAYS('2007-09-15')
265  */
266  if (!left_endp && ! (
267  temporal.hours()
268  || temporal.minutes()
269  || temporal.seconds()
270  || temporal.useconds()
271  || temporal.nseconds()
272  )
273  )
274  ; /* do nothing */
275  else
276  *incl_endp= true;
277  return julian_day_number;
278 }
279 
280 } /* namespace drizzled */
uint32_t nseconds() const
Definition: temporal.h:112
void to_julian_day_number(int64_t *to) const
Definition: temporal.cc:1113
bool from_string(const char *from, size_t from_len)
Definition: temporal.cc:160
virtual int64_t val_int()=0
uint32_t useconds() const
Definition: temporal.h:116
uint32_t hours() const
Definition: temporal.h:138
bool fixed
Definition: item.h:120
bool null_value
Definition: item.h:122
uint32_t minutes() const
Definition: temporal.h:134
bool from_int64_t(const int64_t from, bool convert)
Definition: temporal.cc:1144
virtual String * val_str(String *str)=0
int64_t val_int_endpoint(bool left_endp, bool *incl_endp)
Definition: to_days.cc:142
uint32_t seconds() const
Definition: temporal.h:130