~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/field/datetime.cc

  • Committer: Brian Aker
  • Date: 2009-01-24 09:43:35 UTC
  • Revision ID: brian@gir-3.local-20090124094335-6qdtvc35gl5fvivz
Adding in an example singe thread scheduler

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