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>
25
String *Item_func_concat::val_str(String *str)
28
String *res,*res2,*use_as_buff;
33
if (!(res=args[0]->val_str(str)))
35
use_as_buff= &tmp_value;
36
/* Item_subselect in --ps-protocol mode will state it as a non-const */
37
is_const= args[0]->const_item() || !args[0]->used_tables();
38
for (i=1 ; i < arg_count ; i++)
40
if (res->length() == 0)
42
if (!(res=args[i]->val_str(str)))
47
if (!(res2=args[i]->val_str(use_as_buff)))
49
if (res2->length() == 0)
51
if (res->length()+res2->length() >
52
current_session->variables.max_allowed_packet)
54
push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
55
ER_WARN_ALLOWED_PACKET_OVERFLOWED,
56
ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED), func_name(),
57
current_session->variables.max_allowed_packet);
60
if (!is_const && res->alloced_length() >= res->length()+res2->length())
64
else if (str->alloced_length() >= res->length()+res2->length())
67
str->replace(0,0,*res);
74
use_as_buff= &tmp_value;
76
else if (res == &tmp_value)
78
if (res->append(*res2)) // Must be a blob
81
else if (res2 == &tmp_value)
82
{ // This can happend only 1 time
83
if (tmp_value.replace(0,0,*res))
86
use_as_buff=str; // Put next arg here
88
else if (tmp_value.is_alloced() && res2->ptr() >= tmp_value.ptr() &&
89
res2->ptr() <= tmp_value.ptr() + tmp_value.alloced_length())
92
This happens really seldom:
93
In this case res2 is sub string of tmp_value. We will
94
now work in place in tmp_value to set it to res | res2
96
/* Chop the last characters in tmp_value that isn't in res2 */
97
tmp_value.length((uint32_t) (res2->ptr() - tmp_value.ptr()) +
99
/* Place res2 at start of tmp_value, remove chars before res2 */
100
if (tmp_value.replace(0,(uint32_t) (res2->ptr() - tmp_value.ptr()),
104
use_as_buff=str; // Put next arg here
107
{ // Two big const strings
109
NOTE: We should be prudent in the initial allocation unit -- the
110
size of the arguments is a function of data distribution, which
111
can be any. Instead of overcommitting at the first row, we grow
112
the allocated amount by the factor of 2. This ensures that no
113
more than 25% of memory will be overcommitted on average.
116
uint32_t concat_len= res->length() + res2->length();
118
if (tmp_value.alloced_length() < concat_len)
120
if (tmp_value.alloced_length() == 0)
122
if (tmp_value.alloc(concat_len))
127
uint32_t new_len = cmax(tmp_value.alloced_length() * 2, concat_len);
129
if (tmp_value.realloc(new_len))
134
if (tmp_value.copy(*res) || tmp_value.append(*res2))
143
res->set_charset(collation.collation);
152
void Item_func_concat::fix_length_and_dec()
154
uint64_t max_result_length= 0;
156
if (agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV, 1))
159
for (uint32_t i=0 ; i < arg_count ; i++)
161
if (args[i]->collation.collation->mbmaxlen != collation.collation->mbmaxlen)
162
max_result_length+= (args[i]->max_length /
163
args[i]->collation.collation->mbmaxlen) *
164
collation.collation->mbmaxlen;
166
max_result_length+= args[i]->max_length;
169
if (max_result_length >= MAX_BLOB_WIDTH)
171
max_result_length= MAX_BLOB_WIDTH;
174
max_length= (ulong) max_result_length;
179
concat with separator. First arg is the separator
180
concat_ws takes at least two arguments.
183
String *Item_func_concat_ws::val_str(String *str)
186
char tmp_str_buff[10];
187
String tmp_sep_str(tmp_str_buff, sizeof(tmp_str_buff),default_charset_info),
188
*sep_str, *res, *res2,*use_as_buff;
192
if (!(sep_str= args[0]->val_str(&tmp_sep_str)))
195
use_as_buff= &tmp_value;
196
str->length(0); // QQ; Should be removed
199
// Skip until non-null argument is found.
200
// If not, return the empty string
201
for (i=1; i < arg_count; i++)
202
if ((res= args[i]->val_str(str)))
205
return &my_empty_string;
207
for (i++; i < arg_count ; i++)
209
if (!(res2= args[i]->val_str(use_as_buff)))
210
continue; // Skip NULL
212
if (res->length() + sep_str->length() + res2->length() >
213
current_session->variables.max_allowed_packet)
215
push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
216
ER_WARN_ALLOWED_PACKET_OVERFLOWED,
217
ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED), func_name(),
218
current_session->variables.max_allowed_packet);
221
if (res->alloced_length() >=
222
res->length() + sep_str->length() + res2->length())
224
res->append(*sep_str); // res->length() > 0 always
227
else if (str->alloced_length() >=
228
res->length() + sep_str->length() + res2->length())
230
/* We have room in str; We can't get any errors here */
232
{ // This is quote uncommon!
233
str->replace(0,0,*sep_str);
234
str->replace(0,0,*res);
239
str->append(*sep_str);
243
use_as_buff= &tmp_value;
245
else if (res == &tmp_value)
247
if (res->append(*sep_str) || res->append(*res2))
248
goto null; // Must be a blob
250
else if (res2 == &tmp_value)
251
{ // This can happend only 1 time
252
if (tmp_value.replace(0,0,*sep_str) || tmp_value.replace(0,0,*res))
255
use_as_buff=str; // Put next arg here
257
else if (tmp_value.is_alloced() && res2->ptr() >= tmp_value.ptr() &&
258
res2->ptr() < tmp_value.ptr() + tmp_value.alloced_length())
261
This happens really seldom:
262
In this case res2 is sub string of tmp_value. We will
263
now work in place in tmp_value to set it to res | sep_str | res2
265
/* Chop the last characters in tmp_value that isn't in res2 */
266
tmp_value.length((uint32_t) (res2->ptr() - tmp_value.ptr()) +
268
/* Place res2 at start of tmp_value, remove chars before res2 */
269
if (tmp_value.replace(0,(uint32_t) (res2->ptr() - tmp_value.ptr()),
271
tmp_value.replace(res->length(),0, *sep_str))
274
use_as_buff=str; // Put next arg here
277
{ // Two big const strings
279
NOTE: We should be prudent in the initial allocation unit -- the
280
size of the arguments is a function of data distribution, which can
281
be any. Instead of overcommitting at the first row, we grow the
282
allocated amount by the factor of 2. This ensures that no more than
283
25% of memory will be overcommitted on average.
286
uint32_t concat_len= res->length() + sep_str->length() + res2->length();
288
if (tmp_value.alloced_length() < concat_len)
290
if (tmp_value.alloced_length() == 0)
292
if (tmp_value.alloc(concat_len))
297
uint32_t new_len = cmax(tmp_value.alloced_length() * 2, concat_len);
299
if (tmp_value.realloc(new_len))
304
if (tmp_value.copy(*res) ||
305
tmp_value.append(*sep_str) ||
306
tmp_value.append(*res2))
312
res->set_charset(collation.collation);
321
void Item_func_concat_ws::fix_length_and_dec()
323
uint64_t max_result_length;
325
if (agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV, 1))
329
arg_count cannot be less than 2,
330
it is done on parser level in sql_yacc.yy
331
so, (arg_count - 2) is safe here.
333
max_result_length= (uint64_t) args[0]->max_length * (arg_count - 2);
334
for (uint32_t i=1 ; i < arg_count ; i++)
335
max_result_length+=args[i]->max_length;
337
if (max_result_length >= MAX_BLOB_WIDTH)
339
max_result_length= MAX_BLOB_WIDTH;
342
max_length= (ulong) max_result_length;