Drizzled Public API Documentation

microsecond.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; version 2 of the License.
00009  *
00010  *  This program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  *  GNU General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU General Public License
00016  *  along with this program; if not, write to the Free Software
00017  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00018  */
00019 
00020 #include <config.h>
00021 
00022 #include <drizzled/temporal.h>
00023 #include <drizzled/error.h>
00024 #include <drizzled/function/time/microsecond.h>
00025 
00026 namespace drizzled
00027 {
00028 
00029 int64_t Item_func_microsecond::val_int()
00030 {
00031   assert(fixed);
00032 
00033   if (args[0]->is_null())
00034   {
00035     /* For NULL argument, we return a NULL result */
00036     null_value= true;
00037     return 0;
00038   }
00039 
00040   /* 
00041    * Because of the ridiculous way in which MySQL handles
00042    * TIME values (it does implicit integer -> string conversions
00043    * but only for DATETIME, not TIME values) we must first 
00044    * try a conversion into a TIME from a string.  If this
00045    * fails, we fall back on a DATETIME conversion.  This is
00046    * necessary because of the fact that DateTime::from_string()
00047    * looks first for DATETIME, then DATE regex matches.  6 consecutive
00048    * numbers, say 231130, will match the DATE regex YYMMDD
00049    * with no TIME part, but MySQL actually implicitly treats
00050    * parameters to SECOND(), HOUR(), and MINUTE() as TIME-only
00051    * values and matches 231130 as HHmmSS!
00052    *
00053    * Oh, and Brian Aker MADE me do this. :) --JRP
00054    */
00055   Time temporal_time;
00056   
00057   char time_buff[DRIZZLE_MAX_LENGTH_DATETIME_AS_STRING];
00058   String tmp_time(time_buff,sizeof(time_buff), &my_charset_utf8_bin);
00059   String *time_res= args[0]->val_str(&tmp_time);
00060 
00061   if (time_res && (time_res != &tmp_time))
00062   {
00063     tmp_time.copy(*time_res);
00064   }
00065 
00066   if (! temporal_time.from_string(tmp_time.c_ptr(), tmp_time.length()))
00067   {
00068     /* 
00069      * OK, we failed to match the first argument as a string
00070      * representing a time value, so we grab the first argument 
00071      * as a DateTime object and try that for a match...
00072      */
00073     DateTime temporal_datetime;
00074     Item_result arg0_result_type= args[0]->result_type();
00075     
00076     switch (arg0_result_type)
00077     {
00078       case DECIMAL_RESULT: 
00079         /* 
00080          * For doubles supplied, interpret the arg as a string, 
00081          * so intentionally fall-through here...
00082          * This allows us to accept double parameters like 
00083          * 19971231235959.01 and interpret it the way MySQL does:
00084          * as a TIMESTAMP-like thing with a microsecond component.
00085          * Ugh, but need to keep backwards-compat.
00086          */
00087       case STRING_RESULT:
00088         {
00089           char buff[DRIZZLE_MAX_LENGTH_DATETIME_AS_STRING];
00090           String tmp(buff,sizeof(buff), &my_charset_utf8_bin);
00091           String *res= args[0]->val_str(&tmp);
00092 
00093           if (res && (res != &tmp))
00094           {
00095             tmp.copy(*res);
00096           }
00097 
00098           if (! temporal_datetime.from_string(tmp.c_ptr(), tmp.length()))
00099           {
00100             /* 
00101             * Could not interpret the function argument as a temporal value, 
00102             * so throw an error and return 0
00103             */
00104             my_error(ER_INVALID_DATETIME_VALUE, MYF(0), tmp.c_ptr());
00105             return 0;
00106           }
00107         }
00108         break;
00109       case INT_RESULT:
00110         if (temporal_datetime.from_int64_t(args[0]->val_int()))
00111           break;
00112         /* Intentionally fall-through on invalid conversion from integer */
00113       default:
00114         {
00115           /* 
00116           * Could not interpret the function argument as a temporal value, 
00117           * so throw an error and return 0
00118           */
00119           null_value= true;
00120           char buff[DRIZZLE_MAX_LENGTH_DATETIME_AS_STRING];
00121           String tmp(buff,sizeof(buff), &my_charset_utf8_bin);
00122           String *res;
00123 
00124           res= args[0]->val_str(&tmp);
00125 
00126           if (res && (res != &tmp))
00127           {
00128             tmp.copy(*res);
00129           }
00130 
00131           my_error(ER_INVALID_DATETIME_VALUE, MYF(0), tmp.c_ptr());
00132           return 0;
00133         }
00134     }
00135     return (int64_t) temporal_datetime.useconds();
00136   }
00137   return (int64_t) temporal_time.useconds();
00138 }
00139 
00140 } /* namespace drizzled */