sql/item_strfunc.h (1,236 lines of code) (raw):

/* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* This file defines all string functions */ #ifndef ITEM_STRFUNC_INCLUDED #define ITEM_STRFUNC_INCLUDED #include <stddef.h> #include <sys/types.h> #include <algorithm> #include "control_events.h" #include "crypt_genhash_impl.h" // CRYPT_MAX_PASSWORD_SIZE #include "enum_query_type.h" #include "field.h" #include "item.h" #include "item_cmpfunc.h" // Item_bool_func #include "item_func.h" // Item_func #include "lex_string.h" #include "m_ctype.h" #include "my_dbug.h" #include "my_decimal.h" #include "my_inttypes.h" #include "my_table_map.h" #include "my_time.h" #include "mysql_com.h" #include "parse_tree_node_base.h" #include "sql_const.h" #include "sql_string.h" #include "sql_udf.h" #include "system_variables.h" #include "table.h" class MY_LOCALE; class PT_item_list; class THD; template <class T> class List; CHARSET_INFO * mysqld_collation_get_by_name(const char *name, CHARSET_INFO *name_cs= system_charset_info); class Item_str_func :public Item_func { typedef Item_func super; public: Item_str_func() :Item_func() { set_data_type_string_init(); } explicit Item_str_func(const POS &pos) :super(pos) { set_data_type_string_init(); } Item_str_func(Item *a) :Item_func(a) { set_data_type_string_init(); } Item_str_func(const POS &pos, Item *a) :Item_func(pos, a) { set_data_type_string_init(); } Item_str_func(Item *a,Item *b) :Item_func(a,b) { set_data_type_string_init(); } Item_str_func(const POS &pos, Item *a,Item *b) :Item_func(pos, a,b) { set_data_type_string_init(); } Item_str_func(Item *a, Item *b, Item *c) :Item_func(a, b, c) { set_data_type_string_init(); } Item_str_func(const POS &pos, Item *a, Item *b, Item *c) :Item_func(pos, a,b,c) { set_data_type_string_init(); } Item_str_func(Item *a, Item *b, Item *c, Item *d) :Item_func(a, b, c, d) { set_data_type_string_init(); } Item_str_func(const POS &pos, Item *a, Item *b, Item *c, Item *d) :Item_func(pos, a,b,c,d) { set_data_type_string_init(); } Item_str_func(Item *a, Item *b, Item *c, Item *d, Item* e) :Item_func(a, b, c, d, e) { set_data_type_string_init(); } Item_str_func(const POS &pos, Item *a, Item *b, Item *c, Item *d, Item* e) :Item_func(pos, a, b, c, d, e) { set_data_type_string_init(); } Item_str_func(List<Item> &list) :Item_func(list) { set_data_type_string_init(); } Item_str_func(const POS &pos, PT_item_list *opt_list) :Item_func(pos, opt_list) { set_data_type_string_init(); } longlong val_int() override; double val_real() override; my_decimal *val_decimal(my_decimal *) override; bool get_date(MYSQL_TIME *ltime, my_time_flags_t fuzzydate) override { return get_date_from_string(ltime, fuzzydate); } bool get_time(MYSQL_TIME *ltime) override { return get_time_from_string(ltime); } enum Item_result result_type() const override { return STRING_RESULT; } void left_right_max_length(); bool fix_fields(THD *thd, Item **ref) override; String *val_str_from_val_str_ascii(String *str, String *str2); }; /* Functions that return values with ASCII repertoire */ class Item_str_ascii_func : public Item_str_func { String ascii_buf; public: Item_str_ascii_func() :Item_str_func() { collation.set_repertoire(MY_REPERTOIRE_ASCII); } Item_str_ascii_func(Item *a) :Item_str_func(a) { collation.set_repertoire(MY_REPERTOIRE_ASCII); } Item_str_ascii_func(const POS &pos, Item *a) :Item_str_func(pos, a) { collation.set_repertoire(MY_REPERTOIRE_ASCII); } Item_str_ascii_func(Item *a,Item *b) :Item_str_func(a,b) { collation.set_repertoire(MY_REPERTOIRE_ASCII); } Item_str_ascii_func(const POS &pos, Item *a,Item *b) :Item_str_func(pos, a,b) { collation.set_repertoire(MY_REPERTOIRE_ASCII); } Item_str_ascii_func(Item *a,Item *b,Item *c) :Item_str_func(a,b,c) { collation.set_repertoire(MY_REPERTOIRE_ASCII); } Item_str_ascii_func(const POS &pos, Item *a,Item *b,Item *c) :Item_str_func(pos, a,b,c) { collation.set_repertoire(MY_REPERTOIRE_ASCII); } String *val_str(String *str) override { return val_str_from_val_str_ascii(str, &ascii_buf); } virtual String *val_str_ascii(String *) override= 0; }; class Item_func_md5 final : public Item_str_ascii_func { String tmp_value; public: Item_func_md5(const POS &pos, Item *a) :Item_str_ascii_func(pos, a) {} String *val_str_ascii(String *) override; bool resolve_type(THD *thd) override; const char *func_name() const override { return "md5"; } }; class Item_func_sha :public Item_str_ascii_func { public: Item_func_sha(const POS &pos, Item *a) :Item_str_ascii_func(pos, a) {} String *val_str_ascii(String *) override; bool resolve_type(THD *thd) override; const char *func_name() const override { return "sha"; } }; class Item_func_sha2 :public Item_str_ascii_func { public: Item_func_sha2(const POS &pos, Item *a, Item *b) :Item_str_ascii_func(pos, a, b) {} String *val_str_ascii(String *) override; bool resolve_type(THD *thd) override; const char *func_name() const override { return "sha2"; } }; class Item_func_to_base64 final : public Item_str_ascii_func { String tmp_value; public: Item_func_to_base64(const POS &pos, Item *a) :Item_str_ascii_func(pos, a) {} String *val_str_ascii(String *) override; bool resolve_type(THD *) override; const char *func_name() const override { return "to_base64"; } }; class Item_func_from_base64 final :public Item_str_func { String tmp_value; public: Item_func_from_base64(const POS &pos, Item *a) :Item_str_func(pos, a) {} String *val_str(String *) override; bool resolve_type(THD *thd) override; const char *func_name() const override { return "from_base64"; } }; class Item_func_aes_encrypt final : public Item_str_func { String tmp_value; typedef Item_str_func super; public: Item_func_aes_encrypt(const POS &pos, Item *a, Item *b) :Item_str_func(pos, a, b) {} Item_func_aes_encrypt(const POS &pos, Item *a, Item *b, Item *c) :Item_str_func(pos, a, b, c) {} bool itemize(Parse_context *pc, Item **res) override; String *val_str(String *) override; bool resolve_type(THD *) override; const char *func_name() const override { return "aes_encrypt"; } }; class Item_func_aes_decrypt :public Item_str_func { typedef Item_str_func super; public: Item_func_aes_decrypt(const POS &pos, Item *a, Item *b) :Item_str_func(pos, a, b) {} Item_func_aes_decrypt(const POS &pos, Item *a, Item *b, Item *c) :Item_str_func(pos, a, b, c) {} bool itemize(Parse_context *pc, Item **res) override; String *val_str(String *) override; bool resolve_type(THD *thd) override; const char *func_name() const override { return "aes_decrypt"; } }; class Item_func_random_bytes : public Item_str_func { typedef Item_str_func super; /** limitation from the SSL library */ static const ulonglong MAX_RANDOM_BYTES_BUFFER; public: Item_func_random_bytes(const POS &pos, Item *a) : Item_str_func(pos, a) {} bool itemize(Parse_context *pc, Item **res) override; bool resolve_type(THD *thd) override; String *val_str(String *a) override; const char *func_name() const override { return "random_bytes"; } }; class Item_func_concat :public Item_str_func { String tmp_value { "", 0, collation.collation }; // Initialize to empty public: Item_func_concat(const POS &pos, PT_item_list *opt_list) : Item_str_func(pos, opt_list) {} Item_func_concat(Item *a, Item *b) : Item_str_func(a,b) {} Item_func_concat(const POS &pos, Item *a,Item *b) : Item_str_func(pos, a,b) {} String *val_str(String *) override; bool resolve_type(THD *thd) override; const char *func_name() const override { return "concat"; } }; class Item_func_concat_ws :public Item_str_func { String tmp_value { "", 0, collation.collation }; // Initialize to empty public: Item_func_concat_ws(List<Item> &list) : Item_str_func(list) {} Item_func_concat_ws(const POS &pos, PT_item_list *opt_list) : Item_str_func(pos, opt_list) {} String *val_str(String *) override; bool resolve_type(THD *thd) override; const char *func_name() const override { return "concat_ws"; } table_map not_null_tables() const override { return 0; } }; class Item_func_reverse :public Item_str_func { String tmp_value; public: Item_func_reverse(Item *a) :Item_str_func(a) {} Item_func_reverse(const POS &pos, Item *a) :Item_str_func(pos, a) {} String *val_str(String *) override; bool resolve_type(THD *thd) override; const char *func_name() const override { return "reverse"; } }; class Item_func_replace :public Item_str_func { String tmp_value,tmp_value2; /// Holds result in case we need to allocate our own result buffer. String tmp_value_res; public: Item_func_replace(const POS &pos, Item *org,Item *find,Item *replace) :Item_str_func(pos, org,find,replace) {} String *val_str(String *) override; bool resolve_type(THD *thd) override; const char *func_name() const override { return "replace"; } }; class Item_func_insert :public Item_str_func { String tmp_value; /// Holds result in case we need to allocate our own result buffer. String tmp_value_res; public: Item_func_insert(const POS &pos, Item *org, Item *start, Item *length, Item *new_str) :Item_str_func(pos, org,start,length,new_str) {} String *val_str(String *) override; bool resolve_type(THD *thd) override; const char *func_name() const override { return "insert"; } }; class Item_str_conv :public Item_str_func { protected: uint multiply; my_charset_conv_case converter; String tmp_value; public: Item_str_conv(const POS &pos, Item *item) :Item_str_func(pos, item) {} String *val_str(String *) override; }; class Item_func_lower :public Item_str_conv { public: Item_func_lower(const POS &pos, Item *item) :Item_str_conv(pos, item) {} const char *func_name() const override { return "lower"; } bool resolve_type(THD *) override; }; class Item_func_upper :public Item_str_conv { public: Item_func_upper(const POS &pos, Item *item) :Item_str_conv(pos, item) {} const char *func_name() const override { return "upper"; } bool resolve_type(THD *) override; }; class Item_func_left :public Item_str_func { String tmp_value; public: Item_func_left(const POS &pos, Item *a,Item *b) :Item_str_func(pos, a,b) {} String *val_str(String *) override; bool resolve_type(THD *thd) override; const char *func_name() const override { return "left"; } }; class Item_func_right :public Item_str_func { String tmp_value; public: Item_func_right(const POS &pos, Item *a,Item *b) :Item_str_func(pos, a,b) {} String *val_str(String *) override; bool resolve_type(THD *thd) override; const char *func_name() const override { return "right"; } }; class Item_func_substr :public Item_str_func { typedef Item_str_func super; String tmp_value; public: Item_func_substr(Item *a,Item *b) :Item_str_func(a,b) {} Item_func_substr(const POS &pos, Item *a,Item *b) :super(pos, a,b) {} Item_func_substr(Item *a,Item *b,Item *c) :Item_str_func(a,b,c) {} Item_func_substr(const POS &pos, Item *a,Item *b,Item *c) :super(pos, a, b, c) {} String *val_str(String *) override; bool resolve_type(THD *thd) override; const char *func_name() const override { return "substr"; } }; class Item_func_substr_index final : public Item_str_func { String tmp_value; public: Item_func_substr_index(const POS &pos, Item *a,Item *b, Item *c) :Item_str_func(pos, a, b, c) {} String *val_str(String *) override; bool resolve_type(THD *) override; const char *func_name() const override { return "substring_index"; } }; class Item_func_roles_graphml final : public Item_str_func { private: String m_str; public: public: Item_func_roles_graphml(const POS &pos) : Item_str_func(pos) {} String *val_str(String *) override; bool fix_fields(THD *thd, Item **ref) override; const char *func_name() const override { return "ROLES_GRAPHML"; } void print(String *str, enum_query_type query_type) override; bool resolve_type(THD *) override { return false; } }; class Item_func_trim : public Item_str_func { public: /** Why all the trim modes in this enum? We need to maintain parsing information, so that our print() function can reproduce correct messages and view definitions. */ enum TRIM_MODE { TRIM_BOTH_DEFAULT, TRIM_BOTH, TRIM_LEADING, TRIM_TRAILING, TRIM_LTRIM, TRIM_RTRIM }; private: String tmp_value; String remove; const TRIM_MODE m_trim_mode; const bool m_trim_leading; const bool m_trim_trailing; public: Item_func_trim(Item *a, Item *b, TRIM_MODE tm) : Item_str_func(a,b), m_trim_mode(tm), m_trim_leading(trim_leading()), m_trim_trailing(trim_trailing()) {} Item_func_trim(const POS &pos, Item *a, Item *b, TRIM_MODE tm) : Item_str_func(pos, a,b), m_trim_mode(tm), m_trim_leading(trim_leading()), m_trim_trailing(trim_trailing()) {} Item_func_trim(Item *a, TRIM_MODE tm) : Item_str_func(a), m_trim_mode(tm), m_trim_leading(trim_leading()), m_trim_trailing(trim_trailing()) {} Item_func_trim(const POS &pos, Item *a, TRIM_MODE tm) : Item_str_func(pos, a), m_trim_mode(tm), m_trim_leading(trim_leading()), m_trim_trailing(trim_trailing()) {} bool trim_leading() const { return m_trim_mode == TRIM_BOTH_DEFAULT || m_trim_mode == TRIM_BOTH || m_trim_mode == TRIM_LEADING || m_trim_mode == TRIM_LTRIM; } bool trim_trailing() const { return m_trim_mode == TRIM_BOTH_DEFAULT || m_trim_mode == TRIM_BOTH || m_trim_mode == TRIM_TRAILING || m_trim_mode == TRIM_RTRIM; } String *val_str(String *) override; bool resolve_type(THD *) override; const char *func_name() const override { switch(m_trim_mode) { case TRIM_BOTH_DEFAULT: return "trim"; case TRIM_BOTH: return "trim"; case TRIM_LEADING: return "ltrim"; case TRIM_TRAILING: return "rtrim"; case TRIM_LTRIM: return "ltrim"; case TRIM_RTRIM: return "rtrim"; } return NULL; } void print(String *str, enum_query_type query_type) override; }; class Item_func_ltrim final : public Item_func_trim { public: Item_func_ltrim(const POS &pos, Item *a) : Item_func_trim(pos, a, TRIM_LTRIM) {} }; class Item_func_rtrim final : public Item_func_trim { public: Item_func_rtrim(const POS &pos, Item *a) : Item_func_trim(pos, a, TRIM_RTRIM) {} }; /* Item_func_password -- new (4.1.1) PASSWORD() function implementation. Returns strcat('*', octet2hex(sha1(sha1(password)))). '*' stands for new password format, sha1(sha1(password) is so-called hash_stage2 value. Length of returned string is always 41 byte. To find out how entire authentication procedure works, see comments in password.c. */ class Item_func_password :public Item_str_ascii_func { char m_hashed_password_buffer[CRYPT_MAX_PASSWORD_SIZE + 1]; unsigned int m_hashed_password_buffer_len; bool m_recalculate_password; public: Item_func_password(Item *a) : Item_str_ascii_func(a) { m_hashed_password_buffer_len= 0; m_recalculate_password= false; } String *val_str_ascii(String *str) override; bool resolve_type(THD *thd) override; const char *func_name() const override { return "password"; } static char *create_password_hash_buffer(THD *thd, const char *password, size_t pass_len); }; class Item_func_des_encrypt :public Item_str_func { String tmp_value,tmp_arg; public: Item_func_des_encrypt(const POS &pos, Item *a) :Item_str_func(pos, a) {} Item_func_des_encrypt(const POS &pos, Item *a, Item *b) : Item_str_func(pos, a, b) {} String *val_str(String *) override; bool resolve_type(THD *) override { maybe_null= true; /* 9 = MAX ((8- (arg_len % 8)) + 1) */ set_data_type_string(args[0]->max_length + 9U); return false; } const char *func_name() const override { return "des_encrypt"; } }; class Item_func_des_decrypt :public Item_str_func { String tmp_value; public: Item_func_des_decrypt(const POS &pos, Item *a) :Item_str_func(pos, a) {} Item_func_des_decrypt(const POS &pos, Item *a, Item *b) : Item_str_func(pos, a, b) {} String *val_str(String *) override; bool resolve_type(THD *) override { maybe_null= true; /* 9 = MAX ((8- (arg_len % 8)) + 1) */ max_length= args[0]->max_length; if (max_length >= 9U) max_length-= 9U; set_data_type_string(max_length); return false; } const char *func_name() const override { return "des_decrypt"; } }; class Item_func_encrypt final : public Item_str_func { typedef Item_str_func super; String tmp_value; /* Encapsulate common constructor actions */ void constructor_helper() { collation.set(&my_charset_bin); } public: Item_func_encrypt(const POS &pos, Item *a) :Item_str_func(pos, a) { constructor_helper(); } Item_func_encrypt(const POS &pos, Item *a, Item *b): Item_str_func(pos, a, b) { constructor_helper(); } bool itemize(Parse_context *pc, Item **res) override; String *val_str(String *) override; bool resolve_type(THD *) override { maybe_null= true; set_data_type_string(13U); return false; } const char *func_name() const override { return "encrypt"; } bool check_gcol_func_processor(uchar *) override { return true; } }; #include "sql_crypt.h" class Item_func_encode : public Item_str_func { private: /** Whether the PRNG has already been seeded. */ bool seeded; /// Holds result in case we need to allocate our own result buffer. String tmp_value_res; protected: SQL_CRYPT sql_crypt; public: Item_func_encode(const POS &pos, Item *a, Item *seed) :Item_str_func(pos, a, seed) {} String *val_str(String *) override; bool resolve_type(THD *) override; const char *func_name() const override { return "encode"; } protected: virtual void crypto_transform(String *); private: /** Provide a seed for the PRNG sequence. */ bool seed(); }; class Item_func_decode final : public Item_func_encode { public: Item_func_decode(const POS &pos, Item *a, Item *seed) :Item_func_encode(pos, a, seed) {} const char *func_name() const override { return "decode"; } protected: void crypto_transform(String *) override; }; class Item_func_sysconst :public Item_str_func { typedef Item_str_func super; public: Item_func_sysconst() { collation.set(system_charset_info,DERIVATION_SYSCONST); } explicit Item_func_sysconst(const POS &pos) : super(pos) { collation.set(system_charset_info,DERIVATION_SYSCONST); } Item *safe_charset_converter(const CHARSET_INFO *tocs) override; /* Used to create correct Item name in new converted item in safe_charset_converter, return string representation of this function call */ virtual const Name_string fully_qualified_func_name() const = 0; bool check_gcol_func_processor(uchar *) override { return true; } }; class Item_func_database :public Item_func_sysconst { typedef Item_func_sysconst super; public: explicit Item_func_database(const POS &pos) :Item_func_sysconst(pos) {} bool itemize(Parse_context *pc, Item **res) override; String *val_str(String *) override; bool resolve_type(THD *) override { set_data_type_string(uint32(MAX_FIELD_NAME)); maybe_null= true; return false; } const char *func_name() const override { return "database"; } const Name_string fully_qualified_func_name() const override { return NAME_STRING("database()"); } }; class Item_func_user :public Item_func_sysconst { typedef Item_func_sysconst super; protected: bool init(const char *user, const char *host); type_conversion_status save_in_field_inner(Field *field, bool) override { return save_str_value_in_field(field, &str_value); } public: Item_func_user() { str_value.set("", 0, system_charset_info); } explicit Item_func_user(const POS &pos) : super(pos) { str_value.set("", 0, system_charset_info); } bool itemize(Parse_context *pc, Item **res) override; String *val_str(String *) override { DBUG_ASSERT(fixed == 1); return (null_value ? 0 : &str_value); } bool fix_fields(THD *thd, Item **ref) override; bool resolve_type(THD *) override { set_data_type_string(uint32(USERNAME_CHAR_LENGTH + HOSTNAME_LENGTH + 1U)); return false; } const char *func_name() const override { return "user"; } const Name_string fully_qualified_func_name() const override { return NAME_STRING("user()"); } }; class Item_func_current_user :public Item_func_user { typedef Item_func_user super; Name_resolution_context *context; public: explicit Item_func_current_user(const POS &pos) : super(pos) {} bool itemize(Parse_context *pc, Item **res) override; bool fix_fields(THD *thd, Item **ref) override; const char *func_name() const override { return "current_user"; } const Name_string fully_qualified_func_name() const override { return NAME_STRING("current_user()"); } }; class Item_func_soundex :public Item_str_func { String tmp_value; public: Item_func_soundex(Item *a) :Item_str_func(a) {} Item_func_soundex(const POS &pos, Item *a) :Item_str_func(pos, a) {} String *val_str(String *) override; bool resolve_type(THD *thd) override; const char *func_name() const override { return "soundex"; } }; class Item_func_elt final : public Item_str_func { public: Item_func_elt(const POS &pos, PT_item_list *opt_list) :Item_str_func(pos, opt_list) {} double val_real() override; longlong val_int() override; String *val_str(String *str) override; bool resolve_type(THD *thd) override; const char *func_name() const override { return "elt"; } }; class Item_func_make_set final : public Item_str_func { typedef Item_str_func super; Item *item; String tmp_str; public: Item_func_make_set(const POS &pos, Item *a, PT_item_list *opt_list) :Item_str_func(pos, opt_list), item(a) {} bool itemize(Parse_context *pc, Item **res) override; String *val_str(String *str) override; bool fix_fields(THD *thd, Item **ref) override { DBUG_ASSERT(fixed == 0); bool res= ((!item->fixed && item->fix_fields(thd, &item)) || item->check_cols(1) || Item_func::fix_fields(thd, ref)); maybe_null|= item->maybe_null; return res; } void split_sum_func(THD *thd, Ref_item_array ref_item_array, List<Item> &fields) override; bool resolve_type(THD *) override; void update_used_tables() override; const char *func_name() const override { return "make_set"; } bool walk(Item_processor processor, enum_walk walk, uchar *arg) override { if ((walk & WALK_PREFIX) && (this->*processor)(arg)) return true; if (item->walk(processor, walk, arg)) return true; for (uint i= 0; i < arg_count; i++) { if (args[i]->walk(processor, walk, arg)) return true; } return ((walk & WALK_POSTFIX) && (this->*processor)(arg)); } Item *transform(Item_transformer transformer, uchar *arg) override; void print(String *str, enum_query_type query_type) override; }; class Item_func_format final : public Item_str_ascii_func { String tmp_str; MY_LOCALE *locale; public: Item_func_format(const POS &pos, Item *org, Item *dec) : Item_str_ascii_func(pos, org, dec) {} Item_func_format(const POS &pos, Item *org, Item *dec, Item *lang) : Item_str_ascii_func(pos, org, dec, lang) {} MY_LOCALE *get_locale(Item *item); String *val_str_ascii(String *) override; bool resolve_type(THD *thd) override; const char *func_name() const override { return "format"; } void print(String *str, enum_query_type query_type) override; }; class Item_func_char final : public Item_str_func { public: Item_func_char(const POS &pos, PT_item_list *list) :Item_str_func(pos, list) { collation.set(&my_charset_bin); } Item_func_char(const POS &pos, PT_item_list *list, const CHARSET_INFO *cs) : Item_str_func(pos, list) { collation.set(cs); } String *val_str(String *) override; bool resolve_type(THD *) override { set_data_type_string(arg_count * 4U); return false; } const char *func_name() const override { return "char"; } }; class Item_func_repeat final : public Item_str_func { String tmp_value; public: Item_func_repeat(const POS &pos, Item *arg1,Item *arg2) :Item_str_func(pos, arg1,arg2) {} String *val_str(String *) override; bool resolve_type(THD *thd) override; const char *func_name() const override { return "repeat"; } }; class Item_func_space final : public Item_str_func { public: Item_func_space(const POS &pos, Item *arg1) :Item_str_func(pos, arg1) {} String *val_str(String *) override; bool resolve_type(THD *) override; const char *func_name() const override { return "space"; } }; class Item_func_rpad final : public Item_str_func { String tmp_value, rpad_str; public: Item_func_rpad(const POS &pos, Item *arg1, Item *arg2, Item *arg3) :Item_str_func(pos, arg1, arg2, arg3) {} String *val_str(String *) override; bool resolve_type(THD *) override; const char *func_name() const override { return "rpad"; } }; class Item_func_lpad final : public Item_str_func { String tmp_value, lpad_str; public: Item_func_lpad(const POS &pos, Item *arg1, Item *arg2, Item *arg3) :Item_str_func(pos , arg1, arg2, arg3) {} String *val_str(String *) override; bool resolve_type(THD *) override; const char *func_name() const override { return "lpad"; } }; class Item_func_uuid_to_bin final : public Item_str_func { /// Buffer to store the binary result uchar m_bin_buf[binary_log::Uuid::BYTE_LENGTH]; public: Item_func_uuid_to_bin(const POS &pos, Item *arg1) :Item_str_func(pos , arg1) {} Item_func_uuid_to_bin(const POS &pos, Item *arg1, Item *arg2) :Item_str_func(pos , arg1, arg2) {} String *val_str(String *) override; bool resolve_type(THD *) override; const char *func_name() const override { return "uuid_to_bin"; } }; class Item_func_bin_to_uuid final : public Item_str_ascii_func { /// Buffer to store the text result char m_text_buf[binary_log::Uuid::TEXT_LENGTH + 1]; public: Item_func_bin_to_uuid(const POS &pos, Item *arg1) :Item_str_ascii_func(pos , arg1) {} Item_func_bin_to_uuid(const POS &pos, Item *arg1, Item *arg2) :Item_str_ascii_func(pos , arg1, arg2) {} String *val_str_ascii(String *) override; bool resolve_type(THD *thd) override; const char *func_name() const override { return "bin_to_uuid"; } }; class Item_func_is_uuid final : public Item_bool_func { typedef Item_bool_func super; public: Item_func_is_uuid(const POS &pos, Item *a): Item_bool_func(pos, a) {} longlong val_int() override; const char *func_name() const override { return "is_uuid"; } bool resolve_type(THD *thd) override { bool res= super::resolve_type(thd); maybe_null= true; return res; } }; class Item_func_conv final : public Item_str_func { public: Item_func_conv(const POS &pos, Item *a,Item *b,Item *c) :Item_str_func(pos, a,b,c) {} const char *func_name() const override { return "conv"; } String *val_str(String *) override; bool resolve_type(THD *) override; }; class Item_func_hex :public Item_str_ascii_func { String tmp_value; public: Item_func_hex(const POS &pos, Item *a) :Item_str_ascii_func(pos, a) {} const char *func_name() const override { return "hex"; } String *val_str_ascii(String *) override; bool resolve_type(THD *) override { set_data_type_string(args[0]->max_length * 2U, default_charset()); return false; } }; class Item_func_unhex final : public Item_str_func { String tmp_value; public: Item_func_unhex(const POS &pos, Item *a) :Item_str_func(pos, a) { /* there can be bad hex strings */ maybe_null= 1; } const char *func_name() const override { return "unhex"; } String *val_str(String *) override; bool resolve_type(THD *) override { set_data_type_string((1U + args[0]->max_length) / 2U, &my_charset_bin); return false; } }; #ifndef DBUG_OFF class Item_func_like_range :public Item_str_func { protected: String min_str; String max_str; const bool is_min; public: Item_func_like_range(const POS &pos, Item *a, Item *b, bool is_min_arg) :Item_str_func(pos, a, b), is_min(is_min_arg) { maybe_null= true; } String *val_str(String *) override; bool resolve_type(THD *) override { set_data_type_string(uint32(MAX_BLOB_WIDTH), args[0]->collation); return false; } }; class Item_func_like_range_min final : public Item_func_like_range { public: Item_func_like_range_min(const POS &pos, Item *a, Item *b) :Item_func_like_range(pos, a, b, true) { } const char *func_name() const override { return "like_range_min"; } }; class Item_func_like_range_max final : public Item_func_like_range { public: Item_func_like_range_max(const POS &pos, Item *a, Item *b) :Item_func_like_range(pos, a, b, false) { } const char *func_name() const override { return "like_range_max"; } }; #endif class Item_char_typecast final : public Item_str_func { longlong cast_length; const CHARSET_INFO *cast_cs, *from_cs; bool charset_conversion; String tmp_value; public: Item_char_typecast(Item *a, longlong length_arg, const CHARSET_INFO *cs_arg) :Item_str_func(a), cast_length(length_arg), cast_cs(cs_arg) {} Item_char_typecast(const POS &pos, Item *a, longlong length_arg, const CHARSET_INFO *cs_arg) :Item_str_func(pos, a), cast_length(length_arg), cast_cs(cs_arg) {} enum Functype functype() const override { return TYPECAST_FUNC; } bool eq(const Item *item, bool binary_cmp) const override; const char *func_name() const override { return "cast_as_char"; } String *val_str(String *a) override; bool resolve_type(THD *) override; void print(String *str, enum_query_type query_type) override; }; class Item_func_binary final : public Item_str_func { public: Item_func_binary(const POS &pos, Item *a) :Item_str_func(pos, a) {} String *val_str(String *a) override { DBUG_ASSERT(fixed == 1); String *tmp=args[0]->val_str(a); null_value=args[0]->null_value; if (tmp) tmp->set_charset(&my_charset_bin); return tmp; } bool resolve_type(THD *) override { set_data_type_string(args[0]->max_length, &my_charset_bin); return false; } void print(String *str, enum_query_type query_type) override; const char *func_name() const override { return "cast_as_binary"; } enum Functype functype() const override { return TYPECAST_FUNC; } }; class Item_load_file final : public Item_str_func { typedef Item_str_func super; String tmp_value; public: Item_load_file(const POS &pos, Item *a) :Item_str_func(pos, a) {} bool itemize(Parse_context *pc, Item **res) override; String *val_str(String *) override; const char *func_name() const override { return "load_file"; } bool resolve_type(THD *) override { collation.set(&my_charset_bin, DERIVATION_COERCIBLE); set_data_type_blob(MAX_BLOB_WIDTH); maybe_null= true; return false; } bool check_gcol_func_processor(uchar *) override { return true; } }; class Item_func_export_set final : public Item_str_func { public: Item_func_export_set(const POS &pos, Item *a, Item *b, Item* c) :Item_str_func(pos, a, b, c) {} Item_func_export_set(const POS &pos, Item *a, Item *b, Item* c, Item* d) :Item_str_func(pos, a, b, c, d) {} Item_func_export_set(const POS &pos, Item *a, Item *b, Item* c, Item* d, Item* e) :Item_str_func(pos, a, b, c, d, e) {} String *val_str(String *str) override; bool resolve_type(THD *) override; const char *func_name() const override { return "export_set"; } }; class Item_func_quote :public Item_str_func { String tmp_value; public: Item_func_quote(const POS &pos, Item *a) :Item_str_func(pos, a) {} const char *func_name() const override { return "quote"; } String *val_str(String *) override; bool resolve_type(THD *) override { uint32 max_result_length= args[0]->max_length * 2U + 2U * collation.collation->mbmaxlen; set_data_type_string(std::min<uint32>(max_result_length, MAX_BLOB_WIDTH), args[0]->collation); return false; } }; class Item_func_conv_charset final : public Item_str_func { bool use_cached_value; String tmp_value; public: bool safe; const CHARSET_INFO *conv_charset; // keep it public Item_func_conv_charset(const POS &pos, Item *a, const CHARSET_INFO *cs) : Item_str_func(pos, a) { conv_charset= cs; use_cached_value= 0; safe= 0; } Item_func_conv_charset(Item *a, const CHARSET_INFO *cs, bool cache_if_const) :Item_str_func(a) { DBUG_ASSERT(is_fixed_or_outer_ref(args[0])); conv_charset= cs; if (cache_if_const && args[0]->const_item()) { uint errors= 0; String tmp, *str= args[0]->val_str(&tmp); if (!str || str_value.copy(str->ptr(), str->length(), str->charset(), conv_charset, &errors)) null_value= 1; use_cached_value= 1; str_value.mark_as_const(); safe= (errors == 0); } else { use_cached_value= 0; /* Conversion from and to "binary" is safe. Conversion to Unicode is safe. Other kind of conversions are potentially lossy. */ safe= (args[0]->collation.collation == &my_charset_bin || cs == &my_charset_bin || (cs->state & MY_CS_UNICODE)); } } String *val_str(String *) override; bool resolve_type(THD *) override; const char *func_name() const override { return "convert"; } void print(String *str, enum_query_type query_type) override; }; class Item_func_set_collation final : public Item_str_func { typedef Item_str_func super; LEX_STRING collation_string; public: Item_func_set_collation(const POS &pos, Item *a, const LEX_STRING &collation_string_arg) :super(pos, a, NULL), collation_string(collation_string_arg) {} bool itemize(Parse_context *pc, Item **res) override; String *val_str(String *) override; bool resolve_type(THD *) override; bool eq(const Item *item, bool binary_cmp) const override; const char *func_name() const override { return "collate"; } enum Functype functype() const override { return COLLATE_FUNC; } void print(String *str, enum_query_type query_type) override; Item_field *field_for_view_update() override { /* this function is transparent for view updating */ return args[0]->field_for_view_update(); } }; class Item_func_charset final : public Item_str_func { public: Item_func_charset(const POS &pos, Item *a) :Item_str_func(pos, a) {} String *val_str(String *) override; const char *func_name() const override { return "charset"; } bool resolve_type(THD *) override { set_data_type_string(64U, system_charset_info); maybe_null= false; return false; }; table_map not_null_tables() const override { return 0; } }; class Item_func_collation :public Item_str_func { public: Item_func_collation(const POS &pos, Item *a) :Item_str_func(pos, a) {} String *val_str(String *) override; const char *func_name() const override { return "collation"; } bool resolve_type(THD *) override { set_data_type_string(64U, system_charset_info); maybe_null= false; return false; }; table_map not_null_tables() const override { return 0; } }; class Item_func_weight_string final : public Item_str_func { typedef Item_str_func super; String tmp_value; uint flags; const uint num_codepoints; const uint result_length; Field *field; const bool as_binary; public: Item_func_weight_string(const POS &pos, Item *a, uint result_length_arg, uint num_codepoints_arg, uint flags_arg, bool as_binary_arg= false) :Item_str_func(pos, a), flags(flags_arg), num_codepoints(num_codepoints_arg), result_length(result_length_arg), field(NULL), as_binary(as_binary_arg) {} bool itemize(Parse_context *pc, Item **res) override; const char *func_name() const override { return "weight_string"; } bool eq(const Item *item, bool binary_cmp) const override; String *val_str(String *) override; bool resolve_type(THD *) override; void print(String *str, enum_query_type query_type) override; }; class Item_func_crc32 final : public Item_int_func { String value; public: Item_func_crc32(const POS &pos, Item *a) :Item_int_func(pos, a) { unsigned_flag= true; } const char *func_name() const override { return "crc32"; } bool resolve_type(THD *) override { max_length= 10; return false; } longlong val_int() override; }; class Item_func_uncompressed_length final : public Item_int_func { String value; public: Item_func_uncompressed_length(const POS &pos, Item *a) :Item_int_func(pos, a) {} const char *func_name() const override { return "uncompressed_length"; } bool resolve_type(THD *) override { max_length= 10; return false; } longlong val_int() override; }; class Item_func_compress final : public Item_str_func { String buffer; public: Item_func_compress(const POS &pos, Item *a):Item_str_func(pos, a){} bool resolve_type(THD *) override { set_data_type_string((args[0]->max_length * 120U) / 100U + 12U); return false; } const char *func_name() const override { return "compress"; } String *val_str(String *str) override; }; class Item_func_uncompress final : public Item_str_func { String buffer; public: Item_func_uncompress(const POS &pos, Item *a): Item_str_func(pos, a) {} bool resolve_type(THD *) override { maybe_null= true; set_data_type_string(uint32(MAX_BLOB_WIDTH)); return false; } const char *func_name() const override { return "uncompress"; } String *val_str(String *str) override; }; class Item_func_uuid final : public Item_str_func { typedef Item_str_func super; public: Item_func_uuid(): Item_str_func() {} explicit Item_func_uuid(const POS &pos): Item_str_func(pos) {} bool itemize(Parse_context *pc, Item **res) override; bool resolve_type(THD *) override; const char *func_name() const override { return "uuid"; } String *val_str(String *) override; bool check_gcol_func_processor(uchar *) override { return true; } }; class Item_func_gtid_subtract final : public Item_str_ascii_func { String buf1, buf2; public: Item_func_gtid_subtract(const POS &pos, Item *a, Item *b) :Item_str_ascii_func(pos, a, b) {} bool resolve_type(THD *) override; const char *func_name() const override { return "gtid_subtract"; } String *val_str_ascii(String *) override; }; class Item_func_current_role final : public Item_str_func { typedef Item_str_func super; String m_active_role; public: explicit Item_func_current_role(const POS &pos) : Item_str_func(pos) {} const char *func_name() const override { return "current_role"; } bool resolve_type(THD *) override { return false; } bool fix_fields(THD *thd, Item **ref) override; String *val_str(String *str) override; }; class Item_func_get_dd_column_privileges final : public Item_str_func { public: Item_func_get_dd_column_privileges(const POS &pos, Item *a, Item *b, Item *c) :Item_str_func(pos, a, b, c) {} bool resolve_type(THD *) override { /* There are 14 kinds of grants, with a max length per privileges is 11 chars. So, setting max approximate to 200. */ set_data_type_string(14*11, default_charset()); maybe_null= true; return false; } const char *func_name() const override { return "get_dd_column_privileges"; } String *val_str(String *) override; }; class Item_func_get_dd_create_options final : public Item_str_func { public: Item_func_get_dd_create_options(const POS &pos, Item *a, Item *b) :Item_str_func(pos, a, b) {} bool resolve_type(THD *) override { // maximum string length of all options is expected // to be less than 256 characters. set_data_type_string(256, default_charset()); maybe_null= false; return false; } const char *func_name() const override { return "get_dd_create_options"; } String *val_str(String *) override; }; class Item_func_internal_get_comment_or_error final : public Item_str_func { public: Item_func_internal_get_comment_or_error(const POS &pos, PT_item_list *list) :Item_str_func(pos, list) {} bool resolve_type(THD *) override { // maximum string length of all options is expected // to be less than 256 characters. set_data_type_string(256, default_charset()); maybe_null= 1; return false; } const char *func_name() const override { return "internal_get_comment_or_error"; } String *val_str(String *) override; }; #endif /* ITEM_STRFUNC_INCLUDED */