Drizzled Public API Documentation

epoch.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; 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/epoch.h>
24 #include <drizzled/error.h>
25 #include <drizzled/table.h>
26 #include <drizzled/session.h>
27 #include <drizzled/session/times.h>
28 #include <drizzled/current_session.h>
29 #include <drizzled/temporal.h>
30 #include <cmath>
31 #include <sstream>
32 
33 namespace drizzled {
34 namespace field {
35 
79  Epoch::Epoch(unsigned char *ptr_arg,
80  unsigned char *null_ptr_arg,
81  unsigned char null_bit_arg,
82  enum utype unireg_check_arg,
83  const char *field_name_arg,
84  drizzled::TableShare *share) :
85  Field_str(ptr_arg,
86  MicroTimestamp::MAX_STRING_LENGTH - 1, /* no \0 */
87  null_ptr_arg,
88  null_bit_arg,
89  field_name_arg,
90  &my_charset_bin)
91 {
92  unireg_check= unireg_check_arg;
93  if (! share->getTimestampField() && unireg_check != NONE)
94  {
95  /* This timestamp has auto-update */
96  share->setTimestampField(this);
97  flags|= FUNCTION_DEFAULT_FLAG;
98  if (unireg_check != TIMESTAMP_DN_FIELD)
99  flags|= ON_UPDATE_NOW_FLAG;
100  }
101 }
102 
103 Epoch::Epoch(bool maybe_null_arg,
104  const char *field_name_arg) :
105  Field_str((unsigned char*) NULL,
106  MicroTimestamp::MAX_STRING_LENGTH - 1, /* no \0 */
107  maybe_null_arg ? (unsigned char*) "": 0,
108  0,
109  field_name_arg,
110  &my_charset_bin)
111 {
112  if (unireg_check != TIMESTAMP_DN_FIELD)
113  flags|= ON_UPDATE_NOW_FLAG;
114 }
115 
122 timestamp_auto_set_type Epoch::get_auto_set_type() const
123 {
124  switch (unireg_check)
125  {
126  case TIMESTAMP_DN_FIELD:
127  return TIMESTAMP_AUTO_SET_ON_INSERT;
128  case TIMESTAMP_UN_FIELD:
129  return TIMESTAMP_AUTO_SET_ON_UPDATE;
130  case TIMESTAMP_OLD_FIELD:
131  /*
132  Although we can have several such columns in legacy tables this
133  function should be called only for first of them (i.e. the one
134  having auto-set property).
135  */
136  assert(getTable()->timestamp_field == this);
137  /* Fall-through */
138  case TIMESTAMP_DNUN_FIELD:
139  return TIMESTAMP_AUTO_SET_ON_BOTH;
140  default:
141  /*
142  Normally this function should not be called for TIMESTAMPs without
143  auto-set property.
144  */
145  assert(0);
146  return TIMESTAMP_NO_AUTO_SET;
147  }
148 }
149 
150 int Epoch::store(const char *from,
151  uint32_t len,
152  const charset_info_st * const )
153 {
154  Timestamp temporal;
155 
156  ASSERT_COLUMN_MARKED_FOR_WRITE;
157 
158  if (not temporal.from_string(from, (size_t) len))
159  {
160  my_error(ER_INVALID_TIMESTAMP_VALUE, MYF(ME_FATALERROR), from);
161  return 1;
162  }
163 
164  time_t tmp;
165  temporal.to_time_t(tmp);
166 
167  uint64_t time_tmp= tmp;
168  pack_num(time_tmp);
169  return 0;
170 }
171 
172 int Epoch::store(double from)
173 {
174  ASSERT_COLUMN_MARKED_FOR_WRITE;
175 
176  uint64_t from_tmp= (uint64_t)from;
177 
178  Timestamp temporal;
179  if (not temporal.from_int64_t(from_tmp))
180  {
181  /* Convert the integer to a string using boost::lexical_cast */
182  std::string tmp(boost::lexical_cast<std::string>(from));
183 
184  my_error(ER_INVALID_TIMESTAMP_VALUE, MYF(ME_FATALERROR), tmp.c_str());
185  return 2;
186  }
187 
188  time_t tmp;
189  temporal.to_time_t(tmp);
190 
191  uint64_t tmp_micro= tmp;
192  pack_num(tmp_micro);
193 
194  return 0;
195 }
196 
197 int Epoch::store_decimal(const type::Decimal *value)
198 {
199  double tmp;
200  value->convert(tmp);
201 
202  return store(tmp);
203 }
204 
205 int Epoch::store(int64_t from, bool)
206 {
207  ASSERT_COLUMN_MARKED_FOR_WRITE;
208 
209  /*
210  * Try to create a DateTime from the supplied integer. Throw an error
211  * if unable to create a valid DateTime.
212  */
213  Timestamp temporal;
214  if (not temporal.from_int64_t(from))
215  {
216  /* Convert the integer to a string using boost::lexical_cast */
217  std::string tmp(boost::lexical_cast<std::string>(from));
218 
219  my_error(ER_INVALID_TIMESTAMP_VALUE, MYF(ME_FATALERROR), tmp.c_str());
220  return 2;
221  }
222 
223  time_t tmp;
224  temporal.to_time_t(tmp);
225 
226  uint64_t tmp64= tmp;
227  pack_num(tmp64);
228 
229  return 0;
230 }
231 
232 double Epoch::val_real(void) const
233 {
234  return (double) Epoch::val_int();
235 }
236 
237 int64_t Epoch::val_int(void) const
238 {
239  uint64_t temp;
240 
241  ASSERT_COLUMN_MARKED_FOR_READ;
242 
243  unpack_num(temp);
244 
245  Timestamp temporal;
246  (void) temporal.from_time_t((time_t) temp);
247 
248  /* We must convert into a "timestamp-formatted integer" ... */
249  int64_t result;
250  temporal.to_int64_t(&result);
251  return result;
252 }
253 
254 String *Epoch::val_str(String *val_buffer, String *) const
255 {
256  uint64_t temp= 0;
257  char *to;
258  int to_len= field_length + 1;
259 
260  val_buffer->alloc(to_len);
261  to= (char *) val_buffer->ptr();
262 
263  unpack_num(temp);
264 
265  val_buffer->set_charset(&my_charset_bin); /* Safety */
266 
267  Timestamp temporal;
268  (void) temporal.from_time_t((time_t) temp);
269 
270  int rlen;
271  rlen= temporal.to_string(to, to_len);
272  assert(rlen < to_len);
273 
274  val_buffer->length(rlen);
275  return val_buffer;
276 }
277 
278 bool Epoch::get_date(type::Time &ltime, uint32_t) const
279 {
280  uint64_t temp;
281  type::epoch_t time_temp;
282 
283  unpack_num(temp);
284  time_temp= temp;
285 
286  ltime.reset();
287 
288  ltime.store(time_temp);
289 
290  return 0;
291 }
292 
293 bool Epoch::get_time(type::Time &ltime) const
294 {
295  return Epoch::get_date(ltime, 0);
296 }
297 
298 int Epoch::cmp(const unsigned char *a_ptr, const unsigned char *b_ptr)
299 {
300  uint64_t a,b;
301 
302  unpack_num(a, a_ptr);
303  unpack_num(b, b_ptr);
304 
305  return (a < b) ? -1 : (a > b) ? 1 : 0;
306 }
307 
308 
309 void Epoch::sort_string(unsigned char *to,uint32_t )
310 {
311 #ifdef WORDS_BIGENDIAN
312  if (!getTable() || !getTable()->getShare()->db_low_byte_first)
313  {
314  to[0] = ptr[0];
315  to[1] = ptr[1];
316  to[2] = ptr[2];
317  to[3] = ptr[3];
318  to[4] = ptr[4];
319  to[5] = ptr[5];
320  to[6] = ptr[6];
321  to[7] = ptr[7];
322  }
323  else
324 #endif
325  {
326  to[0] = ptr[7];
327  to[1] = ptr[6];
328  to[2] = ptr[5];
329  to[3] = ptr[4];
330  to[4] = ptr[3];
331  to[5] = ptr[2];
332  to[6] = ptr[1];
333  to[7] = ptr[0];
334  }
335 }
336 
337 void Epoch::set_time()
338 {
339  Session *session= getTable() ? getTable()->in_use : current_session;
340  time_t tmp= session->times.getCurrentTimestampEpoch();
341 
342  set_notnull();
343  pack_num(static_cast<uint32_t>(tmp));
344 }
345 
346 void Epoch::set_default()
347 {
348  if (getTable()->timestamp_field == this &&
349  unireg_check != TIMESTAMP_UN_FIELD)
350  {
351  set_time();
352  }
353  else
354  {
355  Field::set_default();
356  }
357 }
358 
359 long Epoch::get_timestamp(bool *null_value) const
360 {
361  if ((*null_value= is_null()))
362  return 0;
363 
364  uint64_t tmp;
365  return unpack_num(tmp);
366 }
367 
368 size_t Epoch::max_string_length()
369 {
370  return sizeof(uint64_t);
371 }
372 
373 } /* namespace field */
374 } /* namespace drizzled */