1
/* -*- mode: c++ c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
* Copyright (C) 2008 Sun Microsystems, Inc.
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
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>
35
#include <drizzled/temporal.h>
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
48
Up to one of timestamps columns in the table can be automatically
49
set on row update and/or have NOW() as default value.
50
TABLE::timestamp_field points to Field object for such timestamp with
51
auto-set-on-update. TABLE::time_stamp holds offset in record + 1 for this
52
field, and is used by handler code which performs updates required.
54
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
57
and should go away in the future.
59
Also because of this limitation of binary .frm format we use 5 different
60
unireg_check values with TIMESTAMP field to distinguish various cases of
61
DEFAULT or ON UPDATE values. These values are:
63
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
66
field which has 0 as default value and is not automatically updated.
67
TIMESTAMP_DN_FIELD - field with NOW() as default but not set on update
68
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
71
default) (TIMESTAMP ON UPDATE NOW()).
72
TIMESTAMP_DNUN_FIELD - field which has now() as default and is auto-set on
73
update. (TIMESTAMP DEFAULT NOW() ON UPDATE NOW())
74
NONE - field which is not auto-set on update with some other than NOW()
75
default value (TIMESTAMP DEFAULT 0).
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
83
course is non-standard.) In most cases user won't notice any change, only
84
exception is different behavior of old/new timestamps during ALTER TABLE.
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) :
93
MicroTimestamp::MAX_STRING_LENGTH - 1, /* no \0 */
99
unireg_check= unireg_check_arg;
100
if (! share->getTimestampField() && unireg_check != NONE)
102
/* This timestamp has auto-update */
103
share->setTimestampField(this);
104
flags|= FUNCTION_DEFAULT_FLAG;
105
if (unireg_check != TIMESTAMP_DN_FIELD)
106
flags|= ON_UPDATE_NOW_FLAG;
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,
119
if (unireg_check != TIMESTAMP_DN_FIELD)
120
flags|= ON_UPDATE_NOW_FLAG;
124
Get auto-set type for TIMESTAMP field.
126
Returns value indicating during which operations this TIMESTAMP field
127
should be auto-set to current timestamp.
129
timestamp_auto_set_type Epoch::get_auto_set_type() const
131
switch (unireg_check)
133
case TIMESTAMP_DN_FIELD:
134
return TIMESTAMP_AUTO_SET_ON_INSERT;
135
case TIMESTAMP_UN_FIELD:
136
return TIMESTAMP_AUTO_SET_ON_UPDATE;
137
case TIMESTAMP_OLD_FIELD:
139
Although we can have several such columns in legacy tables this
140
function should be called only for first of them (i.e. the one
141
having auto-set property).
143
assert(getTable()->timestamp_field == this);
145
case TIMESTAMP_DNUN_FIELD:
146
return TIMESTAMP_AUTO_SET_ON_BOTH;
149
Normally this function should not be called for TIMESTAMPs without
153
return TIMESTAMP_NO_AUTO_SET;
157
int Epoch::store(const char *from,
159
const CHARSET_INFO * const )
163
ASSERT_COLUMN_MARKED_FOR_WRITE;
165
if (not temporal.from_string(from, (size_t) len))
167
my_error(ER_INVALID_TIMESTAMP_VALUE, MYF(ME_FATALERROR), from);
172
temporal.to_time_t(tmp);
174
uint64_t time_tmp= tmp;
179
int Epoch::store(double from)
181
ASSERT_COLUMN_MARKED_FOR_WRITE;
183
uint64_t from_tmp= (uint64_t)from;
186
if (not temporal.from_int64_t(from_tmp))
188
/* Convert the integer to a string using boost::lexical_cast */
189
std::string tmp(boost::lexical_cast<std::string>(from));
191
my_error(ER_INVALID_TIMESTAMP_VALUE, MYF(ME_FATALERROR), tmp.c_str());
196
temporal.to_time_t(tmp);
198
uint64_t tmp_micro= tmp;
204
int Epoch::store_decimal(const type::Decimal *value)
212
int Epoch::store(int64_t from, bool)
214
ASSERT_COLUMN_MARKED_FOR_WRITE;
217
* Try to create a DateTime from the supplied integer. Throw an error
218
* if unable to create a valid DateTime.
221
if (not temporal.from_int64_t(from))
223
/* Convert the integer to a string using boost::lexical_cast */
224
std::string tmp(boost::lexical_cast<std::string>(from));
226
my_error(ER_INVALID_TIMESTAMP_VALUE, MYF(ME_FATALERROR), tmp.c_str());
231
temporal.to_time_t(tmp);
239
double Epoch::val_real(void) const
241
return (double) Epoch::val_int();
244
int64_t Epoch::val_int(void) const
248
ASSERT_COLUMN_MARKED_FOR_READ;
253
(void) temporal.from_time_t((time_t) temp);
255
/* We must convert into a "timestamp-formatted integer" ... */
257
temporal.to_int64_t(&result);
261
String *Epoch::val_str(String *val_buffer, String *) const
265
int to_len= field_length + 1;
267
val_buffer->alloc(to_len);
268
to= (char *) val_buffer->ptr();
272
val_buffer->set_charset(&my_charset_bin); /* Safety */
275
(void) temporal.from_time_t((time_t) temp);
278
rlen= temporal.to_string(to, to_len);
279
assert(rlen < to_len);
281
val_buffer->length(rlen);
285
bool Epoch::get_date(type::Time <ime, uint32_t) const
288
type::Time::epoch_t time_temp;
295
ltime.store(time_temp);
300
bool Epoch::get_time(type::Time <ime) const
302
return Epoch::get_date(ltime, 0);
305
int Epoch::cmp(const unsigned char *a_ptr, const unsigned char *b_ptr)
309
unpack_num(a, a_ptr);
310
unpack_num(b, b_ptr);
312
return (a < b) ? -1 : (a > b) ? 1 : 0;
316
void Epoch::sort_string(unsigned char *to,uint32_t )
318
#ifdef WORDS_BIGENDIAN
319
if (!getTable() || !getTable()->getShare()->db_low_byte_first)
344
void Epoch::sql_type(String &res) const
346
res.set_ascii(STRING_WITH_LEN("timestamp"));
349
void Epoch::set_time()
351
Session *session= getTable() ? getTable()->in_use : current_session;
352
time_t tmp= session->getCurrentTimestampEpoch();
355
pack_num(static_cast<uint32_t>(tmp));
358
void Epoch::set_default()
360
if (getTable()->timestamp_field == this &&
361
unireg_check != TIMESTAMP_UN_FIELD)
367
Field::set_default();
371
long Epoch::get_timestamp(bool *null_value) const
373
if ((*null_value= is_null()))
377
return unpack_num(tmp);
380
size_t Epoch::max_string_length()
382
return sizeof(uint64_t);
385
} /* namespace field */
386
} /* namespace drizzled */