~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to server/field/datetime.cc

  • Committer: Brian Aker
  • Date: 2008-07-22 17:32:05 UTC
  • mfrom: (202.1.3 toru)
  • Revision ID: brian@tangent.org-20080722173205-fbst5dw713h0gx3o
Merge of Toru + Brian

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
 
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
 
3
 *
 
4
 *  Copyright (C) 2008 MySQL
 
5
 *
 
6
 *  This program is free software; you can redistribute it and/or modify
 
7
 *  it under the terms of the GNU General Public License as published by
 
8
 *  the Free Software Foundation; either version 2 of the License, or
 
9
 *  (at your option) any later version.
 
10
 *
 
11
 *  This program is distributed in the hope that it will be useful,
 
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 *  GNU General Public License for more details.
 
15
 *
 
16
 *  You should have received a copy of the GNU General Public License
 
17
 *  along with this program; if not, write to the Free Software
 
18
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
19
 */
 
20
 
 
21
#ifdef USE_PRAGMA_IMPLEMENTATION
 
22
#pragma implementation                          // gcc: Class implementation
 
23
#endif
 
24
 
 
25
#include "datetime.h"
 
26
 
 
27
/****************************************************************************
 
28
** datetime type
 
29
** In string context: YYYY-MM-DD HH:MM:DD
 
30
** In number context: YYYYMMDDHHMMDD
 
31
** Stored as a 8 byte unsigned int. Should sometimes be change to a 6 byte int.
 
32
****************************************************************************/
 
33
 
 
34
int Field_datetime::store(const char *from,
 
35
                          uint len,
 
36
                          CHARSET_INFO *cs __attribute__((__unused__)))
 
37
{
 
38
  MYSQL_TIME time_tmp;
 
39
  int error;
 
40
  uint64_t tmp= 0;
 
41
  enum enum_mysql_timestamp_type func_res;
 
42
  THD *thd= table ? table->in_use : current_thd;
 
43
 
 
44
  func_res= str_to_datetime(from, len, &time_tmp,
 
45
                            (TIME_FUZZY_DATE |
 
46
                             (thd->variables.sql_mode &
 
47
                              (MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE |
 
48
                               MODE_INVALID_DATES))),
 
49
                            &error);
 
50
  if ((int) func_res > (int) MYSQL_TIMESTAMP_ERROR)
 
51
    tmp= TIME_to_uint64_t_datetime(&time_tmp);
 
52
  else
 
53
    error= 1;                                 // Fix if invalid zero date
 
54
 
 
55
  if (error)
 
56
    set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
 
57
                         ER_WARN_DATA_OUT_OF_RANGE,
 
58
                         from, len, MYSQL_TIMESTAMP_DATETIME, 1);
 
59
 
 
60
#ifdef WORDS_BIGENDIAN
 
61
  if (table && table->s->db_low_byte_first)
 
62
  {
 
63
    int8store(ptr,tmp);
 
64
  }
 
65
  else
 
66
#endif
 
67
    int64_tstore(ptr,tmp);
 
68
  return error;
 
69
}
 
70
 
 
71
 
 
72
int Field_datetime::store(double nr)
 
73
{
 
74
  int error= 0;
 
75
  if (nr < 0.0 || nr > 99991231235959.0)
 
76
  {
 
77
    set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN, 
 
78
                         ER_WARN_DATA_OUT_OF_RANGE,
 
79
                         nr, MYSQL_TIMESTAMP_DATETIME);
 
80
    nr= 0.0;
 
81
    error= 1;
 
82
  }
 
83
  error|= Field_datetime::store((int64_t) rint(nr), false);
 
84
  return error;
 
85
}
 
86
 
 
87
 
 
88
int Field_datetime::store(int64_t nr,
 
89
                          bool unsigned_val __attribute__((__unused__)))
 
90
{
 
91
  MYSQL_TIME not_used;
 
92
  int error;
 
93
  int64_t initial_nr= nr;
 
94
  THD *thd= table ? table->in_use : current_thd;
 
95
 
 
96
  nr= number_to_datetime(nr, &not_used, (TIME_FUZZY_DATE |
 
97
                                         (thd->variables.sql_mode &
 
98
                                          (MODE_NO_ZERO_IN_DATE |
 
99
                                           MODE_NO_ZERO_DATE |
 
100
                                           MODE_INVALID_DATES))), &error);
 
101
 
 
102
  if (nr == -1LL)
 
103
  {
 
104
    nr= 0;
 
105
    error= 2;
 
106
  }
 
107
 
 
108
  if (error)
 
109
    set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
 
110
                         error == 2 ? ER_WARN_DATA_OUT_OF_RANGE :
 
111
                         WARN_DATA_TRUNCATED, initial_nr,
 
112
                         MYSQL_TIMESTAMP_DATETIME, 1);
 
113
 
 
114
#ifdef WORDS_BIGENDIAN
 
115
  if (table && table->s->db_low_byte_first)
 
116
  {
 
117
    int8store(ptr,nr);
 
118
  }
 
119
  else
 
120
#endif
 
121
    int64_tstore(ptr,nr);
 
122
  return error;
 
123
}
 
124
 
 
125
 
 
126
int Field_datetime::store_time(MYSQL_TIME *ltime,timestamp_type time_type)
 
127
{
 
128
  int64_t tmp;
 
129
  int error= 0;
 
130
  /*
 
131
    We don't perform range checking here since values stored in TIME
 
132
    structure always fit into DATETIME range.
 
133
  */
 
134
  if (time_type == MYSQL_TIMESTAMP_DATE ||
 
135
      time_type == MYSQL_TIMESTAMP_DATETIME)
 
136
  {
 
137
    tmp=((ltime->year*10000L+ltime->month*100+ltime->day)*1000000LL+
 
138
         (ltime->hour*10000L+ltime->minute*100+ltime->second));
 
139
    if (check_date(ltime, tmp != 0,
 
140
                   (TIME_FUZZY_DATE |
 
141
                    (current_thd->variables.sql_mode &
 
142
                     (MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE |
 
143
                      MODE_INVALID_DATES))), &error))
 
144
    {
 
145
      char buff[MAX_DATE_STRING_REP_LENGTH];
 
146
      String str(buff, sizeof(buff), &my_charset_latin1);
 
147
      make_datetime((DATE_TIME_FORMAT *) 0, ltime, &str);
 
148
      set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED,
 
149
                           str.ptr(), str.length(), MYSQL_TIMESTAMP_DATETIME,1);
 
150
    }
 
151
  }
 
152
  else
 
153
  {
 
154
    tmp=0;
 
155
    error= 1;
 
156
    set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
 
157
  }
 
158
#ifdef WORDS_BIGENDIAN
 
159
  if (table && table->s->db_low_byte_first)
 
160
  {
 
161
    int8store(ptr,tmp);
 
162
  }
 
163
  else
 
164
#endif
 
165
    int64_tstore(ptr,tmp);
 
166
  return error;
 
167
}
 
168
 
 
169
bool Field_datetime::send_binary(Protocol *protocol)
 
170
{
 
171
  MYSQL_TIME tm;
 
172
  Field_datetime::get_date(&tm, TIME_FUZZY_DATE);
 
173
  return protocol->store(&tm);
 
174
}
 
175
 
 
176
 
 
177
double Field_datetime::val_real(void)
 
178
{
 
179
  return (double) Field_datetime::val_int();
 
180
}
 
181
 
 
182
int64_t Field_datetime::val_int(void)
 
183
{
 
184
  int64_t j;
 
185
#ifdef WORDS_BIGENDIAN
 
186
  if (table && table->s->db_low_byte_first)
 
187
    j=sint8korr(ptr);
 
188
  else
 
189
#endif
 
190
    int64_tget(j,ptr);
 
191
  return j;
 
192
}
 
193
 
 
194
 
 
195
String *Field_datetime::val_str(String *val_buffer,
 
196
                                String *val_ptr __attribute__((unused)))
 
197
{
 
198
  val_buffer->alloc(field_length);
 
199
  val_buffer->length(field_length);
 
200
  uint64_t tmp;
 
201
  long part1,part2;
 
202
  char *pos;
 
203
  int part3;
 
204
 
 
205
#ifdef WORDS_BIGENDIAN
 
206
  if (table && table->s->db_low_byte_first)
 
207
    tmp=sint8korr(ptr);
 
208
  else
 
209
#endif
 
210
    int64_tget(tmp,ptr);
 
211
 
 
212
  /*
 
213
    Avoid problem with slow int64_t arithmetic and sprintf
 
214
  */
 
215
 
 
216
  part1=(long) (tmp/1000000LL);
 
217
  part2=(long) (tmp - (uint64_t) part1*1000000LL);
 
218
 
 
219
  pos=(char*) val_buffer->ptr() + MAX_DATETIME_WIDTH;
 
220
  *pos--=0;
 
221
  *pos--= (char) ('0'+(char) (part2%10)); part2/=10;
 
222
  *pos--= (char) ('0'+(char) (part2%10)); part3= (int) (part2 / 10);
 
223
  *pos--= ':';
 
224
  *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
 
225
  *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
 
226
  *pos--= ':';
 
227
  *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
 
228
  *pos--= (char) ('0'+(char) part3);
 
229
  *pos--= ' ';
 
230
  *pos--= (char) ('0'+(char) (part1%10)); part1/=10;
 
231
  *pos--= (char) ('0'+(char) (part1%10)); part1/=10;
 
232
  *pos--= '-';
 
233
  *pos--= (char) ('0'+(char) (part1%10)); part1/=10;
 
234
  *pos--= (char) ('0'+(char) (part1%10)); part3= (int) (part1/10);
 
235
  *pos--= '-';
 
236
  *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
 
237
  *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
 
238
  *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
 
239
  *pos=(char) ('0'+(char) part3);
 
240
  return val_buffer;
 
241
}
 
242
 
 
243
bool Field_datetime::get_date(MYSQL_TIME *ltime, uint fuzzydate)
 
244
{
 
245
  int64_t tmp=Field_datetime::val_int();
 
246
  uint32 part1,part2;
 
247
  part1=(uint32) (tmp/1000000LL);
 
248
  part2=(uint32) (tmp - (uint64_t) part1*1000000LL);
 
249
 
 
250
  ltime->time_type=     MYSQL_TIMESTAMP_DATETIME;
 
251
  ltime->neg=           0;
 
252
  ltime->second_part=   0;
 
253
  ltime->second=        (int) (part2%100);
 
254
  ltime->minute=        (int) (part2/100%100);
 
255
  ltime->hour=          (int) (part2/10000);
 
256
  ltime->day=           (int) (part1%100);
 
257
  ltime->month=         (int) (part1/100%100);
 
258
  ltime->year=          (int) (part1/10000);
 
259
  return (!(fuzzydate & TIME_FUZZY_DATE) && (!ltime->month || !ltime->day)) ? 1 : 0;
 
260
}
 
261
 
 
262
bool Field_datetime::get_time(MYSQL_TIME *ltime)
 
263
{
 
264
  return Field_datetime::get_date(ltime,0);
 
265
}
 
266
 
 
267
int Field_datetime::cmp(const uchar *a_ptr, const uchar *b_ptr)
 
268
{
 
269
  int64_t a,b;
 
270
#ifdef WORDS_BIGENDIAN
 
271
  if (table && table->s->db_low_byte_first)
 
272
  {
 
273
    a=sint8korr(a_ptr);
 
274
    b=sint8korr(b_ptr);
 
275
  }
 
276
  else
 
277
#endif
 
278
  {
 
279
    int64_tget(a,a_ptr);
 
280
    int64_tget(b,b_ptr);
 
281
  }
 
282
  return ((uint64_t) a < (uint64_t) b) ? -1 :
 
283
    ((uint64_t) a > (uint64_t) b) ? 1 : 0;
 
284
}
 
285
 
 
286
void Field_datetime::sort_string(uchar *to,uint length __attribute__((unused)))
 
287
{
 
288
#ifdef WORDS_BIGENDIAN
 
289
  if (!table || !table->s->db_low_byte_first)
 
290
  {
 
291
    to[0] = ptr[0];
 
292
    to[1] = ptr[1];
 
293
    to[2] = ptr[2];
 
294
    to[3] = ptr[3];
 
295
    to[4] = ptr[4];
 
296
    to[5] = ptr[5];
 
297
    to[6] = ptr[6];
 
298
    to[7] = ptr[7];
 
299
  }
 
300
  else
 
301
#endif
 
302
  {
 
303
    to[0] = ptr[7];
 
304
    to[1] = ptr[6];
 
305
    to[2] = ptr[5];
 
306
    to[3] = ptr[4];
 
307
    to[4] = ptr[3];
 
308
    to[5] = ptr[2];
 
309
    to[6] = ptr[1];
 
310
    to[7] = ptr[0];
 
311
  }
 
312
}
 
313
 
 
314
 
 
315
void Field_datetime::sql_type(String &res) const
 
316
{
 
317
  res.set_ascii(STRING_WITH_LEN("datetime"));
 
318
}
 
319