diff options
Diffstat (limited to 'sql/item_strfunc.h')
-rw-r--r-- | sql/item_strfunc.h | 173 |
1 files changed, 155 insertions, 18 deletions
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index f469b60c344..f9b6f96fb9a 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -64,8 +64,7 @@ public: longlong val_int(); double val_real(); my_decimal *val_decimal(my_decimal *); - enum Item_result result_type () const { return STRING_RESULT; } - enum_field_types field_type() const { return string_field_type(); } + const Type_handler *type_handler() const { return string_type_handler(); } void left_right_max_length(); bool fix_fields(THD *thd, Item **ref); void update_null_value() @@ -244,7 +243,40 @@ public: class Item_func_concat :public Item_str_func { +protected: String tmp_value; + /* + Get the i-th argument val_str() and its const_item() + @param i[IN] - The argument number + @param str[IN] - The buffer for val_str() + @param is_const[IN/OUT] - If args[i]->val_str() returned a non-null value, + then args[i]->const_item() is returned here. + Otherwise, the value of is_const is not touched. + @retval - the result of val_str(). + */ + String *arg_val_str(uint i, String *str, bool *is_const) + { + String *res= args[i]->val_str(str); + if (res) + *is_const= args[i]->const_item(); + return res; + } + /* + Append a non-NULL value to the result. + @param [IN] thd - The current thread. + @param [IN/OUT] res - The current val_str() return value. + @param [IN] res_is_const - If "false", then OK to append to "res" + @param [IN/OUT] str - The val_str() argument. + @param [IN] res2 - The value to be appended. + @param [IN/OUT] use_as_buff - Which buffer to use for the next argument: + args[next_arg]->val_str(use_as_buff) + */ + String *append_value(THD *thd, + String *res, + bool res_is_const, + String *str, + String **use_as_buff, + const String *res2); public: Item_func_concat(THD *thd, List<Item> &list): Item_str_func(thd, list) {} Item_func_concat(THD *thd, Item *a, Item *b): Item_str_func(thd, a, b) {} @@ -255,6 +287,29 @@ public: { return get_item_copy<Item_func_concat>(thd, mem_root, this); } }; + +/* + This class handles the || operator in sql_mode=ORACLE. + Unlike the traditional MariaDB concat(), it treats NULL arguments as ''. +*/ +class Item_func_concat_operator_oracle :public Item_func_concat +{ +public: + Item_func_concat_operator_oracle(THD *thd, List<Item> &list) + :Item_func_concat(thd, list) + { } + Item_func_concat_operator_oracle(THD *thd, Item *a, Item *b) + :Item_func_concat(thd, a, b) + { } + String *val_str(String *); + const char *func_name() const { return "concat_operator_oracle"; } + Item *get_copy(THD *thd, MEM_ROOT *mem_root) + { + return get_item_copy<Item_func_concat_operator_oracle>(thd, mem_root, this); + } +}; + + class Item_func_decode_histogram :public Item_str_func { public: @@ -304,14 +359,28 @@ class Item_func_replace :public Item_str_func public: Item_func_replace(THD *thd, Item *org, Item *find, Item *replace): Item_str_func(thd, org, find, replace) {} - String *val_str(String *); + String *val_str(String *to) { return val_str_internal(to, NULL); }; void fix_length_and_dec(); + String *val_str_internal(String *str, String *empty_string_for_null); const char *func_name() const { return "replace"; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_replace>(thd, mem_root, this); } }; +class Item_func_replace_oracle :public Item_func_replace +{ + String tmp_emtpystr; +public: + Item_func_replace_oracle(THD *thd, Item *org, Item *find, Item *replace): + Item_func_replace(thd, org, find, replace) {} + String *val_str(String *to) { return val_str_internal(to, &tmp_emtpystr); }; + const char *func_name() const { return "replace_oracle"; } + Item *get_copy(THD *thd, MEM_ROOT *mem_root) + { return get_item_copy<Item_func_replace_oracle>(thd, mem_root, this); } +}; + + class Item_func_regexp_replace :public Item_str_func { Regexp_processor_pcre re; @@ -717,6 +786,27 @@ public: }; +class Item_func_sqlerrm :public Item_func_sysconst +{ +public: + Item_func_sqlerrm(THD *thd): Item_func_sysconst(thd) {} + String *val_str(String *); + const char *func_name() const { return "SQLERRM"; } + const char *fully_qualified_func_name() const { return "SQLERRM"; } + void print(String *str, enum_query_type query_type) + { + str->append(func_name()); + } + void fix_length_and_dec() + { + max_length= 512 * system_charset_info->mbmaxlen; + null_value= maybe_null= false; + } + Item *get_copy(THD *thd, MEM_ROOT *mem_root) + { return get_item_copy<Item_func_sqlerrm>(thd, mem_root, this); } +}; + + class Item_func_user :public Item_func_sysconst { protected: @@ -867,7 +957,11 @@ public: Item_func_char(THD *thd, List<Item> &list, CHARSET_INFO *cs): Item_str_func(thd, list) { collation.set(cs); } + Item_func_char(THD *thd, Item *arg1, CHARSET_INFO *cs): + Item_str_func(thd, arg1) + { collation.set(cs); } String *val_str(String *); + void append_char(String * str, int32 num); void fix_length_and_dec() { max_length= arg_count * 4; @@ -877,6 +971,20 @@ public: { return get_item_copy<Item_func_char>(thd, mem_root, this); } }; +class Item_func_chr :public Item_func_char +{ +public: + Item_func_chr(THD *thd, Item *arg1, CHARSET_INFO *cs): + Item_func_char(thd, arg1, cs) {} + String *val_str(String *); + void fix_length_and_dec() + { + max_length= 4; + } + const char *func_name() const { return "chr"; } + Item *get_copy(THD *thd, MEM_ROOT *mem_root) + { return get_item_copy<Item_func_chr>(thd, mem_root, this); } +}; class Item_func_repeat :public Item_str_func { @@ -922,28 +1030,41 @@ public: }; -class Item_func_rpad :public Item_str_func +class Item_func_pad: public Item_str_func { - String tmp_value, rpad_str; +protected: + String tmp_value, pad_str; public: - Item_func_rpad(THD *thd, Item *arg1, Item *arg2, Item *arg3): + Item_func_pad(THD *thd, Item *arg1, Item *arg2, Item *arg3): Item_str_func(thd, arg1, arg2, arg3) {} - String *val_str(String *); + Item_func_pad(THD *thd, Item *arg1, Item *arg2): + Item_str_func(thd, arg1, arg2) {} void fix_length_and_dec(); +}; + + +class Item_func_rpad :public Item_func_pad +{ +public: + Item_func_rpad(THD *thd, Item *arg1, Item *arg2, Item *arg3): + Item_func_pad(thd, arg1, arg2, arg3) {} + Item_func_rpad(THD *thd, Item *arg1, Item *arg2): + Item_func_pad(thd, arg1, arg2) {} + String *val_str(String *); const char *func_name() const { return "rpad"; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_rpad>(thd, mem_root, this); } }; -class Item_func_lpad :public Item_str_func +class Item_func_lpad :public Item_func_pad { - String tmp_value, lpad_str; public: Item_func_lpad(THD *thd, Item *arg1, Item *arg2, Item *arg3): - Item_str_func(thd, arg1, arg2, arg3) {} + Item_func_pad(thd, arg1, arg2, arg3) {} + Item_func_lpad(THD *thd, Item *arg1, Item *arg2): + Item_func_pad(thd, arg1, arg2) {} String *val_str(String *); - void fix_length_and_dec(); const char *func_name() const { return "lpad"; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_lpad>(thd, mem_root, this); } @@ -970,17 +1091,33 @@ public: class Item_func_hex :public Item_str_ascii_checksum_func { +protected: String tmp_value; + /* + Calling arg[0]->type_handler() can be expensive on every row. + It's a virtual method, and in case if args[0] is a complex Item, + its type_handler() can call more virtual methods. + So let's cache it during fix_length_and_dec(). + */ + const Type_handler *m_arg0_type_handler; public: Item_func_hex(THD *thd, Item *a): - Item_str_ascii_checksum_func(thd, a) {} + Item_str_ascii_checksum_func(thd, a), m_arg0_type_handler(NULL) {} const char *func_name() const { return "hex"; } - String *val_str_ascii(String *); + String *val_str_ascii_from_val_int(String *str); + String *val_str_ascii_from_val_real(String *str); + String *val_str_ascii_from_val_str(String *str); + String *val_str_ascii(String *str) + { + DBUG_ASSERT(fixed); + return m_arg0_type_handler->Item_func_hex_val_str_ascii(this, str); + } void fix_length_and_dec() { - collation.set(default_charset()); + collation.set(default_charset(), DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII); decimals=0; fix_char_length(args[0]->max_length * 2); + m_arg0_type_handler= args[0]->type_handler(); } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_func_hex>(thd, mem_root, this); } @@ -1317,11 +1454,11 @@ public: { return get_item_copy<Item_func_weight_string>(thd, mem_root, this); } }; -class Item_func_crc32 :public Item_int_func +class Item_func_crc32 :public Item_long_func { String value; public: - Item_func_crc32(THD *thd, Item *a): Item_int_func(thd, a) + Item_func_crc32(THD *thd, Item *a): Item_long_func(thd, a) { unsigned_flag= 1; } const char *func_name() const { return "crc32"; } void fix_length_and_dec() { max_length=10; } @@ -1330,11 +1467,11 @@ public: { return get_item_copy<Item_func_crc32>(thd, mem_root, this); } }; -class Item_func_uncompressed_length : public Item_int_func +class Item_func_uncompressed_length : public Item_long_func { String value; public: - Item_func_uncompressed_length(THD *thd, Item *a): Item_int_func(thd, a) {} + Item_func_uncompressed_length(THD *thd, Item *a): Item_long_func(thd, a) {} const char *func_name() const{return "uncompressed_length";} void fix_length_and_dec() { max_length=10; maybe_null= true; } longlong val_int(); |