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 
00023 #include <boost/lexical_cast.hpp>
00024 #include <drizzled/field/epoch.h>
00025 #include <drizzled/error.h>
00026 #include <drizzled/tztime.h>
00027 #include <drizzled/table.h>
00028 #include <drizzled/session.h>
00029 #include <drizzled/current_session.h>
00030 
00031 #include <math.h>
00032 
00033 #include <sstream>
00034 
00035 #include <drizzled/temporal.h>
00036 
00037 namespace drizzled
00038 {
00039 
00040 namespace field
00041 {
00042 
00086   Epoch::Epoch(unsigned char *ptr_arg,
00087                unsigned char *null_ptr_arg,
00088                unsigned char null_bit_arg,
00089                enum utype unireg_check_arg,
00090                const char *field_name_arg,
00091                drizzled::TableShare *share) :
00092   Field_str(ptr_arg,
00093             MicroTimestamp::MAX_STRING_LENGTH - 1, /* no \0 */
00094             null_ptr_arg,
00095             null_bit_arg,
00096             field_name_arg,
00097             &my_charset_bin)
00098 {
00099   unireg_check= unireg_check_arg;
00100   if (! share->getTimestampField() && unireg_check != NONE)
00101   {
00102     /* This timestamp has auto-update */
00103     share->setTimestampField(this);
00104     flags|= FUNCTION_DEFAULT_FLAG;
00105     if (unireg_check != TIMESTAMP_DN_FIELD)
00106       flags|= ON_UPDATE_NOW_FLAG;
00107   }
00108 }
00109 
00110 Epoch::Epoch(bool maybe_null_arg,
00111              const char *field_name_arg) :
00112   Field_str((unsigned char*) NULL,
00113             MicroTimestamp::MAX_STRING_LENGTH - 1, /* no \0 */
00114             maybe_null_arg ? (unsigned char*) "": 0,
00115             0,
00116             field_name_arg,
00117             &my_charset_bin)
00118 {
00119   if (unireg_check != TIMESTAMP_DN_FIELD)
00120     flags|= ON_UPDATE_NOW_FLAG;
00121 }
00122 
00129 timestamp_auto_set_type Epoch::get_auto_set_type() const
00130 {
00131   switch (unireg_check)
00132   {
00133   case TIMESTAMP_DN_FIELD:
00134     return TIMESTAMP_AUTO_SET_ON_INSERT;
00135   case TIMESTAMP_UN_FIELD:
00136     return TIMESTAMP_AUTO_SET_ON_UPDATE;
00137   case TIMESTAMP_OLD_FIELD:
00138     /*
00139       Although we can have several such columns in legacy tables this
00140       function should be called only for first of them (i.e. the one
00141       having auto-set property).
00142     */
00143     assert(getTable()->timestamp_field == this);
00144     /* Fall-through */
00145   case TIMESTAMP_DNUN_FIELD:
00146     return TIMESTAMP_AUTO_SET_ON_BOTH;
00147   default:
00148     /*
00149       Normally this function should not be called for TIMESTAMPs without
00150       auto-set property.
00151     */
00152     assert(0);
00153     return TIMESTAMP_NO_AUTO_SET;
00154   }
00155 }
00156 
00157 int Epoch::store(const char *from,
00158                  uint32_t len,
00159                  const CHARSET_INFO * const )
00160 {
00161   Timestamp temporal;
00162 
00163   ASSERT_COLUMN_MARKED_FOR_WRITE;
00164 
00165   if (not temporal.from_string(from, (size_t) len))
00166   {
00167     my_error(ER_INVALID_TIMESTAMP_VALUE, MYF(ME_FATALERROR), from);
00168     return 1;
00169   }
00170 
00171   time_t tmp;
00172   temporal.to_time_t(tmp);
00173 
00174   uint64_t time_tmp= tmp;
00175   pack_num(time_tmp);
00176   return 0;
00177 }
00178 
00179 int Epoch::store(double from)
00180 {
00181   ASSERT_COLUMN_MARKED_FOR_WRITE;
00182 
00183   uint64_t from_tmp= (uint64_t)from;
00184 
00185   Timestamp temporal;
00186   if (not temporal.from_int64_t(from_tmp))
00187   {
00188     /* Convert the integer to a string using boost::lexical_cast */
00189     std::string tmp(boost::lexical_cast<std::string>(from));
00190 
00191     my_error(ER_INVALID_TIMESTAMP_VALUE, MYF(ME_FATALERROR), tmp.c_str());
00192     return 2;
00193   }
00194 
00195   time_t tmp;
00196   temporal.to_time_t(tmp);
00197 
00198   uint64_t tmp_micro= tmp;
00199   pack_num(tmp_micro);
00200 
00201   return 0;
00202 }
00203 
00204 int Epoch::store_decimal(const type::Decimal *value)
00205 {
00206   double tmp;
00207   value->convert(tmp);
00208 
00209   return store(tmp);
00210 }
00211 
00212 int Epoch::store(int64_t from, bool)
00213 {
00214   ASSERT_COLUMN_MARKED_FOR_WRITE;
00215 
00216   /* 
00217    * Try to create a DateTime from the supplied integer.  Throw an error
00218    * if unable to create a valid DateTime.  
00219    */
00220   Timestamp temporal;
00221   if (not temporal.from_int64_t(from))
00222   {
00223     /* Convert the integer to a string using boost::lexical_cast */
00224     std::string tmp(boost::lexical_cast<std::string>(from));
00225 
00226     my_error(ER_INVALID_TIMESTAMP_VALUE, MYF(ME_FATALERROR), tmp.c_str());
00227     return 2;
00228   }
00229 
00230   time_t tmp;
00231   temporal.to_time_t(tmp);
00232 
00233   uint64_t tmp64= tmp;
00234   pack_num(tmp64);
00235 
00236   return 0;
00237 }
00238 
00239 double Epoch::val_real(void) const
00240 {
00241   return (double) Epoch::val_int();
00242 }
00243 
00244 int64_t Epoch::val_int(void) const
00245 {
00246   uint64_t temp;
00247 
00248   ASSERT_COLUMN_MARKED_FOR_READ;
00249 
00250   unpack_num(temp);
00251 
00252   Timestamp temporal;
00253   (void) temporal.from_time_t((time_t) temp);
00254 
00255   /* We must convert into a "timestamp-formatted integer" ... */
00256   int64_t result;
00257   temporal.to_int64_t(&result);
00258   return result;
00259 }
00260 
00261 String *Epoch::val_str(String *val_buffer, String *) const
00262 {
00263   uint64_t temp= 0;
00264   char *to;
00265   int to_len= field_length + 1;
00266 
00267   val_buffer->alloc(to_len);
00268   to= (char *) val_buffer->ptr();
00269 
00270   unpack_num(temp);
00271 
00272   val_buffer->set_charset(&my_charset_bin); /* Safety */
00273 
00274   Timestamp temporal;
00275   (void) temporal.from_time_t((time_t) temp);
00276 
00277   int rlen;
00278   rlen= temporal.to_string(to, to_len);
00279   assert(rlen < to_len);
00280 
00281   val_buffer->length(rlen);
00282   return val_buffer;
00283 }
00284 
00285 bool Epoch::get_date(type::Time &ltime, uint32_t) const
00286 {
00287   uint64_t temp;
00288   type::Time::epoch_t time_temp;
00289 
00290   unpack_num(temp);
00291   time_temp= temp;
00292   
00293   ltime.reset();
00294 
00295   ltime.store(time_temp);
00296 
00297   return 0;
00298 }
00299 
00300 bool Epoch::get_time(type::Time &ltime) const
00301 {
00302   return Epoch::get_date(ltime, 0);
00303 }
00304 
00305 int Epoch::cmp(const unsigned char *a_ptr, const unsigned char *b_ptr)
00306 {
00307   uint64_t a,b;
00308 
00309   unpack_num(a, a_ptr);
00310   unpack_num(b, b_ptr);
00311 
00312   return (a < b) ? -1 : (a > b) ? 1 : 0;
00313 }
00314 
00315 
00316 void Epoch::sort_string(unsigned char *to,uint32_t )
00317 {
00318 #ifdef WORDS_BIGENDIAN
00319   if (!getTable() || !getTable()->getShare()->db_low_byte_first)
00320   {
00321     to[0] = ptr[0];
00322     to[1] = ptr[1];
00323     to[2] = ptr[2];
00324     to[3] = ptr[3];
00325     to[4] = ptr[4];
00326     to[5] = ptr[5];
00327     to[6] = ptr[6];
00328     to[7] = ptr[7];
00329   }
00330   else
00331 #endif
00332   {
00333     to[0] = ptr[7];
00334     to[1] = ptr[6];
00335     to[2] = ptr[5];
00336     to[3] = ptr[4];
00337     to[4] = ptr[3];
00338     to[5] = ptr[2];
00339     to[6] = ptr[1];
00340     to[7] = ptr[0];
00341   }
00342 }
00343 
00344 void Epoch::sql_type(String &res) const
00345 {
00346   res.set_ascii(STRING_WITH_LEN("timestamp"));
00347 }
00348 
00349 void Epoch::set_time()
00350 {
00351   Session *session= getTable() ? getTable()->in_use : current_session;
00352   time_t tmp= session->getCurrentTimestampEpoch();
00353 
00354   set_notnull();
00355   pack_num(static_cast<uint32_t>(tmp));
00356 }
00357 
00358 void Epoch::set_default()
00359 {
00360   if (getTable()->timestamp_field == this &&
00361       unireg_check != TIMESTAMP_UN_FIELD)
00362   {
00363     set_time();
00364   }
00365   else
00366   {
00367     Field::set_default();
00368   }
00369 }
00370 
00371 long Epoch::get_timestamp(bool *null_value) const
00372 {
00373   if ((*null_value= is_null()))
00374     return 0;
00375 
00376   uint64_t tmp;
00377   return unpack_num(tmp);
00378 }
00379 
00380 size_t Epoch::max_string_length()
00381 {
00382   return sizeof(uint64_t);
00383 }
00384 
00385 } /* namespace field */
00386 } /* namespace drizzled */