~drizzle-trunk/drizzle/development

2046.2.1 by Brian Aker
First pass on micro timestamp.
1
/* -*- mode: c++ c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
 *
4
 *  Copyright (C) 2008 Sun Microsystems, Inc.
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
#include "config.h"
22
#include <boost/lexical_cast.hpp>
23
#include <drizzled/field/microtime.h>
24
#include <drizzled/error.h>
25
#include <drizzled/tztime.h>
26
#include <drizzled/table.h>
27
#include <drizzled/session.h>
28
29
#include <math.h>
30
31
#include <sstream>
32
2057.2.2 by Brian Aker
Merge in fixes for microtimestamp,
33
#include <boost/date_time/posix_time/posix_time.hpp>
34
2046.2.1 by Brian Aker
First pass on micro timestamp.
35
#include "drizzled/temporal.h"
36
37
namespace drizzled
38
{
39
40
namespace field
41
{
2046.2.3 by Brian Aker
Add basic tests for microtime.
42
2057.2.2 by Brian Aker
Merge in fixes for microtimestamp,
43
static boost::posix_time::ptime _epoch(boost::gregorian::date(1970, 1, 1));
2046.2.3 by Brian Aker
Add basic tests for microtime.
44
2046.2.1 by Brian Aker
First pass on micro timestamp.
45
Microtime::Microtime(unsigned char *ptr_arg,
46
                     unsigned char *null_ptr_arg,
47
                     unsigned char null_bit_arg,
48
                     enum utype unireg_check_arg,
49
                     const char *field_name_arg,
50
                     drizzled::TableShare *share) :
51
  Epoch(ptr_arg,
52
        null_ptr_arg,
53
        null_bit_arg,
54
        unireg_check_arg,
55
        field_name_arg,
56
        share)
57
  {
58
  }
59
60
Microtime::Microtime(bool maybe_null_arg,
61
                     const char *field_name_arg) :
62
  Epoch(maybe_null_arg,
63
        field_name_arg)
64
{
65
}
66
67
int Microtime::store(const char *from,
2046.2.3 by Brian Aker
Add basic tests for microtime.
68
                     uint32_t len,
69
                     const CHARSET_INFO * const )
2046.2.1 by Brian Aker
First pass on micro timestamp.
70
{
2046.2.3 by Brian Aker
Add basic tests for microtime.
71
  MicroTimestamp temporal;
2046.2.1 by Brian Aker
First pass on micro timestamp.
72
73
  ASSERT_COLUMN_MARKED_FOR_WRITE;
74
75
  if (not temporal.from_string(from, (size_t) len))
76
  {
77
    my_error(ER_INVALID_UNIX_TIMESTAMP_VALUE, MYF(ME_FATALERROR), from);
78
    return 1;
79
  }
80
2046.2.3 by Brian Aker
Add basic tests for microtime.
81
  struct timeval tmp;
82
  temporal.to_timeval(tmp);
83
84
  uint64_t tmp_seconds= tmp.tv_sec;
2057.2.2 by Brian Aker
Merge in fixes for microtimestamp,
85
  uint32_t tmp_micro= tmp.tv_usec;
2046.2.3 by Brian Aker
Add basic tests for microtime.
86
87
  pack_num(tmp_seconds);
88
  pack_num(tmp_micro, ptr +8);
89
2046.2.1 by Brian Aker
First pass on micro timestamp.
90
  return 0;
91
}
92
2069.2.1 by Brian Aker
Fix issue with now() not storing fractional seconds in timestamp(6)
93
int Microtime::store_time(type::Time *ltime, enum enum_drizzle_timestamp_type )
94
{
95
  long my_timezone;
96
  bool in_dst_time_gap;
97
98
  time_t time_tmp= my_system_gmt_sec(ltime, &my_timezone, &in_dst_time_gap, true);
99
  uint64_t tmp_seconds= time_tmp;
100
  uint32_t tmp_micro= ltime->second_part;
101
102
  pack_num(tmp_seconds);
103
  pack_num(tmp_micro, ptr +8);
104
105
  return 0;
106
}
107
2046.2.1 by Brian Aker
First pass on micro timestamp.
108
int Microtime::store(double from)
109
{
110
  ASSERT_COLUMN_MARKED_FOR_WRITE;
111
112
  if (from < 0 || from > 99991231235959.0)
113
  {
114
    /* Convert the double to a string using stringstream */
115
    std::stringstream ss;
116
    std::string tmp;
117
    ss.precision(18); /* 18 places should be fine for error display of double input. */
118
    ss << from; 
119
    ss >> tmp;
120
121
    my_error(ER_INVALID_UNIX_TIMESTAMP_VALUE, MYF(ME_FATALERROR), tmp.c_str());
122
    return 2;
123
  }
124
  return Microtime::store((int64_t) rint(from), false);
125
}
126
127
int Microtime::store(int64_t from, bool)
128
{
129
  ASSERT_COLUMN_MARKED_FOR_WRITE;
130
2046.2.3 by Brian Aker
Add basic tests for microtime.
131
  MicroTimestamp temporal;
132
  if (not temporal.from_int64_t(from))
2046.2.1 by Brian Aker
First pass on micro timestamp.
133
  {
134
    /* Convert the integer to a string using boost::lexical_cast */
135
    std::string tmp(boost::lexical_cast<std::string>(from));
136
137
    my_error(ER_INVALID_UNIX_TIMESTAMP_VALUE, MYF(ME_FATALERROR), tmp.c_str());
138
    return 2;
139
  }
140
141
  time_t tmp;
142
  temporal.to_time_t(tmp);
143
2046.2.3 by Brian Aker
Add basic tests for microtime.
144
  uint64_t tmp_micro= tmp;
145
  pack_num(tmp_micro);
146
  pack_num(static_cast<uint32_t>(0), ptr +8);
2046.2.1 by Brian Aker
First pass on micro timestamp.
147
148
  return 0;
149
}
150
151
double Microtime::val_real(void)
152
{
153
  return (double) Microtime::val_int();
154
}
155
156
int64_t Microtime::val_int(void)
157
{
158
  uint64_t temp;
159
160
  ASSERT_COLUMN_MARKED_FOR_READ;
161
162
  unpack_num(temp);
163
164
  Timestamp temporal;
165
  (void) temporal.from_time_t((time_t) temp);
166
167
  /* We must convert into a "timestamp-formatted integer" ... */
168
  int64_t result;
169
  temporal.to_int64_t(&result);
2046.2.3 by Brian Aker
Add basic tests for microtime.
170
2046.2.1 by Brian Aker
First pass on micro timestamp.
171
  return result;
172
}
173
174
String *Microtime::val_str(String *val_buffer, String *)
175
{
176
  uint64_t temp= 0;
2046.2.3 by Brian Aker
Add basic tests for microtime.
177
  uint32_t micro_temp= 0;
2046.2.1 by Brian Aker
First pass on micro timestamp.
178
  char *to;
2057.2.2 by Brian Aker
Merge in fixes for microtimestamp,
179
  int to_len= field_length + 1 + 8;
2046.2.1 by Brian Aker
First pass on micro timestamp.
180
181
  val_buffer->alloc(to_len);
182
  to= (char *) val_buffer->ptr();
183
184
  unpack_num(temp);
2046.2.3 by Brian Aker
Add basic tests for microtime.
185
  unpack_num(micro_temp, ptr +8);
2046.2.1 by Brian Aker
First pass on micro timestamp.
186
187
  val_buffer->set_charset(&my_charset_bin);	/* Safety */
188
2046.2.3 by Brian Aker
Add basic tests for microtime.
189
  struct timeval buffer;
190
  buffer.tv_sec= temp;
191
  buffer.tv_usec= micro_temp;
192
193
  MicroTimestamp temporal;
194
  (void) temporal.from_timeval(buffer);
2046.2.1 by Brian Aker
First pass on micro timestamp.
195
2057.2.2 by Brian Aker
Merge in fixes for microtimestamp,
196
  int rlen= temporal.to_string(to, to_len);
197
  assert(rlen <= to_len);
2046.2.1 by Brian Aker
First pass on micro timestamp.
198
199
  val_buffer->length(rlen);
2057.2.2 by Brian Aker
Merge in fixes for microtimestamp,
200
2046.2.1 by Brian Aker
First pass on micro timestamp.
201
  return val_buffer;
202
}
203
204
bool Microtime::get_date(type::Time *ltime, uint32_t)
205
{
206
  uint64_t temp;
2046.2.3 by Brian Aker
Add basic tests for microtime.
207
  uint32_t micro_temp= 0;
2046.2.1 by Brian Aker
First pass on micro timestamp.
208
209
  unpack_num(temp);
2046.2.3 by Brian Aker
Add basic tests for microtime.
210
  unpack_num(micro_temp, ptr +8);
2046.2.1 by Brian Aker
First pass on micro timestamp.
211
  
212
  memset(ltime, 0, sizeof(*ltime));
213
214
  Timestamp temporal;
215
  (void) temporal.from_time_t((time_t) temp);
216
217
  /* @TODO Goodbye the below code when type::Time is finally gone.. */
218
219
  ltime->time_type= DRIZZLE_TIMESTAMP_DATETIME;
220
  ltime->year= temporal.years();
221
  ltime->month= temporal.months();
222
  ltime->day= temporal.days();
223
  ltime->hour= temporal.hours();
224
  ltime->minute= temporal.minutes();
225
  ltime->second= temporal.seconds();
2046.2.3 by Brian Aker
Add basic tests for microtime.
226
  ltime->second_part= temporal.useconds();
2046.2.1 by Brian Aker
First pass on micro timestamp.
227
228
  return 0;
229
}
230
231
bool Microtime::get_time(type::Time *ltime)
232
{
233
  return Microtime::get_date(ltime,0);
234
}
235
236
int Microtime::cmp(const unsigned char *a_ptr, const unsigned char *b_ptr)
237
{
238
  uint64_t a,b;
2046.2.3 by Brian Aker
Add basic tests for microtime.
239
  uint32_t a_micro, b_micro;
2046.2.1 by Brian Aker
First pass on micro timestamp.
240
241
  unpack_num(a, a_ptr);
2046.2.3 by Brian Aker
Add basic tests for microtime.
242
  unpack_num(a_micro, a_ptr +8);
243
2046.2.1 by Brian Aker
First pass on micro timestamp.
244
  unpack_num(b, b_ptr);
2046.2.3 by Brian Aker
Add basic tests for microtime.
245
  unpack_num(b_micro, b_ptr +8);
246
247
  if (a == b)
248
    return (a_micro < b_micro) ? -1 : (a_micro > b_micro) ? 1 : 0;
2046.2.1 by Brian Aker
First pass on micro timestamp.
249
250
  return (a < b) ? -1 : (a > b) ? 1 : 0;
251
}
252
253
254
void Microtime::sort_string(unsigned char *to,uint32_t )
255
{
256
#ifdef WORDS_BIGENDIAN
257
  if ((not getTable()) or (not getTable()->getShare()->db_low_byte_first))
258
  {
259
    std::reverse_copy(to, to+pack_length(), ptr);
2046.2.3 by Brian Aker
Add basic tests for microtime.
260
    std::reverse_copy(to +8, to+pack_length(), ptr +8);
2046.2.1 by Brian Aker
First pass on micro timestamp.
261
  }
262
  else
263
#endif
264
  {
265
    memcpy(to, ptr, pack_length());
266
  }
267
}
268
269
void Microtime::sql_type(String &res) const
270
{
2046.2.2 by Brian Aker
Basic support added for microstamp as alias to epoch
271
  res.set_ascii(STRING_WITH_LEN("microsecond timestamp"));
2046.2.1 by Brian Aker
First pass on micro timestamp.
272
}
273
274
void Microtime::set_time()
275
{
276
  Session *session= getTable() ? getTable()->in_use : current_session;
2057.2.2 by Brian Aker
Merge in fixes for microtimestamp,
277
278
  uint32_t fractional_seconds= 0;
279
  uint64_t epoch_seconds= session->getCurrentTimestampEpoch(fractional_seconds);
280
2046.2.1 by Brian Aker
First pass on micro timestamp.
281
  set_notnull();
2057.2.2 by Brian Aker
Merge in fixes for microtimestamp,
282
  pack_num(epoch_seconds);
283
  pack_num(fractional_seconds, ptr +8);
2046.2.1 by Brian Aker
First pass on micro timestamp.
284
}
285
286
long Microtime::get_timestamp(bool *null_value)
287
{
288
  if ((*null_value= is_null()))
289
    return 0;
290
291
  uint64_t tmp;
292
  return unpack_num(tmp);
293
}
294
295
} /* namespace field */
296
} /* namespace drizzled */