Drizzled Public API Documentation

datetime.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 MySQL
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; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 #include <config.h>
22 #include <boost/lexical_cast.hpp>
23 #include <drizzled/field/datetime.h>
24 #include <drizzled/error.h>
25 #include <drizzled/table.h>
26 #include <drizzled/temporal.h>
27 #include <drizzled/session.h>
28 
29 #include <math.h>
30 
31 #include <sstream>
32 #include <string>
33 
34 
35 namespace drizzled
36 {
37 
38 /****************************************************************************
39 ** datetime type
40 ** In string context: YYYY-MM-DD HH:MM:DD
41 ** In number context: YYYYMMDDHHMMDD
42 ****************************************************************************/
43 
44 int Field_datetime::store(const char *from,
45  uint32_t len,
46  const charset_info_st * const )
47 {
48  ASSERT_COLUMN_MARKED_FOR_WRITE;
49  /*
50  * Try to create a DateTime from the supplied string. Throw an error
51  * if unable to create a valid DateTime.
52  */
53  DateTime temporal;
54  if (! temporal.from_string(from, (size_t) len))
55  {
56  my_error(ER_INVALID_DATETIME_VALUE, MYF(ME_FATALERROR), from);
57  return 2;
58  }
59  /* Create the stored integer format. @TODO This should go away. Should be up to engine... */
60  int64_t int_value;
61  temporal.to_int64_t(&int_value);
62 
63 #ifdef WORDS_BIGENDIAN
64  if (getTable() && getTable()->isDatabaseLowByteFirst())
65  {
66  int8store(ptr, int_value);
67  }
68  else
69 #endif
70  int64_tstore(ptr, int_value);
71  return 0;
72 }
73 
74 int Field_datetime::store(double from)
75 {
76  ASSERT_COLUMN_MARKED_FOR_WRITE;
77  if (from < 0.0 || from > 99991231235959.0)
78  {
79  /* Convert the double to a string using boost::lexical_cast */
80  std::string tmp(boost::lexical_cast<std::string>(from));
81 
82  my_error(ER_INVALID_DATETIME_VALUE, MYF(ME_FATALERROR), tmp.c_str());
83  return 2;
84  }
85  return Field_datetime::store((int64_t) rint(from), false);
86 }
87 
88 int Field_datetime::store(int64_t from, bool)
89 {
90  ASSERT_COLUMN_MARKED_FOR_WRITE;
91  /*
92  * Try to create a DateTime from the supplied integer. Throw an error
93  * if unable to create a valid DateTime.
94  */
95  DateTime temporal;
96  if (! temporal.from_int64_t(from))
97  {
98  /* Convert the integer to a string using boost::lexical_cast */
99  std::string tmp(boost::lexical_cast<std::string>(from));
100 
101  my_error(ER_INVALID_DATETIME_VALUE, MYF(ME_FATALERROR), tmp.c_str());
102  return 2;
103  }
104 
105  /*
106  * Because "from" may be a silly MySQL-like "datetime number" (like, oh, 101)
107  * we must here get the value of the DateTime as its *real* int64_t, after
108  * the conversion above has been done...yuck. God, save us.
109  */
110  int64_t int_value;
111  temporal.to_int64_t(&int_value);
112 
113 #ifdef WORDS_BIGENDIAN
114  if (getTable() && getTable()->isDatabaseLowByteFirst())
115  {
116  int8store(ptr, int_value);
117  }
118  else
119 #endif
120  int64_tstore(ptr, int_value);
121  return 0;
122 }
123 
124 int Field_datetime::store_time(type::Time &ltime, type::timestamp_t)
125 {
126  DateTime temporal;
127 
128  temporal.set_years(ltime.year);
129  temporal.set_months(ltime.month);
130  temporal.set_days(ltime.day);
131  temporal.set_hours(ltime.hour);
132  temporal.set_minutes(ltime.minute);
133  temporal.set_seconds(ltime.second);
134 
135  if (! temporal.is_valid())
136  {
137  char tmp_string[type::Time::MAX_STRING_LENGTH];
138  size_t tmp_string_len;
139 
140  tmp_string_len= temporal.to_string(tmp_string, type::Time::MAX_STRING_LENGTH);
141  (void)(tmp_string_len);
142  assert(tmp_string_len < type::Time::MAX_STRING_LENGTH);
143  my_error(ER_INVALID_DATETIME_VALUE, MYF(ME_FATALERROR), tmp_string);
144  return 1;
145  }
146 
147  int64_t int_value;
148  temporal.to_int64_t(&int_value);
149 
150 #ifdef WORDS_BIGENDIAN
151  if (getTable() && getTable()->isDatabaseLowByteFirst())
152  {
153  int8store(ptr, int_value);
154  }
155  else
156 #endif
157  int64_tstore(ptr, int_value);
158 
159  return 0;
160 }
161 
162 double Field_datetime::val_real(void) const
163 {
164  return (double) Field_datetime::val_int();
165 }
166 
167 int64_t Field_datetime::val_int(void) const
168 {
169  int64_t j;
170 
171  ASSERT_COLUMN_MARKED_FOR_READ;
172 
173 #ifdef WORDS_BIGENDIAN
174  if (getTable() && getTable()->isDatabaseLowByteFirst())
175  j=sint8korr(ptr);
176  else
177 #endif
178  int64_tget(j,ptr);
179  return j;
180 }
181 
182 
183 String *Field_datetime::val_str(String *val_buffer, String *) const
184 {
185  val_buffer->alloc(DateTime::MAX_STRING_LENGTH);
186  val_buffer->length(DateTime::MAX_STRING_LENGTH);
187  int64_t tmp;
188 
189  ASSERT_COLUMN_MARKED_FOR_READ;
190 
191 #ifdef WORDS_BIGENDIAN
192  if (getTable() && getTable()->isDatabaseLowByteFirst())
193  tmp=sint8korr(ptr);
194  else
195 #endif
196  int64_tget(tmp,ptr);
197 
198  DateTime dt;
199 
200  /* TODO: add an assert that this succeeds
201  * currently fails due to bug in allowing
202  * ALTER TABLE to add a datetime column that's
203  * not null without a default value.
204  */
205  dt.from_int64_t(tmp, false); /* NOTE: this does *NOT* attempt convertion
206  from formats such as 20090101 as
207  the stored value has already been
208  converted.
209  */
210 
211  int rlen;
212  rlen= dt.to_string((char*)val_buffer->ptr(), DateTime::MAX_STRING_LENGTH);
213  assert((rlen+1) < DateTime::MAX_STRING_LENGTH);
214 
215  val_buffer->length(rlen);
216 
217  return val_buffer;
218 }
219 
220 bool Field_datetime::get_date(type::Time &ltime, uint32_t fuzzydate) const
221 {
222  int64_t tmp=Field_datetime::val_int();
223  uint32_t part1,part2;
224  part1=(uint32_t) (tmp/INT64_C(1000000));
225  part2=(uint32_t) (tmp - (uint64_t) part1*INT64_C(1000000));
226 
227  ltime.time_type= type::DRIZZLE_TIMESTAMP_DATETIME;
228  ltime.neg= 0;
229  ltime.second_part= 0;
230  ltime.second= (int) (part2%100);
231  ltime.minute= (int) (part2/100%100);
232  ltime.hour= (int) (part2/10000);
233  ltime.day= (int) (part1%100);
234  ltime.month= (int) (part1/100%100);
235  ltime.year= (int) (part1/10000);
236 
237  return (!(fuzzydate & TIME_FUZZY_DATE) && (!ltime.month || !ltime.day)) ? 1 : 0;
238 }
239 
240 bool Field_datetime::get_time(type::Time &ltime) const
241 {
242  return Field_datetime::get_date(ltime,0);
243 }
244 
245 int Field_datetime::cmp(const unsigned char *a_ptr, const unsigned char *b_ptr)
246 {
247  int64_t a,b;
248 #ifdef WORDS_BIGENDIAN
249  if (getTable() && getTable()->isDatabaseLowByteFirst())
250  {
251  a=sint8korr(a_ptr);
252  b=sint8korr(b_ptr);
253  }
254  else
255 #endif
256  {
257  int64_tget(a,a_ptr);
258  int64_tget(b,b_ptr);
259  }
260  return ((uint64_t) a < (uint64_t) b) ? -1 :
261  ((uint64_t) a > (uint64_t) b) ? 1 : 0;
262 }
263 
264 void Field_datetime::sort_string(unsigned char *to,uint32_t )
265 {
266 #ifdef WORDS_BIGENDIAN
267  if (not getTable() || not getTable()->isDatabaseLowByteFirst())
268  {
269  to[0] = ptr[0];
270  to[1] = ptr[1];
271  to[2] = ptr[2];
272  to[3] = ptr[3];
273  to[4] = ptr[4];
274  to[5] = ptr[5];
275  to[6] = ptr[6];
276  to[7] = ptr[7];
277  }
278  else
279 #endif
280  {
281  to[0] = ptr[7];
282  to[1] = ptr[6];
283  to[2] = ptr[5];
284  to[3] = ptr[4];
285  to[4] = ptr[3];
286  to[5] = ptr[2];
287  to[6] = ptr[1];
288  to[7] = ptr[0];
289  }
290 }
291 
292 } /* namespace drizzled */
virtual int to_string(char *to, size_t to_len) const
Definition: temporal.cc:999
void set_hours(const uint32_t hour)
Definition: temporal.h:136
TODO: Rename this file - func.h is stupid.
void set_years(const uint32_t year)
Definition: temporal.h:148
void to_int64_t(int64_t *to) const
Definition: temporal.cc:1073
void set_minutes(const uint32_t minute)
Definition: temporal.h:132
int store_time(type::Time &ltime, type::timestamp_t type)
Definition: datetime.cc:124
void set_days(const uint32_t day)
Definition: temporal.h:140
static const int MAX_STRING_LENGTH
Definition: temporal.h:608
void set_seconds(const uint32_t second)
Definition: temporal.h:128
void set_months(const uint32_t month)
Definition: temporal.h:144
virtual bool is_valid() const
Definition: temporal.cc:1383
unsigned char * ptr
Definition: field.h:71