~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Brian Aker
  • Date: 2009-02-18 19:27:32 UTC
  • mfrom: (873.1.17 temporal-new)
  • Revision ID: brian@tangent.org-20090218192732-ype4iscybtftjk2y
Merge Jay

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/to_days.h>
 
22
#include "drizzled/function/time/to_days.h"
 
23
#include "drizzled/error.h"
 
24
#include "drizzled/temporal.h"
23
25
 
 
26
/* 
 
27
 * We intepret the first argument as a DateTime and then convert
 
28
 * it to a Julian Day Number and return it.
 
29
 */
24
30
int64_t Item_func_to_days::val_int()
25
31
{
26
 
  assert(fixed == 1);
27
 
  DRIZZLE_TIME ltime;
28
 
  if (get_arg0_date(&ltime, TIME_NO_ZERO_DATE))
29
 
    return 0;
30
 
  return (int64_t) calc_daynr(ltime.year,ltime.month,ltime.day);
 
32
  assert(fixed);
 
33
 
 
34
  /* We return NULL from FROM_DAYS() only when supplied a NULL argument */
 
35
  if (args[0]->null_value)
 
36
  {
 
37
    null_value= true;
 
38
    return false;
 
39
  }
 
40
 
 
41
  /*
 
42
   * We attempt to convert the first argument into a
 
43
   * temporal value.  If the conversion is successful, 
 
44
   * we know that a conversion to a Julian Day Number
 
45
   * is always possible.  Upon successful conversion, 
 
46
   * we return the Julian Day Number.  If no conversion
 
47
   * was possible into a temporal value, we throw an 
 
48
   * error and return 0, setting the null_value flag to true.
 
49
   */
 
50
  /* Grab the first argument as a DateTime object */
 
51
  drizzled::DateTime temporal;
 
52
  Item_result arg0_result_type= args[0]->result_type();
 
53
  
 
54
  switch (arg0_result_type)
 
55
  {
 
56
    case REAL_RESULT:
 
57
    case DECIMAL_RESULT: 
 
58
      /* 
 
59
       * For doubles supplied, interpret the arg as a string, 
 
60
       * so intentionally fall-through here...
 
61
       * This allows us to accept double parameters like 
 
62
       * 19971231235959.01 and interpret it the way MySQL does:
 
63
       * as a TIMESTAMP-like thing with a microsecond component.
 
64
       * Ugh, but need to keep backwards-compat.
 
65
       */
 
66
    case STRING_RESULT:
 
67
      {
 
68
        char buff[DRIZZLE_MAX_LENGTH_DATETIME_AS_STRING];
 
69
        String tmp(buff,sizeof(buff), &my_charset_utf8_bin);
 
70
        String *res= args[0]->val_str(&tmp);
 
71
 
 
72
        if (! res)
 
73
        {
 
74
          /* 
 
75
           * Likely a nested function issue where the nested
 
76
           * function had bad input.  We rely on the nested
 
77
           * function my_error() and simply return false here.
 
78
           */
 
79
          return false;
 
80
        }
 
81
 
 
82
        if (! temporal.from_string(res->c_ptr(), res->length()))
 
83
        {
 
84
          /* 
 
85
          * Could not interpret the function argument as a temporal value, 
 
86
          * so throw an error and return 0
 
87
          */
 
88
          my_error(ER_INVALID_DATETIME_VALUE, MYF(0), res->c_ptr());
 
89
          return 0;
 
90
        }
 
91
      }
 
92
      break;
 
93
    case INT_RESULT:
 
94
      if (temporal.from_int64_t(args[0]->val_int()))
 
95
        break;
 
96
      /* Intentionally fall-through on invalid conversion from integer */
 
97
    default:
 
98
      {
 
99
        /* 
 
100
        * Could not interpret the function argument as a temporal value, 
 
101
        * so throw an error and return 0
 
102
        */
 
103
        null_value= true;
 
104
        char buff[DRIZZLE_MAX_LENGTH_DATETIME_AS_STRING];
 
105
        String tmp(buff,sizeof(buff), &my_charset_utf8_bin);
 
106
        String *res;
 
107
 
 
108
        res= args[0]->val_str(&tmp);
 
109
 
 
110
        if (! res)
 
111
        {
 
112
          /* 
 
113
           * Likely a nested function issue where the nested
 
114
           * function had bad input.  We rely on the nested
 
115
           * function my_error() and simply return false here.
 
116
           */
 
117
          return false;
 
118
        }
 
119
 
 
120
        my_error(ER_INVALID_DATETIME_VALUE, MYF(0), res->c_ptr());
 
121
        return 0;
 
122
      }
 
123
  }
 
124
  int64_t julian_day_number;
 
125
  temporal.to_julian_day_number(&julian_day_number);
 
126
  return julian_day_number;
31
127
}
32
128
 
33
 
 
34
129
/*
35
130
  Get information about this Item tree monotonicity
36
131
 
44
139
  RETURN
45
140
    See enum_monotonicity_info.
46
141
*/
47
 
 
48
142
enum_monotonicity_info Item_func_to_days::get_monotonicity_info() const
49
143
{
50
144
  if (args[0]->type() == Item::FIELD_ITEM)
59
153
 
60
154
int64_t Item_func_to_days::val_int_endpoint(bool left_endp, bool *incl_endp)
61
155
{
62
 
  assert(fixed == 1);
63
 
  DRIZZLE_TIME ltime;
64
 
  int64_t res;
65
 
  if (get_arg0_date(&ltime, TIME_NO_ZERO_DATE))
 
156
  assert(fixed);
 
157
 
 
158
  /*
 
159
   * We attempt to convert the first argument into a
 
160
   * temporal value.  If the conversion is successful, 
 
161
   * we know that a conversion to a Julian Day Number
 
162
   * is always possible. Depending on whether the 
 
163
   * first argument is a Date, or a DateTime with no
 
164
   * time-portion, we return the Julian Day Number or
 
165
   * the appropriate end-point integer.
 
166
   */
 
167
  /* Grab the first argument as a DateTime object */
 
168
  drizzled::DateTime temporal;
 
169
  Item_result arg0_result_type= args[0]->result_type();
 
170
  
 
171
  switch (arg0_result_type)
 
172
  {
 
173
    case REAL_RESULT:
 
174
    case DECIMAL_RESULT: 
 
175
      /* 
 
176
       * For doubles supplied, interpret the arg as a string, 
 
177
       * so intentionally fall-through here...
 
178
       * This allows us to accept double parameters like 
 
179
       * 19971231235959.01 and interpret it the way MySQL does:
 
180
       * as a TIMESTAMP-like thing with a microsecond component.
 
181
       * Ugh, but need to keep backwards-compat.
 
182
       */
 
183
    case STRING_RESULT:
 
184
      {
 
185
        char buff[DRIZZLE_MAX_LENGTH_DATETIME_AS_STRING];
 
186
        String tmp(buff,sizeof(buff), &my_charset_utf8_bin);
 
187
        String *res= args[0]->val_str(&tmp);
 
188
 
 
189
        if (! res)
 
190
        {
 
191
          /* 
 
192
           * Likely a nested function issue where the nested
 
193
           * function had bad input.  We rely on the nested
 
194
           * function my_error() and simply return false here.
 
195
           */
 
196
          return 0;
 
197
        }
 
198
 
 
199
        if (! temporal.from_string(res->c_ptr(), res->length()))
 
200
        {
 
201
          /* 
 
202
          * Could not interpret the function argument as a temporal value, 
 
203
          * so throw an error and return 0
 
204
          */
 
205
          my_error(ER_INVALID_DATETIME_VALUE, MYF(0), res->c_ptr());
 
206
          return 0;
 
207
        }
 
208
      }
 
209
      break;
 
210
    case INT_RESULT:
 
211
      if (temporal.from_int64_t(args[0]->val_int()))
 
212
        break;
 
213
      /* Intentionally fall-through on invalid conversion from integer */
 
214
    default:
 
215
      {
 
216
        /* 
 
217
        * Could not interpret the function argument as a temporal value, 
 
218
        * so throw an error and return 0
 
219
        */
 
220
        null_value= true;
 
221
        char buff[DRIZZLE_MAX_LENGTH_DATETIME_AS_STRING];
 
222
        String tmp(buff,sizeof(buff), &my_charset_utf8_bin);
 
223
        String *res;
 
224
 
 
225
        res= args[0]->val_str(&tmp);
 
226
 
 
227
        if (! res)
 
228
        {
 
229
          /* 
 
230
           * Likely a nested function issue where the nested
 
231
           * function had bad input.  We rely on the nested
 
232
           * function my_error() and simply return false here.
 
233
           */
 
234
          return 0;
 
235
        }
 
236
 
 
237
        my_error(ER_INVALID_DATETIME_VALUE, MYF(0), res->c_ptr());
 
238
        return 0;
 
239
      }
 
240
  }
 
241
 
 
242
  if (null_value == true)
66
243
  {
67
244
    /* got NULL, leave the incl_endp intact */
68
245
    return INT64_MIN;
69
246
  }
70
 
  res=(int64_t) calc_daynr(ltime.year,ltime.month,ltime.day);
 
247
 
 
248
  int64_t julian_day_number;
 
249
  temporal.to_julian_day_number(&julian_day_number);
71
250
 
72
251
  if (args[0]->field_type() == DRIZZLE_TYPE_DATE)
73
252
  {
74
 
    // TO_DAYS() is strictly monotonic for dates, leave incl_endp intact
75
 
    return res;
 
253
    /* TO_DAYS() is strictly monotonic for dates, leave incl_endp intact */
 
254
    return julian_day_number;
76
255
  }
77
256
 
78
257
  /*
86
265
 
87
266
      col < '2007-09-15 12:34:56'  -> TO_DAYS(col) <= TO_DAYS('2007-09-15')
88
267
  */
89
 
  if (!left_endp && !(ltime.hour || ltime.minute || ltime.second ||
90
 
                      ltime.second_part))
 
268
  if (!left_endp && ! (
 
269
                    temporal.hours() 
 
270
                    || temporal.minutes()
 
271
                    || temporal.seconds() 
 
272
                    || temporal.useconds()
 
273
                    || temporal.nseconds()
 
274
                    )
 
275
                    )
91
276
    ; /* do nothing */
92
277
  else
93
278
    *incl_endp= true;
94
 
  return res;
 
279
  return julian_day_number;
95
280
}
96