00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <config.h>
00021
00022 #include <drizzled/internal/m_string.h>
00023 #include <drizzled/error.h>
00024 #include <drizzled/session.h>
00025 #include <drizzled/current_session.h>
00026 #include <drizzled/function/time/date.h>
00027 #include <drizzled/temporal_interval.h>
00028 #include <drizzled/time_functions.h>
00029
00030 namespace drizzled
00031 {
00032
00033 bool TemporalInterval::initFromItem(Item *args,
00034 interval_type int_type,
00035 String *str_value)
00036 {
00037 uint64_t array[MAX_STRING_ELEMENTS];
00038 int64_t value= 0;
00039 const char *str= NULL;
00040 size_t length= 0;
00041 const CHARSET_INFO * const cs= str_value->charset();
00042
00043
00044
00045 if (static_cast<int>(int_type) <= INTERVAL_MICROSECOND)
00046 {
00047 value= args->val_int();
00048 if (args->null_value)
00049 return true;
00050 if (value < 0)
00051 {
00052 neg= true;
00053 value= -value;
00054 }
00055 }
00056 else
00057 {
00058
00059 String *res;
00060 if (!(res= args->val_str(str_value)))
00061 return true;
00062
00063
00064 str= res->ptr();
00065 const char *end= str+res->length();
00066
00067 while (str != end && my_isspace(cs,*str))
00068 str++;
00069 if (str != end && *str == '-')
00070 {
00071 neg= true;
00072
00073 str++;
00074 }
00075 length= static_cast<size_t>(end-str);
00076 }
00077
00078 switch (int_type)
00079 {
00080 case INTERVAL_YEAR:
00081 year= static_cast<uint32_t>(value);
00082 break;
00083 case INTERVAL_QUARTER:
00084 month= static_cast<uint32_t>(value*3);
00085 break;
00086 case INTERVAL_MONTH:
00087 month= static_cast<uint32_t>(value);
00088 break;
00089 case INTERVAL_WEEK:
00090 day= static_cast<uint32_t>(value*7);
00091 break;
00092 case INTERVAL_DAY:
00093 day= static_cast<uint32_t>(value);
00094 break;
00095 case INTERVAL_HOUR:
00096 hour= static_cast<uint32_t>(value);
00097 break;
00098 case INTERVAL_MICROSECOND:
00099 second_part= value;
00100 break;
00101 case INTERVAL_MINUTE:
00102 minute= value;
00103 break;
00104 case INTERVAL_SECOND:
00105 second= value;
00106 break;
00107 case INTERVAL_YEAR_MONTH:
00108 if (getIntervalFromString(str,length,cs,NUM_YEAR_MONTH_STRING_ELEMENTS,array,false))
00109 return true;
00110 year= static_cast<uint32_t>(array[0]);
00111 month= static_cast<uint32_t>(array[1]);
00112 break;
00113 case INTERVAL_DAY_HOUR:
00114 if (getIntervalFromString(str,length,cs,NUM_DAY_HOUR_STRING_ELEMENTS,array,false))
00115 return true;
00116 day= static_cast<uint32_t>(array[0]);
00117 hour= static_cast<uint32_t>(array[1]);
00118 break;
00119 case INTERVAL_DAY_MICROSECOND:
00120 if (getIntervalFromString(str,length,cs,NUM_DAY_MICROSECOND_STRING_ELEMENTS,array,true))
00121 return true;
00122 day= static_cast<uint32_t>(array[0]);
00123 hour= static_cast<uint32_t>(array[1]);
00124 minute= array[2];
00125 second= array[3];
00126 second_part= array[4];
00127 break;
00128 case INTERVAL_DAY_MINUTE:
00129 if (getIntervalFromString(str,length,cs,NUM_DAY_MINUTE_STRING_ELEMENTS,array,false))
00130 return true;
00131 day= static_cast<uint32_t>(array[0]);
00132 hour= static_cast<uint32_t>(array[1]);
00133 minute= array[2];
00134 break;
00135 case INTERVAL_DAY_SECOND:
00136 if (getIntervalFromString(str,length,cs,NUM_DAY_SECOND_STRING_ELEMENTS,array,false))
00137 return true;
00138 day= static_cast<uint32_t>(array[0]);
00139 hour= static_cast<uint32_t>(array[1]);
00140 minute= array[2];
00141 second= array[3];
00142 break;
00143 case INTERVAL_HOUR_MICROSECOND:
00144 if (getIntervalFromString(str,length,cs,NUM_HOUR_MICROSECOND_STRING_ELEMENTS,array,true))
00145 return true;
00146 hour= static_cast<uint32_t>(array[0]);
00147 minute= array[1];
00148 second= array[2];
00149 second_part= array[3];
00150 break;
00151 case INTERVAL_HOUR_MINUTE:
00152 if (getIntervalFromString(str,length,cs,NUM_HOUR_MINUTE_STRING_ELEMENTS,array,false))
00153 return true;
00154 hour= static_cast<uint32_t>(array[0]);
00155 minute= array[1];
00156 break;
00157 case INTERVAL_HOUR_SECOND:
00158 if (getIntervalFromString(str,length,cs,NUM_HOUR_SECOND_STRING_ELEMENTS,array,false))
00159 return true;
00160 hour= static_cast<uint32_t>(array[0]);
00161 minute= array[1];
00162 second= array[2];
00163 break;
00164 case INTERVAL_MINUTE_MICROSECOND:
00165 if (getIntervalFromString(str,length,cs,NUM_MINUTE_MICROSECOND_STRING_ELEMENTS,array,true))
00166 return true;
00167 minute= array[0];
00168 second= array[1];
00169 second_part= array[2];
00170 break;
00171 case INTERVAL_MINUTE_SECOND:
00172 if (getIntervalFromString(str,length,cs,NUM_MINUTE_SECOND_STRING_ELEMENTS,array,false))
00173 return true;
00174 minute= array[0];
00175 second= array[1];
00176 break;
00177 case INTERVAL_SECOND_MICROSECOND:
00178 if (getIntervalFromString(str,length,cs,NUM_SECOND_MICROSECOND_STRING_ELEMENTS,array,true))
00179 return true;
00180 second= array[0];
00181 second_part= array[1];
00182 break;
00183 case INTERVAL_LAST:
00184 assert(0);
00185 break;
00186 }
00187 return false;
00188 }
00189
00190 bool TemporalInterval::addDate(type::Time *ltime, interval_type int_type)
00191 {
00192 long period, sign;
00193
00194 ltime->neg= 0;
00195
00196 sign= (neg ? -1 : 1);
00197
00198 switch (int_type)
00199 {
00200 case INTERVAL_SECOND:
00201 case INTERVAL_SECOND_MICROSECOND:
00202 case INTERVAL_MICROSECOND:
00203 case INTERVAL_MINUTE:
00204 case INTERVAL_HOUR:
00205 case INTERVAL_MINUTE_MICROSECOND:
00206 case INTERVAL_MINUTE_SECOND:
00207 case INTERVAL_HOUR_MICROSECOND:
00208 case INTERVAL_HOUR_SECOND:
00209 case INTERVAL_HOUR_MINUTE:
00210 case INTERVAL_DAY_MICROSECOND:
00211 case INTERVAL_DAY_SECOND:
00212 case INTERVAL_DAY_MINUTE:
00213 case INTERVAL_DAY_HOUR:
00214 int64_t sec, days, daynr, microseconds, extra_sec;
00215 ltime->time_type= type::DRIZZLE_TIMESTAMP_DATETIME;
00216 microseconds= ltime->second_part + sign*second_part;
00217 extra_sec= microseconds/1000000L;
00218 microseconds= microseconds%1000000L;
00219
00220 sec= ((ltime->day-1)*3600*24L+ltime->hour*3600+ltime->minute*60+
00221 ltime->second +
00222 sign* (int64_t) (day*3600*24L +
00223 hour*3600L+minute*60L+
00224 second))+ extra_sec;
00225 if (microseconds < 0)
00226 {
00227 microseconds+= 1000000L;
00228 sec--;
00229 }
00230 days= sec/(3600*24L);
00231 sec-= days*3600*24L;
00232 if (sec < 0)
00233 {
00234 days--;
00235 sec+= 3600*24L;
00236 }
00237 ltime->second_part= (uint32_t) microseconds;
00238 ltime->second= (uint32_t) (sec % 60);
00239 ltime->minute= (uint32_t) (sec/60 % 60);
00240 ltime->hour= (uint32_t) (sec/3600);
00241 daynr= calc_daynr(ltime->year,ltime->month,1) + days;
00242
00243 if ((uint64_t) daynr > MAX_DAY_NUMBER)
00244 goto invalid_date;
00245 get_date_from_daynr((long) daynr, <ime->year, <ime->month, <ime->day);
00246 break;
00247 case INTERVAL_DAY:
00248 case INTERVAL_WEEK:
00249 period= (calc_daynr(ltime->year,ltime->month,ltime->day) +
00250 sign * (long) day);
00251
00252 if (period > MAX_DAY_NUMBER)
00253 goto invalid_date;
00254 get_date_from_daynr((long) period,<ime->year,<ime->month,<ime->day);
00255 break;
00256 case INTERVAL_YEAR:
00257 ltime->year+= sign * (long) year;
00258 if (ltime->year >= 10000L)
00259 goto invalid_date;
00260 if (ltime->month == 2 && ltime->day == 29 &&
00261 calc_days_in_year(ltime->year) != 366)
00262 ltime->day= 28;
00263 break;
00264 case INTERVAL_YEAR_MONTH:
00265 case INTERVAL_QUARTER:
00266 case INTERVAL_MONTH:
00267 period= (ltime->year*12 + sign * (long) year*12 +
00268 ltime->month-1 + sign * (long) month);
00269 if (period >= 120000L)
00270 goto invalid_date;
00271 ltime->year= (uint32_t) (period / 12);
00272 ltime->month= (uint32_t) (period % 12L)+1;
00273
00274 if (ltime->day > days_in_month[ltime->month-1])
00275 {
00276 ltime->day= days_in_month[ltime->month-1];
00277 if (ltime->month == 2 && calc_days_in_year(ltime->year) == 366)
00278 ltime->day++;
00279 }
00280 break;
00281 default:
00282 goto null_date;
00283 }
00284
00285 return 0;
00286
00287 invalid_date:
00288 push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
00289 ER_DATETIME_FUNCTION_OVERFLOW,
00290 ER(ER_DATETIME_FUNCTION_OVERFLOW),
00291 "datetime");
00292 null_date:
00293 return 1;
00294 }
00295
00296 bool TemporalInterval::getIntervalFromString(const char *str,
00297 uint32_t length,
00298 const CHARSET_INFO * const cs,
00299 uint32_t count, uint64_t *values,
00300 bool transform_msec)
00301 {
00302 const char *end= str+length;
00303 uint32_t x;
00304
00305 while (str != end && !my_isdigit(cs,*str))
00306 str++;
00307
00308 for (x= 0 ; x < count ; x++)
00309 {
00310 int64_t value;
00311 const char *start= str;
00312 for (value= 0 ; str != end && my_isdigit(cs,*str) ; str++)
00313 value= value * 10L + (int64_t) (*str - '0');
00314 if (transform_msec && (x == count - 1 || str == end))
00315 {
00316 long msec_length= 6 - (str - start);
00317 if (msec_length > 0)
00318 value*= (long) log_10_int[msec_length];
00319 }
00320 values[x]= value;
00321 while (str != end && !my_isdigit(cs,*str))
00322 str++;
00323 if (str == end && x != count-1)
00324 {
00325 x++;
00326
00327 internal::bmove_upp((unsigned char*) (values+count),
00328 (unsigned char*) (values+x),
00329 sizeof(*values)*x);
00330 memset(values, 0, sizeof(*values)*(count-x));
00331 break;
00332 }
00333 }
00334 return (str != end);
00335 }
00336
00337 }