1
by brian
clean slate |
1 |
/* Copyright (C) 2000-2006 MySQL AB
|
2 |
||
3 |
This program is free software; you can redistribute it and/or modify
|
|
4 |
it under the terms of the GNU General Public License as published by
|
|
5 |
the Free Software Foundation; version 2 of the License.
|
|
6 |
||
7 |
This program is distributed in the hope that it will be useful,
|
|
8 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
9 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
10 |
GNU General Public License for more details.
|
|
11 |
||
12 |
You should have received a copy of the GNU General Public License
|
|
13 |
along with this program; if not, write to the Free Software
|
|
14 |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
|
15 |
||
16 |
||
17 |
/**
|
|
18 |
@file
|
|
19 |
||
20 |
@brief
|
|
21 |
This file defines all string functions
|
|
22 |
||
23 |
@warning
|
|
24 |
Some string functions don't always put and end-null on a String.
|
|
25 |
(This shouldn't be needed)
|
|
26 |
*/
|
|
27 |
||
243.1.17
by Jay Pipes
FINAL PHASE removal of mysql_priv.h (Bye, bye my friend.) |
28 |
#include <drizzled/server_includes.h> |
212.5.6
by Monty Taylor
Moved sha1.h and sha2.h to mysys. |
29 |
#include <mysys/sha1.h> |
1
by brian
clean slate |
30 |
#include <zlib.h> |
561.1.3
by Monty Taylor
Split some more things out of common_includes.h. |
31 |
#include <drizzled/query_id.h> |
564
by Brian Aker
New UUID code. Also changed default scaling for "8" core machine instead of |
32 |
#include <uuid/uuid.h> |
520.6.7
by Monty Taylor
Moved a bunch of crap out of common_includes. |
33 |
#include <drizzled/data_home.h> |
549
by Monty Taylor
Took gettext.h out of header files. |
34 |
#include <drizzled/error.h> |
1
by brian
clean slate |
35 |
|
520.6.7
by Monty Taylor
Moved a bunch of crap out of common_includes. |
36 |
// For soundex_map
|
37 |
#include <mysys/my_static.h> |
|
572.1.4
by Monty Taylor
Removed a bunch of unusued tests and defines from autoconf. |
38 |
#include CMATH_H
|
39 |
||
40 |
#if defined(CMATH_NAMESPACE)
|
|
41 |
using namespace CMATH_NAMESPACE; |
|
42 |
#endif
|
|
520.6.7
by Monty Taylor
Moved a bunch of crap out of common_includes. |
43 |
|
44 |
using namespace std; |
|
45 |
||
1
by brian
clean slate |
46 |
String my_empty_string("",default_charset_info); |
47 |
||
48 |
||
49 |
||
50 |
||
520.1.22
by Brian Aker
Second pass of thd cleanup |
51 |
bool Item_str_func::fix_fields(Session *session, Item **ref) |
1
by brian
clean slate |
52 |
{
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
53 |
bool res= Item_func::fix_fields(session, ref); |
1
by brian
clean slate |
54 |
/*
|
55 |
In Item_str_func::check_well_formed_result() we may set null_value
|
|
56 |
flag on the same condition as in test() below.
|
|
57 |
*/
|
|
360
by Brian Aker
More MODE removal. |
58 |
maybe_null= (maybe_null || true); |
1
by brian
clean slate |
59 |
return res; |
60 |
}
|
|
61 |
||
62 |
||
63 |
my_decimal *Item_str_func::val_decimal(my_decimal *decimal_value) |
|
64 |
{
|
|
51.1.23
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
65 |
assert(fixed == 1); |
1
by brian
clean slate |
66 |
char buff[64]; |
67 |
String *res, tmp(buff,sizeof(buff), &my_charset_bin); |
|
68 |
res= val_str(&tmp); |
|
69 |
if (!res) |
|
70 |
return 0; |
|
71 |
(void)str2my_decimal(E_DEC_FATAL_ERROR, (char*) res->ptr(), |
|
72 |
res->length(), res->charset(), decimal_value); |
|
73 |
return decimal_value; |
|
74 |
}
|
|
75 |
||
76 |
||
77 |
double Item_str_func::val_real() |
|
78 |
{
|
|
51.1.23
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
79 |
assert(fixed == 1); |
1
by brian
clean slate |
80 |
int err_not_used; |
81 |
char *end_not_used, buff[64]; |
|
82 |
String *res, tmp(buff,sizeof(buff), &my_charset_bin); |
|
83 |
res= val_str(&tmp); |
|
84 |
return res ? my_strntod(res->charset(), (char*) res->ptr(), res->length(), |
|
85 |
&end_not_used, &err_not_used) : 0.0; |
|
86 |
}
|
|
87 |
||
88 |
||
152
by Brian Aker
longlong replacement |
89 |
int64_t Item_str_func::val_int() |
1
by brian
clean slate |
90 |
{
|
51.1.23
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
91 |
assert(fixed == 1); |
1
by brian
clean slate |
92 |
int err; |
93 |
char buff[22]; |
|
94 |
String *res, tmp(buff,sizeof(buff), &my_charset_bin); |
|
95 |
res= val_str(&tmp); |
|
96 |
return (res ? |
|
97 |
my_strntoll(res->charset(), res->ptr(), res->length(), 10, NULL, |
|
98 |
&err) : |
|
152
by Brian Aker
longlong replacement |
99 |
(int64_t) 0); |
1
by brian
clean slate |
100 |
}
|
101 |
||
102 |
/**
|
|
103 |
Concatenate args with the following premises:
|
|
104 |
If only one arg (which is ok), return value of arg;
|
|
105 |
Don't reallocate val_str() if not absolute necessary.
|
|
106 |
*/
|
|
107 |
||
108 |
String *Item_func_concat::val_str(String *str) |
|
109 |
{
|
|
51.1.23
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
110 |
assert(fixed == 1); |
1
by brian
clean slate |
111 |
String *res,*res2,*use_as_buff; |
482
by Brian Aker
Remove uint. |
112 |
uint32_t i; |
1
by brian
clean slate |
113 |
bool is_const= 0; |
114 |
||
115 |
null_value=0; |
|
116 |
if (!(res=args[0]->val_str(str))) |
|
117 |
goto null; |
|
118 |
use_as_buff= &tmp_value; |
|
119 |
/* Item_subselect in --ps-protocol mode will state it as a non-const */
|
|
120 |
is_const= args[0]->const_item() || !args[0]->used_tables(); |
|
121 |
for (i=1 ; i < arg_count ; i++) |
|
122 |
{
|
|
123 |
if (res->length() == 0) |
|
124 |
{
|
|
125 |
if (!(res=args[i]->val_str(str))) |
|
126 |
goto null; |
|
127 |
}
|
|
128 |
else
|
|
129 |
{
|
|
130 |
if (!(res2=args[i]->val_str(use_as_buff))) |
|
131 |
goto null; |
|
132 |
if (res2->length() == 0) |
|
133 |
continue; |
|
134 |
if (res->length()+res2->length() > |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
135 |
current_session->variables.max_allowed_packet) |
1
by brian
clean slate |
136 |
{
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
137 |
push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN, |
1
by brian
clean slate |
138 |
ER_WARN_ALLOWED_PACKET_OVERFLOWED, |
139 |
ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED), func_name(), |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
140 |
current_session->variables.max_allowed_packet); |
1
by brian
clean slate |
141 |
goto null; |
142 |
}
|
|
143 |
if (!is_const && res->alloced_length() >= res->length()+res2->length()) |
|
144 |
{ // Use old buffer |
|
145 |
res->append(*res2); |
|
146 |
}
|
|
147 |
else if (str->alloced_length() >= res->length()+res2->length()) |
|
148 |
{
|
|
149 |
if (str == res2) |
|
150 |
str->replace(0,0,*res); |
|
151 |
else
|
|
152 |
{
|
|
153 |
str->copy(*res); |
|
154 |
str->append(*res2); |
|
155 |
}
|
|
156 |
res= str; |
|
157 |
use_as_buff= &tmp_value; |
|
158 |
}
|
|
159 |
else if (res == &tmp_value) |
|
160 |
{
|
|
161 |
if (res->append(*res2)) // Must be a blob |
|
162 |
goto null; |
|
163 |
}
|
|
164 |
else if (res2 == &tmp_value) |
|
165 |
{ // This can happend only 1 time |
|
166 |
if (tmp_value.replace(0,0,*res)) |
|
167 |
goto null; |
|
168 |
res= &tmp_value; |
|
169 |
use_as_buff=str; // Put next arg here |
|
170 |
}
|
|
171 |
else if (tmp_value.is_alloced() && res2->ptr() >= tmp_value.ptr() && |
|
172 |
res2->ptr() <= tmp_value.ptr() + tmp_value.alloced_length()) |
|
173 |
{
|
|
174 |
/*
|
|
175 |
This happens really seldom:
|
|
176 |
In this case res2 is sub string of tmp_value. We will
|
|
177 |
now work in place in tmp_value to set it to res | res2
|
|
178 |
*/
|
|
179 |
/* Chop the last characters in tmp_value that isn't in res2 */
|
|
205
by Brian Aker
uint32 -> uin32_t |
180 |
tmp_value.length((uint32_t) (res2->ptr() - tmp_value.ptr()) + |
1
by brian
clean slate |
181 |
res2->length()); |
182 |
/* Place res2 at start of tmp_value, remove chars before res2 */
|
|
205
by Brian Aker
uint32 -> uin32_t |
183 |
if (tmp_value.replace(0,(uint32_t) (res2->ptr() - tmp_value.ptr()), |
1
by brian
clean slate |
184 |
*res)) |
185 |
goto null; |
|
186 |
res= &tmp_value; |
|
187 |
use_as_buff=str; // Put next arg here |
|
188 |
}
|
|
189 |
else
|
|
190 |
{ // Two big const strings |
|
191 |
/*
|
|
192 |
NOTE: We should be prudent in the initial allocation unit -- the
|
|
193 |
size of the arguments is a function of data distribution, which
|
|
194 |
can be any. Instead of overcommitting at the first row, we grow
|
|
195 |
the allocated amount by the factor of 2. This ensures that no
|
|
196 |
more than 25% of memory will be overcommitted on average.
|
|
197 |
*/
|
|
198 |
||
482
by Brian Aker
Remove uint. |
199 |
uint32_t concat_len= res->length() + res2->length(); |
1
by brian
clean slate |
200 |
|
201 |
if (tmp_value.alloced_length() < concat_len) |
|
202 |
{
|
|
203 |
if (tmp_value.alloced_length() == 0) |
|
204 |
{
|
|
205 |
if (tmp_value.alloc(concat_len)) |
|
206 |
goto null; |
|
207 |
}
|
|
208 |
else
|
|
209 |
{
|
|
482
by Brian Aker
Remove uint. |
210 |
uint32_t new_len = cmax(tmp_value.alloced_length() * 2, concat_len); |
1
by brian
clean slate |
211 |
|
212 |
if (tmp_value.realloc(new_len)) |
|
213 |
goto null; |
|
214 |
}
|
|
215 |
}
|
|
216 |
||
217 |
if (tmp_value.copy(*res) || tmp_value.append(*res2)) |
|
218 |
goto null; |
|
219 |
||
220 |
res= &tmp_value; |
|
221 |
use_as_buff=str; |
|
222 |
}
|
|
223 |
is_const= 0; |
|
224 |
}
|
|
225 |
}
|
|
226 |
res->set_charset(collation.collation); |
|
227 |
return res; |
|
228 |
||
229 |
null: |
|
230 |
null_value=1; |
|
231 |
return 0; |
|
232 |
}
|
|
233 |
||
234 |
||
235 |
void Item_func_concat::fix_length_and_dec() |
|
236 |
{
|
|
151
by Brian Aker
Ulonglong to uint64_t |
237 |
uint64_t max_result_length= 0; |
1
by brian
clean slate |
238 |
|
239 |
if (agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV, 1)) |
|
240 |
return; |
|
241 |
||
482
by Brian Aker
Remove uint. |
242 |
for (uint32_t i=0 ; i < arg_count ; i++) |
1
by brian
clean slate |
243 |
{
|
244 |
if (args[i]->collation.collation->mbmaxlen != collation.collation->mbmaxlen) |
|
245 |
max_result_length+= (args[i]->max_length / |
|
246 |
args[i]->collation.collation->mbmaxlen) * |
|
247 |
collation.collation->mbmaxlen; |
|
248 |
else
|
|
249 |
max_result_length+= args[i]->max_length; |
|
250 |
}
|
|
251 |
||
252 |
if (max_result_length >= MAX_BLOB_WIDTH) |
|
253 |
{
|
|
254 |
max_result_length= MAX_BLOB_WIDTH; |
|
255 |
maybe_null= 1; |
|
256 |
}
|
|
257 |
max_length= (ulong) max_result_length; |
|
258 |
}
|
|
259 |
||
260 |
||
261 |
/**
|
|
262 |
concat with separator. First arg is the separator
|
|
263 |
concat_ws takes at least two arguments.
|
|
264 |
*/
|
|
265 |
||
266 |
String *Item_func_concat_ws::val_str(String *str) |
|
267 |
{
|
|
51.1.23
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
268 |
assert(fixed == 1); |
1
by brian
clean slate |
269 |
char tmp_str_buff[10]; |
270 |
String tmp_sep_str(tmp_str_buff, sizeof(tmp_str_buff),default_charset_info), |
|
271 |
*sep_str, *res, *res2,*use_as_buff; |
|
482
by Brian Aker
Remove uint. |
272 |
uint32_t i; |
1
by brian
clean slate |
273 |
|
274 |
null_value=0; |
|
275 |
if (!(sep_str= args[0]->val_str(&tmp_sep_str))) |
|
276 |
goto null; |
|
277 |
||
278 |
use_as_buff= &tmp_value; |
|
279 |
str->length(0); // QQ; Should be removed |
|
280 |
res=str; |
|
281 |
||
282 |
// Skip until non-null argument is found.
|
|
283 |
// If not, return the empty string
|
|
284 |
for (i=1; i < arg_count; i++) |
|
285 |
if ((res= args[i]->val_str(str))) |
|
286 |
break; |
|
287 |
if (i == arg_count) |
|
288 |
return &my_empty_string; |
|
289 |
||
290 |
for (i++; i < arg_count ; i++) |
|
291 |
{
|
|
292 |
if (!(res2= args[i]->val_str(use_as_buff))) |
|
293 |
continue; // Skip NULL |
|
294 |
||
295 |
if (res->length() + sep_str->length() + res2->length() > |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
296 |
current_session->variables.max_allowed_packet) |
1
by brian
clean slate |
297 |
{
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
298 |
push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN, |
1
by brian
clean slate |
299 |
ER_WARN_ALLOWED_PACKET_OVERFLOWED, |
300 |
ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED), func_name(), |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
301 |
current_session->variables.max_allowed_packet); |
1
by brian
clean slate |
302 |
goto null; |
303 |
}
|
|
304 |
if (res->alloced_length() >= |
|
305 |
res->length() + sep_str->length() + res2->length()) |
|
306 |
{ // Use old buffer |
|
307 |
res->append(*sep_str); // res->length() > 0 always |
|
308 |
res->append(*res2); |
|
309 |
}
|
|
310 |
else if (str->alloced_length() >= |
|
311 |
res->length() + sep_str->length() + res2->length()) |
|
312 |
{
|
|
313 |
/* We have room in str; We can't get any errors here */
|
|
314 |
if (str == res2) |
|
315 |
{ // This is quote uncommon! |
|
316 |
str->replace(0,0,*sep_str); |
|
317 |
str->replace(0,0,*res); |
|
318 |
}
|
|
319 |
else
|
|
320 |
{
|
|
321 |
str->copy(*res); |
|
322 |
str->append(*sep_str); |
|
323 |
str->append(*res2); |
|
324 |
}
|
|
325 |
res=str; |
|
326 |
use_as_buff= &tmp_value; |
|
327 |
}
|
|
328 |
else if (res == &tmp_value) |
|
329 |
{
|
|
330 |
if (res->append(*sep_str) || res->append(*res2)) |
|
331 |
goto null; // Must be a blob |
|
332 |
}
|
|
333 |
else if (res2 == &tmp_value) |
|
334 |
{ // This can happend only 1 time |
|
335 |
if (tmp_value.replace(0,0,*sep_str) || tmp_value.replace(0,0,*res)) |
|
336 |
goto null; |
|
337 |
res= &tmp_value; |
|
338 |
use_as_buff=str; // Put next arg here |
|
339 |
}
|
|
340 |
else if (tmp_value.is_alloced() && res2->ptr() >= tmp_value.ptr() && |
|
341 |
res2->ptr() < tmp_value.ptr() + tmp_value.alloced_length()) |
|
342 |
{
|
|
343 |
/*
|
|
344 |
This happens really seldom:
|
|
345 |
In this case res2 is sub string of tmp_value. We will
|
|
346 |
now work in place in tmp_value to set it to res | sep_str | res2
|
|
347 |
*/
|
|
348 |
/* Chop the last characters in tmp_value that isn't in res2 */
|
|
205
by Brian Aker
uint32 -> uin32_t |
349 |
tmp_value.length((uint32_t) (res2->ptr() - tmp_value.ptr()) + |
1
by brian
clean slate |
350 |
res2->length()); |
351 |
/* Place res2 at start of tmp_value, remove chars before res2 */
|
|
205
by Brian Aker
uint32 -> uin32_t |
352 |
if (tmp_value.replace(0,(uint32_t) (res2->ptr() - tmp_value.ptr()), |
1
by brian
clean slate |
353 |
*res) || |
354 |
tmp_value.replace(res->length(),0, *sep_str)) |
|
355 |
goto null; |
|
356 |
res= &tmp_value; |
|
357 |
use_as_buff=str; // Put next arg here |
|
358 |
}
|
|
359 |
else
|
|
360 |
{ // Two big const strings |
|
361 |
/*
|
|
362 |
NOTE: We should be prudent in the initial allocation unit -- the
|
|
363 |
size of the arguments is a function of data distribution, which can
|
|
364 |
be any. Instead of overcommitting at the first row, we grow the
|
|
365 |
allocated amount by the factor of 2. This ensures that no more than
|
|
366 |
25% of memory will be overcommitted on average.
|
|
367 |
*/
|
|
368 |
||
482
by Brian Aker
Remove uint. |
369 |
uint32_t concat_len= res->length() + sep_str->length() + res2->length(); |
1
by brian
clean slate |
370 |
|
371 |
if (tmp_value.alloced_length() < concat_len) |
|
372 |
{
|
|
373 |
if (tmp_value.alloced_length() == 0) |
|
374 |
{
|
|
375 |
if (tmp_value.alloc(concat_len)) |
|
376 |
goto null; |
|
377 |
}
|
|
378 |
else
|
|
379 |
{
|
|
482
by Brian Aker
Remove uint. |
380 |
uint32_t new_len = cmax(tmp_value.alloced_length() * 2, concat_len); |
1
by brian
clean slate |
381 |
|
382 |
if (tmp_value.realloc(new_len)) |
|
383 |
goto null; |
|
384 |
}
|
|
385 |
}
|
|
386 |
||
387 |
if (tmp_value.copy(*res) || |
|
388 |
tmp_value.append(*sep_str) || |
|
389 |
tmp_value.append(*res2)) |
|
390 |
goto null; |
|
391 |
res= &tmp_value; |
|
392 |
use_as_buff=str; |
|
393 |
}
|
|
394 |
}
|
|
395 |
res->set_charset(collation.collation); |
|
396 |
return res; |
|
397 |
||
398 |
null: |
|
399 |
null_value=1; |
|
400 |
return 0; |
|
401 |
}
|
|
402 |
||
403 |
||
404 |
void Item_func_concat_ws::fix_length_and_dec() |
|
405 |
{
|
|
151
by Brian Aker
Ulonglong to uint64_t |
406 |
uint64_t max_result_length; |
1
by brian
clean slate |
407 |
|
408 |
if (agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV, 1)) |
|
409 |
return; |
|
410 |
||
411 |
/*
|
|
412 |
arg_count cannot be less than 2,
|
|
413 |
it is done on parser level in sql_yacc.yy
|
|
414 |
so, (arg_count - 2) is safe here.
|
|
415 |
*/
|
|
151
by Brian Aker
Ulonglong to uint64_t |
416 |
max_result_length= (uint64_t) args[0]->max_length * (arg_count - 2); |
482
by Brian Aker
Remove uint. |
417 |
for (uint32_t i=1 ; i < arg_count ; i++) |
1
by brian
clean slate |
418 |
max_result_length+=args[i]->max_length; |
419 |
||
420 |
if (max_result_length >= MAX_BLOB_WIDTH) |
|
421 |
{
|
|
422 |
max_result_length= MAX_BLOB_WIDTH; |
|
423 |
maybe_null= 1; |
|
424 |
}
|
|
425 |
max_length= (ulong) max_result_length; |
|
426 |
}
|
|
427 |
||
428 |
||
429 |
String *Item_func_reverse::val_str(String *str) |
|
430 |
{
|
|
51.1.23
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
431 |
assert(fixed == 1); |
1
by brian
clean slate |
432 |
String *res = args[0]->val_str(str); |
433 |
char *ptr, *end, *tmp; |
|
434 |
||
435 |
if ((null_value=args[0]->null_value)) |
|
436 |
return 0; |
|
437 |
/* An empty string is a special case as the string pointer may be null */
|
|
438 |
if (!res->length()) |
|
439 |
return &my_empty_string; |
|
440 |
if (tmp_value.alloced_length() < res->length() && |
|
441 |
tmp_value.realloc(res->length())) |
|
442 |
{
|
|
443 |
null_value= 1; |
|
444 |
return 0; |
|
445 |
}
|
|
446 |
tmp_value.length(res->length()); |
|
447 |
tmp_value.set_charset(res->charset()); |
|
448 |
ptr= (char *) res->ptr(); |
|
449 |
end= ptr + res->length(); |
|
450 |
tmp= (char *) tmp_value.ptr() + tmp_value.length(); |
|
451 |
#ifdef USE_MB
|
|
452 |
if (use_mb(res->charset())) |
|
453 |
{
|
|
205
by Brian Aker
uint32 -> uin32_t |
454 |
register uint32_t l; |
1
by brian
clean slate |
455 |
while (ptr < end) |
456 |
{
|
|
457 |
if ((l= my_ismbchar(res->charset(),ptr,end))) |
|
458 |
{
|
|
459 |
tmp-= l; |
|
460 |
memcpy(tmp,ptr,l); |
|
461 |
ptr+= l; |
|
462 |
}
|
|
463 |
else
|
|
464 |
*--tmp= *ptr++; |
|
465 |
}
|
|
466 |
}
|
|
467 |
else
|
|
468 |
#endif /* USE_MB */ |
|
469 |
{
|
|
470 |
while (ptr < end) |
|
471 |
*--tmp= *ptr++; |
|
472 |
}
|
|
473 |
return &tmp_value; |
|
474 |
}
|
|
475 |
||
476 |
||
477 |
void Item_func_reverse::fix_length_and_dec() |
|
478 |
{
|
|
479 |
collation.set(args[0]->collation); |
|
480 |
max_length = args[0]->max_length; |
|
481 |
}
|
|
482 |
||
483 |
/**
|
|
484 |
Replace all occurences of string2 in string1 with string3.
|
|
485 |
||
486 |
Don't reallocate val_str() if not needed.
|
|
487 |
||
488 |
@todo
|
|
489 |
Fix that this works with binary strings when using USE_MB
|
|
490 |
*/
|
|
491 |
||
492 |
String *Item_func_replace::val_str(String *str) |
|
493 |
{
|
|
51.1.23
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
494 |
assert(fixed == 1); |
1
by brian
clean slate |
495 |
String *res,*res2,*res3; |
496 |
int offset; |
|
482
by Brian Aker
Remove uint. |
497 |
uint32_t from_length,to_length; |
1
by brian
clean slate |
498 |
bool alloced=0; |
499 |
#ifdef USE_MB
|
|
500 |
const char *ptr,*end,*strend,*search,*search_end; |
|
205
by Brian Aker
uint32 -> uin32_t |
501 |
register uint32_t l; |
1
by brian
clean slate |
502 |
bool binary_cmp; |
503 |
#endif
|
|
504 |
||
505 |
null_value=0; |
|
506 |
res=args[0]->val_str(str); |
|
507 |
if (args[0]->null_value) |
|
508 |
goto null; |
|
509 |
res2=args[1]->val_str(&tmp_value); |
|
510 |
if (args[1]->null_value) |
|
511 |
goto null; |
|
512 |
||
513 |
res->set_charset(collation.collation); |
|
514 |
||
515 |
#ifdef USE_MB
|
|
516 |
binary_cmp = ((res->charset()->state & MY_CS_BINSORT) || !use_mb(res->charset())); |
|
517 |
#endif
|
|
518 |
||
519 |
if (res2->length() == 0) |
|
520 |
return res; |
|
521 |
#ifndef USE_MB
|
|
522 |
if ((offset=res->strstr(*res2)) < 0) |
|
523 |
return res; |
|
524 |
#else
|
|
525 |
offset=0; |
|
526 |
if (binary_cmp && (offset=res->strstr(*res2)) < 0) |
|
527 |
return res; |
|
528 |
#endif
|
|
529 |
if (!(res3=args[2]->val_str(&tmp_value2))) |
|
530 |
goto null; |
|
531 |
from_length= res2->length(); |
|
532 |
to_length= res3->length(); |
|
533 |
||
534 |
#ifdef USE_MB
|
|
535 |
if (!binary_cmp) |
|
536 |
{
|
|
537 |
search=res2->ptr(); |
|
538 |
search_end=search+from_length; |
|
539 |
redo: |
|
540 |
ptr=res->ptr()+offset; |
|
541 |
strend=res->ptr()+res->length(); |
|
542 |
end=strend-from_length+1; |
|
543 |
while (ptr < end) |
|
544 |
{
|
|
545 |
if (*ptr == *search) |
|
546 |
{
|
|
547 |
register char *i,*j; |
|
548 |
i=(char*) ptr+1; j=(char*) search+1; |
|
549 |
while (j != search_end) |
|
550 |
if (*i++ != *j++) goto skip; |
|
551 |
offset= (int) (ptr-res->ptr()); |
|
552 |
if (res->length()-from_length + to_length > |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
553 |
current_session->variables.max_allowed_packet) |
1
by brian
clean slate |
554 |
{
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
555 |
push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN, |
1
by brian
clean slate |
556 |
ER_WARN_ALLOWED_PACKET_OVERFLOWED, |
557 |
ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED), |
|
558 |
func_name(), |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
559 |
current_session->variables.max_allowed_packet); |
1
by brian
clean slate |
560 |
|
561 |
goto null; |
|
562 |
}
|
|
563 |
if (!alloced) |
|
564 |
{
|
|
565 |
alloced=1; |
|
566 |
res=copy_if_not_alloced(str,res,res->length()+to_length); |
|
567 |
}
|
|
568 |
res->replace((uint) offset,from_length,*res3); |
|
569 |
offset+=(int) to_length; |
|
570 |
goto redo; |
|
571 |
}
|
|
572 |
skip: |
|
573 |
if ((l=my_ismbchar(res->charset(), ptr,strend))) ptr+=l; |
|
574 |
else ++ptr; |
|
575 |
}
|
|
576 |
}
|
|
577 |
else
|
|
578 |
#endif /* USE_MB */ |
|
579 |
do
|
|
580 |
{
|
|
581 |
if (res->length()-from_length + to_length > |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
582 |
current_session->variables.max_allowed_packet) |
1
by brian
clean slate |
583 |
{
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
584 |
push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN, |
1
by brian
clean slate |
585 |
ER_WARN_ALLOWED_PACKET_OVERFLOWED, |
586 |
ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED), func_name(), |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
587 |
current_session->variables.max_allowed_packet); |
1
by brian
clean slate |
588 |
goto null; |
589 |
}
|
|
590 |
if (!alloced) |
|
591 |
{
|
|
592 |
alloced=1; |
|
593 |
res=copy_if_not_alloced(str,res,res->length()+to_length); |
|
594 |
}
|
|
595 |
res->replace((uint) offset,from_length,*res3); |
|
596 |
offset+=(int) to_length; |
|
597 |
}
|
|
598 |
while ((offset=res->strstr(*res2,(uint) offset)) >= 0); |
|
599 |
return res; |
|
600 |
||
601 |
null: |
|
602 |
null_value=1; |
|
603 |
return 0; |
|
604 |
}
|
|
605 |
||
606 |
||
607 |
void Item_func_replace::fix_length_and_dec() |
|
608 |
{
|
|
151
by Brian Aker
Ulonglong to uint64_t |
609 |
uint64_t max_result_length= args[0]->max_length; |
1
by brian
clean slate |
610 |
int diff=(int) (args[2]->max_length - args[1]->max_length); |
611 |
if (diff > 0 && args[1]->max_length) |
|
612 |
{ // Calculate of maxreplaces |
|
151
by Brian Aker
Ulonglong to uint64_t |
613 |
uint64_t max_substrs= max_result_length/args[1]->max_length; |
1
by brian
clean slate |
614 |
max_result_length+= max_substrs * (uint) diff; |
615 |
}
|
|
616 |
if (max_result_length >= MAX_BLOB_WIDTH) |
|
617 |
{
|
|
618 |
max_result_length= MAX_BLOB_WIDTH; |
|
619 |
maybe_null= 1; |
|
620 |
}
|
|
621 |
max_length= (ulong) max_result_length; |
|
622 |
||
623 |
if (agg_arg_charsets(collation, args, 3, MY_COLL_CMP_CONV, 1)) |
|
624 |
return; |
|
625 |
}
|
|
626 |
||
627 |
||
628 |
String *Item_func_insert::val_str(String *str) |
|
629 |
{
|
|
51.1.23
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
630 |
assert(fixed == 1); |
1
by brian
clean slate |
631 |
String *res,*res2; |
152
by Brian Aker
longlong replacement |
632 |
int64_t start, length; /* must be int64_t to avoid truncation */ |
1
by brian
clean slate |
633 |
|
634 |
null_value=0; |
|
635 |
res=args[0]->val_str(str); |
|
636 |
res2=args[3]->val_str(&tmp_value); |
|
637 |
start= args[1]->val_int() - 1; |
|
638 |
length= args[2]->val_int(); |
|
639 |
||
640 |
if (args[0]->null_value || args[1]->null_value || args[2]->null_value || |
|
641 |
args[3]->null_value) |
|
642 |
goto null; /* purecov: inspected */ |
|
643 |
||
644 |
if ((start < 0) || (start > res->length())) |
|
645 |
return res; // Wrong param; skip insert |
|
646 |
if ((length < 0) || (length > res->length())) |
|
647 |
length= res->length(); |
|
648 |
||
649 |
/* start and length are now sufficiently valid to pass to charpos function */
|
|
650 |
start= res->charpos((int) start); |
|
205
by Brian Aker
uint32 -> uin32_t |
651 |
length= res->charpos((int) length, (uint32_t) start); |
1
by brian
clean slate |
652 |
|
653 |
/* Re-testing with corrected params */
|
|
654 |
if (start > res->length()) |
|
655 |
return res; /* purecov: inspected */ // Wrong param; skip insert |
|
656 |
if (length > res->length() - start) |
|
657 |
length= res->length() - start; |
|
658 |
||
151
by Brian Aker
Ulonglong to uint64_t |
659 |
if ((uint64_t) (res->length() - length + res2->length()) > |
520.1.22
by Brian Aker
Second pass of thd cleanup |
660 |
(uint64_t) current_session->variables.max_allowed_packet) |
1
by brian
clean slate |
661 |
{
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
662 |
push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN, |
1
by brian
clean slate |
663 |
ER_WARN_ALLOWED_PACKET_OVERFLOWED, |
664 |
ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED), |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
665 |
func_name(), current_session->variables.max_allowed_packet); |
1
by brian
clean slate |
666 |
goto null; |
667 |
}
|
|
668 |
res=copy_if_not_alloced(str,res,res->length()); |
|
205
by Brian Aker
uint32 -> uin32_t |
669 |
res->replace((uint32_t) start,(uint32_t) length,*res2); |
1
by brian
clean slate |
670 |
return res; |
671 |
null: |
|
672 |
null_value=1; |
|
673 |
return 0; |
|
674 |
}
|
|
675 |
||
676 |
||
677 |
void Item_func_insert::fix_length_and_dec() |
|
678 |
{
|
|
151
by Brian Aker
Ulonglong to uint64_t |
679 |
uint64_t max_result_length; |
1
by brian
clean slate |
680 |
|
681 |
// Handle character set for args[0] and args[3].
|
|
682 |
if (agg_arg_charsets(collation, &args[0], 2, MY_COLL_ALLOW_CONV, 3)) |
|
683 |
return; |
|
151
by Brian Aker
Ulonglong to uint64_t |
684 |
max_result_length= ((uint64_t) args[0]->max_length+ |
685 |
(uint64_t) args[3]->max_length); |
|
1
by brian
clean slate |
686 |
if (max_result_length >= MAX_BLOB_WIDTH) |
687 |
{
|
|
688 |
max_result_length= MAX_BLOB_WIDTH; |
|
689 |
maybe_null= 1; |
|
690 |
}
|
|
691 |
max_length= (ulong) max_result_length; |
|
692 |
}
|
|
693 |
||
694 |
||
695 |
String *Item_str_conv::val_str(String *str) |
|
696 |
{
|
|
51.1.23
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
697 |
assert(fixed == 1); |
1
by brian
clean slate |
698 |
String *res; |
699 |
if (!(res=args[0]->val_str(str))) |
|
700 |
{
|
|
701 |
null_value=1; /* purecov: inspected */ |
|
702 |
return 0; /* purecov: inspected */ |
|
703 |
}
|
|
704 |
null_value=0; |
|
705 |
if (multiply == 1) |
|
706 |
{
|
|
482
by Brian Aker
Remove uint. |
707 |
uint32_t len; |
1
by brian
clean slate |
708 |
res= copy_if_not_alloced(str,res,res->length()); |
709 |
len= converter(collation.collation, (char*) res->ptr(), res->length(), |
|
710 |
(char*) res->ptr(), res->length()); |
|
51.1.23
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
711 |
assert(len <= res->length()); |
1
by brian
clean slate |
712 |
res->length(len); |
713 |
}
|
|
714 |
else
|
|
715 |
{
|
|
482
by Brian Aker
Remove uint. |
716 |
uint32_t len= res->length() * multiply; |
1
by brian
clean slate |
717 |
tmp_value.alloc(len); |
718 |
tmp_value.set_charset(collation.collation); |
|
719 |
len= converter(collation.collation, (char*) res->ptr(), res->length(), |
|
720 |
(char*) tmp_value.ptr(), len); |
|
721 |
tmp_value.length(len); |
|
722 |
res= &tmp_value; |
|
723 |
}
|
|
724 |
return res; |
|
725 |
}
|
|
726 |
||
727 |
||
728 |
void Item_func_lcase::fix_length_and_dec() |
|
729 |
{
|
|
730 |
collation.set(args[0]->collation); |
|
731 |
multiply= collation.collation->casedn_multiply; |
|
732 |
converter= collation.collation->cset->casedn; |
|
733 |
max_length= args[0]->max_length * multiply; |
|
734 |
}
|
|
735 |
||
736 |
void Item_func_ucase::fix_length_and_dec() |
|
737 |
{
|
|
738 |
collation.set(args[0]->collation); |
|
739 |
multiply= collation.collation->caseup_multiply; |
|
740 |
converter= collation.collation->cset->caseup; |
|
741 |
max_length= args[0]->max_length * multiply; |
|
742 |
}
|
|
743 |
||
744 |
||
745 |
String *Item_func_left::val_str(String *str) |
|
746 |
{
|
|
51.1.23
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
747 |
assert(fixed == 1); |
1
by brian
clean slate |
748 |
String *res= args[0]->val_str(str); |
749 |
||
152
by Brian Aker
longlong replacement |
750 |
/* must be int64_t to avoid truncation */
|
751 |
int64_t length= args[1]->val_int(); |
|
482
by Brian Aker
Remove uint. |
752 |
uint32_t char_pos; |
1
by brian
clean slate |
753 |
|
754 |
if ((null_value=(args[0]->null_value || args[1]->null_value))) |
|
755 |
return 0; |
|
756 |
||
757 |
/* if "unsigned_flag" is set, we have a *huge* positive number. */
|
|
758 |
if ((length <= 0) && (!args[1]->unsigned_flag)) |
|
759 |
return &my_empty_string; |
|
760 |
||
151
by Brian Aker
Ulonglong to uint64_t |
761 |
if ((res->length() <= (uint64_t) length) || |
1
by brian
clean slate |
762 |
(res->length() <= (char_pos= res->charpos((int) length)))) |
763 |
return res; |
|
764 |
||
765 |
tmp_value.set(*res, 0, char_pos); |
|
766 |
return &tmp_value; |
|
767 |
}
|
|
768 |
||
769 |
||
770 |
void Item_str_func::left_right_max_length() |
|
771 |
{
|
|
772 |
max_length=args[0]->max_length; |
|
773 |
if (args[1]->const_item()) |
|
774 |
{
|
|
775 |
int length=(int) args[1]->val_int()*collation.collation->mbmaxlen; |
|
776 |
if (length <= 0) |
|
777 |
max_length=0; |
|
778 |
else
|
|
779 |
set_if_smaller(max_length,(uint) length); |
|
780 |
}
|
|
781 |
}
|
|
782 |
||
783 |
||
784 |
void Item_func_left::fix_length_and_dec() |
|
785 |
{
|
|
786 |
collation.set(args[0]->collation); |
|
787 |
left_right_max_length(); |
|
788 |
}
|
|
789 |
||
790 |
||
791 |
String *Item_func_right::val_str(String *str) |
|
792 |
{
|
|
51.1.23
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
793 |
assert(fixed == 1); |
1
by brian
clean slate |
794 |
String *res= args[0]->val_str(str); |
152
by Brian Aker
longlong replacement |
795 |
/* must be int64_t to avoid truncation */
|
796 |
int64_t length= args[1]->val_int(); |
|
1
by brian
clean slate |
797 |
|
798 |
if ((null_value=(args[0]->null_value || args[1]->null_value))) |
|
799 |
return 0; /* purecov: inspected */ |
|
800 |
||
801 |
/* if "unsigned_flag" is set, we have a *huge* positive number. */
|
|
802 |
if ((length <= 0) && (!args[1]->unsigned_flag)) |
|
803 |
return &my_empty_string; /* purecov: inspected */ |
|
804 |
||
151
by Brian Aker
Ulonglong to uint64_t |
805 |
if (res->length() <= (uint64_t) length) |
1
by brian
clean slate |
806 |
return res; /* purecov: inspected */ |
807 |
||
482
by Brian Aker
Remove uint. |
808 |
uint32_t start=res->numchars(); |
1
by brian
clean slate |
809 |
if (start <= (uint) length) |
810 |
return res; |
|
811 |
start=res->charpos(start - (uint) length); |
|
812 |
tmp_value.set(*res,start,res->length()-start); |
|
813 |
return &tmp_value; |
|
814 |
}
|
|
815 |
||
816 |
||
817 |
void Item_func_right::fix_length_and_dec() |
|
818 |
{
|
|
819 |
collation.set(args[0]->collation); |
|
820 |
left_right_max_length(); |
|
821 |
}
|
|
822 |
||
823 |
||
824 |
String *Item_func_substr::val_str(String *str) |
|
825 |
{
|
|
51.1.23
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
826 |
assert(fixed == 1); |
1
by brian
clean slate |
827 |
String *res = args[0]->val_str(str); |
152
by Brian Aker
longlong replacement |
828 |
/* must be int64_t to avoid truncation */
|
829 |
int64_t start= args[1]->val_int(); |
|
163
by Brian Aker
Merge Monty's code. |
830 |
/* Assumes that the maximum length of a String is < INT32_MAX. */
|
1
by brian
clean slate |
831 |
/* Limit so that code sees out-of-bound value properly. */
|
163
by Brian Aker
Merge Monty's code. |
832 |
int64_t length= arg_count == 3 ? args[2]->val_int() : INT32_MAX; |
152
by Brian Aker
longlong replacement |
833 |
int64_t tmp_length; |
1
by brian
clean slate |
834 |
|
835 |
if ((null_value=(args[0]->null_value || args[1]->null_value || |
|
836 |
(arg_count == 3 && args[2]->null_value)))) |
|
837 |
return 0; /* purecov: inspected */ |
|
838 |
||
839 |
/* Negative or zero length, will return empty string. */
|
|
840 |
if ((arg_count == 3) && (length <= 0) && |
|
841 |
(length == 0 || !args[2]->unsigned_flag)) |
|
842 |
return &my_empty_string; |
|
843 |
||
163
by Brian Aker
Merge Monty's code. |
844 |
/* Assumes that the maximum length of a String is < INT32_MAX. */
|
1
by brian
clean slate |
845 |
/* Set here so that rest of code sees out-of-bound value as such. */
|
163
by Brian Aker
Merge Monty's code. |
846 |
if ((length <= 0) || (length > INT32_MAX)) |
847 |
length= INT32_MAX; |
|
1
by brian
clean slate |
848 |
|
849 |
/* if "unsigned_flag" is set, we have a *huge* positive number. */
|
|
163
by Brian Aker
Merge Monty's code. |
850 |
/* Assumes that the maximum length of a String is < INT32_MAX. */
|
851 |
if ((!args[1]->unsigned_flag && (start < INT32_MIN || start > INT32_MAX)) || |
|
852 |
(args[1]->unsigned_flag && ((uint64_t) start > INT32_MAX))) |
|
1
by brian
clean slate |
853 |
return &my_empty_string; |
854 |
||
855 |
start= ((start < 0) ? res->numchars() + start : start - 1); |
|
856 |
start= res->charpos((int) start); |
|
857 |
if ((start < 0) || ((uint) start + 1 > res->length())) |
|
858 |
return &my_empty_string; |
|
859 |
||
205
by Brian Aker
uint32 -> uin32_t |
860 |
length= res->charpos((int) length, (uint32_t) start); |
1
by brian
clean slate |
861 |
tmp_length= res->length() - start; |
398.1.4
by Monty Taylor
Renamed max/min. |
862 |
length= cmin(length, tmp_length); |
1
by brian
clean slate |
863 |
|
152
by Brian Aker
longlong replacement |
864 |
if (!start && (int64_t) res->length() == length) |
1
by brian
clean slate |
865 |
return res; |
205
by Brian Aker
uint32 -> uin32_t |
866 |
tmp_value.set(*res, (uint32_t) start, (uint32_t) length); |
1
by brian
clean slate |
867 |
return &tmp_value; |
868 |
}
|
|
869 |
||
870 |
||
871 |
void Item_func_substr::fix_length_and_dec() |
|
872 |
{
|
|
873 |
max_length=args[0]->max_length; |
|
874 |
||
875 |
collation.set(args[0]->collation); |
|
876 |
if (args[1]->const_item()) |
|
877 |
{
|
|
205
by Brian Aker
uint32 -> uin32_t |
878 |
int32_t start= (int32_t) args[1]->val_int(); |
1
by brian
clean slate |
879 |
if (start < 0) |
880 |
max_length= ((uint)(-start) > max_length) ? 0 : (uint)(-start); |
|
881 |
else
|
|
398.1.4
by Monty Taylor
Renamed max/min. |
882 |
max_length-= cmin((uint)(start - 1), max_length); |
1
by brian
clean slate |
883 |
}
|
884 |
if (arg_count == 3 && args[2]->const_item()) |
|
885 |
{
|
|
205
by Brian Aker
uint32 -> uin32_t |
886 |
int32_t length= (int32_t) args[2]->val_int(); |
1
by brian
clean slate |
887 |
if (length <= 0) |
888 |
max_length=0; /* purecov: inspected */ |
|
889 |
else
|
|
890 |
set_if_smaller(max_length,(uint) length); |
|
891 |
}
|
|
892 |
max_length*= collation.collation->mbmaxlen; |
|
893 |
}
|
|
894 |
||
895 |
||
896 |
void Item_func_substr_index::fix_length_and_dec() |
|
897 |
{
|
|
898 |
max_length= args[0]->max_length; |
|
899 |
||
900 |
if (agg_arg_charsets(collation, args, 2, MY_COLL_CMP_CONV, 1)) |
|
901 |
return; |
|
902 |
}
|
|
903 |
||
904 |
||
905 |
String *Item_func_substr_index::val_str(String *str) |
|
906 |
{
|
|
51.1.23
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
907 |
assert(fixed == 1); |
1
by brian
clean slate |
908 |
String *res= args[0]->val_str(str); |
909 |
String *delimiter= args[1]->val_str(&tmp_value); |
|
205
by Brian Aker
uint32 -> uin32_t |
910 |
int32_t count= (int32_t) args[2]->val_int(); |
482
by Brian Aker
Remove uint. |
911 |
uint32_t offset; |
1
by brian
clean slate |
912 |
|
913 |
if (args[0]->null_value || args[1]->null_value || args[2]->null_value) |
|
914 |
{ // string and/or delim are null |
|
915 |
null_value=1; |
|
916 |
return 0; |
|
917 |
}
|
|
918 |
null_value=0; |
|
482
by Brian Aker
Remove uint. |
919 |
uint32_t delimiter_length= delimiter->length(); |
1
by brian
clean slate |
920 |
if (!res->length() || !delimiter_length || !count) |
921 |
return &my_empty_string; // Wrong parameters |
|
922 |
||
923 |
res->set_charset(collation.collation); |
|
924 |
||
925 |
#ifdef USE_MB
|
|
926 |
if (use_mb(res->charset())) |
|
927 |
{
|
|
928 |
const char *ptr= res->ptr(); |
|
929 |
const char *strend= ptr+res->length(); |
|
930 |
const char *end= strend-delimiter_length+1; |
|
931 |
const char *search= delimiter->ptr(); |
|
932 |
const char *search_end= search+delimiter_length; |
|
205
by Brian Aker
uint32 -> uin32_t |
933 |
int32_t n=0,c=count,pass; |
934 |
register uint32_t l; |
|
1
by brian
clean slate |
935 |
for (pass=(count>0);pass<2;++pass) |
936 |
{
|
|
937 |
while (ptr < end) |
|
938 |
{
|
|
939 |
if (*ptr == *search) |
|
940 |
{
|
|
941 |
register char *i,*j; |
|
942 |
i=(char*) ptr+1; j=(char*) search+1; |
|
943 |
while (j != search_end) |
|
944 |
if (*i++ != *j++) goto skip; |
|
945 |
if (pass==0) ++n; |
|
946 |
else if (!--c) break; |
|
947 |
ptr+= delimiter_length; |
|
948 |
continue; |
|
949 |
}
|
|
950 |
skip: |
|
951 |
if ((l=my_ismbchar(res->charset(), ptr,strend))) ptr+=l; |
|
952 |
else ++ptr; |
|
953 |
} /* either not found or got total number when count<0 */ |
|
954 |
if (pass == 0) /* count<0 */ |
|
955 |
{
|
|
956 |
c+=n+1; |
|
957 |
if (c<=0) return res; /* not found, return original string */ |
|
958 |
ptr=res->ptr(); |
|
959 |
}
|
|
960 |
else
|
|
961 |
{
|
|
962 |
if (c) return res; /* Not found, return original string */ |
|
963 |
if (count>0) /* return left part */ |
|
964 |
{
|
|
965 |
tmp_value.set(*res,0,(ulong) (ptr-res->ptr())); |
|
966 |
}
|
|
967 |
else /* return right part */ |
|
968 |
{
|
|
969 |
ptr+= delimiter_length; |
|
970 |
tmp_value.set(*res,(ulong) (ptr-res->ptr()), (ulong) (strend-ptr)); |
|
971 |
}
|
|
972 |
}
|
|
973 |
}
|
|
974 |
}
|
|
975 |
else
|
|
976 |
#endif /* USE_MB */ |
|
977 |
{
|
|
978 |
if (count > 0) |
|
979 |
{ // start counting from the beginning |
|
980 |
for (offset=0; ; offset+= delimiter_length) |
|
981 |
{
|
|
982 |
if ((int) (offset= res->strstr(*delimiter, offset)) < 0) |
|
983 |
return res; // Didn't find, return org string |
|
984 |
if (!--count) |
|
985 |
{
|
|
986 |
tmp_value.set(*res,0,offset); |
|
987 |
break; |
|
988 |
}
|
|
989 |
}
|
|
990 |
}
|
|
991 |
else
|
|
992 |
{
|
|
993 |
/*
|
|
994 |
Negative index, start counting at the end
|
|
995 |
*/
|
|
996 |
for (offset=res->length(); offset ;) |
|
997 |
{
|
|
998 |
/*
|
|
999 |
this call will result in finding the position pointing to one
|
|
1000 |
address space less than where the found substring is located
|
|
1001 |
in res
|
|
1002 |
*/
|
|
1003 |
if ((int) (offset= res->strrstr(*delimiter, offset)) < 0) |
|
1004 |
return res; // Didn't find, return org string |
|
1005 |
/*
|
|
1006 |
At this point, we've searched for the substring
|
|
1007 |
the number of times as supplied by the index value
|
|
1008 |
*/
|
|
1009 |
if (!++count) |
|
1010 |
{
|
|
1011 |
offset+= delimiter_length; |
|
1012 |
tmp_value.set(*res,offset,res->length()- offset); |
|
1013 |
break; |
|
1014 |
}
|
|
1015 |
}
|
|
1016 |
}
|
|
1017 |
}
|
|
1018 |
/*
|
|
1019 |
We always mark tmp_value as const so that if val_str() is called again
|
|
1020 |
on this object, we don't disrupt the contents of tmp_value when it was
|
|
1021 |
derived from another String.
|
|
1022 |
*/
|
|
1023 |
tmp_value.mark_as_const(); |
|
1024 |
return (&tmp_value); |
|
1025 |
}
|
|
1026 |
||
1027 |
/*
|
|
1028 |
** The trim functions are extension to ANSI SQL because they trim substrings
|
|
1029 |
** They ltrim() and rtrim() functions are optimized for 1 byte strings
|
|
1030 |
** They also return the original string if possible, else they return
|
|
1031 |
** a substring that points at the original string.
|
|
1032 |
*/
|
|
1033 |
||
1034 |
||
1035 |
String *Item_func_ltrim::val_str(String *str) |
|
1036 |
{
|
|
51.1.23
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
1037 |
assert(fixed == 1); |
1
by brian
clean slate |
1038 |
char buff[MAX_FIELD_WIDTH], *ptr, *end; |
1039 |
String tmp(buff,sizeof(buff),system_charset_info); |
|
1040 |
String *res, *remove_str; |
|
482
by Brian Aker
Remove uint. |
1041 |
uint32_t remove_length; |
1
by brian
clean slate |
1042 |
|
1043 |
res= args[0]->val_str(str); |
|
1044 |
if ((null_value=args[0]->null_value)) |
|
1045 |
return 0; |
|
1046 |
remove_str= &remove; /* Default value. */ |
|
1047 |
if (arg_count == 2) |
|
1048 |
{
|
|
1049 |
remove_str= args[1]->val_str(&tmp); |
|
1050 |
if ((null_value= args[1]->null_value)) |
|
1051 |
return 0; |
|
1052 |
}
|
|
1053 |
||
1054 |
if ((remove_length= remove_str->length()) == 0 || |
|
1055 |
remove_length > res->length()) |
|
1056 |
return res; |
|
1057 |
||
1058 |
ptr= (char*) res->ptr(); |
|
1059 |
end= ptr+res->length(); |
|
1060 |
if (remove_length == 1) |
|
1061 |
{
|
|
1062 |
char chr=(*remove_str)[0]; |
|
1063 |
while (ptr != end && *ptr == chr) |
|
1064 |
ptr++; |
|
1065 |
}
|
|
1066 |
else
|
|
1067 |
{
|
|
1068 |
const char *r_ptr=remove_str->ptr(); |
|
1069 |
end-=remove_length; |
|
1070 |
while (ptr <= end && !memcmp(ptr, r_ptr, remove_length)) |
|
1071 |
ptr+=remove_length; |
|
1072 |
end+=remove_length; |
|
1073 |
}
|
|
1074 |
if (ptr == res->ptr()) |
|
1075 |
return res; |
|
1076 |
tmp_value.set(*res,(uint) (ptr - res->ptr()),(uint) (end-ptr)); |
|
1077 |
return &tmp_value; |
|
1078 |
}
|
|
1079 |
||
1080 |
||
1081 |
String *Item_func_rtrim::val_str(String *str) |
|
1082 |
{
|
|
51.1.23
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
1083 |
assert(fixed == 1); |
1
by brian
clean slate |
1084 |
char buff[MAX_FIELD_WIDTH], *ptr, *end; |
1085 |
String tmp(buff, sizeof(buff), system_charset_info); |
|
1086 |
String *res, *remove_str; |
|
482
by Brian Aker
Remove uint. |
1087 |
uint32_t remove_length; |
1
by brian
clean slate |
1088 |
|
1089 |
res= args[0]->val_str(str); |
|
1090 |
if ((null_value=args[0]->null_value)) |
|
1091 |
return 0; |
|
1092 |
remove_str= &remove; /* Default value. */ |
|
1093 |
if (arg_count == 2) |
|
1094 |
{
|
|
1095 |
remove_str= args[1]->val_str(&tmp); |
|
1096 |
if ((null_value= args[1]->null_value)) |
|
1097 |
return 0; |
|
1098 |
}
|
|
1099 |
||
1100 |
if ((remove_length= remove_str->length()) == 0 || |
|
1101 |
remove_length > res->length()) |
|
1102 |
return res; |
|
1103 |
||
1104 |
ptr= (char*) res->ptr(); |
|
1105 |
end= ptr+res->length(); |
|
1106 |
#ifdef USE_MB
|
|
1107 |
char *p=ptr; |
|
205
by Brian Aker
uint32 -> uin32_t |
1108 |
register uint32_t l; |
1
by brian
clean slate |
1109 |
#endif
|
1110 |
if (remove_length == 1) |
|
1111 |
{
|
|
1112 |
char chr=(*remove_str)[0]; |
|
1113 |
#ifdef USE_MB
|
|
1114 |
if (use_mb(res->charset())) |
|
1115 |
{
|
|
1116 |
while (ptr < end) |
|
1117 |
{
|
|
1118 |
if ((l=my_ismbchar(res->charset(), ptr,end))) ptr+=l,p=ptr; |
|
1119 |
else ++ptr; |
|
1120 |
}
|
|
1121 |
ptr=p; |
|
1122 |
}
|
|
1123 |
#endif
|
|
1124 |
while (ptr != end && end[-1] == chr) |
|
1125 |
end--; |
|
1126 |
}
|
|
1127 |
else
|
|
1128 |
{
|
|
1129 |
const char *r_ptr=remove_str->ptr(); |
|
1130 |
#ifdef USE_MB
|
|
1131 |
if (use_mb(res->charset())) |
|
1132 |
{
|
|
1133 |
loop: |
|
1134 |
while (ptr + remove_length < end) |
|
1135 |
{
|
|
1136 |
if ((l=my_ismbchar(res->charset(), ptr,end))) ptr+=l; |
|
1137 |
else ++ptr; |
|
1138 |
}
|
|
1139 |
if (ptr + remove_length == end && !memcmp(ptr,r_ptr,remove_length)) |
|
1140 |
{
|
|
1141 |
end-=remove_length; |
|
1142 |
ptr=p; |
|
1143 |
goto loop; |
|
1144 |
}
|
|
1145 |
}
|
|
1146 |
else
|
|
1147 |
#endif /* USE_MB */ |
|
1148 |
{
|
|
1149 |
while (ptr + remove_length <= end && |
|
1150 |
!memcmp(end-remove_length, r_ptr, remove_length)) |
|
1151 |
end-=remove_length; |
|
1152 |
}
|
|
1153 |
}
|
|
1154 |
if (end == res->ptr()+res->length()) |
|
1155 |
return res; |
|
1156 |
tmp_value.set(*res,0,(uint) (end-res->ptr())); |
|
1157 |
return &tmp_value; |
|
1158 |
}
|
|
1159 |
||
1160 |
||
1161 |
String *Item_func_trim::val_str(String *str) |
|
1162 |
{
|
|
51.1.23
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
1163 |
assert(fixed == 1); |
1
by brian
clean slate |
1164 |
char buff[MAX_FIELD_WIDTH], *ptr, *end; |
1165 |
const char *r_ptr; |
|
1166 |
String tmp(buff, sizeof(buff), system_charset_info); |
|
1167 |
String *res, *remove_str; |
|
482
by Brian Aker
Remove uint. |
1168 |
uint32_t remove_length; |
1
by brian
clean slate |
1169 |
|
1170 |
res= args[0]->val_str(str); |
|
1171 |
if ((null_value=args[0]->null_value)) |
|
1172 |
return 0; |
|
1173 |
remove_str= &remove; /* Default value. */ |
|
1174 |
if (arg_count == 2) |
|
1175 |
{
|
|
1176 |
remove_str= args[1]->val_str(&tmp); |
|
1177 |
if ((null_value= args[1]->null_value)) |
|
1178 |
return 0; |
|
1179 |
}
|
|
1180 |
||
1181 |
if ((remove_length= remove_str->length()) == 0 || |
|
1182 |
remove_length > res->length()) |
|
1183 |
return res; |
|
1184 |
||
1185 |
ptr= (char*) res->ptr(); |
|
1186 |
end= ptr+res->length(); |
|
1187 |
r_ptr= remove_str->ptr(); |
|
1188 |
while (ptr+remove_length <= end && !memcmp(ptr,r_ptr,remove_length)) |
|
1189 |
ptr+=remove_length; |
|
1190 |
#ifdef USE_MB
|
|
1191 |
if (use_mb(res->charset())) |
|
1192 |
{
|
|
1193 |
char *p=ptr; |
|
205
by Brian Aker
uint32 -> uin32_t |
1194 |
register uint32_t l; |
1
by brian
clean slate |
1195 |
loop: |
1196 |
while (ptr + remove_length < end) |
|
1197 |
{
|
|
1198 |
if ((l=my_ismbchar(res->charset(), ptr,end))) ptr+=l; |
|
1199 |
else ++ptr; |
|
1200 |
}
|
|
1201 |
if (ptr + remove_length == end && !memcmp(ptr,r_ptr,remove_length)) |
|
1202 |
{
|
|
1203 |
end-=remove_length; |
|
1204 |
ptr=p; |
|
1205 |
goto loop; |
|
1206 |
}
|
|
1207 |
ptr=p; |
|
1208 |
}
|
|
1209 |
else
|
|
1210 |
#endif /* USE_MB */ |
|
1211 |
{
|
|
1212 |
while (ptr + remove_length <= end && |
|
1213 |
!memcmp(end-remove_length,r_ptr,remove_length)) |
|
1214 |
end-=remove_length; |
|
1215 |
}
|
|
1216 |
if (ptr == res->ptr() && end == ptr+res->length()) |
|
1217 |
return res; |
|
1218 |
tmp_value.set(*res,(uint) (ptr - res->ptr()),(uint) (end-ptr)); |
|
1219 |
return &tmp_value; |
|
1220 |
}
|
|
1221 |
||
1222 |
void Item_func_trim::fix_length_and_dec() |
|
1223 |
{
|
|
1224 |
max_length= args[0]->max_length; |
|
1225 |
if (arg_count == 1) |
|
1226 |
{
|
|
1227 |
collation.set(args[0]->collation); |
|
1228 |
remove.set_charset(collation.collation); |
|
1229 |
remove.set_ascii(" ",1); |
|
1230 |
}
|
|
1231 |
else
|
|
1232 |
{
|
|
1233 |
// Handle character set for args[1] and args[0].
|
|
1234 |
// Note that we pass args[1] as the first item, and args[0] as the second.
|
|
1235 |
if (agg_arg_charsets(collation, &args[1], 2, MY_COLL_CMP_CONV, -1)) |
|
1236 |
return; |
|
1237 |
}
|
|
1238 |
}
|
|
1239 |
||
1240 |
void Item_func_trim::print(String *str, enum_query_type query_type) |
|
1241 |
{
|
|
1242 |
if (arg_count == 1) |
|
1243 |
{
|
|
1244 |
Item_func::print(str, query_type); |
|
1245 |
return; |
|
1246 |
}
|
|
1247 |
str->append(Item_func_trim::func_name()); |
|
1248 |
str->append('('); |
|
1249 |
str->append(mode_name()); |
|
1250 |
str->append(' '); |
|
1251 |
args[1]->print(str, query_type); |
|
1252 |
str->append(STRING_WITH_LEN(" from ")); |
|
1253 |
args[0]->print(str, query_type); |
|
1254 |
str->append(')'); |
|
1255 |
}
|
|
1256 |
||
1257 |
||
264.2.6
by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code. |
1258 |
Item *Item_func_sysconst::safe_charset_converter(const CHARSET_INFO * const tocs) |
1
by brian
clean slate |
1259 |
{
|
1260 |
Item_string *conv; |
|
482
by Brian Aker
Remove uint. |
1261 |
uint32_t conv_errors; |
1
by brian
clean slate |
1262 |
String tmp, cstr, *ostr= val_str(&tmp); |
1263 |
cstr.copy(ostr->ptr(), ostr->length(), ostr->charset(), tocs, &conv_errors); |
|
1264 |
if (conv_errors || |
|
1265 |
!(conv= new Item_static_string_func(fully_qualified_func_name(), |
|
1266 |
cstr.ptr(), cstr.length(), |
|
1267 |
cstr.charset(), |
|
1268 |
collation.derivation))) |
|
1269 |
{
|
|
1270 |
return NULL; |
|
1271 |
}
|
|
1272 |
conv->str_value.copy(); |
|
1273 |
conv->str_value.mark_as_const(); |
|
1274 |
return conv; |
|
1275 |
}
|
|
1276 |
||
1277 |
||
1278 |
String *Item_func_database::val_str(String *str) |
|
1279 |
{
|
|
51.1.23
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
1280 |
assert(fixed == 1); |
520.1.22
by Brian Aker
Second pass of thd cleanup |
1281 |
Session *session= current_session; |
1282 |
if (session->db == NULL) |
|
1
by brian
clean slate |
1283 |
{
|
1284 |
null_value= 1; |
|
1285 |
return 0; |
|
1286 |
}
|
|
1287 |
else
|
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
1288 |
str->copy(session->db, session->db_length, system_charset_info); |
1
by brian
clean slate |
1289 |
return str; |
1290 |
}
|
|
1291 |
||
1292 |
||
1293 |
/**
|
|
1294 |
@todo
|
|
1295 |
make USER() replicate properly (currently it is replicated to "")
|
|
1296 |
*/
|
|
1297 |
bool Item_func_user::init(const char *user, const char *host) |
|
1298 |
{
|
|
51.1.23
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
1299 |
assert(fixed == 1); |
1
by brian
clean slate |
1300 |
|
1301 |
// For system threads (e.g. replication SQL thread) user may be empty
|
|
1302 |
if (user) |
|
1303 |
{
|
|
264.2.6
by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code. |
1304 |
const CHARSET_INFO * const cs= str_value.charset(); |
482
by Brian Aker
Remove uint. |
1305 |
uint32_t res_length= (strlen(user)+strlen(host)+2) * cs->mbmaxlen; |
1
by brian
clean slate |
1306 |
|
1307 |
if (str_value.alloc(res_length)) |
|
1308 |
{
|
|
1309 |
null_value=1; |
|
51.1.23
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
1310 |
return true; |
1
by brian
clean slate |
1311 |
}
|
1312 |
||
1313 |
res_length=cs->cset->snprintf(cs, (char*)str_value.ptr(), res_length, |
|
1314 |
"%s@%s", user, host); |
|
1315 |
str_value.length(res_length); |
|
1316 |
str_value.mark_as_const(); |
|
1317 |
}
|
|
51.1.23
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
1318 |
return false; |
1
by brian
clean slate |
1319 |
}
|
1320 |
||
1321 |
||
520.1.22
by Brian Aker
Second pass of thd cleanup |
1322 |
bool Item_func_user::fix_fields(Session *session, Item **ref) |
1
by brian
clean slate |
1323 |
{
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
1324 |
return (Item_func_sysconst::fix_fields(session, ref) || |
1325 |
init(session->main_security_ctx.user, |
|
1326 |
session->main_security_ctx.ip)); |
|
1
by brian
clean slate |
1327 |
}
|
1328 |
||
1329 |
||
520.1.22
by Brian Aker
Second pass of thd cleanup |
1330 |
bool Item_func_current_user::fix_fields(Session *session, Item **ref) |
1
by brian
clean slate |
1331 |
{
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
1332 |
if (Item_func_sysconst::fix_fields(session, ref)) |
51.1.23
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
1333 |
return true; |
1
by brian
clean slate |
1334 |
|
1335 |
Security_context *ctx= |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
1336 |
session->security_ctx; |
265
by brian
First pass through cleaning up security context. |
1337 |
return init(ctx->user, ctx->ip); |
1
by brian
clean slate |
1338 |
}
|
1339 |
||
1340 |
||
1341 |
/**
|
|
1342 |
Change a number to format '3,333,333,333.000'.
|
|
1343 |
||
1344 |
This should be 'internationalized' sometimes.
|
|
1345 |
*/
|
|
1346 |
||
1347 |
const int FORMAT_MAX_DECIMALS= 30; |
|
1348 |
||
1349 |
Item_func_format::Item_func_format(Item *org, Item *dec) |
|
1350 |
: Item_str_func(org, dec) |
|
1351 |
{
|
|
1352 |
}
|
|
1353 |
||
1354 |
void Item_func_format::fix_length_and_dec() |
|
1355 |
{
|
|
1356 |
collation.set(default_charset()); |
|
482
by Brian Aker
Remove uint. |
1357 |
uint32_t char_length= args[0]->max_length/args[0]->collation.collation->mbmaxlen; |
1
by brian
clean slate |
1358 |
max_length= ((char_length + (char_length-args[0]->decimals)/3) * |
1359 |
collation.collation->mbmaxlen); |
|
1360 |
}
|
|
1361 |
||
1362 |
||
1363 |
/**
|
|
1364 |
@todo
|
|
1365 |
This needs to be fixed for multi-byte character set where numbers
|
|
1366 |
are stored in more than one byte
|
|
1367 |
*/
|
|
1368 |
||
1369 |
String *Item_func_format::val_str(String *str) |
|
1370 |
{
|
|
205
by Brian Aker
uint32 -> uin32_t |
1371 |
uint32_t length; |
1372 |
uint32_t str_length; |
|
1
by brian
clean slate |
1373 |
/* Number of decimal digits */
|
1374 |
int dec; |
|
1375 |
/* Number of characters used to represent the decimals, including '.' */
|
|
205
by Brian Aker
uint32 -> uin32_t |
1376 |
uint32_t dec_length; |
1
by brian
clean slate |
1377 |
int diff; |
51.1.23
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
1378 |
assert(fixed == 1); |
1
by brian
clean slate |
1379 |
|
1380 |
dec= (int) args[1]->val_int(); |
|
1381 |
if (args[1]->null_value) |
|
1382 |
{
|
|
1383 |
null_value=1; |
|
1384 |
return NULL; |
|
1385 |
}
|
|
1386 |
||
1387 |
dec= set_zone(dec, 0, FORMAT_MAX_DECIMALS); |
|
1388 |
dec_length= dec ? dec+1 : 0; |
|
1389 |
null_value=0; |
|
1390 |
||
1391 |
if (args[0]->result_type() == DECIMAL_RESULT || |
|
1392 |
args[0]->result_type() == INT_RESULT) |
|
1393 |
{
|
|
1394 |
my_decimal dec_val, rnd_dec, *res; |
|
1395 |
res= args[0]->val_decimal(&dec_val); |
|
1396 |
if ((null_value=args[0]->null_value)) |
|
1397 |
return 0; /* purecov: inspected */ |
|
1398 |
my_decimal_round(E_DEC_FATAL_ERROR, res, dec, false, &rnd_dec); |
|
1399 |
my_decimal2string(E_DEC_FATAL_ERROR, &rnd_dec, 0, 0, 0, str); |
|
1400 |
str_length= str->length(); |
|
1401 |
if (rnd_dec.sign()) |
|
1402 |
str_length--; |
|
1403 |
}
|
|
1404 |
else
|
|
1405 |
{
|
|
1406 |
double nr= args[0]->val_real(); |
|
1407 |
if ((null_value=args[0]->null_value)) |
|
1408 |
return 0; /* purecov: inspected */ |
|
152
by Brian Aker
longlong replacement |
1409 |
nr= my_double_round(nr, (int64_t) dec, false, false); |
1
by brian
clean slate |
1410 |
/* Here default_charset() is right as this is not an automatic conversion */
|
1411 |
str->set_real(nr, dec, default_charset()); |
|
492.3.25
by Lee
Changes to get drizzle building on Solaris 10 (SPARC) |
1412 |
if (isnan(nr)) |
1
by brian
clean slate |
1413 |
return str; |
1414 |
str_length=str->length(); |
|
1415 |
if (nr < 0) |
|
1416 |
str_length--; // Don't count sign |
|
1417 |
}
|
|
1418 |
/* We need this test to handle 'nan' values */
|
|
1419 |
if (str_length >= dec_length+4) |
|
1420 |
{
|
|
1421 |
char *tmp,*pos; |
|
1422 |
length= str->length()+(diff=((int)(str_length- dec_length-1))/3); |
|
1423 |
str= copy_if_not_alloced(&tmp_str,str,length); |
|
1424 |
str->length(length); |
|
1425 |
tmp= (char*) str->ptr()+length - dec_length-1; |
|
1426 |
for (pos= (char*) str->ptr()+length-1; pos != tmp; pos--) |
|
1427 |
pos[0]= pos[-diff]; |
|
1428 |
while (diff) |
|
1429 |
{
|
|
1430 |
*pos= *(pos - diff); |
|
1431 |
pos--; |
|
1432 |
*pos= *(pos - diff); |
|
1433 |
pos--; |
|
1434 |
*pos= *(pos - diff); |
|
1435 |
pos--; |
|
1436 |
pos[0]=','; |
|
1437 |
pos--; |
|
1438 |
diff--; |
|
1439 |
}
|
|
1440 |
}
|
|
1441 |
return str; |
|
1442 |
}
|
|
1443 |
||
1444 |
||
1445 |
void Item_func_format::print(String *str, enum_query_type query_type) |
|
1446 |
{
|
|
1447 |
str->append(STRING_WITH_LEN("format(")); |
|
1448 |
args[0]->print(str, query_type); |
|
1449 |
str->append(','); |
|
1450 |
args[1]->print(str, query_type); |
|
1451 |
str->append(')'); |
|
1452 |
}
|
|
1453 |
||
1454 |
void Item_func_elt::fix_length_and_dec() |
|
1455 |
{
|
|
1456 |
max_length=0; |
|
1457 |
decimals=0; |
|
1458 |
||
1459 |
if (agg_arg_charsets(collation, args+1, arg_count-1, MY_COLL_ALLOW_CONV, 1)) |
|
1460 |
return; |
|
1461 |
||
482
by Brian Aker
Remove uint. |
1462 |
for (uint32_t i= 1 ; i < arg_count ; i++) |
1
by brian
clean slate |
1463 |
{
|
1464 |
set_if_bigger(max_length,args[i]->max_length); |
|
1465 |
set_if_bigger(decimals,args[i]->decimals); |
|
1466 |
}
|
|
1467 |
maybe_null=1; // NULL if wrong first arg |
|
1468 |
}
|
|
1469 |
||
1470 |
||
1471 |
double Item_func_elt::val_real() |
|
1472 |
{
|
|
51.1.23
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
1473 |
assert(fixed == 1); |
482
by Brian Aker
Remove uint. |
1474 |
uint32_t tmp; |
1
by brian
clean slate |
1475 |
null_value=1; |
1476 |
if ((tmp=(uint) args[0]->val_int()) == 0 || tmp >= arg_count) |
|
1477 |
return 0.0; |
|
1478 |
double result= args[tmp]->val_real(); |
|
1479 |
null_value= args[tmp]->null_value; |
|
1480 |
return result; |
|
1481 |
}
|
|
1482 |
||
1483 |
||
152
by Brian Aker
longlong replacement |
1484 |
int64_t Item_func_elt::val_int() |
1
by brian
clean slate |
1485 |
{
|
51.1.23
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
1486 |
assert(fixed == 1); |
482
by Brian Aker
Remove uint. |
1487 |
uint32_t tmp; |
1
by brian
clean slate |
1488 |
null_value=1; |
1489 |
if ((tmp=(uint) args[0]->val_int()) == 0 || tmp >= arg_count) |
|
1490 |
return 0; |
|
1491 |
||
152
by Brian Aker
longlong replacement |
1492 |
int64_t result= args[tmp]->val_int(); |
1
by brian
clean slate |
1493 |
null_value= args[tmp]->null_value; |
1494 |
return result; |
|
1495 |
}
|
|
1496 |
||
1497 |
||
1498 |
String *Item_func_elt::val_str(String *str) |
|
1499 |
{
|
|
51.1.23
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
1500 |
assert(fixed == 1); |
482
by Brian Aker
Remove uint. |
1501 |
uint32_t tmp; |
1
by brian
clean slate |
1502 |
null_value=1; |
1503 |
if ((tmp=(uint) args[0]->val_int()) == 0 || tmp >= arg_count) |
|
1504 |
return NULL; |
|
1505 |
||
1506 |
String *result= args[tmp]->val_str(str); |
|
1507 |
if (result) |
|
1508 |
result->set_charset(collation.collation); |
|
1509 |
null_value= args[tmp]->null_value; |
|
1510 |
return result; |
|
1511 |
}
|
|
1512 |
||
1513 |
||
520.1.22
by Brian Aker
Second pass of thd cleanup |
1514 |
void Item_func_make_set::split_sum_func(Session *session, Item **ref_pointer_array, |
1
by brian
clean slate |
1515 |
List<Item> &fields) |
1516 |
{
|
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
1517 |
item->split_sum_func2(session, ref_pointer_array, fields, &item, true); |
1518 |
Item_str_func::split_sum_func(session, ref_pointer_array, fields); |
|
1
by brian
clean slate |
1519 |
}
|
1520 |
||
1521 |
||
1522 |
void Item_func_make_set::fix_length_and_dec() |
|
1523 |
{
|
|
1524 |
max_length=arg_count-1; |
|
1525 |
||
1526 |
if (agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV, 1)) |
|
1527 |
return; |
|
1528 |
||
482
by Brian Aker
Remove uint. |
1529 |
for (uint32_t i=0 ; i < arg_count ; i++) |
1
by brian
clean slate |
1530 |
max_length+=args[i]->max_length; |
1531 |
||
1532 |
used_tables_cache|= item->used_tables(); |
|
1533 |
not_null_tables_cache&= item->not_null_tables(); |
|
1534 |
const_item_cache&= item->const_item(); |
|
1535 |
with_sum_func= with_sum_func || item->with_sum_func; |
|
1536 |
}
|
|
1537 |
||
1538 |
||
1539 |
void Item_func_make_set::update_used_tables() |
|
1540 |
{
|
|
1541 |
Item_func::update_used_tables(); |
|
1542 |
item->update_used_tables(); |
|
1543 |
used_tables_cache|=item->used_tables(); |
|
1544 |
const_item_cache&=item->const_item(); |
|
1545 |
}
|
|
1546 |
||
1547 |
||
1548 |
String *Item_func_make_set::val_str(String *str) |
|
1549 |
{
|
|
51.1.23
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
1550 |
assert(fixed == 1); |
151
by Brian Aker
Ulonglong to uint64_t |
1551 |
uint64_t bits; |
1
by brian
clean slate |
1552 |
bool first_found=0; |
1553 |
Item **ptr=args; |
|
1554 |
String *result=&my_empty_string; |
|
1555 |
||
1556 |
bits=item->val_int(); |
|
1557 |
if ((null_value=item->null_value)) |
|
1558 |
return NULL; |
|
1559 |
||
1560 |
if (arg_count < 64) |
|
151
by Brian Aker
Ulonglong to uint64_t |
1561 |
bits &= ((uint64_t) 1 << arg_count)-1; |
1
by brian
clean slate |
1562 |
|
1563 |
for (; bits; bits >>= 1, ptr++) |
|
1564 |
{
|
|
1565 |
if (bits & 1) |
|
1566 |
{
|
|
1567 |
String *res= (*ptr)->val_str(str); |
|
1568 |
if (res) // Skip nulls |
|
1569 |
{
|
|
1570 |
if (!first_found) |
|
1571 |
{ // First argument |
|
1572 |
first_found=1; |
|
1573 |
if (res != str) |
|
1574 |
result=res; // Use original string |
|
1575 |
else
|
|
1576 |
{
|
|
1577 |
if (tmp_str.copy(*res)) // Don't use 'str' |
|
1578 |
return &my_empty_string; |
|
1579 |
result= &tmp_str; |
|
1580 |
}
|
|
1581 |
}
|
|
1582 |
else
|
|
1583 |
{
|
|
1584 |
if (result != &tmp_str) |
|
1585 |
{ // Copy data to tmp_str |
|
1586 |
if (tmp_str.alloc(result->length()+res->length()+1) || |
|
1587 |
tmp_str.copy(*result)) |
|
1588 |
return &my_empty_string; |
|
1589 |
result= &tmp_str; |
|
1590 |
}
|
|
1591 |
if (tmp_str.append(STRING_WITH_LEN(","), &my_charset_bin) || tmp_str.append(*res)) |
|
1592 |
return &my_empty_string; |
|
1593 |
}
|
|
1594 |
}
|
|
1595 |
}
|
|
1596 |
}
|
|
1597 |
return result; |
|
1598 |
}
|
|
1599 |
||
1600 |
||
481
by Brian Aker
Remove all of uchar. |
1601 |
Item *Item_func_make_set::transform(Item_transformer transformer, unsigned char *arg) |
1
by brian
clean slate |
1602 |
{
|
1603 |
Item *new_item= item->transform(transformer, arg); |
|
1604 |
if (!new_item) |
|
1605 |
return 0; |
|
1606 |
||
1607 |
/*
|
|
520.1.21
by Brian Aker
THD -> Session rename |
1608 |
Session::change_item_tree() should be called only if the tree was
|
1
by brian
clean slate |
1609 |
really transformed, i.e. when a new item has been created.
|
1610 |
Otherwise we'll be allocating a lot of unnecessary memory for
|
|
1611 |
change records at each execution.
|
|
1612 |
*/
|
|
1613 |
if (item != new_item) |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
1614 |
current_session->change_item_tree(&item, new_item); |
1
by brian
clean slate |
1615 |
return Item_str_func::transform(transformer, arg); |
1616 |
}
|
|
1617 |
||
1618 |
||
1619 |
void Item_func_make_set::print(String *str, enum_query_type query_type) |
|
1620 |
{
|
|
1621 |
str->append(STRING_WITH_LEN("make_set(")); |
|
1622 |
item->print(str, query_type); |
|
1623 |
if (arg_count) |
|
1624 |
{
|
|
1625 |
str->append(','); |
|
1626 |
print_args(str, 0, query_type); |
|
1627 |
}
|
|
1628 |
str->append(')'); |
|
1629 |
}
|
|
1630 |
||
1631 |
||
1632 |
String *Item_func_char::val_str(String *str) |
|
1633 |
{
|
|
51.1.23
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
1634 |
assert(fixed == 1); |
1
by brian
clean slate |
1635 |
str->length(0); |
1636 |
str->set_charset(collation.collation); |
|
482
by Brian Aker
Remove uint. |
1637 |
for (uint32_t i=0 ; i < arg_count ; i++) |
1
by brian
clean slate |
1638 |
{
|
205
by Brian Aker
uint32 -> uin32_t |
1639 |
int32_t num=(int32_t) args[i]->val_int(); |
1
by brian
clean slate |
1640 |
if (!args[i]->null_value) |
1641 |
{
|
|
1642 |
char char_num= (char) num; |
|
1643 |
if (num&0xFF000000L) { |
|
1644 |
str->append((char)(num>>24)); |
|
1645 |
goto b2; |
|
1646 |
} else if (num&0xFF0000L) { |
|
1647 |
b2: str->append((char)(num>>16)); |
|
1648 |
goto b1; |
|
1649 |
} else if (num&0xFF00L) { |
|
1650 |
b1: str->append((char)(num>>8)); |
|
1651 |
}
|
|
1652 |
str->append(&char_num, 1); |
|
1653 |
}
|
|
1654 |
}
|
|
1655 |
str->realloc(str->length()); // Add end 0 (for Purify) |
|
1656 |
return check_well_formed_result(str); |
|
1657 |
}
|
|
1658 |
||
1659 |
||
1660 |
inline String* alloc_buffer(String *res,String *str,String *tmp_value, |
|
1661 |
ulong length) |
|
1662 |
{
|
|
1663 |
if (res->alloced_length() < length) |
|
1664 |
{
|
|
1665 |
if (str->alloced_length() >= length) |
|
1666 |
{
|
|
1667 |
(void) str->copy(*res); |
|
1668 |
str->length(length); |
|
1669 |
return str; |
|
1670 |
}
|
|
1671 |
if (tmp_value->alloc(length)) |
|
1672 |
return 0; |
|
1673 |
(void) tmp_value->copy(*res); |
|
1674 |
tmp_value->length(length); |
|
1675 |
return tmp_value; |
|
1676 |
}
|
|
1677 |
res->length(length); |
|
1678 |
return res; |
|
1679 |
}
|
|
1680 |
||
1681 |
||
1682 |
void Item_func_repeat::fix_length_and_dec() |
|
1683 |
{
|
|
1684 |
collation.set(args[0]->collation); |
|
1685 |
if (args[1]->const_item()) |
|
1686 |
{
|
|
152
by Brian Aker
longlong replacement |
1687 |
/* must be int64_t to avoid truncation */
|
1688 |
int64_t count= args[1]->val_int(); |
|
1
by brian
clean slate |
1689 |
|
163
by Brian Aker
Merge Monty's code. |
1690 |
/* Assumes that the maximum length of a String is < INT32_MAX. */
|
1
by brian
clean slate |
1691 |
/* Set here so that rest of code sees out-of-bound value as such. */
|
163
by Brian Aker
Merge Monty's code. |
1692 |
if (count > INT32_MAX) |
1693 |
count= INT32_MAX; |
|
1
by brian
clean slate |
1694 |
|
151
by Brian Aker
Ulonglong to uint64_t |
1695 |
uint64_t max_result_length= (uint64_t) args[0]->max_length * count; |
1
by brian
clean slate |
1696 |
if (max_result_length >= MAX_BLOB_WIDTH) |
1697 |
{
|
|
1698 |
max_result_length= MAX_BLOB_WIDTH; |
|
1699 |
maybe_null= 1; |
|
1700 |
}
|
|
1701 |
max_length= (ulong) max_result_length; |
|
1702 |
}
|
|
1703 |
else
|
|
1704 |
{
|
|
1705 |
max_length= MAX_BLOB_WIDTH; |
|
1706 |
maybe_null= 1; |
|
1707 |
}
|
|
1708 |
}
|
|
1709 |
||
1710 |
/**
|
|
1711 |
Item_func_repeat::str is carefully written to avoid reallocs
|
|
1712 |
as much as possible at the cost of a local buffer
|
|
1713 |
*/
|
|
1714 |
||
1715 |
String *Item_func_repeat::val_str(String *str) |
|
1716 |
{
|
|
51.1.23
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
1717 |
assert(fixed == 1); |
482
by Brian Aker
Remove uint. |
1718 |
uint32_t length,tot_length; |
1
by brian
clean slate |
1719 |
char *to; |
152
by Brian Aker
longlong replacement |
1720 |
/* must be int64_t to avoid truncation */
|
1721 |
int64_t count= args[1]->val_int(); |
|
1
by brian
clean slate |
1722 |
String *res= args[0]->val_str(str); |
1723 |
||
1724 |
if (args[0]->null_value || args[1]->null_value) |
|
1725 |
goto err; // string and/or delim are null |
|
1726 |
null_value= 0; |
|
1727 |
||
1728 |
if (count <= 0 && (count == 0 || !args[1]->unsigned_flag)) |
|
1729 |
return &my_empty_string; |
|
1730 |
||
163
by Brian Aker
Merge Monty's code. |
1731 |
/* Assumes that the maximum length of a String is < INT32_MAX. */
|
1
by brian
clean slate |
1732 |
/* Bounds check on count: If this is triggered, we will error. */
|
163
by Brian Aker
Merge Monty's code. |
1733 |
if ((uint64_t) count > INT32_MAX) |
1734 |
count= INT32_MAX; |
|
1
by brian
clean slate |
1735 |
if (count == 1) // To avoid reallocs |
1736 |
return res; |
|
1737 |
length=res->length(); |
|
1738 |
// Safe length check
|
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
1739 |
if (length > current_session->variables.max_allowed_packet / (uint) count) |
1
by brian
clean slate |
1740 |
{
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
1741 |
push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN, |
1
by brian
clean slate |
1742 |
ER_WARN_ALLOWED_PACKET_OVERFLOWED, |
1743 |
ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED), |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
1744 |
func_name(), current_session->variables.max_allowed_packet); |
1
by brian
clean slate |
1745 |
goto err; |
1746 |
}
|
|
1747 |
tot_length= length*(uint) count; |
|
1748 |
if (!(res= alloc_buffer(res,str,&tmp_value,tot_length))) |
|
1749 |
goto err; |
|
1750 |
||
1751 |
to=(char*) res->ptr()+length; |
|
1752 |
while (--count) |
|
1753 |
{
|
|
1754 |
memcpy(to,res->ptr(),length); |
|
1755 |
to+=length; |
|
1756 |
}
|
|
1757 |
return (res); |
|
1758 |
||
1759 |
err: |
|
1760 |
null_value=1; |
|
1761 |
return 0; |
|
1762 |
}
|
|
1763 |
||
1764 |
||
1765 |
void Item_func_rpad::fix_length_and_dec() |
|
1766 |
{
|
|
1767 |
// Handle character set for args[0] and args[2].
|
|
1768 |
if (agg_arg_charsets(collation, &args[0], 2, MY_COLL_ALLOW_CONV, 2)) |
|
1769 |
return; |
|
1770 |
if (args[1]->const_item()) |
|
1771 |
{
|
|
151
by Brian Aker
Ulonglong to uint64_t |
1772 |
uint64_t length= 0; |
1
by brian
clean slate |
1773 |
|
1774 |
if (collation.collation->mbmaxlen > 0) |
|
1775 |
{
|
|
151
by Brian Aker
Ulonglong to uint64_t |
1776 |
uint64_t temp= (uint64_t) args[1]->val_int(); |
1
by brian
clean slate |
1777 |
|
163
by Brian Aker
Merge Monty's code. |
1778 |
/* Assumes that the maximum length of a String is < INT32_MAX. */
|
1
by brian
clean slate |
1779 |
/* Set here so that rest of code sees out-of-bound value as such. */
|
163
by Brian Aker
Merge Monty's code. |
1780 |
if (temp > INT32_MAX) |
1781 |
temp = INT32_MAX; |
|
1
by brian
clean slate |
1782 |
|
1783 |
length= temp * collation.collation->mbmaxlen; |
|
1784 |
}
|
|
1785 |
||
1786 |
if (length >= MAX_BLOB_WIDTH) |
|
1787 |
{
|
|
1788 |
length= MAX_BLOB_WIDTH; |
|
1789 |
maybe_null= 1; |
|
1790 |
}
|
|
1791 |
max_length= (ulong) length; |
|
1792 |
}
|
|
1793 |
else
|
|
1794 |
{
|
|
1795 |
max_length= MAX_BLOB_WIDTH; |
|
1796 |
maybe_null= 1; |
|
1797 |
}
|
|
1798 |
}
|
|
1799 |
||
1800 |
||
1801 |
String *Item_func_rpad::val_str(String *str) |
|
1802 |
{
|
|
51.1.23
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
1803 |
assert(fixed == 1); |
205
by Brian Aker
uint32 -> uin32_t |
1804 |
uint32_t res_byte_length,res_char_length,pad_char_length,pad_byte_length; |
1
by brian
clean slate |
1805 |
char *to; |
1806 |
const char *ptr_pad; |
|
152
by Brian Aker
longlong replacement |
1807 |
/* must be int64_t to avoid truncation */
|
1808 |
int64_t count= args[1]->val_int(); |
|
1809 |
int64_t byte_count; |
|
1
by brian
clean slate |
1810 |
String *res= args[0]->val_str(str); |
1811 |
String *rpad= args[2]->val_str(&rpad_str); |
|
1812 |
||
1813 |
if (!res || args[1]->null_value || !rpad || |
|
1814 |
((count < 0) && !args[1]->unsigned_flag)) |
|
1815 |
goto err; |
|
1816 |
null_value=0; |
|
163
by Brian Aker
Merge Monty's code. |
1817 |
/* Assumes that the maximum length of a String is < INT32_MAX. */
|
1
by brian
clean slate |
1818 |
/* Set here so that rest of code sees out-of-bound value as such. */
|
163
by Brian Aker
Merge Monty's code. |
1819 |
if ((uint64_t) count > INT32_MAX) |
1820 |
count= INT32_MAX; |
|
1
by brian
clean slate |
1821 |
if (count <= (res_char_length= res->numchars())) |
1822 |
{ // String to pad is big enough |
|
1823 |
res->length(res->charpos((int) count)); // Shorten result if longer |
|
1824 |
return (res); |
|
1825 |
}
|
|
1826 |
pad_char_length= rpad->numchars(); |
|
1827 |
||
1828 |
byte_count= count * collation.collation->mbmaxlen; |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
1829 |
if ((uint64_t) byte_count > current_session->variables.max_allowed_packet) |
1
by brian
clean slate |
1830 |
{
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
1831 |
push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN, |
1
by brian
clean slate |
1832 |
ER_WARN_ALLOWED_PACKET_OVERFLOWED, |
1833 |
ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED), |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
1834 |
func_name(), current_session->variables.max_allowed_packet); |
1
by brian
clean slate |
1835 |
goto err; |
1836 |
}
|
|
1837 |
if (args[2]->null_value || !pad_char_length) |
|
1838 |
goto err; |
|
1839 |
res_byte_length= res->length(); /* Must be done before alloc_buffer */ |
|
1840 |
if (!(res= alloc_buffer(res,str,&tmp_value, (ulong) byte_count))) |
|
1841 |
goto err; |
|
1842 |
||
1843 |
to= (char*) res->ptr()+res_byte_length; |
|
1844 |
ptr_pad=rpad->ptr(); |
|
1845 |
pad_byte_length= rpad->length(); |
|
1846 |
count-= res_char_length; |
|
205
by Brian Aker
uint32 -> uin32_t |
1847 |
for ( ; (uint32_t) count > pad_char_length; count-= pad_char_length) |
1
by brian
clean slate |
1848 |
{
|
1849 |
memcpy(to,ptr_pad,pad_byte_length); |
|
1850 |
to+= pad_byte_length; |
|
1851 |
}
|
|
1852 |
if (count) |
|
1853 |
{
|
|
1854 |
pad_byte_length= rpad->charpos((int) count); |
|
1855 |
memcpy(to,ptr_pad,(size_t) pad_byte_length); |
|
1856 |
to+= pad_byte_length; |
|
1857 |
}
|
|
1858 |
res->length(to- (char*) res->ptr()); |
|
1859 |
return (res); |
|
1860 |
||
1861 |
err: |
|
1862 |
null_value=1; |
|
1863 |
return 0; |
|
1864 |
}
|
|
1865 |
||
1866 |
||
1867 |
void Item_func_lpad::fix_length_and_dec() |
|
1868 |
{
|
|
1869 |
// Handle character set for args[0] and args[2].
|
|
1870 |
if (agg_arg_charsets(collation, &args[0], 2, MY_COLL_ALLOW_CONV, 2)) |
|
1871 |
return; |
|
1872 |
||
1873 |
if (args[1]->const_item()) |
|
1874 |
{
|
|
151
by Brian Aker
Ulonglong to uint64_t |
1875 |
uint64_t length= 0; |
1
by brian
clean slate |
1876 |
|
1877 |
if (collation.collation->mbmaxlen > 0) |
|
1878 |
{
|
|
151
by Brian Aker
Ulonglong to uint64_t |
1879 |
uint64_t temp= (uint64_t) args[1]->val_int(); |
1
by brian
clean slate |
1880 |
|
163
by Brian Aker
Merge Monty's code. |
1881 |
/* Assumes that the maximum length of a String is < INT32_MAX. */
|
1
by brian
clean slate |
1882 |
/* Set here so that rest of code sees out-of-bound value as such. */
|
163
by Brian Aker
Merge Monty's code. |
1883 |
if (temp > INT32_MAX) |
1884 |
temp= INT32_MAX; |
|
1
by brian
clean slate |
1885 |
|
1886 |
length= temp * collation.collation->mbmaxlen; |
|
1887 |
}
|
|
1888 |
||
1889 |
if (length >= MAX_BLOB_WIDTH) |
|
1890 |
{
|
|
1891 |
length= MAX_BLOB_WIDTH; |
|
1892 |
maybe_null= 1; |
|
1893 |
}
|
|
1894 |
max_length= (ulong) length; |
|
1895 |
}
|
|
1896 |
else
|
|
1897 |
{
|
|
1898 |
max_length= MAX_BLOB_WIDTH; |
|
1899 |
maybe_null= 1; |
|
1900 |
}
|
|
1901 |
}
|
|
1902 |
||
1903 |
||
1904 |
String *Item_func_lpad::val_str(String *str) |
|
1905 |
{
|
|
51.1.23
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
1906 |
assert(fixed == 1); |
205
by Brian Aker
uint32 -> uin32_t |
1907 |
uint32_t res_char_length,pad_char_length; |
152
by Brian Aker
longlong replacement |
1908 |
/* must be int64_t to avoid truncation */
|
1909 |
int64_t count= args[1]->val_int(); |
|
1910 |
int64_t byte_count; |
|
1
by brian
clean slate |
1911 |
String *res= args[0]->val_str(&tmp_value); |
1912 |
String *pad= args[2]->val_str(&lpad_str); |
|
1913 |
||
1914 |
if (!res || args[1]->null_value || !pad || |
|
1915 |
((count < 0) && !args[1]->unsigned_flag)) |
|
1916 |
goto err; |
|
1917 |
null_value=0; |
|
163
by Brian Aker
Merge Monty's code. |
1918 |
/* Assumes that the maximum length of a String is < INT32_MAX. */
|
1
by brian
clean slate |
1919 |
/* Set here so that rest of code sees out-of-bound value as such. */
|
163
by Brian Aker
Merge Monty's code. |
1920 |
if ((uint64_t) count > INT32_MAX) |
1921 |
count= INT32_MAX; |
|
1
by brian
clean slate |
1922 |
|
1923 |
res_char_length= res->numchars(); |
|
1924 |
||
1925 |
if (count <= res_char_length) |
|
1926 |
{
|
|
1927 |
res->length(res->charpos((int) count)); |
|
1928 |
return res; |
|
1929 |
}
|
|
1930 |
||
1931 |
pad_char_length= pad->numchars(); |
|
1932 |
byte_count= count * collation.collation->mbmaxlen; |
|
1933 |
||
520.1.22
by Brian Aker
Second pass of thd cleanup |
1934 |
if ((uint64_t) byte_count > current_session->variables.max_allowed_packet) |
1
by brian
clean slate |
1935 |
{
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
1936 |
push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN, |
1
by brian
clean slate |
1937 |
ER_WARN_ALLOWED_PACKET_OVERFLOWED, |
1938 |
ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED), |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
1939 |
func_name(), current_session->variables.max_allowed_packet); |
1
by brian
clean slate |
1940 |
goto err; |
1941 |
}
|
|
1942 |
||
1943 |
if (args[2]->null_value || !pad_char_length || |
|
205
by Brian Aker
uint32 -> uin32_t |
1944 |
str->alloc((uint32_t) byte_count)) |
1
by brian
clean slate |
1945 |
goto err; |
1946 |
||
1947 |
str->length(0); |
|
1948 |
str->set_charset(collation.collation); |
|
1949 |
count-= res_char_length; |
|
1950 |
while (count >= pad_char_length) |
|
1951 |
{
|
|
1952 |
str->append(*pad); |
|
1953 |
count-= pad_char_length; |
|
1954 |
}
|
|
1955 |
if (count > 0) |
|
1956 |
str->append(pad->ptr(), pad->charpos((int) count), collation.collation); |
|
1957 |
||
1958 |
str->append(*res); |
|
1959 |
null_value= 0; |
|
1960 |
return str; |
|
1961 |
||
1962 |
err: |
|
1963 |
null_value= 1; |
|
1964 |
return 0; |
|
1965 |
}
|
|
1966 |
||
1967 |
||
1968 |
String *Item_func_conv::val_str(String *str) |
|
1969 |
{
|
|
51.1.23
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
1970 |
assert(fixed == 1); |
1
by brian
clean slate |
1971 |
String *res= args[0]->val_str(str); |
1972 |
char *endptr,ans[65],*ptr; |
|
152
by Brian Aker
longlong replacement |
1973 |
int64_t dec; |
1
by brian
clean slate |
1974 |
int from_base= (int) args[1]->val_int(); |
1975 |
int to_base= (int) args[2]->val_int(); |
|
1976 |
int err; |
|
1977 |
||
1978 |
if (args[0]->null_value || args[1]->null_value || args[2]->null_value || |
|
1979 |
abs(to_base) > 36 || abs(to_base) < 2 || |
|
1980 |
abs(from_base) > 36 || abs(from_base) < 2 || !(res->length())) |
|
1981 |
{
|
|
1982 |
null_value= 1; |
|
1983 |
return NULL; |
|
1984 |
}
|
|
1985 |
null_value= 0; |
|
1986 |
unsigned_flag= !(from_base < 0); |
|
1987 |
||
62
by Brian Aker
First pass of removing BIT_TYPE |
1988 |
if (from_base < 0) |
1989 |
dec= my_strntoll(res->charset(), res->ptr(), res->length(), |
|
1990 |
-from_base, &endptr, &err); |
|
1
by brian
clean slate |
1991 |
else
|
152
by Brian Aker
longlong replacement |
1992 |
dec= (int64_t) my_strntoull(res->charset(), res->ptr(), res->length(), |
62
by Brian Aker
First pass of removing BIT_TYPE |
1993 |
from_base, &endptr, &err); |
1
by brian
clean slate |
1994 |
|
152
by Brian Aker
longlong replacement |
1995 |
ptr= int64_t2str(dec, ans, to_base); |
205
by Brian Aker
uint32 -> uin32_t |
1996 |
if (str->copy(ans, (uint32_t) (ptr-ans), default_charset())) |
1
by brian
clean slate |
1997 |
return &my_empty_string; |
1998 |
return str; |
|
1999 |
}
|
|
2000 |
||
2001 |
||
2002 |
String *Item_func_conv_charset::val_str(String *str) |
|
2003 |
{
|
|
51.1.23
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
2004 |
assert(fixed == 1); |
1
by brian
clean slate |
2005 |
if (use_cached_value) |
2006 |
return null_value ? 0 : &str_value; |
|
2007 |
String *arg= args[0]->val_str(str); |
|
482
by Brian Aker
Remove uint. |
2008 |
uint32_t dummy_errors; |
1
by brian
clean slate |
2009 |
if (!arg) |
2010 |
{
|
|
2011 |
null_value=1; |
|
2012 |
return 0; |
|
2013 |
}
|
|
2014 |
null_value= str_value.copy(arg->ptr(),arg->length(),arg->charset(), |
|
2015 |
conv_charset, &dummy_errors); |
|
2016 |
return null_value ? 0 : check_well_formed_result(&str_value); |
|
2017 |
}
|
|
2018 |
||
2019 |
void Item_func_conv_charset::fix_length_and_dec() |
|
2020 |
{
|
|
2021 |
collation.set(conv_charset, DERIVATION_IMPLICIT); |
|
2022 |
max_length = args[0]->max_length*conv_charset->mbmaxlen; |
|
2023 |
}
|
|
2024 |
||
2025 |
void Item_func_conv_charset::print(String *str, enum_query_type query_type) |
|
2026 |
{
|
|
2027 |
str->append(STRING_WITH_LEN("convert(")); |
|
2028 |
args[0]->print(str, query_type); |
|
2029 |
str->append(STRING_WITH_LEN(" using ")); |
|
2030 |
str->append(conv_charset->csname); |
|
2031 |
str->append(')'); |
|
2032 |
}
|
|
2033 |
||
2034 |
String *Item_func_set_collation::val_str(String *str) |
|
2035 |
{
|
|
51.1.23
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
2036 |
assert(fixed == 1); |
1
by brian
clean slate |
2037 |
str=args[0]->val_str(str); |
2038 |
if ((null_value=args[0]->null_value)) |
|
2039 |
return 0; |
|
2040 |
str->set_charset(collation.collation); |
|
2041 |
return str; |
|
2042 |
}
|
|
2043 |
||
2044 |
void Item_func_set_collation::fix_length_and_dec() |
|
2045 |
{
|
|
264.2.6
by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code. |
2046 |
const CHARSET_INFO *set_collation; |
1
by brian
clean slate |
2047 |
const char *colname; |
2048 |
String tmp, *str= args[1]->val_str(&tmp); |
|
2049 |
colname= str->c_ptr(); |
|
2050 |
if (colname == binary_keyword) |
|
2051 |
set_collation= get_charset_by_csname(args[0]->collation.collation->csname, |
|
2052 |
MY_CS_BINSORT,MYF(0)); |
|
2053 |
else
|
|
2054 |
{
|
|
2055 |
if (!(set_collation= get_charset_by_name(colname,MYF(0)))) |
|
2056 |
{
|
|
2057 |
my_error(ER_UNKNOWN_COLLATION, MYF(0), colname); |
|
2058 |
return; |
|
2059 |
}
|
|
2060 |
}
|
|
2061 |
||
2062 |
if (!set_collation || |
|
2063 |
!my_charset_same(args[0]->collation.collation,set_collation)) |
|
2064 |
{
|
|
2065 |
my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0), |
|
2066 |
colname, args[0]->collation.collation->csname); |
|
2067 |
return; |
|
2068 |
}
|
|
2069 |
collation.set(set_collation, DERIVATION_EXPLICIT, |
|
2070 |
args[0]->collation.repertoire); |
|
2071 |
max_length= args[0]->max_length; |
|
2072 |
}
|
|
2073 |
||
2074 |
||
2075 |
bool Item_func_set_collation::eq(const Item *item, bool binary_cmp) const |
|
2076 |
{
|
|
2077 |
/* Assume we don't have rtti */
|
|
2078 |
if (this == item) |
|
2079 |
return 1; |
|
2080 |
if (item->type() != FUNC_ITEM) |
|
2081 |
return 0; |
|
2082 |
Item_func *item_func=(Item_func*) item; |
|
2083 |
if (arg_count != item_func->arg_count || |
|
2084 |
functype() != item_func->functype()) |
|
2085 |
return 0; |
|
2086 |
Item_func_set_collation *item_func_sc=(Item_func_set_collation*) item; |
|
2087 |
if (collation.collation != item_func_sc->collation.collation) |
|
2088 |
return 0; |
|
482
by Brian Aker
Remove uint. |
2089 |
for (uint32_t i=0; i < arg_count ; i++) |
1
by brian
clean slate |
2090 |
if (!args[i]->eq(item_func_sc->args[i], binary_cmp)) |
2091 |
return 0; |
|
2092 |
return 1; |
|
2093 |
}
|
|
2094 |
||
2095 |
||
2096 |
void Item_func_set_collation::print(String *str, enum_query_type query_type) |
|
2097 |
{
|
|
2098 |
str->append('('); |
|
2099 |
args[0]->print(str, query_type); |
|
2100 |
str->append(STRING_WITH_LEN(" collate ")); |
|
51.1.23
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
2101 |
assert(args[1]->basic_const_item() && |
1
by brian
clean slate |
2102 |
args[1]->type() == Item::STRING_ITEM); |
2103 |
args[1]->str_value.print(str); |
|
2104 |
str->append(')'); |
|
2105 |
}
|
|
2106 |
||
2107 |
String *Item_func_charset::val_str(String *str) |
|
2108 |
{
|
|
51.1.23
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
2109 |
assert(fixed == 1); |
482
by Brian Aker
Remove uint. |
2110 |
uint32_t dummy_errors; |
1
by brian
clean slate |
2111 |
|
264.2.6
by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code. |
2112 |
const CHARSET_INFO * const cs= args[0]->collation.collation; |
1
by brian
clean slate |
2113 |
null_value= 0; |
2114 |
str->copy(cs->csname, strlen(cs->csname), |
|
383.1.12
by Brian Aker
Much closer toward UTF8 being around all the time... |
2115 |
&my_charset_utf8_general_ci, collation.collation, &dummy_errors); |
1
by brian
clean slate |
2116 |
return str; |
2117 |
}
|
|
2118 |
||
2119 |
String *Item_func_collation::val_str(String *str) |
|
2120 |
{
|
|
51.1.23
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
2121 |
assert(fixed == 1); |
482
by Brian Aker
Remove uint. |
2122 |
uint32_t dummy_errors; |
264.2.6
by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code. |
2123 |
const CHARSET_INFO * const cs= args[0]->collation.collation; |
1
by brian
clean slate |
2124 |
|
2125 |
null_value= 0; |
|
2126 |
str->copy(cs->name, strlen(cs->name), |
|
383.1.12
by Brian Aker
Much closer toward UTF8 being around all the time... |
2127 |
&my_charset_utf8_general_ci, collation.collation, &dummy_errors); |
1
by brian
clean slate |
2128 |
return str; |
2129 |
}
|
|
2130 |
||
2131 |
||
2132 |
void Item_func_weight_string::fix_length_and_dec() |
|
2133 |
{
|
|
264.2.6
by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code. |
2134 |
const CHARSET_INFO * const cs= args[0]->collation.collation; |
1
by brian
clean slate |
2135 |
collation.set(&my_charset_bin, args[0]->collation.derivation); |
2136 |
flags= my_strxfrm_flag_normalize(flags, cs->levels_for_order); |
|
398.1.4
by Monty Taylor
Renamed max/min. |
2137 |
max_length= cs->mbmaxlen * cmax(args[0]->max_length, nweights); |
1
by brian
clean slate |
2138 |
maybe_null= 1; |
2139 |
}
|
|
2140 |
||
2141 |
||
2142 |
/* Return a weight_string according to collation */
|
|
2143 |
String *Item_func_weight_string::val_str(String *str) |
|
2144 |
{
|
|
2145 |
String *res; |
|
264.2.6
by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code. |
2146 |
const CHARSET_INFO * const cs= args[0]->collation.collation; |
482
by Brian Aker
Remove uint. |
2147 |
uint32_t tmp_length, frm_length; |
51.1.23
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
2148 |
assert(fixed == 1); |
1
by brian
clean slate |
2149 |
|
2150 |
if (args[0]->result_type() != STRING_RESULT || |
|
2151 |
!(res= args[0]->val_str(str))) |
|
2152 |
goto nl; |
|
2153 |
||
2154 |
tmp_length= cs->coll->strnxfrmlen(cs, cs->mbmaxlen * |
|
398.1.4
by Monty Taylor
Renamed max/min. |
2155 |
cmax(res->length(), nweights)); |
1
by brian
clean slate |
2156 |
|
2157 |
if (tmp_value.alloc(tmp_length)) |
|
2158 |
goto nl; |
|
2159 |
||
2160 |
frm_length= cs->coll->strnxfrm(cs, |
|
481
by Brian Aker
Remove all of uchar. |
2161 |
(unsigned char*) tmp_value.ptr(), tmp_length, |
1
by brian
clean slate |
2162 |
nweights ? nweights : tmp_length, |
481
by Brian Aker
Remove all of uchar. |
2163 |
(const unsigned char*) res->ptr(), res->length(), |
1
by brian
clean slate |
2164 |
flags); |
2165 |
tmp_value.length(frm_length); |
|
2166 |
null_value= 0; |
|
2167 |
return &tmp_value; |
|
2168 |
||
2169 |
nl: |
|
2170 |
null_value= 1; |
|
2171 |
return 0; |
|
2172 |
}
|
|
2173 |
||
2174 |
||
2175 |
String *Item_func_hex::val_str(String *str) |
|
2176 |
{
|
|
2177 |
String *res; |
|
51.1.23
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
2178 |
assert(fixed == 1); |
1
by brian
clean slate |
2179 |
if (args[0]->result_type() != STRING_RESULT) |
2180 |
{
|
|
151
by Brian Aker
Ulonglong to uint64_t |
2181 |
uint64_t dec; |
1
by brian
clean slate |
2182 |
char ans[65],*ptr; |
152
by Brian Aker
longlong replacement |
2183 |
/* Return hex of unsigned int64_t value */
|
1
by brian
clean slate |
2184 |
if (args[0]->result_type() == REAL_RESULT || |
2185 |
args[0]->result_type() == DECIMAL_RESULT) |
|
2186 |
{
|
|
2187 |
double val= args[0]->val_real(); |
|
163
by Brian Aker
Merge Monty's code. |
2188 |
if ((val <= (double) INT64_MIN) || |
2189 |
(val >= (double) (uint64_t) UINT64_MAX)) |
|
152
by Brian Aker
longlong replacement |
2190 |
dec= ~(int64_t) 0; |
1
by brian
clean slate |
2191 |
else
|
151
by Brian Aker
Ulonglong to uint64_t |
2192 |
dec= (uint64_t) (val + (val > 0 ? 0.5 : -0.5)); |
1
by brian
clean slate |
2193 |
}
|
2194 |
else
|
|
151
by Brian Aker
Ulonglong to uint64_t |
2195 |
dec= (uint64_t) args[0]->val_int(); |
1
by brian
clean slate |
2196 |
|
2197 |
if ((null_value= args[0]->null_value)) |
|
2198 |
return 0; |
|
152
by Brian Aker
longlong replacement |
2199 |
ptr= int64_t2str(dec,ans,16); |
205
by Brian Aker
uint32 -> uin32_t |
2200 |
if (str->copy(ans,(uint32_t) (ptr-ans),default_charset())) |
1
by brian
clean slate |
2201 |
return &my_empty_string; // End of memory |
2202 |
return str; |
|
2203 |
}
|
|
2204 |
||
2205 |
/* Convert given string to a hex string, character by character */
|
|
2206 |
res= args[0]->val_str(str); |
|
2207 |
if (!res || tmp_value.alloc(res->length()*2+1)) |
|
2208 |
{
|
|
2209 |
null_value=1; |
|
2210 |
return 0; |
|
2211 |
}
|
|
2212 |
null_value=0; |
|
2213 |
tmp_value.length(res->length()*2); |
|
2214 |
||
2215 |
octet2hex((char*) tmp_value.ptr(), res->ptr(), res->length()); |
|
2216 |
return &tmp_value; |
|
2217 |
}
|
|
2218 |
||
2219 |
/** Convert given hex string to a binary string. */
|
|
2220 |
||
2221 |
String *Item_func_unhex::val_str(String *str) |
|
2222 |
{
|
|
2223 |
const char *from, *end; |
|
2224 |
char *to; |
|
2225 |
String *res; |
|
482
by Brian Aker
Remove uint. |
2226 |
uint32_t length; |
51.1.23
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
2227 |
assert(fixed == 1); |
1
by brian
clean slate |
2228 |
|
2229 |
res= args[0]->val_str(str); |
|
2230 |
if (!res || tmp_value.alloc(length= (1+res->length())/2)) |
|
2231 |
{
|
|
2232 |
null_value=1; |
|
2233 |
return 0; |
|
2234 |
}
|
|
2235 |
||
2236 |
from= res->ptr(); |
|
2237 |
null_value= 0; |
|
2238 |
tmp_value.length(length); |
|
2239 |
to= (char*) tmp_value.ptr(); |
|
2240 |
if (res->length() % 2) |
|
2241 |
{
|
|
2242 |
int hex_char; |
|
2243 |
*to++= hex_char= hexchar_to_int(*from++); |
|
2244 |
if ((null_value= (hex_char == -1))) |
|
2245 |
return 0; |
|
2246 |
}
|
|
2247 |
for (end=res->ptr()+res->length(); from < end ; from+=2, to++) |
|
2248 |
{
|
|
2249 |
int hex_char; |
|
2250 |
*to= (hex_char= hexchar_to_int(from[0])) << 4; |
|
2251 |
if ((null_value= (hex_char == -1))) |
|
2252 |
return 0; |
|
2253 |
*to|= hex_char= hexchar_to_int(from[1]); |
|
2254 |
if ((null_value= (hex_char == -1))) |
|
2255 |
return 0; |
|
2256 |
}
|
|
2257 |
return &tmp_value; |
|
2258 |
}
|
|
2259 |
||
2260 |
||
2261 |
void Item_func_binary::print(String *str, enum_query_type query_type) |
|
2262 |
{
|
|
2263 |
str->append(STRING_WITH_LEN("cast(")); |
|
2264 |
args[0]->print(str, query_type); |
|
2265 |
str->append(STRING_WITH_LEN(" as binary)")); |
|
2266 |
}
|
|
2267 |
||
2268 |
||
2269 |
String *Item_load_file::val_str(String *str) |
|
2270 |
{
|
|
51.1.23
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
2271 |
assert(fixed == 1); |
1
by brian
clean slate |
2272 |
String *file_name; |
2273 |
File file; |
|
15
by brian
Fix for stat, NETWARE removal |
2274 |
struct stat stat_info; |
1
by brian
clean slate |
2275 |
char path[FN_REFLEN]; |
2276 |
||
2277 |
if (!(file_name= args[0]->val_str(str))) |
|
2278 |
goto err; |
|
2279 |
||
2280 |
(void) fn_format(path, file_name->c_ptr(), mysql_real_data_home, "", |
|
2281 |
MY_RELATIVE_PATH | MY_UNPACK_FILENAME); |
|
2282 |
||
2283 |
/* Read only allowed from within dir specified by secure_file_priv */
|
|
2284 |
if (opt_secure_file_priv && |
|
2285 |
strncmp(opt_secure_file_priv, path, strlen(opt_secure_file_priv))) |
|
2286 |
goto err; |
|
2287 |
||
15
by brian
Fix for stat, NETWARE removal |
2288 |
if (stat(path, &stat_info)) |
1
by brian
clean slate |
2289 |
goto err; |
2290 |
||
2291 |
if (!(stat_info.st_mode & S_IROTH)) |
|
2292 |
{
|
|
2293 |
/* my_error(ER_TEXTFILE_NOT_READABLE, MYF(0), file_name->c_ptr()); */
|
|
2294 |
goto err; |
|
2295 |
}
|
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
2296 |
if (stat_info.st_size > (long) current_session->variables.max_allowed_packet) |
1
by brian
clean slate |
2297 |
{
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
2298 |
push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN, |
1
by brian
clean slate |
2299 |
ER_WARN_ALLOWED_PACKET_OVERFLOWED, |
2300 |
ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED), |
|
520.1.22
by Brian Aker
Second pass of thd cleanup |
2301 |
func_name(), current_session->variables.max_allowed_packet); |
1
by brian
clean slate |
2302 |
goto err; |
2303 |
}
|
|
2304 |
if (tmp_value.alloc(stat_info.st_size)) |
|
2305 |
goto err; |
|
2306 |
if ((file = my_open(file_name->c_ptr(), O_RDONLY, MYF(0))) < 0) |
|
2307 |
goto err; |
|
481
by Brian Aker
Remove all of uchar. |
2308 |
if (my_read(file, (unsigned char*) tmp_value.ptr(), stat_info.st_size, MYF(MY_NABP))) |
1
by brian
clean slate |
2309 |
{
|
2310 |
my_close(file, MYF(0)); |
|
2311 |
goto err; |
|
2312 |
}
|
|
2313 |
tmp_value.length(stat_info.st_size); |
|
2314 |
my_close(file, MYF(0)); |
|
2315 |
null_value = 0; |
|
51.1.23
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
2316 |
return(&tmp_value); |
1
by brian
clean slate |
2317 |
|
2318 |
err: |
|
2319 |
null_value = 1; |
|
51.1.23
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
2320 |
return(0); |
1
by brian
clean slate |
2321 |
}
|
2322 |
||
2323 |
||
2324 |
String* Item_func_export_set::val_str(String* str) |
|
2325 |
{
|
|
51.1.23
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
2326 |
assert(fixed == 1); |
151
by Brian Aker
Ulonglong to uint64_t |
2327 |
uint64_t the_set = (uint64_t) args[0]->val_int(); |
1
by brian
clean slate |
2328 |
String yes_buf, *yes; |
2329 |
yes = args[1]->val_str(&yes_buf); |
|
2330 |
String no_buf, *no; |
|
2331 |
no = args[2]->val_str(&no_buf); |
|
2332 |
String *sep = NULL, sep_buf ; |
|
2333 |
||
482
by Brian Aker
Remove uint. |
2334 |
uint32_t num_set_values = 64; |
151
by Brian Aker
Ulonglong to uint64_t |
2335 |
uint64_t mask = 0x1; |
1
by brian
clean slate |
2336 |
str->length(0); |
2337 |
str->set_charset(collation.collation); |
|
2338 |
||
2339 |
/* Check if some argument is a NULL value */
|
|
2340 |
if (args[0]->null_value || args[1]->null_value || args[2]->null_value) |
|
2341 |
{
|
|
2342 |
null_value=1; |
|
2343 |
return 0; |
|
2344 |
}
|
|
2345 |
/*
|
|
2346 |
Arg count can only be 3, 4 or 5 here. This is guaranteed from the
|
|
2347 |
grammar for EXPORT_SET()
|
|
2348 |
*/
|
|
2349 |
switch(arg_count) { |
|
2350 |
case 5: |
|
2351 |
num_set_values = (uint) args[4]->val_int(); |
|
2352 |
if (num_set_values > 64) |
|
2353 |
num_set_values=64; |
|
2354 |
if (args[4]->null_value) |
|
2355 |
{
|
|
2356 |
null_value=1; |
|
2357 |
return 0; |
|
2358 |
}
|
|
2359 |
/* Fall through */
|
|
2360 |
case 4: |
|
2361 |
if (!(sep = args[3]->val_str(&sep_buf))) // Only true if NULL |
|
2362 |
{
|
|
2363 |
null_value=1; |
|
2364 |
return 0; |
|
2365 |
}
|
|
2366 |
break; |
|
2367 |
case 3: |
|
2368 |
{
|
|
2369 |
/* errors is not checked - assume "," can always be converted */
|
|
482
by Brian Aker
Remove uint. |
2370 |
uint32_t errors; |
1
by brian
clean slate |
2371 |
sep_buf.copy(STRING_WITH_LEN(","), &my_charset_bin, collation.collation, &errors); |
2372 |
sep = &sep_buf; |
|
2373 |
}
|
|
2374 |
break; |
|
2375 |
default: |
|
51.1.23
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
2376 |
assert(0); // cannot happen |
1
by brian
clean slate |
2377 |
}
|
2378 |
null_value=0; |
|
2379 |
||
482
by Brian Aker
Remove uint. |
2380 |
for (uint32_t i = 0; i < num_set_values; i++, mask = (mask << 1)) |
1
by brian
clean slate |
2381 |
{
|
2382 |
if (the_set & mask) |
|
2383 |
str->append(*yes); |
|
2384 |
else
|
|
2385 |
str->append(*no); |
|
2386 |
if (i != num_set_values - 1) |
|
2387 |
str->append(*sep); |
|
2388 |
}
|
|
2389 |
return str; |
|
2390 |
}
|
|
2391 |
||
2392 |
void Item_func_export_set::fix_length_and_dec() |
|
2393 |
{
|
|
482
by Brian Aker
Remove uint. |
2394 |
uint32_t length=cmax(args[1]->max_length,args[2]->max_length); |
2395 |
uint32_t sep_length=(arg_count > 3 ? args[3]->max_length : 1); |
|
1
by brian
clean slate |
2396 |
max_length=length*64+sep_length*63; |
2397 |
||
398.1.4
by Monty Taylor
Renamed max/min. |
2398 |
if (agg_arg_charsets(collation, args+1, cmin((uint)4,arg_count)-1, |
1
by brian
clean slate |
2399 |
MY_COLL_ALLOW_CONV, 1)) |
2400 |
return; |
|
2401 |
}
|
|
2402 |
||
2403 |
||
2404 |
#define get_esc_bit(mask, num) (1 & (*((mask) + ((num) >> 3))) >> ((num) & 7))
|
|
2405 |
||
2406 |
/**
|
|
2407 |
QUOTE() function returns argument string in single quotes suitable for
|
|
2408 |
using in a SQL statement.
|
|
2409 |
||
2410 |
Adds a \\ before all characters that needs to be escaped in a SQL string.
|
|
2411 |
We also escape '^Z' (END-OF-FILE in windows) to avoid probelms when
|
|
2412 |
running commands from a file in windows.
|
|
2413 |
||
2414 |
This function is very useful when you want to generate SQL statements.
|
|
2415 |
||
2416 |
@note
|
|
2417 |
QUOTE(NULL) returns the string 'NULL' (4 letters, without quotes).
|
|
2418 |
||
2419 |
@retval
|
|
2420 |
str Quoted string
|
|
2421 |
@retval
|
|
2422 |
NULL Out of memory.
|
|
2423 |
*/
|
|
2424 |
||
2425 |
String *Item_func_quote::val_str(String *str) |
|
2426 |
{
|
|
51.1.23
by Jay Pipes
Removed DBUG symbols and fixed TRUE/FALSE |
2427 |
assert(fixed == 1); |
1
by brian
clean slate |
2428 |
/*
|
2429 |
Bit mask that has 1 for set for the position of the following characters:
|
|
2430 |
0, \, ' and ^Z
|
|
2431 |
*/
|
|
2432 |
||
481
by Brian Aker
Remove all of uchar. |
2433 |
static unsigned char escmask[32]= |
1
by brian
clean slate |
2434 |
{
|
2435 |
0x01, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x00, |
|
2436 |
0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, |
|
2437 |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
2438 |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
|
2439 |
};
|
|
2440 |
||
2441 |
char *from, *to, *end, *start; |
|
2442 |
String *arg= args[0]->val_str(str); |
|
482
by Brian Aker
Remove uint. |
2443 |
uint32_t arg_length, new_length; |
1
by brian
clean slate |
2444 |
if (!arg) // Null argument |
2445 |
{
|
|
2446 |
/* Return the string 'NULL' */
|
|
2447 |
str->copy(STRING_WITH_LEN("NULL"), collation.collation); |
|
2448 |
null_value= 0; |
|
2449 |
return str; |
|
2450 |
}
|
|
2451 |
||
2452 |
arg_length= arg->length(); |
|
2453 |
new_length= arg_length+2; /* for beginning and ending ' signs */ |
|
2454 |
||
2455 |
for (from= (char*) arg->ptr(), end= from + arg_length; from < end; from++) |
|
481
by Brian Aker
Remove all of uchar. |
2456 |
new_length+= get_esc_bit(escmask, (unsigned char) *from); |
1
by brian
clean slate |
2457 |
|
2458 |
if (tmp_value.alloc(new_length)) |
|
2459 |
goto null; |
|
2460 |
||
2461 |
/*
|
|
2462 |
We replace characters from the end to the beginning
|
|
2463 |
*/
|
|
2464 |
to= (char*) tmp_value.ptr() + new_length - 1; |
|
2465 |
*to--= '\''; |
|
2466 |
for (start= (char*) arg->ptr(),end= start + arg_length; end-- != start; to--) |
|
2467 |
{
|
|
2468 |
/*
|
|
2469 |
We can't use the bitmask here as we want to replace \O and ^Z with 0
|
|
2470 |
and Z
|
|
2471 |
*/
|
|
2472 |
switch (*end) { |
|
2473 |
case 0: |
|
2474 |
*to--= '0'; |
|
2475 |
*to= '\\'; |
|
2476 |
break; |
|
2477 |
case '\032': |
|
2478 |
*to--= 'Z'; |
|
2479 |
*to= '\\'; |
|
2480 |
break; |
|
2481 |
case '\'': |
|
2482 |
case '\\': |
|
2483 |
*to--= *end; |
|
2484 |
*to= '\\'; |
|
2485 |
break; |
|
2486 |
default: |
|
2487 |
*to= *end; |
|
2488 |
break; |
|
2489 |
}
|
|
2490 |
}
|
|
2491 |
*to= '\''; |
|
2492 |
tmp_value.length(new_length); |
|
2493 |
tmp_value.set_charset(collation.collation); |
|
2494 |
null_value= 0; |
|
2495 |
return &tmp_value; |
|
2496 |
||
2497 |
null: |
|
2498 |
null_value= 1; |
|
2499 |
return 0; |
|
2500 |
}
|
|
2501 |
||
564
by Brian Aker
New UUID code. Also changed default scaling for "8" core machine instead of |
2502 |
|
1
by brian
clean slate |
2503 |
|
2504 |
String *Item_func_uuid::val_str(String *str) |
|
2505 |
{
|
|
564
by Brian Aker
New UUID code. Also changed default scaling for "8" core machine instead of |
2506 |
uuid_t uu; |
2507 |
char *uuid_string; |
|
2508 |
||
2509 |
/* 36 characters for uuid string +1 for NULL */
|
|
2510 |
str->realloc(36+1); |
|
2511 |
str->length(36); |
|
1
by brian
clean slate |
2512 |
str->set_charset(system_charset_info); |
564
by Brian Aker
New UUID code. Also changed default scaling for "8" core machine instead of |
2513 |
uuid_string= (char *) str->ptr(); |
2514 |
uuid_generate_time(uu); |
|
2515 |
uuid_unparse(uu, uuid_string); |
|
2516 |
||
1
by brian
clean slate |
2517 |
return str; |
2518 |
}
|