~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/field/date.cc

  • Committer: Monty Taylor
  • Date: 2008-10-30 18:44:27 UTC
  • mto: (520.4.35 devel)
  • mto: This revision was merged to the branch mainline in revision 572.
  • Revision ID: monty@inaugust.com-20081030184427-7cr1v6r5cqnuqm3v
Removed global sql_array.h.

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