~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/field/timestamp.cc

Renamed namespace slot to namespace service.

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