~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Padraig
  • Date: 2009-03-01 04:15:34 UTC
  • mfrom: (908 drizzle)
  • mto: (934.3.2 mordred)
  • mto: This revision was merged to the branch mainline in revision 938.
  • Revision ID: posulliv@linux-lap-20090301041534-3p2c1l2l2436cczq
MergeĀ fromĀ trunk.

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
 
  else if (arg0_field_type == DRIZZLE_TYPE_TIME)
50
 
    cached_field_type= DRIZZLE_TYPE_TIME;
51
 
}
52
 
 
53
 
/**
54
 
  ADDTIME(t,a) and SUBTIME(t,a) are time functions that calculate a
55
 
  time/datetime value
56
 
 
57
 
  t: time_or_datetime_expression
58
 
  a: time_expression
59
 
 
60
 
  Result: Time value or datetime value
61
 
*/
62
 
 
63
 
String *Item_func_add_time::val_str(String *str)
64
 
{
65
 
  assert(fixed == 1);
66
 
  DRIZZLE_TIME l_time1, l_time2, l_time3;
67
 
  bool is_time= 0;
68
 
  long days, microseconds;
69
 
  int64_t seconds;
70
 
  int l_sign= sign;
71
 
 
72
 
  null_value=0;
73
 
  if (is_date)                        // TIMESTAMP function
74
 
  {
75
 
    if (get_arg0_date(&l_time1, TIME_FUZZY_DATE) ||
76
 
        args[1]->get_time(&l_time2) ||
77
 
        l_time1.time_type == DRIZZLE_TIMESTAMP_TIME ||
78
 
        l_time2.time_type != DRIZZLE_TIMESTAMP_TIME)
79
 
      goto null_date;
80
 
  }
81
 
  else                                // ADDTIME function
82
 
  {
83
 
    if (args[0]->get_time(&l_time1) ||
84
 
        args[1]->get_time(&l_time2) ||
85
 
        l_time2.time_type == DRIZZLE_TIMESTAMP_DATETIME)
86
 
      goto null_date;
87
 
    is_time= (l_time1.time_type == DRIZZLE_TIMESTAMP_TIME);
88
 
  }
89
 
  if (l_time1.neg != l_time2.neg)
90
 
    l_sign= -l_sign;
91
 
 
92
 
  memset(&l_time3, 0, sizeof(l_time3));
93
 
 
94
 
  l_time3.neg= calc_time_diff(&l_time1, &l_time2, -l_sign,
95
 
                              &seconds, &microseconds);
96
 
 
97
 
  /*
98
 
    If first argument was negative and diff between arguments
99
 
    is non-zero we need to swap sign to get proper result.
100
 
  */
101
 
  if (l_time1.neg && (seconds || microseconds))
102
 
    l_time3.neg= 1-l_time3.neg;         // Swap sign of result
103
 
 
104
 
  if (!is_time && l_time3.neg)
105
 
    goto null_date;
106
 
 
107
 
  days= (long)(seconds/86400L);
108
 
 
109
 
  calc_time_from_sec(&l_time3, (long)(seconds%86400L), microseconds);
110
 
 
111
 
  if (!is_time)
112
 
  {
113
 
    get_date_from_daynr(days,&l_time3.year,&l_time3.month,&l_time3.day);
114
 
    if (l_time3.day &&
115
 
        !make_datetime(l_time1.second_part || l_time2.second_part ?
116
 
                       DATE_TIME_MICROSECOND : DATE_TIME,
117
 
                       &l_time3, str))
118
 
      return str;
119
 
    goto null_date;
120
 
  }
121
 
 
122
 
  l_time3.hour+= days*24;
123
 
  if (!make_datetime_with_warn(l_time1.second_part || l_time2.second_part ?
124
 
                               TIME_MICROSECOND : TIME_ONLY,
125
 
                               &l_time3, str))
126
 
    return str;
127
 
 
128
 
null_date:
129
 
  null_value=1;
130
 
  return 0;
131
 
}
132
 
 
133
 
 
134
 
void Item_func_add_time::print(String *str, enum_query_type query_type)
135
 
{
136
 
  if (is_date)
137
 
  {
138
 
    assert(sign > 0);
139
 
    str->append(STRING_WITH_LEN("timestamp("));
140
 
  }
141
 
  else
142
 
  {
143
 
    if (sign > 0)
144
 
      str->append(STRING_WITH_LEN("addtime("));
145
 
    else
146
 
      str->append(STRING_WITH_LEN("subtime("));
147
 
  }
148
 
  args[0]->print(str, query_type);
149
 
  str->append(',');
150
 
  args[1]->print(str, query_type);
151
 
  str->append(')');
152
 
}
153