~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/function/time/add_time.cc

  • Committer: Jay Pipes
  • Date: 2009-02-28 17:49:22 UTC
  • mto: (910.2.6 mordred-noatomics)
  • mto: This revision was merged to the branch mainline in revision 908.
  • Revision ID: jpipes@serialcoder-20090228174922-jczgt4d0662fqmnf
Merging in old r902 temporal changes

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
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; version 2 of the License.
9
 
 *
10
 
 *  This program is distributed in the hope that it will be useful,
11
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
 *  GNU General Public License for more details.
14
 
 *
15
 
 *  You should have received a copy of the GNU General Public License
16
 
 *  along with this program; if not, write to the Free Software
17
 
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
 
 */
19
 
 
20
 
#include <drizzled/server_includes.h>
21
 
#include CSTDINT_H
22
 
#include <drizzled/function/time/add_time.h>
23
 
#include <drizzled/function/time/make_datetime.h>
24
 
#include <drizzled/function/time/make_datetime_with_warn.h>
25
 
 
26
 
void Item_func_add_time::fix_length_and_dec()
27
 
{
28
 
  enum_field_types arg0_field_type;
29
 
  decimals=0;
30
 
  max_length=MAX_DATETIME_FULL_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
31
 
  maybe_null= 1;
32
 
 
33
 
  /*
34
 
    The field type for the result of an Item_func_add_time function is defined
35
 
    as follows:
36
 
 
37
 
    - If first arg is a DRIZZLE_TYPE_DATETIME or DRIZZLE_TYPE_TIMESTAMP
38
 
      result is DRIZZLE_TYPE_DATETIME
39
 
    - If first arg is a DRIZZLE_TYPE_TIME result is DRIZZLE_TYPE_TIME
40
 
    - Otherwise the result is DRIZZLE_TYPE_VARCHAR
41
 
  */
42
 
 
43
 
  cached_field_type= DRIZZLE_TYPE_VARCHAR;
44
 
  arg0_field_type= args[0]->field_type();
45
 
  if (arg0_field_type == DRIZZLE_TYPE_DATE ||
46
 
      arg0_field_type == DRIZZLE_TYPE_DATETIME ||
47
 
      arg0_field_type == DRIZZLE_TYPE_TIMESTAMP)
48
 
    cached_field_type= DRIZZLE_TYPE_DATETIME;
49
 
}
50
 
 
51
 
/**
52
 
  ADDTIME(t,a) and SUBTIME(t,a) are time functions that calculate a
53
 
  time/datetime value
54
 
 
55
 
  t: time_or_datetime_expression
56
 
  a: time_expression
57
 
 
58
 
  Result: Time value or datetime value
59
 
*/
60
 
 
61
 
String *Item_func_add_time::val_str(String *str)
62
 
{
63
 
  assert(fixed == 1);
64
 
  DRIZZLE_TIME l_time1, l_time2, l_time3;
65
 
  bool is_time= 0;
66
 
  long days, microseconds;
67
 
  int64_t seconds;
68
 
  int l_sign= sign;
69
 
 
70
 
  null_value=0;
71
 
  if (is_date)                        // TIMESTAMP function
72
 
  {
73
 
    if (get_arg0_date(&l_time1, TIME_FUZZY_DATE) ||
74
 
        args[1]->get_time(&l_time2) ||
75
 
        l_time1.time_type == DRIZZLE_TIMESTAMP_TIME ||
76
 
        l_time2.time_type != DRIZZLE_TIMESTAMP_TIME)
77
 
      goto null_date;
78
 
  }
79
 
  else                                // ADDTIME function
80
 
  {
81
 
    if (args[0]->get_time(&l_time1) ||
82
 
        args[1]->get_time(&l_time2) ||
83
 
        l_time2.time_type == DRIZZLE_TIMESTAMP_DATETIME)
84
 
      goto null_date;
85
 
    is_time= (l_time1.time_type == DRIZZLE_TIMESTAMP_TIME);
86
 
  }
87
 
  if (l_time1.neg != l_time2.neg)
88
 
    l_sign= -l_sign;
89
 
 
90
 
  memset(&l_time3, 0, sizeof(l_time3));
91
 
 
92
 
  l_time3.neg= calc_time_diff(&l_time1, &l_time2, -l_sign,
93
 
                              &seconds, &microseconds);
94
 
 
95
 
  /*
96
 
    If first argument was negative and diff between arguments
97
 
    is non-zero we need to swap sign to get proper result.
98
 
  */
99
 
  if (l_time1.neg && (seconds || microseconds))
100
 
    l_time3.neg= 1-l_time3.neg;         // Swap sign of result
101
 
 
102
 
  if (!is_time && l_time3.neg)
103
 
    goto null_date;
104
 
 
105
 
  days= (long)(seconds/86400L);
106
 
 
107
 
  calc_time_from_sec(&l_time3, (long)(seconds%86400L), microseconds);
108
 
 
109
 
  if (!is_time)
110
 
  {
111
 
    get_date_from_daynr(days,&l_time3.year,&l_time3.month,&l_time3.day);
112
 
    if (l_time3.day &&
113
 
        !make_datetime(l_time1.second_part || l_time2.second_part ?
114
 
                       DATE_TIME_MICROSECOND : DATE_TIME,
115
 
                       &l_time3, str))
116
 
      return str;
117
 
    goto null_date;
118
 
  }
119
 
 
120
 
  l_time3.hour+= days*24;
121
 
  if (!make_datetime_with_warn(l_time1.second_part || l_time2.second_part ?
122
 
                               TIME_MICROSECOND : TIME_ONLY,
123
 
                               &l_time3, str))
124
 
    return str;
125
 
 
126
 
null_date:
127
 
  null_value=1;
128
 
  return 0;
129
 
}
130
 
 
131
 
 
132
 
void Item_func_add_time::print(String *str, enum_query_type query_type)
133
 
{
134
 
  if (is_date)
135
 
  {
136
 
    assert(sign > 0);
137
 
    str->append(STRING_WITH_LEN("timestamp("));
138
 
  }
139
 
  else
140
 
  {
141
 
    if (sign > 0)
142
 
      str->append(STRING_WITH_LEN("addtime("));
143
 
    else
144
 
      str->append(STRING_WITH_LEN("subtime("));
145
 
  }
146
 
  args[0]->print(str, query_type);
147
 
  str->append(',');
148
 
  args[1]->print(str, query_type);
149
 
  str->append(')');
150
 
}
151