~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Brian Aker
  • Date: 2008-11-23 17:00:44 UTC
  • mfrom: (590.2.12 devel)
  • Revision ID: brian@tangent.org-20081123170044-lk3sdqabwnwushp2
Merging in Monty's work.

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/functions/time/date_format.h>
 
23
#include <drizzled/session.h>
 
24
 
 
25
void Item_func_date_format::fix_length_and_dec()
 
26
{
 
27
  Session* session= current_session;
 
28
  /*
 
29
    Must use this_item() in case it's a local SP variable
 
30
    (for ->max_length and ->str_value)
 
31
  */
 
32
  Item *arg1= args[1]->this_item();
 
33
 
 
34
  decimals=0;
 
35
  const CHARSET_INFO * const cs= session->variables.collation_connection;
 
36
  uint32_t repertoire= arg1->collation.repertoire;
 
37
  if (!session->variables.lc_time_names->is_ascii)
 
38
    repertoire|= MY_REPERTOIRE_EXTENDED;
 
39
  collation.set(cs, arg1->collation.derivation, repertoire);
 
40
  if (arg1->type() == STRING_ITEM)
 
41
  {                                             // Optimize the normal case
 
42
    fixed_length=1;
 
43
    max_length= format_length(&arg1->str_value) *
 
44
                collation.collation->mbmaxlen;
 
45
  }
 
46
  else
 
47
  {
 
48
    fixed_length=0;
 
49
    max_length=cmin(arg1->max_length,(uint32_t) MAX_BLOB_WIDTH) * 10 *
 
50
                   collation.collation->mbmaxlen;
 
51
    set_if_smaller(max_length,MAX_BLOB_WIDTH);
 
52
  }
 
53
  maybe_null=1;                                 // If wrong date
 
54
}
 
55
 
 
56
bool Item_func_date_format::eq(const Item *item, bool binary_cmp) const
 
57
{
 
58
  Item_func_date_format *item_func;
 
59
 
 
60
  if (item->type() != FUNC_ITEM)
 
61
    return 0;
 
62
  if (func_name() != ((Item_func*) item)->func_name())
 
63
    return 0;
 
64
  if (this == item)
 
65
    return 1;
 
66
  item_func= (Item_func_date_format*) item;
 
67
  if (!args[0]->eq(item_func->args[0], binary_cmp))
 
68
    return 0;
 
69
  /*
 
70
    We must compare format string case sensitive.
 
71
    This needed because format modifiers with different case,
 
72
    for example %m and %M, have different meaning.
 
73
  */
 
74
  if (!args[1]->eq(item_func->args[1], 1))
 
75
    return 0;
 
76
  return 1;
 
77
}
 
78
 
 
79
uint32_t Item_func_date_format::format_length(const String *format)
 
80
{
 
81
  uint32_t size=0;
 
82
  const char *ptr=format->ptr();
 
83
  const char *end=ptr+format->length();
 
84
 
 
85
  for (; ptr != end ; ptr++)
 
86
  {
 
87
    if (*ptr != '%' || ptr == end-1)
 
88
      size++;
 
89
    else
 
90
    {
 
91
      switch(*++ptr) {
 
92
      case 'M': /* month, textual */
 
93
      case 'W': /* day (of the week), textual */
 
94
        size += 64; /* large for UTF8 locale data */
 
95
        break;
 
96
      case 'D': /* day (of the month), numeric plus english suffix */
 
97
      case 'Y': /* year, numeric, 4 digits */
 
98
      case 'x': /* Year, used with 'v' */
 
99
      case 'X': /* Year, used with 'v, where week starts with Monday' */
 
100
        size += 4;
 
101
        break;
 
102
      case 'a': /* locale's abbreviated weekday name (Sun..Sat) */
 
103
      case 'b': /* locale's abbreviated month name (Jan.Dec) */
 
104
        size += 32; /* large for UTF8 locale data */
 
105
        break;
 
106
      case 'j': /* day of year (001..366) */
 
107
        size += 3;
 
108
        break;
 
109
      case 'U': /* week (00..52) */
 
110
      case 'u': /* week (00..52), where week starts with Monday */
 
111
      case 'V': /* week 1..53 used with 'x' */
 
112
      case 'v': /* week 1..53 used with 'x', where week starts with Monday */
 
113
      case 'y': /* year, numeric, 2 digits */
 
114
      case 'm': /* month, numeric */
 
115
      case 'd': /* day (of the month), numeric */
 
116
      case 'h': /* hour (01..12) */
 
117
      case 'I': /* --||-- */
 
118
      case 'i': /* minutes, numeric */
 
119
      case 'l': /* hour ( 1..12) */
 
120
      case 'p': /* locale's AM or PM */
 
121
      case 'S': /* second (00..61) */
 
122
      case 's': /* seconds, numeric */
 
123
      case 'c': /* month (0..12) */
 
124
      case 'e': /* day (0..31) */
 
125
        size += 2;
 
126
        break;
 
127
      case 'k': /* hour ( 0..23) */
 
128
      case 'H': /* hour (00..23; value > 23 OK, padding always 2-digit) */
 
129
        size += 7; /* docs allow > 23, range depends on sizeof(unsigned int) */
 
130
        break;
 
131
      case 'r': /* time, 12-hour (hh:mm:ss [AP]M) */
 
132
        size += 11;
 
133
        break;
 
134
      case 'T': /* time, 24-hour (hh:mm:ss) */
 
135
        size += 8;
 
136
        break;
 
137
      case 'f': /* microseconds */
 
138
        size += 6;
 
139
        break;
 
140
      case 'w': /* day (of the week), numeric */
 
141
      case '%':
 
142
      default:
 
143
        size++;
 
144
        break;
 
145
      }
 
146
    }
 
147
  }
 
148
  return size;
 
149
}
 
150
 
 
151
 
 
152
String *Item_func_date_format::val_str(String *str)
 
153
{
 
154
  String *format;
 
155
  DRIZZLE_TIME l_time;
 
156
  uint32_t size;
 
157
  assert(fixed == 1);
 
158
 
 
159
  if (!is_time_format)
 
160
  {
 
161
    if (get_arg0_date(&l_time, TIME_FUZZY_DATE))
 
162
      return 0;
 
163
  }
 
164
  else
 
165
  {
 
166
    String *res;
 
167
    if (!(res=args[0]->val_str(str)) ||
 
168
        (str_to_time_with_warn(res->ptr(), res->length(), &l_time)))
 
169
      goto null_date;
 
170
 
 
171
    l_time.year=l_time.month=l_time.day=0;
 
172
    null_value=0;
 
173
  }
 
174
 
 
175
  if (!(format = args[1]->val_str(str)) || !format->length())
 
176
    goto null_date;
 
177
 
 
178
  if (fixed_length)
 
179
    size=max_length;
 
180
  else
 
181
    size=format_length(format);
 
182
 
 
183
  if (size < MAX_DATE_STRING_REP_LENGTH)
 
184
    size= MAX_DATE_STRING_REP_LENGTH;
 
185
 
 
186
  if (format == str)
 
187
    str= &value;                                // Save result here
 
188
  if (str->alloc(size))
 
189
    goto null_date;
 
190
 
 
191
  DATE_TIME_FORMAT date_time_format;
 
192
  date_time_format.format.str=    (char*) format->ptr();
 
193
  date_time_format.format.length= format->length(); 
 
194
 
 
195
  /* Create the result string */
 
196
  str->set_charset(collation.collation);
 
197
  if (!make_date_time(&date_time_format, &l_time,
 
198
                      is_time_format ? DRIZZLE_TIMESTAMP_TIME :
 
199
                                       DRIZZLE_TIMESTAMP_DATE,
 
200
                      str))
 
201
    return str;
 
202
 
 
203
null_date:
 
204
  null_value=1;
 
205
  return 0;
 
206
}
 
207