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/pad.h>
00023 #include <drizzled/error.h>
00024 #include <drizzled/function/str/alloc_buffer.h>
00025 #include <drizzled/session.h>
00026
00027 namespace drizzled
00028 {
00029
00030 void Item_func_rpad::fix_length_and_dec()
00031 {
00032
00033 if (agg_arg_charsets(collation, &args[0], 2, MY_COLL_ALLOW_CONV, 2))
00034 return;
00035 if (args[1]->const_item())
00036 {
00037 uint64_t length= 0;
00038
00039 if (collation.collation->mbmaxlen > 0)
00040 {
00041 uint64_t temp= (uint64_t) args[1]->val_int();
00042
00043
00044
00045 if (temp > INT32_MAX)
00046 temp = INT32_MAX;
00047
00048 length= temp * collation.collation->mbmaxlen;
00049 }
00050
00051 if (length >= MAX_BLOB_WIDTH)
00052 {
00053 length= MAX_BLOB_WIDTH;
00054 maybe_null= 1;
00055 }
00056 max_length= (ulong) length;
00057 }
00058 else
00059 {
00060 max_length= MAX_BLOB_WIDTH;
00061 maybe_null= 1;
00062 }
00063 }
00064
00065
00066 String *Item_func_rpad::val_str(String *str)
00067 {
00068 assert(fixed == 1);
00069 uint32_t res_byte_length,res_char_length,pad_char_length,pad_byte_length;
00070 char *to;
00071 const char *ptr_pad;
00072
00073 int64_t count= args[1]->val_int();
00074 int64_t byte_count;
00075 String *res= args[0]->val_str(str);
00076 String *rpad= args[2]->val_str(&rpad_str);
00077
00078 if (!res || args[1]->null_value || !rpad ||
00079 ((count < 0) && !args[1]->unsigned_flag))
00080 goto err;
00081 null_value=0;
00082
00083
00084 if ((uint64_t) count > INT32_MAX)
00085 count= INT32_MAX;
00086 if (count <= (res_char_length= res->numchars()))
00087 {
00088 res->length(res->charpos((int) count));
00089 return (res);
00090 }
00091 pad_char_length= rpad->numchars();
00092
00093 byte_count= count * collation.collation->mbmaxlen;
00094 if ((uint64_t) byte_count > session.variables.max_allowed_packet)
00095 {
00096 push_warning_printf(&session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
00097 ER_WARN_ALLOWED_PACKET_OVERFLOWED,
00098 ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED),
00099 func_name(), session.variables.max_allowed_packet);
00100 goto err;
00101 }
00102 if (args[2]->null_value || !pad_char_length)
00103 goto err;
00104 res_byte_length= res->length();
00105 if (!(res= alloc_buffer(res,str,&tmp_value, (ulong) byte_count)))
00106 goto err;
00107
00108 to= (char*) res->ptr()+res_byte_length;
00109 ptr_pad=rpad->ptr();
00110 pad_byte_length= rpad->length();
00111 count-= res_char_length;
00112 for ( ; (uint32_t) count > pad_char_length; count-= pad_char_length)
00113 {
00114 memcpy(to,ptr_pad,pad_byte_length);
00115 to+= pad_byte_length;
00116 }
00117 if (count)
00118 {
00119 pad_byte_length= rpad->charpos((int) count);
00120 memcpy(to,ptr_pad,(size_t) pad_byte_length);
00121 to+= pad_byte_length;
00122 }
00123 res->length(to- (char*) res->ptr());
00124 return (res);
00125
00126 err:
00127 null_value=1;
00128 return 0;
00129 }
00130
00131
00132 void Item_func_lpad::fix_length_and_dec()
00133 {
00134
00135 if (agg_arg_charsets(collation, &args[0], 2, MY_COLL_ALLOW_CONV, 2))
00136 return;
00137
00138 if (args[1]->const_item())
00139 {
00140 uint64_t length= 0;
00141
00142 if (collation.collation->mbmaxlen > 0)
00143 {
00144 uint64_t temp= (uint64_t) args[1]->val_int();
00145
00146
00147
00148 if (temp > INT32_MAX)
00149 temp= INT32_MAX;
00150
00151 length= temp * collation.collation->mbmaxlen;
00152 }
00153
00154 if (length >= MAX_BLOB_WIDTH)
00155 {
00156 length= MAX_BLOB_WIDTH;
00157 maybe_null= 1;
00158 }
00159 max_length= (ulong) length;
00160 }
00161 else
00162 {
00163 max_length= MAX_BLOB_WIDTH;
00164 maybe_null= 1;
00165 }
00166 }
00167
00168
00169 String *Item_func_lpad::val_str(String *str)
00170 {
00171 assert(fixed == 1);
00172 uint32_t res_char_length,pad_char_length;
00173
00174 int64_t count= args[1]->val_int();
00175 int64_t byte_count;
00176 String *res= args[0]->val_str(&tmp_value);
00177 String *pad= args[2]->val_str(&lpad_str);
00178
00179 if (!res || args[1]->null_value || !pad ||
00180 ((count < 0) && !args[1]->unsigned_flag))
00181 goto err;
00182 null_value=0;
00183
00184
00185 if ((uint64_t) count > INT32_MAX)
00186 count= INT32_MAX;
00187
00188 res_char_length= res->numchars();
00189
00190 if (count <= res_char_length)
00191 {
00192 res->length(res->charpos((int) count));
00193 return res;
00194 }
00195
00196 pad_char_length= pad->numchars();
00197 byte_count= count * collation.collation->mbmaxlen;
00198
00199 if ((uint64_t) byte_count > session.variables.max_allowed_packet)
00200 {
00201 push_warning_printf(&session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
00202 ER_WARN_ALLOWED_PACKET_OVERFLOWED,
00203 ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED),
00204 func_name(), session.variables.max_allowed_packet);
00205 goto err;
00206 }
00207
00208 if (args[2]->null_value || !pad_char_length ||
00209 str->alloc((uint32_t) byte_count))
00210 goto err;
00211
00212 str->length(0);
00213 str->set_charset(collation.collation);
00214 count-= res_char_length;
00215 while (count >= pad_char_length)
00216 {
00217 str->append(*pad);
00218 count-= pad_char_length;
00219 }
00220 if (count > 0)
00221 str->append(pad->ptr(), pad->charpos((int) count), collation.collation);
00222
00223 str->append(*res);
00224 null_value= 0;
00225 return str;
00226
00227 err:
00228 null_value= 1;
00229 return 0;
00230 }
00231
00232 }