~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Brian Aker
  • Date: 2010-02-11 22:43:58 UTC
  • Revision ID: brian@gaz-20100211224358-y0gdvnat2ahg4c1e
Disabling support for memcached plugins until we can test for version of
memcached.

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
 
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 (! temporal.from_string(res->c_ptr(), res->length()))
 
86
        {
 
87
          /* 
 
88
          * Could not interpret the function argument as a temporal value, 
 
89
          * so throw an error and return 0
 
90
          */
 
91
          my_error(ER_INVALID_DATETIME_VALUE, MYF(0), res->c_ptr());
 
92
          return 0;
 
93
        }
 
94
      }
 
95
      break;
 
96
    case INT_RESULT:
 
97
      if (temporal.from_int64_t(args[0]->val_int()))
 
98
        break;
 
99
      /* Intentionally fall-through on invalid conversion from integer */
 
100
    default:
 
101
      {
 
102
        /* 
 
103
        * Could not interpret the function argument as a temporal value, 
 
104
        * so throw an error and return 0
 
105
        */
 
106
        null_value= true;
 
107
        char buff[DRIZZLE_MAX_LENGTH_DATETIME_AS_STRING];
 
108
        String tmp(buff,sizeof(buff), &my_charset_utf8_bin);
 
109
        String *res;
 
110
 
 
111
        res= args[0]->val_str(&tmp);
 
112
 
 
113
        if (! res)
 
114
        {
 
115
          /* 
 
116
           * Likely a nested function issue where the nested
 
117
           * function had bad input.  We rely on the nested
 
118
           * function my_error() and simply return false here.
 
119
           */
 
120
          return false;
 
121
        }
 
122
 
 
123
        my_error(ER_INVALID_DATETIME_VALUE, MYF(0), res->c_ptr());
 
124
        return 0;
 
125
      }
 
126
  }
 
127
  int64_t julian_day_number;
 
128
  temporal.to_julian_day_number(&julian_day_number);
 
129
  return julian_day_number;
 
130
}
 
131
 
 
132
int64_t Item_func_to_days::val_int_endpoint(bool left_endp, bool *incl_endp)
 
133
{
 
134
  assert(fixed);
 
135
 
 
136
  /*
 
137
   * We attempt to convert the first argument into a
 
138
   * temporal value.  If the conversion is successful, 
 
139
   * we know that a conversion to a Julian Day Number
 
140
   * is always possible. Depending on whether the 
 
141
   * first argument is a Date, or a DateTime with no
 
142
   * time-portion, we return the Julian Day Number or
 
143
   * the appropriate end-point integer.
 
144
   */
 
145
  /* Grab the first argument as a DateTime object */
 
146
  DateTime temporal;
 
147
  Item_result arg0_result_type= args[0]->result_type();
 
148
  
 
149
  switch (arg0_result_type)
 
150
  {
 
151
    case REAL_RESULT:
 
152
    case DECIMAL_RESULT: 
 
153
      /* 
 
154
       * For doubles supplied, interpret the arg as a string, 
 
155
       * so intentionally fall-through here...
 
156
       * This allows us to accept double parameters like 
 
157
       * 19971231235959.01 and interpret it the way MySQL does:
 
158
       * as a TIMESTAMP-like thing with a microsecond component.
 
159
       * Ugh, but need to keep backwards-compat.
 
160
       */
 
161
    case STRING_RESULT:
 
162
      {
 
163
        char buff[DRIZZLE_MAX_LENGTH_DATETIME_AS_STRING];
 
164
        String tmp(buff,sizeof(buff), &my_charset_utf8_bin);
 
165
        String *res= args[0]->val_str(&tmp);
 
166
 
 
167
        if (! res)
 
168
        {
 
169
          /* 
 
170
           * Likely a nested function issue where the nested
 
171
           * function had bad input.  We rely on the nested
 
172
           * function my_error() and simply return false here.
 
173
           */
 
174
          return 0;
 
175
        }
 
176
 
 
177
        if (! temporal.from_string(res->c_ptr(), res->length()))
 
178
        {
 
179
          /* 
 
180
          * Could not interpret the function argument as a temporal value, 
 
181
          * so throw an error and return 0
 
182
          */
 
183
          my_error(ER_INVALID_DATETIME_VALUE, MYF(0), res->c_ptr());
 
184
          return 0;
 
185
        }
 
186
      }
 
187
      break;
 
188
    case INT_RESULT:
 
189
      if (temporal.from_int64_t(args[0]->val_int()))
 
190
        break;
 
191
      /* Intentionally fall-through on invalid conversion from integer */
 
192
    default:
 
193
      {
 
194
        /* 
 
195
        * Could not interpret the function argument as a temporal value, 
 
196
        * so throw an error and return 0
 
197
        */
 
198
        null_value= true;
 
199
        char buff[DRIZZLE_MAX_LENGTH_DATETIME_AS_STRING];
 
200
        String tmp(buff,sizeof(buff), &my_charset_utf8_bin);
 
201
        String *res;
 
202
 
 
203
        res= args[0]->val_str(&tmp);
 
204
 
 
205
        if (! res)
 
206
        {
 
207
          /* 
 
208
           * Likely a nested function issue where the nested
 
209
           * function had bad input.  We rely on the nested
 
210
           * function my_error() and simply return false here.
 
211
           */
 
212
          return 0;
 
213
        }
 
214
 
 
215
        my_error(ER_INVALID_DATETIME_VALUE, MYF(0), res->c_ptr());
 
216
        return 0;
 
217
      }
 
218
  }
 
219
 
 
220
  if (null_value == true)
 
221
  {
 
222
    /* got NULL, leave the incl_endp intact */
 
223
    return INT64_MIN;
 
224
  }
 
225
 
 
226
  int64_t julian_day_number;
 
227
  temporal.to_julian_day_number(&julian_day_number);
 
228
 
 
229
  if (args[0]->field_type() == DRIZZLE_TYPE_DATE)
 
230
  {
 
231
    /* TO_DAYS() is strictly monotonic for dates, leave incl_endp intact */
 
232
    return julian_day_number;
 
233
  }
 
234
 
 
235
  /*
 
236
    Handle the special but practically useful case of datetime values that
 
237
    point to day bound ("strictly less" comparison stays intact):
 
238
 
 
239
      col < '2007-09-15 00:00:00'  -> TO_DAYS(col) <  TO_DAYS('2007-09-15')
 
240
 
 
241
    which is different from the general case ("strictly less" changes to
 
242
    "less or equal"):
 
243
 
 
244
      col < '2007-09-15 12:34:56'  -> TO_DAYS(col) <= TO_DAYS('2007-09-15')
 
245
  */
 
246
  if (!left_endp && ! (
 
247
                    temporal.hours() 
 
248
                    || temporal.minutes()
 
249
                    || temporal.seconds() 
 
250
                    || temporal.useconds()
 
251
                    || temporal.nseconds()
 
252
                    )
 
253
                    )
 
254
    ; /* do nothing */
 
255
  else
 
256
    *incl_endp= true;
 
257
  return julian_day_number;
 
258
}
 
259
 
 
260
} /* namespace drizzled */