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