~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/field/timestamp.cc

  • Committer: Brian Aker
  • Date: 2009-02-12 22:45:08 UTC
  • Revision ID: brian@tangent.org-20090212224508-mrd9jwgn1zjdpqdk
Minor refactoring (we will need to disconnect the code from the include
file).

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 MySQL
 
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
 
#ifdef USE_PRAGMA_IMPLEMENTATION
22
 
#pragma implementation                          // gcc: Class implementation
23
 
#endif
24
21
 
25
22
#include <drizzled/server_includes.h>
26
23
#include <drizzled/field/timestamp.h>
 
24
#include <drizzled/error.h>
 
25
#include <drizzled/tztime.h>
 
26
#include <drizzled/table.h>
 
27
#include <drizzled/session.h>
 
28
#include CMATH_H
 
29
 
 
30
#if defined(CMATH_NAMESPACE)
 
31
using namespace CMATH_NAMESPACE;
 
32
#endif
27
33
 
28
34
/**
29
 
  TIMESTAMP type holds datetime values in range from 1970-01-01 00:00:01 UTC to 
30
 
  2038-01-01 00:00:00 UTC stored as number of seconds since Unix 
 
35
  TIMESTAMP type holds datetime values in range from 1970-01-01 00:00:01 UTC to
 
36
  2038-01-01 00:00:00 UTC stored as number of seconds since Unix
31
37
  Epoch in UTC.
32
 
  
33
 
  Up to one of timestamps columns in the table can be automatically 
 
38
 
 
39
  Up to one of timestamps columns in the table can be automatically
34
40
  set on row update and/or have NOW() as default value.
35
 
  TABLE::timestamp_field points to Field object for such timestamp with 
 
41
  TABLE::timestamp_field points to Field object for such timestamp with
36
42
  auto-set-on-update. TABLE::time_stamp holds offset in record + 1 for this
37
43
  field, and is used by handler code which performs updates required.
38
 
  
 
44
 
39
45
  Actually SQL-99 says that we should allow niladic functions (like NOW())
40
 
  as defaults for any field. Current limitations (only NOW() and only 
41
 
  for one TIMESTAMP field) are because of restricted binary .frm format 
 
46
  as defaults for any field. Current limitations (only NOW() and only
 
47
  for one TIMESTAMP field) are because of restricted binary .frm format
42
48
  and should go away in the future.
43
 
  
 
49
 
44
50
  Also because of this limitation of binary .frm format we use 5 different
45
51
  unireg_check values with TIMESTAMP field to distinguish various cases of
46
52
  DEFAULT or ON UPDATE values. These values are:
47
 
  
 
53
 
48
54
  TIMESTAMP_OLD_FIELD - old timestamp, if there was not any fields with
49
 
    auto-set-on-update (or now() as default) in this table before, then this 
50
 
    field has NOW() as default and is updated when row changes, else it is 
 
55
    auto-set-on-update (or now() as default) in this table before, then this
 
56
    field has NOW() as default and is updated when row changes, else it is
51
57
    field which has 0 as default value and is not automatically updated.
52
58
  TIMESTAMP_DN_FIELD - field with NOW() as default but not set on update
53
59
    automatically (TIMESTAMP DEFAULT NOW())
54
 
  TIMESTAMP_UN_FIELD - field which is set on update automatically but has not 
55
 
    NOW() as default (but it may has 0 or some other const timestamp as 
 
60
  TIMESTAMP_UN_FIELD - field which is set on update automatically but has not
 
61
    NOW() as default (but it may has 0 or some other const timestamp as
56
62
    default) (TIMESTAMP ON UPDATE NOW()).
57
 
  TIMESTAMP_DNUN_FIELD - field which has now() as default and is auto-set on 
 
63
  TIMESTAMP_DNUN_FIELD - field which has now() as default and is auto-set on
58
64
    update. (TIMESTAMP DEFAULT NOW() ON UPDATE NOW())
59
 
  NONE - field which is not auto-set on update with some other than NOW() 
 
65
  NONE - field which is not auto-set on update with some other than NOW()
60
66
    default value (TIMESTAMP DEFAULT 0).
61
67
 
62
 
  Note that TIMESTAMP_OLD_FIELDs are never created explicitly now, they are 
63
 
  left only for preserving ability to read old tables. Such fields replaced 
64
 
  with their newer analogs in CREATE TABLE and in SHOW CREATE TABLE. This is 
65
 
  because we want to prefer NONE unireg_check before TIMESTAMP_OLD_FIELD for 
66
 
  "TIMESTAMP DEFAULT 'Const'" field. (Old timestamps allowed such 
67
 
  specification too but ignored default value for first timestamp, which of 
 
68
  Note that TIMESTAMP_OLD_FIELDs are never created explicitly now, they are
 
69
  left only for preserving ability to read old tables. Such fields replaced
 
70
  with their newer analogs in CREATE TABLE and in SHOW CREATE TABLE. This is
 
71
  because we want to prefer NONE unireg_check before TIMESTAMP_OLD_FIELD for
 
72
  "TIMESTAMP DEFAULT 'Const'" field. (Old timestamps allowed such
 
73
  specification too but ignored default value for first timestamp, which of
68
74
  course is non-standard.) In most cases user won't notice any change, only
69
75
  exception is different behavior of old/new timestamps during ALTER TABLE.
70
76
 */
71
77
 
72
78
Field_timestamp::Field_timestamp(unsigned char *ptr_arg,
73
 
                                 uint32_t len_arg __attribute__((unused)),
 
79
                                 uint32_t ,
74
80
                                 unsigned char *null_ptr_arg, unsigned char null_bit_arg,
75
81
                                 enum utype unireg_check_arg,
76
82
                                 const char *field_name_arg,
143
149
 
144
150
int Field_timestamp::store(const char *from,
145
151
                           uint32_t len,
146
 
                           const CHARSET_INFO * const cs __attribute__((unused)))
 
152
                           const CHARSET_INFO * const )
147
153
{
148
154
  DRIZZLE_TIME l_time;
149
 
  my_time_t tmp= 0;
 
155
  time_t tmp= 0;
150
156
  int error;
151
157
  bool have_smth_to_conv;
152
158
  bool in_dst_time_gap;
153
 
  THD *thd= table ? table->in_use : current_thd;
 
159
  Session *session= table ? table->in_use : current_session;
154
160
 
155
161
  /* We don't want to store invalid or fuzzy datetime values in TIMESTAMP */
156
162
  have_smth_to_conv= (str_to_datetime(from, len, &l_time, 1, &error) >
166
172
  /* Only convert a correct date (not a zero date) */
167
173
  if (have_smth_to_conv && l_time.month)
168
174
  {
169
 
    if (!(tmp= TIME_to_timestamp(thd, &l_time, &in_dst_time_gap)))
 
175
    if (!(tmp= TIME_to_timestamp(session, &l_time, &in_dst_time_gap)))
170
176
    {
171
177
      set_datetime_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
172
178
                           ER_WARN_DATA_OUT_OF_RANGE,
203
209
 
204
210
 
205
211
int Field_timestamp::store(int64_t nr,
206
 
                           bool unsigned_val __attribute__((unused)))
 
212
                           bool )
207
213
{
208
214
  DRIZZLE_TIME l_time;
209
 
  my_time_t timestamp= 0;
 
215
  time_t timestamp= 0;
210
216
  int error;
211
217
  bool in_dst_time_gap;
212
 
  THD *thd= table ? table->in_use : current_thd;
 
218
  Session *session= table ? table->in_use : current_session;
213
219
 
214
220
  /* We don't want to store invalid or fuzzy datetime values in TIMESTAMP */
215
 
  int64_t tmp= number_to_datetime(nr, &l_time, (thd->variables.sql_mode &
 
221
  int64_t tmp= number_to_datetime(nr, &l_time, (session->variables.sql_mode &
216
222
                                                 MODE_NO_ZERO_DATE), &error);
217
223
  if (tmp == INT64_C(-1))
218
224
  {
221
227
 
222
228
  if (!error && tmp)
223
229
  {
224
 
    if (!(timestamp= TIME_to_timestamp(thd, &l_time, &in_dst_time_gap)))
 
230
    if (!(timestamp= TIME_to_timestamp(session, &l_time, &in_dst_time_gap)))
225
231
    {
226
232
      set_datetime_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
227
233
                           ER_WARN_DATA_OUT_OF_RANGE,
253
259
{
254
260
  uint32_t temp;
255
261
  DRIZZLE_TIME time_tmp;
256
 
  THD  *thd= table ? table->in_use : current_thd;
 
262
  Session  *session= table ? table->in_use : current_session;
257
263
 
258
 
  thd->time_zone_used= 1;
259
264
#ifdef WORDS_BIGENDIAN
260
265
  if (table && table->s->db_low_byte_first)
261
266
    temp=uint4korr(ptr);
265
270
 
266
271
  if (temp == 0L)                               // No time
267
272
    return(0);                                  /* purecov: inspected */
268
 
  
269
 
  thd->variables.time_zone->gmt_sec_to_TIME(&time_tmp, (my_time_t)temp);
270
 
  
 
273
 
 
274
  session->variables.time_zone->gmt_sec_to_TIME(&time_tmp, (time_t)temp);
 
275
 
271
276
  return time_tmp.year * INT64_C(10000000000) +
272
277
         time_tmp.month * INT64_C(100000000) +
273
278
         time_tmp.day * 1000000 + time_tmp.hour * 10000 +
279
284
{
280
285
  uint32_t temp, temp2;
281
286
  DRIZZLE_TIME time_tmp;
282
 
  THD *thd= table ? table->in_use : current_thd;
 
287
  Session *session= table ? table->in_use : current_session;
283
288
  char *to;
284
289
 
285
290
  val_buffer->alloc(field_length+1);
286
291
  to= (char*) val_buffer->ptr();
287
292
  val_buffer->length(field_length);
288
293
 
289
 
  thd->time_zone_used= 1;
290
294
#ifdef WORDS_BIGENDIAN
291
295
  if (table && table->s->db_low_byte_first)
292
296
    temp=uint4korr(ptr);
300
304
    return val_ptr;
301
305
  }
302
306
  val_buffer->set_charset(&my_charset_bin);     // Safety
303
 
  
304
 
  thd->variables.time_zone->gmt_sec_to_TIME(&time_tmp,(my_time_t)temp);
 
307
 
 
308
  session->variables.time_zone->gmt_sec_to_TIME(&time_tmp,(time_t)temp);
305
309
 
306
310
  temp= time_tmp.year % 100;
307
311
  if (temp < YY_PART_YEAR - 1)
350
354
bool Field_timestamp::get_date(DRIZZLE_TIME *ltime, uint32_t fuzzydate)
351
355
{
352
356
  long temp;
353
 
  THD *thd= table ? table->in_use : current_thd;
354
 
  thd->time_zone_used= 1;
 
357
  Session *session= table ? table->in_use : current_session;
355
358
#ifdef WORDS_BIGENDIAN
356
359
  if (table && table->s->db_low_byte_first)
357
360
    temp=uint4korr(ptr);
366
369
  }
367
370
  else
368
371
  {
369
 
    thd->variables.time_zone->gmt_sec_to_TIME(ltime, (my_time_t)temp);
 
372
    session->variables.time_zone->gmt_sec_to_TIME(ltime, (time_t)temp);
370
373
  }
371
374
  return 0;
372
375
}
404
407
}
405
408
 
406
409
 
407
 
void Field_timestamp::sort_string(unsigned char *to,uint32_t length __attribute__((unused)))
 
410
void Field_timestamp::sort_string(unsigned char *to,uint32_t )
408
411
{
409
412
#ifdef WORDS_BIGENDIAN
410
413
  if (!table || !table->s->db_low_byte_first)
433
436
 
434
437
void Field_timestamp::set_time()
435
438
{
436
 
  THD *thd= table ? table->in_use : current_thd;
437
 
  long tmp= (long) thd->query_start();
 
439
  Session *session= table ? table->in_use : current_session;
 
440
  long tmp= (long) session->query_start();
438
441
  set_notnull();
439
442
  store_timestamp(tmp);
440
443
}
441
444
 
 
445
 
 
446
void Field_timestamp::set_default()
 
447
{
 
448
  if (table->timestamp_field == this &&
 
449
      unireg_check != TIMESTAMP_UN_FIELD)
 
450
    set_time();
 
451
  else
 
452
    Field::set_default();
 
453
}
 
454
 
 
455
long Field_timestamp::get_timestamp(bool *null_value)
 
456
{
 
457
  if ((*null_value= is_null()))
 
458
    return 0;
 
459
#ifdef WORDS_BIGENDIAN
 
460
  if (table && table->s->db_low_byte_first)
 
461
    return sint4korr(ptr);
 
462
#endif
 
463
  long tmp;
 
464
  longget(tmp,ptr);
 
465
  return tmp;
 
466
}
 
467
 
 
468
 
 
469
void Field_timestamp::store_timestamp(time_t timestamp)
 
470
{
 
471
#ifdef WORDS_BIGENDIAN
 
472
  if (table && table->s->db_low_byte_first)
 
473
  {
 
474
    int4store(ptr,timestamp);
 
475
  }
 
476
  else
 
477
#endif
 
478
    longstore(ptr,(uint32_t) timestamp);
 
479
}
 
480