~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/functions/time/date_add_interval.cc

  • Committer: Brian Aker
  • Date: 2008-11-26 16:31:46 UTC
  • mfrom: (612.2.10 devel)
  • Revision ID: brian@tangent.org-20081126163146-nptzh53wd333f620
Merge from Monty

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/item/timefunc.h>
 
23
#include <drizzled/functions/time/date_add_interval.h>
 
24
#include <drizzled/functions/time/get_interval_value.h>
 
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
 
 
79
bool Item_date_add_interval::get_date(DRIZZLE_TIME *ltime, uint32_t fuzzy_date __attribute__((unused)))
 
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
}