Drizzled Public API Documentation

epoch.cc
00001 /* -*- mode: c++ c-basic-offset: 2; indent-tabs-mode: nil; -*-
00002  *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
00003  *
00004  *  Copyright (C) 2008 Sun Microsystems, Inc.
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; either version 2 of the License, or
00009  *  (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00019  */
00020 
00021 #include <config.h>
00022 #include <boost/lexical_cast.hpp>
00023 #include <drizzled/field/epoch.h>
00024 #include <drizzled/error.h>
00025 #include <drizzled/table.h>
00026 #include <drizzled/session.h>
00027 #include <drizzled/session/times.h>
00028 #include <drizzled/current_session.h>
00029 #include <drizzled/temporal.h>
00030 #include <cmath>
00031 #include <sstream>
00032 
00033 namespace drizzled {
00034 namespace field {
00035 
00079   Epoch::Epoch(unsigned char *ptr_arg,
00080                unsigned char *null_ptr_arg,
00081                unsigned char null_bit_arg,
00082                enum utype unireg_check_arg,
00083                const char *field_name_arg,
00084                drizzled::TableShare *share) :
00085   Field_str(ptr_arg,
00086             MicroTimestamp::MAX_STRING_LENGTH - 1, /* no \0 */
00087             null_ptr_arg,
00088             null_bit_arg,
00089             field_name_arg,
00090             &my_charset_bin)
00091 {
00092   unireg_check= unireg_check_arg;
00093   if (! share->getTimestampField() && unireg_check != NONE)
00094   {
00095     /* This timestamp has auto-update */
00096     share->setTimestampField(this);
00097     flags|= FUNCTION_DEFAULT_FLAG;
00098     if (unireg_check != TIMESTAMP_DN_FIELD)
00099       flags|= ON_UPDATE_NOW_FLAG;
00100   }
00101 }
00102 
00103 Epoch::Epoch(bool maybe_null_arg,
00104              const char *field_name_arg) :
00105   Field_str((unsigned char*) NULL,
00106             MicroTimestamp::MAX_STRING_LENGTH - 1, /* no \0 */
00107             maybe_null_arg ? (unsigned char*) "": 0,
00108             0,
00109             field_name_arg,
00110             &my_charset_bin)
00111 {
00112   if (unireg_check != TIMESTAMP_DN_FIELD)
00113     flags|= ON_UPDATE_NOW_FLAG;
00114 }
00115 
00122 timestamp_auto_set_type Epoch::get_auto_set_type() const
00123 {
00124   switch (unireg_check)
00125   {
00126   case TIMESTAMP_DN_FIELD:
00127     return TIMESTAMP_AUTO_SET_ON_INSERT;
00128   case TIMESTAMP_UN_FIELD:
00129     return TIMESTAMP_AUTO_SET_ON_UPDATE;
00130   case TIMESTAMP_OLD_FIELD:
00131     /*
00132       Although we can have several such columns in legacy tables this
00133       function should be called only for first of them (i.e. the one
00134       having auto-set property).
00135     */
00136     assert(getTable()->timestamp_field == this);
00137     /* Fall-through */
00138   case TIMESTAMP_DNUN_FIELD:
00139     return TIMESTAMP_AUTO_SET_ON_BOTH;
00140   default:
00141     /*
00142       Normally this function should not be called for TIMESTAMPs without
00143       auto-set property.
00144     */
00145     assert(0);
00146     return TIMESTAMP_NO_AUTO_SET;
00147   }
00148 }
00149 
00150 int Epoch::store(const char *from,
00151                  uint32_t len,
00152                  const charset_info_st * const )
00153 {
00154   Timestamp temporal;
00155 
00156   ASSERT_COLUMN_MARKED_FOR_WRITE;
00157 
00158   if (not temporal.from_string(from, (size_t) len))
00159   {
00160     my_error(ER_INVALID_TIMESTAMP_VALUE, MYF(ME_FATALERROR), from);
00161     return 1;
00162   }
00163 
00164   time_t tmp;
00165   temporal.to_time_t(tmp);
00166 
00167   uint64_t time_tmp= tmp;
00168   pack_num(time_tmp);
00169   return 0;
00170 }
00171 
00172 int Epoch::store(double from)
00173 {
00174   ASSERT_COLUMN_MARKED_FOR_WRITE;
00175 
00176   uint64_t from_tmp= (uint64_t)from;
00177 
00178   Timestamp temporal;
00179   if (not temporal.from_int64_t(from_tmp))
00180   {
00181     /* Convert the integer to a string using boost::lexical_cast */
00182     std::string tmp(boost::lexical_cast<std::string>(from));
00183 
00184     my_error(ER_INVALID_TIMESTAMP_VALUE, MYF(ME_FATALERROR), tmp.c_str());
00185     return 2;
00186   }
00187 
00188   time_t tmp;
00189   temporal.to_time_t(tmp);
00190 
00191   uint64_t tmp_micro= tmp;
00192   pack_num(tmp_micro);
00193 
00194   return 0;
00195 }
00196 
00197 int Epoch::store_decimal(const type::Decimal *value)
00198 {
00199   double tmp;
00200   value->convert(tmp);
00201 
00202   return store(tmp);
00203 }
00204 
00205 int Epoch::store(int64_t from, bool)
00206 {
00207   ASSERT_COLUMN_MARKED_FOR_WRITE;
00208 
00209   /* 
00210    * Try to create a DateTime from the supplied integer.  Throw an error
00211    * if unable to create a valid DateTime.  
00212    */
00213   Timestamp temporal;
00214   if (not temporal.from_int64_t(from))
00215   {
00216     /* Convert the integer to a string using boost::lexical_cast */
00217     std::string tmp(boost::lexical_cast<std::string>(from));
00218 
00219     my_error(ER_INVALID_TIMESTAMP_VALUE, MYF(ME_FATALERROR), tmp.c_str());
00220     return 2;
00221   }
00222 
00223   time_t tmp;
00224   temporal.to_time_t(tmp);
00225 
00226   uint64_t tmp64= tmp;
00227   pack_num(tmp64);
00228 
00229   return 0;
00230 }
00231 
00232 double Epoch::val_real(void) const
00233 {
00234   return (double) Epoch::val_int();
00235 }
00236 
00237 int64_t Epoch::val_int(void) const
00238 {
00239   uint64_t temp;
00240 
00241   ASSERT_COLUMN_MARKED_FOR_READ;
00242 
00243   unpack_num(temp);
00244 
00245   Timestamp temporal;
00246   (void) temporal.from_time_t((time_t) temp);
00247 
00248   /* We must convert into a "timestamp-formatted integer" ... */
00249   int64_t result;
00250   temporal.to_int64_t(&result);
00251   return result;
00252 }
00253 
00254 String *Epoch::val_str(String *val_buffer, String *) const
00255 {
00256   uint64_t temp= 0;
00257   char *to;
00258   int to_len= field_length + 1;
00259 
00260   val_buffer->alloc(to_len);
00261   to= (char *) val_buffer->ptr();
00262 
00263   unpack_num(temp);
00264 
00265   val_buffer->set_charset(&my_charset_bin); /* Safety */
00266 
00267   Timestamp temporal;
00268   (void) temporal.from_time_t((time_t) temp);
00269 
00270   int rlen;
00271   rlen= temporal.to_string(to, to_len);
00272   assert(rlen < to_len);
00273 
00274   val_buffer->length(rlen);
00275   return val_buffer;
00276 }
00277 
00278 bool Epoch::get_date(type::Time &ltime, uint32_t) const
00279 {
00280   uint64_t temp;
00281   type::epoch_t time_temp;
00282 
00283   unpack_num(temp);
00284   time_temp= temp;
00285   
00286   ltime.reset();
00287 
00288   ltime.store(time_temp);
00289 
00290   return 0;
00291 }
00292 
00293 bool Epoch::get_time(type::Time &ltime) const
00294 {
00295   return Epoch::get_date(ltime, 0);
00296 }
00297 
00298 int Epoch::cmp(const unsigned char *a_ptr, const unsigned char *b_ptr)
00299 {
00300   uint64_t a,b;
00301 
00302   unpack_num(a, a_ptr);
00303   unpack_num(b, b_ptr);
00304 
00305   return (a < b) ? -1 : (a > b) ? 1 : 0;
00306 }
00307 
00308 
00309 void Epoch::sort_string(unsigned char *to,uint32_t )
00310 {
00311 #ifdef WORDS_BIGENDIAN
00312   if (!getTable() || !getTable()->getShare()->db_low_byte_first)
00313   {
00314     to[0] = ptr[0];
00315     to[1] = ptr[1];
00316     to[2] = ptr[2];
00317     to[3] = ptr[3];
00318     to[4] = ptr[4];
00319     to[5] = ptr[5];
00320     to[6] = ptr[6];
00321     to[7] = ptr[7];
00322   }
00323   else
00324 #endif
00325   {
00326     to[0] = ptr[7];
00327     to[1] = ptr[6];
00328     to[2] = ptr[5];
00329     to[3] = ptr[4];
00330     to[4] = ptr[3];
00331     to[5] = ptr[2];
00332     to[6] = ptr[1];
00333     to[7] = ptr[0];
00334   }
00335 }
00336 
00337 void Epoch::set_time()
00338 {
00339   Session *session= getTable() ? getTable()->in_use : current_session;
00340   time_t tmp= session->times.getCurrentTimestampEpoch();
00341 
00342   set_notnull();
00343   pack_num(static_cast<uint32_t>(tmp));
00344 }
00345 
00346 void Epoch::set_default()
00347 {
00348   if (getTable()->timestamp_field == this &&
00349       unireg_check != TIMESTAMP_UN_FIELD)
00350   {
00351     set_time();
00352   }
00353   else
00354   {
00355     Field::set_default();
00356   }
00357 }
00358 
00359 long Epoch::get_timestamp(bool *null_value) const
00360 {
00361   if ((*null_value= is_null()))
00362     return 0;
00363 
00364   uint64_t tmp;
00365   return unpack_num(tmp);
00366 }
00367 
00368 size_t Epoch::max_string_length()
00369 {
00370   return sizeof(uint64_t);
00371 }
00372 
00373 } /* namespace field */
00374 } /* namespace drizzled */