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 #include <drizzled/system_variables.h>
00026
00027 #include <algorithm>
00028
00029 using namespace std;
00030
00031 namespace drizzled {
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 res->append(*res2);
00087 }
00088 else if (res2 == &tmp_value)
00089 {
00090 tmp_value.replace(0,0,*res);
00091 res= &tmp_value;
00092 use_as_buff=str;
00093 }
00094 else if (tmp_value.is_alloced() && res2->ptr() >= tmp_value.ptr() &&
00095 res2->ptr() <= tmp_value.ptr() + tmp_value.alloced_length())
00096 {
00097
00098
00099
00100
00101
00102
00103 tmp_value.length((uint32_t) (res2->ptr() - tmp_value.ptr()) +
00104 res2->length());
00105
00106 tmp_value.replace(0,(uint32_t) (res2->ptr() - tmp_value.ptr()), *res);
00107 res= &tmp_value;
00108 use_as_buff=str;
00109 }
00110 else
00111 {
00112
00113
00114
00115
00116
00117
00118
00119
00120 size_t concat_len= res->length() + res2->length();
00121
00122 if (tmp_value.alloced_length() < concat_len)
00123 {
00124 if (tmp_value.alloced_length() == 0)
00125 {
00126 tmp_value.alloc(concat_len);
00127 }
00128 else
00129 {
00130 uint32_t new_len= max(tmp_value.alloced_length() * 2, concat_len);
00131
00132 tmp_value.realloc(new_len);
00133 }
00134 }
00135
00136 tmp_value.copy(*res);
00137 tmp_value.append(*res2);
00138
00139 res= &tmp_value;
00140 use_as_buff=str;
00141 }
00142 is_const= 0;
00143 }
00144 }
00145 res->set_charset(collation.collation);
00146 return res;
00147
00148 null:
00149 null_value=1;
00150 return 0;
00151 }
00152
00153
00154 void Item_func_concat::fix_length_and_dec()
00155 {
00156 uint64_t max_result_length= 0;
00157
00158 if (agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV, 1))
00159 return;
00160
00161 for (uint32_t i=0 ; i < arg_count ; i++)
00162 {
00163 if (args[i]->collation.collation->mbmaxlen != collation.collation->mbmaxlen)
00164 max_result_length+= (args[i]->max_length /
00165 args[i]->collation.collation->mbmaxlen) *
00166 collation.collation->mbmaxlen;
00167 else
00168 max_result_length+= args[i]->max_length;
00169 }
00170
00171 if (max_result_length >= MAX_BLOB_WIDTH)
00172 {
00173 max_result_length= MAX_BLOB_WIDTH;
00174 maybe_null= 1;
00175 }
00176 max_length= (ulong) max_result_length;
00177 }
00178
00179
00185 String *Item_func_concat_ws::val_str(String *str)
00186 {
00187 assert(fixed == 1);
00188 char tmp_str_buff[10];
00189 String tmp_sep_str(tmp_str_buff, sizeof(tmp_str_buff),default_charset_info),
00190 *sep_str, *res, *res2,*use_as_buff;
00191 uint32_t i;
00192
00193 null_value=0;
00194 if (!(sep_str= args[0]->val_str(&tmp_sep_str)))
00195 goto null;
00196
00197 use_as_buff= &tmp_value;
00198 str->length(0);
00199 res=str;
00200
00201
00202
00203 for (i=1; i < arg_count; i++)
00204 if ((res= args[i]->val_str(str)))
00205 break;
00206 if (i == arg_count)
00207 return &my_empty_string;
00208
00209 for (i++; i < arg_count ; i++)
00210 {
00211 if (!(res2= args[i]->val_str(use_as_buff)))
00212 continue;
00213
00214 if (res->length() + sep_str->length() + res2->length() >
00215 session.variables.max_allowed_packet)
00216 {
00217 push_warning_printf(&session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
00218 ER_WARN_ALLOWED_PACKET_OVERFLOWED,
00219 ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED), func_name(),
00220 session.variables.max_allowed_packet);
00221 goto null;
00222 }
00223 if (res->alloced_length() >=
00224 res->length() + sep_str->length() + res2->length())
00225 {
00226 res->append(*sep_str);
00227 res->append(*res2);
00228 }
00229 else if (str->alloced_length() >=
00230 res->length() + sep_str->length() + res2->length())
00231 {
00232
00233 if (str == res2)
00234 {
00235 str->replace(0,0,*sep_str);
00236 str->replace(0,0,*res);
00237 }
00238 else
00239 {
00240 str->copy(*res);
00241 str->append(*sep_str);
00242 str->append(*res2);
00243 }
00244 res=str;
00245 use_as_buff= &tmp_value;
00246 }
00247 else if (res == &tmp_value)
00248 {
00249 res->append(*sep_str);
00250 res->append(*res2);
00251 }
00252 else if (res2 == &tmp_value)
00253 {
00254 tmp_value.replace(0,0,*sep_str);
00255 tmp_value.replace(0,0,*res);
00256 res= &tmp_value;
00257 use_as_buff=str;
00258 }
00259 else if (tmp_value.is_alloced() && res2->ptr() >= tmp_value.ptr() &&
00260 res2->ptr() < tmp_value.ptr() + tmp_value.alloced_length())
00261 {
00262
00263
00264
00265
00266
00267
00268 tmp_value.length((uint32_t) (res2->ptr() - tmp_value.ptr()) +
00269 res2->length());
00270
00271 tmp_value.replace(0,(uint32_t) (res2->ptr() - tmp_value.ptr()), *res);
00272 tmp_value.replace(res->length(),0, *sep_str);
00273 res= &tmp_value;
00274 use_as_buff=str;
00275 }
00276 else
00277 {
00278
00279
00280
00281
00282
00283
00284
00285
00286 size_t concat_len= res->length() + sep_str->length() + res2->length();
00287
00288 if (tmp_value.alloced_length() < concat_len)
00289 {
00290 if (tmp_value.alloced_length() == 0)
00291 {
00292 tmp_value.alloc(concat_len);
00293 }
00294 else
00295 {
00296 uint32_t new_len= max(tmp_value.alloced_length() * 2, concat_len);
00297
00298 tmp_value.realloc(new_len);
00299 }
00300 }
00301
00302 tmp_value.copy(*res);
00303 tmp_value.append(*sep_str);
00304 tmp_value.append(*res2);
00305 res= &tmp_value;
00306 use_as_buff=str;
00307 }
00308 }
00309 res->set_charset(collation.collation);
00310 return res;
00311
00312 null:
00313 null_value=1;
00314 return 0;
00315 }
00316
00317
00318 void Item_func_concat_ws::fix_length_and_dec()
00319 {
00320 uint64_t max_result_length;
00321
00322 if (agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV, 1))
00323 return;
00324
00325
00326
00327
00328
00329
00330 max_result_length= (uint64_t) args[0]->max_length * (arg_count - 2);
00331 for (uint32_t i=1 ; i < arg_count ; i++)
00332 max_result_length+=args[i]->max_length;
00333
00334 if (max_result_length >= MAX_BLOB_WIDTH)
00335 {
00336 max_result_length= MAX_BLOB_WIDTH;
00337 maybe_null= 1;
00338 }
00339 max_length= (ulong) max_result_length;
00340 }
00341
00342 }