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/functions/str/concat.h>
23
#include <drizzled/error.h>
24
#include <drizzled/session.h>
26
String *Item_func_concat::val_str(String *str)
29
String *res,*res2,*use_as_buff;
34
if (!(res=args[0]->val_str(str)))
36
use_as_buff= &tmp_value;
37
/* Item_subselect in --ps-protocol mode will state it as a non-const */
38
is_const= args[0]->const_item() || !args[0]->used_tables();
39
for (i=1 ; i < arg_count ; i++)
41
if (res->length() == 0)
43
if (!(res=args[i]->val_str(str)))
48
if (!(res2=args[i]->val_str(use_as_buff)))
50
if (res2->length() == 0)
52
if (res->length()+res2->length() >
53
current_session->variables.max_allowed_packet)
55
push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
56
ER_WARN_ALLOWED_PACKET_OVERFLOWED,
57
ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED), func_name(),
58
current_session->variables.max_allowed_packet);
61
if (!is_const && res->alloced_length() >= res->length()+res2->length())
65
else if (str->alloced_length() >= res->length()+res2->length())
68
str->replace(0,0,*res);
75
use_as_buff= &tmp_value;
77
else if (res == &tmp_value)
79
if (res->append(*res2)) // Must be a blob
82
else if (res2 == &tmp_value)
83
{ // This can happend only 1 time
84
if (tmp_value.replace(0,0,*res))
87
use_as_buff=str; // Put next arg here
89
else if (tmp_value.is_alloced() && res2->ptr() >= tmp_value.ptr() &&
90
res2->ptr() <= tmp_value.ptr() + tmp_value.alloced_length())
93
This happens really seldom:
94
In this case res2 is sub string of tmp_value. We will
95
now work in place in tmp_value to set it to res | res2
97
/* Chop the last characters in tmp_value that isn't in res2 */
98
tmp_value.length((uint32_t) (res2->ptr() - tmp_value.ptr()) +
100
/* Place res2 at start of tmp_value, remove chars before res2 */
101
if (tmp_value.replace(0,(uint32_t) (res2->ptr() - tmp_value.ptr()),
105
use_as_buff=str; // Put next arg here
108
{ // Two big const strings
110
NOTE: We should be prudent in the initial allocation unit -- the
111
size of the arguments is a function of data distribution, which
112
can be any. Instead of overcommitting at the first row, we grow
113
the allocated amount by the factor of 2. This ensures that no
114
more than 25% of memory will be overcommitted on average.
117
uint32_t concat_len= res->length() + res2->length();
119
if (tmp_value.alloced_length() < concat_len)
121
if (tmp_value.alloced_length() == 0)
123
if (tmp_value.alloc(concat_len))
128
uint32_t new_len = cmax(tmp_value.alloced_length() * 2, concat_len);
130
if (tmp_value.realloc(new_len))
135
if (tmp_value.copy(*res) || tmp_value.append(*res2))
144
res->set_charset(collation.collation);
153
void Item_func_concat::fix_length_and_dec()
155
uint64_t max_result_length= 0;
157
if (agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV, 1))
160
for (uint32_t i=0 ; i < arg_count ; i++)
162
if (args[i]->collation.collation->mbmaxlen != collation.collation->mbmaxlen)
163
max_result_length+= (args[i]->max_length /
164
args[i]->collation.collation->mbmaxlen) *
165
collation.collation->mbmaxlen;
167
max_result_length+= args[i]->max_length;
170
if (max_result_length >= MAX_BLOB_WIDTH)
172
max_result_length= MAX_BLOB_WIDTH;
175
max_length= (ulong) max_result_length;
180
concat with separator. First arg is the separator
181
concat_ws takes at least two arguments.
184
String *Item_func_concat_ws::val_str(String *str)
187
char tmp_str_buff[10];
188
String tmp_sep_str(tmp_str_buff, sizeof(tmp_str_buff),default_charset_info),
189
*sep_str, *res, *res2,*use_as_buff;
193
if (!(sep_str= args[0]->val_str(&tmp_sep_str)))
196
use_as_buff= &tmp_value;
197
str->length(0); // QQ; Should be removed
200
// Skip until non-null argument is found.
201
// If not, return the empty string
202
for (i=1; i < arg_count; i++)
203
if ((res= args[i]->val_str(str)))
206
return &my_empty_string;
208
for (i++; i < arg_count ; i++)
210
if (!(res2= args[i]->val_str(use_as_buff)))
211
continue; // Skip NULL
213
if (res->length() + sep_str->length() + res2->length() >
214
current_session->variables.max_allowed_packet)
216
push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
217
ER_WARN_ALLOWED_PACKET_OVERFLOWED,
218
ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED), func_name(),
219
current_session->variables.max_allowed_packet);
222
if (res->alloced_length() >=
223
res->length() + sep_str->length() + res2->length())
225
res->append(*sep_str); // res->length() > 0 always
228
else if (str->alloced_length() >=
229
res->length() + sep_str->length() + res2->length())
231
/* We have room in str; We can't get any errors here */
233
{ // This is quote uncommon!
234
str->replace(0,0,*sep_str);
235
str->replace(0,0,*res);
240
str->append(*sep_str);
244
use_as_buff= &tmp_value;
246
else if (res == &tmp_value)
248
if (res->append(*sep_str) || res->append(*res2))
249
goto null; // Must be a blob
251
else if (res2 == &tmp_value)
252
{ // This can happend only 1 time
253
if (tmp_value.replace(0,0,*sep_str) || tmp_value.replace(0,0,*res))
256
use_as_buff=str; // Put next arg here
258
else if (tmp_value.is_alloced() && res2->ptr() >= tmp_value.ptr() &&
259
res2->ptr() < tmp_value.ptr() + tmp_value.alloced_length())
262
This happens really seldom:
263
In this case res2 is sub string of tmp_value. We will
264
now work in place in tmp_value to set it to res | sep_str | res2
266
/* Chop the last characters in tmp_value that isn't in res2 */
267
tmp_value.length((uint32_t) (res2->ptr() - tmp_value.ptr()) +
269
/* Place res2 at start of tmp_value, remove chars before res2 */
270
if (tmp_value.replace(0,(uint32_t) (res2->ptr() - tmp_value.ptr()),
272
tmp_value.replace(res->length(),0, *sep_str))
275
use_as_buff=str; // Put next arg here
278
{ // Two big const strings
280
NOTE: We should be prudent in the initial allocation unit -- the
281
size of the arguments is a function of data distribution, which can
282
be any. Instead of overcommitting at the first row, we grow the
283
allocated amount by the factor of 2. This ensures that no more than
284
25% of memory will be overcommitted on average.
287
uint32_t concat_len= res->length() + sep_str->length() + res2->length();
289
if (tmp_value.alloced_length() < concat_len)
291
if (tmp_value.alloced_length() == 0)
293
if (tmp_value.alloc(concat_len))
298
uint32_t new_len = cmax(tmp_value.alloced_length() * 2, concat_len);
300
if (tmp_value.realloc(new_len))
305
if (tmp_value.copy(*res) ||
306
tmp_value.append(*sep_str) ||
307
tmp_value.append(*res2))
313
res->set_charset(collation.collation);
322
void Item_func_concat_ws::fix_length_and_dec()
324
uint64_t max_result_length;
326
if (agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV, 1))
330
arg_count cannot be less than 2,
331
it is done on parser level in sql_yacc.yy
332
so, (arg_count - 2) is safe here.
334
max_result_length= (uint64_t) args[0]->max_length * (arg_count - 2);
335
for (uint32_t i=1 ; i < arg_count ; i++)
336
max_result_length+=args[i]->max_length;
338
if (max_result_length >= MAX_BLOB_WIDTH)
340
max_result_length= MAX_BLOB_WIDTH;
343
max_length= (ulong) max_result_length;