00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <config.h>
00021
00022 #include <drizzled/function/str/concat.h>
00023 #include <drizzled/error.h>
00024 #include <drizzled/session.h>
00025
00026 #include <algorithm>
00027
00028 using namespace std;
00029
00030 namespace drizzled
00031 {
00032
00033 String *Item_func_concat::val_str(String *str)
00034 {
00035 assert(fixed == 1);
00036 String *res,*res2,*use_as_buff;
00037 uint32_t i;
00038 bool is_const= 0;
00039
00040 null_value=0;
00041 if (!(res=args[0]->val_str(str)))
00042 goto null;
00043 use_as_buff= &tmp_value;
00044
00045 is_const= args[0]->const_item() || !args[0]->used_tables();
00046 for (i=1 ; i < arg_count ; i++)
00047 {
00048 if (res->length() == 0)
00049 {
00050 if (!(res=args[i]->val_str(str)))
00051 goto null;
00052 }
00053 else
00054 {
00055 if (!(res2=args[i]->val_str(use_as_buff)))
00056 goto null;
00057 if (res2->length() == 0)
00058 continue;
00059 if (res->length()+res2->length() >
00060 session.variables.max_allowed_packet)
00061 {
00062 push_warning_printf(&session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
00063 ER_WARN_ALLOWED_PACKET_OVERFLOWED,
00064 ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED), func_name(),
00065 session.variables.max_allowed_packet);
00066 goto null;
00067 }
00068 if (!is_const && res->alloced_length() >= res->length()+res2->length())
00069 {
00070 res->append(*res2);
00071 }
00072 else if (str->alloced_length() >= res->length()+res2->length())
00073 {
00074 if (str == res2)
00075 str->replace(0,0,*res);
00076 else
00077 {
00078 str->copy(*res);
00079 str->append(*res2);
00080 }
00081 res= str;
00082 use_as_buff= &tmp_value;
00083 }
00084 else if (res == &tmp_value)
00085 {
00086 if (res->append(*res2))
00087 goto null;
00088 }
00089 else if (res2 == &tmp_value)
00090 {
00091 if (tmp_value.replace(0,0,*res))
00092 goto null;
00093 res= &tmp_value;
00094 use_as_buff=str;
00095 }
00096 else if (tmp_value.is_alloced() && res2->ptr() >= tmp_value.ptr() &&
00097 res2->ptr() <= tmp_value.ptr() + tmp_value.alloced_length())
00098 {
00099
00100
00101
00102
00103
00104
00105 tmp_value.length((uint32_t) (res2->ptr() - tmp_value.ptr()) +
00106 res2->length());
00107
00108 if (tmp_value.replace(0,(uint32_t) (res2->ptr() - tmp_value.ptr()),
00109 *res))
00110 goto null;
00111 res= &tmp_value;
00112 use_as_buff=str;
00113 }
00114 else
00115 {
00116
00117
00118
00119
00120
00121
00122
00123
00124 size_t concat_len= res->length() + res2->length();
00125
00126 if (tmp_value.alloced_length() < concat_len)
00127 {
00128 if (tmp_value.alloced_length() == 0)
00129 {
00130 if (tmp_value.alloc(concat_len))
00131 goto null;
00132 }
00133 else
00134 {
00135 uint32_t new_len= max(tmp_value.alloced_length() * 2, concat_len);
00136
00137 if (tmp_value.realloc(new_len))
00138 goto null;
00139 }
00140 }
00141
00142 if (tmp_value.copy(*res) || tmp_value.append(*res2))
00143 goto null;
00144
00145 res= &tmp_value;
00146 use_as_buff=str;
00147 }
00148 is_const= 0;
00149 }
00150 }
00151 res->set_charset(collation.collation);
00152 return res;
00153
00154 null:
00155 null_value=1;
00156 return 0;
00157 }
00158
00159
00160 void Item_func_concat::fix_length_and_dec()
00161 {
00162 uint64_t max_result_length= 0;
00163
00164 if (agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV, 1))
00165 return;
00166
00167 for (uint32_t i=0 ; i < arg_count ; i++)
00168 {
00169 if (args[i]->collation.collation->mbmaxlen != collation.collation->mbmaxlen)
00170 max_result_length+= (args[i]->max_length /
00171 args[i]->collation.collation->mbmaxlen) *
00172 collation.collation->mbmaxlen;
00173 else
00174 max_result_length+= args[i]->max_length;
00175 }
00176
00177 if (max_result_length >= MAX_BLOB_WIDTH)
00178 {
00179 max_result_length= MAX_BLOB_WIDTH;
00180 maybe_null= 1;
00181 }
00182 max_length= (ulong) max_result_length;
00183 }
00184
00185
00191 String *Item_func_concat_ws::val_str(String *str)
00192 {
00193 assert(fixed == 1);
00194 char tmp_str_buff[10];
00195 String tmp_sep_str(tmp_str_buff, sizeof(tmp_str_buff),default_charset_info),
00196 *sep_str, *res, *res2,*use_as_buff;
00197 uint32_t i;
00198
00199 null_value=0;
00200 if (!(sep_str= args[0]->val_str(&tmp_sep_str)))
00201 goto null;
00202
00203 use_as_buff= &tmp_value;
00204 str->length(0);
00205 res=str;
00206
00207
00208
00209 for (i=1; i < arg_count; i++)
00210 if ((res= args[i]->val_str(str)))
00211 break;
00212 if (i == arg_count)
00213 return &my_empty_string;
00214
00215 for (i++; i < arg_count ; i++)
00216 {
00217 if (!(res2= args[i]->val_str(use_as_buff)))
00218 continue;
00219
00220 if (res->length() + sep_str->length() + res2->length() >
00221 session.variables.max_allowed_packet)
00222 {
00223 push_warning_printf(&session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
00224 ER_WARN_ALLOWED_PACKET_OVERFLOWED,
00225 ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED), func_name(),
00226 session.variables.max_allowed_packet);
00227 goto null;
00228 }
00229 if (res->alloced_length() >=
00230 res->length() + sep_str->length() + res2->length())
00231 {
00232 res->append(*sep_str);
00233 res->append(*res2);
00234 }
00235 else if (str->alloced_length() >=
00236 res->length() + sep_str->length() + res2->length())
00237 {
00238
00239 if (str == res2)
00240 {
00241 str->replace(0,0,*sep_str);
00242 str->replace(0,0,*res);
00243 }
00244 else
00245 {
00246 str->copy(*res);
00247 str->append(*sep_str);
00248 str->append(*res2);
00249 }
00250 res=str;
00251 use_as_buff= &tmp_value;
00252 }
00253 else if (res == &tmp_value)
00254 {
00255 if (res->append(*sep_str) || res->append(*res2))
00256 goto null;
00257 }
00258 else if (res2 == &tmp_value)
00259 {
00260 if (tmp_value.replace(0,0,*sep_str) || tmp_value.replace(0,0,*res))
00261 goto null;
00262 res= &tmp_value;
00263 use_as_buff=str;
00264 }
00265 else if (tmp_value.is_alloced() && res2->ptr() >= tmp_value.ptr() &&
00266 res2->ptr() < tmp_value.ptr() + tmp_value.alloced_length())
00267 {
00268
00269
00270
00271
00272
00273
00274 tmp_value.length((uint32_t) (res2->ptr() - tmp_value.ptr()) +
00275 res2->length());
00276
00277 if (tmp_value.replace(0,(uint32_t) (res2->ptr() - tmp_value.ptr()),
00278 *res) ||
00279 tmp_value.replace(res->length(),0, *sep_str))
00280 goto null;
00281 res= &tmp_value;
00282 use_as_buff=str;
00283 }
00284 else
00285 {
00286
00287
00288
00289
00290
00291
00292
00293
00294 size_t concat_len= res->length() + sep_str->length() + res2->length();
00295
00296 if (tmp_value.alloced_length() < concat_len)
00297 {
00298 if (tmp_value.alloced_length() == 0)
00299 {
00300 if (tmp_value.alloc(concat_len))
00301 goto null;
00302 }
00303 else
00304 {
00305 uint32_t new_len= max(tmp_value.alloced_length() * 2, concat_len);
00306
00307 if (tmp_value.realloc(new_len))
00308 goto null;
00309 }
00310 }
00311
00312 if (tmp_value.copy(*res) ||
00313 tmp_value.append(*sep_str) ||
00314 tmp_value.append(*res2))
00315 goto null;
00316 res= &tmp_value;
00317 use_as_buff=str;
00318 }
00319 }
00320 res->set_charset(collation.collation);
00321 return res;
00322
00323 null:
00324 null_value=1;
00325 return 0;
00326 }
00327
00328
00329 void Item_func_concat_ws::fix_length_and_dec()
00330 {
00331 uint64_t max_result_length;
00332
00333 if (agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV, 1))
00334 return;
00335
00336
00337
00338
00339
00340
00341 max_result_length= (uint64_t) args[0]->max_length * (arg_count - 2);
00342 for (uint32_t i=1 ; i < arg_count ; i++)
00343 max_result_length+=args[i]->max_length;
00344
00345 if (max_result_length >= MAX_BLOB_WIDTH)
00346 {
00347 max_result_length= MAX_BLOB_WIDTH;
00348 maybe_null= 1;
00349 }
00350 max_length= (ulong) max_result_length;
00351 }
00352
00353 }