~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/field/date.cc

pandora-build v0.100 - Fixes several bugs found by cb1kenobi. Add several thoughts from folks at LCA.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
 
1
/* - mode: c++ c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
3
 *
4
4
 *  Copyright (C) 2008 MySQL
18
18
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19
19
 */
20
20
 
21
 
#ifdef USE_PRAGMA_IMPLEMENTATION
22
 
#pragma implementation                          // gcc: Class implementation
23
 
#endif
24
 
 
25
 
#include <drizzled/server_includes.h>
26
 
#include <drizzled/field/date.h>
 
21
#include "config.h"
 
22
#include "drizzled/field/date.h"
 
23
#include "drizzled/error.h"
 
24
#include "drizzled/table.h"
 
25
#include "drizzled/temporal.h"
 
26
#include "drizzled/session.h"
 
27
#include "drizzled/time_functions.h"
 
28
 
 
29
#include <math.h>
 
30
 
 
31
#include <sstream>
 
32
#include <string>
 
33
 
27
34
 
28
35
/****************************************************************************
29
 
** The new date type
30
 
** This is identical to the old date type, but stored on 3 bytes instead of 4
 
36
** Drizzle date type stored in 3 bytes
31
37
** In number context: YYYYMMDD
32
38
****************************************************************************/
33
39
 
35
41
  Store string into a date field
36
42
 
37
43
  SYNOPSIS
38
 
    Field_newdate::store()
 
44
    Field_date::store()
39
45
    from                Date string
40
46
    len                 Length of date field
41
47
    cs                  Character set (not used)
49
55
       nearly-identical class Field_date doesn't ever return 3 from its
50
56
       store function.
51
57
*/
52
 
 
53
 
int Field_newdate::store(const char *from,
54
 
                         uint len,
55
 
                         const CHARSET_INFO * const cs __attribute__((unused)))
 
58
int Field_date::store(const char *from,
 
59
                         uint32_t len,
 
60
                         const CHARSET_INFO * const )
56
61
{
 
62
#ifdef NOTDEFINED
57
63
  long tmp;
58
64
  DRIZZLE_TIME l_time;
59
65
  int error;
60
 
  THD *thd= table ? table->in_use : current_thd;
 
66
  Session *session= table ? table->in_use : current_session;
61
67
  enum enum_drizzle_timestamp_type ret;
62
68
  if ((ret= str_to_datetime(from, len, &l_time,
63
69
                            (TIME_FUZZY_DATE |
64
 
                             (thd->variables.sql_mode &
65
 
                              (MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE |
66
 
                               MODE_INVALID_DATES))),
 
70
                             (session->variables.sql_mode &
 
71
                              (MODE_NO_ZERO_DATE | MODE_INVALID_DATES))),
67
72
                            &error)) <= DRIZZLE_TIMESTAMP_ERROR)
68
73
  {
69
74
    tmp= 0;
84
89
                         from, len, DRIZZLE_TIMESTAMP_DATE, 1);
85
90
 
86
91
  int3store(ptr, tmp);
87
 
  return error;
88
 
}
89
 
 
90
 
 
91
 
int Field_newdate::store(double nr)
92
 
{
93
 
  if (nr < 0.0 || nr > 99991231235959.0)
94
 
  {
95
 
    int3store(ptr,(int32_t) 0);
96
 
    set_datetime_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
97
 
                         ER_WARN_DATA_TRUNCATED, nr, DRIZZLE_TIMESTAMP_DATE);
98
 
    return 1;
99
 
  }
100
 
  return Field_newdate::store((int64_t) rint(nr), false);
101
 
}
102
 
 
103
 
 
104
 
int Field_newdate::store(int64_t nr,
105
 
                         bool unsigned_val __attribute__((unused)))
106
 
{
107
 
  DRIZZLE_TIME l_time;
108
 
  int64_t tmp;
109
 
  int error;
110
 
  THD *thd= table ? table->in_use : current_thd;
111
 
  if (number_to_datetime(nr, &l_time,
112
 
                         (TIME_FUZZY_DATE |
113
 
                          (thd->variables.sql_mode &
114
 
                           (MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE |
115
 
                            MODE_INVALID_DATES))),
116
 
                         &error) == -1LL)
117
 
  {
118
 
    tmp= 0L;
119
 
    error= 2;
120
 
  }
121
 
  else
122
 
    tmp= l_time.day + l_time.month*32 + l_time.year*16*32;
123
 
 
124
 
  if (!error && l_time.time_type != DRIZZLE_TIMESTAMP_DATE &&
125
 
      (l_time.hour || l_time.minute || l_time.second || l_time.second_part))
126
 
    error= 3;
127
 
 
128
 
  if (error)
129
 
    set_datetime_warning(error == 3 ? DRIZZLE_ERROR::WARN_LEVEL_NOTE :
130
 
                         DRIZZLE_ERROR::WARN_LEVEL_WARN,
131
 
                         error == 2 ? 
132
 
                         ER_WARN_DATA_OUT_OF_RANGE : ER_WARN_DATA_TRUNCATED,
133
 
                         nr,DRIZZLE_TIMESTAMP_DATE, 1);
134
 
 
135
 
  int3store(ptr,tmp);
136
 
  return error;
137
 
}
138
 
 
139
 
 
140
 
int Field_newdate::store_time(DRIZZLE_TIME *ltime,timestamp_type time_type)
 
92
#endif /* NOTDEFINED */
 
93
  /* 
 
94
   * Try to create a DateTime from the supplied string.  Throw an error
 
95
   * if unable to create a valid DateTime.  A DateTime is used so that
 
96
   * automatic conversion from the higher-storage DateTime can be used
 
97
   * and matches on datetime format strings can occur.
 
98
   */
 
99
  ASSERT_COLUMN_MARKED_FOR_WRITE;
 
100
  drizzled::DateTime temporal;
 
101
  if (! temporal.from_string(from, (size_t) len))
 
102
  {
 
103
    my_error(ER_INVALID_DATETIME_VALUE, MYF(ME_FATALERROR), from);
 
104
    return 2;
 
105
  }
 
106
  /* Create the stored integer format. @TODO This should go away. Should be up to engine... */
 
107
  uint32_t int_value= (temporal.years() * 16 * 32) + (temporal.months() * 32) + temporal.days();
 
108
  int3store(ptr, int_value);
 
109
  return 0;
 
110
}
 
111
 
 
112
int Field_date::store(double from)
 
113
{
 
114
  ASSERT_COLUMN_MARKED_FOR_WRITE;
 
115
  if (from < 0.0 || from > 99991231235959.0)
 
116
  {
 
117
    /* Convert the double to a string using stringstream */
 
118
    std::stringstream ss;
 
119
    std::string tmp;
 
120
    ss.precision(18); /* 18 places should be fine for error display of double input. */
 
121
    ss << from; ss >> tmp;
 
122
 
 
123
    my_error(ER_INVALID_DATETIME_VALUE, MYF(ME_FATALERROR), tmp.c_str());
 
124
    return 2;
 
125
  }
 
126
  return Field_date::store((int64_t) rint(from), false);
 
127
}
 
128
 
 
129
int Field_date::store(int64_t from, bool)
 
130
{
 
131
  /* 
 
132
   * Try to create a DateTime from the supplied integer.  Throw an error
 
133
   * if unable to create a valid DateTime.  
 
134
   */
 
135
  ASSERT_COLUMN_MARKED_FOR_WRITE;
 
136
  drizzled::DateTime temporal;
 
137
  if (! temporal.from_int64_t(from))
 
138
  {
 
139
    /* Convert the integer to a string using stringstream */
 
140
    std::stringstream ss;
 
141
    std::string tmp;
 
142
    ss << from; ss >> tmp;
 
143
 
 
144
    my_error(ER_INVALID_DATETIME_VALUE, MYF(ME_FATALERROR), tmp.c_str());
 
145
    return 2;
 
146
  }
 
147
 
 
148
  /* Create the stored integer format. @TODO This should go away. Should be up to engine... */
 
149
  uint32_t int_value= (temporal.years() * 16 * 32) + (temporal.months() * 32) + temporal.days();
 
150
  int3store(ptr, int_value);
 
151
  return 0;
 
152
}
 
153
 
 
154
int Field_date::store_time(DRIZZLE_TIME *ltime,
 
155
                              enum enum_drizzle_timestamp_type time_type)
141
156
{
142
157
  long tmp;
143
158
  int error= 0;
147
162
    tmp=ltime->year*16*32+ltime->month*32+ltime->day;
148
163
    if (check_date(ltime, tmp != 0,
149
164
                   (TIME_FUZZY_DATE |
150
 
                    (current_thd->variables.sql_mode &
151
 
                     (MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE |
152
 
                      MODE_INVALID_DATES))), &error))
 
165
                    (current_session->variables.sql_mode &
 
166
                     (MODE_NO_ZERO_DATE | MODE_INVALID_DATES))), &error))
153
167
    {
154
168
      char buff[MAX_DATE_STRING_REP_LENGTH];
155
 
      String str(buff, sizeof(buff), &my_charset_latin1);
156
 
      make_date((DATE_TIME_FORMAT *) 0, ltime, &str);
 
169
      String str(buff, sizeof(buff), &my_charset_utf8_general_ci);
 
170
      make_date(ltime, &str);
157
171
      set_datetime_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED,
158
172
                           str.ptr(), str.length(), DRIZZLE_TIMESTAMP_DATE, 1);
159
173
    }
161
175
        (ltime->hour || ltime->minute || ltime->second || ltime->second_part))
162
176
    {
163
177
      char buff[MAX_DATE_STRING_REP_LENGTH];
164
 
      String str(buff, sizeof(buff), &my_charset_latin1);
165
 
      make_datetime((DATE_TIME_FORMAT *) 0, ltime, &str);
 
178
      String str(buff, sizeof(buff), &my_charset_utf8_general_ci);
 
179
      make_datetime(ltime, &str);
166
180
      set_datetime_warning(DRIZZLE_ERROR::WARN_LEVEL_NOTE,
167
181
                           ER_WARN_DATA_TRUNCATED,
168
182
                           str.ptr(), str.length(), DRIZZLE_TIMESTAMP_DATE, 1);
179
193
  return error;
180
194
}
181
195
 
182
 
 
183
 
bool Field_newdate::send_binary(Protocol *protocol)
184
 
{
185
 
  DRIZZLE_TIME tm;
186
 
  Field_newdate::get_date(&tm,0);
187
 
  return protocol->store_date(&tm);
188
 
}
189
 
 
190
 
 
191
 
double Field_newdate::val_real(void)
192
 
{
193
 
  return (double) Field_newdate::val_int();
194
 
}
195
 
 
196
 
 
197
 
int64_t Field_newdate::val_int(void)
198
 
{
199
 
  uint32_t j= uint3korr(ptr);
 
196
double Field_date::val_real(void)
 
197
{
 
198
  return (double) Field_date::val_int();
 
199
}
 
200
 
 
201
int64_t Field_date::val_int(void)
 
202
{
 
203
  uint32_t j;
 
204
 
 
205
  ASSERT_COLUMN_MARKED_FOR_READ;
 
206
 
 
207
  j= uint3korr(ptr);
200
208
  j= (j % 32L)+(j / 32L % 16L)*100L + (j/(16L*32L))*10000L;
 
209
 
201
210
  return (int64_t) j;
202
211
}
203
212
 
204
 
 
205
 
String *Field_newdate::val_str(String *val_buffer,
206
 
                               String *val_ptr __attribute__((unused)))
 
213
String *Field_date::val_str(String *val_buffer,
 
214
                               String *)
207
215
{
208
216
  val_buffer->alloc(field_length);
209
217
  val_buffer->length(field_length);
211
219
  int part;
212
220
  char *pos=(char*) val_buffer->ptr()+10;
213
221
 
 
222
  ASSERT_COLUMN_MARKED_FOR_READ;
 
223
 
214
224
  /* Open coded to get more speed */
215
225
  *pos--=0;                                     // End NULL
216
226
  part=(int) (tmp & 31);
229
239
  return val_buffer;
230
240
}
231
241
 
232
 
 
233
 
bool Field_newdate::get_date(DRIZZLE_TIME *ltime,uint fuzzydate)
 
242
bool Field_date::get_date(DRIZZLE_TIME *ltime,uint32_t fuzzydate)
234
243
{
235
244
  uint32_t tmp=(uint32_t) uint3korr(ptr);
236
245
  ltime->day=   tmp & 31;
242
251
          1 : 0);
243
252
}
244
253
 
245
 
 
246
 
bool Field_newdate::get_time(DRIZZLE_TIME *ltime)
 
254
bool Field_date::get_time(DRIZZLE_TIME *ltime)
247
255
{
248
 
  return Field_newdate::get_date(ltime,0);
 
256
  return Field_date::get_date(ltime,0);
249
257
}
250
258
 
251
 
 
252
 
int Field_newdate::cmp(const uchar *a_ptr, const uchar *b_ptr)
 
259
int Field_date::cmp(const unsigned char *a_ptr, const unsigned char *b_ptr)
253
260
{
254
261
  uint32_t a,b;
255
262
  a=(uint32_t) uint3korr(a_ptr);
257
264
  return (a < b) ? -1 : (a > b) ? 1 : 0;
258
265
}
259
266
 
260
 
 
261
 
void Field_newdate::sort_string(uchar *to,uint length __attribute__((unused)))
 
267
void Field_date::sort_string(unsigned char *to,uint32_t )
262
268
{
263
269
  to[0] = ptr[2];
264
270
  to[1] = ptr[1];
265
271
  to[2] = ptr[0];
266
272
}
267
273
 
268
 
 
269
 
void Field_newdate::sql_type(String &res) const
 
274
void Field_date::sql_type(String &res) const
270
275
{
271
276
  res.set_ascii(STRING_WITH_LEN("date"));
272
277
}
273