Merge lp:~dedzone/drizzle/ded-rm-my into lp:~drizzle-trunk/drizzle/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
Reviewer Review Type Date Requested Status
Brian Aker Needs Fixing
Jay Pipes (community) Approve
Review via email: mp+22437@code.launchpad.net

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/internal/ .. (todo)
./drizzled/my_hash.h needs to be merged with ./drizzled/hash.h
./drizzled/my_getsystime.cc (don't really now if it has to be changed .. but easy)

To post a comment you must log in.
Revision history for this message
Jay Pipes (jaypipes) wrote :

Excellent work!

-jay

review: Approve
Revision history for this message
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, &not_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, &not_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.