~drizzle-trunk/drizzle/development

574.3.22 by Lee
moving functions from drizzled/item/timefunc to drizzled/functions/time
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
 *
1999.6.1 by kalebral at gmail
update Copyright strings to a more common format to help with creating the master debian copyright file
4
 *  Copyright (C) 2008 Sun Microsystems, Inc.
574.3.22 by Lee
moving functions from drizzled/item/timefunc to drizzled/functions/time
5
 *
6
 *  This program is free software; you can redistribute it and/or modify
7
 *  it under the terms of the GNU General Public License as published by
8
 *  the Free Software Foundation; version 2 of the License.
9
 *
10
 *  This program is distributed in the hope that it will be useful,
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 *  GNU General Public License for more details.
14
 *
15
 *  You should have received a copy of the GNU General Public License
16
 *  along with this program; if not, write to the Free Software
17
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
 */
19
1241.9.36 by Monty Taylor
ZOMG. I deleted drizzled/server_includes.h.
20
#include "config.h"
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
21
813.1.22 by Jay Pipes
default_week_format variable has gone the way of the Dodo, as have the
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"
574.3.22 by Lee
moving functions from drizzled/item/timefunc to drizzled/functions/time
27
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
28
namespace drizzled
29
{
30
574.3.22 by Lee
moving functions from drizzled/item/timefunc to drizzled/functions/time
31
/*
32
   'interval_names' reflects the order of the enumeration interval_type.
33
   See item/time.h
34
 */
35
36
extern const char *interval_names[];
37
38
void Item_extract::print(String *str, enum_query_type query_type)
39
{
40
  str->append(STRING_WITH_LEN("extract("));
41
  str->append(interval_names[int_type]);
42
  str->append(STRING_WITH_LEN(" from "));
43
  args[0]->print(str, query_type);
44
  str->append(')');
45
}
46
47
void Item_extract::fix_length_and_dec()
48
{
813.1.24 by Jay Pipes
fixed logic error in EXTRACT() function whereby datetime temporals were improperly pointing to the time temporals. Fixed test cases for func_time and func_sapdb to remove the week and weekofyear functions.
49
  value.alloc(DRIZZLE_MAX_LENGTH_DATETIME_AS_STRING);				
574.3.22 by Lee
moving functions from drizzled/item/timefunc to drizzled/functions/time
50
813.1.22 by Jay Pipes
default_week_format variable has gone the way of the Dodo, as have the
51
  maybe_null= 1;					/* If NULL supplied only */
574.3.22 by Lee
moving functions from drizzled/item/timefunc to drizzled/functions/time
52
  switch (int_type) {
53
  case INTERVAL_YEAR:		max_length=4; date_value=1; break;
54
  case INTERVAL_YEAR_MONTH:	max_length=6; date_value=1; break;
55
  case INTERVAL_QUARTER:        max_length=2; date_value=1; break;
56
  case INTERVAL_MONTH:		max_length=2; date_value=1; break;
57
  case INTERVAL_WEEK:		max_length=2; date_value=1; break;
58
  case INTERVAL_DAY:		max_length=2; date_value=1; break;
59
  case INTERVAL_DAY_HOUR:	max_length=9; date_value=0; break;
60
  case INTERVAL_DAY_MINUTE:	max_length=11; date_value=0; break;
61
  case INTERVAL_DAY_SECOND:	max_length=13; date_value=0; break;
62
  case INTERVAL_HOUR:		max_length=2; date_value=0; break;
63
  case INTERVAL_HOUR_MINUTE:	max_length=4; date_value=0; break;
64
  case INTERVAL_HOUR_SECOND:	max_length=6; date_value=0; break;
65
  case INTERVAL_MINUTE:		max_length=2; date_value=0; break;
66
  case INTERVAL_MINUTE_SECOND:	max_length=4; date_value=0; break;
67
  case INTERVAL_SECOND:		max_length=2; date_value=0; break;
68
  case INTERVAL_MICROSECOND:	max_length=2; date_value=0; break;
69
  case INTERVAL_DAY_MICROSECOND: max_length=20; date_value=0; break;
70
  case INTERVAL_HOUR_MICROSECOND: max_length=13; date_value=0; break;
71
  case INTERVAL_MINUTE_MICROSECOND: max_length=11; date_value=0; break;
72
  case INTERVAL_SECOND_MICROSECOND: max_length=9; date_value=0; break;
971.6.11 by Eric Day
Removed purecov messages.
73
  case INTERVAL_LAST: assert(0); break;
574.3.22 by Lee
moving functions from drizzled/item/timefunc to drizzled/functions/time
74
  }
75
}
76
77
int64_t Item_extract::val_int()
78
{
813.1.22 by Jay Pipes
default_week_format variable has gone the way of the Dodo, as have the
79
  assert(fixed);
80
81
  if (args[0]->is_null())
82
  {
83
    /* For NULL argument, we return a NULL result */
84
    null_value= true;
85
    return 0;
86
  }
87
88
  /* We could have either a datetime or a time.. */
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
89
  DateTime datetime_temporal;
90
  Time time_temporal;
813.1.22 by Jay Pipes
default_week_format variable has gone the way of the Dodo, as have the
91
92
  /* Abstract pointer type we'll use in the final switch */
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
93
  Temporal *temporal;
813.1.22 by Jay Pipes
default_week_format variable has gone the way of the Dodo, as have the
94
574.3.22 by Lee
moving functions from drizzled/item/timefunc to drizzled/functions/time
95
  if (date_value)
96
  {
813.1.22 by Jay Pipes
default_week_format variable has gone the way of the Dodo, as have the
97
    /* Grab the first argument as a DateTime object */
98
    Item_result arg0_result_type= args[0]->result_type();
99
    
100
    switch (arg0_result_type)
101
    {
102
      case DECIMAL_RESULT: 
103
        /* 
104
        * For doubles supplied, interpret the arg as a string, 
105
        * so intentionally fall-through here...
106
        * This allows us to accept double parameters like 
107
        * 19971231235959.01 and interpret it the way MySQL does:
108
        * as a TIMESTAMP-like thing with a microsecond component.
109
        * Ugh, but need to keep backwards-compat.
110
        */
111
      case STRING_RESULT:
112
        {
113
          char buff[DRIZZLE_MAX_LENGTH_DATETIME_AS_STRING];
114
          String tmp(buff,sizeof(buff), &my_charset_utf8_bin);
115
          String *res= args[0]->val_str(&tmp);
1750.3.1 by David Shrewsbury
Use of String::c_ptr() in temporal functions can corrupt PBXT row cache, so make sure temporaries are used.
116
117
          if (res && (res != &tmp))
118
          {
119
            tmp.copy(*res);
120
          }
121
122
          if (! datetime_temporal.from_string(tmp.c_ptr(), tmp.length()))
813.1.22 by Jay Pipes
default_week_format variable has gone the way of the Dodo, as have the
123
          {
124
            /* 
125
            * Could not interpret the function argument as a temporal value, 
126
            * so throw an error and return 0
127
            */
1750.3.1 by David Shrewsbury
Use of String::c_ptr() in temporal functions can corrupt PBXT row cache, so make sure temporaries are used.
128
            my_error(ER_INVALID_DATETIME_VALUE, MYF(0), tmp.c_ptr());
813.1.22 by Jay Pipes
default_week_format variable has gone the way of the Dodo, as have the
129
            return 0;
130
          }
131
        }
132
        break;
133
      case INT_RESULT:
134
        if (datetime_temporal.from_int64_t(args[0]->val_int()))
135
          break;
136
        /* Intentionally fall-through on invalid conversion from integer */
137
      default:
138
        {
139
          /* 
140
          * Could not interpret the function argument as a temporal value, 
141
          * so throw an error and return 0
142
          */
143
          null_value= true;
144
          char buff[DRIZZLE_MAX_LENGTH_DATETIME_AS_STRING];
145
          String tmp(buff,sizeof(buff), &my_charset_utf8_bin);
146
          String *res;
147
148
          res= args[0]->val_str(&tmp);
149
1750.3.1 by David Shrewsbury
Use of String::c_ptr() in temporal functions can corrupt PBXT row cache, so make sure temporaries are used.
150
          if (res && (res != &tmp))
151
          {
152
            tmp.copy(*res);
153
          }
154
155
          my_error(ER_INVALID_DATETIME_VALUE, MYF(0), tmp.c_ptr());
813.1.22 by Jay Pipes
default_week_format variable has gone the way of the Dodo, as have the
156
          return 0;
157
        }
158
    }
159
    /* 
160
     * If we got here, we have a successfully converted DateTime temporal. 
161
     * Point our working temporal to this.
162
     */
163
    temporal= &datetime_temporal;
574.3.22 by Lee
moving functions from drizzled/item/timefunc to drizzled/functions/time
164
  }
165
  else
166
  {
813.1.22 by Jay Pipes
default_week_format variable has gone the way of the Dodo, as have the
167
    /* 
168
     * Because of the ridiculous way in which MySQL handles
169
     * TIME values (it does implicit integer -> string conversions
170
     * but only for DATETIME, not TIME values) we must first 
171
     * try a conversion into a TIME from a string.  If this
172
     * fails, we fall back on a DATETIME conversion.  This is
173
     * necessary because of the fact that DateTime::from_string()
174
     * looks first for DATETIME, then DATE regex matches.  6 consecutive
175
     * numbers, say 231130, will match the DATE regex YYMMDD
176
     * with no TIME part, but MySQL actually implicitly treats
177
     * parameters to SECOND(), HOUR(), and MINUTE() as TIME-only
178
     * values and matches 231130 as HHmmSS!
179
     *
180
     * Oh, and Brian Aker MADE me do this. :) --JRP
181
     */
182
    
183
    char time_buff[DRIZZLE_MAX_LENGTH_DATETIME_AS_STRING];
184
    String tmp_time(time_buff,sizeof(time_buff), &my_charset_utf8_bin);
185
    String *time_res= args[0]->val_str(&tmp_time);
1750.3.1 by David Shrewsbury
Use of String::c_ptr() in temporal functions can corrupt PBXT row cache, so make sure temporaries are used.
186
187
    if (time_res && (time_res != &tmp_time))
188
    {
189
      tmp_time.copy(*time_res);
190
    }
191
192
    if (! time_temporal.from_string(tmp_time.c_ptr(), tmp_time.length()))
574.3.22 by Lee
moving functions from drizzled/item/timefunc to drizzled/functions/time
193
    {
813.1.22 by Jay Pipes
default_week_format variable has gone the way of the Dodo, as have the
194
      /* 
195
       * OK, we failed to match the first argument as a string
196
       * representing a time value, so we grab the first argument 
197
       * as a DateTime object and try that for a match...
198
       */
199
      Item_result arg0_result_type= args[0]->result_type();
200
      
201
      switch (arg0_result_type)
202
      {
203
        case DECIMAL_RESULT: 
204
          /* 
205
           * For doubles supplied, interpret the arg as a string, 
206
           * so intentionally fall-through here...
207
           * This allows us to accept double parameters like 
208
           * 19971231235959.01 and interpret it the way MySQL does:
209
           * as a TIMESTAMP-like thing with a microsecond component.
210
           * Ugh, but need to keep backwards-compat.
211
           */
212
        case STRING_RESULT:
213
          {
214
            char buff[DRIZZLE_MAX_LENGTH_DATETIME_AS_STRING];
215
            String tmp(buff,sizeof(buff), &my_charset_utf8_bin);
216
            String *res= args[0]->val_str(&tmp);
1750.3.1 by David Shrewsbury
Use of String::c_ptr() in temporal functions can corrupt PBXT row cache, so make sure temporaries are used.
217
218
            if (res && (res != &tmp))
219
            {
220
              tmp.copy(*res);
221
            }
222
223
            if (! datetime_temporal.from_string(tmp.c_ptr(), tmp.length()))
813.1.22 by Jay Pipes
default_week_format variable has gone the way of the Dodo, as have the
224
            {
225
              /* 
226
               * Could not interpret the function argument as a temporal value, 
227
               * so throw an error and return 0
228
               */
1750.3.1 by David Shrewsbury
Use of String::c_ptr() in temporal functions can corrupt PBXT row cache, so make sure temporaries are used.
229
              my_error(ER_INVALID_DATETIME_VALUE, MYF(0), tmp.c_ptr());
813.1.22 by Jay Pipes
default_week_format variable has gone the way of the Dodo, as have the
230
              return 0;
231
            }
232
          }
233
          break;
234
        case INT_RESULT:
235
          if (datetime_temporal.from_int64_t(args[0]->val_int()))
236
            break;
237
          /* Intentionally fall-through on invalid conversion from integer */
238
        default:
239
          {
240
            /* 
241
             * Could not interpret the function argument as a temporal value, 
242
             * so throw an error and return 0
243
             */
244
            null_value= true;
245
            char buff[DRIZZLE_MAX_LENGTH_DATETIME_AS_STRING];
246
            String tmp(buff,sizeof(buff), &my_charset_utf8_bin);
247
            String *res;
248
249
            res= args[0]->val_str(&tmp);
250
251
            my_error(ER_INVALID_DATETIME_VALUE, MYF(0), res->c_ptr());
252
            return 0;
253
          }
254
      }
255
      /* If we're here, our time failed, but our datetime succeeded... */
256
      temporal= &datetime_temporal;
574.3.22 by Lee
moving functions from drizzled/item/timefunc to drizzled/functions/time
257
    }
813.1.24 by Jay Pipes
fixed logic error in EXTRACT() function whereby datetime temporals were improperly pointing to the time temporals. Fixed test cases for func_time and func_sapdb to remove the week and weekofyear functions.
258
    else
259
    {
260
      /* If we're here, our time succeeded... */
261
      temporal= &time_temporal;
262
    }
574.3.22 by Lee
moving functions from drizzled/item/timefunc to drizzled/functions/time
263
  }
813.1.22 by Jay Pipes
default_week_format variable has gone the way of the Dodo, as have the
264
265
  /* Return the requested datetime component */
574.3.22 by Lee
moving functions from drizzled/item/timefunc to drizzled/functions/time
266
  switch (int_type) {
813.1.22 by Jay Pipes
default_week_format variable has gone the way of the Dodo, as have the
267
    case INTERVAL_YEAR:		
268
      return (int64_t) temporal->years();
269
    case INTERVAL_YEAR_MONTH:	
270
      return (int64_t) ((temporal->years() * 100L) + temporal->months());
271
    case INTERVAL_QUARTER:
272
      return (int64_t) (temporal->months() + 2) / 3;
273
    case INTERVAL_MONTH:
274
      return (int64_t) temporal->months();
275
    case INTERVAL_WEEK:
276
      return iso_week_number_from_gregorian_date(temporal->years()
277
                                               , temporal->months()
1831.1.1 by Andrew Hutchings
Fix new warnings in GCC 4.5
278
                                               , temporal->days());
813.1.22 by Jay Pipes
default_week_format variable has gone the way of the Dodo, as have the
279
    case INTERVAL_DAY:
280
      return (int64_t) temporal->days();
281
    case INTERVAL_DAY_HOUR:	
282
      return (int64_t) ((temporal->days() * 100L) + temporal->hours());
283
    case INTERVAL_DAY_MINUTE:	
284
      return (int64_t) ((temporal->days() * 10000L)
285
            + (temporal->hours() * 100L) 
286
            + temporal->minutes());
287
    case INTERVAL_DAY_SECOND:	 
288
      return (int64_t) (
289
              (int64_t) (temporal->days() * 1000000L) 
290
            + (int64_t) (temporal->hours() * 10000L)
291
            + (temporal->minutes() * 100L) 
292
            + temporal->seconds());
293
    case INTERVAL_HOUR:		
294
      return (int64_t) temporal->hours();
295
    case INTERVAL_HOUR_MINUTE:	
296
      return (int64_t) (temporal->hours() * 100L) 
297
            + temporal->minutes();
298
    case INTERVAL_HOUR_SECOND:	
299
      return (int64_t) (temporal->hours() * 10000L) 
300
            + (temporal->minutes() * 100L) 
301
            + temporal->seconds();
302
    case INTERVAL_MINUTE:
303
      return (int64_t) temporal->minutes();
304
    case INTERVAL_MINUTE_SECOND:	
305
      return (int64_t) (temporal->minutes() * 100L) + temporal->seconds();
306
    case INTERVAL_SECOND:
307
      return (int64_t) temporal->seconds();
308
    case INTERVAL_MICROSECOND:	
309
      return (int64_t) temporal->useconds();
310
    case INTERVAL_DAY_MICROSECOND: 
311
      return (int64_t) 
312
              (
313
              (
314
              (int64_t) (temporal->days() * 1000000L) 
315
            + (int64_t) (temporal->hours() * 10000L) 
316
            + (temporal->minutes() * 100L) 
317
            + temporal->seconds()
318
              ) 
319
              * 1000000L
320
              ) 
321
            + temporal->useconds();
322
    case INTERVAL_HOUR_MICROSECOND:
323
        return (int64_t)
324
              (
325
              (
326
              (int64_t) (temporal->hours() * 10000L) 
327
            + (temporal->minutes() * 100L) 
328
            + temporal->seconds()
329
              ) 
330
              * 1000000L
331
              ) 
332
            + temporal->useconds();
333
    case INTERVAL_MINUTE_MICROSECOND:
334
        return (int64_t)
335
              (
336
              (
337
              (temporal->minutes() * 100L) 
338
            + temporal->seconds()
339
              ) 
340
              * 1000000L
341
              ) 
342
            + temporal->useconds();
343
    case INTERVAL_SECOND_MICROSECOND: 
344
        return (int64_t) (temporal->seconds() * 1000000L)
345
            + temporal->useconds();
346
    case INTERVAL_LAST: 
347
    default:
348
        assert(0); 
971.6.11 by Eric Day
Removed purecov messages.
349
        return 0;
813.1.22 by Jay Pipes
default_week_format variable has gone the way of the Dodo, as have the
350
  }
574.3.22 by Lee
moving functions from drizzled/item/timefunc to drizzled/functions/time
351
}
352
353
bool Item_extract::eq(const Item *item, bool binary_cmp) const
354
{
355
  if (this == item)
356
    return 1;
357
  if (item->type() != FUNC_ITEM ||
358
      functype() != ((Item_func*)item)->functype())
359
    return 0;
360
361
  Item_extract* ie= (Item_extract*)item;
362
  if (ie->int_type != int_type)
363
    return 0;
364
365
  if (!args[0]->eq(ie->args[0], binary_cmp))
366
      return 0;
367
  return 1;
368
}
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
369
370
} /* namespace drizzled */