Drizzled Public API Documentation

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