~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/field/timestamp.cc

  • Committer: Monty Taylor
  • Date: 2008-10-14 21:20:42 UTC
  • mto: (511.1.4 codestyle)
  • mto: This revision was merged to the branch mainline in revision 521.
  • Revision ID: monty@inaugust.com-20081014212042-tef3njx3368b6lwt
Override copy ctr and op= because we have pointer members.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* -*- mode: c++ c-basic-offset: 2; indent-tabs-mode: nil; -*-
 
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 MySQL
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
 
 
23
 
#include <boost/lexical_cast.hpp>
24
 
#include <drizzled/field/epoch.h>
25
 
#include <drizzled/error.h>
26
 
#include <drizzled/tztime.h>
27
 
#include <drizzled/table.h>
28
 
#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
 
{
 
21
 
 
22
#include <drizzled/server_includes.h>
 
23
#include <drizzled/field/timestamp.h>
42
24
 
43
25
/**
44
 
  TIMESTAMP type holds datetime values in range from 1970-01-01 00:00:01 UTC to
45
 
  2038-01-01 00:00:00 UTC stored as number of seconds since Unix
 
26
  TIMESTAMP type holds datetime values in range from 1970-01-01 00:00:01 UTC to 
 
27
  2038-01-01 00:00:00 UTC stored as number of seconds since Unix 
46
28
  Epoch in UTC.
47
 
 
48
 
  Up to one of timestamps columns in the table can be automatically
 
29
  
 
30
  Up to one of timestamps columns in the table can be automatically 
49
31
  set on row update and/or have NOW() as default value.
50
 
  TABLE::timestamp_field points to Field object for such timestamp with
 
32
  TABLE::timestamp_field points to Field object for such timestamp with 
51
33
  auto-set-on-update. TABLE::time_stamp holds offset in record + 1 for this
52
34
  field, and is used by handler code which performs updates required.
53
 
 
 
35
  
54
36
  Actually SQL-99 says that we should allow niladic functions (like NOW())
55
 
  as defaults for any field. Current limitations (only NOW() and only
56
 
  for one TIMESTAMP field) are because of restricted binary .frm format
 
37
  as defaults for any field. Current limitations (only NOW() and only 
 
38
  for one TIMESTAMP field) are because of restricted binary .frm format 
57
39
  and should go away in the future.
58
 
 
 
40
  
59
41
  Also because of this limitation of binary .frm format we use 5 different
60
42
  unireg_check values with TIMESTAMP field to distinguish various cases of
61
43
  DEFAULT or ON UPDATE values. These values are:
62
 
 
 
44
  
63
45
  TIMESTAMP_OLD_FIELD - old timestamp, if there was not any fields with
64
 
    auto-set-on-update (or now() as default) in this table before, then this
65
 
    field has NOW() as default and is updated when row changes, else it is
 
46
    auto-set-on-update (or now() as default) in this table before, then this 
 
47
    field has NOW() as default and is updated when row changes, else it is 
66
48
    field which has 0 as default value and is not automatically updated.
67
49
  TIMESTAMP_DN_FIELD - field with NOW() as default but not set on update
68
50
    automatically (TIMESTAMP DEFAULT NOW())
69
 
  TIMESTAMP_UN_FIELD - field which is set on update automatically but has not
70
 
    NOW() as default (but it may has 0 or some other const timestamp as
 
51
  TIMESTAMP_UN_FIELD - field which is set on update automatically but has not 
 
52
    NOW() as default (but it may has 0 or some other const timestamp as 
71
53
    default) (TIMESTAMP ON UPDATE NOW()).
72
 
  TIMESTAMP_DNUN_FIELD - field which has now() as default and is auto-set on
 
54
  TIMESTAMP_DNUN_FIELD - field which has now() as default and is auto-set on 
73
55
    update. (TIMESTAMP DEFAULT NOW() ON UPDATE NOW())
74
 
  NONE - field which is not auto-set on update with some other than NOW()
 
56
  NONE - field which is not auto-set on update with some other than NOW() 
75
57
    default value (TIMESTAMP DEFAULT 0).
76
58
 
77
 
  Note that TIMESTAMP_OLD_FIELDs are never created explicitly now, they are
78
 
  left only for preserving ability to read old tables. Such fields replaced
79
 
  with their newer analogs in CREATE TABLE and in SHOW CREATE TABLE. This is
80
 
  because we want to prefer NONE unireg_check before TIMESTAMP_OLD_FIELD for
81
 
  "TIMESTAMP DEFAULT 'Const'" field. (Old timestamps allowed such
82
 
  specification too but ignored default value for first timestamp, which of
 
59
  Note that TIMESTAMP_OLD_FIELDs are never created explicitly now, they are 
 
60
  left only for preserving ability to read old tables. Such fields replaced 
 
61
  with their newer analogs in CREATE TABLE and in SHOW CREATE TABLE. This is 
 
62
  because we want to prefer NONE unireg_check before TIMESTAMP_OLD_FIELD for 
 
63
  "TIMESTAMP DEFAULT 'Const'" field. (Old timestamps allowed such 
 
64
  specification too but ignored default value for first timestamp, which of 
83
65
  course is non-standard.) In most cases user won't notice any change, only
84
66
  exception is different behavior of old/new timestamps during ALTER TABLE.
85
67
 */
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)
 
68
 
 
69
Field_timestamp::Field_timestamp(unsigned char *ptr_arg,
 
70
                                 uint32_t len_arg __attribute__((unused)),
 
71
                                 unsigned char *null_ptr_arg, unsigned char null_bit_arg,
 
72
                                 enum utype unireg_check_arg,
 
73
                                 const char *field_name_arg,
 
74
                                 TABLE_SHARE *share,
 
75
                                 const CHARSET_INFO * const cs)
 
76
  :Field_str(ptr_arg, MAX_DATETIME_WIDTH, null_ptr_arg, null_bit_arg,
 
77
             unireg_check_arg, field_name_arg, cs)
98
78
{
99
 
  unireg_check= unireg_check_arg;
100
 
  if (! share->getTimestampField() && unireg_check != NONE)
 
79
  /* For 4.0 MYD and 4.0 InnoDB compatibility */
 
80
  flags|= UNSIGNED_FLAG;
 
81
  if (!share->timestamp_field && unireg_check != NONE)
101
82
  {
102
83
    /* This timestamp has auto-update */
103
 
    share->setTimestampField(this);
104
 
    flags|= FUNCTION_DEFAULT_FLAG;
 
84
    share->timestamp_field= this;
 
85
    flags|= TIMESTAMP_FLAG;
105
86
    if (unireg_check != TIMESTAMP_DN_FIELD)
106
87
      flags|= ON_UPDATE_NOW_FLAG;
107
88
  }
108
89
}
109
90
 
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)
 
91
 
 
92
Field_timestamp::Field_timestamp(bool maybe_null_arg,
 
93
                                 const char *field_name_arg,
 
94
                                 const CHARSET_INFO * const cs)
 
95
  :Field_str((unsigned char*) 0, MAX_DATETIME_WIDTH,
 
96
             maybe_null_arg ? (unsigned char*) "": 0, 0,
 
97
             NONE, field_name_arg, cs)
118
98
{
119
 
  if (unireg_check != TIMESTAMP_DN_FIELD)
120
 
    flags|= ON_UPDATE_NOW_FLAG;
 
99
  /* For 4.0 MYD and 4.0 InnoDB compatibility */
 
100
  flags|= UNSIGNED_FLAG;
 
101
    if (unireg_check != TIMESTAMP_DN_FIELD)
 
102
      flags|= ON_UPDATE_NOW_FLAG;
121
103
}
122
104
 
 
105
 
123
106
/**
124
107
  Get auto-set type for TIMESTAMP field.
125
108
 
126
109
  Returns value indicating during which operations this TIMESTAMP field
127
110
  should be auto-set to current timestamp.
128
111
*/
129
 
timestamp_auto_set_type Epoch::get_auto_set_type() const
 
112
timestamp_auto_set_type Field_timestamp::get_auto_set_type() const
130
113
{
131
114
  switch (unireg_check)
132
115
  {
140
123
      function should be called only for first of them (i.e. the one
141
124
      having auto-set property).
142
125
    */
143
 
    assert(getTable()->timestamp_field == this);
 
126
    assert(table->timestamp_field == this);
144
127
    /* Fall-through */
145
128
  case TIMESTAMP_DNUN_FIELD:
146
129
    return TIMESTAMP_AUTO_SET_ON_BOTH;
154
137
  }
155
138
}
156
139
 
157
 
int Epoch::store(const char *from,
158
 
                 uint32_t len,
159
 
                 const CHARSET_INFO * const )
160
 
{
161
 
  Timestamp temporal;
162
 
 
163
 
  ASSERT_COLUMN_MARKED_FOR_WRITE;
164
 
 
165
 
  if (not temporal.from_string(from, (size_t) len))
166
 
  {
167
 
    my_error(ER_INVALID_TIMESTAMP_VALUE, MYF(ME_FATALERROR), from);
168
 
    return 1;
169
 
  }
170
 
 
171
 
  time_t tmp;
172
 
  temporal.to_time_t(tmp);
173
 
 
174
 
  uint64_t time_tmp= tmp;
175
 
  pack_num(time_tmp);
176
 
  return 0;
177
 
}
178
 
 
179
 
int Epoch::store(double from)
180
 
{
181
 
  ASSERT_COLUMN_MARKED_FOR_WRITE;
182
 
 
183
 
  uint64_t from_tmp= (uint64_t)from;
184
 
 
185
 
  Timestamp temporal;
186
 
  if (not temporal.from_int64_t(from_tmp))
187
 
  {
188
 
    /* Convert the integer to a string using boost::lexical_cast */
189
 
    std::string tmp(boost::lexical_cast<std::string>(from));
190
 
 
191
 
    my_error(ER_INVALID_TIMESTAMP_VALUE, MYF(ME_FATALERROR), tmp.c_str());
192
 
    return 2;
193
 
  }
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)
213
 
{
214
 
  ASSERT_COLUMN_MARKED_FOR_WRITE;
215
 
 
216
 
  /* 
217
 
   * Try to create a DateTime from the supplied integer.  Throw an error
218
 
   * if unable to create a valid DateTime.  
219
 
   */
220
 
  Timestamp temporal;
221
 
  if (not temporal.from_int64_t(from))
222
 
  {
223
 
    /* Convert the integer to a string using boost::lexical_cast */
224
 
    std::string tmp(boost::lexical_cast<std::string>(from));
225
 
 
226
 
    my_error(ER_INVALID_TIMESTAMP_VALUE, MYF(ME_FATALERROR), tmp.c_str());
227
 
    return 2;
228
 
  }
229
 
 
230
 
  time_t tmp;
231
 
  temporal.to_time_t(tmp);
232
 
 
233
 
  uint64_t tmp64= tmp;
234
 
  pack_num(tmp64);
235
 
 
236
 
  return 0;
237
 
}
238
 
 
239
 
double Epoch::val_real(void) const
240
 
{
241
 
  return (double) Epoch::val_int();
242
 
}
243
 
 
244
 
int64_t Epoch::val_int(void) const
245
 
{
246
 
  uint64_t temp;
247
 
 
248
 
  ASSERT_COLUMN_MARKED_FOR_READ;
249
 
 
250
 
  unpack_num(temp);
251
 
 
252
 
  Timestamp temporal;
253
 
  (void) temporal.from_time_t((time_t) temp);
254
 
 
255
 
  /* We must convert into a "timestamp-formatted integer" ... */
256
 
  int64_t result;
257
 
  temporal.to_int64_t(&result);
258
 
  return result;
259
 
}
260
 
 
261
 
String *Epoch::val_str(String *val_buffer, String *) const
262
 
{
263
 
  uint64_t temp= 0;
 
140
 
 
141
int Field_timestamp::store(const char *from,
 
142
                           uint32_t len,
 
143
                           const CHARSET_INFO * const cs __attribute__((unused)))
 
144
{
 
145
  DRIZZLE_TIME l_time;
 
146
  my_time_t tmp= 0;
 
147
  int error;
 
148
  bool have_smth_to_conv;
 
149
  bool in_dst_time_gap;
 
150
  THD *thd= table ? table->in_use : current_thd;
 
151
 
 
152
  /* We don't want to store invalid or fuzzy datetime values in TIMESTAMP */
 
153
  have_smth_to_conv= (str_to_datetime(from, len, &l_time, 1, &error) >
 
154
                      DRIZZLE_TIMESTAMP_ERROR);
 
155
 
 
156
  if (error || !have_smth_to_conv)
 
157
  {
 
158
    error= 1;
 
159
    set_datetime_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED,
 
160
                         from, len, DRIZZLE_TIMESTAMP_DATETIME, 1);
 
161
  }
 
162
 
 
163
  /* Only convert a correct date (not a zero date) */
 
164
  if (have_smth_to_conv && l_time.month)
 
165
  {
 
166
    if (!(tmp= TIME_to_timestamp(thd, &l_time, &in_dst_time_gap)))
 
167
    {
 
168
      set_datetime_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
169
                           ER_WARN_DATA_OUT_OF_RANGE,
 
170
                           from, len, DRIZZLE_TIMESTAMP_DATETIME, !error);
 
171
      error= 1;
 
172
    }
 
173
    else if (in_dst_time_gap)
 
174
    {
 
175
      set_datetime_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
176
                           ER_WARN_INVALID_TIMESTAMP,
 
177
                           from, len, DRIZZLE_TIMESTAMP_DATETIME, !error);
 
178
      error= 1;
 
179
    }
 
180
  }
 
181
  store_timestamp(tmp);
 
182
  return error;
 
183
}
 
184
 
 
185
 
 
186
int Field_timestamp::store(double nr)
 
187
{
 
188
  int error= 0;
 
189
  if (nr < 0 || nr > 99991231235959.0)
 
190
  {
 
191
    set_datetime_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
192
                         ER_WARN_DATA_OUT_OF_RANGE,
 
193
                         nr, DRIZZLE_TIMESTAMP_DATETIME);
 
194
    nr= 0;                                      // Avoid overflow on buff
 
195
    error= 1;
 
196
  }
 
197
  error|= Field_timestamp::store((int64_t) rint(nr), false);
 
198
  return error;
 
199
}
 
200
 
 
201
 
 
202
int Field_timestamp::store(int64_t nr,
 
203
                           bool unsigned_val __attribute__((unused)))
 
204
{
 
205
  DRIZZLE_TIME l_time;
 
206
  my_time_t timestamp= 0;
 
207
  int error;
 
208
  bool in_dst_time_gap;
 
209
  THD *thd= table ? table->in_use : current_thd;
 
210
 
 
211
  /* We don't want to store invalid or fuzzy datetime values in TIMESTAMP */
 
212
  int64_t tmp= number_to_datetime(nr, &l_time, (thd->variables.sql_mode &
 
213
                                                 MODE_NO_ZERO_DATE), &error);
 
214
  if (tmp == INT64_C(-1))
 
215
  {
 
216
    error= 2;
 
217
  }
 
218
 
 
219
  if (!error && tmp)
 
220
  {
 
221
    if (!(timestamp= TIME_to_timestamp(thd, &l_time, &in_dst_time_gap)))
 
222
    {
 
223
      set_datetime_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
224
                           ER_WARN_DATA_OUT_OF_RANGE,
 
225
                           nr, DRIZZLE_TIMESTAMP_DATETIME, 1);
 
226
      error= 1;
 
227
    }
 
228
    if (in_dst_time_gap)
 
229
    {
 
230
      set_datetime_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
231
                           ER_WARN_INVALID_TIMESTAMP,
 
232
                           nr, DRIZZLE_TIMESTAMP_DATETIME, 1);
 
233
      error= 1;
 
234
    }
 
235
  } else if (error)
 
236
    set_datetime_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
237
                         ER_WARN_DATA_TRUNCATED,
 
238
                         nr, DRIZZLE_TIMESTAMP_DATETIME, 1);
 
239
 
 
240
  store_timestamp(timestamp);
 
241
  return error;
 
242
}
 
243
 
 
244
double Field_timestamp::val_real(void)
 
245
{
 
246
  return (double) Field_timestamp::val_int();
 
247
}
 
248
 
 
249
int64_t Field_timestamp::val_int(void)
 
250
{
 
251
  uint32_t temp;
 
252
  DRIZZLE_TIME time_tmp;
 
253
  THD  *thd= table ? table->in_use : current_thd;
 
254
 
 
255
  thd->time_zone_used= 1;
 
256
#ifdef WORDS_BIGENDIAN
 
257
  if (table && table->s->db_low_byte_first)
 
258
    temp=uint4korr(ptr);
 
259
  else
 
260
#endif
 
261
    longget(temp,ptr);
 
262
 
 
263
  if (temp == 0L)                               // No time
 
264
    return(0);                                  /* purecov: inspected */
 
265
  
 
266
  thd->variables.time_zone->gmt_sec_to_TIME(&time_tmp, (my_time_t)temp);
 
267
  
 
268
  return time_tmp.year * INT64_C(10000000000) +
 
269
         time_tmp.month * INT64_C(100000000) +
 
270
         time_tmp.day * 1000000 + time_tmp.hour * 10000 +
 
271
         time_tmp.minute * 100 + time_tmp.second;
 
272
}
 
273
 
 
274
 
 
275
String *Field_timestamp::val_str(String *val_buffer, String *val_ptr)
 
276
{
 
277
  uint32_t temp, temp2;
 
278
  DRIZZLE_TIME time_tmp;
 
279
  THD *thd= table ? table->in_use : current_thd;
264
280
  char *to;
265
 
  int to_len= field_length + 1;
266
 
 
267
 
  val_buffer->alloc(to_len);
268
 
  to= (char *) val_buffer->ptr();
269
 
 
270
 
  unpack_num(temp);
271
 
 
272
 
  val_buffer->set_charset(&my_charset_bin);     /* Safety */
273
 
 
274
 
  Timestamp temporal;
275
 
  (void) temporal.from_time_t((time_t) temp);
276
 
 
277
 
  int rlen;
278
 
  rlen= temporal.to_string(to, to_len);
279
 
  assert(rlen < to_len);
280
 
 
281
 
  val_buffer->length(rlen);
 
281
 
 
282
  val_buffer->alloc(field_length+1);
 
283
  to= (char*) val_buffer->ptr();
 
284
  val_buffer->length(field_length);
 
285
 
 
286
  thd->time_zone_used= 1;
 
287
#ifdef WORDS_BIGENDIAN
 
288
  if (table && table->s->db_low_byte_first)
 
289
    temp=uint4korr(ptr);
 
290
  else
 
291
#endif
 
292
    longget(temp,ptr);
 
293
 
 
294
  if (temp == 0L)
 
295
  {                                   /* Zero time is "000000" */
 
296
    val_ptr->set(STRING_WITH_LEN("0000-00-00 00:00:00"), &my_charset_bin);
 
297
    return val_ptr;
 
298
  }
 
299
  val_buffer->set_charset(&my_charset_bin);     // Safety
 
300
  
 
301
  thd->variables.time_zone->gmt_sec_to_TIME(&time_tmp,(my_time_t)temp);
 
302
 
 
303
  temp= time_tmp.year % 100;
 
304
  if (temp < YY_PART_YEAR - 1)
 
305
  {
 
306
    *to++= '2';
 
307
    *to++= '0';
 
308
  }
 
309
  else
 
310
  {
 
311
    *to++= '1';
 
312
    *to++= '9';
 
313
  }
 
314
  temp2=temp/10; temp=temp-temp2*10;
 
315
  *to++= (char) ('0'+(char) (temp2));
 
316
  *to++= (char) ('0'+(char) (temp));
 
317
  *to++= '-';
 
318
  temp=time_tmp.month;
 
319
  temp2=temp/10; temp=temp-temp2*10;
 
320
  *to++= (char) ('0'+(char) (temp2));
 
321
  *to++= (char) ('0'+(char) (temp));
 
322
  *to++= '-';
 
323
  temp=time_tmp.day;
 
324
  temp2=temp/10; temp=temp-temp2*10;
 
325
  *to++= (char) ('0'+(char) (temp2));
 
326
  *to++= (char) ('0'+(char) (temp));
 
327
  *to++= ' ';
 
328
  temp=time_tmp.hour;
 
329
  temp2=temp/10; temp=temp-temp2*10;
 
330
  *to++= (char) ('0'+(char) (temp2));
 
331
  *to++= (char) ('0'+(char) (temp));
 
332
  *to++= ':';
 
333
  temp=time_tmp.minute;
 
334
  temp2=temp/10; temp=temp-temp2*10;
 
335
  *to++= (char) ('0'+(char) (temp2));
 
336
  *to++= (char) ('0'+(char) (temp));
 
337
  *to++= ':';
 
338
  temp=time_tmp.second;
 
339
  temp2=temp/10; temp=temp-temp2*10;
 
340
  *to++= (char) ('0'+(char) (temp2));
 
341
  *to++= (char) ('0'+(char) (temp));
 
342
  *to= 0;
282
343
  return val_buffer;
283
344
}
284
345
 
285
 
bool Epoch::get_date(type::Time &ltime, uint32_t) const
 
346
 
 
347
bool Field_timestamp::get_date(DRIZZLE_TIME *ltime, uint32_t fuzzydate)
286
348
{
287
 
  uint64_t temp;
288
 
  type::Time::epoch_t time_temp;
289
 
 
290
 
  unpack_num(temp);
291
 
  time_temp= temp;
292
 
  
293
 
  ltime.reset();
294
 
 
295
 
  ltime.store(time_temp);
296
 
 
 
349
  long temp;
 
350
  THD *thd= table ? table->in_use : current_thd;
 
351
  thd->time_zone_used= 1;
 
352
#ifdef WORDS_BIGENDIAN
 
353
  if (table && table->s->db_low_byte_first)
 
354
    temp=uint4korr(ptr);
 
355
  else
 
356
#endif
 
357
    longget(temp,ptr);
 
358
  if (temp == 0L)
 
359
  {                                   /* Zero time is "000000" */
 
360
    if (fuzzydate & TIME_NO_ZERO_DATE)
 
361
      return 1;
 
362
    memset(ltime, 0, sizeof(*ltime));
 
363
  }
 
364
  else
 
365
  {
 
366
    thd->variables.time_zone->gmt_sec_to_TIME(ltime, (my_time_t)temp);
 
367
  }
297
368
  return 0;
298
369
}
299
370
 
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)
 
371
bool Field_timestamp::get_time(DRIZZLE_TIME *ltime)
 
372
{
 
373
  return Field_timestamp::get_date(ltime,0);
 
374
}
 
375
 
 
376
 
 
377
bool Field_timestamp::send_binary(Protocol *protocol)
 
378
{
 
379
  DRIZZLE_TIME tm;
 
380
  Field_timestamp::get_date(&tm, 0);
 
381
  return protocol->store(&tm);
 
382
}
 
383
 
 
384
 
 
385
int Field_timestamp::cmp(const unsigned char *a_ptr, const unsigned char *b_ptr)
 
386
{
 
387
  int32_t a,b;
 
388
#ifdef WORDS_BIGENDIAN
 
389
  if (table && table->s->db_low_byte_first)
 
390
  {
 
391
    a=sint4korr(a_ptr);
 
392
    b=sint4korr(b_ptr);
 
393
  }
 
394
  else
 
395
#endif
 
396
  {
 
397
  longget(a,a_ptr);
 
398
  longget(b,b_ptr);
 
399
  }
 
400
  return ((uint32_t) a < (uint32_t) b) ? -1 : ((uint32_t) a > (uint32_t) b) ? 1 : 0;
 
401
}
 
402
 
 
403
 
 
404
void Field_timestamp::sort_string(unsigned char *to,uint32_t length __attribute__((unused)))
 
405
{
 
406
#ifdef WORDS_BIGENDIAN
 
407
  if (!table || !table->s->db_low_byte_first)
320
408
  {
321
409
    to[0] = ptr[0];
322
410
    to[1] = ptr[1];
323
411
    to[2] = ptr[2];
324
412
    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
413
  }
330
414
  else
331
415
#endif
332
416
  {
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];
 
417
    to[0] = ptr[3];
 
418
    to[1] = ptr[2];
 
419
    to[2] = ptr[1];
 
420
    to[3] = ptr[0];
341
421
  }
342
422
}
343
423
 
344
 
void Epoch::sql_type(String &res) const
 
424
 
 
425
void Field_timestamp::sql_type(String &res) const
345
426
{
346
427
  res.set_ascii(STRING_WITH_LEN("timestamp"));
347
428
}
348
429
 
349
 
void Epoch::set_time()
 
430
 
 
431
void Field_timestamp::set_time()
350
432
{
351
 
  Session *session= getTable() ? getTable()->in_use : current_session;
352
 
  time_t tmp= session->getCurrentTimestampEpoch();
353
 
 
 
433
  THD *thd= table ? table->in_use : current_thd;
 
434
  long tmp= (long) thd->query_start();
354
435
  set_notnull();
355
 
  pack_num(static_cast<uint32_t>(tmp));
356
 
}
357
 
 
358
 
void Epoch::set_default()
359
 
{
360
 
  if (getTable()->timestamp_field == this &&
361
 
      unireg_check != TIMESTAMP_UN_FIELD)
362
 
  {
363
 
    set_time();
364
 
  }
365
 
  else
366
 
  {
367
 
    Field::set_default();
368
 
  }
369
 
}
370
 
 
371
 
long Epoch::get_timestamp(bool *null_value) const
372
 
{
373
 
  if ((*null_value= is_null()))
374
 
    return 0;
375
 
 
376
 
  uint64_t tmp;
377
 
  return unpack_num(tmp);
378
 
}
379
 
 
380
 
size_t Epoch::max_string_length()
381
 
{
382
 
  return sizeof(uint64_t);
383
 
}
384
 
 
385
 
} /* namespace field */
386
 
} /* namespace drizzled */
 
436
  store_timestamp(tmp);
 
437
}
 
438