~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Monty Taylor
  • Date: 2008-11-22 08:48:11 UTC
  • mfrom: (574.3.19 drizzle-clean-code)
  • mto: This revision was merged to the branch mainline in revision 603.
  • Revision ID: monty@inaugust.com-20081122084811-6crylm9iqj4loyjk
MergedĀ fromĀ Lee.

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