Drizzled Public API Documentation

typecast.cc
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, Inc.
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 <config.h>
21 
22 #include <cstdio>
23 
24 #include <drizzled/current_session.h>
25 #include <drizzled/error.h>
26 #include <drizzled/function/time/typecast.h>
27 #include <drizzled/time_functions.h>
28 #include <drizzled/charset.h>
29 
30 namespace drizzled {
31 
32 bool Item_char_typecast::eq(const Item *item, bool binary_cmp) const
33 {
34  if (this == item)
35  return 1;
36  if (item->type() != FUNC_ITEM ||
37  functype() != ((Item_func*)item)->functype())
38  return 0;
39 
41  if (cast_length != cast->cast_length ||
42  cast_cs != cast->cast_cs)
43  return 0;
44 
45  if (!args[0]->eq(cast->args[0], binary_cmp))
46  return 0;
47  return 1;
48 }
49 
51 {
52  str->append(STRING_WITH_LEN("cast("));
53  args[0]->print(str);
54  str->append(STRING_WITH_LEN(" as "));
55  str->append(cast_type(), strlen(cast_type()));
56  str->append(')');
57 }
58 
59 
61 {
62  str->append(STRING_WITH_LEN("cast("));
63  args[0]->print(str);
64  str->append(STRING_WITH_LEN(" as char"));
65  if (cast_length >= 0)
66  {
67  str->append('(');
68  char buffer[20];
69  // my_charset_bin is good enough for numbers
70  String st(buffer, sizeof(buffer), &my_charset_bin);
71  st.set((uint64_t)cast_length, &my_charset_bin);
72  str->append(st);
73  str->append(')');
74  }
75 
76  if (cast_cs)
77  {
78  str->append(STRING_WITH_LEN(" charset "));
79  str->append(cast_cs->csname, strlen(cast_cs->csname));
80  }
81  str->append(')');
82 }
83 
85 {
86  assert(fixed == 1);
87  String *res;
88  uint32_t length;
89 
90  if (!charset_conversion)
91  {
92  if (!(res= args[0]->val_str(str)))
93  {
94  null_value= 1;
95  return 0;
96  }
97  }
98  else
99  {
100  // Convert character set if differ
101  if (!(res= args[0]->val_str(&tmp_value)))
102  {
103  null_value= 1;
104  return 0;
105  }
106  str->copy(res->ptr(), res->length(), cast_cs);
107  res= str;
108  }
109 
110  res->set_charset(cast_cs);
111 
112  /*
113  Cut the tail if cast with length
114  and the result is longer than cast length, e.g.
115  CAST('string' AS CHAR(1))
116  */
117  if (cast_length >= 0)
118  {
119  if (res->length() > (length= (uint32_t) res->charpos(cast_length)))
120  { // Safe even if const arg
121  char char_type[40];
122  snprintf(char_type, sizeof(char_type), "%s(%lu)",
123  cast_cs == &my_charset_bin ? "BINARY" : "CHAR",
124  (ulong) cast_length);
125 
126  if (!res->alloced_length())
127  { // Don't change const str
128  str_value= *res; // Not malloced string
129  res= &str_value;
130  }
131  push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
132  ER_TRUNCATED_WRONG_VALUE,
133  ER(ER_TRUNCATED_WRONG_VALUE), char_type,
134  res->c_str());
135  res->length((uint) length);
136  }
137  else if (cast_cs == &my_charset_bin && res->length() < (uint) cast_length)
138  {
139  if (res->alloced_length() < (uint) cast_length)
140  {
141  str->alloc(cast_length);
142  str->copy(*res);
143  res= str;
144  }
145  memset(res->ptr() + res->length(), 0,
146  (uint) cast_length - res->length());
147  res->length(cast_length);
148  }
149  }
150  null_value= 0;
151  return res;
152 }
153 
154 
155 void Item_char_typecast::fix_length_and_dec()
156 {
157  uint32_t char_length;
158  /*
159  We always force character set conversion if cast_cs
160  is a multi-byte character set. It garantees that the
161  result of CAST is a well-formed string.
162  For single-byte character sets we allow just to copy
163  from the argument. A single-byte character sets string
164  is always well-formed.
165 
166  There is a special trick to convert form a number to ucs2.
167  As numbers have my_charset_bin as their character set,
168  it wouldn't do conversion to ucs2 without an additional action.
169  To force conversion, we should pretend to be non-binary.
170  Let's choose from_cs this way:
171  - If the argument in a number and cast_cs is ucs2 (i.e. mbminlen > 1),
172  then from_cs is set to latin1, to perform latin1 -> ucs2 conversion.
173  - If the argument is a number and cast_cs is ASCII-compatible
174  (i.e. mbminlen == 1), then from_cs is set to cast_cs,
175  which allows just to take over the args[0]->val_str() result
176  and thus avoid unnecessary character set conversion.
177  - If the argument is not a number, then from_cs is set to
178  the argument's charset.
179  */
180  from_cs= (args[0]->result_type() == INT_RESULT ||
181  args[0]->result_type() == DECIMAL_RESULT ||
182  args[0]->result_type() == REAL_RESULT) ?
183  (cast_cs->mbminlen == 1 ? cast_cs : &my_charset_utf8_general_ci) :
184  args[0]->collation.collation;
185  charset_conversion= (cast_cs->mbmaxlen > 1) ||
186  (!my_charset_same(from_cs, cast_cs) && from_cs != &my_charset_bin && cast_cs != &my_charset_bin);
187  collation.set(cast_cs, DERIVATION_IMPLICIT);
188  char_length= (cast_length >= 0) ? (uint32_t)cast_length :
189  (uint32_t)args[0]->max_length/from_cs->mbmaxlen;
190  max_length= char_length * cast_cs->mbmaxlen;
191 }
192 
193 
195 {
196  assert(fixed == 1);
197  type::Time ltime;
198 
199  if (not get_arg0_date(ltime, TIME_FUZZY_DATE))
200  {
201  if (ltime.second_part)
202  {
203  ltime.convert(*str);
204  }
205  else
206  {
207  ltime.convert(*str);
208  }
209 
210  return str;
211  }
212 
213  null_value=1;
214  return 0;
215 }
216 
217 
219 {
220  assert(fixed == 1);
221  type::Time ltime;
222  if (get_arg0_date(ltime, 1))
223  {
224  null_value= 1;
225  return 0;
226  }
227 
228  int64_t tmp;
229  ltime.convert(tmp);
230 
231  return tmp;
232 }
233 
234 
236 {
237  bool res= get_arg0_date(ltime, TIME_FUZZY_DATE);
238 
239  ltime.hour= ltime.minute= ltime.second= ltime.second_part= 0;
240  ltime.time_type= type::DRIZZLE_TIMESTAMP_DATE;
241 
242  return res;
243 }
244 
245 
247 {
248  ltime.reset();
249 
250  return args[0]->null_value;
251 }
252 
253 
255 {
256  assert(fixed == 1);
257  type::Time ltime;
258 
259  if (!get_arg0_date(ltime, TIME_FUZZY_DATE))
260  {
261  str->alloc(type::Time::MAX_STRING_LENGTH);
262  ltime.convert(*str, type::DRIZZLE_TIMESTAMP_DATE);
263 
264  return str;
265  }
266 
267  null_value=1;
268  return 0;
269 }
270 
272 {
273  assert(fixed == 1);
274  type::Time ltime;
275 
276  if ((null_value= args[0]->get_date(ltime, TIME_FUZZY_DATE)))
277  return 0;
278 
279  return (int64_t) (ltime.year * 10000L + ltime.month * 100 + ltime.day);
280 }
281 
282 } /* namespace drizzled */
virtual void print(String *str)
Definition: typecast.cc:50
bool fixed
Definition: item.h:120
String * val_str(String *str)
Definition: typecast.cc:194
bool null_value
Definition: item.h:122
bool eq(const Item *item, bool binary_cmp) const
Definition: typecast.cc:32
bool get_time(type::Time &ltime)
Definition: typecast.cc:246
String * val_str(String *str)
Definition: typecast.cc:254
virtual void print(String *str)
Definition: item.cc:362
bool get_date(type::Time &ltime, uint32_t fuzzy_date)
Definition: typecast.cc:235
String str_value
Definition: item.h:107
virtual void print(String *str)
Definition: typecast.cc:60
String * val_str(String *a)
Definition: typecast.cc:84