~drizzle-trunk/drizzle/development

520.4.14 by Monty Taylor
Removed korr.h and tztime.h from common_includes. Also removed the HAVE_DTRACE block and stuck it in autoconf.
1
/* -*- mode: c++ c-basic-offset: 2; indent-tabs-mode: nil; -*-
173.1.6 by Toru Maesaka
ripped out TIMESTAMP and move to field/
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
 *
520.4.14 by Monty Taylor
Removed korr.h and tztime.h from common_includes. Also removed the HAVE_DTRACE block and stuck it in autoconf.
4
 *  Copyright (C) 2008 Sun Microsystems
173.1.6 by Toru Maesaka
ripped out TIMESTAMP and move to field/
5
 *
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.
10
 *
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.
15
 *
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
19
 */
20
21
243.1.17 by Jay Pipes
FINAL PHASE removal of mysql_priv.h (Bye, bye my friend.)
22
#include <drizzled/server_includes.h>
214 by Brian Aker
Rename of fields (fix issue with string and decimal .h clashing).
23
#include <drizzled/field/timestamp.h>
550 by Monty Taylor
Moved error.h into just the files that need it.
24
#include <drizzled/error.h>
520.4.14 by Monty Taylor
Removed korr.h and tztime.h from common_includes. Also removed the HAVE_DTRACE block and stuck it in autoconf.
25
#include <drizzled/tztime.h>
584.1.15 by Monty Taylor
The mega-patch from hell. Renamed sql_class to session (since that's what it is) and removed it and field and table from common_includes.
26
#include <drizzled/table.h>
27
#include <drizzled/session.h>
907.1.8 by Jay Pipes
Final removal of timezones
28
29
#include "drizzled/temporal.h"
30
173.1.6 by Toru Maesaka
ripped out TIMESTAMP and move to field/
31
/**
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
32
  TIMESTAMP type holds datetime values in range from 1970-01-01 00:00:01 UTC to
33
  2038-01-01 00:00:00 UTC stored as number of seconds since Unix
173.1.6 by Toru Maesaka
ripped out TIMESTAMP and move to field/
34
  Epoch in UTC.
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
35
36
  Up to one of timestamps columns in the table can be automatically
173.1.6 by Toru Maesaka
ripped out TIMESTAMP and move to field/
37
  set on row update and/or have NOW() as default value.
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
38
  TABLE::timestamp_field points to Field object for such timestamp with
173.1.6 by Toru Maesaka
ripped out TIMESTAMP and move to field/
39
  auto-set-on-update. TABLE::time_stamp holds offset in record + 1 for this
40
  field, and is used by handler code which performs updates required.
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
41
173.1.6 by Toru Maesaka
ripped out TIMESTAMP and move to field/
42
  Actually SQL-99 says that we should allow niladic functions (like NOW())
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
43
  as defaults for any field. Current limitations (only NOW() and only
44
  for one TIMESTAMP field) are because of restricted binary .frm format
173.1.6 by Toru Maesaka
ripped out TIMESTAMP and move to field/
45
  and should go away in the future.
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
46
173.1.6 by Toru Maesaka
ripped out TIMESTAMP and move to field/
47
  Also because of this limitation of binary .frm format we use 5 different
48
  unireg_check values with TIMESTAMP field to distinguish various cases of
49
  DEFAULT or ON UPDATE values. These values are:
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
50
173.1.6 by Toru Maesaka
ripped out TIMESTAMP and move to field/
51
  TIMESTAMP_OLD_FIELD - old timestamp, if there was not any fields with
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
52
    auto-set-on-update (or now() as default) in this table before, then this
53
    field has NOW() as default and is updated when row changes, else it is
173.1.6 by Toru Maesaka
ripped out TIMESTAMP and move to field/
54
    field which has 0 as default value and is not automatically updated.
55
  TIMESTAMP_DN_FIELD - field with NOW() as default but not set on update
56
    automatically (TIMESTAMP DEFAULT NOW())
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
57
  TIMESTAMP_UN_FIELD - field which is set on update automatically but has not
58
    NOW() as default (but it may has 0 or some other const timestamp as
173.1.6 by Toru Maesaka
ripped out TIMESTAMP and move to field/
59
    default) (TIMESTAMP ON UPDATE NOW()).
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
60
  TIMESTAMP_DNUN_FIELD - field which has now() as default and is auto-set on
173.1.6 by Toru Maesaka
ripped out TIMESTAMP and move to field/
61
    update. (TIMESTAMP DEFAULT NOW() ON UPDATE NOW())
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
62
  NONE - field which is not auto-set on update with some other than NOW()
173.1.6 by Toru Maesaka
ripped out TIMESTAMP and move to field/
63
    default value (TIMESTAMP DEFAULT 0).
64
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
65
  Note that TIMESTAMP_OLD_FIELDs are never created explicitly now, they are
66
  left only for preserving ability to read old tables. Such fields replaced
67
  with their newer analogs in CREATE TABLE and in SHOW CREATE TABLE. This is
68
  because we want to prefer NONE unireg_check before TIMESTAMP_OLD_FIELD for
69
  "TIMESTAMP DEFAULT 'Const'" field. (Old timestamps allowed such
70
  specification too but ignored default value for first timestamp, which of
173.1.6 by Toru Maesaka
ripped out TIMESTAMP and move to field/
71
  course is non-standard.) In most cases user won't notice any change, only
72
  exception is different behavior of old/new timestamps during ALTER TABLE.
73
 */
481 by Brian Aker
Remove all of uchar.
74
Field_timestamp::Field_timestamp(unsigned char *ptr_arg,
1119.9.12 by Jay Pipes
First phase removal of MTYP_TYPENR() macro. This removes the unireg_check argument for all Field types where it is irrelevant (everything but numeric types and timestamp.
75
                                 uint32_t,
76
                                 unsigned char *null_ptr_arg,
77
                                 unsigned char null_bit_arg,
173.1.6 by Toru Maesaka
ripped out TIMESTAMP and move to field/
78
                                 enum utype unireg_check_arg,
79
                                 const char *field_name_arg,
1000.1.3 by Brian Aker
Renamed TABLE_SHARE to TableShare
80
                                 TableShare *share,
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
81
                                 const CHARSET_INFO * const cs)
1079.4.1 by Stewart Smith
fix length of timestamp type for metadata test (and fix its result). See jay's description at https://code.launchpad.net/~stewart-flamingspork/drizzle/bug373468/+merge/8089
82
  :Field_str(ptr_arg,
83
             drizzled::DateTime::MAX_STRING_LENGTH - 1 /* no \0 */,
1119.9.12 by Jay Pipes
First phase removal of MTYP_TYPENR() macro. This removes the unireg_check argument for all Field types where it is irrelevant (everything but numeric types and timestamp.
84
             null_ptr_arg,
85
             null_bit_arg,
1119.9.14 by Jay Pipes
Style cleanups after review. Thanks Monty :)
86
             field_name_arg,
87
             cs)
173.1.6 by Toru Maesaka
ripped out TIMESTAMP and move to field/
88
{
89
  /* For 4.0 MYD and 4.0 InnoDB compatibility */
216 by Brian Aker
Remove completely ZEROFILL
90
  flags|= UNSIGNED_FLAG;
1119.9.12 by Jay Pipes
First phase removal of MTYP_TYPENR() macro. This removes the unireg_check argument for all Field types where it is irrelevant (everything but numeric types and timestamp.
91
  unireg_check= unireg_check_arg;
92
  if (! share->timestamp_field && unireg_check != NONE)
173.1.6 by Toru Maesaka
ripped out TIMESTAMP and move to field/
93
  {
94
    /* This timestamp has auto-update */
95
    share->timestamp_field= this;
96
    flags|= TIMESTAMP_FLAG;
97
    if (unireg_check != TIMESTAMP_DN_FIELD)
98
      flags|= ON_UPDATE_NOW_FLAG;
99
  }
100
}
101
102
Field_timestamp::Field_timestamp(bool maybe_null_arg,
103
                                 const char *field_name_arg,
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
104
                                 const CHARSET_INFO * const cs)
1119.9.14 by Jay Pipes
Style cleanups after review. Thanks Monty :)
105
  :Field_str((unsigned char*) NULL,
1079.4.1 by Stewart Smith
fix length of timestamp type for metadata test (and fix its result). See jay's description at https://code.launchpad.net/~stewart-flamingspork/drizzle/bug373468/+merge/8089
106
             drizzled::DateTime::MAX_STRING_LENGTH - 1 /* no \0 */,
1119.9.12 by Jay Pipes
First phase removal of MTYP_TYPENR() macro. This removes the unireg_check argument for all Field types where it is irrelevant (everything but numeric types and timestamp.
107
             maybe_null_arg ? (unsigned char*) "": 0,
108
             0,
1119.9.14 by Jay Pipes
Style cleanups after review. Thanks Monty :)
109
             field_name_arg,
1119.9.12 by Jay Pipes
First phase removal of MTYP_TYPENR() macro. This removes the unireg_check argument for all Field types where it is irrelevant (everything but numeric types and timestamp.
110
             cs)
173.1.6 by Toru Maesaka
ripped out TIMESTAMP and move to field/
111
{
112
  /* For 4.0 MYD and 4.0 InnoDB compatibility */
216 by Brian Aker
Remove completely ZEROFILL
113
  flags|= UNSIGNED_FLAG;
1119.9.12 by Jay Pipes
First phase removal of MTYP_TYPENR() macro. This removes the unireg_check argument for all Field types where it is irrelevant (everything but numeric types and timestamp.
114
  if (unireg_check != TIMESTAMP_DN_FIELD)
115
    flags|= ON_UPDATE_NOW_FLAG;
173.1.6 by Toru Maesaka
ripped out TIMESTAMP and move to field/
116
}
117
118
/**
119
  Get auto-set type for TIMESTAMP field.
120
121
  Returns value indicating during which operations this TIMESTAMP field
122
  should be auto-set to current timestamp.
123
*/
124
timestamp_auto_set_type Field_timestamp::get_auto_set_type() const
125
{
126
  switch (unireg_check)
127
  {
128
  case TIMESTAMP_DN_FIELD:
129
    return TIMESTAMP_AUTO_SET_ON_INSERT;
130
  case TIMESTAMP_UN_FIELD:
131
    return TIMESTAMP_AUTO_SET_ON_UPDATE;
132
  case TIMESTAMP_OLD_FIELD:
133
    /*
134
      Although we can have several such columns in legacy tables this
135
      function should be called only for first of them (i.e. the one
136
      having auto-set property).
137
    */
138
    assert(table->timestamp_field == this);
139
    /* Fall-through */
140
  case TIMESTAMP_DNUN_FIELD:
141
    return TIMESTAMP_AUTO_SET_ON_BOTH;
142
  default:
143
    /*
144
      Normally this function should not be called for TIMESTAMPs without
145
      auto-set property.
146
    */
147
    assert(0);
148
    return TIMESTAMP_NO_AUTO_SET;
149
  }
150
}
151
152
int Field_timestamp::store(const char *from,
482 by Brian Aker
Remove uint.
153
                           uint32_t len,
779.1.27 by Monty Taylor
Got rid of __attribute__((unused)) and the like from the .cc files.
154
                           const CHARSET_INFO * const )
173.1.6 by Toru Maesaka
ripped out TIMESTAMP and move to field/
155
{
907.1.7 by Jay Pipes
Merged in remove-timezone work
156
  drizzled::Timestamp temporal;
157
1089.1.3 by Brian Aker
Fix protobuf to release memory. Add in assert() for wrong column usage. Fix
158
  ASSERT_COLUMN_MARKED_FOR_WRITE;
159
907.1.7 by Jay Pipes
Merged in remove-timezone work
160
  if (! temporal.from_string(from, (size_t) len))
161
  {
162
    my_error(ER_INVALID_UNIX_TIMESTAMP_VALUE, MYF(ME_FATALERROR), from);
163
    return 1;
164
  }
165
166
  time_t tmp;
167
  temporal.to_time_t(&tmp);
168
169
  store_timestamp(tmp);
170
  return 0;
171
}
172
173
int Field_timestamp::store(double from)
174
{
1089.1.3 by Brian Aker
Fix protobuf to release memory. Add in assert() for wrong column usage. Fix
175
  ASSERT_COLUMN_MARKED_FOR_WRITE;
176
907.1.7 by Jay Pipes
Merged in remove-timezone work
177
  if (from < 0 || from > 99991231235959.0)
178
  {
179
    /* Convert the double to a string using stringstream */
180
    std::stringstream ss;
181
    std::string tmp;
182
    ss.precision(18); /* 18 places should be fine for error display of double input. */
183
    ss << from; ss >> tmp;
184
185
    my_error(ER_INVALID_UNIX_TIMESTAMP_VALUE, MYF(ME_FATALERROR), tmp.c_str());
186
    return 2;
187
  }
188
  return Field_timestamp::store((int64_t) rint(from), false);
189
}
190
191
int Field_timestamp::store(int64_t from, bool)
192
{
1089.1.3 by Brian Aker
Fix protobuf to release memory. Add in assert() for wrong column usage. Fix
193
  ASSERT_COLUMN_MARKED_FOR_WRITE;
194
907.1.7 by Jay Pipes
Merged in remove-timezone work
195
  /* 
196
   * Try to create a DateTime from the supplied integer.  Throw an error
197
   * if unable to create a valid DateTime.  
198
   */
199
  drizzled::Timestamp temporal;
200
  if (! temporal.from_int64_t(from))
201
  {
202
    /* Convert the integer to a string using stringstream */
203
    std::stringstream ss;
204
    std::string tmp;
205
    ss << from; ss >> tmp;
206
207
    my_error(ER_INVALID_UNIX_TIMESTAMP_VALUE, MYF(ME_FATALERROR), tmp.c_str());
208
    return 2;
209
  }
210
211
  time_t tmp;
212
  temporal.to_time_t(&tmp);
213
214
  store_timestamp(tmp);
215
  return 0;
173.1.6 by Toru Maesaka
ripped out TIMESTAMP and move to field/
216
}
217
218
double Field_timestamp::val_real(void)
219
{
220
  return (double) Field_timestamp::val_int();
221
}
222
223
int64_t Field_timestamp::val_int(void)
224
{
205 by Brian Aker
uint32 -> uin32_t
225
  uint32_t temp;
173.1.6 by Toru Maesaka
ripped out TIMESTAMP and move to field/
226
1089.1.3 by Brian Aker
Fix protobuf to release memory. Add in assert() for wrong column usage. Fix
227
  ASSERT_COLUMN_MARKED_FOR_READ;
228
173.1.6 by Toru Maesaka
ripped out TIMESTAMP and move to field/
229
#ifdef WORDS_BIGENDIAN
230
  if (table && table->s->db_low_byte_first)
907.1.8 by Jay Pipes
Final removal of timezones
231
    temp= uint4korr(ptr);
173.1.6 by Toru Maesaka
ripped out TIMESTAMP and move to field/
232
  else
233
#endif
907.1.8 by Jay Pipes
Final removal of timezones
234
    longget(temp, ptr);
235
236
  drizzled::Timestamp temporal;
237
  (void) temporal.from_time_t((time_t) temp);
238
239
  /* We must convert into a "timestamp-formatted integer" ... */
240
  int64_t result;
241
  temporal.to_int64_t(&result);
242
  return result;
173.1.6 by Toru Maesaka
ripped out TIMESTAMP and move to field/
243
}
244
907.1.8 by Jay Pipes
Final removal of timezones
245
String *Field_timestamp::val_str(String *val_buffer, String *)
173.1.6 by Toru Maesaka
ripped out TIMESTAMP and move to field/
246
{
907.1.8 by Jay Pipes
Final removal of timezones
247
  uint32_t temp;
173.1.6 by Toru Maesaka
ripped out TIMESTAMP and move to field/
248
  char *to;
1079.3.1 by Stewart Smith
Change temporal to_string routines to use snprintf instead of sprintf.
249
  int to_len= field_length + 1;
173.1.6 by Toru Maesaka
ripped out TIMESTAMP and move to field/
250
1079.3.1 by Stewart Smith
Change temporal to_string routines to use snprintf instead of sprintf.
251
  val_buffer->alloc(to_len);
907.1.8 by Jay Pipes
Final removal of timezones
252
  to= (char *) val_buffer->ptr();
173.1.6 by Toru Maesaka
ripped out TIMESTAMP and move to field/
253
254
#ifdef WORDS_BIGENDIAN
255
  if (table && table->s->db_low_byte_first)
907.1.8 by Jay Pipes
Final removal of timezones
256
    temp= uint4korr(ptr);
173.1.6 by Toru Maesaka
ripped out TIMESTAMP and move to field/
257
  else
258
#endif
907.1.8 by Jay Pipes
Final removal of timezones
259
    longget(temp, ptr);
260
261
  val_buffer->set_charset(&my_charset_bin);	/* Safety */
262
263
  drizzled::Timestamp temporal;
264
  (void) temporal.from_time_t((time_t) temp);
1079.3.1 by Stewart Smith
Change temporal to_string routines to use snprintf instead of sprintf.
265
266
  int rlen;
267
  rlen= temporal.to_string(to, to_len);
268
  assert(rlen < to_len);
269
1079.3.2 by Stewart Smith
Replace MAX_(DATE|TIME).*_WIDTH defines in definitions.h with real (and correct) static const members to Temporal types.
270
  val_buffer->length(rlen);
173.1.6 by Toru Maesaka
ripped out TIMESTAMP and move to field/
271
  return val_buffer;
272
}
273
907.1.8 by Jay Pipes
Final removal of timezones
274
bool Field_timestamp::get_date(DRIZZLE_TIME *ltime, uint32_t)
173.1.6 by Toru Maesaka
ripped out TIMESTAMP and move to field/
275
{
907.1.8 by Jay Pipes
Final removal of timezones
276
  uint32_t temp;
277
173.1.6 by Toru Maesaka
ripped out TIMESTAMP and move to field/
278
#ifdef WORDS_BIGENDIAN
279
  if (table && table->s->db_low_byte_first)
907.1.8 by Jay Pipes
Final removal of timezones
280
    temp= uint4korr(ptr);
173.1.6 by Toru Maesaka
ripped out TIMESTAMP and move to field/
281
  else
282
#endif
907.1.8 by Jay Pipes
Final removal of timezones
283
    longget(temp, ptr);
284
  
285
  memset(ltime, 0, sizeof(*ltime));
286
287
  drizzled::Timestamp temporal;
288
  (void) temporal.from_time_t((time_t) temp);
289
290
  /* @TODO Goodbye the below code when DRIZZLE_TIME is finally gone.. */
291
292
  ltime->time_type= DRIZZLE_TIMESTAMP_DATETIME;
293
  ltime->year= temporal.years();
294
  ltime->month= temporal.months();
295
  ltime->day= temporal.days();
296
  ltime->hour= temporal.hours();
297
  ltime->minute= temporal.minutes();
298
  ltime->second= temporal.seconds();
299
173.1.6 by Toru Maesaka
ripped out TIMESTAMP and move to field/
300
  return 0;
301
}
302
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
303
bool Field_timestamp::get_time(DRIZZLE_TIME *ltime)
173.1.6 by Toru Maesaka
ripped out TIMESTAMP and move to field/
304
{
305
  return Field_timestamp::get_date(ltime,0);
306
}
307
481 by Brian Aker
Remove all of uchar.
308
int Field_timestamp::cmp(const unsigned char *a_ptr, const unsigned char *b_ptr)
173.1.6 by Toru Maesaka
ripped out TIMESTAMP and move to field/
309
{
205 by Brian Aker
uint32 -> uin32_t
310
  int32_t a,b;
173.1.6 by Toru Maesaka
ripped out TIMESTAMP and move to field/
311
#ifdef WORDS_BIGENDIAN
312
  if (table && table->s->db_low_byte_first)
313
  {
314
    a=sint4korr(a_ptr);
315
    b=sint4korr(b_ptr);
316
  }
317
  else
318
#endif
319
  {
320
  longget(a,a_ptr);
321
  longget(b,b_ptr);
322
  }
205 by Brian Aker
uint32 -> uin32_t
323
  return ((uint32_t) a < (uint32_t) b) ? -1 : ((uint32_t) a > (uint32_t) b) ? 1 : 0;
173.1.6 by Toru Maesaka
ripped out TIMESTAMP and move to field/
324
}
325
326
779.1.27 by Monty Taylor
Got rid of __attribute__((unused)) and the like from the .cc files.
327
void Field_timestamp::sort_string(unsigned char *to,uint32_t )
173.1.6 by Toru Maesaka
ripped out TIMESTAMP and move to field/
328
{
329
#ifdef WORDS_BIGENDIAN
330
  if (!table || !table->s->db_low_byte_first)
331
  {
332
    to[0] = ptr[0];
333
    to[1] = ptr[1];
334
    to[2] = ptr[2];
335
    to[3] = ptr[3];
336
  }
337
  else
338
#endif
339
  {
340
    to[0] = ptr[3];
341
    to[1] = ptr[2];
342
    to[2] = ptr[1];
343
    to[3] = ptr[0];
344
  }
345
}
346
347
void Field_timestamp::sql_type(String &res) const
348
{
349
  res.set_ascii(STRING_WITH_LEN("timestamp"));
350
}
351
352
void Field_timestamp::set_time()
353
{
520.1.22 by Brian Aker
Second pass of thd cleanup
354
  Session *session= table ? table->in_use : current_session;
355
  long tmp= (long) session->query_start();
173.1.6 by Toru Maesaka
ripped out TIMESTAMP and move to field/
356
  set_notnull();
357
  store_timestamp(tmp);
358
}
359
584.1.13 by Monty Taylor
Split out a little more code. Removed table_list.h from common_includes.
360
void Field_timestamp::set_default()
361
{
362
  if (table->timestamp_field == this &&
363
      unireg_check != TIMESTAMP_UN_FIELD)
364
    set_time();
365
  else
366
    Field::set_default();
367
}
368
369
long Field_timestamp::get_timestamp(bool *null_value)
370
{
371
  if ((*null_value= is_null()))
372
    return 0;
373
#ifdef WORDS_BIGENDIAN
374
  if (table && table->s->db_low_byte_first)
375
    return sint4korr(ptr);
376
#endif
377
  long tmp;
378
  longget(tmp,ptr);
379
  return tmp;
380
}
381
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
382
void Field_timestamp::store_timestamp(time_t timestamp)
584.1.13 by Monty Taylor
Split out a little more code. Removed table_list.h from common_includes.
383
{
384
#ifdef WORDS_BIGENDIAN
385
  if (table && table->s->db_low_byte_first)
386
  {
387
    int4store(ptr,timestamp);
388
  }
389
  else
390
#endif
391
    longstore(ptr,(uint32_t) timestamp);
392
}