~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/field/epoch.cc

  • Committer: Olaf van der Spek
  • Date: 2011-06-23 11:44:30 UTC
  • mto: This revision was merged to the branch mainline in revision 2348.
  • Revision ID: olafvdspek@gmail.com-20110623114430-no355yypk4y3icqb
Refactor

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* -*- mode: c++ c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
3
 *
4
 
 *  Copyright (C) 2008 Sun Microsystems
 
4
 *  Copyright (C) 2008 Sun Microsystems, Inc.
5
5
 *
6
6
 *  This program is free software; you can redistribute it and/or modify
7
7
 *  it under the terms of the GNU General Public License as published by
18
18
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19
19
 */
20
20
 
21
 
#include "config.h"
 
21
#include <config.h>
22
22
#include <boost/lexical_cast.hpp>
23
 
#include <drizzled/field/timestamp.h>
 
23
#include <drizzled/field/epoch.h>
24
24
#include <drizzled/error.h>
25
 
#include <drizzled/tztime.h>
26
25
#include <drizzled/table.h>
27
26
#include <drizzled/session.h>
28
 
 
29
 
#include <math.h>
30
 
 
 
27
#include <drizzled/session/times.h>
 
28
#include <drizzled/current_session.h>
 
29
#include <drizzled/temporal.h>
 
30
#include <cmath>
31
31
#include <sstream>
32
32
 
33
 
#include "drizzled/temporal.h"
34
 
 
35
 
namespace drizzled
36
 
{
 
33
namespace drizzled {
 
34
namespace field {
37
35
 
38
36
/**
39
37
  TIMESTAMP type holds datetime values in range from 1970-01-01 00:00:01 UTC to
78
76
  course is non-standard.) In most cases user won't notice any change, only
79
77
  exception is different behavior of old/new timestamps during ALTER TABLE.
80
78
 */
81
 
Field_timestamp::Field_timestamp(unsigned char *ptr_arg,
82
 
                                 uint32_t,
83
 
                                 unsigned char *null_ptr_arg,
84
 
                                 unsigned char null_bit_arg,
85
 
                                 enum utype unireg_check_arg,
86
 
                                 const char *field_name_arg,
87
 
                                 TableShare *share,
88
 
                                 const CHARSET_INFO * const cs)
89
 
  :Field_str(ptr_arg,
90
 
             DateTime::MAX_STRING_LENGTH - 1 /* no \0 */,
91
 
             null_ptr_arg,
92
 
             null_bit_arg,
93
 
             field_name_arg,
94
 
             cs)
 
79
  Epoch::Epoch(unsigned char *ptr_arg,
 
80
               unsigned char *null_ptr_arg,
 
81
               unsigned char null_bit_arg,
 
82
               enum utype unireg_check_arg,
 
83
               const char *field_name_arg,
 
84
               drizzled::TableShare *share) :
 
85
  Field_str(ptr_arg,
 
86
            MicroTimestamp::MAX_STRING_LENGTH - 1, /* no \0 */
 
87
            null_ptr_arg,
 
88
            null_bit_arg,
 
89
            field_name_arg,
 
90
            &my_charset_bin)
95
91
{
96
 
  /* For 4.0 MYD and 4.0 InnoDB compatibility */
97
 
  flags|= UNSIGNED_FLAG;
98
92
  unireg_check= unireg_check_arg;
99
93
  if (! share->getTimestampField() && unireg_check != NONE)
100
94
  {
106
100
  }
107
101
}
108
102
 
109
 
Field_timestamp::Field_timestamp(bool maybe_null_arg,
110
 
                                 const char *field_name_arg,
111
 
                                 const CHARSET_INFO * const cs)
112
 
  :Field_str((unsigned char*) NULL,
113
 
             DateTime::MAX_STRING_LENGTH - 1 /* no \0 */,
114
 
             maybe_null_arg ? (unsigned char*) "": 0,
115
 
             0,
116
 
             field_name_arg,
117
 
             cs)
 
103
Epoch::Epoch(bool maybe_null_arg,
 
104
             const char *field_name_arg) :
 
105
  Field_str((unsigned char*) NULL,
 
106
            MicroTimestamp::MAX_STRING_LENGTH - 1, /* no \0 */
 
107
            maybe_null_arg ? (unsigned char*) "": 0,
 
108
            0,
 
109
            field_name_arg,
 
110
            &my_charset_bin)
118
111
{
119
 
  /* For 4.0 MYD and 4.0 InnoDB compatibility */
120
 
  flags|= UNSIGNED_FLAG;
121
112
  if (unireg_check != TIMESTAMP_DN_FIELD)
122
113
    flags|= ON_UPDATE_NOW_FLAG;
123
114
}
128
119
  Returns value indicating during which operations this TIMESTAMP field
129
120
  should be auto-set to current timestamp.
130
121
*/
131
 
timestamp_auto_set_type Field_timestamp::get_auto_set_type() const
 
122
timestamp_auto_set_type Epoch::get_auto_set_type() const
132
123
{
133
124
  switch (unireg_check)
134
125
  {
156
147
  }
157
148
}
158
149
 
159
 
int Field_timestamp::store(const char *from,
160
 
                           uint32_t len,
161
 
                           const CHARSET_INFO * const )
 
150
int Epoch::store(const char *from,
 
151
                 uint32_t len,
 
152
                 const charset_info_st * const )
162
153
{
163
154
  Timestamp temporal;
164
155
 
165
156
  ASSERT_COLUMN_MARKED_FOR_WRITE;
166
157
 
167
 
  if (! temporal.from_string(from, (size_t) len))
 
158
  if (not temporal.from_string(from, (size_t) len))
168
159
  {
169
 
    my_error(ER_INVALID_UNIX_TIMESTAMP_VALUE, MYF(ME_FATALERROR), from);
 
160
    my_error(ER_INVALID_TIMESTAMP_VALUE, MYF(ME_FATALERROR), from);
170
161
    return 1;
171
162
  }
172
163
 
173
164
  time_t tmp;
174
 
  temporal.to_time_t(&tmp);
 
165
  temporal.to_time_t(tmp);
175
166
 
176
 
  store_timestamp(tmp);
 
167
  uint64_t time_tmp= tmp;
 
168
  pack_num(time_tmp);
177
169
  return 0;
178
170
}
179
171
 
180
 
int Field_timestamp::store(double from)
 
172
int Epoch::store(double from)
181
173
{
182
174
  ASSERT_COLUMN_MARKED_FOR_WRITE;
183
175
 
184
 
  if (from < 0 || from > 99991231235959.0)
 
176
  uint64_t from_tmp= (uint64_t)from;
 
177
 
 
178
  Timestamp temporal;
 
179
  if (not temporal.from_int64_t(from_tmp))
185
180
  {
186
 
    /* Convert the double to a string using stringstream */
187
 
    std::stringstream ss;
188
 
    std::string tmp;
189
 
    ss.precision(18); /* 18 places should be fine for error display of double input. */
190
 
    ss << from; 
191
 
    ss >> tmp;
 
181
    /* Convert the integer to a string using boost::lexical_cast */
 
182
    std::string tmp(boost::lexical_cast<std::string>(from));
192
183
 
193
 
    my_error(ER_INVALID_UNIX_TIMESTAMP_VALUE, MYF(ME_FATALERROR), tmp.c_str());
 
184
    my_error(ER_INVALID_TIMESTAMP_VALUE, MYF(ME_FATALERROR), tmp.c_str());
194
185
    return 2;
195
186
  }
196
 
  return Field_timestamp::store((int64_t) rint(from), false);
197
 
}
198
 
 
199
 
int Field_timestamp::store(int64_t from, bool)
 
187
 
 
188
  time_t tmp;
 
189
  temporal.to_time_t(tmp);
 
190
 
 
191
  uint64_t tmp_micro= tmp;
 
192
  pack_num(tmp_micro);
 
193
 
 
194
  return 0;
 
195
}
 
196
 
 
197
int Epoch::store_decimal(const type::Decimal *value)
 
198
{
 
199
  double tmp;
 
200
  value->convert(tmp);
 
201
 
 
202
  return store(tmp);
 
203
}
 
204
 
 
205
int Epoch::store(int64_t from, bool)
200
206
{
201
207
  ASSERT_COLUMN_MARKED_FOR_WRITE;
202
208
 
205
211
   * if unable to create a valid DateTime.  
206
212
   */
207
213
  Timestamp temporal;
208
 
  if (! temporal.from_int64_t(from))
 
214
  if (not temporal.from_int64_t(from))
209
215
  {
210
216
    /* Convert the integer to a string using boost::lexical_cast */
211
217
    std::string tmp(boost::lexical_cast<std::string>(from));
212
218
 
213
 
    my_error(ER_INVALID_UNIX_TIMESTAMP_VALUE, MYF(ME_FATALERROR), tmp.c_str());
 
219
    my_error(ER_INVALID_TIMESTAMP_VALUE, MYF(ME_FATALERROR), tmp.c_str());
214
220
    return 2;
215
221
  }
216
222
 
217
223
  time_t tmp;
218
 
  temporal.to_time_t(&tmp);
219
 
 
220
 
  store_timestamp(tmp);
 
224
  temporal.to_time_t(tmp);
 
225
 
 
226
  uint64_t tmp64= tmp;
 
227
  pack_num(tmp64);
 
228
 
221
229
  return 0;
222
230
}
223
231
 
224
 
double Field_timestamp::val_real(void)
 
232
double Epoch::val_real(void) const
225
233
{
226
 
  return (double) Field_timestamp::val_int();
 
234
  return (double) Epoch::val_int();
227
235
}
228
236
 
229
 
int64_t Field_timestamp::val_int(void)
 
237
int64_t Epoch::val_int(void) const
230
238
{
231
239
  uint64_t temp;
232
240
 
233
241
  ASSERT_COLUMN_MARKED_FOR_READ;
234
242
 
235
 
#ifdef WORDS_BIGENDIAN
236
 
  if (getTable() && getTable()->getShare()->db_low_byte_first)
237
 
    temp= uint8korr(ptr);
238
 
  else
239
 
#endif
240
 
    int64_tget(temp, ptr);
 
243
  unpack_num(temp);
241
244
 
242
245
  Timestamp temporal;
243
246
  (void) temporal.from_time_t((time_t) temp);
248
251
  return result;
249
252
}
250
253
 
251
 
String *Field_timestamp::val_str(String *val_buffer, String *)
 
254
String *Epoch::val_str(String *val_buffer, String *) const
252
255
{
253
 
  uint64_t temp;
 
256
  uint64_t temp= 0;
254
257
  char *to;
255
258
  int to_len= field_length + 1;
256
259
 
257
260
  val_buffer->alloc(to_len);
258
261
  to= (char *) val_buffer->ptr();
259
262
 
260
 
#ifdef WORDS_BIGENDIAN
261
 
  if (getTable() && getTable()->getShare()->db_low_byte_first)
262
 
    temp= uint8korr(ptr);
263
 
  else
264
 
#endif
265
 
    int64_tget(temp, ptr);
 
263
  unpack_num(temp);
266
264
 
267
265
  val_buffer->set_charset(&my_charset_bin);     /* Safety */
268
266
 
277
275
  return val_buffer;
278
276
}
279
277
 
280
 
bool Field_timestamp::get_date(DRIZZLE_TIME *ltime, uint32_t)
 
278
bool Epoch::get_date(type::Time &ltime, uint32_t) const
281
279
{
282
280
  uint64_t temp;
 
281
  type::Time::epoch_t time_temp;
283
282
 
284
 
#ifdef WORDS_BIGENDIAN
285
 
  if (getTable() && getTable()->getShare()->db_low_byte_first)
286
 
    temp= uint8korr(ptr);
287
 
  else
288
 
#endif
289
 
    int64_tget(temp, ptr);
 
283
  unpack_num(temp);
 
284
  time_temp= temp;
290
285
  
291
 
  memset(ltime, 0, sizeof(*ltime));
292
 
 
293
 
  Timestamp temporal;
294
 
  (void) temporal.from_time_t((time_t) temp);
295
 
 
296
 
  /* @TODO Goodbye the below code when DRIZZLE_TIME is finally gone.. */
297
 
 
298
 
  ltime->time_type= DRIZZLE_TIMESTAMP_DATETIME;
299
 
  ltime->year= temporal.years();
300
 
  ltime->month= temporal.months();
301
 
  ltime->day= temporal.days();
302
 
  ltime->hour= temporal.hours();
303
 
  ltime->minute= temporal.minutes();
304
 
  ltime->second= temporal.seconds();
 
286
  ltime.reset();
 
287
 
 
288
  ltime.store(time_temp);
305
289
 
306
290
  return 0;
307
291
}
308
292
 
309
 
bool Field_timestamp::get_time(DRIZZLE_TIME *ltime)
310
 
{
311
 
  return Field_timestamp::get_date(ltime,0);
312
 
}
313
 
 
314
 
int Field_timestamp::cmp(const unsigned char *a_ptr, const unsigned char *b_ptr)
315
 
{
316
 
  int64_t a,b;
317
 
#ifdef WORDS_BIGENDIAN
318
 
  if (getTable() && getTable()->getShare()->db_low_byte_first)
319
 
  {
320
 
    a=sint8korr(a_ptr);
321
 
    b=sint8korr(b_ptr);
322
 
  }
323
 
  else
324
 
#endif
325
 
  {
326
 
    int64_tget(a, a_ptr);
327
 
    int64_tget(b, b_ptr);
328
 
  }
329
 
  return ((uint64_t) a < (uint64_t) b) ? -1 : ((uint64_t) a > (uint64_t) b) ? 1 : 0;
330
 
}
331
 
 
332
 
 
333
 
void Field_timestamp::sort_string(unsigned char *to,uint32_t )
 
293
bool Epoch::get_time(type::Time &ltime) const
 
294
{
 
295
  return Epoch::get_date(ltime, 0);
 
296
}
 
297
 
 
298
int Epoch::cmp(const unsigned char *a_ptr, const unsigned char *b_ptr)
 
299
{
 
300
  uint64_t a,b;
 
301
 
 
302
  unpack_num(a, a_ptr);
 
303
  unpack_num(b, b_ptr);
 
304
 
 
305
  return (a < b) ? -1 : (a > b) ? 1 : 0;
 
306
}
 
307
 
 
308
 
 
309
void Epoch::sort_string(unsigned char *to,uint32_t )
334
310
{
335
311
#ifdef WORDS_BIGENDIAN
336
312
  if (!getTable() || !getTable()->getShare()->db_low_byte_first)
358
334
  }
359
335
}
360
336
 
361
 
void Field_timestamp::sql_type(String &res) const
362
 
{
363
 
  res.set_ascii(STRING_WITH_LEN("timestamp"));
364
 
}
365
 
 
366
 
void Field_timestamp::set_time()
 
337
void Epoch::set_time()
367
338
{
368
339
  Session *session= getTable() ? getTable()->in_use : current_session;
369
 
  time_t tmp= session->query_start();
 
340
  time_t tmp= session->times.getCurrentTimestampEpoch();
 
341
 
370
342
  set_notnull();
371
 
  store_timestamp(tmp);
 
343
  pack_num(static_cast<uint32_t>(tmp));
372
344
}
373
345
 
374
 
void Field_timestamp::set_default()
 
346
void Epoch::set_default()
375
347
{
376
348
  if (getTable()->timestamp_field == this &&
377
349
      unireg_check != TIMESTAMP_UN_FIELD)
 
350
  {
378
351
    set_time();
 
352
  }
379
353
  else
 
354
  {
380
355
    Field::set_default();
 
356
  }
381
357
}
382
358
 
383
 
long Field_timestamp::get_timestamp(bool *null_value)
 
359
long Epoch::get_timestamp(bool *null_value) const
384
360
{
385
361
  if ((*null_value= is_null()))
386
362
    return 0;
387
 
#ifdef WORDS_BIGENDIAN
388
 
  if (getTable() && getTable()->getShare()->db_low_byte_first)
389
 
    return sint8korr(ptr);
390
 
#endif
391
 
  int64_t tmp;
392
 
  int64_tget(tmp, ptr);
393
 
  return tmp;
 
363
 
 
364
  uint64_t tmp;
 
365
  return unpack_num(tmp);
394
366
}
395
367
 
396
 
void Field_timestamp::store_timestamp(int64_t timestamp)
 
368
size_t Epoch::max_string_length()
397
369
{
398
 
#ifdef WORDS_BIGENDIAN
399
 
  if (getTable() && getTable()->getShare()->db_low_byte_first)
400
 
  {
401
 
    int8store(ptr, timestamp);
402
 
  }
403
 
  else
404
 
#endif
405
 
    int64_tstore(ptr, timestamp);
 
370
  return sizeof(uint64_t);
406
371
}
407
372
 
 
373
} /* namespace field */
408
374
} /* namespace drizzled */