~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/temporal_format.cc

  • Committer: Stewart Smith
  • Date: 2008-11-21 16:06:07 UTC
  • mto: This revision was merged to the branch mainline in revision 593.
  • Revision ID: stewart@flamingspork.com-20081121160607-n6gdlt013spuo54r
remove mysql_frm_type
and fix engines to return correct value from delete_table when table doesn't exist.
(it should be ENOENT).

Also fix up some tests that manipulated frm files by hand. These tests are no longer valid and will need to be rewritten in the not too distant future.

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
 
 *  Authors:
7
 
 *
8
 
 *  Jay Pipes <jay.pipes@sun.com>
9
 
 *
10
 
 *  This program is free software; you can redistribute it and/or modify
11
 
 *  it under the terms of the GNU General Public License as published by
12
 
 *  the Free Software Foundation; either version 2 of the License, or
13
 
 *  (at your option) any later version.
14
 
 *
15
 
 *  This program is distributed in the hope that it will be useful,
16
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 
 *  GNU General Public License for more details.
19
 
 *
20
 
 *  You should have received a copy of the GNU General Public License
21
 
 *  along with this program; if not, write to the Free Software
22
 
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
23
 
 */
24
 
 
25
 
/**
26
 
 * @file 
27
 
 *
28
 
 * Implementation of the server's date and time string matching utility.
29
 
 */
30
 
 
31
 
#include "config.h"
32
 
 
33
 
#include "drizzled/temporal_format.h"
34
 
#include "drizzled/temporal.h"
35
 
 
36
 
#include <string.h>
37
 
#include PCRE_HEADER
38
 
 
39
 
#include <string>
40
 
#include <vector>
41
 
 
42
 
using namespace std;
43
 
 
44
 
namespace drizzled
45
 
{
46
 
 
47
 
TemporalFormat::TemporalFormat(const char *pattern) :
48
 
  _pattern(pattern)
49
 
, _error_offset(0)
50
 
, _error(NULL)
51
 
, _year_part_index(0)
52
 
, _month_part_index(0)
53
 
, _day_part_index(0)
54
 
, _hour_part_index(0)
55
 
, _minute_part_index(0)
56
 
, _second_part_index(0)
57
 
, _usecond_part_index(0)
58
 
, _nsecond_part_index(0)
59
 
{
60
 
  /* Compile our regular expression */
61
 
  _re= pcre_compile(pattern
62
 
                    , 0 /* Default options */
63
 
                    , &_error
64
 
                    , &_error_offset
65
 
                    , NULL /* Use default character table */
66
 
                    );
67
 
}
68
 
 
69
 
bool TemporalFormat::matches(const char *data, size_t data_len, Temporal *to)
70
 
{
71
 
  if (! is_valid()) 
72
 
    return false;
73
 
 
74
 
  int32_t match_vector[OUT_VECTOR_SIZE]; /**< Stores match substring indexes */
75
 
  
76
 
  /* Make sure we've got no junk in the match_vector. */
77
 
  memset(match_vector, 0, sizeof(match_vector));
78
 
 
79
 
  /* Simply check the subject against the compiled regular expression */
80
 
  int32_t result= pcre_exec(_re
81
 
                            , NULL /* No extra data */
82
 
                            , data
83
 
                            , data_len
84
 
                            , 0 /* Start at offset 0 of subject...*/
85
 
                            , 0 /* Default options */
86
 
                            , match_vector
87
 
                            , OUT_VECTOR_SIZE
88
 
                            );
89
 
  if (result < 0)
90
 
  {
91
 
    switch (result)
92
 
    {
93
 
      case PCRE_ERROR_NOMATCH:
94
 
        return false; /* No match, just return false */
95
 
      default:
96
 
        return false;
97
 
    }
98
 
    return false;
99
 
  }
100
 
 
101
 
  int32_t expected_match_count= (_year_part_index > 1 ? 1 : 0)
102
 
                              + (_month_part_index > 1 ? 1 : 0)
103
 
                              + (_day_part_index > 1 ? 1 : 0)
104
 
                              + (_hour_part_index > 1 ? 1 : 0)
105
 
                              + (_minute_part_index > 1 ? 1 : 0)
106
 
                              + (_second_part_index > 1 ? 1 : 0)
107
 
                              + (_usecond_part_index > 1 ? 1 : 0)
108
 
                              + (_nsecond_part_index > 1 ? 1 : 0)
109
 
                              + 1; /* Add one for the entire match... */
110
 
  if (result != expected_match_count)
111
 
    return false;
112
 
 
113
 
  /* C++ string class easy to use substr() method is very useful here */
114
 
  string copy_data(data, data_len);
115
 
  /* 
116
 
   * OK, we have the expected substring matches, so grab
117
 
   * the various temporal parts from the subject string
118
 
   *
119
 
   * @note 
120
 
   *
121
 
   * TemporalFormatMatch is a friend class to Temporal, so
122
 
   * we can access the temporal instance's protected data.
123
 
   */
124
 
  if (_year_part_index > 1)
125
 
  {
126
 
    size_t year_start= match_vector[_year_part_index];
127
 
    size_t year_len= match_vector[_year_part_index + 1] - match_vector[_year_part_index];
128
 
    to->_years= atoi(copy_data.substr(year_start, year_len).c_str());
129
 
    if (year_len == 2)
130
 
      to->_years+= (to->_years >= DRIZZLE_YY_PART_YEAR ? 1900 : 2000);
131
 
  }
132
 
  if (_month_part_index > 1)
133
 
  {
134
 
    size_t month_start= match_vector[_month_part_index];
135
 
    size_t month_len= match_vector[_month_part_index + 1] - match_vector[_month_part_index];
136
 
    to->_months= atoi(copy_data.substr(month_start, month_len).c_str());
137
 
  }
138
 
  if (_day_part_index > 1)
139
 
  {
140
 
    size_t day_start= match_vector[_day_part_index];
141
 
    size_t day_len= match_vector[_day_part_index + 1] - match_vector[_day_part_index];
142
 
    to->_days= atoi(copy_data.substr(day_start, day_len).c_str());
143
 
  }
144
 
  if (_hour_part_index > 1)
145
 
  {
146
 
    size_t hour_start= match_vector[_hour_part_index];
147
 
    size_t hour_len= match_vector[_hour_part_index + 1] - match_vector[_hour_part_index];
148
 
    to->_hours= atoi(copy_data.substr(hour_start, hour_len).c_str());
149
 
  }
150
 
  if (_minute_part_index > 1)
151
 
  {
152
 
    size_t minute_start= match_vector[_minute_part_index];
153
 
    size_t minute_len= match_vector[_minute_part_index + 1] - match_vector[_minute_part_index];
154
 
    to->_minutes= atoi(copy_data.substr(minute_start, minute_len).c_str());
155
 
  }
156
 
  if (_second_part_index > 1)
157
 
  {
158
 
    size_t second_start= match_vector[_second_part_index];
159
 
    size_t second_len= match_vector[_second_part_index + 1] - match_vector[_second_part_index];
160
 
    to->_seconds= atoi(copy_data.substr(second_start, second_len).c_str());
161
 
  }
162
 
  if (_usecond_part_index > 1)
163
 
  {
164
 
    size_t usecond_start= match_vector[_usecond_part_index];
165
 
    size_t usecond_len= match_vector[_usecond_part_index + 1] - match_vector[_usecond_part_index];
166
 
    /* 
167
 
     * For microseconds, which are millionth of 1 second, 
168
 
     * we must ensure that we produce a correct result, 
169
 
     * even if < 6 places were specified.  For instance, if we get .1, 
170
 
     * we must produce 100000. .11 should produce 110000, etc.
171
 
     */
172
 
    uint32_t multiplier= 1;
173
 
    int32_t x= usecond_len;
174
 
    while (x < 6)
175
 
    {
176
 
      multiplier*= 10;
177
 
      ++x;
178
 
    }
179
 
    to->_useconds= atoi(copy_data.substr(usecond_start, usecond_len).c_str()) * multiplier;
180
 
  }
181
 
  if (_nsecond_part_index > 1)
182
 
  {
183
 
    size_t nsecond_start= match_vector[_nsecond_part_index];
184
 
    size_t nsecond_len= match_vector[_nsecond_part_index + 1] - match_vector[_nsecond_part_index];
185
 
    /* 
186
 
     * For nanoseconds, which are 1 billionth of a second, 
187
 
     * we must ensure that we produce a correct result, 
188
 
     * even if < 9 places were specified.  For instance, if we get .1, 
189
 
     * we must produce 100000000. .11 should produce 110000000, etc.
190
 
     */
191
 
    uint32_t multiplier= 1;
192
 
    int32_t x= nsecond_len;
193
 
    while (x < 9)
194
 
    {
195
 
      multiplier*= 10;
196
 
      ++x;
197
 
    }
198
 
    to->_nseconds= atoi(copy_data.substr(nsecond_start, nsecond_len).c_str()) * multiplier;
199
 
  }
200
 
  return true;
201
 
}
202
 
 
203
 
 
204
 
#define COUNT_KNOWN_FORMATS 19
205
 
 
206
 
struct temporal_format_args
207
 
{
208
 
  const char *pattern;
209
 
  int32_t year_part_index;
210
 
  int32_t month_part_index;
211
 
  int32_t day_part_index;
212
 
  int32_t hour_part_index;
213
 
  int32_t minute_part_index;
214
 
  int32_t second_part_index;
215
 
  int32_t usecond_part_index;
216
 
  int32_t nsecond_part_index;
217
 
};
218
 
 
219
 
/**
220
 
 * A collection of all known format strings.
221
 
 *
222
 
 * @note
223
 
 *
224
 
 * IMPORTANT: Make sure TIMESTAMP and DATETIME formats precede DATE formats and TIME formats, 
225
 
 * as the matching functionality matches on the first hit.
226
 
 *
227
 
 * @note 
228
 
 *
229
 
 * Remember to increment COUNT_KNOWN_FORMATS when you add a known format!
230
 
 */
231
 
static struct temporal_format_args __format_args[COUNT_KNOWN_FORMATS]= 
232
 
{
233
 
  {"^(\\d{4})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})\\.(\\d{1,6})$", 1, 2, 3, 4, 5, 6, 7, 0} /* YYYYMMDDHHmmSS.uuuuuu */
234
 
, {"^(\\d{4})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})$", 1, 2, 3, 4, 5, 6, 0, 0} /* YYYYMMDDHHmmSS */
235
 
, {"^(\\d{4})[-/.](\\d{1,2})[-/.](\\d{1,2})[T|\\s+](\\d{2}):(\\d{2}):(\\d{2})\\.(\\d{1,6})$", 1, 2, 3, 4, 5, 6, 7, 0} /* YYYY[/-.]MM[/-.]DD[T]HH:mm:SS.uuuuuu */
236
 
, {"^(\\d{4})[-/.](\\d{1,2})[-/.](\\d{1,2})[T|\\s+](\\d{2}):(\\d{2}):(\\d{2})$", 1, 2, 3, 4, 5, 6, 0, 0} /* YYYY[/-.][M]M[/-.][D]D[T]HH:mm:SS */
237
 
, {"^(\\d{2})[-/.](\\d{1,2})[-/.](\\d{1,2})[\\s+](\\d{2}):(\\d{2}):(\\d{2})$", 1, 2, 3, 4, 5, 6, 0, 0} /* YY[/-.][M]M[/-.][D]D HH:mm:SS */
238
 
, {"^(\\d{2})[-/.](\\d{1,2})[-/.](\\d{1,2})[\\s+](\\d{2}):(\\d{2})$", 1, 2, 3, 4, 5, 0, 0, 0} /* YY[/-.][M]M[/-.][D]D HH:mm */
239
 
, {"^(\\d{4})[-/.](\\d{1,2})[-/.](\\d{1,2})[\\s+](\\d{2}):(\\d{2})$", 1, 2, 3, 4, 5, 0, 0, 0} /* YYYY[/-.][M]M[/-.][D]D HH:mm */
240
 
, {"^(\\d{4})[-/.](\\d{1,2})[-/.](\\d{1,2})$", 1, 2, 3, 0, 0, 0, 0, 0} /* YYYY-[M]M-[D]D, YYYY.[M]M.[D]D, YYYY/[M]M/[D]D */ 
241
 
, {"^(\\d{4})(\\d{2})(\\d{2})$", 1, 2, 3, 0, 0, 0, 0, 0} /* YYYYMMDD */
242
 
, {"^(\\d{2})[-/.]*(\\d{2})[-/.]*(\\d{4})$", 3, 1, 2, 0, 0, 0, 0, 0} /* MM[-/.]DD[-/.]YYYY (US common format)*/
243
 
, {"^(\\d{2})[-/.]*(\\d{2})[-/.]*(\\d{2})$", 1, 2, 3, 0, 0, 0, 0, 0} /* YY[-/.]MM[-/.]DD */
244
 
, {"^(\\d{2})[-/.]*(\\d{1,2})[-/.]*(\\d{1,2})$", 1, 2, 3, 0, 0, 0, 0, 0} /* YY[-/.][M]M[-/.][D]D */
245
 
, {"^(\\d{4})[-/.]*(\\d{1,2})[-/.]*(\\d{1,2})$", 1, 2, 3, 0, 0, 0, 0, 0} /* YYYY[-/.][M]M[-/.][D]D */
246
 
, {"^(\\d{2}):*(\\d{2}):*(\\d{2})\\.(\\d{1,6})$", 0, 0, 0, 1, 2, 3, 4, 0} /* HHmmSS.uuuuuu, HH:mm:SS.uuuuuu */
247
 
, {"^(\\d{1,2}):*(\\d{2}):*(\\d{2})$", 0, 0, 0, 1, 2, 3, 0, 0} /* [H]HmmSS, [H]H:mm:SS */
248
 
, {"^(\\d{1,2}):(\\d{1,2}):(\\d{1,2})$", 0, 0, 0, 1, 2, 3, 0, 0} /* [H]H:[m]m:[S]S */
249
 
, {"^(\\d{1,2}):*(\\d{2})$", 0, 0, 0, 0, 1, 2, 0, 0} /* [m]mSS, [m]m:SS */
250
 
, {"^(\\d{1,2})$", 0, 0, 0, 0, 0, 1, 0, 0} /* SS, S */
251
 
, {"^(\\d{1,2})\\.(\\d{1,6})$", 0, 0, 0, 0, 0, 1, 2, 0} /* [S]S.uuuuuu */
252
 
};
253
 
 
254
 
vector<TemporalFormat *> known_datetime_formats;
255
 
vector<TemporalFormat *> known_date_formats;
256
 
vector<TemporalFormat *> known_time_formats;
257
 
vector<TemporalFormat *> all_temporal_formats;
258
 
 
259
 
/**
260
 
 * We allocate and initialize all known date/time formats.
261
 
 *
262
 
 * @TODO Cut down calls to new. Allocate as a block...
263
 
 */
264
 
bool init_temporal_formats()
265
 
{
266
 
  /* Compile all the regular expressions for the datetime formats */
267
 
  TemporalFormat *tmp;
268
 
  struct temporal_format_args current_format_args;
269
 
  int32_t x;
270
 
  
271
 
  for (x= 0; x<COUNT_KNOWN_FORMATS; ++x)
272
 
  {
273
 
    current_format_args= __format_args[x];
274
 
    tmp= new TemporalFormat(current_format_args.pattern);
275
 
    tmp->set_year_part_index(current_format_args.year_part_index);
276
 
    tmp->set_month_part_index(current_format_args.month_part_index);
277
 
    tmp->set_day_part_index(current_format_args.day_part_index);
278
 
    tmp->set_hour_part_index(current_format_args.hour_part_index);
279
 
    tmp->set_minute_part_index(current_format_args.minute_part_index);
280
 
    tmp->set_second_part_index(current_format_args.second_part_index);
281
 
    tmp->set_usecond_part_index(current_format_args.usecond_part_index);
282
 
    tmp->set_nsecond_part_index(current_format_args.nsecond_part_index);
283
 
    
284
 
    /* 
285
 
     * We store the pointer in all_temporal_formats because we 
286
 
     * delete pointers from that vector and only that vector
287
 
     */
288
 
    all_temporal_formats.push_back(tmp); 
289
 
 
290
 
    if (current_format_args.year_part_index > 0) /* A date must have a year */
291
 
    {
292
 
      known_datetime_formats.push_back(tmp);
293
 
      if (current_format_args.second_part_index == 0) /* A time must have seconds. */
294
 
        known_date_formats.push_back(tmp);
295
 
    }
296
 
    if (current_format_args.second_part_index > 0) /* A time must have seconds, but may not have minutes or hours */
297
 
      if (current_format_args.year_part_index == 0) /* A time may not have a date part, and date parts must have a year */
298
 
        known_time_formats.push_back(tmp);
299
 
  }
300
 
  return true;
301
 
}
302
 
 
303
 
/** Free all allocated temporal formats */
304
 
void deinit_temporal_formats()
305
 
{
306
 
  vector<TemporalFormat *>::iterator p= all_temporal_formats.begin();
307
 
  while (p != all_temporal_formats.end())
308
 
  {
309
 
    delete *p;
310
 
    ++p;
311
 
  }
312
 
  known_date_formats.clear();
313
 
  known_datetime_formats.clear();
314
 
  known_time_formats.clear();
315
 
  all_temporal_formats.clear();
316
 
}
317
 
 
318
 
} /* end namespace drizzled */