Merge lp:~dedzone/drizzle/ded-rm-my into lp:~drizzle-trunk/drizzle/development
- ded-rm-my
- Merge into development
Proposed by
Djellel E. Difallah
Status: | Merged |
---|---|
Merged at revision: | not available |
Proposed branch: | lp:~dedzone/drizzle/ded-rm-my |
Merge into: | lp:~drizzle-trunk/drizzle/development |
Diff against target: |
8376 lines (+3786/-3786) 48 files modified
client/client_priv.h (+1/-1) client/drizzle.cc (+2/-2) client/drizzledump.cc (+2/-2) client/drizzleimport.cc (+2/-2) client/drizzleslap.cc (+2/-2) client/drizzletest.cc (+4/-4) drizzled/decimal.h (+1/-1) drizzled/drizzle_time.cc (+1260/-0) drizzled/drizzle_time.h (+194/-0) drizzled/drizzled.cc (+5/-5) drizzled/include.am (+7/-7) drizzled/item.h (+1/-1) drizzled/item/sum.h (+1/-1) drizzled/my_getopt.cc (+0/-1289) drizzled/my_getopt.h (+0/-97) drizzled/my_getsystime.cc (+1/-1) drizzled/my_time.cc (+0/-1260) drizzled/my_time.h (+0/-194) drizzled/my_tree.cc (+0/-715) drizzled/my_tree.h (+0/-92) drizzled/my_var.h (+0/-41) drizzled/option.cc (+1289/-0) drizzled/option.h (+97/-0) drizzled/plugin.h (+3/-3) drizzled/plugin/loader.cc (+19/-19) drizzled/select_dumpvar.h (+3/-3) drizzled/session.h (+1/-1) drizzled/set_var.cc (+7/-7) drizzled/set_var.h (+6/-6) drizzled/sql_yacc.yy (+1/-1) drizzled/time_functions.h (+1/-1) drizzled/tree.cc (+715/-0) drizzled/tree.h (+92/-0) drizzled/unique.h (+1/-1) drizzled/uniques.cc (+1/-1) drizzled/var.h (+41/-0) extra/my_print_defaults.cc (+3/-3) plugin/archive/archive_performance.cc (+1/-1) plugin/archive/archive_reader.cc (+4/-4) plugin/archive/archive_test.cc (+1/-1) plugin/archive/concurrency_test.cc (+1/-1) plugin/heap/heap.h (+1/-1) plugin/heap/heap_priv.h (+1/-1) plugin/myisam/ha_myisam.cc (+5/-5) plugin/myisam/mi_check.cc (+1/-1) plugin/myisam/myisam_priv.h (+1/-1) support-files/drizzle.spec.in (+4/-4) tests/resolve_stack_dump.cc (+3/-3) |
To merge this branch: | bzr merge lp:~dedzone/drizzle/ded-rm-my |
Related bugs: | |
Related blueprints: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Brian Aker | Needs Fixing | ||
Jay Pipes (community) | Approve | ||
Review via email:
|
Commit message
Description of the change
file name changes:
my_tree => tree
my_var => var
my_time => drizzle_time
my_getopt => option
object changes:
my_option => option
ToDo list:
under ./drizzled/
./drizzled/
./drizzled/
To post a comment you must log in.
Revision history for this message
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Brian Aker (brianaker) wrote : | # |
Hi!
This code needs to be remerged with trunk.
Thanks!
-Brian
review:
Needs Fixing
lp:~dedzone/drizzle/ded-rm-my
updated
- 1415. By Djellel E. Difallah <ded@ubuntu>
-
merge to trunk
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'client/client_priv.h' |
2 | --- client/client_priv.h 2009-12-23 21:16:15 +0000 |
3 | +++ client/client_priv.h 2010-04-02 06:48:30 +0000 |
4 | @@ -19,7 +19,7 @@ |
5 | |
6 | #include "config.h" |
7 | #include <libdrizzle/drizzle_client.h> |
8 | -#include "drizzled/my_getopt.h" |
9 | +#include "drizzled/option.h" |
10 | #include "drizzled/internal/my_sys.h" |
11 | |
12 | #include "client/get_password.h" |
13 | |
14 | === modified file 'client/drizzle.cc' |
15 | --- client/drizzle.cc 2010-04-01 06:29:46 +0000 |
16 | +++ client/drizzle.cc 2010-04-02 06:48:30 +0000 |
17 | @@ -1418,7 +1418,7 @@ |
18 | } |
19 | #endif |
20 | |
21 | -static struct my_option my_long_options[] = |
22 | +static struct option my_long_options[] = |
23 | { |
24 | {"help", '?', N_("Display this help and exit."), 0, 0, 0, GET_NO_ARG, NO_ARG, 0, |
25 | 0, 0, 0, 0, 0}, |
26 | @@ -1606,7 +1606,7 @@ |
27 | } |
28 | |
29 | |
30 | -static int get_one_option(int optid, const struct my_option *, char *argument) |
31 | +static int get_one_option(int optid, const struct option *, char *argument) |
32 | { |
33 | char *endchar= NULL; |
34 | uint64_t temp_drizzle_port= 0; |
35 | |
36 | === modified file 'client/drizzledump.cc' |
37 | --- client/drizzledump.cc 2010-03-26 19:25:23 +0000 |
38 | +++ client/drizzledump.cc 2010-04-02 06:48:30 +0000 |
39 | @@ -155,7 +155,7 @@ |
40 | |
41 | drizzled::hash_set<string> ignore_table; |
42 | |
43 | -static struct my_option my_long_options[] = |
44 | +static struct option my_long_options[] = |
45 | { |
46 | {"all", 'a', "Deprecated. Use --create-options instead.", |
47 | (char**) &create_options, (char**) &create_options, 0, GET_BOOL, NO_ARG, 1, |
48 | @@ -509,7 +509,7 @@ |
49 | } /* write_footer */ |
50 | |
51 | |
52 | -static int get_one_option(int optid, const struct my_option *, char *argument) |
53 | +static int get_one_option(int optid, const struct option *, char *argument) |
54 | { |
55 | char *endchar= NULL; |
56 | uint64_t temp_drizzle_port= 0; |
57 | |
58 | === modified file 'client/drizzleimport.cc' |
59 | --- client/drizzleimport.cc 2010-03-26 21:57:02 +0000 |
60 | +++ client/drizzleimport.cc 2010-04-02 06:48:30 +0000 |
61 | @@ -67,7 +67,7 @@ |
62 | static uint32_t opt_drizzle_port= 0; |
63 | static int64_t opt_ignore_lines= -1; |
64 | |
65 | -static struct my_option my_long_options[] = |
66 | +static struct option my_long_options[] = |
67 | { |
68 | {"columns", 'c', |
69 | "Use only these columns to import the data to. Give the column names in a comma separated list. This is same as giving columns to LOAD DATA INFILE.", |
70 | @@ -170,7 +170,7 @@ |
71 | my_print_variables(my_long_options); |
72 | } |
73 | |
74 | -static int get_one_option(int optid, const struct my_option *, char *argument) |
75 | +static int get_one_option(int optid, const struct option *, char *argument) |
76 | { |
77 | char *endchar= NULL; |
78 | uint64_t temp_drizzle_port= 0; |
79 | |
80 | === modified file 'client/drizzleslap.cc' |
81 | --- client/drizzleslap.cc 2010-03-25 09:08:56 +0000 |
82 | +++ client/drizzleslap.cc 2010-04-02 06:48:30 +0000 |
83 | @@ -528,7 +528,7 @@ |
84 | } |
85 | |
86 | |
87 | -static struct my_option my_long_options[] = |
88 | +static struct option my_long_options[] = |
89 | { |
90 | {"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, |
91 | 0, 0, 0, 0, 0, 0}, |
92 | @@ -727,7 +727,7 @@ |
93 | my_print_help(my_long_options); |
94 | } |
95 | |
96 | -static int get_one_option(int optid, const struct my_option *, char *argument) |
97 | +static int get_one_option(int optid, const struct option *, char *argument) |
98 | { |
99 | char *endchar= NULL; |
100 | uint64_t temp_drizzle_port= 0; |
101 | |
102 | === modified file 'client/drizzletest.cc' |
103 | --- client/drizzletest.cc 2010-03-26 21:45:29 +0000 |
104 | +++ client/drizzletest.cc 2010-04-02 06:48:30 +0000 |
105 | @@ -64,7 +64,7 @@ |
106 | /* Added this for string translation. */ |
107 | #include "drizzled/gettext.h" |
108 | #include "drizzled/hash.h" |
109 | -#include "drizzled/my_time.h" |
110 | +#include "drizzled/drizzle_time.h" |
111 | #include "drizzled/charset.h" |
112 | |
113 | #ifndef DRIZZLE_RETURN_SERVER_GONE |
114 | @@ -77,7 +77,7 @@ |
115 | extern "C" |
116 | unsigned char *get_var_key(const unsigned char* var, size_t *len, bool); |
117 | |
118 | -int get_one_option(int optid, const struct my_option *, char *argument); |
119 | +int get_one_option(int optid, const struct option *, char *argument); |
120 | |
121 | #define MAX_VAR_NAME_LENGTH 256 |
122 | #define MAX_COLUMNS 256 |
123 | @@ -4578,7 +4578,7 @@ |
124 | } |
125 | |
126 | |
127 | -static struct my_option my_long_options[] = |
128 | +static struct option my_long_options[] = |
129 | { |
130 | {"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, |
131 | 0, 0, 0, 0, 0, 0}, |
132 | @@ -4666,7 +4666,7 @@ |
133 | my_print_variables(my_long_options); |
134 | } |
135 | |
136 | -int get_one_option(int optid, const struct my_option *, char *argument) |
137 | +int get_one_option(int optid, const struct option *, char *argument) |
138 | { |
139 | char *endchar= NULL; |
140 | uint64_t temp_drizzle_port= 0; |
141 | |
142 | === modified file 'drizzled/decimal.h' |
143 | --- drizzled/decimal.h 2010-03-28 03:03:18 +0000 |
144 | +++ drizzled/decimal.h 2010-04-02 06:48:30 +0000 |
145 | @@ -18,7 +18,7 @@ |
146 | #include <assert.h> |
147 | #include <drizzled/sql_string.h> |
148 | #include "drizzled/definitions.h" |
149 | -#include "drizzled/my_time.h" |
150 | +#include "drizzled/drizzle_time.h" |
151 | namespace drizzled |
152 | { |
153 | |
154 | |
155 | === added file 'drizzled/drizzle_time.cc' |
156 | --- drizzled/drizzle_time.cc 1970-01-01 00:00:00 +0000 |
157 | +++ drizzled/drizzle_time.cc 2010-04-02 06:48:30 +0000 |
158 | @@ -0,0 +1,1260 @@ |
159 | +/* Copyright (C) 2004-2006 MySQL AB |
160 | + |
161 | + This program is free software; you can redistribute it and/or modify |
162 | + it under the terms of the GNU General Public License as published by |
163 | + the Free Software Foundation; version 2 of the License. |
164 | + |
165 | + This program is distributed in the hope that it will be useful, |
166 | + but WITHOUT ANY WARRANTY; without even the implied warranty of |
167 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
168 | + GNU General Public License for more details. |
169 | + |
170 | + You should have received a copy of the GNU General Public License |
171 | + along with this program; if not, write to the Free Software |
172 | + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ |
173 | + |
174 | +#include "config.h" |
175 | + |
176 | +#include "drizzled/drizzle_time.h" |
177 | + |
178 | +#include "drizzled/internal/m_string.h" |
179 | +#include "drizzled/charset_info.h" |
180 | +#include <drizzled/util/test.h> |
181 | +#include "drizzled/definitions.h" |
182 | + |
183 | +#include <cstdio> |
184 | +#include <algorithm> |
185 | + |
186 | +using namespace std; |
187 | + |
188 | +namespace drizzled |
189 | +{ |
190 | + |
191 | +static int check_time_range(DRIZZLE_TIME *my_time, int *warning); |
192 | + |
193 | +/* Windows version of localtime_r() is declared in my_ptrhead.h */ |
194 | + |
195 | +uint64_t log_10_int[20]= |
196 | +{ |
197 | + 1, 10, 100, 1000, 10000UL, 100000UL, 1000000UL, 10000000UL, |
198 | + 100000000ULL, 1000000000ULL, 10000000000ULL, 100000000000ULL, |
199 | + 1000000000000ULL, 10000000000000ULL, 100000000000000ULL, |
200 | + 1000000000000000ULL, 10000000000000000ULL, 100000000000000000ULL, |
201 | + 1000000000000000000ULL, 10000000000000000000ULL |
202 | +}; |
203 | + |
204 | + |
205 | +/* Position for YYYY-DD-MM HH-MM-DD.FFFFFF AM in default format */ |
206 | + |
207 | +static unsigned char internal_format_positions[]= |
208 | +{0, 1, 2, 3, 4, 5, 6, (unsigned char) 255}; |
209 | + |
210 | +static char time_separator=':'; |
211 | + |
212 | +static uint32_t const days_at_timestart=719528; /* daynr at 1970.01.01 */ |
213 | +unsigned char days_in_month[]= {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0}; |
214 | + |
215 | +/* |
216 | + Offset of system time zone from UTC in seconds used to speed up |
217 | + work of my_system_gmt_sec() function. |
218 | +*/ |
219 | +static long my_time_zone=0; |
220 | + |
221 | + |
222 | +/* Calc days in one year. works with 0 <= year <= 99 */ |
223 | + |
224 | +uint32_t calc_days_in_year(uint32_t year) |
225 | +{ |
226 | + return ((year & 3) == 0 && (year%100 || (year%400 == 0 && year)) ? |
227 | + 366 : 365); |
228 | +} |
229 | + |
230 | +/** |
231 | + @brief Check datetime value for validity according to flags. |
232 | + |
233 | + @param[in] ltime Date to check. |
234 | + @param[in] not_zero_date ltime is not the zero date |
235 | + @param[in] flags flags to check |
236 | + (see str_to_datetime() flags in drizzle_time.h) |
237 | + @param[out] was_cut set to 2 if value was invalid according to flags. |
238 | + (Feb 29 in non-leap etc.) This remains unchanged |
239 | + if value is not invalid. |
240 | + |
241 | + @details Here we assume that year and month is ok! |
242 | + If month is 0 we allow any date. (This only happens if we allow zero |
243 | + date parts in str_to_datetime()) |
244 | + Disallow dates with zero year and non-zero month and/or day. |
245 | + |
246 | + @return |
247 | + 0 OK |
248 | + 1 error |
249 | +*/ |
250 | + |
251 | +bool check_date(const DRIZZLE_TIME *ltime, bool not_zero_date, |
252 | + uint32_t flags, int *was_cut) |
253 | +{ |
254 | + if (not_zero_date) |
255 | + { |
256 | + if ((((flags & TIME_NO_ZERO_IN_DATE) || !(flags & TIME_FUZZY_DATE)) && |
257 | + (ltime->month == 0 || ltime->day == 0)) || |
258 | + (!(flags & TIME_INVALID_DATES) && |
259 | + ltime->month && ltime->day > days_in_month[ltime->month-1] && |
260 | + (ltime->month != 2 || calc_days_in_year(ltime->year) != 366 || |
261 | + ltime->day != 29))) |
262 | + { |
263 | + *was_cut= 2; |
264 | + return true; |
265 | + } |
266 | + } |
267 | + else if (flags & TIME_NO_ZERO_DATE) |
268 | + { |
269 | + /* |
270 | + We don't set *was_cut here to signal that the problem was a zero date |
271 | + and not an invalid date |
272 | + */ |
273 | + return true; |
274 | + } |
275 | + return false; |
276 | +} |
277 | + |
278 | + |
279 | +/* |
280 | + Convert a timestamp string to a DRIZZLE_TIME value. |
281 | + |
282 | + SYNOPSIS |
283 | + str_to_datetime() |
284 | + str String to parse |
285 | + length Length of string |
286 | + l_time Date is stored here |
287 | + flags Bitmap of following items |
288 | + TIME_FUZZY_DATE Set if we should allow partial dates |
289 | + TIME_DATETIME_ONLY Set if we only allow full datetimes. |
290 | + TIME_NO_ZERO_IN_DATE Don't allow partial dates |
291 | + TIME_NO_ZERO_DATE Don't allow 0000-00-00 date |
292 | + TIME_INVALID_DATES Allow 2000-02-31 |
293 | + was_cut 0 Value OK |
294 | + 1 If value was cut during conversion |
295 | + 2 check_date(date,flags) considers date invalid |
296 | + |
297 | + DESCRIPTION |
298 | + At least the following formats are recogniced (based on number of digits) |
299 | + YYMMDD, YYYYMMDD, YYMMDDHHMMSS, YYYYMMDDHHMMSS |
300 | + YY-MM-DD, YYYY-MM-DD, YY-MM-DD HH.MM.SS |
301 | + YYYYMMDDTHHMMSS where T is a the character T (ISO8601) |
302 | + Also dates where all parts are zero are allowed |
303 | + |
304 | + The second part may have an optional .###### fraction part. |
305 | + |
306 | + NOTES |
307 | + This function should work with a format position vector as long as the |
308 | + following things holds: |
309 | + - All date are kept together and all time parts are kept together |
310 | + - Date and time parts must be separated by blank |
311 | + - Second fractions must come after second part and be separated |
312 | + by a '.'. (The second fractions are optional) |
313 | + - AM/PM must come after second fractions (or after seconds if no fractions) |
314 | + - Year must always been specified. |
315 | + - If time is before date, then we will use datetime format only if |
316 | + the argument consist of two parts, separated by space. |
317 | + Otherwise we will assume the argument is a date. |
318 | + - The hour part must be specified in hour-minute-second order. |
319 | + |
320 | + RETURN VALUES |
321 | + DRIZZLE_TIMESTAMP_NONE String wasn't a timestamp, like |
322 | + [DD [HH:[MM:[SS]]]].fraction. |
323 | + l_time is not changed. |
324 | + DRIZZLE_TIMESTAMP_DATE DATE string (YY MM and DD parts ok) |
325 | + DRIZZLE_TIMESTAMP_DATETIME Full timestamp |
326 | + DRIZZLE_TIMESTAMP_ERROR Timestamp with wrong values. |
327 | + All elements in l_time is set to 0 |
328 | +*/ |
329 | + |
330 | +#define MAX_DATE_PARTS 8 |
331 | + |
332 | +enum enum_drizzle_timestamp_type |
333 | +str_to_datetime(const char *str, uint32_t length, DRIZZLE_TIME *l_time, |
334 | + uint32_t flags, int *was_cut) |
335 | +{ |
336 | + uint32_t field_length, year_length=4, digits, i, number_of_fields; |
337 | + uint32_t date[MAX_DATE_PARTS], date_len[MAX_DATE_PARTS]; |
338 | + uint32_t add_hours= 0, start_loop; |
339 | + uint32_t not_zero_date, allow_space; |
340 | + bool is_internal_format; |
341 | + const char *pos, *last_field_pos=NULL; |
342 | + const char *end=str+length; |
343 | + const unsigned char *format_position; |
344 | + bool found_delimitier= 0, found_space= 0; |
345 | + uint32_t frac_pos, frac_len; |
346 | + |
347 | + *was_cut= 0; |
348 | + |
349 | + /* Skip space at start */ |
350 | + for (; str != end && my_isspace(&my_charset_utf8_general_ci, *str) ; str++) |
351 | + ; |
352 | + if (str == end || ! my_isdigit(&my_charset_utf8_general_ci, *str)) |
353 | + { |
354 | + *was_cut= 1; |
355 | + return(DRIZZLE_TIMESTAMP_NONE); |
356 | + } |
357 | + |
358 | + is_internal_format= 0; |
359 | + /* This has to be changed if want to activate different timestamp formats */ |
360 | + format_position= internal_format_positions; |
361 | + |
362 | + /* |
363 | + Calculate number of digits in first part. |
364 | + If length= 8 or >= 14 then year is of format YYYY. |
365 | + (YYYY-MM-DD, YYYYMMDD, YYYYYMMDDHHMMSS) |
366 | + */ |
367 | + for (pos=str; |
368 | + pos != end && (my_isdigit(&my_charset_utf8_general_ci,*pos) || *pos == 'T'); |
369 | + pos++) |
370 | + ; |
371 | + |
372 | + digits= (uint32_t) (pos-str); |
373 | + start_loop= 0; /* Start of scan loop */ |
374 | + date_len[format_position[0]]= 0; /* Length of year field */ |
375 | + if (pos == end || *pos == '.') |
376 | + { |
377 | + /* Found date in internal format (only numbers like YYYYMMDD) */ |
378 | + year_length= (digits == 4 || digits == 8 || digits >= 14) ? 4 : 2; |
379 | + field_length= year_length; |
380 | + is_internal_format= 1; |
381 | + format_position= internal_format_positions; |
382 | + } |
383 | + else |
384 | + { |
385 | + if (format_position[0] >= 3) /* If year is after HHMMDD */ |
386 | + { |
387 | + /* |
388 | + If year is not in first part then we have to determinate if we got |
389 | + a date field or a datetime field. |
390 | + We do this by checking if there is two numbers separated by |
391 | + space in the input. |
392 | + */ |
393 | + while (pos < end && !my_isspace(&my_charset_utf8_general_ci, *pos)) |
394 | + pos++; |
395 | + while (pos < end && !my_isdigit(&my_charset_utf8_general_ci, *pos)) |
396 | + pos++; |
397 | + if (pos == end) |
398 | + { |
399 | + if (flags & TIME_DATETIME_ONLY) |
400 | + { |
401 | + *was_cut= 1; |
402 | + return(DRIZZLE_TIMESTAMP_NONE); /* Can't be a full datetime */ |
403 | + } |
404 | + /* Date field. Set hour, minutes and seconds to 0 */ |
405 | + date[0]= date[1]= date[2]= date[3]= date[4]= 0; |
406 | + start_loop= 5; /* Start with first date part */ |
407 | + } |
408 | + } |
409 | + |
410 | + field_length= format_position[0] == 0 ? 4 : 2; |
411 | + } |
412 | + |
413 | + /* |
414 | + Only allow space in the first "part" of the datetime field and: |
415 | + - after days, part seconds |
416 | + - before and after AM/PM (handled by code later) |
417 | + |
418 | + 2003-03-03 20:00:20 AM |
419 | + 20:00:20.000000 AM 03-03-2000 |
420 | + */ |
421 | + i= max((uint32_t) format_position[0], (uint32_t) format_position[1]); |
422 | + set_if_bigger(i, (uint32_t) format_position[2]); |
423 | + allow_space= ((1 << i) | (1 << format_position[6])); |
424 | + allow_space&= (1 | 2 | 4 | 8); |
425 | + |
426 | + not_zero_date= 0; |
427 | + for (i = start_loop; |
428 | + i < MAX_DATE_PARTS-1 && str != end && |
429 | + my_isdigit(&my_charset_utf8_general_ci,*str); |
430 | + i++) |
431 | + { |
432 | + const char *start= str; |
433 | + uint32_t tmp_value= (uint32_t) (unsigned char) (*str++ - '0'); |
434 | + while (str != end && my_isdigit(&my_charset_utf8_general_ci,str[0]) && |
435 | + (!is_internal_format || --field_length)) |
436 | + { |
437 | + tmp_value=tmp_value*10 + (uint32_t) (unsigned char) (*str - '0'); |
438 | + str++; |
439 | + } |
440 | + date_len[i]= (uint32_t) (str - start); |
441 | + if (tmp_value > 999999) /* Impossible date part */ |
442 | + { |
443 | + *was_cut= 1; |
444 | + return(DRIZZLE_TIMESTAMP_NONE); |
445 | + } |
446 | + date[i]=tmp_value; |
447 | + not_zero_date|= tmp_value; |
448 | + |
449 | + /* Length of next field */ |
450 | + field_length= format_position[i+1] == 0 ? 4 : 2; |
451 | + |
452 | + if ((last_field_pos= str) == end) |
453 | + { |
454 | + i++; /* Register last found part */ |
455 | + break; |
456 | + } |
457 | + /* Allow a 'T' after day to allow CCYYMMDDT type of fields */ |
458 | + if (i == format_position[2] && *str == 'T') |
459 | + { |
460 | + str++; /* ISO8601: CCYYMMDDThhmmss */ |
461 | + continue; |
462 | + } |
463 | + if (i == format_position[5]) /* Seconds */ |
464 | + { |
465 | + if (*str == '.') /* Followed by part seconds */ |
466 | + { |
467 | + str++; |
468 | + field_length= 6; /* 6 digits */ |
469 | + } |
470 | + continue; |
471 | + } |
472 | + while (str != end && |
473 | + (my_ispunct(&my_charset_utf8_general_ci,*str) || |
474 | + my_isspace(&my_charset_utf8_general_ci,*str))) |
475 | + { |
476 | + if (my_isspace(&my_charset_utf8_general_ci,*str)) |
477 | + { |
478 | + if (!(allow_space & (1 << i))) |
479 | + { |
480 | + *was_cut= 1; |
481 | + return(DRIZZLE_TIMESTAMP_NONE); |
482 | + } |
483 | + found_space= 1; |
484 | + } |
485 | + str++; |
486 | + found_delimitier= 1; /* Should be a 'normal' date */ |
487 | + } |
488 | + /* Check if next position is AM/PM */ |
489 | + if (i == format_position[6]) /* Seconds, time for AM/PM */ |
490 | + { |
491 | + i++; /* Skip AM/PM part */ |
492 | + if (format_position[7] != 255) /* If using AM/PM */ |
493 | + { |
494 | + if (str+2 <= end && (str[1] == 'M' || str[1] == 'm')) |
495 | + { |
496 | + if (str[0] == 'p' || str[0] == 'P') |
497 | + add_hours= 12; |
498 | + else if (str[0] != 'a' || str[0] != 'A') |
499 | + continue; /* Not AM/PM */ |
500 | + str+= 2; /* Skip AM/PM */ |
501 | + /* Skip space after AM/PM */ |
502 | + while (str != end && my_isspace(&my_charset_utf8_general_ci,*str)) |
503 | + str++; |
504 | + } |
505 | + } |
506 | + } |
507 | + last_field_pos= str; |
508 | + } |
509 | + if (found_delimitier && !found_space && (flags & TIME_DATETIME_ONLY)) |
510 | + { |
511 | + *was_cut= 1; |
512 | + return(DRIZZLE_TIMESTAMP_NONE); /* Can't be a datetime */ |
513 | + } |
514 | + |
515 | + str= last_field_pos; |
516 | + |
517 | + number_of_fields= i - start_loop; |
518 | + while (i < MAX_DATE_PARTS) |
519 | + { |
520 | + date_len[i]= 0; |
521 | + date[i++]= 0; |
522 | + } |
523 | + |
524 | + if (!is_internal_format) |
525 | + { |
526 | + year_length= date_len[(uint32_t) format_position[0]]; |
527 | + if (!year_length) /* Year must be specified */ |
528 | + { |
529 | + *was_cut= 1; |
530 | + return(DRIZZLE_TIMESTAMP_NONE); |
531 | + } |
532 | + |
533 | + l_time->year= date[(uint32_t) format_position[0]]; |
534 | + l_time->month= date[(uint32_t) format_position[1]]; |
535 | + l_time->day= date[(uint32_t) format_position[2]]; |
536 | + l_time->hour= date[(uint32_t) format_position[3]]; |
537 | + l_time->minute= date[(uint32_t) format_position[4]]; |
538 | + l_time->second= date[(uint32_t) format_position[5]]; |
539 | + |
540 | + frac_pos= (uint32_t) format_position[6]; |
541 | + frac_len= date_len[frac_pos]; |
542 | + if (frac_len < 6) |
543 | + date[frac_pos]*= (uint32_t) log_10_int[6 - frac_len]; |
544 | + l_time->second_part= date[frac_pos]; |
545 | + |
546 | + if (format_position[7] != (unsigned char) 255) |
547 | + { |
548 | + if (l_time->hour > 12) |
549 | + { |
550 | + *was_cut= 1; |
551 | + goto err; |
552 | + } |
553 | + l_time->hour= l_time->hour%12 + add_hours; |
554 | + } |
555 | + } |
556 | + else |
557 | + { |
558 | + l_time->year= date[0]; |
559 | + l_time->month= date[1]; |
560 | + l_time->day= date[2]; |
561 | + l_time->hour= date[3]; |
562 | + l_time->minute= date[4]; |
563 | + l_time->second= date[5]; |
564 | + if (date_len[6] < 6) |
565 | + date[6]*= (uint32_t) log_10_int[6 - date_len[6]]; |
566 | + l_time->second_part=date[6]; |
567 | + } |
568 | + l_time->neg= 0; |
569 | + |
570 | + if (year_length == 2 && not_zero_date) |
571 | + l_time->year+= (l_time->year < YY_PART_YEAR ? 2000 : 1900); |
572 | + |
573 | + if (number_of_fields < 3 || |
574 | + l_time->year > 9999 || l_time->month > 12 || |
575 | + l_time->day > 31 || l_time->hour > 23 || |
576 | + l_time->minute > 59 || l_time->second > 59) |
577 | + { |
578 | + /* Only give warning for a zero date if there is some garbage after */ |
579 | + if (!not_zero_date) /* If zero date */ |
580 | + { |
581 | + for (; str != end ; str++) |
582 | + { |
583 | + if (!my_isspace(&my_charset_utf8_general_ci, *str)) |
584 | + { |
585 | + not_zero_date= 1; /* Give warning */ |
586 | + break; |
587 | + } |
588 | + } |
589 | + } |
590 | + *was_cut= test(not_zero_date); |
591 | + goto err; |
592 | + } |
593 | + |
594 | + if (check_date(l_time, not_zero_date != 0, flags, was_cut)) |
595 | + goto err; |
596 | + |
597 | + l_time->time_type= (number_of_fields <= 3 ? |
598 | + DRIZZLE_TIMESTAMP_DATE : DRIZZLE_TIMESTAMP_DATETIME); |
599 | + |
600 | + for (; str != end ; str++) |
601 | + { |
602 | + if (!my_isspace(&my_charset_utf8_general_ci,*str)) |
603 | + { |
604 | + *was_cut= 1; |
605 | + break; |
606 | + } |
607 | + } |
608 | + |
609 | + return(l_time->time_type= |
610 | + (number_of_fields <= 3 ? DRIZZLE_TIMESTAMP_DATE : |
611 | + DRIZZLE_TIMESTAMP_DATETIME)); |
612 | + |
613 | +err: |
614 | + memset(l_time, 0, sizeof(*l_time)); |
615 | + return(DRIZZLE_TIMESTAMP_ERROR); |
616 | +} |
617 | + |
618 | + |
619 | +/* |
620 | + Convert a time string to a DRIZZLE_TIME struct. |
621 | + |
622 | + SYNOPSIS |
623 | + str_to_time() |
624 | + str A string in full TIMESTAMP format or |
625 | + [-] DAYS [H]H:MM:SS, [H]H:MM:SS, [M]M:SS, [H]HMMSS, |
626 | + [M]MSS or [S]S |
627 | + There may be an optional [.second_part] after seconds |
628 | + length Length of str |
629 | + l_time Store result here |
630 | + warning Set DRIZZLE_TIME_WARN_TRUNCATED flag if the input string |
631 | + was cut during conversion, and/or |
632 | + DRIZZLE_TIME_WARN_OUT_OF_RANGE flag, if the value is |
633 | + out of range. |
634 | + |
635 | + NOTES |
636 | + Because of the extra days argument, this function can only |
637 | + work with times where the time arguments are in the above order. |
638 | + |
639 | + RETURN |
640 | + 0 ok |
641 | + 1 error |
642 | +*/ |
643 | + |
644 | +bool str_to_time(const char *str, uint32_t length, DRIZZLE_TIME *l_time, |
645 | + int *warning) |
646 | +{ |
647 | + uint32_t date[5]; |
648 | + uint64_t value; |
649 | + const char *end=str+length, *end_of_days; |
650 | + bool found_days,found_hours; |
651 | + uint32_t state; |
652 | + |
653 | + l_time->neg=0; |
654 | + *warning= 0; |
655 | + for (; str != end && my_isspace(&my_charset_utf8_general_ci,*str) ; str++) |
656 | + length--; |
657 | + if (str != end && *str == '-') |
658 | + { |
659 | + l_time->neg=1; |
660 | + str++; |
661 | + length--; |
662 | + } |
663 | + if (str == end) |
664 | + return 1; |
665 | + |
666 | + /* Check first if this is a full TIMESTAMP */ |
667 | + if (length >= 12) |
668 | + { /* Probably full timestamp */ |
669 | + int was_cut; |
670 | + enum enum_drizzle_timestamp_type |
671 | + res= str_to_datetime(str, length, l_time, |
672 | + (TIME_FUZZY_DATE | TIME_DATETIME_ONLY), &was_cut); |
673 | + if ((int) res >= (int) DRIZZLE_TIMESTAMP_ERROR) |
674 | + { |
675 | + if (was_cut) |
676 | + *warning|= DRIZZLE_TIME_WARN_TRUNCATED; |
677 | + return res == DRIZZLE_TIMESTAMP_ERROR; |
678 | + } |
679 | + } |
680 | + |
681 | + /* Not a timestamp. Try to get this as a DAYS_TO_SECOND string */ |
682 | + for (value=0; str != end && my_isdigit(&my_charset_utf8_general_ci,*str) ; str++) |
683 | + value=value*10L + (long) (*str - '0'); |
684 | + |
685 | + /* Skip all space after 'days' */ |
686 | + end_of_days= str; |
687 | + for (; str != end && my_isspace(&my_charset_utf8_general_ci, str[0]) ; str++) |
688 | + ; |
689 | + |
690 | + found_days=found_hours=0; |
691 | + if ((uint32_t) (end-str) > 1 && str != end_of_days && |
692 | + my_isdigit(&my_charset_utf8_general_ci, *str)) |
693 | + { /* Found days part */ |
694 | + date[0]= (uint32_t) value; |
695 | + state= 1; /* Assume next is hours */ |
696 | + found_days= 1; |
697 | + } |
698 | + else if ((end-str) > 1 && *str == time_separator && |
699 | + my_isdigit(&my_charset_utf8_general_ci, str[1])) |
700 | + { |
701 | + date[0]= 0; /* Assume we found hours */ |
702 | + date[1]= (uint32_t) value; |
703 | + state=2; |
704 | + found_hours=1; |
705 | + str++; /* skip ':' */ |
706 | + } |
707 | + else |
708 | + { |
709 | + /* String given as one number; assume HHMMSS format */ |
710 | + date[0]= 0; |
711 | + date[1]= (uint32_t) (value/10000); |
712 | + date[2]= (uint32_t) (value/100 % 100); |
713 | + date[3]= (uint32_t) (value % 100); |
714 | + state=4; |
715 | + goto fractional; |
716 | + } |
717 | + |
718 | + /* Read hours, minutes and seconds */ |
719 | + for (;;) |
720 | + { |
721 | + for (value=0; str != end && my_isdigit(&my_charset_utf8_general_ci,*str) ; str++) |
722 | + value=value*10L + (long) (*str - '0'); |
723 | + date[state++]= (uint32_t) value; |
724 | + if (state == 4 || (end-str) < 2 || *str != time_separator || |
725 | + !my_isdigit(&my_charset_utf8_general_ci,str[1])) |
726 | + break; |
727 | + str++; /* Skip time_separator (':') */ |
728 | + } |
729 | + |
730 | + if (state != 4) |
731 | + { /* Not HH:MM:SS */ |
732 | + /* Fix the date to assume that seconds was given */ |
733 | + if (!found_hours && !found_days) |
734 | + { |
735 | + internal::bmove_upp((unsigned char*) (date+4), (unsigned char*) (date+state), |
736 | + sizeof(long)*(state-1)); |
737 | + memset(date, 0, sizeof(long)*(4-state)); |
738 | + } |
739 | + else |
740 | + memset(date+state, 0, sizeof(long)*(4-state)); |
741 | + } |
742 | + |
743 | +fractional: |
744 | + /* Get fractional second part */ |
745 | + if ((end-str) >= 2 && *str == '.' && my_isdigit(&my_charset_utf8_general_ci,str[1])) |
746 | + { |
747 | + int field_length= 5; |
748 | + str++; value=(uint32_t) (unsigned char) (*str - '0'); |
749 | + while (++str != end && my_isdigit(&my_charset_utf8_general_ci, *str)) |
750 | + { |
751 | + if (field_length-- > 0) |
752 | + value= value*10 + (uint32_t) (unsigned char) (*str - '0'); |
753 | + } |
754 | + if (field_length > 0) |
755 | + value*= (long) log_10_int[field_length]; |
756 | + else if (field_length < 0) |
757 | + *warning|= DRIZZLE_TIME_WARN_TRUNCATED; |
758 | + date[4]= (uint32_t) value; |
759 | + } |
760 | + else |
761 | + date[4]=0; |
762 | + |
763 | + /* Check for exponent part: E<gigit> | E<sign><digit> */ |
764 | + /* (may occur as result of %g formatting of time value) */ |
765 | + if ((end - str) > 1 && |
766 | + (*str == 'e' || *str == 'E') && |
767 | + (my_isdigit(&my_charset_utf8_general_ci, str[1]) || |
768 | + ((str[1] == '-' || str[1] == '+') && |
769 | + (end - str) > 2 && |
770 | + my_isdigit(&my_charset_utf8_general_ci, str[2])))) |
771 | + return 1; |
772 | + |
773 | + if (internal_format_positions[7] != 255) |
774 | + { |
775 | + /* Read a possible AM/PM */ |
776 | + while (str != end && my_isspace(&my_charset_utf8_general_ci, *str)) |
777 | + str++; |
778 | + if (str+2 <= end && (str[1] == 'M' || str[1] == 'm')) |
779 | + { |
780 | + if (str[0] == 'p' || str[0] == 'P') |
781 | + { |
782 | + str+= 2; |
783 | + date[1]= date[1]%12 + 12; |
784 | + } |
785 | + else if (str[0] == 'a' || str[0] == 'A') |
786 | + str+=2; |
787 | + } |
788 | + } |
789 | + |
790 | + /* Integer overflow checks */ |
791 | + if (date[0] > UINT_MAX || date[1] > UINT_MAX || |
792 | + date[2] > UINT_MAX || date[3] > UINT_MAX || |
793 | + date[4] > UINT_MAX) |
794 | + return 1; |
795 | + |
796 | + l_time->year= 0; /* For protocol::store_time */ |
797 | + l_time->month= 0; |
798 | + l_time->day= date[0]; |
799 | + l_time->hour= date[1]; |
800 | + l_time->minute= date[2]; |
801 | + l_time->second= date[3]; |
802 | + l_time->second_part= date[4]; |
803 | + l_time->time_type= DRIZZLE_TIMESTAMP_TIME; |
804 | + |
805 | + /* Check if the value is valid and fits into DRIZZLE_TIME range */ |
806 | + if (check_time_range(l_time, warning)) |
807 | + return 1; |
808 | + |
809 | + /* Check if there is garbage at end of the DRIZZLE_TIME specification */ |
810 | + if (str != end) |
811 | + { |
812 | + do |
813 | + { |
814 | + if (!my_isspace(&my_charset_utf8_general_ci,*str)) |
815 | + { |
816 | + *warning|= DRIZZLE_TIME_WARN_TRUNCATED; |
817 | + break; |
818 | + } |
819 | + } while (++str != end); |
820 | + } |
821 | + return 0; |
822 | +} |
823 | + |
824 | + |
825 | +/* |
826 | + Check 'time' value to lie in the DRIZZLE_TIME range |
827 | + |
828 | + SYNOPSIS: |
829 | + check_time_range() |
830 | + time pointer to DRIZZLE_TIME value |
831 | + warning set DRIZZLE_TIME_WARN_OUT_OF_RANGE flag if the value is out of range |
832 | + |
833 | + DESCRIPTION |
834 | + If the time value lies outside of the range [-838:59:59, 838:59:59], |
835 | + set it to the closest endpoint of the range and set |
836 | + DRIZZLE_TIME_WARN_OUT_OF_RANGE flag in the 'warning' variable. |
837 | + |
838 | + RETURN |
839 | + 0 time value is valid, but was possibly truncated |
840 | + 1 time value is invalid |
841 | +*/ |
842 | + |
843 | +static int check_time_range(DRIZZLE_TIME *my_time, int *warning) |
844 | +{ |
845 | + int64_t hour; |
846 | + |
847 | + if (my_time->minute >= 60 || my_time->second >= 60) |
848 | + return 1; |
849 | + |
850 | + hour= my_time->hour + (24*my_time->day); |
851 | + if (hour <= TIME_MAX_HOUR && |
852 | + (hour != TIME_MAX_HOUR || my_time->minute != TIME_MAX_MINUTE || |
853 | + my_time->second != TIME_MAX_SECOND || !my_time->second_part)) |
854 | + return 0; |
855 | + |
856 | + my_time->day= 0; |
857 | + my_time->hour= TIME_MAX_HOUR; |
858 | + my_time->minute= TIME_MAX_MINUTE; |
859 | + my_time->second= TIME_MAX_SECOND; |
860 | + my_time->second_part= 0; |
861 | + *warning|= DRIZZLE_TIME_WARN_OUT_OF_RANGE; |
862 | + return 0; |
863 | +} |
864 | + |
865 | + |
866 | +/* |
867 | + Prepare offset of system time zone from UTC for my_system_gmt_sec() func. |
868 | + |
869 | + SYNOPSIS |
870 | + init_time() |
871 | +*/ |
872 | +void init_time(void) |
873 | +{ |
874 | + time_t seconds; |
875 | + struct tm *l_time,tm_tmp; |
876 | + DRIZZLE_TIME my_time; |
877 | + bool not_used; |
878 | + |
879 | + seconds= (time_t) time((time_t*) 0); |
880 | + localtime_r(&seconds,&tm_tmp); |
881 | + l_time= &tm_tmp; |
882 | + my_time_zone= 3600; /* Comp. for -3600 in my_gmt_sec */ |
883 | + my_time.year= (uint32_t) l_time->tm_year+1900; |
884 | + my_time.month= (uint32_t) l_time->tm_mon+1; |
885 | + my_time.day= (uint32_t) l_time->tm_mday; |
886 | + my_time.hour= (uint32_t) l_time->tm_hour; |
887 | + my_time.minute= (uint32_t) l_time->tm_min; |
888 | + my_time.second= (uint32_t) l_time->tm_sec; |
889 | + my_time.time_type= DRIZZLE_TIMESTAMP_NONE; |
890 | + my_time.second_part= 0; |
891 | + my_time.neg= false; |
892 | + my_system_gmt_sec(&my_time, &my_time_zone, ¬_used); /* Init my_time_zone */ |
893 | +} |
894 | + |
895 | + |
896 | +/* |
897 | + Handle 2 digit year conversions |
898 | + |
899 | + SYNOPSIS |
900 | + year_2000_handling() |
901 | + year 2 digit year |
902 | + |
903 | + RETURN |
904 | + Year between 1970-2069 |
905 | +*/ |
906 | + |
907 | +uint32_t year_2000_handling(uint32_t year) |
908 | +{ |
909 | + if ((year=year+1900) < 1900+YY_PART_YEAR) |
910 | + year+=100; |
911 | + return year; |
912 | +} |
913 | + |
914 | + |
915 | +/* |
916 | + Calculate nr of day since year 0 in new date-system (from 1615) |
917 | + |
918 | + SYNOPSIS |
919 | + calc_daynr() |
920 | + year Year (exact 4 digit year, no year conversions) |
921 | + month Month |
922 | + day Day |
923 | + |
924 | + NOTES: 0000-00-00 is a valid date, and will return 0 |
925 | + |
926 | + RETURN |
927 | + Days since 0000-00-00 |
928 | +*/ |
929 | + |
930 | +long calc_daynr(uint32_t year,uint32_t month,uint32_t day) |
931 | +{ |
932 | + long delsum; |
933 | + int temp; |
934 | + |
935 | + if (year == 0 && month == 0 && day == 0) |
936 | + return(0); /* Skip errors */ |
937 | + delsum= (long) (365L * year+ 31*(month-1) +day); |
938 | + if (month <= 2) |
939 | + year--; |
940 | + else |
941 | + delsum-= (long) (month*4+23)/10; |
942 | + temp=(int) ((year/100+1)*3)/4; |
943 | + return(delsum+(int) year/4-temp); |
944 | +} /* calc_daynr */ |
945 | + |
946 | + |
947 | +/* |
948 | + Convert time in DRIZZLE_TIME representation in system time zone to its |
949 | + time_t form (number of seconds in UTC since begginning of Unix Epoch). |
950 | + |
951 | + SYNOPSIS |
952 | + my_system_gmt_sec() |
953 | + t - time value to be converted |
954 | + my_timezone - pointer to long where offset of system time zone |
955 | + from UTC will be stored for caching |
956 | + in_dst_time_gap - set to true if time falls into spring time-gap |
957 | + |
958 | + NOTES |
959 | + The idea is to cache the time zone offset from UTC (including daylight |
960 | + saving time) for the next call to make things faster. But currently we |
961 | + just calculate this offset during startup (by calling init_time() |
962 | + function) and use it all the time. |
963 | + Time value provided should be legal time value (e.g. '2003-01-01 25:00:00' |
964 | + is not allowed). |
965 | + |
966 | + RETURN VALUE |
967 | + Time in UTC seconds since Unix Epoch representation. |
968 | +*/ |
969 | +time_t |
970 | +my_system_gmt_sec(const DRIZZLE_TIME *t_src, long *my_timezone, |
971 | + bool *in_dst_time_gap) |
972 | +{ |
973 | + uint32_t loop; |
974 | + time_t tmp= 0; |
975 | + int shift= 0; |
976 | + DRIZZLE_TIME tmp_time; |
977 | + DRIZZLE_TIME *t= &tmp_time; |
978 | + struct tm *l_time,tm_tmp; |
979 | + long diff, current_timezone; |
980 | + |
981 | + /* |
982 | + Use temp variable to avoid trashing input data, which could happen in |
983 | + case of shift required for boundary dates processing. |
984 | + */ |
985 | + memcpy(&tmp_time, t_src, sizeof(DRIZZLE_TIME)); |
986 | + |
987 | + if (!validate_timestamp_range(t)) |
988 | + return 0; |
989 | + |
990 | + /* |
991 | + Calculate the gmt time based on current time and timezone |
992 | + The -1 on the end is to ensure that if have a date that exists twice |
993 | + (like 2002-10-27 02:00:0 MET), we will find the initial date. |
994 | + |
995 | + By doing -3600 we will have to call localtime_r() several times, but |
996 | + I couldn't come up with a better way to get a repeatable result :( |
997 | + |
998 | + We can't use mktime() as it's buggy on many platforms and not thread safe. |
999 | + |
1000 | + Note: this code assumes that our time_t estimation is not too far away |
1001 | + from real value (we assume that localtime_r(tmp) will return something |
1002 | + within 24 hrs from t) which is probably true for all current time zones. |
1003 | + |
1004 | + Note2: For the dates, which have time_t representation close to |
1005 | + MAX_INT32 (efficient time_t limit for supported platforms), we should |
1006 | + do a small trick to avoid overflow. That is, convert the date, which is |
1007 | + two days earlier, and then add these days to the final value. |
1008 | + |
1009 | + The same trick is done for the values close to 0 in time_t |
1010 | + representation for platfroms with unsigned time_t (QNX). |
1011 | + |
1012 | + To be more verbose, here is a sample (extracted from the code below): |
1013 | + (calc_daynr(2038, 1, 19) - (long) days_at_timestart)*86400L + 4*3600L |
1014 | + would return -2147480896 because of the long type overflow. In result |
1015 | + we would get 1901 year in localtime_r(), which is an obvious error. |
1016 | + |
1017 | + Alike problem raises with the dates close to Epoch. E.g. |
1018 | + (calc_daynr(1969, 12, 31) - (long) days_at_timestart)*86400L + 23*3600L |
1019 | + will give -3600. |
1020 | + |
1021 | + On some platforms, (E.g. on QNX) time_t is unsigned and localtime(-3600) |
1022 | + wil give us a date around 2106 year. Which is no good. |
1023 | + |
1024 | + Theoreticaly, there could be problems with the latter conversion: |
1025 | + there are at least two timezones, which had time switches near 1 Jan |
1026 | + of 1970 (because of political reasons). These are America/Hermosillo and |
1027 | + America/Mazatlan time zones. They changed their offset on |
1028 | + 1970-01-01 08:00:00 UTC from UTC-8 to UTC-7. For these zones |
1029 | + the code below will give incorrect results for dates close to |
1030 | + 1970-01-01, in the case OS takes into account these historical switches. |
1031 | + Luckily, it seems that we support only one platform with unsigned |
1032 | + time_t. It's QNX. And QNX does not support historical timezone data at all. |
1033 | + E.g. there are no /usr/share/zoneinfo/ files or any other mean to supply |
1034 | + historical information for localtime_r() etc. That is, the problem is not |
1035 | + relevant to QNX. |
1036 | + |
1037 | + We are safe with shifts close to MAX_INT32, as there are no known |
1038 | + time switches on Jan 2038 yet :) |
1039 | + */ |
1040 | + if ((t->year == TIMESTAMP_MAX_YEAR) && (t->month == 1) && (t->day > 4)) |
1041 | + { |
1042 | + /* |
1043 | + Below we will pass (uint32_t) (t->day - shift) to calc_daynr. |
1044 | + As we don't want to get an overflow here, we will shift |
1045 | + only safe dates. That's why we have (t->day > 4) above. |
1046 | + */ |
1047 | + t->day-= 2; |
1048 | + shift= 2; |
1049 | + } |
1050 | +#ifdef TIME_T_UNSIGNED |
1051 | + else |
1052 | + { |
1053 | + /* |
1054 | + We can get 0 in time_t representaion only on 1969, 31 of Dec or on |
1055 | + 1970, 1 of Jan. For both dates we use shift, which is added |
1056 | + to t->day in order to step out a bit from the border. |
1057 | + This is required for platforms, where time_t is unsigned. |
1058 | + As far as I know, among the platforms we support it's only QNX. |
1059 | + Note: the order of below if-statements is significant. |
1060 | + */ |
1061 | + |
1062 | + if ((t->year == TIMESTAMP_MIN_YEAR + 1) && (t->month == 1) |
1063 | + && (t->day <= 10)) |
1064 | + { |
1065 | + t->day+= 2; |
1066 | + shift= -2; |
1067 | + } |
1068 | + |
1069 | + if ((t->year == TIMESTAMP_MIN_YEAR) && (t->month == 12) |
1070 | + && (t->day == 31)) |
1071 | + { |
1072 | + t->year++; |
1073 | + t->month= 1; |
1074 | + t->day= 2; |
1075 | + shift= -2; |
1076 | + } |
1077 | + } |
1078 | +#endif |
1079 | + |
1080 | + tmp= (time_t) (((calc_daynr((uint32_t) t->year, (uint32_t) t->month, (uint32_t) t->day) - |
1081 | + (long) days_at_timestart)*86400L + (long) t->hour*3600L + |
1082 | + (long) (t->minute*60 + t->second)) + (time_t) my_time_zone - |
1083 | + 3600); |
1084 | + |
1085 | + current_timezone= my_time_zone; |
1086 | + localtime_r(&tmp,&tm_tmp); |
1087 | + l_time=&tm_tmp; |
1088 | + for (loop=0; |
1089 | + loop < 2 && |
1090 | + (t->hour != (uint32_t) l_time->tm_hour || |
1091 | + t->minute != (uint32_t) l_time->tm_min || |
1092 | + t->second != (uint32_t) l_time->tm_sec); |
1093 | + loop++) |
1094 | + { /* One check should be enough ? */ |
1095 | + /* Get difference in days */ |
1096 | + int days= t->day - l_time->tm_mday; |
1097 | + if (days < -1) |
1098 | + days= 1; /* Month has wrapped */ |
1099 | + else if (days > 1) |
1100 | + days= -1; |
1101 | + diff=(3600L*(long) (days*24+((int) t->hour - (int) l_time->tm_hour)) + |
1102 | + (long) (60*((int) t->minute - (int) l_time->tm_min)) + |
1103 | + (long) ((int) t->second - (int) l_time->tm_sec)); |
1104 | + current_timezone+= diff+3600; /* Compensate for -3600 above */ |
1105 | + tmp+= (time_t) diff; |
1106 | + localtime_r(&tmp,&tm_tmp); |
1107 | + l_time=&tm_tmp; |
1108 | + } |
1109 | + /* |
1110 | + Fix that if we are in the non existing daylight saving time hour |
1111 | + we move the start of the next real hour. |
1112 | + |
1113 | + This code doesn't handle such exotical thing as time-gaps whose length |
1114 | + is more than one hour or non-integer (latter can theoretically happen |
1115 | + if one of seconds will be removed due leap correction, or because of |
1116 | + general time correction like it happened for Africa/Monrovia time zone |
1117 | + in year 1972). |
1118 | + */ |
1119 | + if (loop == 2 && t->hour != (uint32_t) l_time->tm_hour) |
1120 | + { |
1121 | + int days= t->day - l_time->tm_mday; |
1122 | + if (days < -1) |
1123 | + days=1; /* Month has wrapped */ |
1124 | + else if (days > 1) |
1125 | + days= -1; |
1126 | + diff=(3600L*(long) (days*24+((int) t->hour - (int) l_time->tm_hour))+ |
1127 | + (long) (60*((int) t->minute - (int) l_time->tm_min)) + |
1128 | + (long) ((int) t->second - (int) l_time->tm_sec)); |
1129 | + if (diff == 3600) |
1130 | + tmp+=3600 - t->minute*60 - t->second; /* Move to next hour */ |
1131 | + else if (diff == -3600) |
1132 | + tmp-=t->minute*60 + t->second; /* Move to previous hour */ |
1133 | + |
1134 | + *in_dst_time_gap= true; |
1135 | + } |
1136 | + *my_timezone= current_timezone; |
1137 | + |
1138 | + |
1139 | + /* shift back, if we were dealing with boundary dates */ |
1140 | + tmp+= shift*86400L; |
1141 | + |
1142 | + /* |
1143 | + This is possible for dates, which slightly exceed boundaries. |
1144 | + Conversion will pass ok for them, but we don't allow them. |
1145 | + First check will pass for platforms with signed time_t. |
1146 | + instruction above (tmp+= shift*86400L) could exceed |
1147 | + MAX_INT32 (== TIMESTAMP_MAX_VALUE) and overflow will happen. |
1148 | + So, tmp < TIMESTAMP_MIN_VALUE will be triggered. On platfroms |
1149 | + with unsigned time_t tmp+= shift*86400L might result in a number, |
1150 | + larger then TIMESTAMP_MAX_VALUE, so another check will work. |
1151 | + */ |
1152 | + if ((tmp < TIMESTAMP_MIN_VALUE) || (tmp > TIMESTAMP_MAX_VALUE)) |
1153 | + tmp= 0; |
1154 | + |
1155 | + return (time_t) tmp; |
1156 | +} /* my_system_gmt_sec */ |
1157 | + |
1158 | + |
1159 | +/* Set DRIZZLE_TIME structure to 0000-00-00 00:00:00.000000 */ |
1160 | + |
1161 | +void set_zero_time(DRIZZLE_TIME *tm, enum enum_drizzle_timestamp_type time_type) |
1162 | +{ |
1163 | + memset(tm, 0, sizeof(*tm)); |
1164 | + tm->time_type= time_type; |
1165 | +} |
1166 | + |
1167 | + |
1168 | +/* |
1169 | + Functions to convert time/date/datetime value to a string, |
1170 | + using default format. |
1171 | + This functions don't check that given DRIZZLE_TIME structure members are |
1172 | + in valid range. If they are not, return value won't reflect any |
1173 | + valid date either. Additionally, make_time doesn't take into |
1174 | + account time->day member: it's assumed that days have been converted |
1175 | + to hours already. |
1176 | + |
1177 | + RETURN |
1178 | + number of characters written to 'to' |
1179 | +*/ |
1180 | + |
1181 | +static int my_time_to_str(const DRIZZLE_TIME *l_time, char *to) |
1182 | +{ |
1183 | + uint32_t extra_hours= 0; |
1184 | + return sprintf(to, "%s%02u:%02u:%02u", |
1185 | + (l_time->neg ? "-" : ""), |
1186 | + extra_hours+ l_time->hour, |
1187 | + l_time->minute, |
1188 | + l_time->second); |
1189 | +} |
1190 | + |
1191 | +int my_date_to_str(const DRIZZLE_TIME *l_time, char *to) |
1192 | +{ |
1193 | + return sprintf(to, "%04u-%02u-%02u", |
1194 | + l_time->year, |
1195 | + l_time->month, |
1196 | + l_time->day); |
1197 | +} |
1198 | + |
1199 | +int my_datetime_to_str(const DRIZZLE_TIME *l_time, char *to) |
1200 | +{ |
1201 | + return sprintf(to, "%04u-%02u-%02u %02u:%02u:%02u", |
1202 | + l_time->year, |
1203 | + l_time->month, |
1204 | + l_time->day, |
1205 | + l_time->hour, |
1206 | + l_time->minute, |
1207 | + l_time->second); |
1208 | +} |
1209 | + |
1210 | + |
1211 | +/* |
1212 | + Convert struct DATE/TIME/DATETIME value to string using built-in |
1213 | + MySQL time conversion formats. |
1214 | + |
1215 | + SYNOPSIS |
1216 | + my_TIME_to_string() |
1217 | + |
1218 | + NOTE |
1219 | + The string must have at least MAX_DATE_STRING_REP_LENGTH bytes reserved. |
1220 | +*/ |
1221 | + |
1222 | +int my_TIME_to_str(const DRIZZLE_TIME *l_time, char *to) |
1223 | +{ |
1224 | + switch (l_time->time_type) { |
1225 | + case DRIZZLE_TIMESTAMP_DATETIME: |
1226 | + return my_datetime_to_str(l_time, to); |
1227 | + case DRIZZLE_TIMESTAMP_DATE: |
1228 | + return my_date_to_str(l_time, to); |
1229 | + case DRIZZLE_TIMESTAMP_TIME: |
1230 | + return my_time_to_str(l_time, to); |
1231 | + case DRIZZLE_TIMESTAMP_NONE: |
1232 | + case DRIZZLE_TIMESTAMP_ERROR: |
1233 | + to[0]='\0'; |
1234 | + return 0; |
1235 | + default: |
1236 | + assert(0); |
1237 | + return 0; |
1238 | + } |
1239 | +} |
1240 | + |
1241 | + |
1242 | +/* |
1243 | + Convert datetime value specified as number to broken-down TIME |
1244 | + representation and form value of DATETIME type as side-effect. |
1245 | + |
1246 | + SYNOPSIS |
1247 | + number_to_datetime() |
1248 | + nr - datetime value as number |
1249 | + time_res - pointer for structure for broken-down representation |
1250 | + flags - flags to use in validating date, as in str_to_datetime() |
1251 | + was_cut 0 Value ok |
1252 | + 1 If value was cut during conversion |
1253 | + 2 check_date(date,flags) considers date invalid |
1254 | + |
1255 | + DESCRIPTION |
1256 | + Convert a datetime value of formats YYMMDD, YYYYMMDD, YYMMDDHHMSS, |
1257 | + YYYYMMDDHHMMSS to broken-down DRIZZLE_TIME representation. Return value in |
1258 | + YYYYMMDDHHMMSS format as side-effect. |
1259 | + |
1260 | + This function also checks if datetime value fits in DATETIME range. |
1261 | + |
1262 | + RETURN VALUE |
1263 | + -1 Timestamp with wrong values |
1264 | + anything else DATETIME as integer in YYYYMMDDHHMMSS format |
1265 | + Datetime value in YYYYMMDDHHMMSS format. |
1266 | +*/ |
1267 | + |
1268 | +int64_t number_to_datetime(int64_t nr, DRIZZLE_TIME *time_res, |
1269 | + uint32_t flags, int *was_cut) |
1270 | +{ |
1271 | + long part1,part2; |
1272 | + |
1273 | + *was_cut= 0; |
1274 | + memset(time_res, 0, sizeof(*time_res)); |
1275 | + time_res->time_type=DRIZZLE_TIMESTAMP_DATE; |
1276 | + |
1277 | + if (nr == 0LL || nr >= 10000101000000LL) |
1278 | + { |
1279 | + time_res->time_type=DRIZZLE_TIMESTAMP_DATETIME; |
1280 | + goto ok; |
1281 | + } |
1282 | + if (nr < 101) |
1283 | + goto err; |
1284 | + if (nr <= (YY_PART_YEAR-1)*10000L+1231L) |
1285 | + { |
1286 | + nr= (nr+20000000L)*1000000L; /* YYMMDD, year: 2000-2069 */ |
1287 | + goto ok; |
1288 | + } |
1289 | + if (nr < (YY_PART_YEAR)*10000L+101L) |
1290 | + goto err; |
1291 | + if (nr <= 991231L) |
1292 | + { |
1293 | + nr= (nr+19000000L)*1000000L; /* YYMMDD, year: 1970-1999 */ |
1294 | + goto ok; |
1295 | + } |
1296 | + if (nr < 10000101L) |
1297 | + goto err; |
1298 | + if (nr <= 99991231L) |
1299 | + { |
1300 | + nr= nr*1000000L; |
1301 | + goto ok; |
1302 | + } |
1303 | + if (nr < 101000000L) |
1304 | + goto err; |
1305 | + |
1306 | + time_res->time_type=DRIZZLE_TIMESTAMP_DATETIME; |
1307 | + |
1308 | + if (nr <= (YY_PART_YEAR-1) * 10000000000LL + 1231235959LL) |
1309 | + { |
1310 | + nr= nr + 20000000000000LL; /* YYMMDDHHMMSS, 2000-2069 */ |
1311 | + goto ok; |
1312 | + } |
1313 | + if (nr < YY_PART_YEAR * 10000000000LL + 101000000LL) |
1314 | + goto err; |
1315 | + if (nr <= 991231235959LL) |
1316 | + nr= nr + 19000000000000LL; /* YYMMDDHHMMSS, 1970-1999 */ |
1317 | + |
1318 | + ok: |
1319 | + part1=(long) (nr / 1000000LL); |
1320 | + part2=(long) (nr - (int64_t) part1 * 1000000LL); |
1321 | + time_res->year= (int) (part1/10000L); part1%=10000L; |
1322 | + time_res->month= (int) part1 / 100; |
1323 | + time_res->day= (int) part1 % 100; |
1324 | + time_res->hour= (int) (part2/10000L); part2%=10000L; |
1325 | + time_res->minute=(int) part2 / 100; |
1326 | + time_res->second=(int) part2 % 100; |
1327 | + |
1328 | + if (time_res->year <= 9999 && time_res->month <= 12 && |
1329 | + time_res->day <= 31 && time_res->hour <= 23 && |
1330 | + time_res->minute <= 59 && time_res->second <= 59 && |
1331 | + !check_date(time_res, (nr != 0), flags, was_cut)) |
1332 | + return nr; |
1333 | + |
1334 | + /* Don't want to have was_cut get set if NO_ZERO_DATE was violated. */ |
1335 | + if (!nr && (flags & TIME_NO_ZERO_DATE)) |
1336 | + return -1LL; |
1337 | + |
1338 | + err: |
1339 | + *was_cut= 1; |
1340 | + return -1LL; |
1341 | +} |
1342 | + |
1343 | + |
1344 | +/* Convert time value to integer in YYYYMMDDHHMMSS format */ |
1345 | + |
1346 | +uint64_t TIME_to_uint64_t_datetime(const DRIZZLE_TIME *my_time) |
1347 | +{ |
1348 | + return ((uint64_t) (my_time->year * 10000UL + |
1349 | + my_time->month * 100UL + |
1350 | + my_time->day) * 1000000ULL + |
1351 | + (uint64_t) (my_time->hour * 10000UL + |
1352 | + my_time->minute * 100UL + |
1353 | + my_time->second)); |
1354 | +} |
1355 | + |
1356 | + |
1357 | +/* Convert DRIZZLE_TIME value to integer in YYYYMMDD format */ |
1358 | + |
1359 | +static uint64_t TIME_to_uint64_t_date(const DRIZZLE_TIME *my_time) |
1360 | +{ |
1361 | + return (uint64_t) (my_time->year * 10000UL + my_time->month * 100UL + |
1362 | + my_time->day); |
1363 | +} |
1364 | + |
1365 | + |
1366 | +/* |
1367 | + Convert DRIZZLE_TIME value to integer in HHMMSS format. |
1368 | + This function doesn't take into account time->day member: |
1369 | + it's assumed that days have been converted to hours already. |
1370 | +*/ |
1371 | + |
1372 | +static uint64_t TIME_to_uint64_t_time(const DRIZZLE_TIME *my_time) |
1373 | +{ |
1374 | + return (uint64_t) (my_time->hour * 10000UL + |
1375 | + my_time->minute * 100UL + |
1376 | + my_time->second); |
1377 | +} |
1378 | + |
1379 | + |
1380 | +/* |
1381 | + Convert struct DRIZZLE_TIME (date and time split into year/month/day/hour/... |
1382 | + to a number in format YYYYMMDDHHMMSS (DATETIME), |
1383 | + YYYYMMDD (DATE) or HHMMSS (TIME). |
1384 | + |
1385 | + SYNOPSIS |
1386 | + TIME_to_uint64_t() |
1387 | + |
1388 | + DESCRIPTION |
1389 | + The function is used when we need to convert value of time item |
1390 | + to a number if it's used in numeric context, i. e.: |
1391 | + SELECT NOW()+1, CURDATE()+0, CURTIMIE()+0; |
1392 | + SELECT ?+1; |
1393 | + |
1394 | + NOTE |
1395 | + This function doesn't check that given DRIZZLE_TIME structure members are |
1396 | + in valid range. If they are not, return value won't reflect any |
1397 | + valid date either. |
1398 | +*/ |
1399 | + |
1400 | +uint64_t TIME_to_uint64_t(const DRIZZLE_TIME *my_time) |
1401 | +{ |
1402 | + switch (my_time->time_type) { |
1403 | + case DRIZZLE_TIMESTAMP_DATETIME: |
1404 | + return TIME_to_uint64_t_datetime(my_time); |
1405 | + case DRIZZLE_TIMESTAMP_DATE: |
1406 | + return TIME_to_uint64_t_date(my_time); |
1407 | + case DRIZZLE_TIMESTAMP_TIME: |
1408 | + return TIME_to_uint64_t_time(my_time); |
1409 | + case DRIZZLE_TIMESTAMP_NONE: |
1410 | + case DRIZZLE_TIMESTAMP_ERROR: |
1411 | + return 0ULL; |
1412 | + default: |
1413 | + assert(0); |
1414 | + } |
1415 | + return 0; |
1416 | +} |
1417 | + |
1418 | +} /* namespace drizzled */ |
1419 | |
1420 | === added file 'drizzled/drizzle_time.h' |
1421 | --- drizzled/drizzle_time.h 1970-01-01 00:00:00 +0000 |
1422 | +++ drizzled/drizzle_time.h 2010-04-02 06:48:30 +0000 |
1423 | @@ -0,0 +1,194 @@ |
1424 | +/* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*- |
1425 | + * vim:expandtab:shiftwidth=2:tabstop=2:smarttab: |
1426 | + * |
1427 | + * Copyright (C) 2008 MySQL |
1428 | + * |
1429 | + * This program is free software; you can redistribute it and/or modify |
1430 | + * it under the terms of the GNU General Public License as published by |
1431 | + * the Free Software Foundation; either version 2 of the License, or |
1432 | + * (at your option) any later version. |
1433 | + * |
1434 | + * This program is distributed in the hope that it will be useful, |
1435 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1436 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1437 | + * GNU General Public License for more details. |
1438 | + * |
1439 | + * You should have received a copy of the GNU General Public License |
1440 | + * along with this program; if not, write to the Free Software |
1441 | + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
1442 | + */ |
1443 | + |
1444 | +#ifndef DRIZZLED_DRIZZLE_TIME_H |
1445 | +#define DRIZZLED_DRIZZLE_TIME_H |
1446 | + |
1447 | +#if TIME_WITH_SYS_TIME |
1448 | +# include <sys/time.h> |
1449 | +# include <time.h> |
1450 | +#else |
1451 | +# if HAVE_SYS_TIME_H |
1452 | +# include <sys/time.h> |
1453 | +# else |
1454 | +# include <time.h> |
1455 | +# endif |
1456 | +#endif |
1457 | + |
1458 | +namespace drizzled |
1459 | +{ |
1460 | + |
1461 | +extern uint64_t log_10_int[20]; |
1462 | +extern unsigned char days_in_month[]; |
1463 | + |
1464 | +/* Time handling defaults */ |
1465 | +#define TIMESTAMP_MAX_YEAR 2038 |
1466 | +#define TIMESTAMP_MIN_YEAR (1900 + YY_PART_YEAR - 1) |
1467 | +#define TIMESTAMP_MAX_VALUE INT32_MAX |
1468 | +#define TIMESTAMP_MIN_VALUE 1 |
1469 | + |
1470 | +/* two-digit years < this are 20..; >= this are 19.. */ |
1471 | +#define YY_PART_YEAR 70 |
1472 | + |
1473 | +/* Flags to str_to_datetime */ |
1474 | +#define TIME_FUZZY_DATE 1 |
1475 | +#define TIME_DATETIME_ONLY 2 |
1476 | +/* Must be same as MODE_NO_ZERO_IN_DATE */ |
1477 | +#define TIME_NO_ZERO_IN_DATE (65536L*2*2*2*2*2*2*2) |
1478 | +/* Must be same as MODE_NO_ZERO_DATE */ |
1479 | +#define TIME_NO_ZERO_DATE (TIME_NO_ZERO_IN_DATE*2) |
1480 | +#define TIME_INVALID_DATES (TIME_NO_ZERO_DATE*2) |
1481 | + |
1482 | +#define DRIZZLE_TIME_WARN_TRUNCATED 1 |
1483 | +#define DRIZZLE_TIME_WARN_OUT_OF_RANGE 2 |
1484 | + |
1485 | +/* Limits for the TIME data type */ |
1486 | +#define TIME_MAX_HOUR 838 |
1487 | +#define TIME_MAX_MINUTE 59 |
1488 | +#define TIME_MAX_SECOND 59 |
1489 | +#define TIME_MAX_VALUE (TIME_MAX_HOUR*10000 + TIME_MAX_MINUTE*100 + \ |
1490 | + TIME_MAX_SECOND) |
1491 | +#define TIME_MAX_VALUE_SECONDS (TIME_MAX_HOUR * 3600L + \ |
1492 | + TIME_MAX_MINUTE * 60L + TIME_MAX_SECOND) |
1493 | + |
1494 | +enum enum_drizzle_timestamp_type |
1495 | +{ |
1496 | + DRIZZLE_TIMESTAMP_NONE= -2, DRIZZLE_TIMESTAMP_ERROR= -1, |
1497 | + DRIZZLE_TIMESTAMP_DATE= 0, DRIZZLE_TIMESTAMP_DATETIME= 1, DRIZZLE_TIMESTAMP_TIME= 2 |
1498 | +}; |
1499 | + |
1500 | + |
1501 | +/* |
1502 | + Structure which is used to represent datetime values inside Drizzle. |
1503 | + |
1504 | + We assume that values in this structure are normalized, i.e. year <= 9999, |
1505 | + month <= 12, day <= 31, hour <= 23, hour <= 59, hour <= 59. Many functions |
1506 | + in server such as my_system_gmt_sec() or make_time() family of functions |
1507 | + rely on this (actually now usage of make_*() family relies on a bit weaker |
1508 | + restriction). Also functions that produce DRIZZLE_TIME as result ensure this. |
1509 | + There is one exception to this rule though if this structure holds time |
1510 | + value (time_type == DRIZZLE_TIMESTAMP_TIME) days and hour member can hold |
1511 | + bigger values. |
1512 | +*/ |
1513 | +typedef struct st_drizzle_time |
1514 | +{ |
1515 | + unsigned int year, month, day, hour, minute, second; |
1516 | + unsigned long second_part; |
1517 | + bool neg; |
1518 | + enum enum_drizzle_timestamp_type time_type; |
1519 | +} DRIZZLE_TIME; |
1520 | + |
1521 | + |
1522 | +bool check_date(const DRIZZLE_TIME *ltime, bool not_zero_date, |
1523 | + uint32_t flags, int *was_cut); |
1524 | +enum enum_drizzle_timestamp_type |
1525 | +str_to_datetime(const char *str, uint32_t length, DRIZZLE_TIME *l_time, |
1526 | + uint32_t flags, int *was_cut); |
1527 | +int64_t number_to_datetime(int64_t nr, DRIZZLE_TIME *time_res, |
1528 | + uint32_t flags, int *was_cut); |
1529 | +uint64_t TIME_to_uint64_t_datetime(const DRIZZLE_TIME *); |
1530 | +uint64_t TIME_to_uint64_t(const DRIZZLE_TIME *); |
1531 | + |
1532 | + |
1533 | +bool str_to_time(const char *str,uint32_t length, DRIZZLE_TIME *l_time, |
1534 | + int *warning); |
1535 | + |
1536 | +long calc_daynr(uint32_t year,uint32_t month,uint32_t day); |
1537 | +uint32_t calc_days_in_year(uint32_t year); |
1538 | +uint32_t year_2000_handling(uint32_t year); |
1539 | + |
1540 | +void init_time(void); |
1541 | + |
1542 | + |
1543 | +/* |
1544 | + Function to check sanity of a TIMESTAMP value |
1545 | + |
1546 | + DESCRIPTION |
1547 | + Check if a given DRIZZLE_TIME value fits in TIMESTAMP range. |
1548 | + This function doesn't make precise check, but rather a rough |
1549 | + estimate. |
1550 | + |
1551 | + RETURN VALUES |
1552 | + false The value seems sane |
1553 | + true The DRIZZLE_TIME value is definitely out of range |
1554 | +*/ |
1555 | + |
1556 | +static inline bool validate_timestamp_range(const DRIZZLE_TIME *t) |
1557 | +{ |
1558 | + if ((t->year > TIMESTAMP_MAX_YEAR || t->year < TIMESTAMP_MIN_YEAR) || |
1559 | + (t->year == TIMESTAMP_MAX_YEAR && (t->month > 1 || t->day > 19)) || |
1560 | + (t->year == TIMESTAMP_MIN_YEAR && (t->month < 12 || t->day < 31))) |
1561 | + return false; |
1562 | + |
1563 | + return true; |
1564 | +} |
1565 | + |
1566 | +time_t |
1567 | +my_system_gmt_sec(const DRIZZLE_TIME *t, long *my_timezone, |
1568 | + bool *in_dst_time_gap); |
1569 | + |
1570 | +void set_zero_time(DRIZZLE_TIME *tm, enum enum_drizzle_timestamp_type time_type); |
1571 | + |
1572 | +/* |
1573 | + Required buffer length for my_time_to_str, my_date_to_str, |
1574 | + my_datetime_to_str and TIME_to_string functions. Note, that the |
1575 | + caller is still responsible to check that given TIME structure |
1576 | + has values in valid ranges, otherwise size of the buffer could |
1577 | + be not enough. We also rely on the fact that even wrong values |
1578 | + sent using binary protocol fit in this buffer. |
1579 | +*/ |
1580 | +#define MAX_DATE_STRING_REP_LENGTH 30 |
1581 | + |
1582 | +int my_date_to_str(const DRIZZLE_TIME *l_time, char *to); |
1583 | +int my_datetime_to_str(const DRIZZLE_TIME *l_time, char *to); |
1584 | +int my_TIME_to_str(const DRIZZLE_TIME *l_time, char *to); |
1585 | + |
1586 | +/* |
1587 | + Available interval types used in any statement. |
1588 | + |
1589 | + 'interval_type' must be sorted so that simple intervals comes first, |
1590 | + ie year, quarter, month, week, day, hour, etc. The order based on |
1591 | + interval size is also important and the intervals should be kept in a |
1592 | + large to smaller order. (get_interval_value() depends on this) |
1593 | + |
1594 | + Note: If you change the order of elements in this enum you should fix |
1595 | + order of elements in 'interval_type_to_name' and 'interval_names' |
1596 | + arrays |
1597 | + |
1598 | + See also interval_type_to_name, get_interval_value, interval_names |
1599 | +*/ |
1600 | + |
1601 | +enum interval_type |
1602 | +{ |
1603 | + INTERVAL_YEAR, INTERVAL_QUARTER, INTERVAL_MONTH, INTERVAL_WEEK, INTERVAL_DAY, |
1604 | + INTERVAL_HOUR, INTERVAL_MINUTE, INTERVAL_SECOND, INTERVAL_MICROSECOND, |
1605 | + INTERVAL_YEAR_MONTH, INTERVAL_DAY_HOUR, INTERVAL_DAY_MINUTE, |
1606 | + INTERVAL_DAY_SECOND, INTERVAL_HOUR_MINUTE, INTERVAL_HOUR_SECOND, |
1607 | + INTERVAL_MINUTE_SECOND, INTERVAL_DAY_MICROSECOND, INTERVAL_HOUR_MICROSECOND, |
1608 | + INTERVAL_MINUTE_MICROSECOND, INTERVAL_SECOND_MICROSECOND, INTERVAL_LAST |
1609 | +}; |
1610 | + |
1611 | +extern uint64_t my_getsystime(void); |
1612 | +extern uint64_t my_micro_time(void); |
1613 | +extern uint64_t my_micro_time_and_time(time_t *time_arg); |
1614 | + |
1615 | +} /* namespace drizzled */ |
1616 | + |
1617 | +#endif /* DRIZZLED_DRIZZLE_TIME_H */ |
1618 | |
1619 | === modified file 'drizzled/drizzled.cc' |
1620 | --- drizzled/drizzled.cc 2010-03-26 21:36:11 +0000 |
1621 | +++ drizzled/drizzled.cc 2010-04-02 06:48:30 +0000 |
1622 | @@ -77,7 +77,7 @@ |
1623 | |
1624 | #include <errno.h> |
1625 | #include <sys/stat.h> |
1626 | -#include "drizzled/my_getopt.h" |
1627 | +#include "drizzled/option.h" |
1628 | #ifdef HAVE_SYSENT_H |
1629 | #include <sysent.h> |
1630 | #endif |
1631 | @@ -373,7 +373,7 @@ |
1632 | extern "C" pthread_handler_t signal_hand(void *arg); |
1633 | static void drizzle_init_variables(void); |
1634 | static void get_options(int *argc,char **argv); |
1635 | -int drizzled_get_one_option(int, const struct my_option *, char *); |
1636 | +int drizzled_get_one_option(int, const struct option *, char *); |
1637 | static int init_thread_environment(); |
1638 | static const char *get_relative_path(const char *path); |
1639 | static void fix_paths(string &progname); |
1640 | @@ -1249,7 +1249,7 @@ |
1641 | { |
1642 | int ho_error; |
1643 | char **tmp_argv= defaults_argv; |
1644 | - struct my_option no_opts[]= |
1645 | + struct option no_opts[]= |
1646 | { |
1647 | {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} |
1648 | }; |
1649 | @@ -1401,7 +1401,7 @@ |
1650 | }; |
1651 | |
1652 | |
1653 | -struct my_option my_long_options[] = |
1654 | +struct option my_long_options[] = |
1655 | { |
1656 | {"help", '?', N_("Display this help and exit."), |
1657 | (char**) &opt_help, (char**) &opt_help, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, |
1658 | @@ -1861,7 +1861,7 @@ |
1659 | } |
1660 | |
1661 | |
1662 | -int drizzled_get_one_option(int optid, const struct my_option *opt, |
1663 | +int drizzled_get_one_option(int optid, const struct option *opt, |
1664 | char *argument) |
1665 | { |
1666 | switch(optid) { |
1667 | |
1668 | === modified file 'drizzled/include.am' |
1669 | --- drizzled/include.am 2010-03-31 22:35:54 +0000 |
1670 | +++ drizzled/include.am 2010-04-02 06:48:30 +0000 |
1671 | @@ -255,11 +255,11 @@ |
1672 | drizzled/memory/sql_alloc.h \ |
1673 | drizzled/memory/multi_malloc.h \ |
1674 | drizzled/memory/root.h \ |
1675 | - drizzled/my_getopt.h \ |
1676 | + drizzled/option.h \ |
1677 | drizzled/my_hash.h \ |
1678 | - drizzled/my_time.h \ |
1679 | - drizzled/my_tree.h \ |
1680 | - drizzled/my_var.h \ |
1681 | + drizzled/drizzle_time.h \ |
1682 | + drizzled/tree.h \ |
1683 | + drizzled/var.h \ |
1684 | drizzled/name_resolution_context.h \ |
1685 | drizzled/name_resolution_context_state.h \ |
1686 | drizzled/named_savepoint.h \ |
1687 | @@ -634,8 +634,8 @@ |
1688 | drizzled/lookup_symbol.cc \ |
1689 | drizzled/my_getsystime.cc \ |
1690 | drizzled/my_hash.cc \ |
1691 | - drizzled/my_time.cc \ |
1692 | - drizzled/my_tree.cc \ |
1693 | + drizzled/drizzle_time.cc \ |
1694 | + drizzled/tree.cc \ |
1695 | drizzled/name_resolution_context_state.cc \ |
1696 | drizzled/natural_join_column.cc \ |
1697 | drizzled/optimizer/explain_plan.cc \ |
1698 | @@ -781,7 +781,7 @@ |
1699 | |
1700 | drizzled_libdynamic_array_la_SOURCES = drizzled/dynamic_array.cc |
1701 | drizzled_liberror_la_SOURCES = drizzled/error.cc |
1702 | -drizzled_libgetopt_la_SOURCES = drizzled/my_getopt.cc |
1703 | +drizzled_libgetopt_la_SOURCES = drizzled/option.cc |
1704 | drizzled_libtypelib_la_SOURCES = drizzled/typelib.cc |
1705 | drizzled_libserialutil_la_SOURCES = drizzled/db.cc drizzled/table_proto_write.cc |
1706 | drizzled_libserialutil_la_CXXFLAGS= ${AM_CXXFLAGS} ${PROTOSKIP_WARNINGS} |
1707 | |
1708 | === modified file 'drizzled/item.h' |
1709 | --- drizzled/item.h 2010-03-27 10:10:49 +0000 |
1710 | +++ drizzled/item.h 2010-04-02 06:48:30 +0000 |
1711 | @@ -21,7 +21,7 @@ |
1712 | #define DRIZZLED_ITEM_H |
1713 | |
1714 | #include <drizzled/dtcollation.h> |
1715 | -#include <drizzled/my_time.h> |
1716 | +#include <drizzled/drizzle_time.h> |
1717 | #include <drizzled/decimal.h> |
1718 | #include <drizzled/sql_bitmap.h> |
1719 | #include <drizzled/sql_list.h> |
1720 | |
1721 | === modified file 'drizzled/item/sum.h' |
1722 | --- drizzled/item/sum.h 2010-02-04 08:14:46 +0000 |
1723 | +++ drizzled/item/sum.h 2010-04-02 06:48:30 +0000 |
1724 | @@ -23,7 +23,7 @@ |
1725 | /* classes for sum functions */ |
1726 | |
1727 | |
1728 | -#include "drizzled/my_tree.h" |
1729 | +#include "drizzled/tree.h" |
1730 | #include <drizzled/hybrid_type.h> |
1731 | #include <drizzled/item.h> |
1732 | #include <drizzled/item/field.h> |
1733 | |
1734 | === removed file 'drizzled/my_getopt.cc' |
1735 | --- drizzled/my_getopt.cc 2010-03-26 14:54:21 +0000 |
1736 | +++ drizzled/my_getopt.cc 1970-01-01 00:00:00 +0000 |
1737 | @@ -1,1289 +0,0 @@ |
1738 | -/* Copyright (C) 2002-2006 MySQL AB |
1739 | - |
1740 | - This program is free software; you can redistribute it and/or modify |
1741 | - it under the terms of the GNU General Public License as published by |
1742 | - the Free Software Foundation; version 2 of the License. |
1743 | - |
1744 | - This program is distributed in the hope that it will be useful, |
1745 | - but WITHOUT ANY WARRANTY; without even the implied warranty of |
1746 | - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1747 | - GNU General Public License for more details. |
1748 | - |
1749 | - You should have received a copy of the GNU General Public License |
1750 | - along with this program; if not, write to the Free Software |
1751 | - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ |
1752 | - |
1753 | -#include "config.h" |
1754 | -#include "drizzled/internal/my_sys.h" |
1755 | -#include <drizzled/gettext.h> |
1756 | - |
1757 | -#include "drizzled/internal/m_string.h" |
1758 | -#include "drizzled/internal/my_sys.h" |
1759 | -#include "drizzled/error.h" |
1760 | -#include "drizzled/my_getopt.h" |
1761 | - |
1762 | -#include <stdio.h> |
1763 | -#include <stdlib.h> |
1764 | -#include <errno.h> |
1765 | -#include <iostream> |
1766 | -#include <algorithm> |
1767 | - |
1768 | -using namespace std; |
1769 | -namespace drizzled |
1770 | -{ |
1771 | - |
1772 | -typedef void (*init_func_p)(const struct my_option *option, char **variable, |
1773 | - int64_t value); |
1774 | - |
1775 | -void default_reporter(enum loglevel level, const char *format, ...); |
1776 | -my_error_reporter my_getopt_error_reporter= &default_reporter; |
1777 | - |
1778 | -static int findopt(char *optpat, uint32_t length, |
1779 | - const struct my_option **opt_res, |
1780 | - char **ffname); |
1781 | -static int64_t getopt_ll(char *arg, const struct my_option *optp, int *err); |
1782 | -static uint64_t getopt_ull(char *arg, const struct my_option *optp, |
1783 | - int *err); |
1784 | -static size_t getopt_size(char *arg, const struct my_option *optp, int *err); |
1785 | -static double getopt_double(char *arg, const struct my_option *optp, int *err); |
1786 | -static void init_variables(const struct my_option *options, |
1787 | - init_func_p init_one_value); |
1788 | -static void init_one_value(const struct my_option *option, char **variable, |
1789 | - int64_t value); |
1790 | -static void fini_one_value(const struct my_option *option, char **variable, |
1791 | - int64_t value); |
1792 | -static int setval(const struct my_option *opts, char* *value, char *argument, |
1793 | - bool set_maximum_value); |
1794 | -static char *check_struct_option(char *cur_arg, char *key_name); |
1795 | - |
1796 | -/* |
1797 | - The following three variables belong to same group and the number and |
1798 | - order of their arguments must correspond to each other. |
1799 | - */ |
1800 | -static const char *special_opt_prefix[]= |
1801 | -{"skip", "disable", "enable", "maximum", "loose", 0}; |
1802 | -static const uint32_t special_opt_prefix_lengths[]= |
1803 | -{ 4, 7, 6, 7, 5, 0}; |
1804 | -enum enum_special_opt |
1805 | -{ OPT_SKIP, OPT_DISABLE, OPT_ENABLE, OPT_MAXIMUM, OPT_LOOSE}; |
1806 | - |
1807 | -char *disabled_my_option= (char*) "0"; |
1808 | - |
1809 | -/* |
1810 | - This is a flag that can be set in client programs. 1 means that |
1811 | - my_getopt will skip over options it does not know how to handle. |
1812 | - */ |
1813 | - |
1814 | -bool my_getopt_skip_unknown= 0; |
1815 | - |
1816 | -void default_reporter(enum loglevel level, const char *format, ...) |
1817 | -{ |
1818 | - va_list args; |
1819 | - va_start(args, format); |
1820 | - if (level == WARNING_LEVEL) |
1821 | - fprintf(stderr, "%s", _("Warning: ")); |
1822 | - else if (level == INFORMATION_LEVEL) |
1823 | - fprintf(stderr, "%s", _("Info: ")); |
1824 | - vfprintf(stderr, format, args); |
1825 | - va_end(args); |
1826 | - fputc('\n', stderr); |
1827 | - fflush(stderr); |
1828 | -} |
1829 | - |
1830 | -/* |
1831 | -function: handle_options |
1832 | - |
1833 | -Sort options; put options first, until special end of options (--), or |
1834 | -until end of argv. Parse options; check that the given option matches with |
1835 | -one of the options in struct 'my_option', return error in case of ambiguous |
1836 | -or unknown option. Check that option was given an argument if it requires |
1837 | -one. Call function 'get_one_option()' once for each option. |
1838 | - */ |
1839 | - |
1840 | -static getopt_get_addr_func getopt_get_addr; |
1841 | - |
1842 | -int handle_options(int *argc, char ***argv, |
1843 | - const struct my_option *longopts, |
1844 | - my_get_one_option get_one_option) |
1845 | -{ |
1846 | - uint32_t opt_found, argvpos= 0, length; |
1847 | - bool end_of_options= 0, must_be_var, set_maximum_value=false, |
1848 | - option_is_loose; |
1849 | - char **pos, **pos_end, *optend, *prev_found=NULL, |
1850 | - *opt_str, key_name[FN_REFLEN]; |
1851 | - const struct my_option *optp; |
1852 | - char* *value; |
1853 | - int error, i; |
1854 | - |
1855 | - /* handle_options() assumes arg0 (program name) always exists */ |
1856 | - assert(argc && *argc >= 1); |
1857 | - assert(argv && *argv); |
1858 | - (*argc)--; /* Skip the program name */ |
1859 | - (*argv)++; /* --- || ---- */ |
1860 | - init_variables(longopts, init_one_value); |
1861 | - |
1862 | - for (pos= *argv, pos_end=pos+ *argc; pos != pos_end ; pos++) |
1863 | - { |
1864 | - char **first= pos; |
1865 | - char *cur_arg= *pos; |
1866 | - if (cur_arg[0] == '-' && cur_arg[1] && !end_of_options) /* must be opt */ |
1867 | - { |
1868 | - char *argument= 0; |
1869 | - must_be_var= 0; |
1870 | - set_maximum_value= 0; |
1871 | - option_is_loose= 0; |
1872 | - |
1873 | - cur_arg++; /* skip '-' */ |
1874 | - if (*cur_arg == '-' || *cur_arg == 'O') /* check for long option, */ |
1875 | - { /* --set-variable, or -O */ |
1876 | - if (*cur_arg == 'O') |
1877 | - { |
1878 | - must_be_var= 1; |
1879 | - |
1880 | - if (!(*++cur_arg)) /* If not -Ovar=# */ |
1881 | - { |
1882 | - /* the argument must be in next argv */ |
1883 | - if (!*++pos) |
1884 | - { |
1885 | - my_getopt_error_reporter(ERROR_LEVEL, |
1886 | - "%s: Option '-O' requires an argument", |
1887 | - internal::my_progname); |
1888 | - return EXIT_ARGUMENT_REQUIRED; |
1889 | - } |
1890 | - cur_arg= *pos; |
1891 | - (*argc)--; |
1892 | - } |
1893 | - } |
1894 | - else if (!getopt_compare_strings(cur_arg, "-set-variable", 13)) |
1895 | - { |
1896 | - must_be_var= 1; |
1897 | - if (cur_arg[13] == '=') |
1898 | - { |
1899 | - cur_arg+= 14; |
1900 | - if (!*cur_arg) |
1901 | - { |
1902 | - my_getopt_error_reporter(ERROR_LEVEL, |
1903 | - "%s: Option '--set-variable' requires an argument", |
1904 | - internal::my_progname); |
1905 | - return EXIT_ARGUMENT_REQUIRED; |
1906 | - } |
1907 | - } |
1908 | - else if (cur_arg[14]) /* garbage, or another option. break out */ |
1909 | - must_be_var= 0; |
1910 | - else |
1911 | - { |
1912 | - /* the argument must be in next argv */ |
1913 | - if (!*++pos) |
1914 | - { |
1915 | - my_getopt_error_reporter(ERROR_LEVEL, |
1916 | - "%s: Option '--set-variable' requires an argument", |
1917 | - internal::my_progname); |
1918 | - return EXIT_ARGUMENT_REQUIRED; |
1919 | - } |
1920 | - cur_arg= *pos; |
1921 | - (*argc)--; |
1922 | - } |
1923 | - } |
1924 | - else if (!must_be_var) |
1925 | - { |
1926 | - if (!*++cur_arg) /* skip the double dash */ |
1927 | - { |
1928 | - /* '--' means end of options, look no further */ |
1929 | - end_of_options= 1; |
1930 | - (*argc)--; |
1931 | - continue; |
1932 | - } |
1933 | - } |
1934 | - opt_str= check_struct_option(cur_arg, key_name); |
1935 | - optend= strrchr(opt_str, '='); |
1936 | - if (optend != NULL) |
1937 | - { |
1938 | - length= (uint32_t) (optend - opt_str); |
1939 | - optend++; |
1940 | - } |
1941 | - else |
1942 | - { |
1943 | - length= static_cast<uint32_t>(strlen(opt_str)); |
1944 | - optend= 0; |
1945 | - } |
1946 | - |
1947 | - /* |
1948 | - Find first the right option. Return error in case of an ambiguous, |
1949 | - or unknown option |
1950 | - */ |
1951 | - optp= longopts; |
1952 | - if (!(opt_found= findopt(opt_str, length, &optp, &prev_found))) |
1953 | - { |
1954 | - /* |
1955 | - Didn't find any matching option. Let's see if someone called |
1956 | - option with a special option prefix |
1957 | - */ |
1958 | - if (!must_be_var) |
1959 | - { |
1960 | - if (optend) |
1961 | - must_be_var= 1; /* option is followed by an argument */ |
1962 | - for (i= 0; special_opt_prefix[i]; i++) |
1963 | - { |
1964 | - if (!getopt_compare_strings(special_opt_prefix[i], opt_str, |
1965 | - special_opt_prefix_lengths[i]) && |
1966 | - (opt_str[special_opt_prefix_lengths[i]] == '-' || |
1967 | - opt_str[special_opt_prefix_lengths[i]] == '_')) |
1968 | - { |
1969 | - /* |
1970 | - We were called with a special prefix, we can reuse opt_found |
1971 | - */ |
1972 | - opt_str+= special_opt_prefix_lengths[i] + 1; |
1973 | - length-= special_opt_prefix_lengths[i] + 1; |
1974 | - if (i == OPT_LOOSE) |
1975 | - option_is_loose= 1; |
1976 | - if ((opt_found= findopt(opt_str, length, &optp, &prev_found))) |
1977 | - { |
1978 | - if (opt_found > 1) |
1979 | - { |
1980 | - my_getopt_error_reporter(ERROR_LEVEL, |
1981 | - "%s: ambiguous option '--%s-%s' (--%s-%s)", |
1982 | - internal::my_progname, |
1983 | - special_opt_prefix[i], |
1984 | - cur_arg, special_opt_prefix[i], |
1985 | - prev_found); |
1986 | - return EXIT_AMBIGUOUS_OPTION; |
1987 | - } |
1988 | - switch (i) { |
1989 | - case OPT_SKIP: |
1990 | - case OPT_DISABLE: /* fall through */ |
1991 | - /* |
1992 | - double negation is actually enable again, |
1993 | - for example: --skip-option=0 -> option = true |
1994 | - */ |
1995 | - optend= (optend && *optend == '0' && !(*(optend + 1))) ? |
1996 | - (char*) "1" : disabled_my_option; |
1997 | - break; |
1998 | - case OPT_ENABLE: |
1999 | - optend= (optend && *optend == '0' && !(*(optend + 1))) ? |
2000 | - disabled_my_option : (char*) "1"; |
2001 | - break; |
2002 | - case OPT_MAXIMUM: |
2003 | - set_maximum_value= true; |
2004 | - must_be_var= true; |
2005 | - break; |
2006 | - } |
2007 | - break; /* break from the inner loop, main loop continues */ |
2008 | - } |
2009 | - i= -1; /* restart the loop */ |
2010 | - } |
2011 | - } |
2012 | - } |
2013 | - if (!opt_found) |
2014 | - { |
2015 | - if (my_getopt_skip_unknown) |
2016 | - { |
2017 | - /* |
2018 | - preserve all the components of this unknown option, this may |
2019 | - occurr when the user provides options like: "-O foo" or |
2020 | - "--set-variable foo" (note that theres a space in there) |
2021 | - Generally, these kind of options are to be avoided |
2022 | - */ |
2023 | - do { |
2024 | - (*argv)[argvpos++]= *first++; |
2025 | - } while (first <= pos); |
2026 | - continue; |
2027 | - } |
2028 | - if (must_be_var) |
2029 | - { |
2030 | - my_getopt_error_reporter(option_is_loose ? |
2031 | - WARNING_LEVEL : ERROR_LEVEL, |
2032 | - "%s: unknown variable '%s'", |
2033 | - internal::my_progname, cur_arg); |
2034 | - if (!option_is_loose) |
2035 | - return EXIT_UNKNOWN_VARIABLE; |
2036 | - } |
2037 | - else |
2038 | - { |
2039 | - my_getopt_error_reporter(option_is_loose ? |
2040 | - WARNING_LEVEL : ERROR_LEVEL, |
2041 | - "%s: unknown option '--%s'", |
2042 | - internal::my_progname, cur_arg); |
2043 | - if (!option_is_loose) |
2044 | - return EXIT_UNKNOWN_OPTION; |
2045 | - } |
2046 | - if (option_is_loose) |
2047 | - { |
2048 | - (*argc)--; |
2049 | - continue; |
2050 | - } |
2051 | - } |
2052 | - } |
2053 | - if (opt_found > 1) |
2054 | - { |
2055 | - if (must_be_var) |
2056 | - { |
2057 | - my_getopt_error_reporter(ERROR_LEVEL, |
2058 | - "%s: variable prefix '%s' is not unique", |
2059 | - internal::my_progname, opt_str); |
2060 | - return EXIT_VAR_PREFIX_NOT_UNIQUE; |
2061 | - } |
2062 | - else |
2063 | - { |
2064 | - my_getopt_error_reporter(ERROR_LEVEL, |
2065 | - "%s: ambiguous option '--%s' (%s, %s)", |
2066 | - internal::my_progname, opt_str, prev_found, |
2067 | - optp->name); |
2068 | - return EXIT_AMBIGUOUS_OPTION; |
2069 | - } |
2070 | - } |
2071 | - if ((optp->var_type & GET_TYPE_MASK) == GET_DISABLED) |
2072 | - { |
2073 | - fprintf(stderr, |
2074 | - _("%s: %s: Option '%s' used, but is disabled\n"), |
2075 | - internal::my_progname, |
2076 | - option_is_loose ? _("WARNING") : _("ERROR"), opt_str); |
2077 | - if (option_is_loose) |
2078 | - { |
2079 | - (*argc)--; |
2080 | - continue; |
2081 | - } |
2082 | - return EXIT_OPTION_DISABLED; |
2083 | - } |
2084 | - if (must_be_var && (optp->var_type & GET_TYPE_MASK) == GET_NO_ARG) |
2085 | - { |
2086 | - my_getopt_error_reporter(ERROR_LEVEL, |
2087 | - "%s: option '%s' cannot take an argument", |
2088 | - internal::my_progname, optp->name); |
2089 | - return EXIT_NO_ARGUMENT_ALLOWED; |
2090 | - } |
2091 | - value= optp->var_type & GET_ASK_ADDR ? |
2092 | - (*getopt_get_addr)(key_name, (uint32_t) strlen(key_name), optp) : optp->value; |
2093 | - |
2094 | - if (optp->arg_type == NO_ARG) |
2095 | - { |
2096 | - if (optend && (optp->var_type & GET_TYPE_MASK) != GET_BOOL) |
2097 | - { |
2098 | - my_getopt_error_reporter(ERROR_LEVEL, |
2099 | - "%s: option '--%s' cannot take an argument", |
2100 | - internal::my_progname, optp->name); |
2101 | - return EXIT_NO_ARGUMENT_ALLOWED; |
2102 | - } |
2103 | - if ((optp->var_type & GET_TYPE_MASK) == GET_BOOL) |
2104 | - { |
2105 | - /* |
2106 | - Set bool to 1 if no argument or if the user has used |
2107 | - --enable-'option-name'. |
2108 | - *optend was set to '0' if one used --disable-option |
2109 | - */ |
2110 | - (*argc)--; |
2111 | - if (!optend || *optend == '1' || |
2112 | - !my_strcasecmp(&my_charset_utf8_general_ci, optend, "true")) |
2113 | - *((bool*) value)= (bool) 1; |
2114 | - else if (*optend == '0' || |
2115 | - !my_strcasecmp(&my_charset_utf8_general_ci, optend, "false")) |
2116 | - *((bool*) value)= (bool) 0; |
2117 | - else |
2118 | - { |
2119 | - my_getopt_error_reporter(WARNING_LEVEL, |
2120 | - "%s: ignoring option '--%s' due to " |
2121 | - "invalid value '%s'", |
2122 | - internal::my_progname, |
2123 | - optp->name, optend); |
2124 | - continue; |
2125 | - } |
2126 | - error= get_one_option(optp->id, optp, *((bool*) value) ? |
2127 | - (char*) "1" : disabled_my_option); |
2128 | - if (error != 0) |
2129 | - return error; |
2130 | - else |
2131 | - continue; |
2132 | - } |
2133 | - argument= optend; |
2134 | - } |
2135 | - else if (optp->arg_type == OPT_ARG && |
2136 | - (optp->var_type & GET_TYPE_MASK) == GET_BOOL) |
2137 | - { |
2138 | - if (optend == disabled_my_option) |
2139 | - *((bool*) value)= (bool) 0; |
2140 | - else |
2141 | - { |
2142 | - if (!optend) /* No argument -> enable option */ |
2143 | - *((bool*) value)= (bool) 1; |
2144 | - else |
2145 | - argument= optend; |
2146 | - } |
2147 | - } |
2148 | - else if (optp->arg_type == REQUIRED_ARG && !optend) |
2149 | - { |
2150 | - /* Check if there are more arguments after this one */ |
2151 | - if (!*++pos) |
2152 | - { |
2153 | - my_getopt_error_reporter(ERROR_LEVEL, |
2154 | - "%s: option '--%s' requires an argument", |
2155 | - internal::my_progname, optp->name); |
2156 | - return EXIT_ARGUMENT_REQUIRED; |
2157 | - } |
2158 | - argument= *pos; |
2159 | - (*argc)--; |
2160 | - } |
2161 | - else |
2162 | - argument= optend; |
2163 | - } |
2164 | - else /* must be short option */ |
2165 | - { |
2166 | - for (optend= cur_arg; *optend; optend++) |
2167 | - { |
2168 | - opt_found= 0; |
2169 | - for (optp= longopts; optp->id; optp++) |
2170 | - { |
2171 | - if (optp->id == (int) (unsigned char) *optend) |
2172 | - { |
2173 | - /* Option recognized. Find next what to do with it */ |
2174 | - opt_found= 1; |
2175 | - if ((optp->var_type & GET_TYPE_MASK) == GET_DISABLED) |
2176 | - { |
2177 | - fprintf(stderr, |
2178 | - _("%s: ERROR: Option '-%c' used, but is disabled\n"), |
2179 | - internal::my_progname, optp->id); |
2180 | - return EXIT_OPTION_DISABLED; |
2181 | - } |
2182 | - if ((optp->var_type & GET_TYPE_MASK) == GET_BOOL && |
2183 | - optp->arg_type == NO_ARG) |
2184 | - { |
2185 | - *((bool*) optp->value)= (bool) 1; |
2186 | - error= get_one_option(optp->id, optp, argument); |
2187 | - if (error != 0) |
2188 | - return error; |
2189 | - else |
2190 | - continue; |
2191 | - |
2192 | - } |
2193 | - else if (optp->arg_type == REQUIRED_ARG || |
2194 | - optp->arg_type == OPT_ARG) |
2195 | - { |
2196 | - if (*(optend + 1)) |
2197 | - { |
2198 | - /* The rest of the option is option argument */ |
2199 | - argument= optend + 1; |
2200 | - /* This is in effect a jump out of the outer loop */ |
2201 | - optend= (char*) " "; |
2202 | - } |
2203 | - else |
2204 | - { |
2205 | - if (optp->arg_type == OPT_ARG) |
2206 | - { |
2207 | - if (optp->var_type == GET_BOOL) |
2208 | - *((bool*) optp->value)= (bool) 1; |
2209 | - error= get_one_option(optp->id, optp, argument); |
2210 | - if (error != 0) |
2211 | - return error; |
2212 | - else |
2213 | - continue; |
2214 | - } |
2215 | - /* Check if there are more arguments after this one */ |
2216 | - if (!pos[1]) |
2217 | - { |
2218 | - my_getopt_error_reporter(ERROR_LEVEL, |
2219 | - "%s: option '-%c' requires " |
2220 | - "an argument", |
2221 | - internal::my_progname, optp->id); |
2222 | - return EXIT_ARGUMENT_REQUIRED; |
2223 | - } |
2224 | - argument= *++pos; |
2225 | - (*argc)--; |
2226 | - /* the other loop will break, because *optend + 1 == 0 */ |
2227 | - } |
2228 | - } |
2229 | - if ((error= setval(optp, optp->value, argument, |
2230 | - set_maximum_value))) |
2231 | - { |
2232 | - my_getopt_error_reporter(ERROR_LEVEL, |
2233 | - "%s: Error while setting value '%s' " |
2234 | - "to '%s'", |
2235 | - internal::my_progname, |
2236 | - argument, optp->name); |
2237 | - return error; |
2238 | - } |
2239 | - error= get_one_option(optp->id, optp, argument); |
2240 | - if (error != 0) |
2241 | - return error; |
2242 | - else |
2243 | - break; |
2244 | - } |
2245 | - } |
2246 | - if (!opt_found) |
2247 | - { |
2248 | - my_getopt_error_reporter(ERROR_LEVEL, |
2249 | - "%s: unknown option '-%c'", |
2250 | - internal::my_progname, *optend); |
2251 | - return EXIT_UNKNOWN_OPTION; |
2252 | - } |
2253 | - } |
2254 | - (*argc)--; /* option handled (short), decrease argument count */ |
2255 | - continue; |
2256 | - } |
2257 | - if ((error= setval(optp, value, argument, set_maximum_value))) |
2258 | - { |
2259 | - my_getopt_error_reporter(ERROR_LEVEL, |
2260 | - "%s: Error while setting value '%s' to '%s'", |
2261 | - internal::my_progname, argument, optp->name); |
2262 | - return error; |
2263 | - } |
2264 | - error= get_one_option(optp->id, optp, argument); |
2265 | - if (error != 0) |
2266 | - return error; |
2267 | - |
2268 | - (*argc)--; /* option handled (short or long), decrease argument count */ |
2269 | - } |
2270 | - else /* non-option found */ |
2271 | - (*argv)[argvpos++]= cur_arg; |
2272 | - } |
2273 | - /* |
2274 | - Destroy the first, already handled option, so that programs that look |
2275 | - for arguments in 'argv', without checking 'argc', know when to stop. |
2276 | - Items in argv, before the destroyed one, are all non-option -arguments |
2277 | - to the program, yet to be (possibly) handled. |
2278 | - */ |
2279 | - (*argv)[argvpos]= 0; |
2280 | - return 0; |
2281 | -} |
2282 | - |
2283 | - |
2284 | -/* |
2285 | -function: check_struct_option |
2286 | - |
2287 | -Arguments: Current argument under processing from argv and a variable |
2288 | -where to store the possible key name. |
2289 | - |
2290 | -Return value: In case option is a struct option, returns a pointer to |
2291 | -the current argument at the position where the struct option (key_name) |
2292 | -ends, the next character after the dot. In case argument is not a struct |
2293 | -option, returns a pointer to the argument. |
2294 | - |
2295 | -key_name will hold the name of the key, or 0 if not found. |
2296 | - */ |
2297 | - |
2298 | -static char *check_struct_option(char *cur_arg, char *key_name) |
2299 | -{ |
2300 | - char *ptr, *end; |
2301 | - |
2302 | - ptr= strrchr(cur_arg + 1, '.'); /* Skip the first character */ |
2303 | - end= strrchr(cur_arg, '='); |
2304 | - |
2305 | - /* |
2306 | - If the first dot is after an equal sign, then it is part |
2307 | - of a variable value and the option is not a struct option. |
2308 | - Also, if the last character in the string before the ending |
2309 | - NULL, or the character right before equal sign is the first |
2310 | - dot found, the option is not a struct option. |
2311 | - */ |
2312 | - if ((ptr != NULL) && (end != NULL) && (end - ptr > 1)) |
2313 | - { |
2314 | - uint32_t len= (uint32_t) (ptr - cur_arg); |
2315 | - set_if_smaller(len, (uint32_t)FN_REFLEN-1); |
2316 | - strncpy(key_name, cur_arg, len); |
2317 | - return ++ptr; |
2318 | - } |
2319 | - key_name[0]= 0; |
2320 | - return cur_arg; |
2321 | -} |
2322 | - |
2323 | -/* |
2324 | -function: setval |
2325 | - |
2326 | -Arguments: opts, argument |
2327 | -Will set the option value to given value |
2328 | - */ |
2329 | - |
2330 | -static int setval(const struct my_option *opts, char **value, char *argument, |
2331 | - bool set_maximum_value) |
2332 | -{ |
2333 | - int err= 0; |
2334 | - |
2335 | - if (value && argument) |
2336 | - { |
2337 | - char* *result_pos= ((set_maximum_value) ? |
2338 | - opts->u_max_value : value); |
2339 | - |
2340 | - if (!result_pos) |
2341 | - return EXIT_NO_PTR_TO_VARIABLE; |
2342 | - |
2343 | - switch ((opts->var_type & GET_TYPE_MASK)) { |
2344 | - case GET_BOOL: /* If argument differs from 0, enable option, else disable */ |
2345 | - *((bool*) result_pos)= (bool) atoi(argument) != 0; |
2346 | - break; |
2347 | - case GET_INT: |
2348 | - *((int32_t*) result_pos)= (int) getopt_ll(argument, opts, &err); |
2349 | - break; |
2350 | - case GET_UINT: |
2351 | - case GET_UINT32: |
2352 | - *((uint32_t*) result_pos)= (uint32_t) getopt_ull(argument, opts, &err); |
2353 | - break; |
2354 | - case GET_ULONG_IS_FAIL: |
2355 | - *((ulong*) result_pos)= (ulong) getopt_ull(argument, opts, &err); |
2356 | - break; |
2357 | - case GET_LONG: |
2358 | - *((long*) result_pos)= (long) getopt_ll(argument, opts, &err); |
2359 | - break; |
2360 | - case GET_LL: |
2361 | - *((int64_t*) result_pos)= getopt_ll(argument, opts, &err); |
2362 | - break; |
2363 | - case GET_ULL: |
2364 | - case GET_UINT64: |
2365 | - *((uint64_t*) result_pos)= getopt_ull(argument, opts, &err); |
2366 | - break; |
2367 | - case GET_SIZE: |
2368 | - *((size_t*) result_pos)= getopt_size(argument, opts, &err); |
2369 | - break; |
2370 | - case GET_DOUBLE: |
2371 | - *((double*) result_pos)= getopt_double(argument, opts, &err); |
2372 | - break; |
2373 | - case GET_STR: |
2374 | - *((char**) result_pos)= argument; |
2375 | - break; |
2376 | - case GET_STR_ALLOC: |
2377 | - if ((*((char**) result_pos))) |
2378 | - free((*(char**) result_pos)); |
2379 | - if (!(*((char**) result_pos)= strdup(argument))) |
2380 | - return EXIT_OUT_OF_MEMORY; |
2381 | - break; |
2382 | - case GET_ENUM: |
2383 | - if (((*(int*)result_pos)= find_type(argument, opts->typelib, 2) - 1) < 0) |
2384 | - return EXIT_ARGUMENT_INVALID; |
2385 | - break; |
2386 | - case GET_SET: |
2387 | - *((uint64_t*)result_pos)= find_typeset(argument, opts->typelib, &err); |
2388 | - if (err) |
2389 | - return EXIT_ARGUMENT_INVALID; |
2390 | - break; |
2391 | - default: /* dummy default to avoid compiler warnings */ |
2392 | - break; |
2393 | - } |
2394 | - if (err) |
2395 | - return EXIT_UNKNOWN_SUFFIX; |
2396 | - } |
2397 | - return 0; |
2398 | -} |
2399 | - |
2400 | - |
2401 | -/* |
2402 | - Find option |
2403 | - |
2404 | - SYNOPSIS |
2405 | - findopt() |
2406 | - optpat Prefix of option to find (with - or _) |
2407 | - length Length of optpat |
2408 | - opt_res Options |
2409 | - ffname Place for pointer to first found name |
2410 | - |
2411 | - IMPLEMENTATION |
2412 | - Go through all options in the my_option struct. Return number |
2413 | - of options found that match the pattern and in the argument |
2414 | - list the option found, if any. In case of ambiguous option, store |
2415 | - the name in ffname argument |
2416 | - |
2417 | - RETURN |
2418 | - 0 No matching options |
2419 | -# Number of matching options |
2420 | -ffname points to first matching option |
2421 | - */ |
2422 | - |
2423 | -static int findopt(char *optpat, uint32_t length, |
2424 | - const struct my_option **opt_res, |
2425 | - char **ffname) |
2426 | -{ |
2427 | - uint32_t count; |
2428 | - struct my_option *opt= (struct my_option *) *opt_res; |
2429 | - |
2430 | - for (count= 0; opt->name; opt++) |
2431 | - { |
2432 | - if (!getopt_compare_strings(opt->name, optpat, length)) /* match found */ |
2433 | - { |
2434 | - (*opt_res)= opt; |
2435 | - if (!opt->name[length]) /* Exact match */ |
2436 | - return 1; |
2437 | - if (!count) |
2438 | - { |
2439 | - count= 1; |
2440 | - *ffname= (char *) opt->name; /* We only need to know one prev */ |
2441 | - } |
2442 | - else if (strcmp(*ffname, opt->name)) |
2443 | - { |
2444 | - /* |
2445 | - The above test is to not count same option twice |
2446 | - (see mysql.cc, option "help") |
2447 | - */ |
2448 | - count++; |
2449 | - } |
2450 | - } |
2451 | - } |
2452 | - return count; |
2453 | -} |
2454 | - |
2455 | - |
2456 | -/* |
2457 | -function: compare_strings |
2458 | - |
2459 | -Works like strncmp, other than 1.) considers '-' and '_' the same. |
2460 | -2.) Returns -1 if strings differ, 0 if they are equal |
2461 | - */ |
2462 | - |
2463 | -bool getopt_compare_strings(register const char *s, register const char *t, |
2464 | - uint32_t length) |
2465 | -{ |
2466 | - char const *end= s + length; |
2467 | - for (;s != end ; s++, t++) |
2468 | - { |
2469 | - if ((*s != '-' ? *s : '_') != (*t != '-' ? *t : '_')) |
2470 | - return 1; |
2471 | - } |
2472 | - return 0; |
2473 | -} |
2474 | - |
2475 | -/* |
2476 | -function: eval_num_suffix |
2477 | - |
2478 | -Transforms a number with a suffix to real number. Suffix can |
2479 | -be k|K for kilo, m|M for mega or g|G for giga. |
2480 | - */ |
2481 | - |
2482 | -static int64_t eval_num_suffix(char *argument, int *error, char *option_name) |
2483 | -{ |
2484 | - char *endchar; |
2485 | - int64_t num; |
2486 | - |
2487 | - *error= 0; |
2488 | - errno= 0; |
2489 | - num= strtoll(argument, &endchar, 10); |
2490 | - if (errno == ERANGE) |
2491 | - { |
2492 | - my_getopt_error_reporter(ERROR_LEVEL, |
2493 | - "Incorrect integer value: '%s'", argument); |
2494 | - *error= 1; |
2495 | - return 0; |
2496 | - } |
2497 | - if (*endchar == 'k' || *endchar == 'K') |
2498 | - num*= 1024L; |
2499 | - else if (*endchar == 'm' || *endchar == 'M') |
2500 | - num*= 1024L * 1024L; |
2501 | - else if (*endchar == 'g' || *endchar == 'G') |
2502 | - num*= 1024L * 1024L * 1024L; |
2503 | - else if (*endchar) |
2504 | - { |
2505 | - fprintf(stderr, |
2506 | - _("Unknown suffix '%c' used for variable '%s' (value '%s')\n"), |
2507 | - *endchar, option_name, argument); |
2508 | - *error= 1; |
2509 | - return 0; |
2510 | - } |
2511 | - return num; |
2512 | -} |
2513 | - |
2514 | -/* |
2515 | -function: getopt_ll |
2516 | - |
2517 | -Evaluates and returns the value that user gave as an argument |
2518 | -to a variable. Recognizes (case insensitive) K as KILO, M as MEGA |
2519 | -and G as GIGA bytes. Some values must be in certain blocks, as |
2520 | -defined in the given my_option struct, this function will check |
2521 | -that those values are honored. |
2522 | -In case of an error, set error value in *err. |
2523 | - */ |
2524 | - |
2525 | -static int64_t getopt_ll(char *arg, const struct my_option *optp, int *err) |
2526 | -{ |
2527 | - int64_t num=eval_num_suffix(arg, err, (char*) optp->name); |
2528 | - return getopt_ll_limit_value(num, optp, NULL); |
2529 | -} |
2530 | - |
2531 | -/* |
2532 | -function: getopt_ll_limit_value |
2533 | - |
2534 | -Applies min/max/block_size to a numeric value of an option. |
2535 | -Returns "fixed" value. |
2536 | - */ |
2537 | - |
2538 | -int64_t getopt_ll_limit_value(int64_t num, const struct my_option *optp, |
2539 | - bool *fix) |
2540 | -{ |
2541 | - int64_t old= num; |
2542 | - bool adjusted= false; |
2543 | - char buf1[255], buf2[255]; |
2544 | - uint64_t block_size= (optp->block_size ? (uint64_t) optp->block_size : 1L); |
2545 | - |
2546 | - if (num > 0 && ((uint64_t) num > (uint64_t) optp->max_value) && |
2547 | - optp->max_value) /* if max value is not set -> no upper limit */ |
2548 | - { |
2549 | - num= (uint64_t) optp->max_value; |
2550 | - adjusted= true; |
2551 | - } |
2552 | - |
2553 | - switch ((optp->var_type & GET_TYPE_MASK)) { |
2554 | - case GET_INT: |
2555 | - if (num > (int64_t) INT_MAX) |
2556 | - { |
2557 | - num= ((int64_t) INT_MAX); |
2558 | - adjusted= true; |
2559 | - } |
2560 | - break; |
2561 | - case GET_LONG: |
2562 | - if (num > (int64_t) INT32_MAX) |
2563 | - { |
2564 | - num= ((int64_t) INT32_MAX); |
2565 | - adjusted= true; |
2566 | - } |
2567 | - break; |
2568 | - default: |
2569 | - assert((optp->var_type & GET_TYPE_MASK) == GET_LL); |
2570 | - break; |
2571 | - } |
2572 | - |
2573 | - num= ((num - optp->sub_size) / block_size); |
2574 | - num= (int64_t) (num * block_size); |
2575 | - |
2576 | - if (num < optp->min_value) |
2577 | - { |
2578 | - num= optp->min_value; |
2579 | - adjusted= true; |
2580 | - } |
2581 | - |
2582 | - if (fix) |
2583 | - *fix= adjusted; |
2584 | - else if (adjusted) |
2585 | - my_getopt_error_reporter(WARNING_LEVEL, |
2586 | - "option '%s': signed value %s adjusted to %s", |
2587 | - optp->name, internal::llstr(old, buf1), internal::llstr(num, buf2)); |
2588 | - return num; |
2589 | -} |
2590 | - |
2591 | -/* |
2592 | -function: getopt_ull |
2593 | - |
2594 | -This is the same as getopt_ll, but is meant for uint64_t |
2595 | -values. |
2596 | - */ |
2597 | - |
2598 | -static uint64_t getopt_ull(char *arg, const struct my_option *optp, int *err) |
2599 | -{ |
2600 | - uint64_t num= eval_num_suffix(arg, err, (char*) optp->name); |
2601 | - return getopt_ull_limit_value(num, optp, NULL); |
2602 | -} |
2603 | - |
2604 | - |
2605 | -static size_t getopt_size(char *arg, const struct my_option *optp, int *err) |
2606 | -{ |
2607 | - return (size_t)getopt_ull(arg, optp, err); |
2608 | -} |
2609 | - |
2610 | - |
2611 | - |
2612 | -uint64_t getopt_ull_limit_value(uint64_t num, const struct my_option *optp, |
2613 | - bool *fix) |
2614 | -{ |
2615 | - bool adjusted= false; |
2616 | - uint64_t old= num; |
2617 | - char buf1[255], buf2[255]; |
2618 | - |
2619 | - if ((uint64_t) num > (uint64_t) optp->max_value && |
2620 | - optp->max_value) /* if max value is not set -> no upper limit */ |
2621 | - { |
2622 | - num= (uint64_t) optp->max_value; |
2623 | - adjusted= true; |
2624 | - } |
2625 | - |
2626 | - switch ((optp->var_type & GET_TYPE_MASK)) { |
2627 | - case GET_UINT: |
2628 | - if (num > (uint64_t) UINT_MAX) |
2629 | - { |
2630 | - num= ((uint64_t) UINT_MAX); |
2631 | - adjusted= true; |
2632 | - } |
2633 | - break; |
2634 | - case GET_UINT32: |
2635 | - case GET_ULONG_IS_FAIL: |
2636 | - if (num > (uint64_t) UINT32_MAX) |
2637 | - { |
2638 | - num= ((uint64_t) UINT32_MAX); |
2639 | - adjusted= true; |
2640 | - } |
2641 | - break; |
2642 | - case GET_SIZE: |
2643 | - if (num > (uint64_t) SIZE_MAX) |
2644 | - { |
2645 | - num= ((uint64_t) SIZE_MAX); |
2646 | - adjusted= true; |
2647 | - } |
2648 | - break; |
2649 | - default: |
2650 | - assert(((optp->var_type & GET_TYPE_MASK) == GET_ULL) |
2651 | - || ((optp->var_type & GET_TYPE_MASK) == GET_UINT64)); |
2652 | - break; |
2653 | - } |
2654 | - |
2655 | - if (optp->block_size > 1) |
2656 | - { |
2657 | - num/= (uint64_t) optp->block_size; |
2658 | - num*= (uint64_t) optp->block_size; |
2659 | - } |
2660 | - |
2661 | - if (num < (uint64_t) optp->min_value) |
2662 | - { |
2663 | - num= (uint64_t) optp->min_value; |
2664 | - adjusted= true; |
2665 | - } |
2666 | - |
2667 | - if (fix) |
2668 | - *fix= adjusted; |
2669 | - else if (adjusted) |
2670 | - my_getopt_error_reporter(WARNING_LEVEL, |
2671 | - "option '%s': unsigned value %s adjusted to %s", |
2672 | - optp->name, internal::ullstr(old, buf1), internal::ullstr(num, buf2)); |
2673 | - |
2674 | - return num; |
2675 | -} |
2676 | - |
2677 | - |
2678 | -/* |
2679 | - Get double value withing ranges |
2680 | - |
2681 | - Evaluates and returns the value that user gave as an argument to a variable. |
2682 | - |
2683 | - RETURN |
2684 | - decimal value of arg |
2685 | - |
2686 | - In case of an error, prints an error message and sets *err to |
2687 | - EXIT_ARGUMENT_INVALID. Otherwise err is not touched |
2688 | - */ |
2689 | - |
2690 | -static double getopt_double(char *arg, const struct my_option *optp, int *err) |
2691 | -{ |
2692 | - double num; |
2693 | - int error; |
2694 | - char *end= arg + 1000; /* Big enough as *arg is \0 terminated */ |
2695 | - num= internal::my_strtod(arg, &end, &error); |
2696 | - if (end[0] != 0 || error) |
2697 | - { |
2698 | - fprintf(stderr, |
2699 | - _("%s: ERROR: Invalid decimal value for option '%s'\n"), |
2700 | - internal::my_progname, optp->name); |
2701 | - *err= EXIT_ARGUMENT_INVALID; |
2702 | - return 0.0; |
2703 | - } |
2704 | - if (optp->max_value && num > (double) optp->max_value) |
2705 | - num= (double) optp->max_value; |
2706 | - return max(num, (double) optp->min_value); |
2707 | -} |
2708 | - |
2709 | -/* |
2710 | - Init one value to it's default values |
2711 | - |
2712 | - SYNOPSIS |
2713 | - init_one_value() |
2714 | - option Option to initialize |
2715 | - value Pointer to variable |
2716 | - */ |
2717 | - |
2718 | -static void init_one_value(const struct my_option *option, char** variable, |
2719 | - int64_t value) |
2720 | -{ |
2721 | - switch ((option->var_type & GET_TYPE_MASK)) { |
2722 | - case GET_BOOL: |
2723 | - *((bool*) variable)= (bool) value; |
2724 | - break; |
2725 | - case GET_INT: |
2726 | - *((int*) variable)= (int) value; |
2727 | - break; |
2728 | - case GET_UINT: |
2729 | - case GET_ENUM: |
2730 | - *((uint*) variable)= (uint32_t) value; |
2731 | - break; |
2732 | - case GET_LONG: |
2733 | - *((long*) variable)= (long) value; |
2734 | - break; |
2735 | - case GET_UINT32: |
2736 | - *((uint32_t*) variable)= (uint32_t) value; |
2737 | - break; |
2738 | - case GET_ULONG_IS_FAIL: |
2739 | - *((ulong*) variable)= (ulong) value; |
2740 | - break; |
2741 | - case GET_LL: |
2742 | - *((int64_t*) variable)= (int64_t) value; |
2743 | - break; |
2744 | - case GET_SIZE: |
2745 | - *((size_t*) variable)= (size_t) value; |
2746 | - break; |
2747 | - case GET_ULL: |
2748 | - case GET_SET: |
2749 | - case GET_UINT64: |
2750 | - *((uint64_t*) variable)= (uint64_t) value; |
2751 | - break; |
2752 | - case GET_DOUBLE: |
2753 | - *((double*) variable)= (double) value; |
2754 | - break; |
2755 | - case GET_STR: |
2756 | - /* |
2757 | - Do not clear variable value if it has no default value. |
2758 | - The default value may already be set. |
2759 | -NOTE: To avoid compiler warnings, we first cast int64_t to intptr_t, |
2760 | -so that the value has the same size as a pointer. |
2761 | - */ |
2762 | - if ((char*) (intptr_t) value) |
2763 | - *((char**) variable)= (char*) (intptr_t) value; |
2764 | - break; |
2765 | - case GET_STR_ALLOC: |
2766 | - /* |
2767 | - Do not clear variable value if it has no default value. |
2768 | - The default value may already be set. |
2769 | -NOTE: To avoid compiler warnings, we first cast int64_t to intptr_t, |
2770 | -so that the value has the same size as a pointer. |
2771 | - */ |
2772 | - if ((char*) (intptr_t) value) |
2773 | - { |
2774 | - free((*(char**) variable)); |
2775 | - char *tmpptr= strdup((char *) (intptr_t) value); |
2776 | - if (tmpptr != NULL) |
2777 | - *((char**) variable)= tmpptr; |
2778 | - } |
2779 | - break; |
2780 | - default: /* dummy default to avoid compiler warnings */ |
2781 | - break; |
2782 | - } |
2783 | - return; |
2784 | -} |
2785 | - |
2786 | - |
2787 | -/* |
2788 | - Init one value to it's default values |
2789 | - |
2790 | - SYNOPSIS |
2791 | - init_one_value() |
2792 | - option Option to initialize |
2793 | - value Pointer to variable |
2794 | - */ |
2795 | - |
2796 | -static void fini_one_value(const struct my_option *option, char **variable, |
2797 | - int64_t) |
2798 | -{ |
2799 | - switch ((option->var_type & GET_TYPE_MASK)) { |
2800 | - case GET_STR_ALLOC: |
2801 | - free((*(char**) variable)); |
2802 | - *((char**) variable)= NULL; |
2803 | - break; |
2804 | - default: /* dummy default to avoid compiler warnings */ |
2805 | - break; |
2806 | - } |
2807 | - return; |
2808 | -} |
2809 | - |
2810 | - |
2811 | -void my_cleanup_options(const struct my_option *options) |
2812 | -{ |
2813 | - init_variables(options, fini_one_value); |
2814 | -} |
2815 | - |
2816 | - |
2817 | -/* |
2818 | - initialize all variables to their default values |
2819 | - |
2820 | - SYNOPSIS |
2821 | - init_variables() |
2822 | - options Array of options |
2823 | - |
2824 | - NOTES |
2825 | - We will initialize the value that is pointed to by options->value. |
2826 | - If the value is of type GET_ASK_ADDR, we will also ask for the address |
2827 | - for a value and initialize. |
2828 | - */ |
2829 | - |
2830 | -static void init_variables(const struct my_option *options, |
2831 | - init_func_p init_one_value) |
2832 | -{ |
2833 | - for (; options->name; options++) |
2834 | - { |
2835 | - char* *variable; |
2836 | - /* |
2837 | - We must set u_max_value first as for some variables |
2838 | - options->u_max_value == options->value and in this case we want to |
2839 | - set the value to default value. |
2840 | - */ |
2841 | - if (options->u_max_value) |
2842 | - init_one_value(options, options->u_max_value, options->max_value); |
2843 | - if (options->value) |
2844 | - init_one_value(options, options->value, options->def_value); |
2845 | - if (options->var_type & GET_ASK_ADDR && |
2846 | - (variable= (*getopt_get_addr)("", 0, options))) |
2847 | - init_one_value(options, variable, options->def_value); |
2848 | - } |
2849 | - return; |
2850 | -} |
2851 | - |
2852 | - |
2853 | -/* |
2854 | -function: my_print_options |
2855 | - |
2856 | -Print help for all options and variables. |
2857 | - */ |
2858 | - |
2859 | -void my_print_help(const struct my_option *options) |
2860 | -{ |
2861 | - uint32_t col, name_space= 22, comment_space= 57; |
2862 | - const char *line_end; |
2863 | - const struct my_option *optp; |
2864 | - |
2865 | - for (optp= options; optp->id; optp++) |
2866 | - { |
2867 | - if (optp->id < 256) |
2868 | - { |
2869 | - printf(" -%c%s", optp->id, strlen(optp->name) ? ", " : " "); |
2870 | - col= 6; |
2871 | - } |
2872 | - else |
2873 | - { |
2874 | - printf(" "); |
2875 | - col= 2; |
2876 | - } |
2877 | - if (strlen(optp->name)) |
2878 | - { |
2879 | - printf("--%s", optp->name); |
2880 | - col+= 2 + (uint32_t) strlen(optp->name); |
2881 | - if ((optp->var_type & GET_TYPE_MASK) == GET_STR || |
2882 | - (optp->var_type & GET_TYPE_MASK) == GET_STR_ALLOC) |
2883 | - { |
2884 | - printf("%s=name%s ", optp->arg_type == OPT_ARG ? "[" : "", |
2885 | - optp->arg_type == OPT_ARG ? "]" : ""); |
2886 | - col+= (optp->arg_type == OPT_ARG) ? 8 : 6; |
2887 | - } |
2888 | - else if ((optp->var_type & GET_TYPE_MASK) == GET_NO_ARG || |
2889 | - (optp->var_type & GET_TYPE_MASK) == GET_BOOL) |
2890 | - { |
2891 | - putchar(' '); |
2892 | - col++; |
2893 | - } |
2894 | - else |
2895 | - { |
2896 | - printf("%s=#%s ", optp->arg_type == OPT_ARG ? "[" : "", |
2897 | - optp->arg_type == OPT_ARG ? "]" : ""); |
2898 | - col+= (optp->arg_type == OPT_ARG) ? 5 : 3; |
2899 | - } |
2900 | - if (col > name_space && optp->comment && *optp->comment) |
2901 | - { |
2902 | - putchar('\n'); |
2903 | - col= 0; |
2904 | - } |
2905 | - } |
2906 | - for (; col < name_space; col++) |
2907 | - putchar(' '); |
2908 | - if (optp->comment && *optp->comment) |
2909 | - { |
2910 | - const char *comment= _(optp->comment), *end= strchr(comment, '\0'); |
2911 | - |
2912 | - while ((uint32_t) (end - comment) > comment_space) |
2913 | - { |
2914 | - for (line_end= comment + comment_space; *line_end != ' '; line_end--) |
2915 | - {} |
2916 | - for (; comment != line_end; comment++) |
2917 | - putchar(*comment); |
2918 | - comment++; /* skip the space, as a newline will take it's place now */ |
2919 | - putchar('\n'); |
2920 | - for (col= 0; col < name_space; col++) |
2921 | - putchar(' '); |
2922 | - } |
2923 | - printf("%s", comment); |
2924 | - } |
2925 | - putchar('\n'); |
2926 | - if ((optp->var_type & GET_TYPE_MASK) == GET_NO_ARG || |
2927 | - (optp->var_type & GET_TYPE_MASK) == GET_BOOL) |
2928 | - { |
2929 | - if (optp->def_value != 0) |
2930 | - { |
2931 | - printf(_("%*s(Defaults to on; use --skip-%s to disable.)\n"), name_space, "", optp->name); |
2932 | - } |
2933 | - } |
2934 | - } |
2935 | -} |
2936 | - |
2937 | - |
2938 | -/* |
2939 | -function: my_print_options |
2940 | - |
2941 | -Print variables. |
2942 | - */ |
2943 | - |
2944 | -void my_print_variables(const struct my_option *options) |
2945 | -{ |
2946 | - uint32_t name_space= 34, length, nr; |
2947 | - uint64_t bit, llvalue; |
2948 | - char buff[255]; |
2949 | - const struct my_option *optp; |
2950 | - |
2951 | - printf(_("\nVariables (--variable-name=value)\n" |
2952 | - "and boolean options {false|true} Value (after reading options)\n" |
2953 | - "--------------------------------- -----------------------------\n")); |
2954 | - for (optp= options; optp->id; optp++) |
2955 | - { |
2956 | - char* *value= (optp->var_type & GET_ASK_ADDR ? |
2957 | - (*getopt_get_addr)("", 0, optp) : optp->value); |
2958 | - if (value) |
2959 | - { |
2960 | - printf("%s ", optp->name); |
2961 | - length= (uint32_t) strlen(optp->name)+1; |
2962 | - for (; length < name_space; length++) |
2963 | - putchar(' '); |
2964 | - switch ((optp->var_type & GET_TYPE_MASK)) { |
2965 | - case GET_SET: |
2966 | - if (!(llvalue= *(uint64_t*) value)) |
2967 | - printf("%s\n", _("(No default value)")); |
2968 | - else |
2969 | - for (nr= 0, bit= 1; llvalue && nr < optp->typelib->count; nr++, bit<<=1) |
2970 | - { |
2971 | - if (!(bit & llvalue)) |
2972 | - continue; |
2973 | - llvalue&= ~bit; |
2974 | - printf( llvalue ? "%s," : "%s\n", get_type(optp->typelib, nr)); |
2975 | - } |
2976 | - break; |
2977 | - case GET_ENUM: |
2978 | - printf("%s\n", get_type(optp->typelib, *(uint*) value)); |
2979 | - break; |
2980 | - case GET_STR: |
2981 | - case GET_STR_ALLOC: /* fall through */ |
2982 | - printf("%s\n", *((char**) value) ? *((char**) value) : |
2983 | - _("(No default value)")); |
2984 | - break; |
2985 | - case GET_BOOL: |
2986 | - printf("%s\n", *((bool*) value) ? _("true") : _("false")); |
2987 | - break; |
2988 | - case GET_INT: |
2989 | - printf("%d\n", *((int*) value)); |
2990 | - break; |
2991 | - case GET_UINT: |
2992 | - printf("%d\n", *((uint*) value)); |
2993 | - break; |
2994 | - case GET_LONG: |
2995 | - printf("%ld\n", *((long*) value)); |
2996 | - break; |
2997 | - case GET_UINT32: |
2998 | - printf("%u\n", *((uint32_t*) value)); |
2999 | - break; |
3000 | - case GET_ULONG_IS_FAIL: |
3001 | - printf("%lu\n", *((ulong*) value)); |
3002 | - break; |
3003 | - case GET_SIZE: |
3004 | - internal::int64_t2str((uint64_t)(*(size_t*)value), buff, 10); |
3005 | - printf("%s\n", buff); |
3006 | - break; |
3007 | - case GET_LL: |
3008 | - printf("%s\n", internal::llstr(*((int64_t*) value), buff)); |
3009 | - break; |
3010 | - case GET_ULL: |
3011 | - case GET_UINT64: |
3012 | - internal::int64_t2str(*((uint64_t*) value), buff, 10); |
3013 | - printf("%s\n", buff); |
3014 | - break; |
3015 | - case GET_DOUBLE: |
3016 | - printf("%g\n", *(double*) value); |
3017 | - break; |
3018 | - default: |
3019 | - printf(_("(Disabled)\n")); |
3020 | - break; |
3021 | - } |
3022 | - } |
3023 | - } |
3024 | -} |
3025 | - |
3026 | -} /* namespace drizzled */ |
3027 | |
3028 | === removed file 'drizzled/my_getopt.h' |
3029 | --- drizzled/my_getopt.h 2010-03-25 09:08:56 +0000 |
3030 | +++ drizzled/my_getopt.h 1970-01-01 00:00:00 +0000 |
3031 | @@ -1,97 +0,0 @@ |
3032 | -/* Copyright (C) 2002-2004 MySQL AB |
3033 | - |
3034 | - This program is free software; you can redistribute it and/or modify |
3035 | - it under the terms of the GNU General Public License as published by |
3036 | - the Free Software Foundation; version 2 of the License. |
3037 | - |
3038 | - This program is distributed in the hope that it will be useful, |
3039 | - but WITHOUT ANY WARRANTY; without even the implied warranty of |
3040 | - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3041 | - GNU General Public License for more details. |
3042 | - |
3043 | - You should have received a copy of the GNU General Public License |
3044 | - along with this program; if not, write to the Free Software |
3045 | - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ |
3046 | - |
3047 | -#ifndef DRIZZLED_MY_GETOPT_H |
3048 | -#define DRIZZLED_MY_GETOPT_H |
3049 | - |
3050 | -#include "drizzled/typelib.h" |
3051 | - |
3052 | -namespace drizzled |
3053 | -{ |
3054 | - |
3055 | -#define GET_NO_ARG 1 |
3056 | -#define GET_BOOL 2 |
3057 | -#define GET_INT 3 |
3058 | -#define GET_UINT 4 |
3059 | -#define GET_LONG 5 |
3060 | -#define GET_UINT32 6 |
3061 | -#define GET_LL 7 |
3062 | -#define GET_ULL 8 |
3063 | -#define GET_STR 9 |
3064 | -#define GET_STR_ALLOC 10 |
3065 | -#define GET_DISABLED 11 |
3066 | -#define GET_ENUM 12 |
3067 | -#define GET_SET 13 |
3068 | -#define GET_DOUBLE 14 |
3069 | -#define GET_SIZE 15 |
3070 | -#define GET_UINT64 16 |
3071 | -#define GET_ULONG_IS_FAIL 17 |
3072 | - |
3073 | -#define GET_ASK_ADDR 128 |
3074 | -#define GET_TYPE_MASK 127 |
3075 | - |
3076 | -enum loglevel { |
3077 | - ERROR_LEVEL, |
3078 | - WARNING_LEVEL, |
3079 | - INFORMATION_LEVEL |
3080 | -}; |
3081 | - |
3082 | -enum get_opt_arg_type { NO_ARG, OPT_ARG, REQUIRED_ARG }; |
3083 | - |
3084 | -struct st_typelib; |
3085 | - |
3086 | -struct my_option |
3087 | -{ |
3088 | - const char *name; /* Name of the option */ |
3089 | - int id; /* unique id or short option */ |
3090 | - const char *comment; /* option comment, for autom. --help */ |
3091 | - char **value; /* The variable value */ |
3092 | - char **u_max_value; /* The user def. max variable value */ |
3093 | - struct st_typelib *typelib; /* Pointer to possible values */ |
3094 | - uint32_t var_type; |
3095 | - enum get_opt_arg_type arg_type; |
3096 | - int64_t def_value; /* Default value */ |
3097 | - int64_t min_value; /* Min allowed value */ |
3098 | - int64_t max_value; /* Max allowed value */ |
3099 | - int64_t sub_size; /* Subtract this from given value */ |
3100 | - long block_size; /* Value should be a mult. of this */ |
3101 | - void *app_type; /* To be used by an application */ |
3102 | -}; |
3103 | - |
3104 | - |
3105 | -typedef int (* my_get_one_option) (int, const struct my_option *, char * ); |
3106 | -typedef void (* my_error_reporter) (enum loglevel level, const char *format, ... ); |
3107 | -typedef char ** (*getopt_get_addr_func)(const char *, uint32_t, const struct my_option *); |
3108 | - |
3109 | -extern char *disabled_my_option; |
3110 | -extern bool my_getopt_skip_unknown; |
3111 | -extern my_error_reporter my_getopt_error_reporter; |
3112 | - |
3113 | -extern int handle_options (int *argc, char ***argv, |
3114 | - const struct my_option *longopts, my_get_one_option); |
3115 | -extern void my_cleanup_options(const struct my_option *options); |
3116 | -extern void my_print_help(const struct my_option *options); |
3117 | -extern void my_print_variables(const struct my_option *options); |
3118 | - |
3119 | -uint64_t getopt_ull_limit_value(uint64_t num, const struct my_option *optp, |
3120 | - bool *fix); |
3121 | -int64_t getopt_ll_limit_value(int64_t, const struct my_option *, |
3122 | - bool *fix); |
3123 | -bool getopt_compare_strings(const char *s, const char *t, uint32_t length); |
3124 | - |
3125 | -} /* namespace drizzled */ |
3126 | - |
3127 | -#endif /* DRIZZLED_MY_GETOPT_H */ |
3128 | - |
3129 | |
3130 | === modified file 'drizzled/my_getsystime.cc' |
3131 | --- drizzled/my_getsystime.cc 2010-02-04 08:14:46 +0000 |
3132 | +++ drizzled/my_getsystime.cc 2010-04-02 06:48:30 +0000 |
3133 | @@ -23,7 +23,7 @@ |
3134 | */ |
3135 | |
3136 | #include "config.h" |
3137 | -#include "drizzled/my_time.h" |
3138 | +#include "drizzled/drizzle_time.h" |
3139 | |
3140 | #if TIME_WITH_SYS_TIME |
3141 | # include <sys/time.h> |
3142 | |
3143 | === removed file 'drizzled/my_time.cc' |
3144 | --- drizzled/my_time.cc 2010-02-04 08:14:46 +0000 |
3145 | +++ drizzled/my_time.cc 1970-01-01 00:00:00 +0000 |
3146 | @@ -1,1260 +0,0 @@ |
3147 | -/* Copyright (C) 2004-2006 MySQL AB |
3148 | - |
3149 | - This program is free software; you can redistribute it and/or modify |
3150 | - it under the terms of the GNU General Public License as published by |
3151 | - the Free Software Foundation; version 2 of the License. |
3152 | - |
3153 | - This program is distributed in the hope that it will be useful, |
3154 | - but WITHOUT ANY WARRANTY; without even the implied warranty of |
3155 | - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3156 | - GNU General Public License for more details. |
3157 | - |
3158 | - You should have received a copy of the GNU General Public License |
3159 | - along with this program; if not, write to the Free Software |
3160 | - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ |
3161 | - |
3162 | -#include "config.h" |
3163 | - |
3164 | -#include "drizzled/my_time.h" |
3165 | - |
3166 | -#include "drizzled/internal/m_string.h" |
3167 | -#include "drizzled/charset_info.h" |
3168 | -#include <drizzled/util/test.h> |
3169 | -#include "drizzled/definitions.h" |
3170 | - |
3171 | -#include <cstdio> |
3172 | -#include <algorithm> |
3173 | - |
3174 | -using namespace std; |
3175 | - |
3176 | -namespace drizzled |
3177 | -{ |
3178 | - |
3179 | -static int check_time_range(DRIZZLE_TIME *my_time, int *warning); |
3180 | - |
3181 | -/* Windows version of localtime_r() is declared in my_ptrhead.h */ |
3182 | - |
3183 | -uint64_t log_10_int[20]= |
3184 | -{ |
3185 | - 1, 10, 100, 1000, 10000UL, 100000UL, 1000000UL, 10000000UL, |
3186 | - 100000000ULL, 1000000000ULL, 10000000000ULL, 100000000000ULL, |
3187 | - 1000000000000ULL, 10000000000000ULL, 100000000000000ULL, |
3188 | - 1000000000000000ULL, 10000000000000000ULL, 100000000000000000ULL, |
3189 | - 1000000000000000000ULL, 10000000000000000000ULL |
3190 | -}; |
3191 | - |
3192 | - |
3193 | -/* Position for YYYY-DD-MM HH-MM-DD.FFFFFF AM in default format */ |
3194 | - |
3195 | -static unsigned char internal_format_positions[]= |
3196 | -{0, 1, 2, 3, 4, 5, 6, (unsigned char) 255}; |
3197 | - |
3198 | -static char time_separator=':'; |
3199 | - |
3200 | -static uint32_t const days_at_timestart=719528; /* daynr at 1970.01.01 */ |
3201 | -unsigned char days_in_month[]= {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0}; |
3202 | - |
3203 | -/* |
3204 | - Offset of system time zone from UTC in seconds used to speed up |
3205 | - work of my_system_gmt_sec() function. |
3206 | -*/ |
3207 | -static long my_time_zone=0; |
3208 | - |
3209 | - |
3210 | -/* Calc days in one year. works with 0 <= year <= 99 */ |
3211 | - |
3212 | -uint32_t calc_days_in_year(uint32_t year) |
3213 | -{ |
3214 | - return ((year & 3) == 0 && (year%100 || (year%400 == 0 && year)) ? |
3215 | - 366 : 365); |
3216 | -} |
3217 | - |
3218 | -/** |
3219 | - @brief Check datetime value for validity according to flags. |
3220 | - |
3221 | - @param[in] ltime Date to check. |
3222 | - @param[in] not_zero_date ltime is not the zero date |
3223 | - @param[in] flags flags to check |
3224 | - (see str_to_datetime() flags in my_time.h) |
3225 | - @param[out] was_cut set to 2 if value was invalid according to flags. |
3226 | - (Feb 29 in non-leap etc.) This remains unchanged |
3227 | - if value is not invalid. |
3228 | - |
3229 | - @details Here we assume that year and month is ok! |
3230 | - If month is 0 we allow any date. (This only happens if we allow zero |
3231 | - date parts in str_to_datetime()) |
3232 | - Disallow dates with zero year and non-zero month and/or day. |
3233 | - |
3234 | - @return |
3235 | - 0 OK |
3236 | - 1 error |
3237 | -*/ |
3238 | - |
3239 | -bool check_date(const DRIZZLE_TIME *ltime, bool not_zero_date, |
3240 | - uint32_t flags, int *was_cut) |
3241 | -{ |
3242 | - if (not_zero_date) |
3243 | - { |
3244 | - if ((((flags & TIME_NO_ZERO_IN_DATE) || !(flags & TIME_FUZZY_DATE)) && |
3245 | - (ltime->month == 0 || ltime->day == 0)) || |
3246 | - (!(flags & TIME_INVALID_DATES) && |
3247 | - ltime->month && ltime->day > days_in_month[ltime->month-1] && |
3248 | - (ltime->month != 2 || calc_days_in_year(ltime->year) != 366 || |
3249 | - ltime->day != 29))) |
3250 | - { |
3251 | - *was_cut= 2; |
3252 | - return true; |
3253 | - } |
3254 | - } |
3255 | - else if (flags & TIME_NO_ZERO_DATE) |
3256 | - { |
3257 | - /* |
3258 | - We don't set *was_cut here to signal that the problem was a zero date |
3259 | - and not an invalid date |
3260 | - */ |
3261 | - return true; |
3262 | - } |
3263 | - return false; |
3264 | -} |
3265 | - |
3266 | - |
3267 | -/* |
3268 | - Convert a timestamp string to a DRIZZLE_TIME value. |
3269 | - |
3270 | - SYNOPSIS |
3271 | - str_to_datetime() |
3272 | - str String to parse |
3273 | - length Length of string |
3274 | - l_time Date is stored here |
3275 | - flags Bitmap of following items |
3276 | - TIME_FUZZY_DATE Set if we should allow partial dates |
3277 | - TIME_DATETIME_ONLY Set if we only allow full datetimes. |
3278 | - TIME_NO_ZERO_IN_DATE Don't allow partial dates |
3279 | - TIME_NO_ZERO_DATE Don't allow 0000-00-00 date |
3280 | - TIME_INVALID_DATES Allow 2000-02-31 |
3281 | - was_cut 0 Value OK |
3282 | - 1 If value was cut during conversion |
3283 | - 2 check_date(date,flags) considers date invalid |
3284 | - |
3285 | - DESCRIPTION |
3286 | - At least the following formats are recogniced (based on number of digits) |
3287 | - YYMMDD, YYYYMMDD, YYMMDDHHMMSS, YYYYMMDDHHMMSS |
3288 | - YY-MM-DD, YYYY-MM-DD, YY-MM-DD HH.MM.SS |
3289 | - YYYYMMDDTHHMMSS where T is a the character T (ISO8601) |
3290 | - Also dates where all parts are zero are allowed |
3291 | - |
3292 | - The second part may have an optional .###### fraction part. |
3293 | - |
3294 | - NOTES |
3295 | - This function should work with a format position vector as long as the |
3296 | - following things holds: |
3297 | - - All date are kept together and all time parts are kept together |
3298 | - - Date and time parts must be separated by blank |
3299 | - - Second fractions must come after second part and be separated |
3300 | - by a '.'. (The second fractions are optional) |
3301 | - - AM/PM must come after second fractions (or after seconds if no fractions) |
3302 | - - Year must always been specified. |
3303 | - - If time is before date, then we will use datetime format only if |
3304 | - the argument consist of two parts, separated by space. |
3305 | - Otherwise we will assume the argument is a date. |
3306 | - - The hour part must be specified in hour-minute-second order. |
3307 | - |
3308 | - RETURN VALUES |
3309 | - DRIZZLE_TIMESTAMP_NONE String wasn't a timestamp, like |
3310 | - [DD [HH:[MM:[SS]]]].fraction. |
3311 | - l_time is not changed. |
3312 | - DRIZZLE_TIMESTAMP_DATE DATE string (YY MM and DD parts ok) |
3313 | - DRIZZLE_TIMESTAMP_DATETIME Full timestamp |
3314 | - DRIZZLE_TIMESTAMP_ERROR Timestamp with wrong values. |
3315 | - All elements in l_time is set to 0 |
3316 | -*/ |
3317 | - |
3318 | -#define MAX_DATE_PARTS 8 |
3319 | - |
3320 | -enum enum_drizzle_timestamp_type |
3321 | -str_to_datetime(const char *str, uint32_t length, DRIZZLE_TIME *l_time, |
3322 | - uint32_t flags, int *was_cut) |
3323 | -{ |
3324 | - uint32_t field_length, year_length=4, digits, i, number_of_fields; |
3325 | - uint32_t date[MAX_DATE_PARTS], date_len[MAX_DATE_PARTS]; |
3326 | - uint32_t add_hours= 0, start_loop; |
3327 | - uint32_t not_zero_date, allow_space; |
3328 | - bool is_internal_format; |
3329 | - const char *pos, *last_field_pos=NULL; |
3330 | - const char *end=str+length; |
3331 | - const unsigned char *format_position; |
3332 | - bool found_delimitier= 0, found_space= 0; |
3333 | - uint32_t frac_pos, frac_len; |
3334 | - |
3335 | - *was_cut= 0; |
3336 | - |
3337 | - /* Skip space at start */ |
3338 | - for (; str != end && my_isspace(&my_charset_utf8_general_ci, *str) ; str++) |
3339 | - ; |
3340 | - if (str == end || ! my_isdigit(&my_charset_utf8_general_ci, *str)) |
3341 | - { |
3342 | - *was_cut= 1; |
3343 | - return(DRIZZLE_TIMESTAMP_NONE); |
3344 | - } |
3345 | - |
3346 | - is_internal_format= 0; |
3347 | - /* This has to be changed if want to activate different timestamp formats */ |
3348 | - format_position= internal_format_positions; |
3349 | - |
3350 | - /* |
3351 | - Calculate number of digits in first part. |
3352 | - If length= 8 or >= 14 then year is of format YYYY. |
3353 | - (YYYY-MM-DD, YYYYMMDD, YYYYYMMDDHHMMSS) |
3354 | - */ |
3355 | - for (pos=str; |
3356 | - pos != end && (my_isdigit(&my_charset_utf8_general_ci,*pos) || *pos == 'T'); |
3357 | - pos++) |
3358 | - ; |
3359 | - |
3360 | - digits= (uint32_t) (pos-str); |
3361 | - start_loop= 0; /* Start of scan loop */ |
3362 | - date_len[format_position[0]]= 0; /* Length of year field */ |
3363 | - if (pos == end || *pos == '.') |
3364 | - { |
3365 | - /* Found date in internal format (only numbers like YYYYMMDD) */ |
3366 | - year_length= (digits == 4 || digits == 8 || digits >= 14) ? 4 : 2; |
3367 | - field_length= year_length; |
3368 | - is_internal_format= 1; |
3369 | - format_position= internal_format_positions; |
3370 | - } |
3371 | - else |
3372 | - { |
3373 | - if (format_position[0] >= 3) /* If year is after HHMMDD */ |
3374 | - { |
3375 | - /* |
3376 | - If year is not in first part then we have to determinate if we got |
3377 | - a date field or a datetime field. |
3378 | - We do this by checking if there is two numbers separated by |
3379 | - space in the input. |
3380 | - */ |
3381 | - while (pos < end && !my_isspace(&my_charset_utf8_general_ci, *pos)) |
3382 | - pos++; |
3383 | - while (pos < end && !my_isdigit(&my_charset_utf8_general_ci, *pos)) |
3384 | - pos++; |
3385 | - if (pos == end) |
3386 | - { |
3387 | - if (flags & TIME_DATETIME_ONLY) |
3388 | - { |
3389 | - *was_cut= 1; |
3390 | - return(DRIZZLE_TIMESTAMP_NONE); /* Can't be a full datetime */ |
3391 | - } |
3392 | - /* Date field. Set hour, minutes and seconds to 0 */ |
3393 | - date[0]= date[1]= date[2]= date[3]= date[4]= 0; |
3394 | - start_loop= 5; /* Start with first date part */ |
3395 | - } |
3396 | - } |
3397 | - |
3398 | - field_length= format_position[0] == 0 ? 4 : 2; |
3399 | - } |
3400 | - |
3401 | - /* |
3402 | - Only allow space in the first "part" of the datetime field and: |
3403 | - - after days, part seconds |
3404 | - - before and after AM/PM (handled by code later) |
3405 | - |
3406 | - 2003-03-03 20:00:20 AM |
3407 | - 20:00:20.000000 AM 03-03-2000 |
3408 | - */ |
3409 | - i= max((uint32_t) format_position[0], (uint32_t) format_position[1]); |
3410 | - set_if_bigger(i, (uint32_t) format_position[2]); |
3411 | - allow_space= ((1 << i) | (1 << format_position[6])); |
3412 | - allow_space&= (1 | 2 | 4 | 8); |
3413 | - |
3414 | - not_zero_date= 0; |
3415 | - for (i = start_loop; |
3416 | - i < MAX_DATE_PARTS-1 && str != end && |
3417 | - my_isdigit(&my_charset_utf8_general_ci,*str); |
3418 | - i++) |
3419 | - { |
3420 | - const char *start= str; |
3421 | - uint32_t tmp_value= (uint32_t) (unsigned char) (*str++ - '0'); |
3422 | - while (str != end && my_isdigit(&my_charset_utf8_general_ci,str[0]) && |
3423 | - (!is_internal_format || --field_length)) |
3424 | - { |
3425 | - tmp_value=tmp_value*10 + (uint32_t) (unsigned char) (*str - '0'); |
3426 | - str++; |
3427 | - } |
3428 | - date_len[i]= (uint32_t) (str - start); |
3429 | - if (tmp_value > 999999) /* Impossible date part */ |
3430 | - { |
3431 | - *was_cut= 1; |
3432 | - return(DRIZZLE_TIMESTAMP_NONE); |
3433 | - } |
3434 | - date[i]=tmp_value; |
3435 | - not_zero_date|= tmp_value; |
3436 | - |
3437 | - /* Length of next field */ |
3438 | - field_length= format_position[i+1] == 0 ? 4 : 2; |
3439 | - |
3440 | - if ((last_field_pos= str) == end) |
3441 | - { |
3442 | - i++; /* Register last found part */ |
3443 | - break; |
3444 | - } |
3445 | - /* Allow a 'T' after day to allow CCYYMMDDT type of fields */ |
3446 | - if (i == format_position[2] && *str == 'T') |
3447 | - { |
3448 | - str++; /* ISO8601: CCYYMMDDThhmmss */ |
3449 | - continue; |
3450 | - } |
3451 | - if (i == format_position[5]) /* Seconds */ |
3452 | - { |
3453 | - if (*str == '.') /* Followed by part seconds */ |
3454 | - { |
3455 | - str++; |
3456 | - field_length= 6; /* 6 digits */ |
3457 | - } |
3458 | - continue; |
3459 | - } |
3460 | - while (str != end && |
3461 | - (my_ispunct(&my_charset_utf8_general_ci,*str) || |
3462 | - my_isspace(&my_charset_utf8_general_ci,*str))) |
3463 | - { |
3464 | - if (my_isspace(&my_charset_utf8_general_ci,*str)) |
3465 | - { |
3466 | - if (!(allow_space & (1 << i))) |
3467 | - { |
3468 | - *was_cut= 1; |
3469 | - return(DRIZZLE_TIMESTAMP_NONE); |
3470 | - } |
3471 | - found_space= 1; |
3472 | - } |
3473 | - str++; |
3474 | - found_delimitier= 1; /* Should be a 'normal' date */ |
3475 | - } |
3476 | - /* Check if next position is AM/PM */ |
3477 | - if (i == format_position[6]) /* Seconds, time for AM/PM */ |
3478 | - { |
3479 | - i++; /* Skip AM/PM part */ |
3480 | - if (format_position[7] != 255) /* If using AM/PM */ |
3481 | - { |
3482 | - if (str+2 <= end && (str[1] == 'M' || str[1] == 'm')) |
3483 | - { |
3484 | - if (str[0] == 'p' || str[0] == 'P') |
3485 | - add_hours= 12; |
3486 | - else if (str[0] != 'a' || str[0] != 'A') |
3487 | - continue; /* Not AM/PM */ |
3488 | - str+= 2; /* Skip AM/PM */ |
3489 | - /* Skip space after AM/PM */ |
3490 | - while (str != end && my_isspace(&my_charset_utf8_general_ci,*str)) |
3491 | - str++; |
3492 | - } |
3493 | - } |
3494 | - } |
3495 | - last_field_pos= str; |
3496 | - } |
3497 | - if (found_delimitier && !found_space && (flags & TIME_DATETIME_ONLY)) |
3498 | - { |
3499 | - *was_cut= 1; |
3500 | - return(DRIZZLE_TIMESTAMP_NONE); /* Can't be a datetime */ |
3501 | - } |
3502 | - |
3503 | - str= last_field_pos; |
3504 | - |
3505 | - number_of_fields= i - start_loop; |
3506 | - while (i < MAX_DATE_PARTS) |
3507 | - { |
3508 | - date_len[i]= 0; |
3509 | - date[i++]= 0; |
3510 | - } |
3511 | - |
3512 | - if (!is_internal_format) |
3513 | - { |
3514 | - year_length= date_len[(uint32_t) format_position[0]]; |
3515 | - if (!year_length) /* Year must be specified */ |
3516 | - { |
3517 | - *was_cut= 1; |
3518 | - return(DRIZZLE_TIMESTAMP_NONE); |
3519 | - } |
3520 | - |
3521 | - l_time->year= date[(uint32_t) format_position[0]]; |
3522 | - l_time->month= date[(uint32_t) format_position[1]]; |
3523 | - l_time->day= date[(uint32_t) format_position[2]]; |
3524 | - l_time->hour= date[(uint32_t) format_position[3]]; |
3525 | - l_time->minute= date[(uint32_t) format_position[4]]; |
3526 | - l_time->second= date[(uint32_t) format_position[5]]; |
3527 | - |
3528 | - frac_pos= (uint32_t) format_position[6]; |
3529 | - frac_len= date_len[frac_pos]; |
3530 | - if (frac_len < 6) |
3531 | - date[frac_pos]*= (uint32_t) log_10_int[6 - frac_len]; |
3532 | - l_time->second_part= date[frac_pos]; |
3533 | - |
3534 | - if (format_position[7] != (unsigned char) 255) |
3535 | - { |
3536 | - if (l_time->hour > 12) |
3537 | - { |
3538 | - *was_cut= 1; |
3539 | - goto err; |
3540 | - } |
3541 | - l_time->hour= l_time->hour%12 + add_hours; |
3542 | - } |
3543 | - } |
3544 | - else |
3545 | - { |
3546 | - l_time->year= date[0]; |
3547 | - l_time->month= date[1]; |
3548 | - l_time->day= date[2]; |
3549 | - l_time->hour= date[3]; |
3550 | - l_time->minute= date[4]; |
3551 | - l_time->second= date[5]; |
3552 | - if (date_len[6] < 6) |
3553 | - date[6]*= (uint32_t) log_10_int[6 - date_len[6]]; |
3554 | - l_time->second_part=date[6]; |
3555 | - } |
3556 | - l_time->neg= 0; |
3557 | - |
3558 | - if (year_length == 2 && not_zero_date) |
3559 | - l_time->year+= (l_time->year < YY_PART_YEAR ? 2000 : 1900); |
3560 | - |
3561 | - if (number_of_fields < 3 || |
3562 | - l_time->year > 9999 || l_time->month > 12 || |
3563 | - l_time->day > 31 || l_time->hour > 23 || |
3564 | - l_time->minute > 59 || l_time->second > 59) |
3565 | - { |
3566 | - /* Only give warning for a zero date if there is some garbage after */ |
3567 | - if (!not_zero_date) /* If zero date */ |
3568 | - { |
3569 | - for (; str != end ; str++) |
3570 | - { |
3571 | - if (!my_isspace(&my_charset_utf8_general_ci, *str)) |
3572 | - { |
3573 | - not_zero_date= 1; /* Give warning */ |
3574 | - break; |
3575 | - } |
3576 | - } |
3577 | - } |
3578 | - *was_cut= test(not_zero_date); |
3579 | - goto err; |
3580 | - } |
3581 | - |
3582 | - if (check_date(l_time, not_zero_date != 0, flags, was_cut)) |
3583 | - goto err; |
3584 | - |
3585 | - l_time->time_type= (number_of_fields <= 3 ? |
3586 | - DRIZZLE_TIMESTAMP_DATE : DRIZZLE_TIMESTAMP_DATETIME); |
3587 | - |
3588 | - for (; str != end ; str++) |
3589 | - { |
3590 | - if (!my_isspace(&my_charset_utf8_general_ci,*str)) |
3591 | - { |
3592 | - *was_cut= 1; |
3593 | - break; |
3594 | - } |
3595 | - } |
3596 | - |
3597 | - return(l_time->time_type= |
3598 | - (number_of_fields <= 3 ? DRIZZLE_TIMESTAMP_DATE : |
3599 | - DRIZZLE_TIMESTAMP_DATETIME)); |
3600 | - |
3601 | -err: |
3602 | - memset(l_time, 0, sizeof(*l_time)); |
3603 | - return(DRIZZLE_TIMESTAMP_ERROR); |
3604 | -} |
3605 | - |
3606 | - |
3607 | -/* |
3608 | - Convert a time string to a DRIZZLE_TIME struct. |
3609 | - |
3610 | - SYNOPSIS |
3611 | - str_to_time() |
3612 | - str A string in full TIMESTAMP format or |
3613 | - [-] DAYS [H]H:MM:SS, [H]H:MM:SS, [M]M:SS, [H]HMMSS, |
3614 | - [M]MSS or [S]S |
3615 | - There may be an optional [.second_part] after seconds |
3616 | - length Length of str |
3617 | - l_time Store result here |
3618 | - warning Set DRIZZLE_TIME_WARN_TRUNCATED flag if the input string |
3619 | - was cut during conversion, and/or |
3620 | - DRIZZLE_TIME_WARN_OUT_OF_RANGE flag, if the value is |
3621 | - out of range. |
3622 | - |
3623 | - NOTES |
3624 | - Because of the extra days argument, this function can only |
3625 | - work with times where the time arguments are in the above order. |
3626 | - |
3627 | - RETURN |
3628 | - 0 ok |
3629 | - 1 error |
3630 | -*/ |
3631 | - |
3632 | -bool str_to_time(const char *str, uint32_t length, DRIZZLE_TIME *l_time, |
3633 | - int *warning) |
3634 | -{ |
3635 | - uint32_t date[5]; |
3636 | - uint64_t value; |
3637 | - const char *end=str+length, *end_of_days; |
3638 | - bool found_days,found_hours; |
3639 | - uint32_t state; |
3640 | - |
3641 | - l_time->neg=0; |
3642 | - *warning= 0; |
3643 | - for (; str != end && my_isspace(&my_charset_utf8_general_ci,*str) ; str++) |
3644 | - length--; |
3645 | - if (str != end && *str == '-') |
3646 | - { |
3647 | - l_time->neg=1; |
3648 | - str++; |
3649 | - length--; |
3650 | - } |
3651 | - if (str == end) |
3652 | - return 1; |
3653 | - |
3654 | - /* Check first if this is a full TIMESTAMP */ |
3655 | - if (length >= 12) |
3656 | - { /* Probably full timestamp */ |
3657 | - int was_cut; |
3658 | - enum enum_drizzle_timestamp_type |
3659 | - res= str_to_datetime(str, length, l_time, |
3660 | - (TIME_FUZZY_DATE | TIME_DATETIME_ONLY), &was_cut); |
3661 | - if ((int) res >= (int) DRIZZLE_TIMESTAMP_ERROR) |
3662 | - { |
3663 | - if (was_cut) |
3664 | - *warning|= DRIZZLE_TIME_WARN_TRUNCATED; |
3665 | - return res == DRIZZLE_TIMESTAMP_ERROR; |
3666 | - } |
3667 | - } |
3668 | - |
3669 | - /* Not a timestamp. Try to get this as a DAYS_TO_SECOND string */ |
3670 | - for (value=0; str != end && my_isdigit(&my_charset_utf8_general_ci,*str) ; str++) |
3671 | - value=value*10L + (long) (*str - '0'); |
3672 | - |
3673 | - /* Skip all space after 'days' */ |
3674 | - end_of_days= str; |
3675 | - for (; str != end && my_isspace(&my_charset_utf8_general_ci, str[0]) ; str++) |
3676 | - ; |
3677 | - |
3678 | - found_days=found_hours=0; |
3679 | - if ((uint32_t) (end-str) > 1 && str != end_of_days && |
3680 | - my_isdigit(&my_charset_utf8_general_ci, *str)) |
3681 | - { /* Found days part */ |
3682 | - date[0]= (uint32_t) value; |
3683 | - state= 1; /* Assume next is hours */ |
3684 | - found_days= 1; |
3685 | - } |
3686 | - else if ((end-str) > 1 && *str == time_separator && |
3687 | - my_isdigit(&my_charset_utf8_general_ci, str[1])) |
3688 | - { |
3689 | - date[0]= 0; /* Assume we found hours */ |
3690 | - date[1]= (uint32_t) value; |
3691 | - state=2; |
3692 | - found_hours=1; |
3693 | - str++; /* skip ':' */ |
3694 | - } |
3695 | - else |
3696 | - { |
3697 | - /* String given as one number; assume HHMMSS format */ |
3698 | - date[0]= 0; |
3699 | - date[1]= (uint32_t) (value/10000); |
3700 | - date[2]= (uint32_t) (value/100 % 100); |
3701 | - date[3]= (uint32_t) (value % 100); |
3702 | - state=4; |
3703 | - goto fractional; |
3704 | - } |
3705 | - |
3706 | - /* Read hours, minutes and seconds */ |
3707 | - for (;;) |
3708 | - { |
3709 | - for (value=0; str != end && my_isdigit(&my_charset_utf8_general_ci,*str) ; str++) |
3710 | - value=value*10L + (long) (*str - '0'); |
3711 | - date[state++]= (uint32_t) value; |
3712 | - if (state == 4 || (end-str) < 2 || *str != time_separator || |
3713 | - !my_isdigit(&my_charset_utf8_general_ci,str[1])) |
3714 | - break; |
3715 | - str++; /* Skip time_separator (':') */ |
3716 | - } |
3717 | - |
3718 | - if (state != 4) |
3719 | - { /* Not HH:MM:SS */ |
3720 | - /* Fix the date to assume that seconds was given */ |
3721 | - if (!found_hours && !found_days) |
3722 | - { |
3723 | - internal::bmove_upp((unsigned char*) (date+4), (unsigned char*) (date+state), |
3724 | - sizeof(long)*(state-1)); |
3725 | - memset(date, 0, sizeof(long)*(4-state)); |
3726 | - } |
3727 | - else |
3728 | - memset(date+state, 0, sizeof(long)*(4-state)); |
3729 | - } |
3730 | - |
3731 | -fractional: |
3732 | - /* Get fractional second part */ |
3733 | - if ((end-str) >= 2 && *str == '.' && my_isdigit(&my_charset_utf8_general_ci,str[1])) |
3734 | - { |
3735 | - int field_length= 5; |
3736 | - str++; value=(uint32_t) (unsigned char) (*str - '0'); |
3737 | - while (++str != end && my_isdigit(&my_charset_utf8_general_ci, *str)) |
3738 | - { |
3739 | - if (field_length-- > 0) |
3740 | - value= value*10 + (uint32_t) (unsigned char) (*str - '0'); |
3741 | - } |
3742 | - if (field_length > 0) |
3743 | - value*= (long) log_10_int[field_length]; |
3744 | - else if (field_length < 0) |
3745 | - *warning|= DRIZZLE_TIME_WARN_TRUNCATED; |
3746 | - date[4]= (uint32_t) value; |
3747 | - } |
3748 | - else |
3749 | - date[4]=0; |
3750 | - |
3751 | - /* Check for exponent part: E<gigit> | E<sign><digit> */ |
3752 | - /* (may occur as result of %g formatting of time value) */ |
3753 | - if ((end - str) > 1 && |
3754 | - (*str == 'e' || *str == 'E') && |
3755 | - (my_isdigit(&my_charset_utf8_general_ci, str[1]) || |
3756 | - ((str[1] == '-' || str[1] == '+') && |
3757 | - (end - str) > 2 && |
3758 | - my_isdigit(&my_charset_utf8_general_ci, str[2])))) |
3759 | - return 1; |
3760 | - |
3761 | - if (internal_format_positions[7] != 255) |
3762 | - { |
3763 | - /* Read a possible AM/PM */ |
3764 | - while (str != end && my_isspace(&my_charset_utf8_general_ci, *str)) |
3765 | - str++; |
3766 | - if (str+2 <= end && (str[1] == 'M' || str[1] == 'm')) |
3767 | - { |
3768 | - if (str[0] == 'p' || str[0] == 'P') |
3769 | - { |
3770 | - str+= 2; |
3771 | - date[1]= date[1]%12 + 12; |
3772 | - } |
3773 | - else if (str[0] == 'a' || str[0] == 'A') |
3774 | - str+=2; |
3775 | - } |
3776 | - } |
3777 | - |
3778 | - /* Integer overflow checks */ |
3779 | - if (date[0] > UINT_MAX || date[1] > UINT_MAX || |
3780 | - date[2] > UINT_MAX || date[3] > UINT_MAX || |
3781 | - date[4] > UINT_MAX) |
3782 | - return 1; |
3783 | - |
3784 | - l_time->year= 0; /* For protocol::store_time */ |
3785 | - l_time->month= 0; |
3786 | - l_time->day= date[0]; |
3787 | - l_time->hour= date[1]; |
3788 | - l_time->minute= date[2]; |
3789 | - l_time->second= date[3]; |
3790 | - l_time->second_part= date[4]; |
3791 | - l_time->time_type= DRIZZLE_TIMESTAMP_TIME; |
3792 | - |
3793 | - /* Check if the value is valid and fits into DRIZZLE_TIME range */ |
3794 | - if (check_time_range(l_time, warning)) |
3795 | - return 1; |
3796 | - |
3797 | - /* Check if there is garbage at end of the DRIZZLE_TIME specification */ |
3798 | - if (str != end) |
3799 | - { |
3800 | - do |
3801 | - { |
3802 | - if (!my_isspace(&my_charset_utf8_general_ci,*str)) |
3803 | - { |
3804 | - *warning|= DRIZZLE_TIME_WARN_TRUNCATED; |
3805 | - break; |
3806 | - } |
3807 | - } while (++str != end); |
3808 | - } |
3809 | - return 0; |
3810 | -} |
3811 | - |
3812 | - |
3813 | -/* |
3814 | - Check 'time' value to lie in the DRIZZLE_TIME range |
3815 | - |
3816 | - SYNOPSIS: |
3817 | - check_time_range() |
3818 | - time pointer to DRIZZLE_TIME value |
3819 | - warning set DRIZZLE_TIME_WARN_OUT_OF_RANGE flag if the value is out of range |
3820 | - |
3821 | - DESCRIPTION |
3822 | - If the time value lies outside of the range [-838:59:59, 838:59:59], |
3823 | - set it to the closest endpoint of the range and set |
3824 | - DRIZZLE_TIME_WARN_OUT_OF_RANGE flag in the 'warning' variable. |
3825 | - |
3826 | - RETURN |
3827 | - 0 time value is valid, but was possibly truncated |
3828 | - 1 time value is invalid |
3829 | -*/ |
3830 | - |
3831 | -static int check_time_range(DRIZZLE_TIME *my_time, int *warning) |
3832 | -{ |
3833 | - int64_t hour; |
3834 | - |
3835 | - if (my_time->minute >= 60 || my_time->second >= 60) |
3836 | - return 1; |
3837 | - |
3838 | - hour= my_time->hour + (24*my_time->day); |
3839 | - if (hour <= TIME_MAX_HOUR && |
3840 | - (hour != TIME_MAX_HOUR || my_time->minute != TIME_MAX_MINUTE || |
3841 | - my_time->second != TIME_MAX_SECOND || !my_time->second_part)) |
3842 | - return 0; |
3843 | - |
3844 | - my_time->day= 0; |
3845 | - my_time->hour= TIME_MAX_HOUR; |
3846 | - my_time->minute= TIME_MAX_MINUTE; |
3847 | - my_time->second= TIME_MAX_SECOND; |
3848 | - my_time->second_part= 0; |
3849 | - *warning|= DRIZZLE_TIME_WARN_OUT_OF_RANGE; |
3850 | - return 0; |
3851 | -} |
3852 | - |
3853 | - |
3854 | -/* |
3855 | - Prepare offset of system time zone from UTC for my_system_gmt_sec() func. |
3856 | - |
3857 | - SYNOPSIS |
3858 | - init_time() |
3859 | -*/ |
3860 | -void init_time(void) |
3861 | -{ |
3862 | - time_t seconds; |
3863 | - struct tm *l_time,tm_tmp; |
3864 | - DRIZZLE_TIME my_time; |
3865 | - bool not_used; |
3866 | - |
3867 | - seconds= (time_t) time((time_t*) 0); |
3868 | - localtime_r(&seconds,&tm_tmp); |
3869 | - l_time= &tm_tmp; |
3870 | - my_time_zone= 3600; /* Comp. for -3600 in my_gmt_sec */ |
3871 | - my_time.year= (uint32_t) l_time->tm_year+1900; |
3872 | - my_time.month= (uint32_t) l_time->tm_mon+1; |
3873 | - my_time.day= (uint32_t) l_time->tm_mday; |
3874 | - my_time.hour= (uint32_t) l_time->tm_hour; |
3875 | - my_time.minute= (uint32_t) l_time->tm_min; |
3876 | - my_time.second= (uint32_t) l_time->tm_sec; |
3877 | - my_time.time_type= DRIZZLE_TIMESTAMP_NONE; |
3878 | - my_time.second_part= 0; |
3879 | - my_time.neg= false; |
3880 | - my_system_gmt_sec(&my_time, &my_time_zone, ¬_used); /* Init my_time_zone */ |
3881 | -} |
3882 | - |
3883 | - |
3884 | -/* |
3885 | - Handle 2 digit year conversions |
3886 | - |
3887 | - SYNOPSIS |
3888 | - year_2000_handling() |
3889 | - year 2 digit year |
3890 | - |
3891 | - RETURN |
3892 | - Year between 1970-2069 |
3893 | -*/ |
3894 | - |
3895 | -uint32_t year_2000_handling(uint32_t year) |
3896 | -{ |
3897 | - if ((year=year+1900) < 1900+YY_PART_YEAR) |
3898 | - year+=100; |
3899 | - return year; |
3900 | -} |
3901 | - |
3902 | - |
3903 | -/* |
3904 | - Calculate nr of day since year 0 in new date-system (from 1615) |
3905 | - |
3906 | - SYNOPSIS |
3907 | - calc_daynr() |
3908 | - year Year (exact 4 digit year, no year conversions) |
3909 | - month Month |
3910 | - day Day |
3911 | - |
3912 | - NOTES: 0000-00-00 is a valid date, and will return 0 |
3913 | - |
3914 | - RETURN |
3915 | - Days since 0000-00-00 |
3916 | -*/ |
3917 | - |
3918 | -long calc_daynr(uint32_t year,uint32_t month,uint32_t day) |
3919 | -{ |
3920 | - long delsum; |
3921 | - int temp; |
3922 | - |
3923 | - if (year == 0 && month == 0 && day == 0) |
3924 | - return(0); /* Skip errors */ |
3925 | - delsum= (long) (365L * year+ 31*(month-1) +day); |
3926 | - if (month <= 2) |
3927 | - year--; |
3928 | - else |
3929 | - delsum-= (long) (month*4+23)/10; |
3930 | - temp=(int) ((year/100+1)*3)/4; |
3931 | - return(delsum+(int) year/4-temp); |
3932 | -} /* calc_daynr */ |
3933 | - |
3934 | - |
3935 | -/* |
3936 | - Convert time in DRIZZLE_TIME representation in system time zone to its |
3937 | - time_t form (number of seconds in UTC since begginning of Unix Epoch). |
3938 | - |
3939 | - SYNOPSIS |
3940 | - my_system_gmt_sec() |
3941 | - t - time value to be converted |
3942 | - my_timezone - pointer to long where offset of system time zone |
3943 | - from UTC will be stored for caching |
3944 | - in_dst_time_gap - set to true if time falls into spring time-gap |
3945 | - |
3946 | - NOTES |
3947 | - The idea is to cache the time zone offset from UTC (including daylight |
3948 | - saving time) for the next call to make things faster. But currently we |
3949 | - just calculate this offset during startup (by calling init_time() |
3950 | - function) and use it all the time. |
3951 | - Time value provided should be legal time value (e.g. '2003-01-01 25:00:00' |
3952 | - is not allowed). |
3953 | - |
3954 | - RETURN VALUE |
3955 | - Time in UTC seconds since Unix Epoch representation. |
3956 | -*/ |
3957 | -time_t |
3958 | -my_system_gmt_sec(const DRIZZLE_TIME *t_src, long *my_timezone, |
3959 | - bool *in_dst_time_gap) |
3960 | -{ |
3961 | - uint32_t loop; |
3962 | - time_t tmp= 0; |
3963 | - int shift= 0; |
3964 | - DRIZZLE_TIME tmp_time; |
3965 | - DRIZZLE_TIME *t= &tmp_time; |
3966 | - struct tm *l_time,tm_tmp; |
3967 | - long diff, current_timezone; |
3968 | - |
3969 | - /* |
3970 | - Use temp variable to avoid trashing input data, which could happen in |
3971 | - case of shift required for boundary dates processing. |
3972 | - */ |
3973 | - memcpy(&tmp_time, t_src, sizeof(DRIZZLE_TIME)); |
3974 | - |
3975 | - if (!validate_timestamp_range(t)) |
3976 | - return 0; |
3977 | - |
3978 | - /* |
3979 | - Calculate the gmt time based on current time and timezone |
3980 | - The -1 on the end is to ensure that if have a date that exists twice |
3981 | - (like 2002-10-27 02:00:0 MET), we will find the initial date. |
3982 | - |
3983 | - By doing -3600 we will have to call localtime_r() several times, but |
3984 | - I couldn't come up with a better way to get a repeatable result :( |
3985 | - |
3986 | - We can't use mktime() as it's buggy on many platforms and not thread safe. |
3987 | - |
3988 | - Note: this code assumes that our time_t estimation is not too far away |
3989 | - from real value (we assume that localtime_r(tmp) will return something |
3990 | - within 24 hrs from t) which is probably true for all current time zones. |
3991 | - |
3992 | - Note2: For the dates, which have time_t representation close to |
3993 | - MAX_INT32 (efficient time_t limit for supported platforms), we should |
3994 | - do a small trick to avoid overflow. That is, convert the date, which is |
3995 | - two days earlier, and then add these days to the final value. |
3996 | - |
3997 | - The same trick is done for the values close to 0 in time_t |
3998 | - representation for platfroms with unsigned time_t (QNX). |
3999 | - |
4000 | - To be more verbose, here is a sample (extracted from the code below): |
4001 | - (calc_daynr(2038, 1, 19) - (long) days_at_timestart)*86400L + 4*3600L |
4002 | - would return -2147480896 because of the long type overflow. In result |
4003 | - we would get 1901 year in localtime_r(), which is an obvious error. |
4004 | - |
4005 | - Alike problem raises with the dates close to Epoch. E.g. |
4006 | - (calc_daynr(1969, 12, 31) - (long) days_at_timestart)*86400L + 23*3600L |
4007 | - will give -3600. |
4008 | - |
4009 | - On some platforms, (E.g. on QNX) time_t is unsigned and localtime(-3600) |
4010 | - wil give us a date around 2106 year. Which is no good. |
4011 | - |
4012 | - Theoreticaly, there could be problems with the latter conversion: |
4013 | - there are at least two timezones, which had time switches near 1 Jan |
4014 | - of 1970 (because of political reasons). These are America/Hermosillo and |
4015 | - America/Mazatlan time zones. They changed their offset on |
4016 | - 1970-01-01 08:00:00 UTC from UTC-8 to UTC-7. For these zones |
4017 | - the code below will give incorrect results for dates close to |
4018 | - 1970-01-01, in the case OS takes into account these historical switches. |
4019 | - Luckily, it seems that we support only one platform with unsigned |
4020 | - time_t. It's QNX. And QNX does not support historical timezone data at all. |
4021 | - E.g. there are no /usr/share/zoneinfo/ files or any other mean to supply |
4022 | - historical information for localtime_r() etc. That is, the problem is not |
4023 | - relevant to QNX. |
4024 | - |
4025 | - We are safe with shifts close to MAX_INT32, as there are no known |
4026 | - time switches on Jan 2038 yet :) |
4027 | - */ |
4028 | - if ((t->year == TIMESTAMP_MAX_YEAR) && (t->month == 1) && (t->day > 4)) |
4029 | - { |
4030 | - /* |
4031 | - Below we will pass (uint32_t) (t->day - shift) to calc_daynr. |
4032 | - As we don't want to get an overflow here, we will shift |
4033 | - only safe dates. That's why we have (t->day > 4) above. |
4034 | - */ |
4035 | - t->day-= 2; |
4036 | - shift= 2; |
4037 | - } |
4038 | -#ifdef TIME_T_UNSIGNED |
4039 | - else |
4040 | - { |
4041 | - /* |
4042 | - We can get 0 in time_t representaion only on 1969, 31 of Dec or on |
4043 | - 1970, 1 of Jan. For both dates we use shift, which is added |
4044 | - to t->day in order to step out a bit from the border. |
4045 | - This is required for platforms, where time_t is unsigned. |
4046 | - As far as I know, among the platforms we support it's only QNX. |
4047 | - Note: the order of below if-statements is significant. |
4048 | - */ |
4049 | - |
4050 | - if ((t->year == TIMESTAMP_MIN_YEAR + 1) && (t->month == 1) |
4051 | - && (t->day <= 10)) |
4052 | - { |
4053 | - t->day+= 2; |
4054 | - shift= -2; |
4055 | - } |
4056 | - |
4057 | - if ((t->year == TIMESTAMP_MIN_YEAR) && (t->month == 12) |
4058 | - && (t->day == 31)) |
4059 | - { |
4060 | - t->year++; |
4061 | - t->month= 1; |
4062 | - t->day= 2; |
4063 | - shift= -2; |
4064 | - } |
4065 | - } |
4066 | -#endif |
4067 | - |
4068 | - tmp= (time_t) (((calc_daynr((uint32_t) t->year, (uint32_t) t->month, (uint32_t) t->day) - |
4069 | - (long) days_at_timestart)*86400L + (long) t->hour*3600L + |
4070 | - (long) (t->minute*60 + t->second)) + (time_t) my_time_zone - |
4071 | - 3600); |
4072 | - |
4073 | - current_timezone= my_time_zone; |
4074 | - localtime_r(&tmp,&tm_tmp); |
4075 | - l_time=&tm_tmp; |
4076 | - for (loop=0; |
4077 | - loop < 2 && |
4078 | - (t->hour != (uint32_t) l_time->tm_hour || |
4079 | - t->minute != (uint32_t) l_time->tm_min || |
4080 | - t->second != (uint32_t) l_time->tm_sec); |
4081 | - loop++) |
4082 | - { /* One check should be enough ? */ |
4083 | - /* Get difference in days */ |
4084 | - int days= t->day - l_time->tm_mday; |
4085 | - if (days < -1) |
4086 | - days= 1; /* Month has wrapped */ |
4087 | - else if (days > 1) |
4088 | - days= -1; |
4089 | - diff=(3600L*(long) (days*24+((int) t->hour - (int) l_time->tm_hour)) + |
4090 | - (long) (60*((int) t->minute - (int) l_time->tm_min)) + |
4091 | - (long) ((int) t->second - (int) l_time->tm_sec)); |
4092 | - current_timezone+= diff+3600; /* Compensate for -3600 above */ |
4093 | - tmp+= (time_t) diff; |
4094 | - localtime_r(&tmp,&tm_tmp); |
4095 | - l_time=&tm_tmp; |
4096 | - } |
4097 | - /* |
4098 | - Fix that if we are in the non existing daylight saving time hour |
4099 | - we move the start of the next real hour. |
4100 | - |
4101 | - This code doesn't handle such exotical thing as time-gaps whose length |
4102 | - is more than one hour or non-integer (latter can theoretically happen |
4103 | - if one of seconds will be removed due leap correction, or because of |
4104 | - general time correction like it happened for Africa/Monrovia time zone |
4105 | - in year 1972). |
4106 | - */ |
4107 | - if (loop == 2 && t->hour != (uint32_t) l_time->tm_hour) |
4108 | - { |
4109 | - int days= t->day - l_time->tm_mday; |
4110 | - if (days < -1) |
4111 | - days=1; /* Month has wrapped */ |
4112 | - else if (days > 1) |
4113 | - days= -1; |
4114 | - diff=(3600L*(long) (days*24+((int) t->hour - (int) l_time->tm_hour))+ |
4115 | - (long) (60*((int) t->minute - (int) l_time->tm_min)) + |
4116 | - (long) ((int) t->second - (int) l_time->tm_sec)); |
4117 | - if (diff == 3600) |
4118 | - tmp+=3600 - t->minute*60 - t->second; /* Move to next hour */ |
4119 | - else if (diff == -3600) |
4120 | - tmp-=t->minute*60 + t->second; /* Move to previous hour */ |
4121 | - |
4122 | - *in_dst_time_gap= true; |
4123 | - } |
4124 | - *my_timezone= current_timezone; |
4125 | - |
4126 | - |
4127 | - /* shift back, if we were dealing with boundary dates */ |
4128 | - tmp+= shift*86400L; |
4129 | - |
4130 | - /* |
4131 | - This is possible for dates, which slightly exceed boundaries. |
4132 | - Conversion will pass ok for them, but we don't allow them. |
4133 | - First check will pass for platforms with signed time_t. |
4134 | - instruction above (tmp+= shift*86400L) could exceed |
4135 | - MAX_INT32 (== TIMESTAMP_MAX_VALUE) and overflow will happen. |
4136 | - So, tmp < TIMESTAMP_MIN_VALUE will be triggered. On platfroms |
4137 | - with unsigned time_t tmp+= shift*86400L might result in a number, |
4138 | - larger then TIMESTAMP_MAX_VALUE, so another check will work. |
4139 | - */ |
4140 | - if ((tmp < TIMESTAMP_MIN_VALUE) || (tmp > TIMESTAMP_MAX_VALUE)) |
4141 | - tmp= 0; |
4142 | - |
4143 | - return (time_t) tmp; |
4144 | -} /* my_system_gmt_sec */ |
4145 | - |
4146 | - |
4147 | -/* Set DRIZZLE_TIME structure to 0000-00-00 00:00:00.000000 */ |
4148 | - |
4149 | -void set_zero_time(DRIZZLE_TIME *tm, enum enum_drizzle_timestamp_type time_type) |
4150 | -{ |
4151 | - memset(tm, 0, sizeof(*tm)); |
4152 | - tm->time_type= time_type; |
4153 | -} |
4154 | - |
4155 | - |
4156 | -/* |
4157 | - Functions to convert time/date/datetime value to a string, |
4158 | - using default format. |
4159 | - This functions don't check that given DRIZZLE_TIME structure members are |
4160 | - in valid range. If they are not, return value won't reflect any |
4161 | - valid date either. Additionally, make_time doesn't take into |
4162 | - account time->day member: it's assumed that days have been converted |
4163 | - to hours already. |
4164 | - |
4165 | - RETURN |
4166 | - number of characters written to 'to' |
4167 | -*/ |
4168 | - |
4169 | -static int my_time_to_str(const DRIZZLE_TIME *l_time, char *to) |
4170 | -{ |
4171 | - uint32_t extra_hours= 0; |
4172 | - return sprintf(to, "%s%02u:%02u:%02u", |
4173 | - (l_time->neg ? "-" : ""), |
4174 | - extra_hours+ l_time->hour, |
4175 | - l_time->minute, |
4176 | - l_time->second); |
4177 | -} |
4178 | - |
4179 | -int my_date_to_str(const DRIZZLE_TIME *l_time, char *to) |
4180 | -{ |
4181 | - return sprintf(to, "%04u-%02u-%02u", |
4182 | - l_time->year, |
4183 | - l_time->month, |
4184 | - l_time->day); |
4185 | -} |
4186 | - |
4187 | -int my_datetime_to_str(const DRIZZLE_TIME *l_time, char *to) |
4188 | -{ |
4189 | - return sprintf(to, "%04u-%02u-%02u %02u:%02u:%02u", |
4190 | - l_time->year, |
4191 | - l_time->month, |
4192 | - l_time->day, |
4193 | - l_time->hour, |
4194 | - l_time->minute, |
4195 | - l_time->second); |
4196 | -} |
4197 | - |
4198 | - |
4199 | -/* |
4200 | - Convert struct DATE/TIME/DATETIME value to string using built-in |
4201 | - MySQL time conversion formats. |
4202 | - |
4203 | - SYNOPSIS |
4204 | - my_TIME_to_string() |
4205 | - |
4206 | - NOTE |
4207 | - The string must have at least MAX_DATE_STRING_REP_LENGTH bytes reserved. |
4208 | -*/ |
4209 | - |
4210 | -int my_TIME_to_str(const DRIZZLE_TIME *l_time, char *to) |
4211 | -{ |
4212 | - switch (l_time->time_type) { |
4213 | - case DRIZZLE_TIMESTAMP_DATETIME: |
4214 | - return my_datetime_to_str(l_time, to); |
4215 | - case DRIZZLE_TIMESTAMP_DATE: |
4216 | - return my_date_to_str(l_time, to); |
4217 | - case DRIZZLE_TIMESTAMP_TIME: |
4218 | - return my_time_to_str(l_time, to); |
4219 | - case DRIZZLE_TIMESTAMP_NONE: |
4220 | - case DRIZZLE_TIMESTAMP_ERROR: |
4221 | - to[0]='\0'; |
4222 | - return 0; |
4223 | - default: |
4224 | - assert(0); |
4225 | - return 0; |
4226 | - } |
4227 | -} |
4228 | - |
4229 | - |
4230 | -/* |
4231 | - Convert datetime value specified as number to broken-down TIME |
4232 | - representation and form value of DATETIME type as side-effect. |
4233 | - |
4234 | - SYNOPSIS |
4235 | - number_to_datetime() |
4236 | - nr - datetime value as number |
4237 | - time_res - pointer for structure for broken-down representation |
4238 | - flags - flags to use in validating date, as in str_to_datetime() |
4239 | - was_cut 0 Value ok |
4240 | - 1 If value was cut during conversion |
4241 | - 2 check_date(date,flags) considers date invalid |
4242 | - |
4243 | - DESCRIPTION |
4244 | - Convert a datetime value of formats YYMMDD, YYYYMMDD, YYMMDDHHMSS, |
4245 | - YYYYMMDDHHMMSS to broken-down DRIZZLE_TIME representation. Return value in |
4246 | - YYYYMMDDHHMMSS format as side-effect. |
4247 | - |
4248 | - This function also checks if datetime value fits in DATETIME range. |
4249 | - |
4250 | - RETURN VALUE |
4251 | - -1 Timestamp with wrong values |
4252 | - anything else DATETIME as integer in YYYYMMDDHHMMSS format |
4253 | - Datetime value in YYYYMMDDHHMMSS format. |
4254 | -*/ |
4255 | - |
4256 | -int64_t number_to_datetime(int64_t nr, DRIZZLE_TIME *time_res, |
4257 | - uint32_t flags, int *was_cut) |
4258 | -{ |
4259 | - long part1,part2; |
4260 | - |
4261 | - *was_cut= 0; |
4262 | - memset(time_res, 0, sizeof(*time_res)); |
4263 | - time_res->time_type=DRIZZLE_TIMESTAMP_DATE; |
4264 | - |
4265 | - if (nr == 0LL || nr >= 10000101000000LL) |
4266 | - { |
4267 | - time_res->time_type=DRIZZLE_TIMESTAMP_DATETIME; |
4268 | - goto ok; |
4269 | - } |
4270 | - if (nr < 101) |
4271 | - goto err; |
4272 | - if (nr <= (YY_PART_YEAR-1)*10000L+1231L) |
4273 | - { |
4274 | - nr= (nr+20000000L)*1000000L; /* YYMMDD, year: 2000-2069 */ |
4275 | - goto ok; |
4276 | - } |
4277 | - if (nr < (YY_PART_YEAR)*10000L+101L) |
4278 | - goto err; |
4279 | - if (nr <= 991231L) |
4280 | - { |
4281 | - nr= (nr+19000000L)*1000000L; /* YYMMDD, year: 1970-1999 */ |
4282 | - goto ok; |
4283 | - } |
4284 | - if (nr < 10000101L) |
4285 | - goto err; |
4286 | - if (nr <= 99991231L) |
4287 | - { |
4288 | - nr= nr*1000000L; |
4289 | - goto ok; |
4290 | - } |
4291 | - if (nr < 101000000L) |
4292 | - goto err; |
4293 | - |
4294 | - time_res->time_type=DRIZZLE_TIMESTAMP_DATETIME; |
4295 | - |
4296 | - if (nr <= (YY_PART_YEAR-1) * 10000000000LL + 1231235959LL) |
4297 | - { |
4298 | - nr= nr + 20000000000000LL; /* YYMMDDHHMMSS, 2000-2069 */ |
4299 | - goto ok; |
4300 | - } |
4301 | - if (nr < YY_PART_YEAR * 10000000000LL + 101000000LL) |
4302 | - goto err; |
4303 | - if (nr <= 991231235959LL) |
4304 | - nr= nr + 19000000000000LL; /* YYMMDDHHMMSS, 1970-1999 */ |
4305 | - |
4306 | - ok: |
4307 | - part1=(long) (nr / 1000000LL); |
4308 | - part2=(long) (nr - (int64_t) part1 * 1000000LL); |
4309 | - time_res->year= (int) (part1/10000L); part1%=10000L; |
4310 | - time_res->month= (int) part1 / 100; |
4311 | - time_res->day= (int) part1 % 100; |
4312 | - time_res->hour= (int) (part2/10000L); part2%=10000L; |
4313 | - time_res->minute=(int) part2 / 100; |
4314 | - time_res->second=(int) part2 % 100; |
4315 | - |
4316 | - if (time_res->year <= 9999 && time_res->month <= 12 && |
4317 | - time_res->day <= 31 && time_res->hour <= 23 && |
4318 | - time_res->minute <= 59 && time_res->second <= 59 && |
4319 | - !check_date(time_res, (nr != 0), flags, was_cut)) |
4320 | - return nr; |
4321 | - |
4322 | - /* Don't want to have was_cut get set if NO_ZERO_DATE was violated. */ |
4323 | - if (!nr && (flags & TIME_NO_ZERO_DATE)) |
4324 | - return -1LL; |
4325 | - |
4326 | - err: |
4327 | - *was_cut= 1; |
4328 | - return -1LL; |
4329 | -} |
4330 | - |
4331 | - |
4332 | -/* Convert time value to integer in YYYYMMDDHHMMSS format */ |
4333 | - |
4334 | -uint64_t TIME_to_uint64_t_datetime(const DRIZZLE_TIME *my_time) |
4335 | -{ |
4336 | - return ((uint64_t) (my_time->year * 10000UL + |
4337 | - my_time->month * 100UL + |
4338 | - my_time->day) * 1000000ULL + |
4339 | - (uint64_t) (my_time->hour * 10000UL + |
4340 | - my_time->minute * 100UL + |
4341 | - my_time->second)); |
4342 | -} |
4343 | - |
4344 | - |
4345 | -/* Convert DRIZZLE_TIME value to integer in YYYYMMDD format */ |
4346 | - |
4347 | -static uint64_t TIME_to_uint64_t_date(const DRIZZLE_TIME *my_time) |
4348 | -{ |
4349 | - return (uint64_t) (my_time->year * 10000UL + my_time->month * 100UL + |
4350 | - my_time->day); |
4351 | -} |
4352 | - |
4353 | - |
4354 | -/* |
4355 | - Convert DRIZZLE_TIME value to integer in HHMMSS format. |
4356 | - This function doesn't take into account time->day member: |
4357 | - it's assumed that days have been converted to hours already. |
4358 | -*/ |
4359 | - |
4360 | -static uint64_t TIME_to_uint64_t_time(const DRIZZLE_TIME *my_time) |
4361 | -{ |
4362 | - return (uint64_t) (my_time->hour * 10000UL + |
4363 | - my_time->minute * 100UL + |
4364 | - my_time->second); |
4365 | -} |
4366 | - |
4367 | - |
4368 | -/* |
4369 | - Convert struct DRIZZLE_TIME (date and time split into year/month/day/hour/... |
4370 | - to a number in format YYYYMMDDHHMMSS (DATETIME), |
4371 | - YYYYMMDD (DATE) or HHMMSS (TIME). |
4372 | - |
4373 | - SYNOPSIS |
4374 | - TIME_to_uint64_t() |
4375 | - |
4376 | - DESCRIPTION |
4377 | - The function is used when we need to convert value of time item |
4378 | - to a number if it's used in numeric context, i. e.: |
4379 | - SELECT NOW()+1, CURDATE()+0, CURTIMIE()+0; |
4380 | - SELECT ?+1; |
4381 | - |
4382 | - NOTE |
4383 | - This function doesn't check that given DRIZZLE_TIME structure members are |
4384 | - in valid range. If they are not, return value won't reflect any |
4385 | - valid date either. |
4386 | -*/ |
4387 | - |
4388 | -uint64_t TIME_to_uint64_t(const DRIZZLE_TIME *my_time) |
4389 | -{ |
4390 | - switch (my_time->time_type) { |
4391 | - case DRIZZLE_TIMESTAMP_DATETIME: |
4392 | - return TIME_to_uint64_t_datetime(my_time); |
4393 | - case DRIZZLE_TIMESTAMP_DATE: |
4394 | - return TIME_to_uint64_t_date(my_time); |
4395 | - case DRIZZLE_TIMESTAMP_TIME: |
4396 | - return TIME_to_uint64_t_time(my_time); |
4397 | - case DRIZZLE_TIMESTAMP_NONE: |
4398 | - case DRIZZLE_TIMESTAMP_ERROR: |
4399 | - return 0ULL; |
4400 | - default: |
4401 | - assert(0); |
4402 | - } |
4403 | - return 0; |
4404 | -} |
4405 | - |
4406 | -} /* namespace drizzled */ |
4407 | |
4408 | === removed file 'drizzled/my_time.h' |
4409 | --- drizzled/my_time.h 2010-02-04 08:14:46 +0000 |
4410 | +++ drizzled/my_time.h 1970-01-01 00:00:00 +0000 |
4411 | @@ -1,194 +0,0 @@ |
4412 | -/* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*- |
4413 | - * vim:expandtab:shiftwidth=2:tabstop=2:smarttab: |
4414 | - * |
4415 | - * Copyright (C) 2008 MySQL |
4416 | - * |
4417 | - * This program is free software; you can redistribute it and/or modify |
4418 | - * it under the terms of the GNU General Public License as published by |
4419 | - * the Free Software Foundation; either version 2 of the License, or |
4420 | - * (at your option) any later version. |
4421 | - * |
4422 | - * This program is distributed in the hope that it will be useful, |
4423 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
4424 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
4425 | - * GNU General Public License for more details. |
4426 | - * |
4427 | - * You should have received a copy of the GNU General Public License |
4428 | - * along with this program; if not, write to the Free Software |
4429 | - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
4430 | - */ |
4431 | - |
4432 | -#ifndef DRIZZLED_MY_TIME_H |
4433 | -#define DRIZZLED_MY_TIME_H |
4434 | - |
4435 | -#if TIME_WITH_SYS_TIME |
4436 | -# include <sys/time.h> |
4437 | -# include <time.h> |
4438 | -#else |
4439 | -# if HAVE_SYS_TIME_H |
4440 | -# include <sys/time.h> |
4441 | -# else |
4442 | -# include <time.h> |
4443 | -# endif |
4444 | -#endif |
4445 | - |
4446 | -namespace drizzled |
4447 | -{ |
4448 | - |
4449 | -extern uint64_t log_10_int[20]; |
4450 | -extern unsigned char days_in_month[]; |
4451 | - |
4452 | -/* Time handling defaults */ |
4453 | -#define TIMESTAMP_MAX_YEAR 2038 |
4454 | -#define TIMESTAMP_MIN_YEAR (1900 + YY_PART_YEAR - 1) |
4455 | -#define TIMESTAMP_MAX_VALUE INT32_MAX |
4456 | -#define TIMESTAMP_MIN_VALUE 1 |
4457 | - |
4458 | -/* two-digit years < this are 20..; >= this are 19.. */ |
4459 | -#define YY_PART_YEAR 70 |
4460 | - |
4461 | -/* Flags to str_to_datetime */ |
4462 | -#define TIME_FUZZY_DATE 1 |
4463 | -#define TIME_DATETIME_ONLY 2 |
4464 | -/* Must be same as MODE_NO_ZERO_IN_DATE */ |
4465 | -#define TIME_NO_ZERO_IN_DATE (65536L*2*2*2*2*2*2*2) |
4466 | -/* Must be same as MODE_NO_ZERO_DATE */ |
4467 | -#define TIME_NO_ZERO_DATE (TIME_NO_ZERO_IN_DATE*2) |
4468 | -#define TIME_INVALID_DATES (TIME_NO_ZERO_DATE*2) |
4469 | - |
4470 | -#define DRIZZLE_TIME_WARN_TRUNCATED 1 |
4471 | -#define DRIZZLE_TIME_WARN_OUT_OF_RANGE 2 |
4472 | - |
4473 | -/* Limits for the TIME data type */ |
4474 | -#define TIME_MAX_HOUR 838 |
4475 | -#define TIME_MAX_MINUTE 59 |
4476 | -#define TIME_MAX_SECOND 59 |
4477 | -#define TIME_MAX_VALUE (TIME_MAX_HOUR*10000 + TIME_MAX_MINUTE*100 + \ |
4478 | - TIME_MAX_SECOND) |
4479 | -#define TIME_MAX_VALUE_SECONDS (TIME_MAX_HOUR * 3600L + \ |
4480 | - TIME_MAX_MINUTE * 60L + TIME_MAX_SECOND) |
4481 | - |
4482 | -enum enum_drizzle_timestamp_type |
4483 | -{ |
4484 | - DRIZZLE_TIMESTAMP_NONE= -2, DRIZZLE_TIMESTAMP_ERROR= -1, |
4485 | - DRIZZLE_TIMESTAMP_DATE= 0, DRIZZLE_TIMESTAMP_DATETIME= 1, DRIZZLE_TIMESTAMP_TIME= 2 |
4486 | -}; |
4487 | - |
4488 | - |
4489 | -/* |
4490 | - Structure which is used to represent datetime values inside Drizzle. |
4491 | - |
4492 | - We assume that values in this structure are normalized, i.e. year <= 9999, |
4493 | - month <= 12, day <= 31, hour <= 23, hour <= 59, hour <= 59. Many functions |
4494 | - in server such as my_system_gmt_sec() or make_time() family of functions |
4495 | - rely on this (actually now usage of make_*() family relies on a bit weaker |
4496 | - restriction). Also functions that produce DRIZZLE_TIME as result ensure this. |
4497 | - There is one exception to this rule though if this structure holds time |
4498 | - value (time_type == DRIZZLE_TIMESTAMP_TIME) days and hour member can hold |
4499 | - bigger values. |
4500 | -*/ |
4501 | -typedef struct st_drizzle_time |
4502 | -{ |
4503 | - unsigned int year, month, day, hour, minute, second; |
4504 | - unsigned long second_part; |
4505 | - bool neg; |
4506 | - enum enum_drizzle_timestamp_type time_type; |
4507 | -} DRIZZLE_TIME; |
4508 | - |
4509 | - |
4510 | -bool check_date(const DRIZZLE_TIME *ltime, bool not_zero_date, |
4511 | - uint32_t flags, int *was_cut); |
4512 | -enum enum_drizzle_timestamp_type |
4513 | -str_to_datetime(const char *str, uint32_t length, DRIZZLE_TIME *l_time, |
4514 | - uint32_t flags, int *was_cut); |
4515 | -int64_t number_to_datetime(int64_t nr, DRIZZLE_TIME *time_res, |
4516 | - uint32_t flags, int *was_cut); |
4517 | -uint64_t TIME_to_uint64_t_datetime(const DRIZZLE_TIME *); |
4518 | -uint64_t TIME_to_uint64_t(const DRIZZLE_TIME *); |
4519 | - |
4520 | - |
4521 | -bool str_to_time(const char *str,uint32_t length, DRIZZLE_TIME *l_time, |
4522 | - int *warning); |
4523 | - |
4524 | -long calc_daynr(uint32_t year,uint32_t month,uint32_t day); |
4525 | -uint32_t calc_days_in_year(uint32_t year); |
4526 | -uint32_t year_2000_handling(uint32_t year); |
4527 | - |
4528 | -void init_time(void); |
4529 | - |
4530 | - |
4531 | -/* |
4532 | - Function to check sanity of a TIMESTAMP value |
4533 | - |
4534 | - DESCRIPTION |
4535 | - Check if a given DRIZZLE_TIME value fits in TIMESTAMP range. |
4536 | - This function doesn't make precise check, but rather a rough |
4537 | - estimate. |
4538 | - |
4539 | - RETURN VALUES |
4540 | - false The value seems sane |
4541 | - true The DRIZZLE_TIME value is definitely out of range |
4542 | -*/ |
4543 | - |
4544 | -static inline bool validate_timestamp_range(const DRIZZLE_TIME *t) |
4545 | -{ |
4546 | - if ((t->year > TIMESTAMP_MAX_YEAR || t->year < TIMESTAMP_MIN_YEAR) || |
4547 | - (t->year == TIMESTAMP_MAX_YEAR && (t->month > 1 || t->day > 19)) || |
4548 | - (t->year == TIMESTAMP_MIN_YEAR && (t->month < 12 || t->day < 31))) |
4549 | - return false; |
4550 | - |
4551 | - return true; |
4552 | -} |
4553 | - |
4554 | -time_t |
4555 | -my_system_gmt_sec(const DRIZZLE_TIME *t, long *my_timezone, |
4556 | - bool *in_dst_time_gap); |
4557 | - |
4558 | -void set_zero_time(DRIZZLE_TIME *tm, enum enum_drizzle_timestamp_type time_type); |
4559 | - |
4560 | -/* |
4561 | - Required buffer length for my_time_to_str, my_date_to_str, |
4562 | - my_datetime_to_str and TIME_to_string functions. Note, that the |
4563 | - caller is still responsible to check that given TIME structure |
4564 | - has values in valid ranges, otherwise size of the buffer could |
4565 | - be not enough. We also rely on the fact that even wrong values |
4566 | - sent using binary protocol fit in this buffer. |
4567 | -*/ |
4568 | -#define MAX_DATE_STRING_REP_LENGTH 30 |
4569 | - |
4570 | -int my_date_to_str(const DRIZZLE_TIME *l_time, char *to); |
4571 | -int my_datetime_to_str(const DRIZZLE_TIME *l_time, char *to); |
4572 | -int my_TIME_to_str(const DRIZZLE_TIME *l_time, char *to); |
4573 | - |
4574 | -/* |
4575 | - Available interval types used in any statement. |
4576 | - |
4577 | - 'interval_type' must be sorted so that simple intervals comes first, |
4578 | - ie year, quarter, month, week, day, hour, etc. The order based on |
4579 | - interval size is also important and the intervals should be kept in a |
4580 | - large to smaller order. (get_interval_value() depends on this) |
4581 | - |
4582 | - Note: If you change the order of elements in this enum you should fix |
4583 | - order of elements in 'interval_type_to_name' and 'interval_names' |
4584 | - arrays |
4585 | - |
4586 | - See also interval_type_to_name, get_interval_value, interval_names |
4587 | -*/ |
4588 | - |
4589 | -enum interval_type |
4590 | -{ |
4591 | - INTERVAL_YEAR, INTERVAL_QUARTER, INTERVAL_MONTH, INTERVAL_WEEK, INTERVAL_DAY, |
4592 | - INTERVAL_HOUR, INTERVAL_MINUTE, INTERVAL_SECOND, INTERVAL_MICROSECOND, |
4593 | - INTERVAL_YEAR_MONTH, INTERVAL_DAY_HOUR, INTERVAL_DAY_MINUTE, |
4594 | - INTERVAL_DAY_SECOND, INTERVAL_HOUR_MINUTE, INTERVAL_HOUR_SECOND, |
4595 | - INTERVAL_MINUTE_SECOND, INTERVAL_DAY_MICROSECOND, INTERVAL_HOUR_MICROSECOND, |
4596 | - INTERVAL_MINUTE_MICROSECOND, INTERVAL_SECOND_MICROSECOND, INTERVAL_LAST |
4597 | -}; |
4598 | - |
4599 | -extern uint64_t my_getsystime(void); |
4600 | -extern uint64_t my_micro_time(void); |
4601 | -extern uint64_t my_micro_time_and_time(time_t *time_arg); |
4602 | - |
4603 | -} /* namespace drizzled */ |
4604 | - |
4605 | -#endif /* DRIZZLED_MY_TIME_H */ |
4606 | |
4607 | === removed file 'drizzled/my_tree.cc' |
4608 | --- drizzled/my_tree.cc 2010-02-04 08:14:46 +0000 |
4609 | +++ drizzled/my_tree.cc 1970-01-01 00:00:00 +0000 |
4610 | @@ -1,715 +0,0 @@ |
4611 | -/* Copyright (C) 2000 MySQL AB |
4612 | - |
4613 | - This program is free software; you can redistribute it and/or modify |
4614 | - it under the terms of the GNU General Public License as published by |
4615 | - the Free Software Foundation; version 2 of the License. |
4616 | - |
4617 | - This program is distributed in the hope that it will be useful, |
4618 | - but WITHOUT ANY WARRANTY; without even the implied warranty of |
4619 | - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
4620 | - GNU General Public License for more details. |
4621 | - |
4622 | - You should have received a copy of the GNU General Public License |
4623 | - along with this program; if not, write to the Free Software |
4624 | - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ |
4625 | - |
4626 | -/* |
4627 | - Code for handling red-black (balanced) binary trees. |
4628 | - key in tree is allocated accrding to following: |
4629 | - |
4630 | - 1) If size < 0 then tree will not allocate keys and only a pointer to |
4631 | - each key is saved in tree. |
4632 | - compare and search functions uses and returns key-pointer |
4633 | - |
4634 | - 2) If size == 0 then there are two options: |
4635 | - - key_size != 0 to tree_insert: The key will be stored in the tree. |
4636 | - - key_size == 0 to tree_insert: A pointer to the key is stored. |
4637 | - compare and search functions uses and returns key-pointer. |
4638 | - |
4639 | - 3) if key_size is given to init_tree then each node will continue the |
4640 | - key and calls to insert_key may increase length of key. |
4641 | - if key_size > sizeof(pointer) and key_size is a multiple of 8 (double |
4642 | - allign) then key will be put on a 8 alligned adress. Else |
4643 | - the key will be on adress (element+1). This is transparent for user |
4644 | - compare and search functions uses a pointer to given key-argument. |
4645 | - |
4646 | - - If you use a free function for tree-elements and you are freeing |
4647 | - the element itself, you should use key_size = 0 to init_tree and |
4648 | - tree_search |
4649 | - |
4650 | - The actual key in TREE_ELEMENT is saved as a pointer or after the |
4651 | - TREE_ELEMENT struct. |
4652 | - If one uses only pointers in tree one can use tree_set_pointer() to |
4653 | - change address of data. |
4654 | - |
4655 | - Implemented by monty. |
4656 | -*/ |
4657 | - |
4658 | -/* |
4659 | - NOTE: |
4660 | - tree->compare function should be ALWAYS called as |
4661 | - (*tree->compare)(custom_arg, ELEMENT_KEY(tree,element), key) |
4662 | - and not other way around, as |
4663 | - (*tree->compare)(custom_arg, key, ELEMENT_KEY(tree,element)) |
4664 | -*/ |
4665 | - |
4666 | -#include "config.h" |
4667 | - |
4668 | -#include "drizzled/my_tree.h" |
4669 | -#include "drizzled/internal/my_sys.h" |
4670 | -#include "drizzled/internal/m_string.h" |
4671 | -#include "drizzled/memory/root.h" |
4672 | - |
4673 | -#define BLACK 1 |
4674 | -#define RED 0 |
4675 | -#define DEFAULT_ALLOC_SIZE 8192 |
4676 | -#define DEFAULT_ALIGN_SIZE 8192 |
4677 | - |
4678 | -#define ELEMENT_KEY(tree,element)\ |
4679 | -(tree->offset_to_key ? (void*)((unsigned char*) element+tree->offset_to_key) :\ |
4680 | - *((void**) (element+1))) |
4681 | -#define ELEMENT_CHILD(element, offs) (*(TREE_ELEMENT**)((char*)element + offs)) |
4682 | - |
4683 | -namespace drizzled |
4684 | -{ |
4685 | - |
4686 | - |
4687 | -static void delete_tree_element(TREE *,TREE_ELEMENT *); |
4688 | -static int tree_walk_left_root_right(TREE *,TREE_ELEMENT *, |
4689 | - tree_walk_action,void *); |
4690 | -static int tree_walk_right_root_left(TREE *,TREE_ELEMENT *, |
4691 | - tree_walk_action,void *); |
4692 | -static void left_rotate(TREE_ELEMENT **parent,TREE_ELEMENT *leaf); |
4693 | -static void right_rotate(TREE_ELEMENT **parent, TREE_ELEMENT *leaf); |
4694 | -static void rb_insert(TREE *tree,TREE_ELEMENT ***parent, |
4695 | - TREE_ELEMENT *leaf); |
4696 | -static void rb_delete_fixup(TREE *tree,TREE_ELEMENT ***parent); |
4697 | - |
4698 | - |
4699 | -void init_tree(TREE *tree, size_t default_alloc_size, uint32_t memory_limit, |
4700 | - uint32_t size, qsort_cmp2 compare, bool with_delete, |
4701 | - tree_element_free free_element, void *custom_arg) |
4702 | -{ |
4703 | - if (default_alloc_size < DEFAULT_ALLOC_SIZE) |
4704 | - default_alloc_size= DEFAULT_ALLOC_SIZE; |
4705 | - default_alloc_size= MY_ALIGN(default_alloc_size, DEFAULT_ALIGN_SIZE); |
4706 | - memset(&tree->null_element, 0, sizeof(tree->null_element)); |
4707 | - tree->root= &tree->null_element; |
4708 | - tree->compare= compare; |
4709 | - tree->size_of_element= size > 0 ? (uint32_t) size : 0; |
4710 | - tree->memory_limit= memory_limit; |
4711 | - tree->free= free_element; |
4712 | - tree->allocated= 0; |
4713 | - tree->elements_in_tree= 0; |
4714 | - tree->custom_arg = custom_arg; |
4715 | - tree->null_element.colour= BLACK; |
4716 | - tree->null_element.left=tree->null_element.right= 0; |
4717 | - tree->flag= 0; |
4718 | - if (!free_element && |
4719 | - (size <= sizeof(void*) || ((uint32_t) size & (sizeof(void*)-1)))) |
4720 | - { |
4721 | - /* |
4722 | - We know that the data doesn't have to be aligned (like if the key |
4723 | - contains a double), so we can store the data combined with the |
4724 | - TREE_ELEMENT. |
4725 | - */ |
4726 | - tree->offset_to_key= sizeof(TREE_ELEMENT); /* Put key after element */ |
4727 | - /* Fix allocation size so that we don't lose any memory */ |
4728 | - default_alloc_size/= (sizeof(TREE_ELEMENT)+size); |
4729 | - if (!default_alloc_size) |
4730 | - default_alloc_size= 1; |
4731 | - default_alloc_size*= (sizeof(TREE_ELEMENT)+size); |
4732 | - } |
4733 | - else |
4734 | - { |
4735 | - tree->offset_to_key= 0; /* use key through pointer */ |
4736 | - tree->size_of_element+= sizeof(void*); |
4737 | - } |
4738 | - if (! (tree->with_delete= with_delete)) |
4739 | - { |
4740 | - init_alloc_root(&tree->mem_root, default_alloc_size); |
4741 | - tree->mem_root.min_malloc= (sizeof(TREE_ELEMENT)+tree->size_of_element); |
4742 | - } |
4743 | -} |
4744 | - |
4745 | -static void free_tree(TREE *tree, myf free_flags) |
4746 | -{ |
4747 | - if (tree->root) /* If initialized */ |
4748 | - { |
4749 | - if (tree->with_delete) |
4750 | - delete_tree_element(tree,tree->root); |
4751 | - else |
4752 | - { |
4753 | - if (tree->free) |
4754 | - { |
4755 | - if (tree->memory_limit) |
4756 | - (*tree->free)(NULL, free_init, tree->custom_arg); |
4757 | - delete_tree_element(tree,tree->root); |
4758 | - if (tree->memory_limit) |
4759 | - (*tree->free)(NULL, free_end, tree->custom_arg); |
4760 | - } |
4761 | - free_root(&tree->mem_root, free_flags); |
4762 | - } |
4763 | - } |
4764 | - tree->root= &tree->null_element; |
4765 | - tree->elements_in_tree= 0; |
4766 | - tree->allocated= 0; |
4767 | -} |
4768 | - |
4769 | -void delete_tree(TREE* tree) |
4770 | -{ |
4771 | - free_tree(tree, MYF(0)); /* free() mem_root if applicable */ |
4772 | -} |
4773 | - |
4774 | -void reset_tree(TREE* tree) |
4775 | -{ |
4776 | - /* do not free mem_root, just mark blocks as free */ |
4777 | - free_tree(tree, MYF(memory::MARK_BLOCKS_FREE)); |
4778 | -} |
4779 | - |
4780 | - |
4781 | -static void delete_tree_element(TREE *tree, TREE_ELEMENT *element) |
4782 | -{ |
4783 | - if (element != &tree->null_element) |
4784 | - { |
4785 | - delete_tree_element(tree,element->left); |
4786 | - if (tree->free) |
4787 | - (*tree->free)(ELEMENT_KEY(tree,element), free_free, tree->custom_arg); |
4788 | - delete_tree_element(tree,element->right); |
4789 | - if (tree->with_delete) |
4790 | - free((char*) element); |
4791 | - } |
4792 | -} |
4793 | - |
4794 | - |
4795 | -/* |
4796 | - insert, search and delete of elements |
4797 | - |
4798 | - The following should be true: |
4799 | - parent[0] = & parent[-1][0]->left || |
4800 | - parent[0] = & parent[-1][0]->right |
4801 | -*/ |
4802 | - |
4803 | -TREE_ELEMENT *tree_insert(TREE *tree, void *key, uint32_t key_size, |
4804 | - void* custom_arg) |
4805 | -{ |
4806 | - int cmp; |
4807 | - TREE_ELEMENT *element,***parent; |
4808 | - |
4809 | - parent= tree->parents; |
4810 | - *parent = &tree->root; element= tree->root; |
4811 | - for (;;) |
4812 | - { |
4813 | - if (element == &tree->null_element || |
4814 | - (cmp = (*tree->compare)(custom_arg, ELEMENT_KEY(tree,element), |
4815 | - key)) == 0) |
4816 | - break; |
4817 | - if (cmp < 0) |
4818 | - { |
4819 | - *++parent= &element->right; element= element->right; |
4820 | - } |
4821 | - else |
4822 | - { |
4823 | - *++parent = &element->left; element= element->left; |
4824 | - } |
4825 | - } |
4826 | - if (element == &tree->null_element) |
4827 | - { |
4828 | - size_t alloc_size= sizeof(TREE_ELEMENT)+key_size+tree->size_of_element; |
4829 | - tree->allocated+= alloc_size; |
4830 | - |
4831 | - if (tree->memory_limit && tree->elements_in_tree |
4832 | - && tree->allocated > tree->memory_limit) |
4833 | - { |
4834 | - reset_tree(tree); |
4835 | - return tree_insert(tree, key, key_size, custom_arg); |
4836 | - } |
4837 | - |
4838 | - key_size+= tree->size_of_element; |
4839 | - if (tree->with_delete) |
4840 | - element= (TREE_ELEMENT *) malloc(alloc_size); |
4841 | - else |
4842 | - element= (TREE_ELEMENT *) alloc_root(&tree->mem_root,alloc_size); |
4843 | - if (!element) |
4844 | - return(NULL); |
4845 | - **parent= element; |
4846 | - element->left= element->right= &tree->null_element; |
4847 | - if (!tree->offset_to_key) |
4848 | - { |
4849 | - if (key_size == sizeof(void*)) /* no length, save pointer */ |
4850 | - *((void**) (element+1))= key; |
4851 | - else |
4852 | - { |
4853 | - *((void**) (element+1))= (void*) ((void **) (element+1)+1); |
4854 | - memcpy(*((void **) (element+1)),key, key_size - sizeof(void*)); |
4855 | - } |
4856 | - } |
4857 | - else |
4858 | - memcpy((unsigned char*) element + tree->offset_to_key, key, key_size); |
4859 | - element->count= 1; /* May give warning in purify */ |
4860 | - tree->elements_in_tree++; |
4861 | - rb_insert(tree,parent,element); /* rebalance tree */ |
4862 | - } |
4863 | - else |
4864 | - { |
4865 | - if (tree->flag & TREE_NO_DUPS) |
4866 | - return(NULL); |
4867 | - element->count++; |
4868 | - /* Avoid a wrap over of the count. */ |
4869 | - if (! element->count) |
4870 | - element->count--; |
4871 | - } |
4872 | - |
4873 | - return element; |
4874 | -} |
4875 | - |
4876 | -int tree_delete(TREE *tree, void *key, uint32_t key_size, void *custom_arg) |
4877 | -{ |
4878 | - int remove_colour; |
4879 | - TREE_ELEMENT *element,***parent, ***org_parent, *nod; |
4880 | - if (!tree->with_delete) |
4881 | - return 1; /* not allowed */ |
4882 | - |
4883 | - parent= tree->parents; |
4884 | - *parent= &tree->root; element= tree->root; |
4885 | - for (;;) |
4886 | - { |
4887 | - int cmp; |
4888 | - |
4889 | - if (element == &tree->null_element) |
4890 | - return 1; /* Was not in tree */ |
4891 | - if ((cmp = (*tree->compare)(custom_arg, ELEMENT_KEY(tree,element), |
4892 | - key)) == 0) |
4893 | - break; |
4894 | - if (cmp < 0) |
4895 | - { |
4896 | - *++parent= &element->right; element= element->right; |
4897 | - } |
4898 | - else |
4899 | - { |
4900 | - *++parent = &element->left; element= element->left; |
4901 | - } |
4902 | - } |
4903 | - if (element->left == &tree->null_element) |
4904 | - { |
4905 | - (**parent)= element->right; |
4906 | - remove_colour= element->colour; |
4907 | - } |
4908 | - else if (element->right == &tree->null_element) |
4909 | - { |
4910 | - (**parent)= element->left; |
4911 | - remove_colour= element->colour; |
4912 | - } |
4913 | - else |
4914 | - { |
4915 | - org_parent= parent; |
4916 | - *++parent= &element->right; nod= element->right; |
4917 | - while (nod->left != &tree->null_element) |
4918 | - { |
4919 | - *++parent= &nod->left; nod= nod->left; |
4920 | - } |
4921 | - (**parent)= nod->right; /* unlink nod from tree */ |
4922 | - remove_colour= nod->colour; |
4923 | - org_parent[0][0]= nod; /* put y in place of element */ |
4924 | - org_parent[1]= &nod->right; |
4925 | - nod->left= element->left; |
4926 | - nod->right= element->right; |
4927 | - nod->colour= element->colour; |
4928 | - } |
4929 | - if (remove_colour == BLACK) |
4930 | - rb_delete_fixup(tree,parent); |
4931 | - if (tree->free) |
4932 | - (*tree->free)(ELEMENT_KEY(tree,element), free_free, tree->custom_arg); |
4933 | - tree->allocated-= sizeof(TREE_ELEMENT) + tree->size_of_element + key_size; |
4934 | - free((unsigned char*) element); |
4935 | - tree->elements_in_tree--; |
4936 | - |
4937 | - return 0; |
4938 | -} |
4939 | - |
4940 | -void *tree_search_key(TREE *tree, const void *key, |
4941 | - TREE_ELEMENT **parents, TREE_ELEMENT ***last_pos, |
4942 | - enum ha_rkey_function flag, void *custom_arg) |
4943 | -{ |
4944 | - TREE_ELEMENT *element= tree->root; |
4945 | - TREE_ELEMENT **last_left_step_parent= NULL, **last_right_step_parent= NULL; |
4946 | - TREE_ELEMENT **last_equal_element= NULL; |
4947 | - |
4948 | -/* |
4949 | - TODO: support for HA_READ_KEY_OR_PREV, HA_READ_PREFIX flags if needed. |
4950 | -*/ |
4951 | - |
4952 | - *parents = &tree->null_element; |
4953 | - while (element != &tree->null_element) |
4954 | - { |
4955 | - int cmp; |
4956 | - |
4957 | - *++parents= element; |
4958 | - |
4959 | - if ((cmp= (*tree->compare)(custom_arg, ELEMENT_KEY(tree, element), |
4960 | - key)) == 0) |
4961 | - { |
4962 | - switch (flag) { |
4963 | - case HA_READ_KEY_EXACT: |
4964 | - case HA_READ_KEY_OR_NEXT: |
4965 | - case HA_READ_BEFORE_KEY: |
4966 | - last_equal_element= parents; |
4967 | - cmp= 1; |
4968 | - break; |
4969 | - case HA_READ_AFTER_KEY: |
4970 | - cmp= -1; |
4971 | - break; |
4972 | - case HA_READ_PREFIX_LAST: |
4973 | - case HA_READ_PREFIX_LAST_OR_PREV: |
4974 | - last_equal_element= parents; |
4975 | - cmp= -1; |
4976 | - break; |
4977 | - default: |
4978 | - return NULL; |
4979 | - } |
4980 | - } |
4981 | - if (cmp < 0) /* element < key */ |
4982 | - { |
4983 | - last_right_step_parent= parents; |
4984 | - element= element->right; |
4985 | - } |
4986 | - else |
4987 | - { |
4988 | - last_left_step_parent= parents; |
4989 | - element= element->left; |
4990 | - } |
4991 | - } |
4992 | - switch (flag) { |
4993 | - case HA_READ_KEY_EXACT: |
4994 | - case HA_READ_PREFIX_LAST: |
4995 | - *last_pos= last_equal_element; |
4996 | - break; |
4997 | - case HA_READ_KEY_OR_NEXT: |
4998 | - *last_pos= last_equal_element ? last_equal_element : last_left_step_parent; |
4999 | - break; |
5000 | - case HA_READ_AFTER_KEY: |
The diff has been truncated for viewing.
Excellent work!
-jay