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