~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/field/date.cc

  • Committer: Jay Pipes
  • Date: 2008-09-11 16:03:22 UTC
  • mto: (383.5.1 trunk)
  • mto: This revision was merged to the branch mainline in revision 386.
  • Revision ID: jay@mysql.com-20080911160322-vrl0k1djo6q6ytv1
Removed SQL_MODE variances from comment_table.test and ensured correct error thrown when a comment that is too long was input.  After moving to proto buffer definition for table, the 2048 length will go away.

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