~drizzle-trunk/drizzle/development

574.3.22 by Lee
moving functions from drizzled/item/timefunc to drizzled/functions/time
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
670.1.20 by Monty Taylor
Renamed functions to function... everything else is singular.
22
#include <drizzled/function/time/date_add_interval.h>
23
#include <drizzled/function/time/get_interval_value.h>
670.1.22 by Monty Taylor
Merged from Lee.
24
#include <drizzled/function/time/make_datetime.h>
574.3.22 by Lee
moving functions from drizzled/item/timefunc to drizzled/functions/time
25
26
/*
27
   'interval_names' reflects the order of the enumeration interval_type.
28
   See item/time.h
29
 */
30
const char *interval_names[]=
31
{
32
  "year", "quarter", "month", "week", "day",
33
  "hour", "minute", "second", "microsecond",
34
  "year_month", "day_hour", "day_minute",
35
  "day_second", "hour_minute", "hour_second",
36
  "minute_second", "day_microsecond",
37
  "hour_microsecond", "minute_microsecond",
38
  "second_microsecond"
39
};
40
41
42
void Item_date_add_interval::fix_length_and_dec()
43
{
44
  enum_field_types arg0_field_type;
45
46
  collation.set(&my_charset_bin);
47
  maybe_null=1;
48
  max_length=MAX_DATETIME_FULL_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
49
  value.alloc(max_length);
50
51
  /*
52
    The field type for the result of an Item_date function is defined as
53
    follows:
54
55
    - If first arg is a DRIZZLE_TYPE_DATETIME result is DRIZZLE_TYPE_DATETIME
56
    - If first arg is a DRIZZLE_TYPE_DATE and the interval type uses hours,
57
      minutes or seconds then type is DRIZZLE_TYPE_DATETIME.
58
    - Otherwise the result is DRIZZLE_TYPE_VARCHAR
59
      (This is because you can't know if the string contains a DATE, DRIZZLE_TIME or
60
      DATETIME argument)
61
  */
62
  cached_field_type= DRIZZLE_TYPE_VARCHAR;
63
  arg0_field_type= args[0]->field_type();
64
  if (arg0_field_type == DRIZZLE_TYPE_DATETIME ||
65
      arg0_field_type == DRIZZLE_TYPE_TIMESTAMP)
66
    cached_field_type= DRIZZLE_TYPE_DATETIME;
67
  else if (arg0_field_type == DRIZZLE_TYPE_DATE)
68
  {
69
    if (int_type <= INTERVAL_DAY || int_type == INTERVAL_YEAR_MONTH)
70
      cached_field_type= arg0_field_type;
71
    else
72
      cached_field_type= DRIZZLE_TYPE_DATETIME;
73
  }
74
}
75
76
77
/* Here arg[1] is a Item_interval object */
78
779.1.27 by Monty Taylor
Got rid of __attribute__((unused)) and the like from the .cc files.
79
bool Item_date_add_interval::get_date(DRIZZLE_TIME *ltime, uint32_t )
574.3.22 by Lee
moving functions from drizzled/item/timefunc to drizzled/functions/time
80
{
81
  INTERVAL interval;
82
83
  if (args[0]->get_date(ltime, TIME_NO_ZERO_DATE) ||
84
      get_interval_value(args[1], int_type, &value, &interval))
85
    return (null_value=1);
86
87
  if (date_sub_interval)
88
    interval.neg = !interval.neg;
89
90
  if ((null_value= date_add_interval(ltime, int_type, interval)))
91
    return 1;
92
  return 0;
93
}
94
95
96
String *Item_date_add_interval::val_str(String *str)
97
{
98
  assert(fixed == 1);
99
  DRIZZLE_TIME ltime;
100
  enum date_time_format_types format;
101
102
  if (Item_date_add_interval::get_date(&ltime, TIME_NO_ZERO_DATE))
103
    return 0;
104
105
  if (ltime.time_type == DRIZZLE_TIMESTAMP_DATE)
106
    format= DATE_ONLY;
107
  else if (ltime.second_part)
108
    format= DATE_TIME_MICROSECOND;
109
  else
110
    format= DATE_TIME;
111
112
  if (!make_datetime(format, &ltime, str))
113
    return str;
114
115
  null_value=1;
116
  return 0;
117
}
118
119
120
int64_t Item_date_add_interval::val_int()
121
{
122
  assert(fixed == 1);
123
  DRIZZLE_TIME ltime;
124
  int64_t date;
125
  if (Item_date_add_interval::get_date(&ltime, TIME_NO_ZERO_DATE))
126
    return (int64_t) 0;
127
  date = (ltime.year*100L + ltime.month)*100L + ltime.day;
128
  return ltime.time_type == DRIZZLE_TIMESTAMP_DATE ? date :
129
    ((date*100L + ltime.hour)*100L+ ltime.minute)*100L + ltime.second;
130
}
131
132
133
134
bool Item_date_add_interval::eq(const Item *item, bool binary_cmp) const
135
{
136
  Item_date_add_interval *other= (Item_date_add_interval*) item;
137
  if (!Item_func::eq(item, binary_cmp))
138
    return 0;
139
  return ((int_type == other->int_type) &&
140
          (date_sub_interval == other->date_sub_interval));
141
}
142
143
void Item_date_add_interval::print(String *str, enum_query_type query_type)
144
{
145
  str->append('(');
146
  args[0]->print(str, query_type);
147
  str->append(date_sub_interval?" - interval ":" + interval ");
148
  args[1]->print(str, query_type);
149
  str->append(' ');
150
  str->append(interval_names[int_type]);
151
  str->append(')');
152
}