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, Inc.
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
22
#include <drizzled/function/str/concat.h>
23
#include <drizzled/error.h>
24
#include <drizzled/session.h>
33
String *Item_func_concat::val_str(String *str)
36
String *res,*res2,*use_as_buff;
41
if (!(res=args[0]->val_str(str)))
43
use_as_buff= &tmp_value;
44
/* Item_subselect in --ps-protocol mode will state it as a non-const */
45
is_const= args[0]->const_item() || !args[0]->used_tables();
46
for (i=1 ; i < arg_count ; i++)
48
if (res->length() == 0)
50
if (!(res=args[i]->val_str(str)))
55
if (!(res2=args[i]->val_str(use_as_buff)))
57
if (res2->length() == 0)
59
if (res->length()+res2->length() >
60
session.variables.max_allowed_packet)
62
push_warning_printf(&session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
63
ER_WARN_ALLOWED_PACKET_OVERFLOWED,
64
ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED), func_name(),
65
session.variables.max_allowed_packet);
68
if (!is_const && res->alloced_length() >= res->length()+res2->length())
72
else if (str->alloced_length() >= res->length()+res2->length())
75
str->replace(0,0,*res);
82
use_as_buff= &tmp_value;
84
else if (res == &tmp_value)
86
if (res->append(*res2)) // Must be a blob
89
else if (res2 == &tmp_value)
90
{ // This can happend only 1 time
91
if (tmp_value.replace(0,0,*res))
94
use_as_buff=str; // Put next arg here
96
else if (tmp_value.is_alloced() && res2->ptr() >= tmp_value.ptr() &&
97
res2->ptr() <= tmp_value.ptr() + tmp_value.alloced_length())
100
This happens really seldom:
101
In this case res2 is sub string of tmp_value. We will
102
now work in place in tmp_value to set it to res | res2
104
/* Chop the last characters in tmp_value that isn't in res2 */
105
tmp_value.length((uint32_t) (res2->ptr() - tmp_value.ptr()) +
107
/* Place res2 at start of tmp_value, remove chars before res2 */
108
if (tmp_value.replace(0,(uint32_t) (res2->ptr() - tmp_value.ptr()),
112
use_as_buff=str; // Put next arg here
115
{ // Two big const strings
117
@note We should be prudent in the initial allocation unit -- the
118
size of the arguments is a function of data distribution, which
119
can be any. Instead of overcommitting at the first row, we grow
120
the allocated amount by the factor of 2. This ensures that no
121
more than 25% of memory will be overcommitted on average.
124
size_t concat_len= res->length() + res2->length();
126
if (tmp_value.alloced_length() < concat_len)
128
if (tmp_value.alloced_length() == 0)
130
if (tmp_value.alloc(concat_len))
135
uint32_t new_len= max(tmp_value.alloced_length() * 2, concat_len);
137
if (tmp_value.realloc(new_len))
142
if (tmp_value.copy(*res) || tmp_value.append(*res2))
151
res->set_charset(collation.collation);
160
void Item_func_concat::fix_length_and_dec()
162
uint64_t max_result_length= 0;
164
if (agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV, 1))
167
for (uint32_t i=0 ; i < arg_count ; i++)
169
if (args[i]->collation.collation->mbmaxlen != collation.collation->mbmaxlen)
170
max_result_length+= (args[i]->max_length /
171
args[i]->collation.collation->mbmaxlen) *
172
collation.collation->mbmaxlen;
174
max_result_length+= args[i]->max_length;
177
if (max_result_length >= MAX_BLOB_WIDTH)
179
max_result_length= MAX_BLOB_WIDTH;
182
max_length= (ulong) max_result_length;
187
concat with separator. First arg is the separator
188
concat_ws takes at least two arguments.
191
String *Item_func_concat_ws::val_str(String *str)
194
char tmp_str_buff[10];
195
String tmp_sep_str(tmp_str_buff, sizeof(tmp_str_buff),default_charset_info),
196
*sep_str, *res, *res2,*use_as_buff;
200
if (!(sep_str= args[0]->val_str(&tmp_sep_str)))
203
use_as_buff= &tmp_value;
204
str->length(0); // QQ; Should be removed
207
// Skip until non-null argument is found.
208
// If not, return the empty string
209
for (i=1; i < arg_count; i++)
210
if ((res= args[i]->val_str(str)))
213
return &my_empty_string;
215
for (i++; i < arg_count ; i++)
217
if (!(res2= args[i]->val_str(use_as_buff)))
218
continue; // Skip NULL
220
if (res->length() + sep_str->length() + res2->length() >
221
session.variables.max_allowed_packet)
223
push_warning_printf(&session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
224
ER_WARN_ALLOWED_PACKET_OVERFLOWED,
225
ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED), func_name(),
226
session.variables.max_allowed_packet);
229
if (res->alloced_length() >=
230
res->length() + sep_str->length() + res2->length())
232
res->append(*sep_str); // res->length() > 0 always
235
else if (str->alloced_length() >=
236
res->length() + sep_str->length() + res2->length())
238
/* We have room in str; We can't get any errors here */
240
{ // This is quote uncommon!
241
str->replace(0,0,*sep_str);
242
str->replace(0,0,*res);
247
str->append(*sep_str);
251
use_as_buff= &tmp_value;
253
else if (res == &tmp_value)
255
if (res->append(*sep_str) || res->append(*res2))
256
goto null; // Must be a blob
258
else if (res2 == &tmp_value)
259
{ // This can happend only 1 time
260
if (tmp_value.replace(0,0,*sep_str) || tmp_value.replace(0,0,*res))
263
use_as_buff=str; // Put next arg here
265
else if (tmp_value.is_alloced() && res2->ptr() >= tmp_value.ptr() &&
266
res2->ptr() < tmp_value.ptr() + tmp_value.alloced_length())
269
This happens really seldom:
270
In this case res2 is sub string of tmp_value. We will
271
now work in place in tmp_value to set it to res | sep_str | res2
273
/* Chop the last characters in tmp_value that isn't in res2 */
274
tmp_value.length((uint32_t) (res2->ptr() - tmp_value.ptr()) +
276
/* Place res2 at start of tmp_value, remove chars before res2 */
277
if (tmp_value.replace(0,(uint32_t) (res2->ptr() - tmp_value.ptr()),
279
tmp_value.replace(res->length(),0, *sep_str))
282
use_as_buff=str; // Put next arg here
285
{ // Two big const strings
287
@note We should be prudent in the initial allocation unit -- the
288
size of the arguments is a function of data distribution, which can
289
be any. Instead of overcommitting at the first row, we grow the
290
allocated amount by the factor of 2. This ensures that no more than
291
25% of memory will be overcommitted on average.
294
size_t concat_len= res->length() + sep_str->length() + res2->length();
296
if (tmp_value.alloced_length() < concat_len)
298
if (tmp_value.alloced_length() == 0)
300
if (tmp_value.alloc(concat_len))
305
uint32_t new_len= max(tmp_value.alloced_length() * 2, concat_len);
307
if (tmp_value.realloc(new_len))
312
if (tmp_value.copy(*res) ||
313
tmp_value.append(*sep_str) ||
314
tmp_value.append(*res2))
320
res->set_charset(collation.collation);
329
void Item_func_concat_ws::fix_length_and_dec()
331
uint64_t max_result_length;
333
if (agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV, 1))
337
arg_count cannot be less than 2,
338
it is done on parser level in sql_yacc.yy
339
so, (arg_count - 2) is safe here.
341
max_result_length= (uint64_t) args[0]->max_length * (arg_count - 2);
342
for (uint32_t i=1 ; i < arg_count ; i++)
343
max_result_length+=args[i]->max_length;
345
if (max_result_length >= MAX_BLOB_WIDTH)
347
max_result_length= MAX_BLOB_WIDTH;
350
max_length= (ulong) max_result_length;
353
} /* namespace drizzled */