~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Lee
  • Date: 2008-10-30 22:02:01 UTC
  • mto: (572.1.2 devel)
  • mto: This revision was merged to the branch mainline in revision 573.
  • Revision ID: lbieber@lbieber-desktop-20081030220201-elb6qprbzpn7c5a4
add my name to the AUTHORS file

Show diffs side-by-side

added added

removed removed

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