~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/field/datetime.cc

  • Committer: Stewart Smith
  • Date: 2008-10-15 04:21:24 UTC
  • mto: This revision was merged to the branch mainline in revision 516.
  • Revision ID: stewart@flamingspork.com-20081015042124-kdmb74bcbky1k1nz
remove my_pthread_[gs]etspecific

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>
 
21
 
 
22
#include <drizzled/server_includes.h>
23
23
#include <drizzled/field/datetime.h>
24
 
#include <drizzled/error.h>
25
 
#include <drizzled/table.h>
26
 
#include <drizzled/temporal.h>
27
 
#include <drizzled/session.h>
28
 
 
29
 
#include <math.h>
30
 
 
31
 
#include <sstream>
32
 
#include <string>
33
 
 
34
 
 
35
 
namespace drizzled
36
 
{
37
24
 
38
25
/****************************************************************************
39
26
** datetime type
40
27
** In string context: YYYY-MM-DD HH:MM:DD
41
28
** In number context: YYYYMMDDHHMMDD
 
29
** Stored as a 8 byte unsigned int. Should sometimes be change to a 6 byte int.
42
30
****************************************************************************/
43
31
 
44
32
int Field_datetime::store(const char *from,
45
33
                          uint32_t len,
46
 
                          const CHARSET_INFO * const )
47
 
{
48
 
  ASSERT_COLUMN_MARKED_FOR_WRITE;
49
 
  /* 
50
 
   * Try to create a DateTime from the supplied string.  Throw an error
51
 
   * if unable to create a valid DateTime.  
52
 
   */
53
 
  DateTime temporal;
54
 
  if (! temporal.from_string(from, (size_t) len))
55
 
  {
56
 
    my_error(ER_INVALID_DATETIME_VALUE, MYF(ME_FATALERROR), from);
57
 
    return 2;
58
 
  }
59
 
  /* Create the stored integer format. @TODO This should go away. Should be up to engine... */
60
 
  int64_t int_value;
61
 
  temporal.to_int64_t(&int_value);
62
 
 
63
 
#ifdef WORDS_BIGENDIAN
64
 
  if (getTable() && getTable()->isDatabaseLowByteFirst())
65
 
  {
66
 
    int8store(ptr, int_value);
67
 
  }
68
 
  else
69
 
#endif
70
 
    int64_tstore(ptr, int_value);
71
 
  return 0;
72
 
}
73
 
 
74
 
int Field_datetime::store(double from)
75
 
{
76
 
  ASSERT_COLUMN_MARKED_FOR_WRITE;
77
 
  if (from < 0.0 || from > 99991231235959.0)
78
 
  {
79
 
    /* Convert the double to a string using boost::lexical_cast */
80
 
    std::string tmp(boost::lexical_cast<std::string>(from));
81
 
 
82
 
    my_error(ER_INVALID_DATETIME_VALUE, MYF(ME_FATALERROR), tmp.c_str());
83
 
    return 2;
84
 
  }
85
 
  return Field_datetime::store((int64_t) rint(from), false);
86
 
}
87
 
 
88
 
int Field_datetime::store(int64_t from, bool)
89
 
{
90
 
  ASSERT_COLUMN_MARKED_FOR_WRITE;
91
 
  /* 
92
 
   * Try to create a DateTime from the supplied integer.  Throw an error
93
 
   * if unable to create a valid DateTime.  
94
 
   */
95
 
  DateTime temporal;
96
 
  if (! temporal.from_int64_t(from))
97
 
  {
98
 
    /* Convert the integer to a string using boost::lexical_cast */
99
 
    std::string tmp(boost::lexical_cast<std::string>(from));
100
 
 
101
 
    my_error(ER_INVALID_DATETIME_VALUE, MYF(ME_FATALERROR), tmp.c_str());
102
 
    return 2;
103
 
  }
104
 
 
105
 
  /* 
106
 
   * Because "from" may be a silly MySQL-like "datetime number" (like, oh, 101)
107
 
   * we must here get the value of the DateTime as its *real* int64_t, after
108
 
   * the conversion above has been done...yuck. God, save us.
109
 
   */
110
 
  int64_t int_value;
111
 
  temporal.to_int64_t(&int_value);
112
 
 
113
 
#ifdef WORDS_BIGENDIAN
114
 
  if (getTable() && getTable()->isDatabaseLowByteFirst())
115
 
  {
116
 
    int8store(ptr, int_value);
117
 
  }
118
 
  else
119
 
#endif
120
 
    int64_tstore(ptr, int_value);
121
 
  return 0;
122
 
}
123
 
 
124
 
int Field_datetime::store_time(type::Time &ltime, type::timestamp_t)
125
 
{
126
 
  DateTime temporal;
127
 
 
128
 
  temporal.set_years(ltime.year);
129
 
  temporal.set_months(ltime.month);
130
 
  temporal.set_days(ltime.day);
131
 
  temporal.set_hours(ltime.hour);
132
 
  temporal.set_minutes(ltime.minute);
133
 
  temporal.set_seconds(ltime.second);
134
 
 
135
 
  if (! temporal.is_valid())
136
 
  {
137
 
    char tmp_string[type::Time::MAX_STRING_LENGTH];
138
 
    size_t tmp_string_len;
139
 
 
140
 
    tmp_string_len= temporal.to_string(tmp_string, type::Time::MAX_STRING_LENGTH);
141
 
    assert(tmp_string_len < type::Time::MAX_STRING_LENGTH);
142
 
    my_error(ER_INVALID_DATETIME_VALUE, MYF(ME_FATALERROR), tmp_string);
143
 
    return 1;
144
 
  }
145
 
 
146
 
  int64_t int_value;
147
 
  temporal.to_int64_t(&int_value);
148
 
 
149
 
#ifdef WORDS_BIGENDIAN
150
 
  if (getTable() && getTable()->isDatabaseLowByteFirst())
151
 
  {
152
 
    int8store(ptr, int_value);
153
 
  }
154
 
  else
155
 
#endif
156
 
    int64_tstore(ptr, int_value);
157
 
 
158
 
  return 0;
159
 
}
160
 
 
161
 
double Field_datetime::val_real(void) const
 
34
                          const CHARSET_INFO * const cs __attribute__((unused)))
 
35
{
 
36
  DRIZZLE_TIME time_tmp;
 
37
  int error;
 
38
  uint64_t tmp= 0;
 
39
  enum enum_drizzle_timestamp_type func_res;
 
40
  THD *thd= table ? table->in_use : current_thd;
 
41
 
 
42
  func_res= str_to_datetime(from, len, &time_tmp,
 
43
                            (TIME_FUZZY_DATE |
 
44
                             (thd->variables.sql_mode &
 
45
                              (MODE_NO_ZERO_DATE | MODE_INVALID_DATES))),
 
46
                            &error);
 
47
  if ((int) func_res > (int) DRIZZLE_TIMESTAMP_ERROR)
 
48
    tmp= TIME_to_uint64_t_datetime(&time_tmp);
 
49
  else
 
50
    error= 1;                                 // Fix if invalid zero date
 
51
 
 
52
  if (error)
 
53
    set_datetime_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
54
                         ER_WARN_DATA_OUT_OF_RANGE,
 
55
                         from, len, DRIZZLE_TIMESTAMP_DATETIME, 1);
 
56
 
 
57
#ifdef WORDS_BIGENDIAN
 
58
  if (table && table->s->db_low_byte_first)
 
59
  {
 
60
    int8store(ptr,tmp);
 
61
  }
 
62
  else
 
63
#endif
 
64
    int64_tstore(ptr,tmp);
 
65
  return error;
 
66
}
 
67
 
 
68
 
 
69
int Field_datetime::store(double nr)
 
70
{
 
71
  int error= 0;
 
72
  if (nr < 0.0 || nr > 99991231235959.0)
 
73
  {
 
74
    set_datetime_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN, 
 
75
                         ER_WARN_DATA_OUT_OF_RANGE,
 
76
                         nr, DRIZZLE_TIMESTAMP_DATETIME);
 
77
    nr= 0.0;
 
78
    error= 1;
 
79
  }
 
80
  error|= Field_datetime::store((int64_t) rint(nr), false);
 
81
  return error;
 
82
}
 
83
 
 
84
 
 
85
int Field_datetime::store(int64_t nr,
 
86
                          bool unsigned_val __attribute__((unused)))
 
87
{
 
88
  DRIZZLE_TIME not_used;
 
89
  int error;
 
90
  int64_t initial_nr= nr;
 
91
  THD *thd= table ? table->in_use : current_thd;
 
92
 
 
93
  nr= number_to_datetime(nr, &not_used, (TIME_FUZZY_DATE |
 
94
                                         (thd->variables.sql_mode &
 
95
                                          (MODE_NO_ZERO_DATE |
 
96
                                           MODE_INVALID_DATES))), &error);
 
97
 
 
98
  if (nr == INT64_C(-1))
 
99
  {
 
100
    nr= 0;
 
101
    error= 2;
 
102
  }
 
103
 
 
104
  if (error)
 
105
    set_datetime_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
106
                         error == 2 ? ER_WARN_DATA_OUT_OF_RANGE :
 
107
                         ER_WARN_DATA_TRUNCATED, initial_nr,
 
108
                         DRIZZLE_TIMESTAMP_DATETIME, 1);
 
109
 
 
110
#ifdef WORDS_BIGENDIAN
 
111
  if (table && table->s->db_low_byte_first)
 
112
  {
 
113
    int8store(ptr,nr);
 
114
  }
 
115
  else
 
116
#endif
 
117
    int64_tstore(ptr,nr);
 
118
  return error;
 
119
}
 
120
 
 
121
 
 
122
int Field_datetime::store_time(DRIZZLE_TIME *ltime,
 
123
                               enum enum_drizzle_timestamp_type time_type)
 
124
{
 
125
  int64_t tmp;
 
126
  int error= 0;
 
127
  /*
 
128
    We don't perform range checking here since values stored in TIME
 
129
    structure always fit into DATETIME range.
 
130
  */
 
131
  if (time_type == DRIZZLE_TIMESTAMP_DATE ||
 
132
      time_type == DRIZZLE_TIMESTAMP_DATETIME)
 
133
  {
 
134
    tmp=((ltime->year*10000L+ltime->month*100+ltime->day)*INT64_C(1000000)+
 
135
         (ltime->hour*10000L+ltime->minute*100+ltime->second));
 
136
    if (check_date(ltime, tmp != 0,
 
137
                   (TIME_FUZZY_DATE |
 
138
                    (current_thd->variables.sql_mode &
 
139
                     (MODE_NO_ZERO_DATE | MODE_INVALID_DATES))), &error))
 
140
    {
 
141
      char buff[MAX_DATE_STRING_REP_LENGTH];
 
142
      String str(buff, sizeof(buff), &my_charset_utf8_general_ci);
 
143
      make_datetime((DATE_TIME_FORMAT *) 0, ltime, &str);
 
144
      set_datetime_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED,
 
145
                           str.ptr(), str.length(), DRIZZLE_TIMESTAMP_DATETIME,1);
 
146
    }
 
147
  }
 
148
  else
 
149
  {
 
150
    tmp=0;
 
151
    error= 1;
 
152
    set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
 
153
  }
 
154
#ifdef WORDS_BIGENDIAN
 
155
  if (table && table->s->db_low_byte_first)
 
156
  {
 
157
    int8store(ptr,tmp);
 
158
  }
 
159
  else
 
160
#endif
 
161
    int64_tstore(ptr,tmp);
 
162
  return error;
 
163
}
 
164
 
 
165
bool Field_datetime::send_binary(Protocol *protocol)
 
166
{
 
167
  DRIZZLE_TIME tm;
 
168
  Field_datetime::get_date(&tm, TIME_FUZZY_DATE);
 
169
  return protocol->store(&tm);
 
170
}
 
171
 
 
172
 
 
173
double Field_datetime::val_real(void)
162
174
{
163
175
  return (double) Field_datetime::val_int();
164
176
}
165
177
 
166
 
int64_t Field_datetime::val_int(void) const
 
178
int64_t Field_datetime::val_int(void)
167
179
{
168
180
  int64_t j;
169
 
 
170
 
  ASSERT_COLUMN_MARKED_FOR_READ;
171
 
 
172
181
#ifdef WORDS_BIGENDIAN
173
 
  if (getTable() && getTable()->isDatabaseLowByteFirst())
 
182
  if (table && table->s->db_low_byte_first)
174
183
    j=sint8korr(ptr);
175
184
  else
176
185
#endif
179
188
}
180
189
 
181
190
 
182
 
String *Field_datetime::val_str(String *val_buffer, String *) const
 
191
String *Field_datetime::val_str(String *val_buffer,
 
192
                                String *val_ptr __attribute__((unused)))
183
193
{
184
 
  val_buffer->alloc(DateTime::MAX_STRING_LENGTH);
185
 
  val_buffer->length(DateTime::MAX_STRING_LENGTH);
186
 
  int64_t tmp;
187
 
 
188
 
  ASSERT_COLUMN_MARKED_FOR_READ;
 
194
  val_buffer->alloc(field_length);
 
195
  val_buffer->length(field_length);
 
196
  uint64_t tmp;
 
197
  long part1,part2;
 
198
  char *pos;
 
199
  int part3;
189
200
 
190
201
#ifdef WORDS_BIGENDIAN
191
 
  if (getTable() && getTable()->isDatabaseLowByteFirst())
 
202
  if (table && table->s->db_low_byte_first)
192
203
    tmp=sint8korr(ptr);
193
204
  else
194
205
#endif
195
206
    int64_tget(tmp,ptr);
196
207
 
197
 
  DateTime dt;
198
 
 
199
 
  /* TODO: add an assert that this succeeds
200
 
   * currently fails due to bug in allowing
201
 
   * ALTER TABLE to add a datetime column that's
202
 
   * not null without a default value.
203
 
   */
204
 
  dt.from_int64_t(tmp, false); /* NOTE: this does *NOT* attempt convertion
205
 
                                 from formats such as 20090101 as
206
 
                                 the stored value has already been
207
 
                                 converted.
208
 
                               */
209
 
 
210
 
  int rlen;
211
 
  rlen= dt.to_string((char*)val_buffer->ptr(), DateTime::MAX_STRING_LENGTH);
212
 
  assert((rlen+1) <  DateTime::MAX_STRING_LENGTH);
213
 
 
214
 
  val_buffer->length(rlen);
215
 
 
 
208
  /*
 
209
    Avoid problem with slow int64_t arithmetic and sprintf
 
210
  */
 
211
 
 
212
  part1=(long) (tmp/INT64_C(1000000));
 
213
  part2=(long) (tmp - (uint64_t) part1*INT64_C(1000000));
 
214
 
 
215
  pos=(char*) val_buffer->ptr() + MAX_DATETIME_WIDTH;
 
216
  *pos--=0;
 
217
  *pos--= (char) ('0'+(char) (part2%10)); part2/=10;
 
218
  *pos--= (char) ('0'+(char) (part2%10)); part3= (int) (part2 / 10);
 
219
  *pos--= ':';
 
220
  *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
 
221
  *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
 
222
  *pos--= ':';
 
223
  *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
 
224
  *pos--= (char) ('0'+(char) part3);
 
225
  *pos--= ' ';
 
226
  *pos--= (char) ('0'+(char) (part1%10)); part1/=10;
 
227
  *pos--= (char) ('0'+(char) (part1%10)); part1/=10;
 
228
  *pos--= '-';
 
229
  *pos--= (char) ('0'+(char) (part1%10)); part1/=10;
 
230
  *pos--= (char) ('0'+(char) (part1%10)); part3= (int) (part1/10);
 
231
  *pos--= '-';
 
232
  *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
 
233
  *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
 
234
  *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
 
235
  *pos=(char) ('0'+(char) part3);
216
236
  return val_buffer;
217
237
}
218
238
 
219
 
bool Field_datetime::get_date(type::Time &ltime, uint32_t fuzzydate) const
 
239
bool Field_datetime::get_date(DRIZZLE_TIME *ltime, uint32_t fuzzydate)
220
240
{
221
241
  int64_t tmp=Field_datetime::val_int();
222
242
  uint32_t part1,part2;
223
243
  part1=(uint32_t) (tmp/INT64_C(1000000));
224
244
  part2=(uint32_t) (tmp - (uint64_t) part1*INT64_C(1000000));
225
245
 
226
 
  ltime.time_type=      type::DRIZZLE_TIMESTAMP_DATETIME;
227
 
  ltime.neg=            0;
228
 
  ltime.second_part=    0;
229
 
  ltime.second= (int) (part2%100);
230
 
  ltime.minute= (int) (part2/100%100);
231
 
  ltime.hour=           (int) (part2/10000);
232
 
  ltime.day=            (int) (part1%100);
233
 
  ltime.month=  (int) (part1/100%100);
234
 
  ltime.year=           (int) (part1/10000);
235
 
 
236
 
  return (!(fuzzydate & TIME_FUZZY_DATE) && (!ltime.month || !ltime.day)) ? 1 : 0;
 
246
  ltime->time_type=     DRIZZLE_TIMESTAMP_DATETIME;
 
247
  ltime->neg=           0;
 
248
  ltime->second_part=   0;
 
249
  ltime->second=        (int) (part2%100);
 
250
  ltime->minute=        (int) (part2/100%100);
 
251
  ltime->hour=          (int) (part2/10000);
 
252
  ltime->day=           (int) (part1%100);
 
253
  ltime->month=         (int) (part1/100%100);
 
254
  ltime->year=          (int) (part1/10000);
 
255
  return (!(fuzzydate & TIME_FUZZY_DATE) && (!ltime->month || !ltime->day)) ? 1 : 0;
237
256
}
238
257
 
239
 
bool Field_datetime::get_time(type::Time &ltime) const
 
258
bool Field_datetime::get_time(DRIZZLE_TIME *ltime)
240
259
{
241
260
  return Field_datetime::get_date(ltime,0);
242
261
}
245
264
{
246
265
  int64_t a,b;
247
266
#ifdef WORDS_BIGENDIAN
248
 
  if (getTable() && getTable()->isDatabaseLowByteFirst())
 
267
  if (table && table->s->db_low_byte_first)
249
268
  {
250
269
    a=sint8korr(a_ptr);
251
270
    b=sint8korr(b_ptr);
260
279
    ((uint64_t) a > (uint64_t) b) ? 1 : 0;
261
280
}
262
281
 
263
 
void Field_datetime::sort_string(unsigned char *to,uint32_t )
 
282
void Field_datetime::sort_string(unsigned char *to,uint32_t length __attribute__((unused)))
264
283
{
265
284
#ifdef WORDS_BIGENDIAN
266
 
  if (not getTable() || not getTable()->isDatabaseLowByteFirst())
 
285
  if (!table || !table->s->db_low_byte_first)
267
286
  {
268
287
    to[0] = ptr[0];
269
288
    to[1] = ptr[1];
294
313
  res.set_ascii(STRING_WITH_LEN("datetime"));
295
314
}
296
315
 
297
 
} /* namespace drizzled */