~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/function/time/extract.cc

  • Committer: Brian Aker
  • Date: 2009-02-04 18:28:00 UTC
  • mfrom: (813.1.26 new-temporal)
  • Revision ID: brian@tangent.org-20090204182800-ra3p8rlu4zrs9fvn
Merge from Monty.

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
18
 */
19
19
 
20
 
#include <drizzled/server_includes.h>
 
20
#include "drizzled/server_includes.h"
21
21
#include CSTDINT_H
22
 
#include <drizzled/function/time/week_mode.h>
23
 
#include <drizzled/function/time/extract.h>
24
 
#include <drizzled/session.h>
 
22
#include "drizzled/temporal.h"
 
23
#include "drizzled/error.h"
 
24
#include "drizzled/session.h"
 
25
#include "drizzled/calendar.h"
 
26
#include "drizzled/function/time/extract.h"
25
27
 
26
28
/*
27
29
   'interval_names' reflects the order of the enumeration interval_type.
29
31
 */
30
32
 
31
33
extern const char *interval_names[];
32
 
/*
33
 
static const char *interval_names[]=
34
 
{
35
 
  "year", "quarter", "month", "week", "day",
36
 
  "hour", "minute", "second", "microsecond",
37
 
  "year_month", "day_hour", "day_minute",
38
 
  "day_second", "hour_minute", "hour_second",
39
 
  "minute_second", "day_microsecond",
40
 
  "hour_microsecond", "minute_microsecond",
41
 
  "second_microsecond"
42
 
};
43
 
*/
44
34
 
45
35
void Item_extract::print(String *str, enum_query_type query_type)
46
36
{
53
43
 
54
44
void Item_extract::fix_length_and_dec()
55
45
{
56
 
  value.alloc(32);                              // alloc buffer
 
46
  value.alloc(DRIZZLE_MAX_LENGTH_DATETIME_AS_STRING);                           
57
47
 
58
 
  maybe_null=1;                                 // If wrong date
 
48
  maybe_null= 1;                                        /* If NULL supplied only */
59
49
  switch (int_type) {
60
50
  case INTERVAL_YEAR:           max_length=4; date_value=1; break;
61
51
  case INTERVAL_YEAR_MONTH:     max_length=6; date_value=1; break;
81
71
  }
82
72
}
83
73
 
84
 
 
85
74
int64_t Item_extract::val_int()
86
75
{
87
 
  assert(fixed == 1);
88
 
  DRIZZLE_TIME ltime;
89
 
  uint32_t year;
90
 
  ulong week_format;
91
 
  long neg;
 
76
  assert(fixed);
 
77
 
 
78
  if (args[0]->is_null())
 
79
  {
 
80
    /* For NULL argument, we return a NULL result */
 
81
    null_value= true;
 
82
    return 0;
 
83
  }
 
84
 
 
85
  /* We could have either a datetime or a time.. */
 
86
  drizzled::DateTime datetime_temporal;
 
87
  drizzled::Time time_temporal;
 
88
 
 
89
  /* Abstract pointer type we'll use in the final switch */
 
90
  drizzled::Temporal *temporal;
 
91
 
92
92
  if (date_value)
93
93
  {
94
 
    if (get_arg0_date(&ltime, TIME_FUZZY_DATE))
95
 
      return 0;
96
 
    neg=1;
 
94
    /* Grab the first argument as a DateTime object */
 
95
    Item_result arg0_result_type= args[0]->result_type();
 
96
    
 
97
    switch (arg0_result_type)
 
98
    {
 
99
      case DECIMAL_RESULT: 
 
100
        /* 
 
101
        * For doubles supplied, interpret the arg as a string, 
 
102
        * so intentionally fall-through here...
 
103
        * This allows us to accept double parameters like 
 
104
        * 19971231235959.01 and interpret it the way MySQL does:
 
105
        * as a TIMESTAMP-like thing with a microsecond component.
 
106
        * Ugh, but need to keep backwards-compat.
 
107
        */
 
108
      case STRING_RESULT:
 
109
        {
 
110
          char buff[DRIZZLE_MAX_LENGTH_DATETIME_AS_STRING];
 
111
          String tmp(buff,sizeof(buff), &my_charset_utf8_bin);
 
112
          String *res= args[0]->val_str(&tmp);
 
113
          if (! datetime_temporal.from_string(res->c_ptr(), res->length()))
 
114
          {
 
115
            /* 
 
116
            * Could not interpret the function argument as a temporal value, 
 
117
            * so throw an error and return 0
 
118
            */
 
119
            my_error(ER_INVALID_DATETIME_VALUE, MYF(0), res->c_ptr());
 
120
            return 0;
 
121
          }
 
122
        }
 
123
        break;
 
124
      case INT_RESULT:
 
125
        if (datetime_temporal.from_int64_t(args[0]->val_int()))
 
126
          break;
 
127
        /* Intentionally fall-through on invalid conversion from integer */
 
128
      default:
 
129
        {
 
130
          /* 
 
131
          * Could not interpret the function argument as a temporal value, 
 
132
          * so throw an error and return 0
 
133
          */
 
134
          null_value= true;
 
135
          char buff[DRIZZLE_MAX_LENGTH_DATETIME_AS_STRING];
 
136
          String tmp(buff,sizeof(buff), &my_charset_utf8_bin);
 
137
          String *res;
 
138
 
 
139
          res= args[0]->val_str(&tmp);
 
140
 
 
141
          my_error(ER_INVALID_DATETIME_VALUE, MYF(0), res->c_ptr());
 
142
          return 0;
 
143
        }
 
144
    }
 
145
    /* 
 
146
     * If we got here, we have a successfully converted DateTime temporal. 
 
147
     * Point our working temporal to this.
 
148
     */
 
149
    temporal= &datetime_temporal;
97
150
  }
98
151
  else
99
152
  {
100
 
    String *res= args[0]->val_str(&value);
101
 
    if (!res || str_to_time_with_warn(res->ptr(), res->length(), &ltime))
102
 
    {
103
 
      null_value=1;
104
 
      return 0;
105
 
    }
106
 
    neg= ltime.neg ? -1 : 1;
107
 
    null_value=0;
 
153
    /* 
 
154
     * Because of the ridiculous way in which MySQL handles
 
155
     * TIME values (it does implicit integer -> string conversions
 
156
     * but only for DATETIME, not TIME values) we must first 
 
157
     * try a conversion into a TIME from a string.  If this
 
158
     * fails, we fall back on a DATETIME conversion.  This is
 
159
     * necessary because of the fact that DateTime::from_string()
 
160
     * looks first for DATETIME, then DATE regex matches.  6 consecutive
 
161
     * numbers, say 231130, will match the DATE regex YYMMDD
 
162
     * with no TIME part, but MySQL actually implicitly treats
 
163
     * parameters to SECOND(), HOUR(), and MINUTE() as TIME-only
 
164
     * values and matches 231130 as HHmmSS!
 
165
     *
 
166
     * Oh, and Brian Aker MADE me do this. :) --JRP
 
167
     */
 
168
    
 
169
    char time_buff[DRIZZLE_MAX_LENGTH_DATETIME_AS_STRING];
 
170
    String tmp_time(time_buff,sizeof(time_buff), &my_charset_utf8_bin);
 
171
    String *time_res= args[0]->val_str(&tmp_time);
 
172
    if (! time_temporal.from_string(time_res->c_ptr(), time_res->length()))
 
173
    {
 
174
      /* 
 
175
       * OK, we failed to match the first argument as a string
 
176
       * representing a time value, so we grab the first argument 
 
177
       * as a DateTime object and try that for a match...
 
178
       */
 
179
      Item_result arg0_result_type= args[0]->result_type();
 
180
      
 
181
      switch (arg0_result_type)
 
182
      {
 
183
        case DECIMAL_RESULT: 
 
184
          /* 
 
185
           * For doubles supplied, interpret the arg as a string, 
 
186
           * so intentionally fall-through here...
 
187
           * This allows us to accept double parameters like 
 
188
           * 19971231235959.01 and interpret it the way MySQL does:
 
189
           * as a TIMESTAMP-like thing with a microsecond component.
 
190
           * Ugh, but need to keep backwards-compat.
 
191
           */
 
192
        case STRING_RESULT:
 
193
          {
 
194
            char buff[DRIZZLE_MAX_LENGTH_DATETIME_AS_STRING];
 
195
            String tmp(buff,sizeof(buff), &my_charset_utf8_bin);
 
196
            String *res= args[0]->val_str(&tmp);
 
197
            if (! datetime_temporal.from_string(res->c_ptr(), res->length()))
 
198
            {
 
199
              /* 
 
200
               * Could not interpret the function argument as a temporal value, 
 
201
               * so throw an error and return 0
 
202
               */
 
203
              my_error(ER_INVALID_DATETIME_VALUE, MYF(0), res->c_ptr());
 
204
              return 0;
 
205
            }
 
206
          }
 
207
          break;
 
208
        case INT_RESULT:
 
209
          if (datetime_temporal.from_int64_t(args[0]->val_int()))
 
210
            break;
 
211
          /* Intentionally fall-through on invalid conversion from integer */
 
212
        default:
 
213
          {
 
214
            /* 
 
215
             * Could not interpret the function argument as a temporal value, 
 
216
             * so throw an error and return 0
 
217
             */
 
218
            null_value= true;
 
219
            char buff[DRIZZLE_MAX_LENGTH_DATETIME_AS_STRING];
 
220
            String tmp(buff,sizeof(buff), &my_charset_utf8_bin);
 
221
            String *res;
 
222
 
 
223
            res= args[0]->val_str(&tmp);
 
224
 
 
225
            my_error(ER_INVALID_DATETIME_VALUE, MYF(0), res->c_ptr());
 
226
            return 0;
 
227
          }
 
228
      }
 
229
      /* If we're here, our time failed, but our datetime succeeded... */
 
230
      temporal= &datetime_temporal;
 
231
    }
 
232
    else
 
233
    {
 
234
      /* If we're here, our time succeeded... */
 
235
      temporal= &time_temporal;
 
236
    }
108
237
  }
 
238
 
 
239
  /* Return the requested datetime component */
109
240
  switch (int_type) {
110
 
  case INTERVAL_YEAR:           return ltime.year;
111
 
  case INTERVAL_YEAR_MONTH:     return ltime.year*100L+ltime.month;
112
 
  case INTERVAL_QUARTER:        return (ltime.month+2)/3;
113
 
  case INTERVAL_MONTH:          return ltime.month;
114
 
  case INTERVAL_WEEK:
115
 
  {
116
 
    week_format= current_session->variables.default_week_format;
117
 
    return calc_week(&ltime, week_mode(week_format), &year);
118
 
  }
119
 
  case INTERVAL_DAY:            return ltime.day;
120
 
  case INTERVAL_DAY_HOUR:       return (long) (ltime.day*100L+ltime.hour)*neg;
121
 
  case INTERVAL_DAY_MINUTE:     return (long) (ltime.day*10000L+
122
 
                                               ltime.hour*100L+
123
 
                                               ltime.minute)*neg;
124
 
  case INTERVAL_DAY_SECOND:      return ((int64_t) ltime.day*1000000L+
125
 
                                         (int64_t) (ltime.hour*10000L+
126
 
                                                     ltime.minute*100+
127
 
                                                     ltime.second))*neg;
128
 
  case INTERVAL_HOUR:           return (long) ltime.hour*neg;
129
 
  case INTERVAL_HOUR_MINUTE:    return (long) (ltime.hour*100+ltime.minute)*neg;
130
 
  case INTERVAL_HOUR_SECOND:    return (long) (ltime.hour*10000+ltime.minute*100+
131
 
                                               ltime.second)*neg;
132
 
  case INTERVAL_MINUTE:         return (long) ltime.minute*neg;
133
 
  case INTERVAL_MINUTE_SECOND:  return (long) (ltime.minute*100+ltime.second)*neg;
134
 
  case INTERVAL_SECOND:         return (long) ltime.second*neg;
135
 
  case INTERVAL_MICROSECOND:    return (long) ltime.second_part*neg;
136
 
  case INTERVAL_DAY_MICROSECOND: return (((int64_t)ltime.day*1000000L +
137
 
                                          (int64_t)ltime.hour*10000L +
138
 
                                          ltime.minute*100 +
139
 
                                          ltime.second)*1000000L +
140
 
                                         ltime.second_part)*neg;
141
 
  case INTERVAL_HOUR_MICROSECOND: return (((int64_t)ltime.hour*10000L +
142
 
                                           ltime.minute*100 +
143
 
                                           ltime.second)*1000000L +
144
 
                                          ltime.second_part)*neg;
145
 
  case INTERVAL_MINUTE_MICROSECOND: return (((int64_t)(ltime.minute*100+
146
 
                                                        ltime.second))*1000000L+
147
 
                                            ltime.second_part)*neg;
148
 
  case INTERVAL_SECOND_MICROSECOND: return ((int64_t)ltime.second*1000000L+
149
 
                                            ltime.second_part)*neg;
150
 
  case INTERVAL_LAST: assert(0); break;  /* purecov: deadcode */
151
 
  }
152
 
  return 0;                                     // Impossible
 
241
    case INTERVAL_YEAR:         
 
242
      return (int64_t) temporal->years();
 
243
    case INTERVAL_YEAR_MONTH:   
 
244
      return (int64_t) ((temporal->years() * 100L) + temporal->months());
 
245
    case INTERVAL_QUARTER:
 
246
      return (int64_t) (temporal->months() + 2) / 3;
 
247
    case INTERVAL_MONTH:
 
248
      return (int64_t) temporal->months();
 
249
    case INTERVAL_WEEK:
 
250
      return iso_week_number_from_gregorian_date(temporal->years()
 
251
                                               , temporal->months()
 
252
                                               , temporal->days()
 
253
                                               , NULL); /* NULL is year_out parameter, which is not needed */
 
254
    case INTERVAL_DAY:
 
255
      return (int64_t) temporal->days();
 
256
    case INTERVAL_DAY_HOUR:     
 
257
      return (int64_t) ((temporal->days() * 100L) + temporal->hours());
 
258
    case INTERVAL_DAY_MINUTE:   
 
259
      return (int64_t) ((temporal->days() * 10000L)
 
260
            + (temporal->hours() * 100L) 
 
261
            + temporal->minutes());
 
262
    case INTERVAL_DAY_SECOND:    
 
263
      return (int64_t) (
 
264
              (int64_t) (temporal->days() * 1000000L) 
 
265
            + (int64_t) (temporal->hours() * 10000L)
 
266
            + (temporal->minutes() * 100L) 
 
267
            + temporal->seconds());
 
268
    case INTERVAL_HOUR:         
 
269
      return (int64_t) temporal->hours();
 
270
    case INTERVAL_HOUR_MINUTE:  
 
271
      return (int64_t) (temporal->hours() * 100L) 
 
272
            + temporal->minutes();
 
273
    case INTERVAL_HOUR_SECOND:  
 
274
      return (int64_t) (temporal->hours() * 10000L) 
 
275
            + (temporal->minutes() * 100L) 
 
276
            + temporal->seconds();
 
277
    case INTERVAL_MINUTE:
 
278
      return (int64_t) temporal->minutes();
 
279
    case INTERVAL_MINUTE_SECOND:        
 
280
      return (int64_t) (temporal->minutes() * 100L) + temporal->seconds();
 
281
    case INTERVAL_SECOND:
 
282
      return (int64_t) temporal->seconds();
 
283
    case INTERVAL_MICROSECOND:  
 
284
      return (int64_t) temporal->useconds();
 
285
    case INTERVAL_DAY_MICROSECOND: 
 
286
      return (int64_t) 
 
287
              (
 
288
              (
 
289
              (int64_t) (temporal->days() * 1000000L) 
 
290
            + (int64_t) (temporal->hours() * 10000L) 
 
291
            + (temporal->minutes() * 100L) 
 
292
            + temporal->seconds()
 
293
              ) 
 
294
              * 1000000L
 
295
              ) 
 
296
            + temporal->useconds();
 
297
    case INTERVAL_HOUR_MICROSECOND:
 
298
        return (int64_t)
 
299
              (
 
300
              (
 
301
              (int64_t) (temporal->hours() * 10000L) 
 
302
            + (temporal->minutes() * 100L) 
 
303
            + temporal->seconds()
 
304
              ) 
 
305
              * 1000000L
 
306
              ) 
 
307
            + temporal->useconds();
 
308
    case INTERVAL_MINUTE_MICROSECOND:
 
309
        return (int64_t)
 
310
              (
 
311
              (
 
312
              (temporal->minutes() * 100L) 
 
313
            + temporal->seconds()
 
314
              ) 
 
315
              * 1000000L
 
316
              ) 
 
317
            + temporal->useconds();
 
318
    case INTERVAL_SECOND_MICROSECOND: 
 
319
        return (int64_t) (temporal->seconds() * 1000000L)
 
320
            + temporal->useconds();
 
321
    case INTERVAL_LAST: 
 
322
    default:
 
323
        assert(0); 
 
324
        return 0;  /* purecov: deadcode */
 
325
  }
153
326
}
154
327
 
155
328
bool Item_extract::eq(const Item *item, bool binary_cmp) const
168
341
      return 0;
169
342
  return 1;
170
343
}
171