1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
* Copyright (C) 2008 Sun Microsystems
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; version 2 of the License.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20
#include <drizzled/server_includes.h>
22
#include <drizzled/function/str/concat.h>
23
#include <drizzled/error.h>
24
#include <drizzled/session.h>
30
String *Item_func_concat::val_str(String *str)
33
String *res,*res2,*use_as_buff;
38
if (!(res=args[0]->val_str(str)))
40
use_as_buff= &tmp_value;
41
/* Item_subselect in --ps-protocol mode will state it as a non-const */
42
is_const= args[0]->const_item() || !args[0]->used_tables();
43
for (i=1 ; i < arg_count ; i++)
45
if (res->length() == 0)
47
if (!(res=args[i]->val_str(str)))
52
if (!(res2=args[i]->val_str(use_as_buff)))
54
if (res2->length() == 0)
56
if (res->length()+res2->length() >
57
current_session->variables.max_allowed_packet)
59
push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
60
ER_WARN_ALLOWED_PACKET_OVERFLOWED,
61
ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED), func_name(),
62
current_session->variables.max_allowed_packet);
65
if (!is_const && res->alloced_length() >= res->length()+res2->length())
69
else if (str->alloced_length() >= res->length()+res2->length())
72
str->replace(0,0,*res);
79
use_as_buff= &tmp_value;
81
else if (res == &tmp_value)
83
if (res->append(*res2)) // Must be a blob
86
else if (res2 == &tmp_value)
87
{ // This can happend only 1 time
88
if (tmp_value.replace(0,0,*res))
91
use_as_buff=str; // Put next arg here
93
else if (tmp_value.is_alloced() && res2->ptr() >= tmp_value.ptr() &&
94
res2->ptr() <= tmp_value.ptr() + tmp_value.alloced_length())
97
This happens really seldom:
98
In this case res2 is sub string of tmp_value. We will
99
now work in place in tmp_value to set it to res | res2
101
/* Chop the last characters in tmp_value that isn't in res2 */
102
tmp_value.length((uint32_t) (res2->ptr() - tmp_value.ptr()) +
104
/* Place res2 at start of tmp_value, remove chars before res2 */
105
if (tmp_value.replace(0,(uint32_t) (res2->ptr() - tmp_value.ptr()),
109
use_as_buff=str; // Put next arg here
112
{ // Two big const strings
114
NOTE: We should be prudent in the initial allocation unit -- the
115
size of the arguments is a function of data distribution, which
116
can be any. Instead of overcommitting at the first row, we grow
117
the allocated amount by the factor of 2. This ensures that no
118
more than 25% of memory will be overcommitted on average.
121
uint32_t concat_len= res->length() + res2->length();
123
if (tmp_value.alloced_length() < concat_len)
125
if (tmp_value.alloced_length() == 0)
127
if (tmp_value.alloc(concat_len))
132
uint32_t new_len= max(tmp_value.alloced_length() * 2, concat_len);
134
if (tmp_value.realloc(new_len))
139
if (tmp_value.copy(*res) || tmp_value.append(*res2))
148
res->set_charset(collation.collation);
157
void Item_func_concat::fix_length_and_dec()
159
uint64_t max_result_length= 0;
161
if (agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV, 1))
164
for (uint32_t i=0 ; i < arg_count ; i++)
166
if (args[i]->collation.collation->mbmaxlen != collation.collation->mbmaxlen)
167
max_result_length+= (args[i]->max_length /
168
args[i]->collation.collation->mbmaxlen) *
169
collation.collation->mbmaxlen;
171
max_result_length+= args[i]->max_length;
174
if (max_result_length >= MAX_BLOB_WIDTH)
176
max_result_length= MAX_BLOB_WIDTH;
179
max_length= (ulong) max_result_length;
184
concat with separator. First arg is the separator
185
concat_ws takes at least two arguments.
188
String *Item_func_concat_ws::val_str(String *str)
191
char tmp_str_buff[10];
192
String tmp_sep_str(tmp_str_buff, sizeof(tmp_str_buff),default_charset_info),
193
*sep_str, *res, *res2,*use_as_buff;
197
if (!(sep_str= args[0]->val_str(&tmp_sep_str)))
200
use_as_buff= &tmp_value;
201
str->length(0); // QQ; Should be removed
204
// Skip until non-null argument is found.
205
// If not, return the empty string
206
for (i=1; i < arg_count; i++)
207
if ((res= args[i]->val_str(str)))
210
return &my_empty_string;
212
for (i++; i < arg_count ; i++)
214
if (!(res2= args[i]->val_str(use_as_buff)))
215
continue; // Skip NULL
217
if (res->length() + sep_str->length() + res2->length() >
218
current_session->variables.max_allowed_packet)
220
push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
221
ER_WARN_ALLOWED_PACKET_OVERFLOWED,
222
ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED), func_name(),
223
current_session->variables.max_allowed_packet);
226
if (res->alloced_length() >=
227
res->length() + sep_str->length() + res2->length())
229
res->append(*sep_str); // res->length() > 0 always
232
else if (str->alloced_length() >=
233
res->length() + sep_str->length() + res2->length())
235
/* We have room in str; We can't get any errors here */
237
{ // This is quote uncommon!
238
str->replace(0,0,*sep_str);
239
str->replace(0,0,*res);
244
str->append(*sep_str);
248
use_as_buff= &tmp_value;
250
else if (res == &tmp_value)
252
if (res->append(*sep_str) || res->append(*res2))
253
goto null; // Must be a blob
255
else if (res2 == &tmp_value)
256
{ // This can happend only 1 time
257
if (tmp_value.replace(0,0,*sep_str) || tmp_value.replace(0,0,*res))
260
use_as_buff=str; // Put next arg here
262
else if (tmp_value.is_alloced() && res2->ptr() >= tmp_value.ptr() &&
263
res2->ptr() < tmp_value.ptr() + tmp_value.alloced_length())
266
This happens really seldom:
267
In this case res2 is sub string of tmp_value. We will
268
now work in place in tmp_value to set it to res | sep_str | res2
270
/* Chop the last characters in tmp_value that isn't in res2 */
271
tmp_value.length((uint32_t) (res2->ptr() - tmp_value.ptr()) +
273
/* Place res2 at start of tmp_value, remove chars before res2 */
274
if (tmp_value.replace(0,(uint32_t) (res2->ptr() - tmp_value.ptr()),
276
tmp_value.replace(res->length(),0, *sep_str))
279
use_as_buff=str; // Put next arg here
282
{ // Two big const strings
284
NOTE: We should be prudent in the initial allocation unit -- the
285
size of the arguments is a function of data distribution, which can
286
be any. Instead of overcommitting at the first row, we grow the
287
allocated amount by the factor of 2. This ensures that no more than
288
25% of memory will be overcommitted on average.
291
uint32_t concat_len= res->length() + sep_str->length() + res2->length();
293
if (tmp_value.alloced_length() < concat_len)
295
if (tmp_value.alloced_length() == 0)
297
if (tmp_value.alloc(concat_len))
302
uint32_t new_len= max(tmp_value.alloced_length() * 2, concat_len);
304
if (tmp_value.realloc(new_len))
309
if (tmp_value.copy(*res) ||
310
tmp_value.append(*sep_str) ||
311
tmp_value.append(*res2))
317
res->set_charset(collation.collation);
326
void Item_func_concat_ws::fix_length_and_dec()
328
uint64_t max_result_length;
330
if (agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV, 1))
334
arg_count cannot be less than 2,
335
it is done on parser level in sql_yacc.yy
336
so, (arg_count - 2) is safe here.
338
max_result_length= (uint64_t) args[0]->max_length * (arg_count - 2);
339
for (uint32_t i=1 ; i < arg_count ; i++)
340
max_result_length+=args[i]->max_length;
342
if (max_result_length >= MAX_BLOB_WIDTH)
344
max_result_length= MAX_BLOB_WIDTH;
347
max_length= (ulong) max_result_length;