~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/field/date.cc

  • Committer: Monty Taylor
  • Date: 2008-12-06 22:41:03 UTC
  • mto: (656.1.7 devel)
  • mto: This revision was merged to the branch mainline in revision 665.
  • Revision ID: monty@inaugust.com-20081206224103-jdouqwt9hb0f01y1
Moved non-working tests into broken suite for easier running of working tests.

Show diffs side-by-side

added added

removed removed

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