~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Brian Aker
  • Date: 2008-10-06 06:47:29 UTC
  • Revision ID: brian@tangent.org-20081006064729-2i9mhjkzyvow9xsm
RemoveĀ uint.

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
 
}