Drizzled Public API Documentation

datetime.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 MySQL
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/datetime.h>
00024 #include <drizzled/error.h>
00025 #include <drizzled/table.h>
00026 #include <drizzled/temporal.h>
00027 #include <drizzled/session.h>
00028 
00029 #include <math.h>
00030 
00031 #include <sstream>
00032 #include <string>
00033 
00034 
00035 namespace drizzled
00036 {
00037 
00038 /****************************************************************************
00039 ** datetime type
00040 ** In string context: YYYY-MM-DD HH:MM:DD
00041 ** In number context: YYYYMMDDHHMMDD
00042 ****************************************************************************/
00043 
00044 int Field_datetime::store(const char *from,
00045                           uint32_t len,
00046                           const CHARSET_INFO * const )
00047 {
00048   ASSERT_COLUMN_MARKED_FOR_WRITE;
00049   /* 
00050    * Try to create a DateTime from the supplied string.  Throw an error
00051    * if unable to create a valid DateTime.  
00052    */
00053   DateTime temporal;
00054   if (! temporal.from_string(from, (size_t) len))
00055   {
00056     my_error(ER_INVALID_DATETIME_VALUE, MYF(ME_FATALERROR), from);
00057     return 2;
00058   }
00059   /* Create the stored integer format. @TODO This should go away. Should be up to engine... */
00060   int64_t int_value;
00061   temporal.to_int64_t(&int_value);
00062 
00063 #ifdef WORDS_BIGENDIAN
00064   if (getTable() && getTable()->isDatabaseLowByteFirst())
00065   {
00066     int8store(ptr, int_value);
00067   }
00068   else
00069 #endif
00070     int64_tstore(ptr, int_value);
00071   return 0;
00072 }
00073 
00074 int Field_datetime::store(double from)
00075 {
00076   ASSERT_COLUMN_MARKED_FOR_WRITE;
00077   if (from < 0.0 || from > 99991231235959.0)
00078   {
00079     /* Convert the double to a string using boost::lexical_cast */
00080     std::string tmp(boost::lexical_cast<std::string>(from));
00081 
00082     my_error(ER_INVALID_DATETIME_VALUE, MYF(ME_FATALERROR), tmp.c_str());
00083     return 2;
00084   }
00085   return Field_datetime::store((int64_t) rint(from), false);
00086 }
00087 
00088 int Field_datetime::store(int64_t from, bool)
00089 {
00090   ASSERT_COLUMN_MARKED_FOR_WRITE;
00091   /* 
00092    * Try to create a DateTime from the supplied integer.  Throw an error
00093    * if unable to create a valid DateTime.  
00094    */
00095   DateTime temporal;
00096   if (! temporal.from_int64_t(from))
00097   {
00098     /* Convert the integer to a string using boost::lexical_cast */
00099     std::string tmp(boost::lexical_cast<std::string>(from));
00100 
00101     my_error(ER_INVALID_DATETIME_VALUE, MYF(ME_FATALERROR), tmp.c_str());
00102     return 2;
00103   }
00104 
00105   /* 
00106    * Because "from" may be a silly MySQL-like "datetime number" (like, oh, 101)
00107    * we must here get the value of the DateTime as its *real* int64_t, after
00108    * the conversion above has been done...yuck. God, save us.
00109    */
00110   int64_t int_value;
00111   temporal.to_int64_t(&int_value);
00112 
00113 #ifdef WORDS_BIGENDIAN
00114   if (getTable() && getTable()->isDatabaseLowByteFirst())
00115   {
00116     int8store(ptr, int_value);
00117   }
00118   else
00119 #endif
00120     int64_tstore(ptr, int_value);
00121   return 0;
00122 }
00123 
00124 int Field_datetime::store_time(type::Time &ltime, type::timestamp_t)
00125 {
00126   DateTime temporal;
00127 
00128   temporal.set_years(ltime.year);
00129   temporal.set_months(ltime.month);
00130   temporal.set_days(ltime.day);
00131   temporal.set_hours(ltime.hour);
00132   temporal.set_minutes(ltime.minute);
00133   temporal.set_seconds(ltime.second);
00134 
00135   if (! temporal.is_valid())
00136   {
00137     char tmp_string[type::Time::MAX_STRING_LENGTH];
00138     size_t tmp_string_len;
00139 
00140     tmp_string_len= temporal.to_string(tmp_string, type::Time::MAX_STRING_LENGTH);
00141     assert(tmp_string_len < type::Time::MAX_STRING_LENGTH);
00142     my_error(ER_INVALID_DATETIME_VALUE, MYF(ME_FATALERROR), tmp_string);
00143     return 1;
00144   }
00145 
00146   int64_t int_value;
00147   temporal.to_int64_t(&int_value);
00148 
00149 #ifdef WORDS_BIGENDIAN
00150   if (getTable() && getTable()->isDatabaseLowByteFirst())
00151   {
00152     int8store(ptr, int_value);
00153   }
00154   else
00155 #endif
00156     int64_tstore(ptr, int_value);
00157 
00158   return 0;
00159 }
00160 
00161 double Field_datetime::val_real(void) const
00162 {
00163   return (double) Field_datetime::val_int();
00164 }
00165 
00166 int64_t Field_datetime::val_int(void) const
00167 {
00168   int64_t j;
00169 
00170   ASSERT_COLUMN_MARKED_FOR_READ;
00171 
00172 #ifdef WORDS_BIGENDIAN
00173   if (getTable() && getTable()->isDatabaseLowByteFirst())
00174     j=sint8korr(ptr);
00175   else
00176 #endif
00177     int64_tget(j,ptr);
00178   return j;
00179 }
00180 
00181 
00182 String *Field_datetime::val_str(String *val_buffer, String *) const
00183 {
00184   val_buffer->alloc(DateTime::MAX_STRING_LENGTH);
00185   val_buffer->length(DateTime::MAX_STRING_LENGTH);
00186   int64_t tmp;
00187 
00188   ASSERT_COLUMN_MARKED_FOR_READ;
00189 
00190 #ifdef WORDS_BIGENDIAN
00191   if (getTable() && getTable()->isDatabaseLowByteFirst())
00192     tmp=sint8korr(ptr);
00193   else
00194 #endif
00195     int64_tget(tmp,ptr);
00196 
00197   DateTime dt;
00198 
00199   /* TODO: add an assert that this succeeds
00200    * currently fails due to bug in allowing
00201    * ALTER TABLE to add a datetime column that's
00202    * not null without a default value.
00203    */
00204   dt.from_int64_t(tmp, false); /* NOTE: this does *NOT* attempt convertion
00205                                  from formats such as 20090101 as
00206                                  the stored value has already been
00207                                  converted.
00208                                */
00209 
00210   int rlen;
00211   rlen= dt.to_string((char*)val_buffer->ptr(), DateTime::MAX_STRING_LENGTH);
00212   assert((rlen+1) <  DateTime::MAX_STRING_LENGTH);
00213 
00214   val_buffer->length(rlen);
00215 
00216   return val_buffer;
00217 }
00218 
00219 bool Field_datetime::get_date(type::Time &ltime, uint32_t fuzzydate) const
00220 {
00221   int64_t tmp=Field_datetime::val_int();
00222   uint32_t part1,part2;
00223   part1=(uint32_t) (tmp/INT64_C(1000000));
00224   part2=(uint32_t) (tmp - (uint64_t) part1*INT64_C(1000000));
00225 
00226   ltime.time_type=  type::DRIZZLE_TIMESTAMP_DATETIME;
00227   ltime.neg=    0;
00228   ltime.second_part=  0;
00229   ltime.second= (int) (part2%100);
00230   ltime.minute= (int) (part2/100%100);
00231   ltime.hour=   (int) (part2/10000);
00232   ltime.day=    (int) (part1%100);
00233   ltime.month=  (int) (part1/100%100);
00234   ltime.year=     (int) (part1/10000);
00235 
00236   return (!(fuzzydate & TIME_FUZZY_DATE) && (!ltime.month || !ltime.day)) ? 1 : 0;
00237 }
00238 
00239 bool Field_datetime::get_time(type::Time &ltime) const
00240 {
00241   return Field_datetime::get_date(ltime,0);
00242 }
00243 
00244 int Field_datetime::cmp(const unsigned char *a_ptr, const unsigned char *b_ptr)
00245 {
00246   int64_t a,b;
00247 #ifdef WORDS_BIGENDIAN
00248   if (getTable() && getTable()->isDatabaseLowByteFirst())
00249   {
00250     a=sint8korr(a_ptr);
00251     b=sint8korr(b_ptr);
00252   }
00253   else
00254 #endif
00255   {
00256     int64_tget(a,a_ptr);
00257     int64_tget(b,b_ptr);
00258   }
00259   return ((uint64_t) a < (uint64_t) b) ? -1 :
00260     ((uint64_t) a > (uint64_t) b) ? 1 : 0;
00261 }
00262 
00263 void Field_datetime::sort_string(unsigned char *to,uint32_t )
00264 {
00265 #ifdef WORDS_BIGENDIAN
00266   if (not getTable() || not getTable()->isDatabaseLowByteFirst())
00267   {
00268     to[0] = ptr[0];
00269     to[1] = ptr[1];
00270     to[2] = ptr[2];
00271     to[3] = ptr[3];
00272     to[4] = ptr[4];
00273     to[5] = ptr[5];
00274     to[6] = ptr[6];
00275     to[7] = ptr[7];
00276   }
00277   else
00278 #endif
00279   {
00280     to[0] = ptr[7];
00281     to[1] = ptr[6];
00282     to[2] = ptr[5];
00283     to[3] = ptr[4];
00284     to[4] = ptr[3];
00285     to[5] = ptr[2];
00286     to[6] = ptr[1];
00287     to[7] = ptr[0];
00288   }
00289 }
00290 
00291 
00292 void Field_datetime::sql_type(String &res) const
00293 {
00294   res.set_ascii(STRING_WITH_LEN("datetime"));
00295 }
00296 
00297 } /* namespace drizzled */