~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Monty Taylor
  • Date: 2009-03-24 17:44:41 UTC
  • mto: (960.5.2 mordred)
  • mto: This revision was merged to the branch mainline in revision 964.
  • Revision ID: mordred@inaugust.com-20090324174441-nmsq0gwjlgf7f0mt
Changed handlerton to StorageEngine.

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 "drizzled/server_includes.h"
 
21
#include CSTDINT_H
 
22
#include "drizzled/function/time/to_days.h"
 
23
#include "drizzled/error.h"
 
24
#include "drizzled/temporal.h"
 
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
 */
 
30
int64_t Item_func_to_days::val_int()
 
31
{
 
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;
 
127
}
 
128
 
 
129
/*
 
130
  Get information about this Item tree monotonicity
 
131
 
 
132
  SYNOPSIS
 
133
    Item_func_to_days::get_monotonicity_info()
 
134
 
 
135
  DESCRIPTION
 
136
  Get information about monotonicity of the function represented by this item
 
137
  tree.
 
138
 
 
139
  RETURN
 
140
    See enum_monotonicity_info.
 
141
*/
 
142
enum_monotonicity_info Item_func_to_days::get_monotonicity_info() const
 
143
{
 
144
  if (args[0]->type() == Item::FIELD_ITEM)
 
145
  {
 
146
    if (args[0]->field_type() == DRIZZLE_TYPE_DATE)
 
147
      return MONOTONIC_STRICT_INCREASING;
 
148
    if (args[0]->field_type() == DRIZZLE_TYPE_DATETIME)
 
149
      return MONOTONIC_INCREASING;
 
150
  }
 
151
  return NON_MONOTONIC;
 
152
}
 
153
 
 
154
int64_t Item_func_to_days::val_int_endpoint(bool left_endp, bool *incl_endp)
 
155
{
 
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)
 
243
  {
 
244
    /* got NULL, leave the incl_endp intact */
 
245
    return INT64_MIN;
 
246
  }
 
247
 
 
248
  int64_t julian_day_number;
 
249
  temporal.to_julian_day_number(&julian_day_number);
 
250
 
 
251
  if (args[0]->field_type() == DRIZZLE_TYPE_DATE)
 
252
  {
 
253
    /* TO_DAYS() is strictly monotonic for dates, leave incl_endp intact */
 
254
    return julian_day_number;
 
255
  }
 
256
 
 
257
  /*
 
258
    Handle the special but practically useful case of datetime values that
 
259
    point to day bound ("strictly less" comparison stays intact):
 
260
 
 
261
      col < '2007-09-15 00:00:00'  -> TO_DAYS(col) <  TO_DAYS('2007-09-15')
 
262
 
 
263
    which is different from the general case ("strictly less" changes to
 
264
    "less or equal"):
 
265
 
 
266
      col < '2007-09-15 12:34:56'  -> TO_DAYS(col) <= TO_DAYS('2007-09-15')
 
267
  */
 
268
  if (!left_endp && ! (
 
269
                    temporal.hours() 
 
270
                    || temporal.minutes()
 
271
                    || temporal.seconds() 
 
272
                    || temporal.useconds()
 
273
                    || temporal.nseconds()
 
274
                    )
 
275
                    )
 
276
    ; /* do nothing */
 
277
  else
 
278
    *incl_endp= true;
 
279
  return julian_day_number;
 
280
}