~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Brian Aker
  • Date: 2009-07-29 15:08:30 UTC
  • mfrom: (1093.1.36 captain)
  • Revision ID: brian@gaz-20090729150830-8sckl9aatssf1xjd
Merge Jay

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/get_interval_value.h>
23
 
 
24
 
 
25
 
/**
26
 
  @details
27
 
  Get a array of positive numbers from a string object.
28
 
  Each number is separated by 1 non digit character
29
 
  Return error if there is too many numbers.
30
 
  If there is too few numbers, assume that the numbers are left out
31
 
  from the high end. This allows one to give:
32
 
  DAY_TO_SECOND as "D MM:HH:SS", "MM:HH:SS" "HH:SS" or as seconds.
33
 
 
34
 
  @param length:         length of str
35
 
  @param cs:             charset of str
36
 
  @param values:         array of results
37
 
  @param count:          count of elements in result array
38
 
  @param transform_msec: if value is true we suppose
39
 
                         that the last part of string value is microseconds
40
 
                         and we should transform value to six digit value.
41
 
                         For example, '1.1' -> '1.100000'
42
 
*/
43
 
 
44
 
static bool get_interval_info(const char *str,uint32_t length, const CHARSET_INFO * const cs,
45
 
                              uint32_t count, uint64_t *values,
46
 
                              bool transform_msec)
47
 
{
48
 
  const char *end=str+length;
49
 
  uint32_t i;
50
 
  while (str != end && !my_isdigit(cs,*str))
51
 
    str++;
52
 
 
53
 
  for (i=0 ; i < count ; i++)
54
 
  {
55
 
    int64_t value;
56
 
    const char *start= str;
57
 
    for (value=0; str != end && my_isdigit(cs,*str) ; str++)
58
 
      value= value * 10L + (int64_t) (*str - '0');
59
 
    if (transform_msec && i == count - 1) // microseconds always last
60
 
    {
61
 
      long msec_length= 6 - (str - start);
62
 
      if (msec_length > 0)
63
 
        value*= (long) log_10_int[msec_length];
64
 
    }
65
 
    values[i]= value;
66
 
    while (str != end && !my_isdigit(cs,*str))
67
 
      str++;
68
 
    if (str == end && i != count-1)
69
 
    {
70
 
      i++;
71
 
      /* Change values[0...i-1] -> values[0...count-1] */
72
 
      bmove_upp((unsigned char*) (values+count), (unsigned char*) (values+i),
73
 
                sizeof(*values)*i);
74
 
      memset(values, 0, sizeof(*values)*(count-i));
75
 
      break;
76
 
    }
77
 
  }
78
 
  return (str != end);
79
 
}
80
 
 
81
 
 
82
 
/**
83
 
  Convert a string to a interval value.
84
 
 
85
 
  To make code easy, allow interval objects without separators.
86
 
*/
87
 
 
88
 
bool get_interval_value(Item *args,interval_type int_type,
89
 
                               String *str_value, INTERVAL *interval)
90
 
{
91
 
  uint64_t array[5];
92
 
  int64_t value= 0;
93
 
  const char *str= NULL;
94
 
  size_t length= 0;
95
 
  const CHARSET_INFO * const cs= str_value->charset();
96
 
 
97
 
  memset(interval, 0, sizeof(*interval));
98
 
  if ((int) int_type <= INTERVAL_MICROSECOND)
99
 
  {
100
 
    value= args->val_int();
101
 
    if (args->null_value)
102
 
      return 1;
103
 
    if (value < 0)
104
 
    {
105
 
      interval->neg=1;
106
 
      value= -value;
107
 
    }
108
 
  }
109
 
  else
110
 
  {
111
 
    String *res;
112
 
    if (!(res=args->val_str(str_value)))
113
 
      return (1);
114
 
 
115
 
    /* record negative intervalls in interval->neg */
116
 
    str=res->ptr();
117
 
    const char *end=str+res->length();
118
 
    while (str != end && my_isspace(cs,*str))
119
 
      str++;
120
 
    if (str != end && *str == '-')
121
 
    {
122
 
      interval->neg=1;
123
 
      str++;
124
 
    }
125
 
    length= (size_t) (end-str);         // Set up pointers to new str
126
 
  }
127
 
 
128
 
  switch (int_type) {
129
 
  case INTERVAL_YEAR:
130
 
    interval->year= (ulong) value;
131
 
    break;
132
 
  case INTERVAL_QUARTER:
133
 
    interval->month= (ulong)(value*3);
134
 
    break;
135
 
  case INTERVAL_MONTH:
136
 
    interval->month= (ulong) value;
137
 
    break;
138
 
  case INTERVAL_WEEK:
139
 
    interval->day= (ulong)(value*7);
140
 
    break;
141
 
  case INTERVAL_DAY:
142
 
    interval->day= (ulong) value;
143
 
    break;
144
 
  case INTERVAL_HOUR:
145
 
    interval->hour= (ulong) value;
146
 
    break;
147
 
  case INTERVAL_MICROSECOND:
148
 
    interval->second_part=value;
149
 
    break;
150
 
  case INTERVAL_MINUTE:
151
 
    interval->minute=value;
152
 
    break;
153
 
  case INTERVAL_SECOND:
154
 
    interval->second=value;
155
 
    break;
156
 
  case INTERVAL_YEAR_MONTH:                     // Allow YEAR-MONTH YYYYYMM
157
 
    if (get_interval_info(str,length,cs,2,array,0))
158
 
      return (1);
159
 
    interval->year=  (ulong) array[0];
160
 
    interval->month= (ulong) array[1];
161
 
    break;
162
 
  case INTERVAL_DAY_HOUR:
163
 
    if (get_interval_info(str,length,cs,2,array,0))
164
 
      return (1);
165
 
    interval->day=  (ulong) array[0];
166
 
    interval->hour= (ulong) array[1];
167
 
    break;
168
 
  case INTERVAL_DAY_MICROSECOND:
169
 
    if (get_interval_info(str,length,cs,5,array,1))
170
 
      return (1);
171
 
    interval->day=    (ulong) array[0];
172
 
    interval->hour=   (ulong) array[1];
173
 
    interval->minute= array[2];
174
 
    interval->second= array[3];
175
 
    interval->second_part= array[4];
176
 
    break;
177
 
  case INTERVAL_DAY_MINUTE:
178
 
    if (get_interval_info(str,length,cs,3,array,0))
179
 
      return (1);
180
 
    interval->day=    (ulong) array[0];
181
 
    interval->hour=   (ulong) array[1];
182
 
    interval->minute= array[2];
183
 
    break;
184
 
  case INTERVAL_DAY_SECOND:
185
 
    if (get_interval_info(str,length,cs,4,array,0))
186
 
      return (1);
187
 
    interval->day=    (ulong) array[0];
188
 
    interval->hour=   (ulong) array[1];
189
 
    interval->minute= array[2];
190
 
    interval->second= array[3];
191
 
    break;
192
 
  case INTERVAL_HOUR_MICROSECOND:
193
 
    if (get_interval_info(str,length,cs,4,array,1))
194
 
      return (1);
195
 
    interval->hour=   (ulong) array[0];
196
 
    interval->minute= array[1];
197
 
    interval->second= array[2];
198
 
    interval->second_part= array[3];
199
 
    break;
200
 
  case INTERVAL_HOUR_MINUTE:
201
 
    if (get_interval_info(str,length,cs,2,array,0))
202
 
      return (1);
203
 
    interval->hour=   (ulong) array[0];
204
 
    interval->minute= array[1];
205
 
    break;
206
 
  case INTERVAL_HOUR_SECOND:
207
 
    if (get_interval_info(str,length,cs,3,array,0))
208
 
      return (1);
209
 
    interval->hour=   (ulong) array[0];
210
 
    interval->minute= array[1];
211
 
    interval->second= array[2];
212
 
    break;
213
 
  case INTERVAL_MINUTE_MICROSECOND:
214
 
    if (get_interval_info(str,length,cs,3,array,1))
215
 
      return (1);
216
 
    interval->minute= array[0];
217
 
    interval->second= array[1];
218
 
    interval->second_part= array[2];
219
 
    break;
220
 
  case INTERVAL_MINUTE_SECOND:
221
 
    if (get_interval_info(str,length,cs,2,array,0))
222
 
      return (1);
223
 
    interval->minute= array[0];
224
 
    interval->second= array[1];
225
 
    break;
226
 
  case INTERVAL_SECOND_MICROSECOND:
227
 
    if (get_interval_info(str,length,cs,2,array,1))
228
 
      return (1);
229
 
    interval->second= array[0];
230
 
    interval->second_part= array[1];
231
 
    break;
232
 
  case INTERVAL_LAST: /* purecov: begin deadcode */
233
 
    assert(0);
234
 
    break;            /* purecov: end */
235
 
  }
236
 
  return 0;
237
 
}