diff options
Diffstat (limited to 'sql')
82 files changed, 8146 insertions, 6725 deletions
diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index 77abc4e6fa5..1dffb6ffb58 100755 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -75,6 +75,7 @@ ADD_EXECUTABLE(mysqld partition_info.cc rpl_utility.cc rpl_injector.cc sql_locale.cc rpl_rli.cc rpl_mi.cc sql_servers.cc sql_connect.cc scheduler.cc + sql_profile.cc ${PROJECT_SOURCE_DIR}/sql/sql_yacc.cc ${PROJECT_SOURCE_DIR}/sql/sql_yacc.h ${PROJECT_SOURCE_DIR}/include/mysqld_error.h diff --git a/sql/Makefile.am b/sql/Makefile.am index 0081417d492..194b6ab29ef 100644 --- a/sql/Makefile.am +++ b/sql/Makefile.am @@ -53,6 +53,7 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \ procedure.h sql_class.h sql_lex.h sql_list.h \ sql_map.h sql_string.h unireg.h \ sql_error.h field.h handler.h mysqld_suffix.h \ + sql_profile.h \ ha_ndbcluster.h ha_ndbcluster_cond.h \ ha_ndbcluster_binlog.h ha_ndbcluster_tables.h \ ha_partition.h rpl_constants.h \ @@ -89,6 +90,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \ sql_connect.cc scheduler.cc sql_parse.cc \ set_var.cc sql_yacc.yy \ sql_base.cc table.cc sql_select.cc sql_insert.cc \ + sql_profile.cc \ sql_prepare.cc sql_error.cc sql_locale.cc \ sql_update.cc sql_delete.cc uniques.cc sql_do.cc \ procedure.cc sql_test.cc \ diff --git a/sql/derror.cc b/sql/derror.cc index 3b67e0f5bf0..a8cfa00ad1d 100644 --- a/sql/derror.cc +++ b/sql/derror.cc @@ -14,7 +14,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* Read language depeneded messagefile */ +/** + @file + + @brief + Read language depeneded messagefile +*/ #include "mysql_priv.h" #include "mysys_err.h" @@ -23,20 +28,17 @@ static bool read_texts(const char *file_name,const char ***point, uint error_messages); static void init_myfunc_errs(void); -/* +/** Read messages from errorfile. - SYNOPSIS - init_errmessage() + This function can be called multiple times to reload the messages. + If it fails to load the messages, it will fail softly by initializing + the errmesg pointer to an array of empty strings or by keeping the + old array if it exists. - DESCRIPTION - This function can be called multiple times to reload the messages. - If it fails to load the messages, it will fail softly by initializing - the errmesg pointer to an array of empty strings or by keeping the - old array if it exists. - - RETURN + @retval FALSE OK + @retval TRUE Error */ @@ -75,7 +77,14 @@ bool init_errmessage(void) } - /* Read text from packed textfile in language-directory */ +/** + Read text from packed textfile in language-directory. + + If we can't read messagefile then it's panic- we can't continue. + + @todo + Convert the character set to server system character set +*/ static bool read_texts(const char *file_name,const char ***point, uint error_messages) @@ -178,7 +187,9 @@ err1: } /* read_texts */ - /* Initiates error-messages used by my_func-library */ +/** + Initiates error-messages used by my_func-library. +*/ static void init_myfunc_errs() { diff --git a/sql/des_key_file.cc b/sql/des_key_file.cc index d99d712b45a..317cb237360 100644 --- a/sql/des_key_file.cc +++ b/sql/des_key_file.cc @@ -21,17 +21,18 @@ struct st_des_keyschedule des_keyschedule[10]; uint des_default_key; -/* - Function which loads DES keys from plaintext file into memory on MySQL - server startup and on command FLUSH DES_KEY_FILE. - Blame tonu@spam.ee on bugs ;) - - RETURN - 0 ok - 1 Error +#define des_cs &my_charset_latin1 + +/** + Load DES keys from plaintext file into + memory on MySQL server startup and on command FLUSH DES_KEY_FILE. + + @retval + 0 ok + @retval + 1 Error */ -#define des_cs &my_charset_latin1 bool load_des_key_file(const char *file_name) diff --git a/sql/discover.cc b/sql/discover.cc index a7af90c440f..56dc00cc5c4 100644 --- a/sql/discover.cc +++ b/sql/discover.cc @@ -14,29 +14,33 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* Functions for discover of frm file from handler */ +/** + @file + + @brief + Functions for discover of frm file from handler +*/ #include "mysql_priv.h" #include <my_dir.h> -/* - Read the contents of a .frm file +/** + Read the contents of a .frm file. - SYNOPSIS - readfrm() + frmdata and len are set to 0 on error. - name path to table-file "db/name" - frmdata frm data - len length of the read frmdata + @param name path to table-file "db/name" + @param frmdata frm data + @param len length of the read frmdata - RETURN VALUES - 0 ok - 1 Could not open file - 2 Could not stat file - 3 Could not allocate data for read - Could not read file - - frmdata and len are set to 0 on error + @retval + 0 ok + @retval + 1 Could not open file + @retval + 2 Could not stat file + @retval + 3 Could not allocate data for read. Could not read file */ int readfrm(const char *name, uchar **frmdata, size_t *len) @@ -87,18 +91,16 @@ int readfrm(const char *name, uchar **frmdata, size_t *len) /* Write the content of a frm data pointer - to a frm file - - SYNOPSIS - writefrm() + to a frm file. - name path to table-file "db/name" - frmdata frm data - len length of the frmdata + @param name path to table-file "db/name" + @param frmdata frm data + @param len length of the frmdata - RETURN VALUES - 0 ok - 2 Could not write file + @retval + 0 ok + @retval + 2 Could not write file */ int writefrm(const char *name, const uchar *frmdata, size_t len) diff --git a/sql/field.cc b/sql/field.cc index 668ced4a229..7c4f6c9ff5f 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -14,9 +14,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/***************************************************************************** -** This file implements classes defined in field.h -*****************************************************************************/ +/** + @file + + @brief + This file implements classes defined in field.h +*/ #ifdef USE_PRAGMA_IMPLEMENTATION #pragma implementation // gcc: Class implementation @@ -913,14 +916,13 @@ static enum_field_types field_types_merge_rules [FIELDTYPE_NUM][FIELDTYPE_NUM]= } }; -/* - Return type of which can carry value of both given types in UNION result +/** + Return type of which can carry value of both given types in UNION result. - SYNOPSIS - Field::field_type_merge() - a, b types for merging + @param a type for merging + @param b type for merging - RETURN + @return type of field */ @@ -992,14 +994,12 @@ test_if_important_data(CHARSET_INFO *cs, const char *str, const char *strend) } -/* - Detect Item_result by given field type of UNION merge result +/** + Detect Item_result by given field type of UNION merge result. - SYNOPSIS - Field::result_merge_type() - field_type given field type + @param field_type given field type - RETURN + @return Item_result (type of internal MySQL expression result) */ @@ -1015,18 +1015,17 @@ Item_result Field::result_merge_type(enum_field_types field_type) *****************************************************************************/ -/* - Check whether a field type can be partially indexed by a key +/** + Check whether a field type can be partially indexed by a key. This is a static method, rather than a virtual function, because we need to check the type of a non-Field in mysql_alter_table(). - SYNOPSIS - type_can_have_key_part() - type field type + @param type field type - RETURN + @retval TRUE Type can have a prefixed key + @retval FALSE Type can not have a prefixed key */ @@ -1048,8 +1047,8 @@ bool Field::type_can_have_key_part(enum enum_field_types type) } -/* - Numeric fields base class constructor +/** + Numeric fields base class constructor. */ Field_num::Field_num(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, utype unireg_check_arg, @@ -1080,23 +1079,25 @@ void Field_num::prepend_zeros(String *value) } } -/* +/** Test if given number is a int. - SYNOPSIS - Field_num::check_int - cs Character set - str String to test - end Pointer to char after last used digit - length String length - error Error returned by strntoull10rnd() + @todo + Make this multi-byte-character safe - NOTE + @param str String to test + @param length Length of 'str' + @param int_end Pointer to char after last used digit + @param cs Character set + + @note This is called after one has called strntoull10rnd() function. - RETURN - 0 ok + @retval + 0 OK + @retval 1 error: empty string or wrong integer. + @retval 2 error: garbage at the end of string. */ @@ -1191,16 +1192,15 @@ out_of_range: return 1; } -/* +/** Process decimal library return codes and issue warnings for overflow and truncation. - SYNOPSIS - Field::warn_if_overflow() - op_result decimal library return code (E_DEC_* see include/decimal.h) + @param op_result decimal library return code (E_DEC_* see include/decimal.h) - RETURN + @retval 1 there was overflow + @retval 0 no error or some other errors except overflow */ @@ -1275,10 +1275,10 @@ static bool test_if_real(const char *str,int length, CHARSET_INFO *cs) #endif -/* +/** Interpret field value as an integer but return the result as a string. - This is used for printing bit_fields as numbers while debugging + This is used for printing bit_fields as numbers while debugging. */ String *Field::val_int_as_str(String *val_buffer, my_bool unsigned_val) @@ -1299,6 +1299,7 @@ String *Field::val_int_as_str(String *val_buffer, my_bool unsigned_val) } +/// This is used as a table name when the table structure is not set up Field::Field(uchar *ptr_arg,uint32 length_arg,uchar *null_ptr_arg, uchar null_bit_arg, utype unireg_check_arg, const char *field_name_arg) @@ -1548,17 +1549,15 @@ void Field::make_field(Send_field *field) } -/* +/** Conversion from decimal to longlong with checking overflow and - setting correct value (min/max) in case of overflow + setting correct value (min/max) in case of overflow. - SYNOPSIS - Field::convert_decimal2longlong() - val value which have to be converted - unsigned_flag type of integer in which we convert val - err variable to pass error code + @param val value which have to be converted + @param unsigned_flag type of integer in which we convert val + @param err variable to pass error code - RETURN + @return value converted from val */ longlong Field::convert_decimal2longlong(const my_decimal *val, @@ -1592,19 +1591,18 @@ longlong Field::convert_decimal2longlong(const my_decimal *val, } -/* +/** Storing decimal in integer fields. - SYNOPSIS - Field_num::store_decimal() - val value for storing + @param val value for storing - NOTE + @note This method is used by all integer fields, real/decimal redefine it - RETURN + @retval 0 OK - != 0 error + @retval + !=0 error */ int Field_num::store_decimal(const my_decimal *val) @@ -1616,19 +1614,17 @@ int Field_num::store_decimal(const my_decimal *val) } -/* - Return decimal value of integer field +/** + Return decimal value of integer field. - SYNOPSIS - Field_num::val_decimal() - decimal_value buffer for storing decimal value + @param decimal_value buffer for storing decimal value - NOTE - This method is used by all integer fields, real/decimal redefine it + @note + This method is used by all integer fields, real/decimal redefine it. All longlong values fit in our decimal buffer which cal store 8*9=72 digits of integer number - RETURN + @return pointer to decimal buffer with value of field */ @@ -1661,22 +1657,24 @@ void Field_num::make_field(Send_field *field) field->decimals= dec; } -/* - Decimal representation of Field_str +/** + Decimal representation of Field_str. - SYNOPSIS - Field_str::store_decimal() - d value for storing + @param d value for storing - NOTE - Field_str is the base class for fields like Field_enum, Field_date and some - similar. Some dates use fraction and also string value should be - converted to floating point value according our rules, so we use double - to store value of decimal in string + @note + Field_str is the base class for fields like Field_enum, + Field_date and some similar. Some dates use fraction and also + string value should be converted to floating point value according + our rules, so we use double to store value of decimal in string. - RETURN + @todo + use decimal2string? + + @retval 0 OK - != 0 error + @retval + !=0 error */ int Field_str::store_decimal(const my_decimal *d) @@ -1749,11 +1747,11 @@ bool Field::get_time(MYSQL_TIME *ltime) return 0; } -/* - This is called when storing a date in a string +/** + This is called when storing a date in a string. - NOTES - Needs to be changed if/when we want to support different time formats + @note + Needs to be changed if/when we want to support different time formats. */ int Field::store_time(MYSQL_TIME *ltime, timestamp_type type_arg) @@ -2375,9 +2373,9 @@ String *Field_decimal::val_str(String *val_buffer __attribute__((unused)), return val_ptr; } -/* -** Should be able to handle at least the following fixed decimal formats: -** 5.00 , -1.0, 05, -05, +5 with optional pre/end space +/** + Should be able to handle at least the following fixed decimal formats: + 5.00 , -1.0, 05, -05, +5 with optional pre/end space */ int Field_decimal::cmp(const uchar *a_ptr,const uchar *b_ptr) @@ -2499,13 +2497,11 @@ int Field_new_decimal::reset(void) } -/* +/** Generate max/min decimal value in case of overflow. - SYNOPSIS - Field_new_decimal::set_value_on_overflow(); - decimal_value buffer for value - sign sign of value which caused overflow + @param decimal_value buffer for value + @param sign sign of value which caused overflow */ void Field_new_decimal::set_value_on_overflow(my_decimal *decimal_value, @@ -2524,21 +2520,19 @@ void Field_new_decimal::set_value_on_overflow(my_decimal *decimal_value, } -/* - Store decimal value in the binary buffer +/** + Store decimal value in the binary buffer. - SYNOPSIS - store_value(const my_decimal *decimal_value) - decimal_value my_decimal + Checks if decimal_value fits into field size. + If it does, stores the decimal in the buffer using binary format. + Otherwise sets maximal number that can be stored in the field. - DESCRIPTION - checks if decimal_value fits into field size. - if it does, stores the decimal in the buffer using binary format. - Otherwise sets maximal number that can be stored in the field. + @param decimal_value my_decimal - RETURN - 0 ok - 1 error + @retval + 0 ok + @retval + 1 error */ bool Field_new_decimal::store_value(const my_decimal *decimal_value) @@ -2647,6 +2641,12 @@ int Field_new_decimal::store(const char *from, uint length, } +/** + @todo + Fix following when double2my_decimal when double2decimal + will return E_DEC_TRUNCATED always correctly +*/ + int Field_new_decimal::store(double nr) { ASSERT_COLUMN_MARKED_FOR_WRITE; @@ -4668,9 +4668,8 @@ void Field_double::sql_type(String &res) const } -/* - TIMESTAMP type. - Holds datetime values in range from 1970-01-01 00:00:01 UTC to +/** + TIMESTAMP type holds datetime values in range from 1970-01-01 00:00:01 UTC to 2038-01-01 00:00:00 UTC stored as number of seconds since Unix Epoch in UTC. @@ -4703,7 +4702,7 @@ void Field_double::sql_type(String &res) const NONE - field which is not auto-set on update with some other than NOW() default value (TIMESTAMP DEFAULT 0). - Note that TIMESTAMP_OLD_FIELD's are never created explicitly now, they are + Note that TIMESTAMP_OLD_FIELDs are never created explicitly now, they are left only for preserving ability to read old tables. Such fields replaced with their newer analogs in CREATE TABLE and in SHOW CREATE TABLE. This is because we want to prefer NONE unireg_check before TIMESTAMP_OLD_FIELD for @@ -4749,15 +4748,11 @@ Field_timestamp::Field_timestamp(bool maybe_null_arg, } -/* +/** Get auto-set type for TIMESTAMP field. - SYNOPSIS - get_auto_set_type() - - DESCRIPTION - Returns value indicating during which operations this TIMESTAMP field - should be auto-set to current timestamp. + Returns value indicating during which operations this TIMESTAMP field + should be auto-set to current timestamp. */ timestamp_auto_set_type Field_timestamp::get_auto_set_type() const { @@ -5240,7 +5235,8 @@ longlong Field_time::val_int(void) } -/* +/** + @note This function is multi-byte safe as the result string is always of type my_charset_bin */ @@ -5267,7 +5263,8 @@ String *Field_time::val_str(String *val_buffer, } -/* +/** + @note Normally we would not consider 'time' as a valid date, but we allow get_date() here to be able to do things like DATE_FORMAT(time, "%l.%i %p") @@ -6396,15 +6393,12 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs) } -/* +/** Store double value in Field_string or Field_varstring. - SYNOPSIS - store(double nr) - nr number + Pretty prints double number into field_length characters buffer. - DESCRIPTION - Pretty prints double number into field_length characters buffer. + @param nr number */ int Field_str::store(double nr) @@ -6812,18 +6806,18 @@ int Field_string::pack_cmp(const uchar *a, const uchar *b, uint length, } -/* - Compare a packed key against row +/** + Compare a packed key against row. - SYNOPSIS - pack_cmp() - key Original key - length Key length. (May be less than field length) - insert_or_update 1 if this is an insert or update + @param key Original key + @param length Key length. (May be less than field length) + @param insert_or_update 1 if this is an insert or update - RETURN + @return < 0 row < key + @return 0 row = key + @return > 0 row > key */ @@ -7067,8 +7061,9 @@ int Field_varstring::cmp_max(const uchar *a_ptr, const uchar *b_ptr, } -/* - NOTE: varstring and blob keys are ALWAYS stored with a 2 byte length prefix +/** + @note + varstring and blob keys are ALWAYS stored with a 2 byte length prefix */ int Field_varstring::key_cmp(const uchar *key_ptr, uint max_key_length) @@ -7088,10 +7083,10 @@ int Field_varstring::key_cmp(const uchar *key_ptr, uint max_key_length) } -/* - Compare to key segments (always 2 byte length prefix) +/** + Compare to key segments (always 2 byte length prefix). - NOTE + @note This is used only to compare key segments created for index_read(). (keys are created and compared in key.cc) */ @@ -7211,21 +7206,18 @@ Field_varstring::pack_key(uchar *to, const uchar *key, uint max_length, } -/* +/** Unpack a key into a record buffer. - SYNOPSIS - unpack_key() - to Pointer into the record buffer. - key Pointer to the packed key. - max_length Key length limit from key description. + A VARCHAR key has a maximum size of 64K-1. + In its packed form, the length field is one or two bytes long, + depending on 'max_length'. - DESCRIPTION - A VARCHAR key has a maximum size of 64K-1. - In its packed form, the length field is one or two bytes long, - depending on 'max_length'. + @param to Pointer into the record buffer. + @param key Pointer to the packed key. + @param max_length Key length limit from key description. - RETURN + @return Pointer to end of 'key' (To the next key part if multi-segment key) */ @@ -7247,16 +7239,14 @@ Field_varstring::unpack_key(uchar *to, const uchar *key, uint max_length, return key + length; } -/* - Create a packed key that will be used for storage in the index tree +/** + Create a packed key that will be used for storage in the index tree. - SYNOPSIS - pack_key_from_key_image() - to Store packed key segment here - from Key segment (as given to index_read()) - max_length Max length of key + @param to Store packed key segment here + @param from Key segment (as given to index_read()) + @param max_length Max length of key - RETURN + @return end of key storage */ @@ -7590,21 +7580,15 @@ uint32 Field_blob::get_length(const uchar *pos, uint packlength_arg, bool low_by } -/* +/** Put a blob length field into a record buffer. - SYNOPSIS - Field_blob::put_length() - pos Pointer into the record buffer. - length The length value to put. - - DESCRIPTION - Depending on the maximum length of a blob, its length field is - put into 1 to 4 bytes. This is a property of the blob object, - described by 'packlength'. + Depending on the maximum length of a blob, its length field is + put into 1 to 4 bytes. This is a property of the blob object, + described by 'packlength'. - RETURN - nothing + @param pos Pointer into the record buffer. + @param length The length value to put. */ void Field_blob::put_length(uchar *pos, uint32 length) @@ -8105,7 +8089,7 @@ int Field_blob::pack_cmp(const uchar *b, uint key_length_arg, insert_or_update); } -/* Create a packed key that will be used for storage from a MySQL row */ +/** Create a packed key that will be used for storage from a MySQL row. */ uchar * Field_blob::pack_key(uchar *to, const uchar *from, uint max_length, @@ -8131,26 +8115,24 @@ Field_blob::pack_key(uchar *to, const uchar *from, uint max_length, } -/* +/** Unpack a blob key into a record buffer. - SYNOPSIS - Field_blob::unpack_key() - to Pointer into the record buffer. - from Pointer to the packed key. - max_length Key length limit from key description. + A blob key has a maximum size of 64K-1. + In its packed form, the length field is one or two bytes long, + depending on 'max_length'. + Depending on the maximum length of a blob, its length field is + put into 1 to 4 bytes. This is a property of the blob object, + described by 'packlength'. + Blobs are internally stored apart from the record buffer, which + contains a pointer to the blob buffer. - DESCRIPTION - A blob key has a maximum size of 64K-1. - In its packed form, the length field is one or two bytes long, - depending on 'max_length'. - Depending on the maximum length of a blob, its length field is - put into 1 to 4 bytes. This is a property of the blob object, - described by 'packlength'. - Blobs are internally stored apart from the record buffer, which - contains a pointer to the blob buffer. - RETURN + @param to Pointer into the record buffer. + @param from Pointer to the packed key. + @param max_length Key length limit from key description. + + @return Pointer into 'from' past the last byte copied from packed key. */ @@ -8177,7 +8159,7 @@ Field_blob::unpack_key(uchar *to, const uchar *from, uint max_length, } -/* Create a packed key that will be used for storage from a MySQL key */ +/** Create a packed key that will be used for storage from a MySQL key. */ uchar * Field_blob::pack_key_from_key_image(uchar *to, const uchar *from, uint max_length, @@ -8369,9 +8351,10 @@ void Field_enum::store_type(ulonglong value) } -/* -** Note. Storing a empty string in a enum field gives a warning -** (if there isn't a empty value in the enum) +/** + @note + Storing a empty string in a enum field gives a warning + (if there isn't a empty value in the enum) */ int Field_enum::store(const char *from,uint length,CHARSET_INFO *cs) @@ -8697,7 +8680,12 @@ void Field_set::sql_type(String &res) const res.append(')'); } -/* returns 1 if the fields are equally defined */ +/** + @retval + 1 if the fields are equally defined + @retval + 0 if the fields are unequally defined +*/ bool Field::eq_def(Field *field) { @@ -8707,6 +8695,10 @@ bool Field::eq_def(Field *field) return 1; } +/** + @return + returns 1 if the fields are equally defined +*/ bool Field_enum::eq_def(Field *field) { if (!Field::eq_def(field)) @@ -8725,6 +8717,10 @@ bool Field_enum::eq_def(Field *field) return 1; } +/** + @return + returns 1 if the fields are equally defined +*/ bool Field_num::eq_def(Field *field) { if (!Field::eq_def(field)) @@ -9300,14 +9296,8 @@ void Field_bit_as_char::sql_type(String &res) const Handling of field and Create_field *****************************************************************************/ -/* - Convert Create_field::length from number of characters to number of bytes - - SYNOPSIS - Create_field::create_length_to_internal_length() - - DESCRIPTION - Convert Create_field::length from number of characters to number of bytes. +/** + Convert create_field::length from number of characters to number of bytes. */ void Create_field::create_length_to_internal_length(void) @@ -9357,6 +9347,9 @@ void Create_field::create_length_to_internal_length(void) } +/** + Init for a tmp table field. To be extended if need be. +*/ void Create_field::init_for_tmp_table(enum_field_types sql_type_arg, uint32 length_arg, uint32 decimals_arg, bool maybe_null, bool is_unsigned) @@ -9375,26 +9368,26 @@ void Create_field::init_for_tmp_table(enum_field_types sql_type_arg, } -/* - Initialize field definition for create - - SYNOPSIS - thd Thread handle - fld_name Field name - fld_type Field type - fld_length Field length - fld_decimals Decimal (if any) - fld_type_modifier Additional type information - fld_default_value Field default value (if any) - fld_on_update_value The value of ON UPDATE clause - fld_comment Field comment - fld_change Field change - fld_interval_list Interval list (if any) - fld_charset Field charset - fld_geom_type Field geometry type (if any) - - RETURN +/** + Initialize field definition for create. + + @param thd Thread handle + @param fld_name Field name + @param fld_type Field type + @param fld_length Field length + @param fld_decimals Decimal (if any) + @param fld_type_modifier Additional type information + @param fld_default_value Field default value (if any) + @param fld_on_update_value The value of ON UPDATE clause + @param fld_comment Field comment + @param fld_change Field change + @param fld_interval_list Interval list (if any) + @param fld_charset Field charset + @param fld_geom_type Field geometry type (if any) + + @retval FALSE on success + @retval TRUE on error */ @@ -9982,7 +9975,7 @@ Field *make_field(TABLE_SHARE *share, uchar *ptr, uint32 field_length, } -/* Create a field suitable for create of table */ +/** Create a field suitable for create of table. */ Create_field::Create_field(Field *old_field,Field *orig_field) { @@ -10070,13 +10063,10 @@ Create_field::Create_field(Field *old_field,Field *orig_field) } -/* - maximum possible display length for blob - - SYNOPSIS - Field_blob::max_display_length() +/** + maximum possible display length for blob. - RETURN + @return length */ @@ -10103,24 +10093,23 @@ uint32 Field_blob::max_display_length() Warning handling *****************************************************************************/ -/* - Produce warning or note about data saved into field +/** + Produce warning or note about data saved into field. - SYNOPSIS - set_warning() - level - level of message (Note/Warning/Error) - code - error code of message to be produced - cuted_increment - whenever we should increase cut fields count or not + @param level - level of message (Note/Warning/Error) + @param code - error code of message to be produced + @param cuted_increment - whenever we should increase cut fields count or not - NOTE + @note This function won't produce warning and increase cut fields counter if count_cuted_fields == CHECK_FIELD_IGNORE for current thread. if count_cuted_fields == CHECK_FIELD_IGNORE then we ignore notes. This allows us to avoid notes in optimisation, like convert_constant_item(). - RETURN VALUE + @retval 1 if count_cuted_fields == CHECK_FIELD_IGNORE and error level is not NOTE + @retval 0 otherwise */ @@ -10144,21 +10133,19 @@ Field::set_warning(MYSQL_ERROR::enum_warning_level level, uint code, } -/* - Produce warning or note about datetime string data saved into field - - SYNOPSIS - set_datime_warning() - level - level of message (Note/Warning/Error) - code - error code of message to be produced - str - string value which we tried to save - str_len - length of string which we tried to save - ts_type - type of datetime value (datetime/date/time) - cuted_increment - whenever we should increase cut fields count or not - - NOTE - This function will always produce some warning but won't increase cut - fields counter if count_cuted_fields == FIELD_CHECK_IGNORE for current +/** + Produce warning or note about datetime string data saved into field. + + @param level level of message (Note/Warning/Error) + @param code error code of message to be produced + @param str string value which we tried to save + @param str_length length of string which we tried to save + @param ts_type type of datetime value (datetime/date/time) + @param cuted_increment whenever we should increase cut fields count or not + + @note + This function will always produce some warning but won't increase cut + fields counter if count_cuted_fields ==FIELD_CHECK_IGNORE for current thread. */ @@ -10176,20 +10163,18 @@ Field::set_datetime_warning(MYSQL_ERROR::enum_warning_level level, uint code, } -/* - Produce warning or note about integer datetime value saved into field +/** + Produce warning or note about integer datetime value saved into field. - SYNOPSIS - set_warning() - level - level of message (Note/Warning/Error) - code - error code of message to be produced - nr - numeric value which we tried to save - ts_type - type of datetime value (datetime/date/time) - cuted_increment - whenever we should increase cut fields count or not - - NOTE - This function will always produce some warning but won't increase cut - fields counter if count_cuted_fields == FIELD_CHECK_IGNORE for current + @param level level of message (Note/Warning/Error) + @param code error code of message to be produced + @param nr numeric value which we tried to save + @param ts_type type of datetime value (datetime/date/time) + @param cuted_increment whenever we should increase cut fields count or not + + @note + This function will always produce some warning but won't increase cut + fields counter if count_cuted_fields == FIELD_CHECK_IGNORE for current thread. */ @@ -10210,19 +10195,17 @@ Field::set_datetime_warning(MYSQL_ERROR::enum_warning_level level, uint code, } -/* - Produce warning or note about double datetime data saved into field +/** + Produce warning or note about double datetime data saved into field. - SYNOPSIS - set_warning() - level - level of message (Note/Warning/Error) - code - error code of message to be produced - nr - double value which we tried to save - ts_type - type of datetime value (datetime/date/time) - - NOTE - This function will always produce some warning but won't increase cut - fields counter if count_cuted_fields == FIELD_CHECK_IGNORE for current + @param level level of message (Note/Warning/Error) + @param code error code of message to be produced + @param nr double value which we tried to save + @param ts_type type of datetime value (datetime/date/time) + + @note + This function will always produce some warning but won't increase cut + fields counter if count_cuted_fields == FIELD_CHECK_IGNORE for current thread. */ diff --git a/sql/field_conv.cc b/sql/field_conv.cc index 16e27bb6cab..11d0bb9cc82 100644 --- a/sql/field_conv.cc +++ b/sql/field_conv.cc @@ -14,11 +14,15 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* - Functions to copy data to or from fields - This could be done with a single short function but opencoding this - gives much more speed. - */ +/** + @file + + @brief + Functions to copy data to or from fields + + This could be done with a single short function but opencoding this + gives much more speed. +*/ #include "mysql_priv.h" #include <m_ctype.h> @@ -129,22 +133,21 @@ set_field_to_null(Field *field) } -/* - Set field to NULL or TIMESTAMP or to next auto_increment number - - SYNOPSIS - set_field_to_null_with_conversions() - field Field to update - no_conversion Set to 1 if we should return 1 if field can't - take null values. - If set to 0 we will do store the 'default value' - if the field is a special field. If not we will - give an error. - - RETURN VALUES - 0 Field could take 0 or an automatic conversion was used - -1 Field could not take NULL and no conversion was used. - If no_conversion was not set, an error message is printed +/** + Set field to NULL or TIMESTAMP or to next auto_increment number. + + @param field Field to update + @param no_conversions Set to 1 if we should return 1 if field can't + take null values. + If set to 0 we will do store the 'default value' + if the field is a special field. If not we will + give an error. + + @retval + 0 Field could take 0 or an automatic conversion was used + @retval + -1 Field could not take NULL and no conversion was used. + If no_conversion was not set, an error message is printed */ int @@ -283,7 +286,7 @@ static void do_conv_blob(Copy_field *copy) copy->tmp.charset()); } -/* Save blob in copy->tmp for GROUP BY */ +/** Save blob in copy->tmp for GROUP BY. */ static void do_save_blob(Copy_field *copy) { @@ -352,9 +355,9 @@ static void do_field_decimal(Copy_field *copy) } -/* +/** string copy for single byte characters set when to string is shorter than - from string + from string. */ static void do_cut_string(Copy_field *copy) @@ -374,9 +377,9 @@ static void do_cut_string(Copy_field *copy) } -/* +/** string copy for multi byte characters set when to string is shorter than - from string + from string. */ static void do_cut_string_complex(Copy_field *copy) @@ -507,7 +510,7 @@ static void do_varstring2_mb(Copy_field *copy) ** The different functions that fills in a Copy_field class ***************************************************************************/ -/* +/** copy of field to maybe null string. If field is null then the all bytes are set to 0. if field is not null then the first byte is set to 1 and the rest of the @@ -748,7 +751,7 @@ Copy_field::get_copy_func(Field *to,Field *from) } -/* Simple quick field convert that is called on insert */ +/** Simple quick field convert that is called on insert. */ int field_conv(Field *to,Field *from) { diff --git a/sql/filesort.cc b/sql/filesort.cc index f2216c12ce4..3783aa2a06a 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -14,7 +14,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* Sorts a database */ +/** + @file + + @brief + Sorts a database +*/ #include "mysql_priv.h" #ifdef HAVE_STDDEF_H @@ -27,8 +32,7 @@ #define SKIP_DBUG_IN_FILESORT #endif - /* How to write record_ref. */ - +/// How to write record_ref. #define WRITE_REF(file,from) \ if (my_b_write((file),(uchar*) (from),param->ref_length)) \ DBUG_RETURN(1); @@ -59,42 +63,40 @@ static SORT_ADDON_FIELD *get_addon_fields(THD *thd, Field **ptabfield, uint sortlength, uint *plength); static void unpack_addon_fields(struct st_sort_addon_field *addon_field, uchar *buff); - -/* - Sort a table - - SYNOPSIS - filesort() - table Table to sort - sortorder How to sort the table - s_length Number of elements in sortorder - select Condition to apply to the rows - ha_maxrows Return only this many rows - sort_positions Set to 1 if we want to force sorting by position +/** + Sort a table. + Creates a set of pointers that can be used to read the rows + in sorted order. This should be done with the functions + in records.cc. + + Before calling filesort, one must have done + table->file->info(HA_STATUS_VARIABLE) + + The result set is stored in table->io_cache or + table->record_pointers. + + @param thd Current thread + @param table Table to sort + @param sortorder How to sort the table + @param s_length Number of elements in sortorder + @param select condition to apply to the rows + @param max_rows Return only this many rows + @param sort_positions Set to 1 if we want to force sorting by position (Needed by UPDATE/INSERT or ALTER TABLE) - examined_rows Store number of examined rows here + @param examined_rows Store number of examined rows here - IMPLEMENTATION - Creates a set of pointers that can be used to read the rows - in sorted order. This should be done with the functions - in records.cc - - REQUIREMENTS - Before calling filesort, one must have done - table->file->info(HA_STATUS_VARIABLE) - - NOTES + @todo + check why we do this (param.keys--) + @note If we sort by position (like if sort_positions is 1) filesort() will call table->prepare_for_position(). - RETURN + @retval HA_POS_ERROR Error - # Number of rows - + @retval + \# Number of rows + @retval examined_rows will be set to number of examined rows - - The result set is stored in table->io_cache or - table->record_pointers */ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, @@ -357,7 +359,7 @@ void filesort_free_buffers(TABLE *table, bool full) } } - /* Make a array of string pointers */ +/** Make a array of string pointers. */ static char **make_char_array(char **old_pos, register uint fields, uint length, myf my_flag) @@ -378,7 +380,7 @@ static char **make_char_array(char **old_pos, register uint fields, } /* make_char_array */ -/* Read 'count' number of buffer pointers into memory */ +/** Read 'count' number of buffer pointers into memory. */ static uchar *read_buffpek_from_file(IO_CACHE *buffpek_pointers, uint count, uchar *buf) @@ -403,38 +405,40 @@ static uchar *read_buffpek_from_file(IO_CACHE *buffpek_pointers, uint count, } -/* +/** Search after sort_keys and write them into tempfile. - SYNOPSIS - find_all_keys() - param Sorting parameter - select Use this to get source data - sort_keys Array of pointers to sort key + addon buffers. - buffpek_pointers File to write BUFFPEKs describing sorted segments - in tempfile. - tempfile File to write sorted sequences of sortkeys to. - indexfile If !NULL, use it for source data (contains rowids) - - NOTE + All produced sequences are guaranteed to be non-empty. + + @param param Sorting parameter + @param select Use this to get source data + @param sort_keys Array of pointers to sort key + addon buffers. + @param buffpek_pointers File to write BUFFPEKs describing sorted segments + in tempfile. + @param tempfile File to write sorted sequences of sortkeys to. + @param indexfile If !NULL, use it for source data (contains rowids) + + @note Basic idea: - while (get_next_sortkey()) - { - if (no free space in sort_keys buffers) - { - sort sort_keys buffer; - dump sorted sequence to 'tempfile'; - dump BUFFPEK describing sequence location into 'buffpek_pointers'; - } - put sort key into 'sort_keys'; - } - if (sort_keys has some elements && dumped at least once) - sort-dump-dump as above; - else - don't sort, leave sort_keys array to be sorted by caller. - - All produced sequences are guaranteed to be non-empty. - RETURN + @verbatim + while (get_next_sortkey()) + { + if (no free space in sort_keys buffers) + { + sort sort_keys buffer; + dump sorted sequence to 'tempfile'; + dump BUFFPEK describing sequence location into 'buffpek_pointers'; + } + put sort key into 'sort_keys'; + } + if (sort_keys has some elements && dumped at least once) + sort-dump-dump as above; + else + don't sort, leave sort_keys array to be sorted by caller. + @endverbatim + + @retval Number of records written on success. + @retval HA_POS_ERROR on error. */ @@ -602,23 +606,25 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select, } /* find_all_keys */ -/* +/** + @details Sort the buffer and write: - 1) the sorted sequence to tempfile - 2) a BUFFPEK describing the sorted sequence position to buffpek_pointers - (was: Skriver en buffert med nycklar till filen) - SYNOPSIS - write_keys() - param Sort parameters - sort_keys Array of pointers to keys to sort - count Number of elements in sort_keys array - buffpek_pointers One 'BUFFPEK' struct will be written into this file. - The BUFFPEK::{file_pos, count} will indicate where - the sorted data was stored. - tempfile The sorted sequence will be written into this file. - - RETURN + -# the sorted sequence to tempfile + -# a BUFFPEK describing the sorted sequence position to buffpek_pointers + + (was: Skriver en buffert med nycklar till filen) + + @param param Sort parameters + @param sort_keys Array of pointers to keys to sort + @param count Number of elements in sort_keys array + @param buffpek_pointers One 'BUFFPEK' struct will be written into this file. + The BUFFPEK::{file_pos, count} will indicate where + the sorted data was stored. + @param tempfile The sorted sequence will be written into this file. + + @retval 0 OK + @retval 1 Error */ @@ -661,8 +667,8 @@ err: } /* write_keys */ -/* - Store length as suffix in high-byte-first order +/** + Store length as suffix in high-byte-first order. */ static inline void store_length(uchar *to, uint length, uint pack_length) @@ -684,7 +690,7 @@ static inline void store_length(uchar *to, uint length, uint pack_length) } - /* makes a sort-key from record */ +/** Make a sort-key from record. */ static void make_sortkey(register SORTPARAM *param, register uchar *to, uchar *ref_pos) @@ -998,7 +1004,7 @@ static bool save_index(SORTPARAM *param, uchar **sort_keys, uint count, } - /* Merge buffers to make < MERGEBUFF2 buffers */ +/** Merge buffers to make < MERGEBUFF2 buffers. */ int merge_many_buff(SORTPARAM *param, uchar *sort_buffer, BUFFPEK *buffpek, uint *maxbuffer, IO_CACHE *t_file) @@ -1051,8 +1057,12 @@ cleanup: } /* merge_many_buff */ - /* Read data to buffer */ - /* This returns (uint) -1 if something goes wrong */ +/** + Read data to buffer. + + @retval + (uint)-1 if something goes wrong +*/ uint read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek, uint rec_length) @@ -1074,15 +1084,15 @@ uint read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek, } /* read_to_buffer */ -/* - Put all room used by freed buffer to use in adjacent buffer. Note, that - we can't simply distribute memory evenly between all buffers, because - new areas must not overlap with old ones. - SYNOPSIS - reuse_freed_buff() - queue IN list of non-empty buffers, without freed buffer - reuse IN empty buffer - key_length IN key length +/** + Put all room used by freed buffer to use in adjacent buffer. + + Note, that we can't simply distribute memory evenly between all buffers, + because new areas must not overlap with old ones. + + @param[in] queue list of non-empty buffers, without freed buffer + @param[in] reuse empty buffer + @param[in] key_length key length */ void reuse_freed_buff(QUEUE *queue, BUFFPEK *reuse, uint key_length) @@ -1107,22 +1117,22 @@ void reuse_freed_buff(QUEUE *queue, BUFFPEK *reuse, uint key_length) } -/* - Merge buffers to one buffer - SYNOPSIS - merge_buffers() - param Sort parameter - from_file File with source data (BUFFPEKs point to this file) - to_file File to write the sorted result data. - sort_buffer Buffer for data to store up to MERGEBUFF2 sort keys. - lastbuff OUT Store here BUFFPEK describing data written to to_file - Fb First element in source BUFFPEKs array - Tb Last element in source BUFFPEKs array - flag - - RETURN - 0 - OK - other - error +/** + Merge buffers to one buffer. + + @param param Sort parameter + @param from_file File with source data (BUFFPEKs point to this file) + @param to_file File to write the sorted result data. + @param sort_buffer Buffer for data to store up to MERGEBUFF2 sort keys. + @param lastbuff OUT Store here BUFFPEK describing data written to to_file + @param Fb First element in source BUFFPEKs array + @param Tb Last element in source BUFFPEKs array + @param flag + + @retval + 0 OK + @retval + other error */ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file, @@ -1358,23 +1368,21 @@ static uint suffix_length(ulong string_length) -/* - Calculate length of sort key - - SYNOPSIS - sortlength() - thd Thread handler - sortorder Order of items to sort - uint s_length Number of items to sort - multi_byte_charset (out) - Set to 1 if we are using multi-byte charset - (In which case we have to use strxnfrm()) - - NOTES - sortorder->length is updated for each sort item +/** + Calculate length of sort key. + + @param thd Thread handler + @param sortorder Order of items to sort + @param s_length Number of items to sort + @param[out] multi_byte_charset Set to 1 if we are using multi-byte charset + (In which case we have to use strxnfrm()) + + @note + sortorder->length is updated for each sort item. + @n sortorder->need_strxnfrm is set 1 if we have to use strxnfrm - RETURN + @return Total length of sort buffer in bytes */ @@ -1461,33 +1469,31 @@ sortlength(THD *thd, SORT_FIELD *sortorder, uint s_length, } -/* +/** Get descriptors of fields appended to sorted fields and - calculate its total length - - SYNOPSIS - get_addon_fields() - thd Current thread - ptabfields Array of references to the table fields - sortlength Total length of sorted fields - plength out: Total length of appended fields - - DESCRIPTION - The function first finds out what fields are used in the result set. - Then it calculates the length of the buffer to store the values of - these fields together with the value of sort values. - If the calculated length is not greater than max_length_for_sort_data - the function allocates memory for an array of descriptors containing - layouts for the values of the non-sorted fields in the buffer and - fills them. - - NOTES + calculate its total length. + + The function first finds out what fields are used in the result set. + Then it calculates the length of the buffer to store the values of + these fields together with the value of sort values. + If the calculated length is not greater than max_length_for_sort_data + the function allocates memory for an array of descriptors containing + layouts for the values of the non-sorted fields in the buffer and + fills them. + + @param thd Current thread + @param ptabfield Array of references to the table fields + @param sortlength Total length of sorted fields + @param[out] plength Total length of appended fields + + @note The null bits for the appended values are supposed to be put together and stored the buffer just ahead of the value of the first field. - RETURN + @return Pointer to the layout descriptors for the appended fields, if any - NULL - if we do not store field values with sort data. + @retval + NULL if we do not store field values with sort data. */ static SORT_ADDON_FIELD * @@ -1563,20 +1569,18 @@ get_addon_fields(THD *thd, Field **ptabfield, uint sortlength, uint *plength) } -/* - Copy (unpack) values appended to sorted fields from a buffer back to +/** + Copy (unpack) values appended to sorted fields from a buffer back to their regular positions specified by the Field::ptr pointers. - SYNOPSIS - unpack_addon_fields() - addon_field Array of descriptors for appended fields - buff Buffer which to unpack the value from + @param addon_field Array of descriptors for appended fields + @param buff Buffer which to unpack the value from - NOTES + @note The function is supposed to be used only as a callback function when getting field values for the sorted result set. - RETURN + @return void. */ diff --git a/sql/gen_lex_hash.cc b/sql/gen_lex_hash.cc index 36b7f30dc64..c9c1813a429 100644 --- a/sql/gen_lex_hash.cc +++ b/sql/gen_lex_hash.cc @@ -13,8 +13,11 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* +/** + @file + @details +@verbatim The idea of presented algorithm see in "The Art of Computer Programming" by Donald E. Knuth Volume 3 "Sorting and searching" @@ -63,12 +66,14 @@ for optimization, link is the 16-bit index in 'symbols' or 'sql_functions' or search-array.. So, we can read full search-structure as 32-bit word +@endverbatim + +@todo + use instead to_upper_lex, special array + (substitute chars) without skip codes.. +@todo + try use reverse order of comparing.. -TODO: -1. use instead to_upper_lex, special array - (substitute chars) without skip codes.. -2. try use reverse order of comparing.. - */ #define NO_YACC_SYMBOLS diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index f72aa7cffea..441da21bf1c 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -14,9 +14,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* - This file defines the NDB Cluster handler: the interface between MySQL and - NDB Cluster +/** + @file + + @brief + This file defines the NDB Cluster handler: the interface between + MySQL and NDB Cluster */ #ifdef USE_PRAGMA_IMPLEMENTATION @@ -140,10 +143,10 @@ static Ndb* g_ndb= NULL; Ndb_cluster_connection* g_ndb_cluster_connection= NULL; uchar g_node_id_map[max_ndb_nodes]; -// Handler synchronization +/// Handler synchronization pthread_mutex_t ndbcluster_mutex; -// Table lock handling +/// Table lock handling HASH ndbcluster_open_tables; static uchar *ndbcluster_get_key(NDB_SHARE *share, size_t *length, @@ -164,14 +167,14 @@ pthread_cond_t COND_ndb_util_ready; pthread_handler_t ndb_util_thread_func(void *arg); ulong ndb_cache_check_time; -/* +/** Dummy buffer to read zero pack_length fields - which are mapped to 1 char + which are mapped to 1 char. */ static uint32 dummy_buf; -/* - Stats that can be retrieved from ndb +/** + Stats that can be retrieved from ndb. */ struct Ndb_statistics { @@ -625,10 +628,10 @@ int ha_ndbcluster::ndb_err(NdbTransaction *trans) } -/* +/** Override the default get_error_message in order to add the - error message of NDB - */ + error message of NDB . +*/ bool ha_ndbcluster::get_error_message(int error, String *buf) @@ -649,7 +652,7 @@ bool ha_ndbcluster::get_error_message(int error, #ifndef DBUG_OFF -/* +/** Check if type is supported by NDB. */ @@ -691,8 +694,8 @@ static bool ndb_supported_type(enum_field_types type) #endif /* !DBUG_OFF */ -/* - Check if MySQL field type forces var part in ndb storage +/** + Check if MySQL field type forces var part in ndb storage. */ static bool field_type_forces_var_part(enum_field_types type) { @@ -711,8 +714,8 @@ static bool field_type_forces_var_part(enum_field_types type) } } -/* - Instruct NDB to set the value of the hidden primary key +/** + Instruct NDB to set the value of the hidden primary key. */ bool ha_ndbcluster::set_hidden_key(NdbOperation *ndb_op, @@ -723,8 +726,8 @@ bool ha_ndbcluster::set_hidden_key(NdbOperation *ndb_op, } -/* - Instruct NDB to set the value of one primary key attribute +/** + Instruct NDB to set the value of one primary key attribute. */ int ha_ndbcluster::set_ndb_key(NdbOperation *ndb_op, Field *field, @@ -744,8 +747,8 @@ int ha_ndbcluster::set_ndb_key(NdbOperation *ndb_op, Field *field, } -/* - Instruct NDB to set the value of one attribute +/** + Instruct NDB to set the value of one attribute. */ int ha_ndbcluster::set_ndb_value(NdbOperation *ndb_op, Field *field, @@ -840,7 +843,9 @@ int ha_ndbcluster::set_ndb_value(NdbOperation *ndb_op, Field *field, } -/* +NdbBlob::ActiveHook g_get_ndb_blobs_value; + +/** Callback to read all blob values. - not done in unpack_record because unpack_record is valid after execute(Commit) but reading blobs is not @@ -848,11 +853,11 @@ int ha_ndbcluster::set_ndb_value(NdbOperation *ndb_op, Field *field, somewhere before the data is available - due to single buffer for all blobs, we let the last blob process all blobs (last so that all are active) - - null bit is still set in unpack_record - - TODO allocate blob part aligned buffers -*/ + - null bit is still set in unpack_record. -NdbBlob::ActiveHook g_get_ndb_blobs_value; + @todo + allocate blob part aligned buffers +*/ int g_get_ndb_blobs_value(NdbBlob *ndb_blob, void *arg) { @@ -948,10 +953,11 @@ int get_ndb_blobs_value(TABLE* table, NdbValue* value_array, } -/* - Instruct NDB to fetch one field - - data is read directly into buffer provided by field - if field is NULL, data is read into memory provided by NDBAPI +/** + Instruct NDB to fetch one field. + + Data is read directly into buffer provided by field + if field is NULL, data is read into memory provided by NDBAPI. */ int ha_ndbcluster::get_ndb_value(NdbOperation *ndb_op, Field *field, @@ -1013,7 +1019,7 @@ int ha_ndbcluster::get_ndb_partition_id(NdbOperation *ndb_op) (char *)&m_part_id) == NULL); } -/* +/** Check if any set or get of blob value in current query. */ @@ -1036,15 +1042,15 @@ bool ha_ndbcluster::uses_blob_value() } -/* - Get metadata for this table from NDB +/** + Get metadata for this table from NDB. - IMPLEMENTATION - - check that frm-file on disk is equal to frm-file - of table accessed in NDB + Check that frm-file on disk is equal to frm-file + of table accessed in NDB. - RETURN + @retval 0 ok + @retval -2 Meta data has changed; Re-read data and try again */ @@ -1442,9 +1448,9 @@ int ha_ndbcluster::drop_indexes(Ndb *ndb, TABLE *tab) DBUG_RETURN(error); } -/* +/** Decode the type of an index from information - provided in table object + provided in table object. */ NDB_INDEX_TYPE ha_ndbcluster::get_index_type_from_table(uint inx) const { @@ -1586,10 +1592,10 @@ inline bool ha_ndbcluster::has_null_in_unique_index(uint idx_no) const } -/* - Get the flags for an index +/** + Get the flags for an index. - RETURN + @return flags depending on the type of the index. */ @@ -1762,8 +1768,8 @@ int ha_ndbcluster::define_read_attrs(uchar* buf, NdbOperation* op) } -/* - Read one record from NDB using primary key +/** + Read one record from NDB using primary key. */ int ha_ndbcluster::pk_read(const uchar *key, uint key_len, uchar *buf, @@ -1830,9 +1836,9 @@ int ha_ndbcluster::pk_read(const uchar *key, uint key_len, uchar *buf, DBUG_RETURN(0); } -/* +/** Read one complementing record from NDB using primary key from old_data - or hidden key + or hidden key. */ int ha_ndbcluster::complemented_read(const uchar *old_data, uchar *new_data, @@ -1893,7 +1899,7 @@ int ha_ndbcluster::complemented_read(const uchar *old_data, uchar *new_data, unpack_record(new_data); table->status= 0; - /** + /* * restore m_value */ for (i= 0; i < no_fields; i++) @@ -1909,12 +1915,12 @@ int ha_ndbcluster::complemented_read(const uchar *old_data, uchar *new_data, DBUG_RETURN(0); } -/* - * Check that all operations between first and last all - * have gotten the errcode - * If checking for HA_ERR_KEY_NOT_FOUND then update m_dupkey - * for all succeeding operations - */ +/** + Check that all operations between first and last all + have gotten the errcode + If checking for HA_ERR_KEY_NOT_FOUND then update m_dupkey + for all succeeding operations +*/ bool ha_ndbcluster::check_all_operations_for_error(NdbTransaction *trans, const NdbOperation *first, const NdbOperation *last, @@ -1994,9 +2000,9 @@ check_null_in_record(const KEY* key_info, const uchar *record) */ } -/* - * Peek to check if any rows already exist with conflicting - * primary key or unique index values +/** + Peek to check if any rows already exist with conflicting + primary key or unique index values */ int ha_ndbcluster::peek_indexed_rows(const uchar *record, @@ -2104,8 +2110,8 @@ int ha_ndbcluster::peek_indexed_rows(const uchar *record, } -/* - Read one record from NDB using unique secondary index +/** + Read one record from NDB using unique secondary index. */ int ha_ndbcluster::unique_index_read(const uchar *key, @@ -2247,15 +2253,14 @@ inline int ha_ndbcluster::fetch_next(NdbScanOperation* cursor) DBUG_RETURN(1); } -/* +/** Get the next record of a started scan. Try to fetch it locally from NdbApi cached records if possible, otherwise ask NDB for more. - NOTE - If this is a update/delete make sure to not contact - NDB before any pending ops have been sent to NDB. - + @note + If this is a update/delete make sure to not contact + NDB before any pending ops have been sent to NDB. */ inline int ha_ndbcluster::next_result(uchar *buf) @@ -2288,7 +2293,7 @@ inline int ha_ndbcluster::next_result(uchar *buf) } } -/* +/** Set bounds for ordered index scan. */ @@ -2469,8 +2474,8 @@ int ha_ndbcluster::set_bounds(NdbIndexScanOperation *op, DBUG_RETURN(op->end_of_bound(range_no)); } -/* - Start ordered index scan in NDB +/** + Start ordered index scan in NDB. */ int ha_ndbcluster::ordered_index_scan(const key_range *start_key, @@ -2654,10 +2659,9 @@ int ha_ndbcluster::unique_index_scan(const KEY* key_info, } -/* - Start full table scan in NDB - */ - +/** + Start full table scan in NDB. +*/ int ha_ndbcluster::full_table_scan(uchar *buf) { int res; @@ -2745,8 +2749,8 @@ ha_ndbcluster::set_auto_inc(Field *field) DBUG_RETURN(0); } -/* - Insert one record into NDB +/** + Insert one record into NDB. */ int ha_ndbcluster::write_row(uchar *record) { @@ -2964,7 +2968,9 @@ int ha_ndbcluster::write_row(uchar *record) } -/* Compare if a key in a row has changed */ +/** + Compare if a key in a row has changed. +*/ int ha_ndbcluster::key_cmp(uint keynr, const uchar * old_row, const uchar * new_row) @@ -2998,8 +3004,8 @@ int ha_ndbcluster::key_cmp(uint keynr, const uchar * old_row, return 0; } -/* - Update one record in NDB using primary key +/** + Update one record in NDB using primary key. */ int ha_ndbcluster::update_row(const uchar *old_data, uchar *new_data) @@ -3228,8 +3234,8 @@ int ha_ndbcluster::update_row(const uchar *old_data, uchar *new_data) } -/* - Delete one record from NDB, using primary key +/** + Delete one record from NDB, using primary key . */ int ha_ndbcluster::delete_row(const uchar *record) @@ -3343,14 +3349,12 @@ int ha_ndbcluster::delete_row(const uchar *record) DBUG_RETURN(0); } -/* - Unpack a record read from NDB +/** + Unpack a record read from NDB. - SYNOPSIS - unpack_record() - buf Buffer to store read row + @param buf Buffer to store read row - NOTE + @note The data for each row is read directly into the destination buffer. This function is primarily called in order to check if any fields should be @@ -3511,12 +3515,12 @@ void ha_ndbcluster::unpack_record(uchar *buf) #endif } -/* - Utility function to print/dump the fetched field - to avoid unnecessary work, wrap in DBUG_EXECUTE as in: +/** + Utility function to print/dump the fetched field. + To avoid unnecessary work, wrap in DBUG_EXECUTE as in: DBUG_EXECUTE("value", print_results();); - */ +*/ void ha_ndbcluster::print_results() { @@ -3598,8 +3602,8 @@ int ha_ndbcluster::index_end() } /** - * Check if key contains null - */ + Check if key contains null. +*/ static int check_null_in_key(const KEY* key_info, const uchar *key, uint key_len) @@ -3872,11 +3876,10 @@ int ha_ndbcluster::rnd_next(uchar *buf) } -/* +/** An "interesting" record has been found and it's pk - retrieved by calling position - Now it's time to read the record from db once - again + retrieved by calling position. Now it's time to read + the record from db once again. */ int ha_ndbcluster::rnd_pos(uchar *buf, uchar *pos) @@ -3919,10 +3922,10 @@ int ha_ndbcluster::rnd_pos(uchar *buf, uchar *pos) } -/* +/** Store the primary key of this record in ref variable, so that the row can be retrieved again later - using "reference" in rnd_pos + using "reference" in rnd_pos. */ void ha_ndbcluster::position(const uchar *record) @@ -4196,14 +4199,13 @@ int ha_ndbcluster::reset() } -/* - Start of an insert, remember number of rows to be inserted, it will - be used in write_row and get_autoincrement to send an optimal number - of rows in each roundtrip to the server +/** + Start of an insert, remember number of rows to be inserted, it will + be used in write_row and get_autoincrement to send an optimal number + of rows in each roundtrip to the server. - SYNOPSIS + @param rows number of rows to insert, 0 if unknown - */ void ha_ndbcluster::start_bulk_insert(ha_rows rows) @@ -4253,9 +4255,9 @@ void ha_ndbcluster::start_bulk_insert(ha_rows rows) DBUG_VOID_RETURN; } -/* - End of an insert - */ +/** + End of an insert. +*/ int ha_ndbcluster::end_bulk_insert() { int error= 0; @@ -4316,8 +4318,9 @@ const char** ha_ndbcluster::bas_ext() const return ha_ndbcluster_exts; } -/* - How many seeks it will take to read through the table +/** + How many seeks it will take to read through the table. + This is to be comparable to the number returned by records_in_range so that we can decide if we should scan the table or use keys. */ @@ -4667,7 +4670,7 @@ error: DBUG_RETURN(error); } -/* +/** Unlock the last row read in an open scan. Rows are unlocked by default in ndb, but for SELECT FOR UPDATE and SELECT LOCK WIT SHARE MODE @@ -4683,12 +4686,12 @@ void ha_ndbcluster::unlock_row() DBUG_VOID_RETURN; } -/* +/** Start a transaction for running a statement if one is not already running in a transaction. This will be the case in a BEGIN; COMMIT; block When using LOCK TABLE's external_lock will start a transaction - since ndb does not currently does not support table locking + since ndb does not currently does not support table locking. */ int ha_ndbcluster::start_stmt(THD *thd, thr_lock_type lock_type) @@ -4713,9 +4716,9 @@ error: } -/* - Commit a transaction started in NDB - */ +/** + Commit a transaction started in NDB. +*/ static int ndbcluster_commit(handlerton *hton, THD *thd, bool all) { @@ -4785,9 +4788,9 @@ static int ndbcluster_commit(handlerton *hton, THD *thd, bool all) } -/* - Rollback a transaction started in NDB - */ +/** + Rollback a transaction started in NDB. +*/ static int ndbcluster_rollback(handlerton *hton, THD *thd, bool all) { @@ -4826,14 +4829,17 @@ static int ndbcluster_rollback(handlerton *hton, THD *thd, bool all) } -/* +/** Define NDB column based on Field. - Returns 0 or mysql error code. + Not member of ha_ndbcluster because NDBCOL cannot be declared. MySQL text types with character set "binary" are mapped to true NDB binary types without a character set. This may change. - */ + + @return + Returns 0 or mysql error code. +*/ static int create_ndb_column(NDBCOL &col, Field *field, @@ -5120,7 +5126,7 @@ static int create_ndb_column(NDBCOL &col, return 0; } -/* +/** Create a table in NDB Cluster */ @@ -5668,9 +5674,12 @@ int ha_ndbcluster::create_unique_index(const char *name, } -/* - Create an index in NDB Cluster - */ +/** + Create an index in NDB Cluster. + + @todo + Only temporary ordered indexes supported +*/ int ha_ndbcluster::create_ndb_index(const char *name, KEY *key_info, @@ -5813,8 +5822,8 @@ int ha_ndbcluster::final_drop_index(TABLE *table_arg) DBUG_RETURN(error); } -/* - Rename a table in NDB Cluster +/** + Rename a table in NDB Cluster. */ int ha_ndbcluster::rename_table(const char *from, const char *to) @@ -5994,10 +6003,9 @@ int ha_ndbcluster::rename_table(const char *from, const char *to) } -/* - Delete table from NDB Cluster - - */ +/** + Delete table from NDB Cluster. +*/ /* static version which does not need a handler */ @@ -6270,9 +6278,9 @@ void ha_ndbcluster::get_auto_increment(ulonglong offset, ulonglong increment, } -/* - Constructor for the NDB Cluster table handler - */ +/** + Constructor for the NDB Cluster table handler . +*/ /* Normal flags for binlogging is that ndb has HA_HAS_OWN_BINLOGGING @@ -6358,9 +6366,9 @@ int ha_ndbcluster::ha_initialise() DBUG_RETURN(TRUE); } -/* - Destructor for NDB Cluster table handler - */ +/** + Destructor for NDB Cluster table handler. +*/ ha_ndbcluster::~ha_ndbcluster() { @@ -6400,13 +6408,15 @@ ha_ndbcluster::~ha_ndbcluster() -/* - Open a table for further use +/** + Open a table for further use. + - fetch metadata for this table from NDB - check that table exists - RETURN + @retval 0 ok + @retval < 0 Table has changed */ @@ -6514,10 +6524,9 @@ void ha_ndbcluster::set_part_info(partition_info *part_info) m_use_partition_function= TRUE; } -/* - Close the table - - release resources setup by open() - */ +/** + Close the table; release resources setup by open(). +*/ int ha_ndbcluster::close(void) { @@ -6534,6 +6543,12 @@ int ha_ndbcluster::close(void) } +/** + @todo + - Alt.1 If init fails because to many allocated Ndb + wait on condition for a Ndb object to be released. + - Alt.2 Seize/release from pool, wait until next release +*/ Thd_ndb* ha_ndbcluster::seize_thd_ndb() { Thd_ndb *thd_ndb; @@ -6569,7 +6584,7 @@ void ha_ndbcluster::release_thd_ndb(Thd_ndb* thd_ndb) } -/* +/** If this thread already has a Thd_ndb object allocated in current THD, reuse it. Otherwise seize a Thd_ndb object, assign it to current THD and use it. @@ -6618,9 +6633,9 @@ static int ndbcluster_close_connection(handlerton *hton, THD *thd) } -/* - Try to discover one table from NDB - */ +/** + Try to discover one table from NDB. +*/ int ndbcluster_discover(handlerton *hton, THD* thd, const char *db, const char *name, @@ -6727,10 +6742,9 @@ err: DBUG_RETURN(error); } -/* - Check if a table exists in NDB - - */ +/** + Check if a table exists in NDB. +*/ int ndbcluster_table_exists_in_engine(handlerton *hton, THD* thd, const char *db, @@ -6769,11 +6783,12 @@ extern "C" uchar* tables_get_key(const char *entry, size_t *length, } -/* +/** Drop a database in NDB Cluster - NOTE add a dummy void function, since stupid handlerton is returning void instead of int... -*/ + @note + add a dummy void function, since stupid handlerton is returning void instead of int... +*/ int ndbcluster_drop_database_impl(const char *path) { DBUG_ENTER("ndbcluster_drop_database"); @@ -7529,10 +7544,9 @@ void ha_ndbcluster::print_error(int error, myf errflag) } -/* - Static error print function called from - static handler method ndbcluster_commit - and ndbcluster_rollback +/** + Static error print function called from static handler method + ndbcluster_commit and ndbcluster_rollback. */ void ndbcluster_print_error(int error, const NdbOperation *error_op) @@ -7550,9 +7564,9 @@ void ndbcluster_print_error(int error, const NdbOperation *error_op) } /** - * Set a given location from full pathname to database name - * - */ + Set a given location from full pathname to database name. +*/ + void ha_ndbcluster::set_dbname(const char *path_name, char *dbname) { char *end, *ptr, *tmp_name; @@ -7585,9 +7599,9 @@ void ha_ndbcluster::set_dbname(const char *path_name, char *dbname) filename_to_tablename(tmp_name, dbname, FN_REFLEN); } -/* - Set m_dbname from full pathname to table file - */ +/** + Set m_dbname from full pathname to table file. +*/ void ha_ndbcluster::set_dbname(const char *path_name) { @@ -7595,9 +7609,9 @@ void ha_ndbcluster::set_dbname(const char *path_name) } /** - * Set a given location from full pathname to table file - * - */ + Set a given location from full pathname to table file. +*/ + void ha_ndbcluster::set_tabname(const char *path_name, char * tabname) { @@ -7626,9 +7640,9 @@ ha_ndbcluster::set_tabname(const char *path_name, char * tabname) filename_to_tablename(tmp_name, tabname, FN_REFLEN); } -/* - Set m_tabname from full pathname to table file - */ +/** + Set m_tabname from full pathname to table file. +*/ void ha_ndbcluster::set_tabname(const char *path_name) { @@ -7899,31 +7913,30 @@ uint ndb_get_commitcount(THD *thd, char *dbname, char *tabname, } -/* +/** Check if a cached query can be used. + This is done by comparing the supplied engine_data to commit_count of the table. + The commit_count is either retrieved from the share for the table, where it has been cached by the util thread. If the util thread is not started, NDB has to be contacetd to retrieve the commit_count, this will introduce a small delay while waiting for NDB to answer. - SYNOPSIS - ndbcluster_cache_retrieval_allowed - thd thread handle - full_name concatenation of database name, - the null character '\0', and the table - name - full_name_len length of the full name, - i.e. len(dbname) + len(tablename) + 1 - - engine_data parameter retrieved when query was first inserted into - the cache. If the value of engine_data is changed, - all queries for this table should be invalidated. + @param thd thread handle + @param full_name concatenation of database name, + the null character '\\0', and the table name + @param full_name_len length of the full name, + i.e. len(dbname) + len(tablename) + 1 + @param engine_data parameter retrieved when query was first inserted into + the cache. If the value of engine_data is changed, + all queries for this table should be invalidated. - RETURN VALUE + @retval TRUE Yes, use the query from cache + @retval FALSE No, don't use the cached query, and if engine_data has changed, all queries for this table should be invalidated @@ -7979,25 +7992,25 @@ ndbcluster_cache_retrieval_allowed(THD *thd, /** - Register a table for use in the query cache. Fetch the commit_count - for the table and return it in engine_data, this will later be used - to check if the table has changed, before the cached query is reused. - - SYNOPSIS - ha_ndbcluster::can_query_cache_table - thd thread handle - full_name concatenation of database name, - the null character '\0', and the table - name - full_name_len length of the full name, - i.e. len(dbname) + len(tablename) + 1 - qc_engine_callback function to be called before using cache on this table - engine_data out, commit_count for this table - - RETURN VALUE + Register a table for use in the query cache. + + Fetch the commit_count for the table and return it in engine_data, + this will later be used to check if the table has changed, before + the cached query is reused. + + @param thd thread handle + @param full_name concatenation of database name, + the null character '\\0', and the table name + @param full_name_len length of the full name, + i.e. len(dbname) + len(tablename) + 1 + @param engine_callback function to be called before using cache on + this table + @param[out] engine_data commit_count for this table + + @retval TRUE Yes, it's ok to cahce this query + @retval FALSE No, don't cach the query - */ my_bool @@ -8034,13 +8047,14 @@ ha_ndbcluster::register_query_cache_table(THD *thd, } -/* +/** Handling the shared NDB_SHARE structure that is needed to provide table locking. + It's also used for sharing data with other NDB handlers in the same MySQL Server. There is currently not much data we want to or can share. - */ +*/ static uchar *ndbcluster_get_key(NDB_SHARE *share, size_t *length, my_bool not_used __attribute__((unused))) @@ -8593,9 +8607,9 @@ retry: DBUG_RETURN(reterr); } -/* +/** Create a .ndb file to serve as a placeholder indicating - that the table with this name is a ndb table + that the table with this name is a ndb table. */ int ha_ndbcluster::write_ndb_file(const char *name) @@ -8702,7 +8716,7 @@ ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p, thd_ndb->query_state|= NDB_QUERY_MULTI_READ_RANGE; m_disable_multi_read= FALSE; - /** + /* * Copy arguments into member variables */ m_multi_ranges= ranges; @@ -8711,7 +8725,7 @@ ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p, multi_range_sorted= sorted; multi_range_buffer= buffer; - /** + /* * read multi range will read ranges as follows (if not ordered) * * input read order @@ -8724,7 +8738,7 @@ ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p, * pk-op 6 pk-ok 6 */ - /** + /* * Variables for loop */ uchar *curr= (uchar*)buffer->buffer; @@ -8851,7 +8865,7 @@ ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p, if (multi_range_curr != multi_range_end) { - /** + /* * Mark that we're using entire buffer (even if might not) as * we haven't read all ranges for some reason * This as we don't want mysqld to reuse the buffer when we read @@ -8864,7 +8878,7 @@ ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p, buffer->end_of_used_area= curr; } - /** + /* * Set first operation in multi range */ m_current_multi_operation= @@ -8968,10 +8982,10 @@ ha_ndbcluster::read_multi_range_next(KEY_MULTI_RANGE ** multi_range_found_p) continue; } } - else /** m_multi_cursor == 0 */ + else /* m_multi_cursor == 0 */ { DBUG_MULTI_RANGE(7); - /** + /* * Corresponds to range 5 in example in read_multi_range_first */ (void)1; @@ -9002,7 +9016,7 @@ close_scan: DBUG_RETURN(HA_ERR_END_OF_FILE); } - /** + /* * Read remaining ranges */ DBUG_RETURN(read_multi_range_first(multi_range_found_p, @@ -9012,7 +9026,7 @@ close_scan: multi_range_buffer)); found: - /** + /* * Found a record belonging to a scan */ m_active_cursor= m_multi_cursor; @@ -9024,7 +9038,7 @@ found: DBUG_RETURN(0); found_next: - /** + /* * Found a record belonging to a pk/index op, * copy result and move to next to prepare for next call */ @@ -9065,6 +9079,12 @@ ha_ndbcluster::setup_recattr(const NdbRecAttr* curr) DBUG_RETURN(0); } +/** + @param[in] comment table comment defined by user + + @return + table comment + additional +*/ char* ha_ndbcluster::update_table_comment( /* out: table comment + additional */ @@ -9106,7 +9126,9 @@ ha_ndbcluster::update_table_comment( } -// Utility thread main loop +/** + Utility thread main loop. +*/ pthread_handler_t ndb_util_thread_func(void *arg __attribute__((unused))) { THD *thd; /* needs to be first for thread_stack */ @@ -9394,7 +9416,7 @@ ndb_util_thread_fail: /* Condition pushdown */ -/* +/** Push a condition to ndbcluster storage engine for evaluation during table and index scans. The conditions will be stored on a stack for possibly storing several conditions. The stack can be popped @@ -9405,9 +9427,10 @@ ndb_util_thread_fail: expressions and function calls) and the following comparison operators: =, !=, >, >=, <, <=, "is null", and "is not null". - RETURN + @retval NULL The condition was supported and will be evaluated for each - row found during the scan + row found during the scan + @retval cond The condition was not supported and all rows will be returned from the scan for evaluation (and thus not saved on stack) */ @@ -9427,7 +9450,7 @@ ha_ndbcluster::cond_push(const COND *cond) DBUG_RETURN(m_cond->cond_push(cond, table, (NDBTAB *)m_table)); } -/* +/** Pop the top condition from the condition stack of the handler instance. */ void diff --git a/sql/handler.cc b/sql/handler.cc index a4926071598..0715ef3cc9c 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -199,8 +199,8 @@ handlerton *ha_resolve_by_legacy_type(THD *thd, enum legacy_db_type db_type) } -/** @brief - Use other database handler if databasehandler is not compiled in +/** + Use other database handler if databasehandler is not compiled in. */ handlerton *ha_checktype(THD *thd, enum legacy_db_type database_type, bool no_substitute, bool report_error) @@ -280,15 +280,13 @@ handler *get_ha_partition(partition_info *part_info) #endif -/** @brief +/** Register handler error messages for use with my_error(). - SYNOPSIS - ha_init_errors() - - RETURN + @retval 0 OK - != 0 Error + @retval + !=0 Error */ static int ha_init_errors(void) { @@ -349,15 +347,13 @@ static int ha_init_errors(void) } -/** @brief +/** Unregister handler error messages. - SYNOPSIS - ha_finish_errors() - - RETURN + @retval 0 OK - != 0 Error + @retval + !=0 Error */ static int ha_finish_errors(void) { @@ -567,8 +563,9 @@ static my_bool closecon_handlerton(THD *thd, plugin_ref plugin, } -/** @brief - don't bother to rollback here, it's done already +/** + @note + don't bother to rollback here, it's done already */ void ha_close_connection(THD* thd) { @@ -578,17 +575,16 @@ void ha_close_connection(THD* thd) /* ======================================================================== ======================= TRANSACTIONS ===================================*/ -/** @brief - Register a storage engine for a transaction +/** + Register a storage engine for a transaction. - DESCRIPTION - Every storage engine MUST call this function when it starts - a transaction or a statement (that is it must be called both for the - "beginning of transaction" and "beginning of statement"). - Only storage engines registered for the transaction/statement - will know when to commit/rollback it. + Every storage engine MUST call this function when it starts + a transaction or a statement (that is it must be called both for the + "beginning of transaction" and "beginning of statement"). + Only storage engines registered for the transaction/statement + will know when to commit/rollback it. - NOTE + @note trans_register_ha is idempotent - storage engine may register many times per transaction. @@ -620,10 +616,11 @@ void trans_register_ha(THD *thd, bool all, handlerton *ht_arg) DBUG_VOID_RETURN; } -/** @brief - RETURN - 0 - ok - 1 - error, transaction was rolled back +/** + @retval + 0 ok + @retval + 1 error, transaction was rolled back */ int ha_prepare(THD *thd) { @@ -660,11 +657,19 @@ int ha_prepare(THD *thd) DBUG_RETURN(error); } -/** @brief - RETURN - 0 - ok - 1 - transaction was rolled back - 2 - error during commit, data may be inconsistent +/** + @retval + 0 ok + @retval + 1 transaction was rolled back + @retval + 2 error during commit, data may be inconsistent + + @todo + Since we don't support nested statement transactions in 5.0, + we can't commit or rollback stmt transactions while we are inside + stored functions or triggers. So we simply do nothing now. + TODO: This should be fixed in later ( >= 5.1) releases. */ int ha_commit_trans(THD *thd, bool all) { @@ -757,9 +762,9 @@ end: DBUG_RETURN(error); } -/** @brief - NOTE - this function does not care about global read lock. - A caller should. +/** + @note + This function does not care about global read lock. A caller should. */ int ha_commit_one_phase(THD *thd, bool all) { @@ -869,13 +874,16 @@ int ha_rollback_trans(THD *thd, bool all) DBUG_RETURN(error); } -/** @brief - This is used to commit or rollback a single statement depending on the value - of error. Note that if the autocommit is on, then the following call inside - InnoDB will commit or rollback the whole transaction (= the statement). The - autocommit mechanism built into InnoDB is based on counting locks, but if - the user has used LOCK TABLES then that mechanism does not know to do the - commit. +/** + This is used to commit or rollback a single statement depending on + the value of error. + + @note + Note that if the autocommit is on, then the following call inside + InnoDB will commit or rollback the whole transaction (= the statement). The + autocommit mechanism built into InnoDB is based on counting locks, but if + the user has used LOCK TABLES then that mechanism does not know to do the + commit. */ int ha_autocommit_or_rollback(THD *thd, int error) { @@ -944,7 +952,10 @@ int ha_commit_or_rollback_by_xid(XID *xid, bool commit) #ifndef DBUG_OFF -/* this does not need to be multi-byte safe or anything */ +/** + @note + This does not need to be multi-byte safe or anything +*/ static char* xid_to_str(char *buf, XID *xid) { int i; @@ -996,24 +1007,21 @@ static char* xid_to_str(char *buf, XID *xid) } #endif -/** @brief - recover() step of xa - - NOTE - there are three modes of operation: - - - automatic recover after a crash - in this case commit_list != 0, tc_heuristic_recover==0 - all xids from commit_list are committed, others are rolled back - - - manual (heuristic) recover - in this case commit_list==0, tc_heuristic_recover != 0 - DBA has explicitly specified that all prepared transactions should - be committed (or rolled back). - - - no recovery (MySQL did not detect a crash) - in this case commit_list==0, tc_heuristic_recover == 0 - there should be no prepared transactions in this case. +/** + recover() step of xa. + + @note + there are three modes of operation: + - automatic recover after a crash + in this case commit_list != 0, tc_heuristic_recover==0 + all xids from commit_list are committed, others are rolled back + - manual (heuristic) recover + in this case commit_list==0, tc_heuristic_recover != 0 + DBA has explicitly specified that all prepared transactions should + be committed (or rolled back). + - no recovery (MySQL did not detect a crash) + in this case commit_list==0, tc_heuristic_recover == 0 + there should be no prepared transactions in this case. */ struct xarecover_st { @@ -1146,10 +1154,10 @@ int ha_recover(HASH *commit_list) DBUG_RETURN(0); } -/** @brief - return the list of XID's to a client, the same way SHOW commands do +/** + return the list of XID's to a client, the same way SHOW commands do. - NOTE + @note I didn't find in XA specs that an RM cannot return the same XID twice, so mysql_xa_recover does not filter XID's to ensure uniqueness. It can be easily fixed later, if necessary. @@ -1195,7 +1203,8 @@ bool mysql_xa_recover(THD *thd) DBUG_RETURN(0); } -/** @brief +/** + @details This function should be called when MySQL sends rows of a SELECT result set or the EOF mark to the client. It releases a possible adaptive hash index S-latch held by thd in InnoDB and also releases a possible InnoDB query @@ -1207,9 +1216,10 @@ bool mysql_xa_recover(THD *thd) performs another SQL query. In MySQL-4.1 this is even more important because there a connection can have several SELECT queries open at the same time. - arguments: - thd: the thread handle of the current connection - return value: always 0 + @param thd the thread handle of the current connection + + @return + always 0 */ static my_bool release_temporary_latches(THD *thd, plugin_ref plugin, void *unused) @@ -1276,8 +1286,9 @@ int ha_rollback_to_savepoint(THD *thd, SAVEPOINT *sv) DBUG_RETURN(error); } -/** @brief - note, that according to the sql standard (ISO/IEC 9075-2:2003) +/** + @note + according to the sql standard (ISO/IEC 9075-2:2003) section "4.33.4 SQL-statements and transaction states", SAVEPOINT is *not* transaction-initiating SQL-statement */ @@ -1593,8 +1604,9 @@ int handler::ha_open(TABLE *table_arg, const char *name, int mode, } -/** @brief - Read first row (only) from a table +/** + Read first row (only) from a table. + This is never called for InnoDB tables, as these table types has the HA_STATS_RECORDS_IS_EXACT set. */ @@ -1627,16 +1639,16 @@ int handler::read_first_row(uchar * buf, uint primary_key) DBUG_RETURN(error); } -/** @brief - Generate the next auto-increment number based on increment and offset: +/** + Generate the next auto-increment number based on increment and offset. computes the lowest number - strictly greater than "nr" - of the form: auto_increment_offset + N * auto_increment_increment In most cases increment= offset= 1, in which case we get: - 1,2,3,4,5,... - If increment=10 and offset=5 and previous number is 1, we get: - 1,5,15,25,35,... + @verbatim 1,2,3,4,5,... @endverbatim + If increment=10 and offset=5 and previous number is 1, we get: + @verbatim 1,5,15,25,35,... @endverbatim */ inline ulonglong compute_next_insert_id(ulonglong nr,struct system_variables *variables) @@ -1702,23 +1714,10 @@ prev_insert_id(ulonglong nr, struct system_variables *variables) } -/* - Update the auto_increment field if necessary - - SYNOPSIS - update_auto_increment() - - RETURN - 0 ok - HA_ERR_AUTOINC_READ_FAILED - get_auto_increment() was called and returned ~(ulonglong) 0 - HA_ERR_AUTOINC_ERANGE - storing value in field caused strict mode failure. - - - IMPLEMENTATION +/** + Update the auto_increment field if necessary. - Updates the record's Field of type NEXT_NUMBER if: + Updates columns with type NEXT_NUMBER if: - If column value is set to NULL (in which case auto_increment_field_not_null is 0) @@ -1769,13 +1768,20 @@ prev_insert_id(ulonglong nr, struct system_variables *variables) present in thd->auto_inc_intervals_in_cur_stmt_for_binlog it is added to this list. - TODO - + @todo Replace all references to "next number" or NEXT_NUMBER to "auto_increment", everywhere (see below: there is table->auto_increment_field_not_null, and there also exists table->next_number_field, it's not consistent). + @retval + 0 ok + @retval + HA_ERR_AUTOINC_READ_FAILED get_auto_increment() was called and + returned ~(ulonglong) 0 + @retval + HA_ERR_AUTOINC_ERANGE storing value in field caused strict mode + failure. */ #define AUTO_INC_DEFAULT_NB_ROWS 1 // Some prefer 1024 here @@ -2079,14 +2085,14 @@ void handler::print_keydup_error(uint key_nr, const char *msg) } -/** @brief - Print error that we got from handler function +/** + Print error that we got from handler function. - NOTE - In case of delete table it's only safe to use the following parts of - the 'table' structure: - table->s->path - table->alias + @note + In case of delete table it's only safe to use the following parts of + the 'table' structure: + - table->s->path + - table->alias */ void handler::print_error(int error, myf errflag) { @@ -2273,14 +2279,14 @@ void handler::print_error(int error, myf errflag) } -/** @brief - Return an error message specific to this handler +/** + Return an error message specific to this handler. - SYNOPSIS - error error code previously returned by handler - buf Pointer to String where to add error message + @param error error code previously returned by handler + @param buf pointer to String where to add error message - Returns true if this is a temporary error + @return + Returns true if this is a temporary error */ bool handler::get_error_message(int error, String* buf) { @@ -2387,8 +2393,10 @@ err: -/** @brief - Return key if error because of duplicated keys */ +/** + @return + key if error because of duplicated keys +*/ uint handler::get_dup_key(int error) { DBUG_ENTER("handler::get_dup_key"); @@ -2401,21 +2409,20 @@ uint handler::get_dup_key(int error) } -/** @brief - Delete all files with extension from bas_ext() +/** + Delete all files with extension from bas_ext(). - SYNOPSIS - delete_table() - name Base name of table + @param name Base name of table - NOTES + @note We assume that the handler may return more extensions than was actually used for the file. - RETURN + @retval 0 If we successfully deleted at least one file from base_ext and - didn't get any other errors than ENOENT - # Error + didn't get any other errors than ENOENT + @retval + !0 Error */ int handler::delete_table(const char *name) { @@ -2462,21 +2469,20 @@ void handler::drop_table(const char *name) } -/** @brief - Performs checks upon the table. - - SYNOPSIS - check() - thd thread doing CHECK TABLE operation - check_opt options from the parser - - NOTES - - RETURN - HA_ADMIN_OK Successful upgrade - HA_ADMIN_NEEDS_UPGRADE Table has structures requiring upgrade - HA_ADMIN_NEEDS_ALTER Table has structures requiring ALTER TABLE - HA_ADMIN_NOT_IMPLEMENTED +/** + Performs checks upon the table. + + @param thd thread doing CHECK TABLE operation + @param check_opt options from the parser + + @retval + HA_ADMIN_OK Successful upgrade + @retval + HA_ADMIN_NEEDS_UPGRADE Table has structures requiring upgrade + @retval + HA_ADMIN_NEEDS_ALTER Table has structures requiring ALTER TABLE + @retval + HA_ADMIN_NOT_IMPLEMENTED */ int handler::ha_check(THD *thd, HA_CHECK_OPT *check_opt) { @@ -2511,7 +2517,7 @@ int handler::ha_repair(THD* thd, HA_CHECK_OPT* check_opt) } -/** @brief +/** Tell the storage engine that it is allowed to "disable transaction" in the handler. It is a hint that ACID is not required - it is used in NDB for ALTER TABLE, for example, when data are copied to temporary table. @@ -2620,15 +2626,12 @@ void handler::get_dynamic_partition_info(PARTITION_INFO *stat_info, ** Some general functions that isn't in the handler class ****************************************************************************/ -/** @brief - Initiates table-file and calls appropriate database-creator +/** + Initiates table-file and calls appropriate database-creator. - NOTES - We must have a write lock on LOCK_open to be sure no other thread - interferes with table - - RETURN + @retval 0 ok + @retval 1 error */ int ha_create_table(THD *thd, const char *path, @@ -2666,17 +2669,18 @@ err: DBUG_RETURN(error != 0); } -/** @brief - Try to discover table from engine +/** + Try to discover table from engine. - NOTES + @note If found, write the frm file to disk. - RETURN VALUES: + @retval -1 Table did not exists + @retval 0 Table created ok + @retval > 0 Error, table existed but could not be created - */ int ha_create_table_from_engine(THD* thd, const char *db, const char *name) { @@ -2747,8 +2751,8 @@ void st_ha_check_opt::init() call to ha_init_key_cache() (probably out of memory) *****************************************************************************/ -/** @brief - Init a key cache if it has not been initied before +/** + Init a key cache if it has not been initied before. */ int ha_init_key_cache(const char *name, KEY_CACHE *key_cache) { @@ -2771,8 +2775,8 @@ int ha_init_key_cache(const char *name, KEY_CACHE *key_cache) } -/** @brief - Resize key cache +/** + Resize key cache. */ int ha_resize_key_cache(KEY_CACHE *key_cache) { @@ -2794,7 +2798,7 @@ int ha_resize_key_cache(KEY_CACHE *key_cache) } -/** @brief +/** Change parameters for key cache (like size) */ int ha_change_key_cache_param(KEY_CACHE *key_cache) @@ -2810,8 +2814,8 @@ int ha_change_key_cache_param(KEY_CACHE *key_cache) return 0; } -/** @brief - Free memory allocated by a key cache +/** + Free memory allocated by a key cache. */ int ha_end_key_cache(KEY_CACHE *key_cache) { @@ -2819,8 +2823,8 @@ int ha_end_key_cache(KEY_CACHE *key_cache) return 0; } -/** @brief - Move all tables from one key cache to another one +/** + Move all tables from one key cache to another one. */ int ha_change_key_cache(KEY_CACHE *old_key_cache, KEY_CACHE *new_key_cache) @@ -2830,13 +2834,15 @@ int ha_change_key_cache(KEY_CACHE *old_key_cache, } -/** @brief - Try to discover one table from handler(s) - - RETURN - -1 : Table did not exists - 0 : OK. In this case *frmblob and *frmlen are set - >0 : error. frmblob and frmlen may not be set +/** + Try to discover one table from handler(s). + + @retval + -1 Table did not exists + @retval + 0 OK. In this case *frmblob and *frmlen are set + @retval + >0 error. frmblob and frmlen may not be set */ struct st_discover_args { @@ -2881,9 +2887,9 @@ int ha_discover(THD *thd, const char *db, const char *name, } -/** @brief - Call this function in order to give the handler the possibility - to ask engine if there are any new tables that should be written to disk +/** + Call this function in order to give the handler the possiblity + to ask engine if there are any new tables that should be written to disk or any dropped tables that need to be removed from disk */ struct st_find_files_args @@ -2926,16 +2932,15 @@ ha_find_files(THD *thd,const char *db,const char *path, DBUG_RETURN(error); } -/* - Ask handler if the table exists in engine - - RETURN +/** + Ask handler if the table exists in engine. + @retval HA_ERR_NO_SUCH_TABLE Table does not exist + @retval HA_ERR_TABLE_EXIST Table exists - # Error code - - */ - + @retval + \# Error code +*/ struct st_table_exists_in_engine_args { const char *db; @@ -3110,29 +3115,29 @@ void ha_binlog_log_query(THD *thd, handlerton *hton, } #endif -/** @brief +/** Read the first row of a multi-range set. - SYNOPSIS - read_multi_range_first() - found_range_p Returns a pointer to the element in 'ranges' that - corresponds to the returned row. - ranges An array of KEY_MULTI_RANGE range descriptions. - range_count Number of ranges in 'ranges'. - sorted If result should be sorted per key. - buffer A HANDLER_BUFFER for internal handler usage. - - NOTES - Record is read into table->record[0]. - *found_range_p returns a valid value only if read_multi_range_first() + @param found_range_p Returns a pointer to the element in 'ranges' that + corresponds to the returned row. + @param ranges An array of KEY_MULTI_RANGE range descriptions. + @param range_count Number of ranges in 'ranges'. + @param sorted If result should be sorted per key. + @param buffer A HANDLER_BUFFER for internal handler usage. + + @note + - Record is read into table->record[0]. + - *found_range_p returns a valid value only if read_multi_range_first() returns 0. - Sorting is done within each range. If you want an overall sort, enter + - Sorting is done within each range. If you want an overall sort, enter 'ranges' with sorted ranges. - RETURN + @retval 0 OK, found a row + @retval HA_ERR_END_OF_FILE No rows in range - # Error code + @retval + \# Error code */ int handler::read_multi_range_first(KEY_MULTI_RANGE **found_range_p, KEY_MULTI_RANGE *ranges, uint range_count, @@ -3166,23 +3171,23 @@ int handler::read_multi_range_first(KEY_MULTI_RANGE **found_range_p, } -/** @brief +/** Read the next row of a multi-range set. - SYNOPSIS - read_multi_range_next() - found_range_p Returns a pointer to the element in 'ranges' that - corresponds to the returned row. + @param found_range_p Returns a pointer to the element in 'ranges' that + corresponds to the returned row. - NOTES - Record is read into table->record[0]. - *found_range_p returns a valid value only if read_multi_range_next() + @note + - Record is read into table->record[0]. + - *found_range_p returns a valid value only if read_multi_range_next() returns 0. - RETURN + @retval 0 OK, found a row + @retval HA_ERR_END_OF_FILE No (more) rows in range - # Error code + @retval + \# Error code */ int handler::read_multi_range_next(KEY_MULTI_RANGE **found_range_p) { @@ -3238,25 +3243,24 @@ scan_it_again: } -/** @brief +/** Read first row between two ranges. - Store ranges for future calls to read_range_next + Store ranges for future calls to read_range_next. - SYNOPSIS - read_range_first() - start_key Start key. Is 0 if no min range - end_key End key. Is 0 if no max range - eq_range_arg Set to 1 if start_key == end_key and the range endpoints - will not change during query execution. - sorted Set to 1 if result should be sorted per key - - NOTES + @param start_key Start key. Is 0 if no min range + @param end_key End key. Is 0 if no max range + @param eq_range_arg Set to 1 if start_key == end_key + @param sorted Set to 1 if result should be sorted per key + + @note Record is read into table->record[0] - RETURN + @retval 0 Found row + @retval HA_ERR_END_OF_FILE No rows in range - # Error code + @retval + \# Error code */ int handler::read_range_first(const key_range *start_key, const key_range *end_key, @@ -3292,19 +3296,18 @@ int handler::read_range_first(const key_range *start_key, } -/** @brief +/** Read next row between two ranges. - SYNOPSIS - read_range_next() - - NOTES + @note Record is read into table->record[0] - RETURN + @retval 0 Found row + @retval HA_ERR_END_OF_FILE No rows in range - # Error code + @retval + \# Error code */ int handler::read_range_next() { @@ -3325,22 +3328,20 @@ int handler::read_range_next() } -/** @brief - Compare if found key (in row) is over max-value +/** + Compare if found key (in row) is over max-value. - SYNOPSIS - compare_key - range range to compare to row. May be 0 for no range - - NOTES - See key.cc::key_cmp() for details + @param range range to compare to row. May be 0 for no range - RETURN + @seealso + key.cc::key_cmp() + + @return The return value is SIGN(key_in_row - range_key): - 0 Key is equal to range or 'range' == 0 (no range) - -1 Key is less than range - 1 Key is larger than range + - 0 : Key is equal to range or 'range' == 0 (no range) + - -1 : Key is less than range + - 1 : Key is larger than range */ int handler::compare_key(key_range *range) { @@ -3369,18 +3370,14 @@ int handler::index_read_idx_map(uchar * buf, uint index, const uchar * key, } -/** @brief +/** Returns a list of all known extensions. - SYNOPSIS - ha_known_exts() - - NOTES No mutexes, worst case race is a minor surplus memory allocation We have to recreate the extension map if mysqld is restarted (for example within libmysqld) - RETURN VALUE + @retval pointer pointer to TYPELIB structure */ static my_bool exts_handlerton(THD *unused, plugin_ref plugin, diff --git a/sql/handler.h b/sql/handler.h index 140b44704a9..c5b867e315f 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -959,11 +959,11 @@ uint calculate_key_len(TABLE *, uint, const uchar *, key_part_map); */ #define make_prev_keypart_map(N) (((key_part_map)1 << (N)) - 1) -/* +/** The handler class is the interface for dynamically loadable storage engines. Do not add ifdefs and take care when adding or changing virtual functions to avoid vtable confusion - */ +*/ class handler :public Sql_alloc { @@ -973,32 +973,12 @@ class handler :public Sql_alloc public: typedef ulonglong Table_flags; - - protected: +protected: struct st_table_share *table_share; /* The table definition */ struct st_table *table; /* The current open table */ Table_flags cached_table_flags; /* Set on init() and open() */ - virtual int index_init(uint idx, bool sorted) { active_index=idx; return 0; } - virtual int index_end() { active_index=MAX_KEY; return 0; } - /* - rnd_init() can be called two times without rnd_end() in between - (it only makes sense if scan=1). - then the second call should prepare for the new table scan (e.g - if rnd_init allocates the cursor, second call should position it - to the start of the table, no need to deallocate and allocate it again - */ - virtual int rnd_init(bool scan) =0; - virtual int rnd_end() { return 0; } - virtual Table_flags table_flags(void) const =0; - - void ha_statistic_increment(ulong SSV::*offset) const; - void **ha_data(THD *) const; - THD *ha_thd(void) const; - ha_rows estimation_rows_to_insert; - virtual void start_bulk_insert(ha_rows rows) {} - virtual int end_bulk_insert() {return 0; } public: handlerton *ht; /* storage engine of this handler */ uchar *ref; /* Pointer to current row */ @@ -1006,13 +986,13 @@ public: ha_statistics stats; - /* The following are for read_multi_range */ + /** The following are for read_multi_range */ bool multi_range_sorted; KEY_MULTI_RANGE *multi_range_curr; KEY_MULTI_RANGE *multi_range_end; HANDLER_BUFFER *multi_range_buffer; - /* The following are for read_range() */ + /** The following are for read_range() */ key_range save_end_range, *end_range; KEY_PART_INFO *range_key_part; int key_compare_result_on_equal; @@ -1021,14 +1001,14 @@ public: uint errkey; /* Last dup key */ uint key_used_on_scan; uint active_index; - /* Length of ref (1-8 or the clustered key length) */ + /** Length of ref (1-8 or the clustered key length) */ uint ref_length; FT_INFO *ft_handler; enum {NONE=0, INDEX, RND} inited; bool locked; bool implicit_emptied; /* Can be !=0 only if HEAP */ const COND *pushed_cond; - /* + /** next_insert_id is the next value which should be inserted into the auto_increment column: in a inserting-multi-row statement (like INSERT SELECT), for the first row where the autoinc value is not specified by the @@ -1038,14 +1018,14 @@ public: get_auto_increment(). */ ulonglong next_insert_id; - /* + /** insert id for the current row (*autogenerated*; if not autogenerated, it's 0). At first successful insertion, this variable is stored into THD::first_successful_insert_id_in_cur_stmt. */ ulonglong insert_id_for_cur_row; - /* + /** Interval returned by get_auto_increment() and being consumed by the inserter. */ @@ -1066,12 +1046,79 @@ public: /* TODO: DBUG_ASSERT(inited == NONE); */ } virtual handler *clone(MEM_ROOT *mem_root); - /* This is called after create to allow us to set up cached variables */ + /** This is called after create to allow us to set up cached variables */ void init() { cached_table_flags= table_flags(); } + /* ha_ methods: pubilc wrappers for private virtual API */ + int ha_open(TABLE *table, const char *name, int mode, int test_if_locked); + int ha_index_init(uint idx, bool sorted) + { + int result; + DBUG_ENTER("ha_index_init"); + DBUG_ASSERT(inited==NONE); + if (!(result= index_init(idx, sorted))) + inited=INDEX; + DBUG_RETURN(result); + } + int ha_index_end() + { + DBUG_ENTER("ha_index_end"); + DBUG_ASSERT(inited==INDEX); + inited=NONE; + DBUG_RETURN(index_end()); + } + int ha_rnd_init(bool scan) + { + int result; + DBUG_ENTER("ha_rnd_init"); + DBUG_ASSERT(inited==NONE || (inited==RND && scan)); + inited= (result= rnd_init(scan)) ? NONE: RND; + DBUG_RETURN(result); + } + int ha_rnd_end() + { + DBUG_ENTER("ha_rnd_end"); + DBUG_ASSERT(inited==RND); + inited=NONE; + DBUG_RETURN(rnd_end()); + } + int ha_reset(); + /* this is necessary in many places, e.g. in HANDLER command */ + int ha_index_or_rnd_end() + { + return inited == INDEX ? ha_index_end() : inited == RND ? ha_rnd_end() : 0; + } + Table_flags ha_table_flags() const { return cached_table_flags; } + /** + These functions represent the public interface to *users* of the + handler class, hence they are *not* virtual. For the inheritance + interface, see the (private) functions write_row(), update_row(), + and delete_row() below. + */ + int ha_external_lock(THD *thd, int lock_type); + int ha_write_row(uchar * buf); + int ha_update_row(const uchar * old_data, uchar * new_data); + int ha_delete_row(const uchar * buf); + void ha_release_auto_increment(); + + int ha_check_for_upgrade(HA_CHECK_OPT *check_opt); + /** to be actually called to get 'check()' functionality*/ + int ha_check(THD *thd, HA_CHECK_OPT *check_opt); + int ha_repair(THD* thd, HA_CHECK_OPT* check_opt); + void ha_start_bulk_insert(ha_rows rows) + { + estimation_rows_to_insert= rows; + start_bulk_insert(rows); + } + int ha_end_bulk_insert() + { + estimation_rows_to_insert= 0; + return end_bulk_insert(); + } + void adjust_next_insert_id_after_explicit_value(ulonglong nr); int update_auto_increment(); void print_keydup_error(uint key_nr, const char *msg); @@ -1092,7 +1139,7 @@ public: { return (ha_table_flags() & HA_NO_TRANSACTIONS) == 0; } virtual uint extra_rec_buf_length() const { return 0; } - /* + /** This method is used to analyse the error to see whether the error is ignorable or not, certain handlers can have more error that are ignorable than others. E.g. the partition handler can get inserts @@ -1112,12 +1159,12 @@ public: return TRUE; } - /* + /** Number of rows in table. It will only be called if (table_flags() & (HA_HAS_RECORDS | HA_STATS_RECORDS_IS_EXACT)) != 0 */ virtual ha_rows records() { return stats.records; } - /* + /** Return upper bound of current number of records in the table (max. of how many records one will retrieve when doing a full table scan) If upper bound is not known, HA_POS_ERROR should be returned as a max @@ -1126,7 +1173,7 @@ public: virtual ha_rows estimate_rows_upper_bound() { return stats.records+EXTRA_RECORDS; } - /* + /** Get the row type from the storage engine. If this method returns ROW_TYPE_NOT_USED, the information in HA_CREATE_INFO should be used. */ @@ -1134,47 +1181,8 @@ public: virtual const char *index_type(uint key_number) { DBUG_ASSERT(0); return "";} - int ha_index_init(uint idx, bool sorted) - { - int result; - DBUG_ENTER("ha_index_init"); - DBUG_ASSERT(inited==NONE); - if (!(result= index_init(idx, sorted))) - inited=INDEX; - DBUG_RETURN(result); - } - int ha_index_end() - { - DBUG_ENTER("ha_index_end"); - DBUG_ASSERT(inited==INDEX); - inited=NONE; - DBUG_RETURN(index_end()); - } - int ha_rnd_init(bool scan) - { - int result; - DBUG_ENTER("ha_rnd_init"); - DBUG_ASSERT(inited==NONE || (inited==RND && scan)); - inited= (result= rnd_init(scan)) ? NONE: RND; - DBUG_RETURN(result); - } - int ha_rnd_end() - { - DBUG_ENTER("ha_rnd_end"); - DBUG_ASSERT(inited==RND); - inited=NONE; - DBUG_RETURN(rnd_end()); - } - int ha_reset(); - - /* this is necessary in many places, e.g. in HANDLER command */ - int ha_index_or_rnd_end() - { - return inited == INDEX ? ha_index_end() : inited == RND ? ha_rnd_end() : 0; - } - Table_flags ha_table_flags() const { return cached_table_flags; } - /* + /** Signal that the table->read_set and table->write_set table maps changed The handler is allowed to set additional bits in the above map in this call. Normally the handler should ignore all calls until we have done @@ -1183,50 +1191,30 @@ public: */ virtual void column_bitmaps_signal(); uint get_index(void) const { return active_index; } - virtual int open(const char *name, int mode, uint test_if_locked)=0; virtual int close(void)=0; - /* - These functions represent the public interface to *users* of the - handler class, hence they are *not* virtual. For the inheritance - interface, see the (private) functions write_row(), update_row(), - and delete_row() below. - */ - int ha_external_lock(THD *thd, int lock_type); - int ha_write_row(uchar * buf); - int ha_update_row(const uchar * old_data, uchar * new_data); - int ha_delete_row(const uchar * buf); - - /* - SYNOPSIS - start_bulk_update() - RETURN - 0 Bulk update used by handler - 1 Bulk update not used, normal operation used + /** + @retval 0 Bulk update used by handler + @retval 1 Bulk update not used, normal operation used */ virtual bool start_bulk_update() { return 1; } - /* - SYNOPSIS - start_bulk_delete() - RETURN - 0 Bulk delete used by handler - 1 Bulk delete not used, normal operation used + /** + @retval 0 Bulk delete used by handler + @retval 1 Bulk delete not used, normal operation used */ virtual bool start_bulk_delete() { return 1; } - /* - SYNOPSIS + /** This method is similar to update_row, however the handler doesn't need to execute the updates at this point in time. The handler can be certain that another call to bulk_update_row will occur OR a call to exec_bulk_update before the set of updates in this query is concluded. - bulk_update_row() - old_data Old record - new_data New record - dup_key_found Number of duplicate keys found - RETURN - 0 Bulk delete used by handler - 1 Bulk delete not used, normal operation used + @param old_data Old record + @param new_data New record + @param dup_key_found Number of duplicate keys found + + @retval 0 Bulk delete used by handler + @retval 1 Bulk delete not used, normal operation used */ virtual int bulk_update_row(const uchar *old_data, uchar *new_data, uint *dup_key_found) @@ -1234,53 +1222,38 @@ public: DBUG_ASSERT(FALSE); return HA_ERR_WRONG_COMMAND; } - /* - SYNOPSIS + /** After this call all outstanding updates must be performed. The number of duplicate key errors are reported in the duplicate key parameter. It is allowed to continue to the batched update after this call, the handler has to wait until end_bulk_update with changing state. - exec_bulk_update() - dup_key_found Number of duplicate keys found - RETURN - 0 Success - >0 Error code + @param dup_key_found Number of duplicate keys found + + @retval 0 Success + @retval >0 Error code */ virtual int exec_bulk_update(uint *dup_key_found) { DBUG_ASSERT(FALSE); return HA_ERR_WRONG_COMMAND; } - /* - SYNOPSIS + /** Perform any needed clean-up, no outstanding updates are there at the moment. - - end_bulk_update() - RETURN - Nothing */ virtual void end_bulk_update() { return; } - /* - SYNOPSIS + /** Execute all outstanding deletes and close down the bulk delete. - end_bulk_delete() - RETURN - 0 Success - >0 Error code + @retval 0 Success + @retval >0 Error code */ virtual int end_bulk_delete() { DBUG_ASSERT(FALSE); return HA_ERR_WRONG_COMMAND; } - private: - virtual int index_read(uchar * buf, const uchar * key, uint key_len, - enum ha_rkey_function find_flag) - { return HA_ERR_WRONG_COMMAND; } - public: /** @brief Positions an index cursor to the index specified in the handle. Fetches the @@ -1312,10 +1285,6 @@ public: virtual int index_last(uchar * buf) { return HA_ERR_WRONG_COMMAND; } virtual int index_next_same(uchar *buf, const uchar *key, uint keylen); - private: - virtual int index_read_last(uchar * buf, const uchar * key, uint key_len) - { return (my_errno=HA_ERR_WRONG_COMMAND); } - public: /** @brief The following functions works like index_read, but it find the last @@ -1343,11 +1312,11 @@ public: virtual int ft_read(uchar *buf) { return HA_ERR_WRONG_COMMAND; } virtual int rnd_next(uchar *buf)=0; virtual int rnd_pos(uchar * buf, uchar *pos)=0; - /* - one has to use this method when to find + /** + One has to use this method when to find random position by record as the plain position() call doesn't work for some - handlers for random position + handlers for random position. */ virtual int rnd_pos_by_record(uchar *record) { @@ -1355,9 +1324,9 @@ public: return rnd_pos(record, ref); } virtual int read_first_row(uchar *buf, uint primary_key); - /* + /** The following function is only needed for tables that may be temporary - tables during joins + tables during joins. */ virtual int restart_rnd_next(uchar *buf, uchar *pos) { return HA_ERR_WRONG_COMMAND; } @@ -1374,13 +1343,7 @@ public: virtual int extra_opt(enum ha_extra_function operation, ulong cache_size) { return extra(operation); } - /* - Reset state of file to after 'open' - This function is called after every statement for all tables used - by that statement. - */ - virtual int reset() { return 0; } - /* + /** In an UPDATE or DELETE, if the row under the cursor was locked by another transaction, and the engine used an optimistic read of the last committed row value under the cursor, then the engine returns 1 from this @@ -1393,7 +1356,7 @@ public: engine that the next read will be a locking re-read of the row. */ virtual bool was_semi_consistent_read() { return 0; } - /* + /** Tell the engine whether it should avoid unnecessary lock waits. If yes, in an UPDATE or DELETE, if the row under the cursor was locked by another transaction, the engine may try an optimistic read of @@ -1402,7 +1365,7 @@ public: virtual void try_semi_consistent_read(bool) {} virtual void unlock_row() {} virtual int start_stmt(THD *thd, thr_lock_type lock_type) {return 0;} - /* + /** This is called to delete all rows in a table If the handler don't support this, then this function will return HA_ERR_WRONG_COMMAND and MySQL will delete the rows one @@ -1414,10 +1377,6 @@ public: ulonglong nb_desired_values, ulonglong *first_value, ulonglong *nb_reserved_values); -private: - virtual void release_auto_increment() { return; }; -public: - void ha_release_auto_increment(); void set_next_insert_id(ulonglong id) { DBUG_PRINT("info",("auto_increment: next value %lu", (ulong)id)); @@ -1438,7 +1397,7 @@ public: next_insert_id= (prev_insert_id > 0) ? prev_insert_id : insert_id_for_cur_row; } - /* + /** Reset the auto-increment counter to the given value, i.e. the next row inserted will get the given value. This is called e.g. after TRUNCATE is emulated by doing a 'DELETE FROM t'. HA_ERR_WRONG_COMMAND is @@ -1448,39 +1407,15 @@ public: { return HA_ERR_WRONG_COMMAND; } virtual void update_create_info(HA_CREATE_INFO *create_info) {} -protected: - /* to be implemented in handlers */ - - /* admin commands - called from mysql_admin_table */ - virtual int check(THD* thd, HA_CHECK_OPT* check_opt) - { return HA_ADMIN_NOT_IMPLEMENTED; } - - /* - in these two methods check_opt can be modified - to specify CHECK option to use to call check() - upon the table - */ - virtual int check_for_upgrade(HA_CHECK_OPT *check_opt) - { return 0; } -public: - int ha_check_for_upgrade(HA_CHECK_OPT *check_opt); int check_old_types(); - /* to be actually called to get 'check()' functionality*/ - int ha_check(THD *thd, HA_CHECK_OPT *check_opt); - virtual int backup(THD* thd, HA_CHECK_OPT* check_opt) { return HA_ADMIN_NOT_IMPLEMENTED; } - /* - restore assumes .frm file must exist, and that generate_table() has been + /** + Restore assumes .frm file must exist, and that generate_table() has been called; It will just copy the data file and run repair. */ virtual int restore(THD* thd, HA_CHECK_OPT* check_opt) { return HA_ADMIN_NOT_IMPLEMENTED; } -protected: - virtual int repair(THD* thd, HA_CHECK_OPT* check_opt) - { return HA_ADMIN_NOT_IMPLEMENTED; } -public: - int ha_repair(THD* thd, HA_CHECK_OPT* check_opt); virtual int optimize(THD* thd, HA_CHECK_OPT* check_opt) { return HA_ADMIN_NOT_IMPLEMENTED; } virtual int analyze(THD* thd, HA_CHECK_OPT* check_opt) @@ -1496,33 +1431,21 @@ public: virtual int disable_indexes(uint mode) { return HA_ERR_WRONG_COMMAND; } virtual int enable_indexes(uint mode) { return HA_ERR_WRONG_COMMAND; } virtual int indexes_are_disabled(void) {return 0;} - void ha_start_bulk_insert(ha_rows rows) - { - estimation_rows_to_insert= rows; - start_bulk_insert(rows); - } - int ha_end_bulk_insert() - { - estimation_rows_to_insert= 0; - return end_bulk_insert(); - } virtual int discard_or_import_tablespace(my_bool discard) {return HA_ERR_WRONG_COMMAND;} virtual int net_read_dump(NET* net) { return HA_ERR_WRONG_COMMAND; } virtual char *update_table_comment(const char * comment) { return (char*) comment;} virtual void append_create_info(String *packet) {} - /* - SYNOPSIS - is_fk_defined_on_table_or_index() - index Index to check if foreign key uses it - RETURN VALUE - TRUE Foreign key defined on table or index - FALSE No foreign key defined - DESCRIPTION - If index == MAX_KEY then a check for table is made and if index < - MAX_KEY then a check is made if the table has foreign keys and if - a foreign key uses this index (and thus the index cannot be dropped). + /** + If index == MAX_KEY then a check for table is made and if index < + MAX_KEY then a check is made if the table has foreign keys and if + a foreign key uses this index (and thus the index cannot be dropped). + + @param index Index to check if foreign key uses it + + @retval TRUE Foreign key defined on table or index + @retval FALSE No foreign key defined */ virtual bool is_fk_defined_on_table_or_index(uint index) { return FALSE; } @@ -1530,18 +1453,18 @@ public: { return(NULL);} /* gets foreign key create string from InnoDB */ virtual char* get_tablespace_name(THD *thd, char *name, uint name_len) { return(NULL);} /* gets tablespace name from handler */ - /* used in ALTER TABLE; 1 if changing storage engine is allowed */ + /** used in ALTER TABLE; 1 if changing storage engine is allowed */ virtual bool can_switch_engines() { return 1; } - /* used in REPLACE; is > 0 if table is referred by a FOREIGN KEY */ + /** used in REPLACE; is > 0 if table is referred by a FOREIGN KEY */ virtual int get_foreign_key_list(THD *thd, List<FOREIGN_KEY_INFO> *f_key_list) { return 0; } virtual uint referenced_by_foreign_key() { return 0;} virtual void init_table_handle_for_HANDLER() { return; } /* prepare InnoDB for HANDLER */ virtual void free_foreign_key_create_info(char* str) {} - /* The following can be called without an open handler */ + /** The following can be called without an open handler */ virtual const char *table_type() const =0; - /* + /** If frm_error() is called then we will use this to find out what file extentions exist for the storage engine. This is also used by the default rename_table and delete_table method in handler.cc. @@ -1598,14 +1521,14 @@ public: virtual bool is_crashed() const { return 0; } virtual bool auto_repair() const { return 0; } - /* + /** default rename_table() and delete_table() rename/delete files with a given name and extensions from bas_ext() */ virtual int rename_table(const char *from, const char *to); virtual int delete_table(const char *name); virtual void drop_table(const char *name); - + virtual int create(const char *name, TABLE *form, HA_CREATE_INFO *info)=0; #define CHF_CREATE_FLAG 0 @@ -1658,7 +1581,7 @@ public: THR_LOCK_DATA **to, enum thr_lock_type lock_type)=0; - /* Type of table for caching query */ + /** Type of table for caching query */ virtual uint8 table_cache_type() { return HA_CACHE_TBL_NONTRANSACT; } @@ -1704,56 +1627,54 @@ public: /* - RETURN - true Primary key (if there is one) is clustered key covering all fields - false otherwise + @retval TRUE Primary key (if there is one) is clustered + key covering all fields + @retval FALSE otherwise */ virtual bool primary_key_is_clustered() { return FALSE; } virtual int cmp_ref(const uchar *ref1, const uchar *ref2) { return memcmp(ref1, ref2, ref_length); } - + /* Condition pushdown to storage engines */ - /* + /** Push condition down to the table handler. - SYNOPSIS - cond_push() - cond Condition to be pushed. The condition tree must not be - modified by the by the caller. - RETURN + @param cond Condition to be pushed. The condition tree must not be + modified by the by the caller. + + @return The 'remainder' condition that caller must use to filter out records. NULL means the handler will not return rows that do not match the passed condition. - NOTES + @note The pushed conditions form a stack (from which one can remove the last pushed condition using cond_pop). The table handler filters out rows using (pushed_cond1 AND pushed_cond2 AND ... AND pushed_condN) or less restrictive condition, depending on handler's capabilities. - + handler->ha_reset() call empties the condition stack. Calls to rnd_init/rnd_end, index_init/index_end etc do not affect the condition stack. */ virtual const COND *cond_push(const COND *cond) { return cond; }; - /* + /** Pop the top condition from the condition stack of the handler instance. - SYNOPSIS - cond_pop() - Pops the top if condition stack, if stack is not empty + + Pops the top if condition stack, if stack is not empty. */ virtual void cond_pop() { return; }; virtual bool check_if_incompatible_data(HA_CREATE_INFO *create_info, uint table_changes) { return COMPATIBLE_DATA_NO; } - /* These are only called from sql_select for internal temporary tables */ + /** These are only called from sql_select for internal temporary tables */ virtual int write_row(uchar *buf __attribute__((unused))) { return HA_ERR_WRONG_COMMAND; @@ -1769,20 +1690,44 @@ public: { return HA_ERR_WRONG_COMMAND; } - /* + /** use_hidden_primary_key() is called in case of an update/delete when (table_flags() and HA_PRIMARY_KEY_REQUIRED_FOR_DELETE) is defined but we don't have a primary key */ virtual void use_hidden_primary_key(); +protected: + /* Service methods for use by storage engines. */ + void ha_statistic_increment(ulong SSV::*offset) const; + void **ha_data(THD *) const; + THD *ha_thd(void) const; private: /* - Row-level primitives for storage engines. These should be + Low-level primitives for storage engines. These should be overridden by the storage engine class. To call these methods, use the corresponding 'ha_*' method above. */ + virtual int open(const char *name, int mode, uint test_if_locked)=0; + virtual int index_init(uint idx, bool sorted) { active_index= idx; return 0; } + virtual int index_end() { active_index= MAX_KEY; return 0; } + /** + rnd_init() can be called two times without rnd_end() in between + (it only makes sense if scan=1). + then the second call should prepare for the new table scan (e.g + if rnd_init allocates the cursor, second call should position it + to the start of the table, no need to deallocate and allocate it again + */ + virtual int rnd_init(bool scan)= 0; + virtual int rnd_end() { return 0; } + /** + Reset state of file to after 'open'. + This function is called after every statement for all tables used + by that statement. + */ + virtual int reset() { return 0; } + virtual Table_flags table_flags(void) const= 0; /** Is not invoked for non-transactional temporary tables. @@ -1810,8 +1755,30 @@ private: { return 0; } + virtual void release_auto_increment() { return; }; + /** admin commands - called from mysql_admin_table */ + virtual int check_for_upgrade(HA_CHECK_OPT *check_opt) + { return 0; } + virtual int check(THD* thd, HA_CHECK_OPT* check_opt) + { return HA_ADMIN_NOT_IMPLEMENTED; } + + /** + In this method check_opt can be modified + to specify CHECK option to use to call check() + upon the table. + */ + virtual int repair(THD* thd, HA_CHECK_OPT* check_opt) + { return HA_ADMIN_NOT_IMPLEMENTED; } + virtual void start_bulk_insert(ha_rows rows) {} + virtual int end_bulk_insert() { return 0; } + virtual int index_read(uchar * buf, const uchar * key, uint key_len, + enum ha_rkey_function find_flag) + { return HA_ERR_WRONG_COMMAND; } + virtual int index_read_last(uchar * buf, const uchar * key, uint key_len) + { return (my_errno= HA_ERR_WRONG_COMMAND); } }; + /* Some extern variables used with handlers */ extern const char *ha_row_type[]; diff --git a/sql/hostname.cc b/sql/hostname.cc index 34384a9c8c0..c8cf46383a9 100644 --- a/sql/hostname.cc +++ b/sql/hostname.cc @@ -14,9 +14,14 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* - Get hostname for an IP. Hostnames are checked with reverse name lookup and - checked that they doesn't resemble an ip. +/** + @file + + @brief + Get hostname for an IP. + + Hostnames are checked with reverse name lookup and + checked that they doesn't resemble an ip. */ #include "mysql_priv.h" diff --git a/sql/init.cc b/sql/init.cc index 73feaa797c3..aee0eb7179c 100644 --- a/sql/init.cc +++ b/sql/init.cc @@ -14,7 +14,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* Init and dummy functions for interface with unireg */ +/** + @file + + @brief + Init and dummy functions for interface with unireg +*/ #include "mysql_priv.h" #include <m_ctype.h> diff --git a/sql/item.cc b/sql/item.cc index 922c3b7a976..463de3e1c52 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -95,6 +95,10 @@ void Hybrid_type_traits_decimal::add(Hybrid_type *val, Field *f) const } +/** + @todo + what is '4' for scale? +*/ void Hybrid_type_traits_decimal::div(Hybrid_type *val, ulonglong u) const { int2my_decimal(E_DEC_FATAL_ERROR, u, TRUE, &val->dec_buf[2]); @@ -156,7 +160,9 @@ Hybrid_type_traits_integer::fix_length_and_dec(Item *item, Item *arg) const ** Item functions *****************************************************************************/ -/* Init all special items */ +/** + Init all special items. +*/ void item_init(void) { @@ -165,8 +171,9 @@ void item_init(void) } -/* -TODO: make this functions class dependent +/** + @todo + Make this functions class dependent */ bool Item::val_bool() @@ -396,10 +403,12 @@ Item::Item(): } } -/* - Constructor used by Item_field, Item_*_ref & aggregate (sum) functions. +/** + Constructor used by Item_field, Item_ref & aggregate (sum) + functions. + Used for duplicating lists in processing queries with temporary - tables + tables. */ Item::Item(THD *thd, Item *item): rsize(0), @@ -456,12 +465,10 @@ void Item::cleanup() } -/* - cleanup() item if it is 'fixed' +/** + cleanup() item if it is 'fixed'. - SYNOPSIS - cleanup_processor() - arg - a dummy parameter, is not used here + @param arg a dummy parameter, is not used here */ bool Item::cleanup_processor(uchar *arg) @@ -472,12 +479,10 @@ bool Item::cleanup_processor(uchar *arg) } -/* - rename item (used for views, cleanup() return original name) +/** + rename item (used for views, cleanup() return original name). - SYNOPSIS - Item::rename() - new_name new name of item; + @param new_name new name of item; */ void Item::rename(char *new_name) @@ -492,36 +497,30 @@ void Item::rename(char *new_name) } -/* +/** Traverse item tree possibly transforming it (replacing items). - SYNOPSIS - Item::transform() - transformer functor that performs transformation of a subtree - arg opaque argument passed to the functor - - DESCRIPTION - This function is designed to ease transformation of Item trees. - - Re-execution note: every such transformation is registered for - rollback by THD::change_item_tree() and is rolled back at the end - of execution by THD::rollback_item_tree_changes(). + This function is designed to ease transformation of Item trees. + Re-execution note: every such transformation is registered for + rollback by THD::change_item_tree() and is rolled back at the end + of execution by THD::rollback_item_tree_changes(). - Therefore: + Therefore: + - this function can not be used at prepared statement prepare + (in particular, in fix_fields!), as only permanent + transformation of Item trees are allowed at prepare. + - the transformer function shall allocate new Items in execution + memory root (thd->mem_root) and not anywhere else: allocated + items will be gone in the end of execution. - - this function can not be used at prepared statement prepare - (in particular, in fix_fields!), as only permanent - transformation of Item trees are allowed at prepare. + If you don't need to transform an item tree, but only traverse + it, please use Item::walk() instead. - - the transformer function shall allocate new Items in execution - memory root (thd->mem_root) and not anywhere else: allocated - items will be gone in the end of execution. - If you don't need to transform an item tree, but only traverse - it, please use Item::walk() instead. + @param transformer functor that performs transformation of a subtree + @param arg opaque argument passed to the functor - - RETURN VALUE + @return Returns pointer to the new subtree root. THD::change_item_tree() should be called for it if transformation took place, i.e. if a pointer to newly allocated item is returned. @@ -549,7 +548,9 @@ Item_ident::Item_ident(Name_resolution_context *context_arg, } -/* Constructor used by Item_field & Item_*_ref (see Item comment) */ +/** + Constructor used by Item_field & Item_*_ref (see Item comment) +*/ Item_ident::Item_ident(THD *thd, Item_ident *item) :Item(thd, item), @@ -594,26 +595,22 @@ bool Item_ident::remove_dependence_processor(uchar * arg) } -/* +/** Store the pointer to this item field into a list if not already there. - SYNOPSIS - Item_field::collect_item_field_processor() - arg pointer to a List<Item_field> + The method is used by Item::walk to collect all unique Item_field objects + from a tree of Items into a set of items represented as a list. - DESCRIPTION - The method is used by Item::walk to collect all unique Item_field objects - from a tree of Items into a set of items represented as a list. + Item_cond::walk() and Item_func::walk() stop the evaluation of the + processor function for its arguments once the processor returns + true.Therefore in order to force this method being called for all item + arguments in a condition the method must return false. - IMPLEMENTATION - Item_cond::walk() and Item_func::walk() stop the evaluation of the - processor function for its arguments once the processor returns - true.Therefore in order to force this method being called for all item - arguments in a condition the method must return false. + @param arg pointer to a List<Item_field> - RETURN + @return FALSE to force the evaluation of collect_item_field_processor - for the subsequent items. + for the subsequent items. */ bool Item_field::collect_item_field_processor(uchar *arg) @@ -633,21 +630,19 @@ bool Item_field::collect_item_field_processor(uchar *arg) } -/* +/** Check if an Item_field references some field from a list of fields. - SYNOPSIS - Item_field::find_item_in_field_list_processor - arg Field being compared, arg must be of type Field + Check whether the Item_field represented by 'this' references any + of the fields in the keyparts passed via 'arg'. Used with the + method Item::walk() to test whether any keypart in a sequence of + keyparts is referenced in an expression. - DESCRIPTION - Check whether the Item_field represented by 'this' references any - of the fields in the keyparts passed via 'arg'. Used with the - method Item::walk() to test whether any keypart in a sequence of - keyparts is referenced in an expression. + @param arg Field being compared, arg must be of type Field - RETURN + @retval TRUE if 'this' references the field 'arg' + @retval FALSE otherwise */ @@ -739,7 +734,8 @@ void Item::set_name(const char *str, uint length, CHARSET_INFO *cs) } -/* +/** + @details This function is called when: - Comparing items in the WHERE clause (when doing where optimization) - When trying to find an ORDER BY/GROUP BY item in the SELECT part @@ -764,7 +760,8 @@ Item *Item::safe_charset_converter(CHARSET_INFO *tocs) } -/* +/** + @details Created mostly for mysql_prepare_table(). Important when a string ENUM/SET column is described with a numeric default value: @@ -891,10 +888,10 @@ bool Item_string::eq(const Item *item, bool binary_cmp) const } -/* +/** Get the value of the function as a MYSQL_TIME structure. As a extra convenience the time structure is reset on error! - */ +*/ bool Item::get_date(MYSQL_TIME *ltime,uint fuzzydate) { @@ -928,10 +925,11 @@ err: return 1; } -/* - Get time of first argument. +/** + Get time of first argument.\ + As a extra convenience the time structure is reset on error! - */ +*/ bool Item::get_time(MYSQL_TIME *ltime) { @@ -1310,27 +1308,25 @@ public: }; -/* - Move SUM items out from item tree and replace with reference +/** + Move SUM items out from item tree and replace with reference. - SYNOPSIS - split_sum_func2() - thd Thread handler - ref_pointer_array Pointer to array of reference fields - fields All fields in select - ref Pointer to item - skip_registered <=> function be must skipped for registered SUM items + @param thd Thread handler + @param ref_pointer_array Pointer to array of reference fields + @param fields All fields in select + @param ref Pointer to item + @param skip_registered <=> function be must skipped for registered + SUM items - NOTES - This is from split_sum_func2() for items that should be split + @note + This is from split_sum_func2() for items that should be split - All found SUM items are added FIRST in the fields list and - we replace the item with a reference. + All found SUM items are added FIRST in the fields list and + we replace the item with a reference. - thd->fatal_error() may be called if we are out of memory + thd->fatal_error() may be called if we are out of memory */ - void Item::split_sum_func2(THD *thd, Item **ref_pointer_array, List<Item> &fields, Item **ref, bool skip_registered) @@ -1397,41 +1393,42 @@ left_is_superset(DTCollation *left, DTCollation *right) return FALSE; } -/* - Aggregate two collations together taking - into account their coercibility (aka derivation): - - 0 == DERIVATION_EXPLICIT - an explicitly written COLLATE clause - 1 == DERIVATION_NONE - a mix of two different collations - 2 == DERIVATION_IMPLICIT - a column - 3 == DERIVATION_COERCIBLE - a string constant - - The most important rules are: - - 1. If collations are the same: - chose this collation, and the strongest derivation. - - 2. If collations are different: - - Character sets may differ, but only if conversion without - data loss is possible. The caller provides flags whether - character set conversion attempts should be done. If no - flags are substituted, then the character sets must be the same. - Currently processed flags are: - MY_COLL_ALLOW_SUPERSET_CONV - allow conversion to a superset - MY_COLL_ALLOW_COERCIBLE_CONV - allow conversion of a coercible value - - two EXPLICIT collations produce an error, e.g. this is wrong: - CONCAT(expr1 collate latin1_swedish_ci, expr2 collate latin1_german_ci) - - the side with smaller derivation value wins, - i.e. a column is stronger than a string constant, - an explicit COLLATE clause is stronger than a column. - - if derivations are the same, we have DERIVATION_NONE, - we'll wait for an explicit COLLATE clause which possibly can - come from another argument later: for example, this is valid, - but we don't know yet when collecting the first two arguments: - CONCAT(latin1_swedish_ci_column, - latin1_german1_ci_column, - expr COLLATE latin1_german2_ci) +/** + Aggregate two collations together taking + into account their coercibility (aka derivation):. + + 0 == DERIVATION_EXPLICIT - an explicitly written COLLATE clause @n + 1 == DERIVATION_NONE - a mix of two different collations @n + 2 == DERIVATION_IMPLICIT - a column @n + 3 == DERIVATION_COERCIBLE - a string constant. + + The most important rules are: + -# If collations are the same: + chose this collation, and the strongest derivation. + -# If collations are different: + - Character sets may differ, but only if conversion without + data loss is possible. The caller provides flags whether + character set conversion attempts should be done. If no + flags are substituted, then the character sets must be the same. + Currently processed flags are: + MY_COLL_ALLOW_SUPERSET_CONV - allow conversion to a superset + MY_COLL_ALLOW_COERCIBLE_CONV - allow conversion of a coercible value + - two EXPLICIT collations produce an error, e.g. this is wrong: + CONCAT(expr1 collate latin1_swedish_ci, expr2 collate latin1_german_ci) + - the side with smaller derivation value wins, + i.e. a column is stronger than a string constant, + an explicit COLLATE clause is stronger than a column. + - if derivations are the same, we have DERIVATION_NONE, + we'll wait for an explicit COLLATE clause which possibly can + come from another argument later: for example, this is valid, + but we don't know yet when collecting the first two arguments: + @code + CONCAT(latin1_swedish_ci_column, + latin1_german1_ci_column, + expr COLLATE latin1_german2_ci) + @endcode */ + bool DTCollation::aggregate(DTCollation &dt, uint flags) { if (!my_charset_same(collation, dt.collation)) @@ -1595,8 +1592,9 @@ bool agg_item_collations_for_comparison(DTCollation &c, const char *fname, } -/* +/** Collect arguments' character sets together. + We allow to apply automatic character set conversion in some cases. The conditions when conversion is possible are: - arguments A and B have different charsets @@ -1612,17 +1610,17 @@ bool agg_item_collations_for_comparison(DTCollation &c, const char *fname, to the collation of A. For functions with more than two arguments: - + @code collect(A,B,C) ::= collect(collect(A,B),C) - + @endcode Since this function calls THD::change_item_tree() on the passed Item ** pointers, it is necessary to pass the original Item **'s, not copies. Otherwise their values will not be properly restored (see BUG#20769). If the items are not consecutive (eg. args[2] and args[5]), use the item_sep argument, ie. - + @code agg_item_charsets(coll, fname, &args[2], 2, flags, 3) - + @endcode */ bool agg_item_charsets(DTCollation &coll, const char *fname, @@ -1744,6 +1742,13 @@ Item_field::Item_field(Field *f) } +/** + Constructor used inside setup_wild(). + + Ensures that field, table, and database names will live as long as + Item_field (this is important in prepared statements). +*/ + Item_field::Item_field(THD *thd, Name_resolution_context *context_arg, Field *f) :Item_ident(context_arg, f->table->s->db.str, *f->table_name, f->field_name), @@ -1795,7 +1800,10 @@ Item_field::Item_field(Name_resolution_context *context_arg, select->select_n_where_fields++; } -// Constructor need to process subselect with temporary tables (see Item) +/** + Constructor need to process subselect with temporary tables (see Item) +*/ + Item_field::Item_field(THD *thd, Item_field *item) :Item_ident(thd, item), field(item->field), @@ -1826,7 +1834,7 @@ void Item_field::set_field(Field *field_par) } -/* +/** Reset this item to point to a field from the new temporary table. This is used when we create a new temporary table for each execution of prepared statement. @@ -2095,9 +2103,9 @@ longlong Item_field::val_int_endpoint(bool left_endp, bool *incl_endp) return null_value? LONGLONG_MIN : res; } -/* +/** Create an item from a string we KNOW points to a valid longlong - end \0 terminated number string. + end \\0 terminated number string. This is always 'signed'. Unsigned values are created with Item_uint() */ @@ -2338,6 +2346,10 @@ double Item_string::val_real() } +/** + @todo + Give error if we wanted a signed integer and we got an unsigned one +*/ longlong Item_string::val_int() { DBUG_ASSERT(fixed == 1); @@ -2411,9 +2423,9 @@ Item *Item_null::safe_charset_converter(CHARSET_INFO *tocs) /*********************** Item_param related ******************************/ -/* +/** Default function of Item_param::set_param_func, so in case - of malformed packet the server won't SIGSEGV + of malformed packet the server won't SIGSEGV. */ static void @@ -2487,16 +2499,14 @@ void Item_param::set_double(double d) } -/* +/** Set decimal parameter value from string. - SYNOPSIS - set_decimal() - str - character string - length - string length + @param str character string + @param length string length - NOTE - as we use character strings to send decimal values in + @note + As we use character strings to send decimal values in binary protocol, we use str2my_decimal to convert it to internal decimal value. */ @@ -2517,16 +2527,14 @@ void Item_param::set_decimal(const char *str, ulong length) } -/* +/** Set parameter value from MYSQL_TIME value. - SYNOPSIS - set_time() - tm - datetime value to set (time_type is ignored) - type - type of datetime value - max_length_arg - max length of datetime value as string + @param tm datetime value to set (time_type is ignored) + @param type type of datetime value + @param max_length_arg max length of datetime value as string - NOTE + @note If we value to be stored is not normalized, zero value will be stored instead and proper warning will be produced. This function relies on the fact that even wrong value sent over binary protocol fits into @@ -2602,16 +2610,15 @@ bool Item_param::set_longdata(const char *str, ulong length) } -/* +/** Set parameter value from user variable value. - SYNOPSIS - set_from_user_var - thd Current thread - entry User variable structure (NULL means use NULL value) + @param thd Current thread + @param entry User variable structure (NULL means use NULL value) - RETURN + @retval 0 OK + @retval 1 Out of memory */ @@ -2680,14 +2687,11 @@ bool Item_param::set_from_user_var(THD *thd, const user_var_entry *entry) DBUG_RETURN(0); } -/* - Resets parameter after execution. - - SYNOPSIS - Item_param::reset() - - NOTES - We clear null_value here instead of setting it in set_* methods, +/** + Resets parameter after execution. + + @note + We clear null_value here instead of setting it in set_* methods, because we want more easily handle case for long data. */ @@ -2906,11 +2910,15 @@ String *Item_param::val_str(String* str) return str; } -/* +/** Return Param item values in string format, for generating the dynamic - query used in update/binary logs - TODO: change interface and implementation to fill log data in place - and avoid one more memcpy/alloc between str and log string. + query used in update/binary logs. + + @todo + - Change interface and implementation to fill log data in place + and avoid one more memcpy/alloc between str and log string. + - In case of error we need to notify replication + that binary log contains wrong statement */ const String *Item_param::query_val_str(String* str) const @@ -2963,7 +2971,7 @@ const String *Item_param::query_val_str(String* str) const } -/* +/** Convert string from client character set to the character set of connection. */ @@ -3187,17 +3195,16 @@ bool Item_ref_null_helper::get_date(MYSQL_TIME *ltime, uint fuzzydate) } -/* - Mark item and SELECT_LEXs as dependent if item was resolved in outer SELECT +/** + Mark item and SELECT_LEXs as dependent if item was resolved in + outer SELECT. - SYNOPSIS - mark_as_dependent() - thd - thread handler - last - select from which current item depend - current - current select - resolved_item - item which was resolved in outer SELECT(for warning) - mark_item - item which should be marked (can be differ in case of - substitution) + @param thd thread handler + @param last select from which current item depend + @param current current select + @param resolved_item item which was resolved in outer SELECT(for warning) + @param mark_item item which should be marked (can be differ in case of + substitution) */ static void mark_as_dependent(THD *thd, SELECT_LEX *last, SELECT_LEX *current, @@ -3226,21 +3233,19 @@ static void mark_as_dependent(THD *thd, SELECT_LEX *last, SELECT_LEX *current, } -/* - Mark range of selects and resolved identifier (field/reference) item as - dependent +/** + Mark range of selects and resolved identifier (field/reference) + item as dependent. - SYNOPSIS - mark_select_range_as_dependent() - thd - thread handler - last_select - select where resolved_item was resolved - current_sel - current select (select where resolved_item was placed) - found_field - field which was found during resolving - found_item - Item which was found during resolving (if resolved - identifier belongs to VIEW) - resolved_item - Identifier which was resolved - - NOTE: + @param thd thread handler + @param last_select select where resolved_item was resolved + @param current_sel current select (select where resolved_item was placed) + @param found_field field which was found during resolving + @param found_item Item which was found during resolving (if resolved + identifier belongs to VIEW) + @param resolved_item Identifier which was resolved + + @note We have to mark all items between current_sel (including) and last_select (excluding) as dependend (select before last_select should be marked with actual table mask used by resolved item, all other with @@ -3292,20 +3297,17 @@ void mark_select_range_as_dependent(THD *thd, } -/* +/** Search a GROUP BY clause for a field with a certain name. - SYNOPSIS - find_field_in_group_list() - find_item the item being searched for - group_list GROUP BY clause + Search the GROUP BY list for a column named as find_item. When searching + preference is given to columns that are qualified with the same table (and + database) name as the one being searched for. - DESCRIPTION - Search the GROUP BY list for a column named as find_item. When searching - preference is given to columns that are qualified with the same table (and - database) name as the one being searched for. + @param find_item the item being searched for + @param group_list GROUP BY clause - RETURN + @return - the found item on success - NULL if find_item is not in group_list */ @@ -3401,43 +3403,40 @@ static Item** find_field_in_group_list(Item *find_item, ORDER *group_list) } -/* +/** Resolve a column reference in a sub-select. - SYNOPSIS - resolve_ref_in_select_and_group() - thd current thread - ref column reference being resolved - select the sub-select that ref is resolved against - - DESCRIPTION - Resolve a column reference (usually inside a HAVING clause) against the - SELECT and GROUP BY clauses of the query described by 'select'. The name - resolution algorithm searches both the SELECT and GROUP BY clauses, and in - case of a name conflict prefers GROUP BY column names over SELECT names. If - both clauses contain different fields with the same names, a warning is - issued that name of 'ref' is ambiguous. We extend ANSI SQL in that when no - GROUP BY column is found, then a HAVING name is resolved as a possibly - derived SELECT column. This extension is allowed only if the - MODE_ONLY_FULL_GROUP_BY sql mode isn't enabled. - - NOTES + Resolve a column reference (usually inside a HAVING clause) against the + SELECT and GROUP BY clauses of the query described by 'select'. The name + resolution algorithm searches both the SELECT and GROUP BY clauses, and in + case of a name conflict prefers GROUP BY column names over SELECT names. If + both clauses contain different fields with the same names, a warning is + issued that name of 'ref' is ambiguous. We extend ANSI SQL in that when no + GROUP BY column is found, then a HAVING name is resolved as a possibly + derived SELECT column. This extension is allowed only if the + MODE_ONLY_FULL_GROUP_BY sql mode isn't enabled. + + @param thd current thread + @param ref column reference being resolved + @param select the sub-select that ref is resolved against + + @note The resolution procedure is: - Search for a column or derived column named col_ref_i [in table T_j] - in the SELECT clause of Q. + in the SELECT clause of Q. - Search for a column named col_ref_i [in table T_j] - in the GROUP BY clause of Q. + in the GROUP BY clause of Q. - If found different columns with the same name in GROUP BY and SELECT - - issue a warning and return the GROUP BY column, - - otherwise - - if the MODE_ONLY_FULL_GROUP_BY mode is enabled return error - - else return the found SELECT column. + - issue a warning and return the GROUP BY column, + - otherwise + - if the MODE_ONLY_FULL_GROUP_BY mode is enabled return error + - else return the found SELECT column. - RETURN - NULL - there was an error, and the error was already reported - not_found_item - the item was not resolved, no error was reported - resolved item - if the item was resolved + @return + - NULL - there was an error, and the error was already reported + - not_found_item - the item was not resolved, no error was reported + - resolved item - if the item was resolved */ static Item** @@ -3513,44 +3512,45 @@ resolve_ref_in_select_and_group(THD *thd, Item_ident *ref, SELECT_LEX *select) } -/* +/** Resolve the name of an outer select column reference. - SYNOPSIS - Item_field::fix_outer_field() - thd [in] current thread - from_field [in/out] found field reference or (Field*)not_found_field - reference [in/out] view column if this item was resolved to a view column + The method resolves the column reference represented by 'this' as a column + present in outer selects that contain current select. - DESCRIPTION - The method resolves the column reference represented by 'this' as a column - present in outer selects that contain current select. - - NOTES - This is the inner loop of Item_field::fix_fields: + In prepared statements, because of cache, find_field_in_tables() + can resolve fields even if they don't belong to current context. + In this case this method only finds appropriate context and marks + current select as dependent. The found reference of field should be + provided in 'from_field'. - for each outer query Q_k beginning from the inner-most one - { - search for a column or derived column named col_ref_i - [in table T_j] in the FROM clause of Q_k; - - if such a column is not found - Search for a column or derived column named col_ref_i - [in table T_j] in the SELECT and GROUP clauses of Q_k. - } + @param[in] thd current thread + @param[in,out] from_field found field reference or (Field*)not_found_field + @param[in,out] reference view column if this item was resolved to a + view column - IMPLEMENTATION - In prepared statements, because of cache, find_field_in_tables() - can resolve fields even if they don't belong to current context. - In this case this method only finds appropriate context and marks - current select as dependent. The found reference of field should be - provided in 'from_field'. + @note + This is the inner loop of Item_field::fix_fields: + @code + for each outer query Q_k beginning from the inner-most one + { + search for a column or derived column named col_ref_i + [in table T_j] in the FROM clause of Q_k; - RETURN - 1 - column succefully resolved and fix_fields() should continue. - 0 - column fully fixed and fix_fields() should return FALSE - -1 - error occured + if such a column is not found + Search for a column or derived column named col_ref_i + [in table T_j] in the SELECT and GROUP clauses of Q_k. + } + @endcode + + @retval + 1 column succefully resolved and fix_fields() should continue. + @retval + 0 column fully fixed and fix_fields() should return FALSE + @retval + -1 error occured */ + int Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference) { @@ -3811,48 +3811,48 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference) } -/* +/** Resolve the name of a column reference. - SYNOPSIS - Item_field::fix_fields() - thd [in] current thread - reference [in/out] view column if this item was resolved to a view column + The method resolves the column reference represented by 'this' as a column + present in one of: FROM clause, SELECT clause, GROUP BY clause of a query + Q, or in outer queries that contain Q. - DESCRIPTION - The method resolves the column reference represented by 'this' as a column - present in one of: FROM clause, SELECT clause, GROUP BY clause of a query - Q, or in outer queries that contain Q. + The name resolution algorithm used is (where [T_j] is an optional table + name that qualifies the column name): - NOTES - The name resolution algorithm used is (where [T_j] is an optional table - name that qualifies the column name): + @code + resolve_column_reference([T_j].col_ref_i) + { + search for a column or derived column named col_ref_i + [in table T_j] in the FROM clause of Q; - resolve_column_reference([T_j].col_ref_i) + if such a column is NOT found AND // Lookup in outer queries. + there are outer queries { - search for a column or derived column named col_ref_i - [in table T_j] in the FROM clause of Q; - - if such a column is NOT found AND // Lookup in outer queries. - there are outer queries + for each outer query Q_k beginning from the inner-most one { - for each outer query Q_k beginning from the inner-most one - { - search for a column or derived column named col_ref_i - [in table T_j] in the FROM clause of Q_k; + search for a column or derived column named col_ref_i + [in table T_j] in the FROM clause of Q_k; - if such a column is not found - Search for a column or derived column named col_ref_i - [in table T_j] in the SELECT and GROUP clauses of Q_k. - } + if such a column is not found + Search for a column or derived column named col_ref_i + [in table T_j] in the SELECT and GROUP clauses of Q_k. } } + } + @endcode Notice that compared to Item_ref::fix_fields, here we first search the FROM clause, and then we search the SELECT and GROUP BY clauses. - RETURN + @param[in] thd current thread + @param[in,out] reference view column if this item was resolved to a + view column + + @retval TRUE if error + @retval FALSE on success */ @@ -4068,26 +4068,24 @@ void Item_field::cleanup() DBUG_VOID_RETURN; } -/* - Find a field among specified multiple equalities +/** + Find a field among specified multiple equalities. - SYNOPSIS - find_item_equal() - cond_equal reference to list of multiple equalities where - the field (this object) is to be looked for - - DESCRIPTION - The function first searches the field among multiple equalities - of the current level (in the cond_equal->current_level list). - If it fails, it continues searching in upper levels accessed - through a pointer cond_equal->upper_levels. - The search terminates as soon as a multiple equality containing - the field is found. - - RETURN VALUES - First Item_equal containing the field, if success - 0, otherwise + The function first searches the field among multiple equalities + of the current level (in the cond_equal->current_level list). + If it fails, it continues searching in upper levels accessed + through a pointer cond_equal->upper_levels. + The search terminates as soon as a multiple equality containing + the field is found. + + @param cond_equal reference to list of multiple equalities where + the field (this object) is to be looked for + + @return + - First Item_equal containing the field, if success + - 0, otherwise */ + Item_equal *Item_field::find_item_equal(COND_EQUAL *cond_equal) { Item_equal *item= 0; @@ -4109,32 +4107,33 @@ Item_equal *Item_field::find_item_equal(COND_EQUAL *cond_equal) } -/* - Check whether a field can be substituted by an equal item +/** + Check whether a field can be substituted by an equal item. - SYNOPSIS - equal_fields_propagator() - arg - *arg != NULL <-> the field is in the context where - substitution for an equal item is valid - - DESCRIPTION - The function checks whether a substitution of the field - occurrence for an equal item is valid. + The function checks whether a substitution of the field + occurrence for an equal item is valid. - NOTES + @param arg *arg != NULL <-> the field is in the context where + substitution for an equal item is valid + + @note The following statement is not always true: + @n x=y => F(x)=F(x/y). + @n This means substitution of an item for an equal item not always - yields an equavalent condition. - Here's an example: - 'a'='a ' - (LENGTH('a')=1) != (LENGTH('a ')=2) + yields an equavalent condition. Here's an example: + @code + 'a'='a ' + (LENGTH('a')=1) != (LENGTH('a ')=2) + @endcode Such a substitution is surely valid if either the substituted field is not of a STRING type or if it is an argument of - a comparison predicate. + a comparison predicate. - RETURN + @retval TRUE substitution is valid + @retval FALSE otherwise */ @@ -4144,30 +4143,28 @@ bool Item_field::subst_argument_checker(uchar **arg) } -/* +/** Set a pointer to the multiple equality the field reference belongs to - (if any) - - SYNOPSIS - equal_fields_propagator() - arg - reference to list of multiple equalities where - the field (this object) is to be looked for - - DESCRIPTION - The function looks for a multiple equality containing the field item - among those referenced by arg. - In the case such equality exists the function does the following. - If the found multiple equality contains a constant, then the field - reference is substituted for this constant, otherwise it sets a pointer - to the multiple equality in the field item. + (if any). - NOTES + The function looks for a multiple equality containing the field item + among those referenced by arg. + In the case such equality exists the function does the following. + If the found multiple equality contains a constant, then the field + reference is substituted for this constant, otherwise it sets a pointer + to the multiple equality in the field item. + + + @param arg reference to list of multiple equalities where + the field (this object) is to be looked for + + @note This function is supposed to be called as a callback parameter in calls - of the compile method. + of the compile method. - RETURN VALUES - pointer to the replacing constant item, if the field item was substituted - pointer to the field item, otherwise. + @return + - pointer to the replacing constant item, if the field item was substituted + - pointer to the field item, otherwise. */ Item *Item_field::equal_fields_propagator(uchar *arg) @@ -4196,9 +4193,10 @@ Item *Item_field::equal_fields_propagator(uchar *arg) } -/* - Mark the item to not be part of substitution if it's not a binary item - See comments in Arg_comparator::set_compare_func() for details +/** + Mark the item to not be part of substitution if it's not a binary item. + + See comments in Arg_comparator::set_compare_func() for details. */ bool Item_field::set_no_const_sub(uchar *arg) @@ -4209,31 +4207,29 @@ bool Item_field::set_no_const_sub(uchar *arg) } -/* +/** Replace an Item_field for an equal Item_field that evaluated earlier - (if any) - - SYNOPSIS - replace_equal_field_() - arg - a dummy parameter, is not used here - - DESCRIPTION - The function returns a pointer to an item that is taken from - the very beginning of the item_equal list which the Item_field - object refers to (belongs to) unless item_equal contains a constant - item. In this case the function returns this constant item, - (if the substitution does not require conversion). - If the Item_field object does not refer any Item_equal object - 'this' is returned + (if any). - NOTES + The function returns a pointer to an item that is taken from + the very beginning of the item_equal list which the Item_field + object refers to (belongs to) unless item_equal contains a constant + item. In this case the function returns this constant item, + (if the substitution does not require conversion). + If the Item_field object does not refer any Item_equal object + 'this' is returned . + + @param arg a dummy parameter, is not used here + + + @note This function is supposed to be called as a callback parameter in calls - of the thransformer method. + of the thransformer method. - RETURN VALUES - pointer to a replacement Item_field if there is a better equal item or - a pointer to a constant equal item; - this - otherwise. + @return + - pointer to a replacement Item_field if there is a better equal item or + a pointer to a constant equal item; + - this - otherwise. */ Item *Item_field::replace_equal_field(uchar *arg) @@ -4370,20 +4366,16 @@ String *Item::check_well_formed_result(String *str, bool send_error) } -/* - Create a field to hold a string value from an item +/** + Create a field to hold a string value from an item. - SYNOPSIS - make_string_field() - table Table for which the field is created + If max_length > CONVERT_IF_BIGGER_TO_BLOB create a blob @n + If max_length > 0 create a varchar @n + If max_length == 0 create a CHAR(0) - IMPLEMENTATION - If max_length > CONVERT_IF_BIGGER_TO_BLOB create a blob - If max_length > 0 create a varchar - If max_length == 0 create a CHAR(0) + @param table Table for which the field is created */ - Field *Item::make_string_field(TABLE *table) { Field *field; @@ -4405,15 +4397,16 @@ Field *Item::make_string_field(TABLE *table) } -/* - Create a field based on field_type of argument +/** + Create a field based on field_type of argument. For now, this is only used to create a field for IFNULL(x,something) and time functions - RETURN - 0 error - # Created field + @retval + NULL error + @retval + \# Created field */ Field *Item::tmp_table_field_from_field_type(TABLE *table, bool fixed_length) @@ -4539,8 +4532,8 @@ void Item_field::make_field(Send_field *tmp_field) } -/* - Set a field:s value from a item +/** + Set a field's value from a item. */ void Item_field::save_org_in_field(Field *to) @@ -4576,21 +4569,19 @@ int Item_field::save_in_field(Field *to, bool no_conversions) } -/* - Store null in field +/** + Store null in field. - SYNOPSIS - save_in_field() - field Field where we want to store NULL + This is used on INSERT. + Allow NULL to be inserted in timestamp and auto_increment values. - DESCRIPTION - This is used on INSERT. - Allow NULL to be inserted in timestamp and auto_increment values + @param field Field where we want to store NULL - RETURN VALUES - 0 ok - 1 Field doesn't support NULL values and can't handle 'field = NULL' -*/ + @retval + 0 ok + @retval + 1 Field doesn't support NULL values and can't handle 'field = NULL' +*/ int Item_null::save_in_field(Field *field, bool no_conversions) { @@ -4598,17 +4589,16 @@ int Item_null::save_in_field(Field *field, bool no_conversions) } -/* - Store null in field +/** + Store null in field. - SYNOPSIS - save_safe_in_field() - field Field where we want to store NULL + @param field Field where we want to store NULL - RETURN VALUES + @retval 0 OK + @retval 1 Field doesn't support NULL values -*/ +*/ int Item_null::save_safe_in_field(Field *field) { @@ -4766,7 +4756,7 @@ static uint nr_of_decimals(const char *str, const char *end) } -/* +/** This function is only called during parsing. We will signal an error if value is not a true double value (overflow) */ @@ -4996,8 +4986,8 @@ Item_bin_string::Item_bin_string(const char *str, uint str_length) } -/* - Pack data in buffer for sending +/** + Pack data in buffer for sending. */ bool Item_null::send(Protocol *protocol, String *packet) @@ -5005,8 +4995,8 @@ bool Item_null::send(Protocol *protocol, String *packet) return protocol->store_null(); } -/* - This is only called from items that is not of type item_field +/** + This is only called from items that is not of type item_field. */ bool Item::send(Protocol *protocol, String *buffer) @@ -5215,60 +5205,67 @@ Item_ref::Item_ref(Name_resolution_context *context_arg, } -/* +/** Resolve the name of a reference to a column reference. - SYNOPSIS - Item_ref::fix_fields() - thd [in] current thread - reference [in/out] view column if this item was resolved to a view column + The method resolves the column reference represented by 'this' as a column + present in one of: GROUP BY clause, SELECT clause, outer queries. It is + used typically for columns in the HAVING clause which are not under + aggregate functions. - DESCRIPTION - The method resolves the column reference represented by 'this' as a column - present in one of: GROUP BY clause, SELECT clause, outer queries. It is - used typically for columns in the HAVING clause which are not under - aggregate functions. + POSTCONDITION @n + Item_ref::ref is 0 or points to a valid item. - NOTES + @note The name resolution algorithm used is (where [T_j] is an optional table name that qualifies the column name): - resolve_extended([T_j].col_ref_i) - { - Search for a column or derived column named col_ref_i [in table T_j] - in the SELECT and GROUP clauses of Q. - - if such a column is NOT found AND // Lookup in outer queries. - there are outer queries + @code + resolve_extended([T_j].col_ref_i) { - for each outer query Q_k beginning from the inner-most one - { - Search for a column or derived column named col_ref_i - [in table T_j] in the SELECT and GROUP clauses of Q_k. + Search for a column or derived column named col_ref_i [in table T_j] + in the SELECT and GROUP clauses of Q. - if such a column is not found AND - - Q_k is not a group query AND - - Q_k is not inside an aggregate function - OR - - Q_(k-1) is not in a HAVING or SELECT clause of Q_k - { - search for a column or derived column named col_ref_i - [in table T_j] in the FROM clause of Q_k; + if such a column is NOT found AND // Lookup in outer queries. + there are outer queries + { + for each outer query Q_k beginning from the inner-most one + { + Search for a column or derived column named col_ref_i + [in table T_j] in the SELECT and GROUP clauses of Q_k. + + if such a column is not found AND + - Q_k is not a group query AND + - Q_k is not inside an aggregate function + OR + - Q_(k-1) is not in a HAVING or SELECT clause of Q_k + { + search for a column or derived column named col_ref_i + [in table T_j] in the FROM clause of Q_k; + } } } } - } - + @endcode + @n This procedure treats GROUP BY and SELECT clauses as one namespace for column references in HAVING. Notice that compared to Item_field::fix_fields, here we first search the SELECT and GROUP BY clauses, and then we search the FROM clause. - POSTCONDITION - Item_ref::ref is 0 or points to a valid item + @param[in] thd current thread + @param[in,out] reference view column if this item was resolved to a + view column - RETURN + @todo + Here we could first find the field anyway, and then test this + condition, so that we can give a better error message - + ER_WRONG_FIELD_WITH_GROUP, instead of the less informative + ER_BAD_FIELD_ERROR which we produce now. + + @retval TRUE if error + @retval FALSE on success */ @@ -5795,16 +5792,15 @@ bool Item_direct_ref::get_date(MYSQL_TIME *ltime,uint fuzzydate) } -/* - Prepare referenced field then call usual Item_direct_ref::fix_fields +/** + Prepare referenced field then call usual Item_direct_ref::fix_fields . - SYNOPSIS - Item_direct_view_ref::fix_fields() - thd thread handler - reference reference on reference where this item stored + @param thd thread handler + @param reference reference on reference where this item stored - RETURN + @retval FALSE OK + @retval TRUE Error */ @@ -5847,25 +5843,23 @@ bool Item_outer_ref::fix_fields(THD *thd, Item **reference) } -/* +/** Compare two view column references for equality. - SYNOPSIS - Item_direct_view_ref::eq() - item item to compare with - binary_cmp make binary comparison + A view column reference is considered equal to another column + reference if the second one is a view column and if both column + references resolve to the same item. It is assumed that both + items are of the same type. - DESCRIPTION - A view column reference is considered equal to another column - reference if the second one is a view column and if both column - references resolve to the same item. + @param item item to compare with + @param binary_cmp make binary comparison - RETURN + @retval TRUE Referenced item is equal to given item + @retval FALSE otherwise */ - bool Item_direct_view_ref::eq(const Item *item, bool binary_cmp) const { if (item->type() == REF_ITEM) @@ -5984,9 +5978,9 @@ int Item_default_value::save_in_field(Field *field_arg, bool no_conversions) } -/* +/** This method like the walk method traverses the item tree, but at the - same time it can replace some nodes in the tree + same time it can replace some nodes in the tree. */ Item *Item_default_value::transform(Item_transformer transformer, uchar *args) @@ -6083,17 +6077,15 @@ void Item_insert_value::print(String *str) } -/* +/** Find index of Field object which will be appropriate for item representing field of row being changed in trigger. - SYNOPSIS - setup_field() - thd - current thread context - table - table of trigger (and where we looking for fields) - table_grant_info - GRANT_INFO of the subject table + @param thd current thread context + @param table table of trigger (and where we looking for fields) + @param table_grant_info GRANT_INFO of the subject table - NOTE + @note This function does almost the same as fix_fields() for Item_field but is invoked right after trigger definition parsing. Since at this stage we can't say exactly what Field object (corresponding @@ -6327,8 +6319,10 @@ void resolve_const_item(THD *thd, Item **ref, Item *comp_item) thd->change_item_tree(ref, new_item); } -/* - Return true if the value stored in the field is equal to the const item +/** + Return true if the value stored in the field is equal to the const + item. + We need to use this on the range optimizer because in some cases we can't store the value in the field without some precision/character loss. */ @@ -6669,14 +6663,11 @@ Item_type_holder::Item_type_holder(THD *thd, Item *item) } -/* - Return expression type of Item_type_holder +/** + Return expression type of Item_type_holder. - SYNOPSIS - Item_type_holder::result_type() - - RETURN - Item_result (type of internal MySQL expression result) + @return + Item_result (type of internal MySQL expression result) */ Item_result Item_type_holder::result_type() const @@ -6685,13 +6676,10 @@ Item_result Item_type_holder::result_type() const } -/* - Find real field type of item - - SYNOPSIS - Item_type_holder::get_real_type() +/** + Find real field type of item. - RETURN + @return type of field which should be created to store item value */ @@ -6756,17 +6744,16 @@ enum_field_types Item_type_holder::get_real_type(Item *item) return item->field_type(); } -/* +/** Find field type which can carry current Item_type_holder type and type of given Item. - SYNOPSIS - Item_type_holder::join_types() - thd thread handler - item given item to join its parameters with this item ones + @param thd thread handler + @param item given item to join its parameters with this item ones - RETURN + @retval TRUE error - types are incompatible + @retval FALSE OK */ @@ -6867,14 +6854,12 @@ bool Item_type_holder::join_types(THD *thd, Item *item) DBUG_RETURN(FALSE); } -/* - Calculate lenth for merging result for given Item type +/** + Calculate lenth for merging result for given Item type. - SYNOPSIS - Item_type_holder::real_length() - item Item for lrngth detection + @param item Item for length detection - RETURN + @return length */ @@ -6928,15 +6913,13 @@ uint32 Item_type_holder::display_length(Item *item) } -/* +/** Make temporary table field according collected information about type - of UNION result + of UNION result. - SYNOPSIS - Item_type_holder::make_field_by_type() - table temporary table for which we create fields + @param table temporary table for which we create fields - RETURN + @return created field */ @@ -6976,13 +6959,11 @@ Field *Item_type_holder::make_field_by_type(TABLE *table) } -/* +/** Get full information from Item about enum/set fields to be able to create - them later + them later. - SYNOPSIS - Item_type_holder::get_full_info - item Item for information collection + @param item Item for information collection */ void Item_type_holder::get_full_info(Item *item) { @@ -7045,26 +7026,21 @@ void Item_result_field::cleanup() DBUG_VOID_RETURN; } -/* - Dummy error processor used by default by Name_resolution_context - - SYNOPSIS - dummy_error_processor() +/** + Dummy error processor used by default by Name_resolution_context. - NOTE + @note do nothing */ void dummy_error_processor(THD *thd, void *data) {} -/* - Wrapper of hide_view_error call for Name_resolution_context error processor - - SYNOPSIS - view_error_processor() +/** + Wrapper of hide_view_error call for Name_resolution_context error + processor. - NOTE + @note hide view underlying tables details in error messages */ diff --git a/sql/item_buff.cc b/sql/item_buff.cc index c162b84f457..2f45d0a17c2 100644 --- a/sql/item_buff.cc +++ b/sql/item_buff.cc @@ -14,12 +14,17 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* Buffers to save and compare item values */ +/** + @file + + @brief + Buffers to save and compare item values +*/ #include "mysql_priv.h" -/* -** Create right type of Cached_item for an item +/** + Create right type of Cached_item for an item. */ Cached_item *new_Cached_item(THD *thd, Item *item) @@ -45,9 +50,11 @@ Cached_item *new_Cached_item(THD *thd, Item *item) Cached_item::~Cached_item() {} -/* -** Compare with old value and replace value with new value -** Return true if values have changed +/** + Compare with old value and replace value with new value. + + @return + Return true if values have changed */ Cached_item_str::Cached_item_str(THD *thd, Item *arg) diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 1d1e28593d4..62ac7bc4751 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -14,7 +14,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* This file defines all compare functions */ +/** + @file + + @brief + This file defines all compare functions +*/ #ifdef USE_PRAGMA_IMPLEMENTATION #pragma implementation // gcc: Class implementation @@ -24,8 +29,7 @@ #include <m_ctype.h> #include "sql_select.h" -static bool convert_constant_item(THD *thd, Item_field *field_item, - Item **item); +static bool convert_constant_item(THD *, Item_field *, Item **); static Item_result item_store_type(Item_result a, Item *item, my_bool unsigned_flag) @@ -105,7 +109,7 @@ static int cmp_row_type(Item* item1, Item* item2) } -/* +/** Aggregates result types from the array of items. SYNOPSIS: @@ -118,11 +122,13 @@ static int cmp_row_type(Item* item1, Item* item2) This function aggregates result types from the array of items. Found type supposed to be used later for comparison of values of these items. Aggregation itself is performed by the item_cmp_type() function. - The function also checks compatibility of row signatures for the - submitted items (see the spec for the cmp_row_type function). + @param[out] type the aggregated type + @param items array of items to aggregate the type from + @param nitems number of items in the array - RETURN VALUES + @retval 1 type incompatibility has been detected + @retval 0 otherwise */ @@ -287,10 +293,11 @@ void Item_func_not::print(String *str) str->append(')'); } -/* - special NOT for ALL subquery +/** + special NOT for ALL subquery. */ + longlong Item_func_not_all::val_int() { DBUG_ASSERT(fixed == 1); @@ -323,10 +330,13 @@ void Item_func_not_all::print(String *str) } -/* - Special NOP (No OPeration) for ALL subquery it is like Item_func_not_all - (return TRUE if underlying subquery do not return rows) but if subquery - returns some rows it return same value as argument (TRUE/FALSE). +/** + Special NOP (No OPeration) for ALL subquery. It is like + Item_func_not_all. + + @return + (return TRUE if underlying subquery do not return rows) but if subquery + returns some rows it return same value as argument (TRUE/FALSE). */ longlong Item_func_nop_all::val_int() @@ -346,16 +356,9 @@ longlong Item_func_nop_all::val_int() } -/* - Convert a constant item to an int and replace the original item - - SYNOPSIS - convert_constant_item() - thd thread handle - field_item item will be converted using the type of this field - item [in/out] reference to the item to convert +/** + Convert a constant item to an int and replace the original item. - DESCRIPTION The function converts a constant expression or string to an integer. On successful conversion the original item is substituted for the result of the item evaluation. @@ -363,16 +366,21 @@ longlong Item_func_nop_all::val_int() also when comparing bigint to strings (in which case strings are converted to bigints). - NOTES + @param thd thread handle + @param field item will be converted using the type of this field + @param[in,out] item reference to the item to convert + + @note This function is called only at prepare stage. As all derived tables are filled only after all derived tables are prepared we do not evaluate items with subselects here because they can contain derived tables and thus we may attempt to use a table that has not been populated yet. - RESULT VALUES - 0 Can't convert item - 1 Item was replaced with an integer version of the item + @retval + 0 Can't convert item + @retval + 1 Item was replaced with an integer version of the item */ static bool convert_constant_item(THD *thd, Item_field *field_item, @@ -1075,13 +1083,15 @@ int Arg_comparator::compare_string() } -/* +/** Compare strings byte by byte. End spaces are also compared. - RETURN - < 0 *a < *b - 0 *b == *b - > 0 *a > *b + @retval + <0 *a < *b + @retval + 0 *b == *b + @retval + >0 *a > *b */ int Arg_comparator::compare_binary_string() @@ -1103,10 +1113,11 @@ int Arg_comparator::compare_binary_string() } -/* - Compare strings, but take into account that NULL == NULL +/** + Compare strings, but take into account that NULL == NULL. */ + int Arg_comparator::compare_e_string() { String *res1,*res2; @@ -1247,7 +1258,7 @@ int Arg_comparator::compare_int_signed() } -/* +/** Compare values as BIGINT UNSIGNED. */ @@ -1270,7 +1281,7 @@ int Arg_comparator::compare_int_unsigned() } -/* +/** Compare signed (*a) with unsigned (*B) */ @@ -1295,7 +1306,7 @@ int Arg_comparator::compare_int_signed_unsigned() } -/* +/** Compare unsigned (*a) with signed (*B) */ @@ -1331,7 +1342,7 @@ int Arg_comparator::compare_e_int() return test(val1 == val2); } -/* +/** Compare unsigned *a with signed *b or signed *a with unsigned *b. */ int Arg_comparator::compare_e_int_diff_signedness() @@ -1620,7 +1631,7 @@ longlong Item_func_eq::val_int() } -/* Same as Item_func_eq, but NULL = NULL */ +/** Same as Item_func_eq, but NULL = NULL. */ void Item_func_equal::fix_length_and_dec() { @@ -1774,21 +1785,18 @@ void Item_func_interval::fix_length_and_dec() } -/* - Execute Item_func_interval() - - SYNOPSIS - Item_func_interval::val_int() +/** + Execute Item_func_interval(). - NOTES - If we are doing a decimal comparison, we are - evaluating the first item twice. + @note + If we are doing a decimal comparison, we are evaluating the first + item twice. - RETURN - -1 if null value, - 0 if lower than lowest - 1 - arg_count-1 if between args[n] and args[n+1] - arg_count if higher than biggest argument + @return + - -1 if null value, + - 0 if lower than lowest + - 1 - arg_count-1 if between args[n] and args[n+1] + - arg_count if higher than biggest argument */ longlong Item_func_interval::val_int() @@ -1870,32 +1878,31 @@ longlong Item_func_interval::val_int() } -/* - Perform context analysis of a BETWEEN item tree - - SYNOPSIS: - fix_fields() - thd reference to the global context of the query thread - tables list of all open tables involved in the query - ref pointer to Item* variable where pointer to resulting "fixed" - item is to be assigned +/** + Perform context analysis of a BETWEEN item tree. - DESCRIPTION This function performs context analysis (name resolution) and calculates various attributes of the item tree with Item_func_between as its root. The function saves in ref the pointer to the item or to a newly created item that is considered as a replacement for the original one. - NOTES + @param thd reference to the global context of the query thread + @param ref pointer to Item* variable where pointer to resulting "fixed" + item is to be assigned + + @note Let T0(e)/T1(e) be the value of not_null_tables(e) when e is used on a predicate/function level. Then it's easy to show that: + @verbatim T0(e BETWEEN e1 AND e2) = union(T1(e),T1(e1),T1(e2)) T1(e BETWEEN e1 AND e2) = union(T1(e),intersection(T1(e1),T1(e2))) T0(e NOT BETWEEN e1 AND e2) = union(T1(e),intersection(T1(e1),T1(e2))) T1(e NOT BETWEEN e1 AND e2) = union(T1(e),intersection(T1(e1),T1(e2))) + @endverbatim - RETURN + @retval 0 ok + @retval 1 got error */ @@ -2239,30 +2246,29 @@ Item_func_ifnull::str_op(String *str) } -/* - Perform context analysis of an IF item tree - - SYNOPSIS: - fix_fields() - thd reference to the global context of the query thread - tables list of all open tables involved in the query - ref pointer to Item* variable where pointer to resulting "fixed" - item is to be assigned +/** + Perform context analysis of an IF item tree. - DESCRIPTION This function performs context analysis (name resolution) and calculates various attributes of the item tree with Item_func_if as its root. The function saves in ref the pointer to the item or to a newly created item that is considered as a replacement for the original one. - NOTES + @param thd reference to the global context of the query thread + @param ref pointer to Item* variable where pointer to resulting "fixed" + item is to be assigned + + @note Let T0(e)/T1(e) be the value of not_null_tables(e) when e is used on a predicate/function level. Then it's easy to show that: + @verbatim T0(IF(e,e1,e2) = T1(IF(e,e1,e2)) T1(IF(e,e1,e2)) = intersection(T1(e1),T1(e2)) + @endverbatim - RETURN + @retval 0 ok + @retval 1 got error */ @@ -2407,11 +2413,14 @@ Item_func_nullif::fix_length_and_dec() } -/* - nullif () returns NULL if arguments are equal, else it returns the - first argument. +/** + @note Note that we have to evaluate the first argument twice as the compare may have been done with a different type than return value + @return + NULL if arguments are equal + @return + the first argument if not equal */ double @@ -2483,14 +2492,7 @@ Item_func_nullif::is_null() } -/* - Return the matching ITEM or NULL if all compares (including else) failed - - SYNOPSIS - find_item() - str Buffer string - - DESCRIPTION +/** Find and return matching items for CASE or ELSE item if all compares are failed or NULL if ELSE item isn't defined. @@ -2504,9 +2506,10 @@ Item_func_nullif::is_null() to it according to their int values i.e. STRING_RESULT is mapped to bit 0, REAL_RESULT to bit 1, so on. - RETURN - NULL - Nothing found and there is no ELSE expression defined - item - Found item or ELSE item if defined and all comparisons are + @retval + NULL Nothing found and there is no ELSE expression defined + @retval + item Found item or ELSE item if defined and all comparisons are failed */ @@ -2755,7 +2758,10 @@ uint Item_func_case::decimal_precision() const } -/* TODO: Fix this so that it prints the whole CASE expression */ +/** + @todo + Fix this so that it prints the whole CASE expression +*/ void Item_func_case::print(String *str) { @@ -2797,7 +2803,7 @@ void Item_func_case::cleanup() } -/* +/** Coalesce - return first not NULL argument. */ @@ -3416,32 +3422,31 @@ bool Item_func_in::nulls_in_row() } -/* - Perform context analysis of an IN item tree - - SYNOPSIS: - fix_fields() - thd reference to the global context of the query thread - tables list of all open tables involved in the query - ref pointer to Item* variable where pointer to resulting "fixed" - item is to be assigned +/** + Perform context analysis of an IN item tree. - DESCRIPTION This function performs context analysis (name resolution) and calculates various attributes of the item tree with Item_func_in as its root. The function saves in ref the pointer to the item or to a newly created item that is considered as a replacement for the original one. - NOTES + @param thd reference to the global context of the query thread + @param ref pointer to Item* variable where pointer to resulting "fixed" + item is to be assigned + + @note Let T0(e)/T1(e) be the value of not_null_tables(e) when e is used on a predicate/function level. Then it's easy to show that: + @verbatim T0(e IN(e1,...,en)) = union(T1(e),intersection(T1(ei))) T1(e IN(e1,...,en)) = union(T1(e),intersection(T1(ei))) T0(e NOT IN(e1,...,en)) = union(T1(e),union(T1(ei))) T1(e NOT IN(e1,...,en)) = union(T1(e),intersection(T1(ei))) + @endverbatim - RETURN + @retval 0 ok + @retval 1 got error */ @@ -3916,16 +3921,9 @@ bool Item_cond::walk(Item_processor processor, bool walk_subquery, uchar *arg) } -/* - Transform an Item_cond object with a transformer callback function - - SYNOPSIS - transform() - transformer the transformer callback function to be applied to the nodes - of the tree of the object - arg parameter to be passed to the transformer +/** + Transform an Item_cond object with a transformer callback function. - DESCRIPTION The function recursively applies the transform method to each member item of the condition list. If the call of the method for a member item returns a new item @@ -3933,7 +3931,11 @@ bool Item_cond::walk(Item_processor processor, bool walk_subquery, uchar *arg) After this the transformer is applied to the root node of the Item_cond object. - RETURN VALUES + @param transformer the transformer callback function to be applied to + the nodes of the tree of the object + @param arg parameter to be passed to the transformer + + @return Item returned as the result of transformation of the root node */ @@ -3962,19 +3964,10 @@ Item *Item_cond::transform(Item_transformer transformer, uchar *arg) } -/* - Compile Item_cond object with a processor and a transformer callback functions - - SYNOPSIS - compile() - analyzer the analyzer callback function to be applied to the nodes - of the tree of the object - arg_p in/out parameter to be passed to the analyzer - transformer the transformer callback function to be applied to the nodes - of the tree of the object - arg_t parameter to be passed to the transformer +/** + Compile Item_cond object with a processor and a transformer + callback functions. - DESCRIPTION First the function applies the analyzer to the root node of the Item_func object. Then if the analyzer succeeeds (returns TRUE) the function recursively applies the compile method to member @@ -3984,7 +3977,14 @@ Item *Item_cond::transform(Item_transformer transformer, uchar *arg) After this the transformer is applied to the root node of the Item_cond object. - RETURN VALUES + @param analyzer the analyzer callback function to be applied to the + nodes of the tree of the object + @param[in,out] arg_p parameter to be passed to the analyzer + @param transformer the transformer callback function to be applied to the + nodes of the tree of the object + @param arg_t parameter to be passed to the transformer + + @return Item returned as the result of transformation of the root node */ @@ -4034,23 +4034,21 @@ void Item_cond::traverse_cond(Cond_traverser traverser, } } -/* - Move SUM items out from item tree and replace with reference +/** + Move SUM items out from item tree and replace with reference. - SYNOPSIS - split_sum_func() - thd Thread handler - ref_pointer_array Pointer to array of reference fields - fields All fields in select - - NOTES - This function is run on all expression (SELECT list, WHERE, HAVING etc) - that have or refer (HAVING) to a SUM expression. - - The split is done to get an unique item for each SUM function - so that we can easily find and calculate them. - (Calculation done by update_sum_func() and copy_sum_funcs() in - sql_select.cc) + The split is done to get an unique item for each SUM function + so that we can easily find and calculate them. + (Calculation done by update_sum_func() and copy_sum_funcs() in + sql_select.cc) + + @param thd Thread handler + @param ref_pointer_array Pointer to array of reference fields + @param fields All fields in select + + @note + This function is run on all expression (SELECT list, WHERE, HAVING etc) + that have or refer (HAVING) to a SUM expression. */ void Item_cond::split_sum_func(THD *thd, Item **ref_pointer_array, @@ -4121,20 +4119,22 @@ void Item_cond::neg_arguments(THD *thd) } -/* - Evaluation of AND(expr, expr, expr ...) +/** + Evaluation of AND(expr, expr, expr ...). - NOTES: + @note abort_if_null is set for AND expressions for which we don't care if the result is NULL or 0. This is set for: - WHERE clause - HAVING clause - IF(expression) - RETURN VALUES + @retval 1 If all expressions are true + @retval 0 If all expressions are false or if we find a NULL expression and 'abort_on_null' is set. + @retval NULL if all expression are either 1 or NULL */ @@ -4176,24 +4176,23 @@ longlong Item_cond_or::val_int() return 0; } -/* - Create an AND expression from two expressions +/** + Create an AND expression from two expressions. - SYNOPSIS - and_expressions() - a expression or NULL - b expression. - org_item Don't modify a if a == *org_item - If a == NULL, org_item is set to point at b, - to ensure that future calls will not modify b. - - NOTES + @param a expression or NULL + @param b expression. + @param org_item Don't modify a if a == *org_item. + If a == NULL, org_item is set to point at b, + to ensure that future calls will not modify b. + + @note This will not modify item pointed to by org_item or b The idea is that one can call this in a loop and create and 'and' over all items without modifying any of the original items. - RETURN + @retval NULL Error + @retval Item */ @@ -4251,7 +4250,9 @@ longlong Item_is_not_null_test::val_int() DBUG_RETURN(1); } -/* Optimize case of not_null_column IS NULL */ +/** + Optimize case of not_null_column IS NULL. +*/ void Item_is_not_null_test::update_used_tables() { if (!args[0]->maybe_null) @@ -4311,7 +4312,9 @@ longlong Item_func_like::val_int() } -/* We can optimize a where if first character isn't a wildcard */ +/** + We can optimize a where if first character isn't a wildcard +*/ Item_func::optimize_type Item_func_like::select_optimize() const { @@ -4597,10 +4600,9 @@ void Item_func_regex::cleanup() #endif -/********************************************************************** - turboBM_compute_suffixes() +/** Precomputation dependent only on pattern_len. -**********************************************************************/ +*/ void Item_func_like::turboBM_compute_suffixes(int *suff) { @@ -4654,10 +4656,9 @@ void Item_func_like::turboBM_compute_suffixes(int *suff) } -/********************************************************************** - turboBM_compute_good_suffix_shifts() - Precomputation dependent only on pattern_len. -**********************************************************************/ +/** + Precomputation dependent only on pattern_len. +*/ void Item_func_like::turboBM_compute_good_suffix_shifts(int *suff) { @@ -4699,10 +4700,9 @@ void Item_func_like::turboBM_compute_good_suffix_shifts(int *suff) } -/********************************************************************** - turboBM_compute_bad_character_shifts() +/** Precomputation dependent on pattern_len. -**********************************************************************/ +*/ void Item_func_like::turboBM_compute_bad_character_shifts() { @@ -4728,10 +4728,12 @@ void Item_func_like::turboBM_compute_bad_character_shifts() } -/********************************************************************** - turboBM_matches() - Search for pattern in text, returns true/false for match/no match -**********************************************************************/ +/** + Search for pattern in text. + + @return + returns true/false for match/no match +*/ bool Item_func_like::turboBM_matches(const char* text, int text_len) const { @@ -4811,24 +4813,20 @@ bool Item_func_like::turboBM_matches(const char* text, int text_len) const } -/* +/** Make a logical XOR of the arguments. - SYNOPSIS - val_int() - - DESCRIPTION If either operator is NULL, return NULL. - NOTE - As we don't do any index optimization on XOR this is not going to be - very fast to use. - - TODO (low priority) - Change this to be optimized as: - A XOR B -> (A) == 1 AND (B) <> 1) OR (A <> 1 AND (B) == 1) + @todo + (low priority) Change this to be optimized as: @n + A XOR B -> (A) == 1 AND (B) <> 1) OR (A <> 1 AND (B) == 1) @n To be able to do this, we would however first have to extend the MySQL range optimizer to handle OR better. + + @note + As we don't do any index optimization on XOR this is not going to be + very fast to use. */ longlong Item_cond_xor::val_int() @@ -4850,15 +4848,12 @@ longlong Item_cond_xor::val_int() return (longlong) result; } -/* +/** Apply NOT transformation to the item and return a new one. - SYNOPSIS - neg_transformer() - thd thread handler - DESCRIPTION Transform the item using next rules: + @verbatim a AND b AND ... -> NOT(a) OR NOT(b) OR ... a OR b OR ... -> NOT(a) AND NOT(b) AND ... NOT(a) -> a @@ -4870,8 +4865,11 @@ longlong Item_cond_xor::val_int() a <= b -> a > b IS NULL(a) -> IS NOT NULL(a) IS NOT NULL(a) -> IS NULL(a) + @endverbatim - RETURN + @param thd thread handler + + @return New item or NULL if we cannot apply NOT transformation (see Item::neg_transformer()). */ @@ -4889,7 +4887,9 @@ Item *Item_bool_rowready_func2::neg_transformer(THD *thd) } -/* a IS NULL -> a IS NOT NULL */ +/** + a IS NULL -> a IS NOT NULL. +*/ Item *Item_func_isnull::neg_transformer(THD *thd) { Item *item= new Item_func_isnotnull(args[0]); @@ -4897,7 +4897,9 @@ Item *Item_func_isnull::neg_transformer(THD *thd) } -/* a IS NOT NULL -> a IS NULL */ +/** + a IS NOT NULL -> a IS NULL. +*/ Item *Item_func_isnotnull::neg_transformer(THD *thd) { Item *item= new Item_func_isnull(args[0]); @@ -4980,7 +4982,9 @@ Item *Item_func_le::negated_item() /* a <= b -> a > b */ return new Item_func_gt(args[0], args[1]); } -// just fake method, should never be called +/** + just fake method, should never be called. +*/ Item *Item_bool_rowready_func2::negated_item() { DBUG_ASSERT(0); @@ -5045,18 +5049,16 @@ uint Item_equal::members() } -/* - Check whether a field is referred in the multiple equality +/** + Check whether a field is referred in the multiple equality. - SYNOPSIS - contains() - field field whose occurrence is to be checked - - DESCRIPTION - The function checks whether field is occurred in the Item_equal object - - RETURN VALUES + The function checks whether field is occurred in the Item_equal object . + + @param field field whose occurrence is to be checked + + @retval 1 if nultiple equality contains a reference to field + @retval 0 otherwise */ @@ -5073,22 +5075,15 @@ bool Item_equal::contains(Field *field) } -/* - Join members of another Item_equal object - - SYNOPSIS - merge() - item multiple equality whose members are to be joined +/** + Join members of another Item_equal object. - DESCRIPTION The function actually merges two multiple equalities. After this operation the Item_equal object additionally contains the field items of another item of the type Item_equal. If the optional constant items are not equal the cond_false flag is set to 1. - - RETURN VALUES - none + @param item multiple equality whose members are to be joined */ void Item_equal::merge(Item_equal *item) @@ -5108,28 +5103,21 @@ void Item_equal::merge(Item_equal *item) } -/* - Order field items in multiple equality according to a sorting criteria +/** + Order field items in multiple equality according to a sorting criteria. - SYNOPSIS - sort() - cmp function to compare field item - arg context extra parameter for the cmp function - - DESCRIPTION - The function perform ordering of the field items in the Item_equal - object according to the criteria determined by the cmp callback parameter. - If cmp(item_field1,item_field2,arg)<0 than item_field1 must be - placed after item_fiel2. + The function perform ordering of the field items in the Item_equal + object according to the criteria determined by the cmp callback parameter. + If cmp(item_field1,item_field2,arg)<0 than item_field1 must be + placed after item_fiel2. - IMPLEMENTATION - The function sorts field items by the exchange sort algorithm. - The list of field items is looked through and whenever two neighboring - members follow in a wrong order they are swapped. This is performed - again and again until we get all members in a right order. - - RETURN VALUES - None + The function sorts field items by the exchange sort algorithm. + The list of field items is looked through and whenever two neighboring + members follow in a wrong order they are swapped. This is performed + again and again until we get all members in a right order. + + @param cmp function to compare field item + @param arg context extra parameter for the cmp function */ void Item_equal::sort(Item_field_cmpfunc cmp, void *arg) @@ -5164,21 +5152,14 @@ void Item_equal::sort(Item_field_cmpfunc cmp, void *arg) } -/* - Check appearance of new constant items in the multiple equality object +/** + Check appearance of new constant items in the multiple equality object. - SYNOPSIS - update_const() - - DESCRIPTION - The function checks appearance of new constant items among - the members of multiple equalities. Each new constant item is - compared with the designated constant item if there is any in the - multiple equality. If there is none the first new constant item - becomes designated. - - RETURN VALUES - none + The function checks appearance of new constant items among + the members of multiple equalities. Each new constant item is + compared with the designated constant item if there is any in the + multiple equality. If there is none the first new constant item + becomes designated. */ void Item_equal::update_const() diff --git a/sql/item_create.cc b/sql/item_create.cc index dc9f6e92884..40578bef5f8 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -13,7 +13,12 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* Functions to create an item. Used by sql_yacc.yy */ +/** + @file + + @brief + Functions to create an item. Used by sql_yac.yy +*/ #include "mysql_priv.h" #include "item_create.h" diff --git a/sql/item_func.cc b/sql/item_func.cc index bdd600c3fc9..be8966598d6 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -14,7 +14,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* This file defines all numerical functions */ +/** + @file + + @brief + This file defines all numerical functions +*/ #ifdef USE_PRAGMA_IMPLEMENTATION #pragma implementation // gcc: Class implementation @@ -46,7 +51,10 @@ bool check_reserved_words(LEX_STRING *name) } -/* return TRUE if item is a constant */ +/** + @return + TRUE if item is a constant +*/ bool eval_const_cond(COND *cond) @@ -237,25 +245,21 @@ void Item_func::traverse_cond(Cond_traverser traverser, } -/* - Transform an Item_func object with a transformer callback function - - SYNOPSIS - transform() - transformer the transformer callback function to be applied to the nodes - of the tree of the object - argument parameter to be passed to the transformer - - DESCRIPTION +/** + Transform an Item_func object with a transformer callback function. + The function recursively applies the transform method to each argument of the Item_func node. If the call of the method for an argument item returns a new item the old item is substituted for a new one. After this the transformer is applied to the root node of the Item_func object. - - RETURN VALUES - Item returned as the result of transformation of the root node + @param transformer the transformer callback function to be applied to + the nodes of the tree of the object + @param argument parameter to be passed to the transformer + + @return + Item returned as the result of transformation of the root node */ Item *Item_func::transform(Item_transformer transformer, uchar *argument) @@ -285,19 +289,10 @@ Item *Item_func::transform(Item_transformer transformer, uchar *argument) } -/* - Compile Item_func object with a processor and a transformer callback functions - - SYNOPSIS - compile() - analyzer the analyzer callback function to be applied to the nodes - of the tree of the object - arg_p in/out parameter to be passed to the processor - transformer the transformer callback function to be applied to the nodes - of the tree of the object - arg_t parameter to be passed to the transformer - - DESCRIPTION +/** + Compile Item_func object with a processor and a transformer + callback functions. + First the function applies the analyzer to the root node of the Item_func object. Then if the analizer succeeeds (returns TRUE) the function recursively applies the compile method to each argument @@ -306,9 +301,16 @@ Item *Item_func::transform(Item_transformer transformer, uchar *argument) the old item is substituted for a new one. After this the transformer is applied to the root node of the Item_func object. - - RETURN VALUES - Item returned as the result of transformation of the root node + + @param analyzer the analyzer callback function to be applied to the + nodes of the tree of the object + @param[in,out] arg_p parameter to be passed to the processor + @param transformer the transformer callback function to be applied to the + nodes of the tree of the object + @param arg_t parameter to be passed to the transformer + + @return + Item returned as the result of transformation of the root node */ Item *Item_func::compile(Item_analyzer analyzer, uchar **arg_p, @@ -334,7 +336,9 @@ Item *Item_func::compile(Item_analyzer analyzer, uchar **arg_p, return (this->*transformer)(arg_t); } -/* See comments in Item_cmp_func::split_sum_func() */ +/** + See comments in Item_cmp_func::split_sum_func() +*/ void Item_func::split_sum_func(THD *thd, Item **ref_pointer_array, List<Item> &fields) @@ -523,12 +527,9 @@ void Item_func_numhybrid::fix_num_length_and_dec() {} -/* +/** Set max_length/decimals of function if function is fixed point and - result length/precision depends on argument ones - - SYNOPSIS - Item_func::count_decimal_length() + result length/precision depends on argument ones. */ void Item_func::count_decimal_length() @@ -548,11 +549,8 @@ void Item_func::count_decimal_length() } -/* - Set max_length of if it is maximum length of its arguments - - SYNOPSIS - Item_func::count_only_length() +/** + Set max_length of if it is maximum length of its arguments. */ void Item_func::count_only_length() @@ -567,12 +565,9 @@ void Item_func::count_only_length() } -/* +/** Set max_length/decimals of function if function is floating point and - result length/precision depends on argument ones - - SYNOPSIS - Item_func::count_real_length() + result length/precision depends on argument ones. */ void Item_func::count_real_length() @@ -655,12 +650,9 @@ bool Item_func_connection_id::fix_fields(THD *thd, Item **ref) } -/* +/** Check arguments here to determine result's type for a numeric function of two arguments. - - SYNOPSIS - Item_num_op::find_num_type() */ void Item_num_op::find_num_type(void) @@ -699,13 +691,10 @@ void Item_num_op::find_num_type(void) } -/* +/** Set result type for a numeric function of one argument (can be also used by a numeric function of many arguments, if the result type depends only on the first argument) - - SYNOPSIS - Item_func_num1::find_num_type() */ void Item_func_num1::find_num_type() @@ -1117,16 +1106,15 @@ longlong Item_func_plus::int_op() } -/* - Calculate plus of two decimail's +/** + Calculate plus of two decimals. - SYNOPSIS - decimal_op() - decimal_value Buffer that can be used to store result + @param decimal_value Buffer that can be used to store result - RETURN - 0 Value was NULL; In this case null_value is set - # Value of operation as a decimal + @retval + 0 Value was NULL; In this case null_value is set + @retval + \# Value of operation as a decimal */ my_decimal *Item_func_plus::decimal_op(my_decimal *decimal_value) @@ -1144,11 +1132,8 @@ my_decimal *Item_func_plus::decimal_op(my_decimal *decimal_value) return 0; } -/* +/** Set precision of results for additive operations (+ and -) - - SYNOPSIS - Item_func_additive_op::result_precision() */ void Item_func_additive_op::result_precision() { @@ -1167,7 +1152,7 @@ void Item_func_additive_op::result_precision() } -/* +/** The following function is here to allow the user to force subtraction of UNSIGNED BIGINT to return negative values. */ @@ -1199,7 +1184,9 @@ longlong Item_func_minus::int_op() } -/* See Item_func_plus::decimal_op for comments */ +/** + See Item_func_plus::decimal_op for comments. +*/ my_decimal *Item_func_minus::decimal_op(my_decimal *decimal_value) { @@ -1238,7 +1225,7 @@ longlong Item_func_mul::int_op() } -/* See Item_func_plus::decimal_op for comments */ +/** See Item_func_plus::decimal_op for comments. */ my_decimal *Item_func_mul::decimal_op(my_decimal *decimal_value) { @@ -1574,7 +1561,7 @@ void Item_func_abs::fix_length_and_dec() } -/* Gateway to natural LOG function */ +/** Gateway to natural LOG function. */ double Item_func_ln::val_real() { DBUG_ASSERT(fixed == 1); @@ -1589,10 +1576,11 @@ double Item_func_ln::val_real() return log(value); } -/* - Extended but so slower LOG function - We have to check if all values are > zero and first one is not one - as these are the cases then result is not a number. +/** + Extended but so slower LOG function. + + We have to check if all values are > zero and first one is not one + as these are the cases then result is not a number. */ double Item_func_log::val_real() { @@ -3026,8 +3014,10 @@ bool udf_handler::get_arguments() return 0; } -/* This returns (String*) 0 in case of NULL values */ - +/** + @return + (String*)NULL in case of NULL values +*/ String *udf_handler::val_str(String *str,String *save_str) { uchar is_null_tmp=0; @@ -3231,10 +3221,11 @@ String *Item_func_udf_str::val_str(String *str) } -/* - This has to come last in the udf_handler methods, or C for AIX - version 6.0.0.0 fails to compile with debugging enabled. (Yes, really.) - */ +/** + @note + This has to come last in the udf_handler methods, or C for AIX + version 6.0.0.0 fails to compile with debugging enabled. (Yes, really.) +*/ udf_handler::~udf_handler() { @@ -3332,10 +3323,10 @@ void item_user_lock_release(User_level_lock *ull) delete ull; } -/* - Wait until we are at or past the given position in the master binlog - on the slave - */ +/** + Wait until we are at or past the given position in the master binlog + on the slave. +*/ longlong Item_master_pos_wait::val_int() { @@ -3397,7 +3388,7 @@ void debug_sync_point(const char* lock_name, uint lock_timeout) Structure is now initialized. Try to get the lock. Set up control struct to allow others to abort locks */ - thd->proc_info="User lock"; + thd_proc_info(thd, "User lock"); thd->mysys_var->current_mutex= &LOCK_user_locks; thd->mysys_var->current_cond= &ull->cond; @@ -3422,7 +3413,7 @@ void debug_sync_point(const char* lock_name, uint lock_timeout) } pthread_mutex_unlock(&LOCK_user_locks); pthread_mutex_lock(&thd->mysys_var->mutex); - thd->proc_info=0; + thd_proc_info(thd, 0); thd->mysys_var->current_mutex= 0; thd->mysys_var->current_cond= 0; pthread_mutex_unlock(&thd->mysys_var->mutex); @@ -3437,11 +3428,15 @@ void debug_sync_point(const char* lock_name, uint lock_timeout) #endif -/* - Get a user level lock. If the thread has an old lock this is first released. - Returns 1: Got lock - Returns 0: Timeout - Returns NULL: Error +/** + Get a user level lock. If the thread has an old lock this is first released. + + @retval + 1 : Got lock + @retval + 0 : Timeout + @retval + NULL : Error */ longlong Item_func_get_lock::val_int() @@ -3509,7 +3504,7 @@ longlong Item_func_get_lock::val_int() Structure is now initialized. Try to get the lock. Set up control struct to allow others to abort locks. */ - thd->proc_info="User lock"; + thd_proc_info(thd, "User lock"); thd->mysys_var->current_mutex= &LOCK_user_locks; thd->mysys_var->current_cond= &ull->cond; @@ -3552,7 +3547,7 @@ longlong Item_func_get_lock::val_int() pthread_mutex_unlock(&LOCK_user_locks); pthread_mutex_lock(&thd->mysys_var->mutex); - thd->proc_info=0; + thd_proc_info(thd, 0); thd->mysys_var->current_mutex= 0; thd->mysys_var->current_cond= 0; pthread_mutex_unlock(&thd->mysys_var->mutex); @@ -3561,12 +3556,12 @@ longlong Item_func_get_lock::val_int() } -/* +/** Release a user level lock. - Return: - 1 if lock released - 0 if lock wasn't held - (SQL) NULL if no such lock + @return + - 1 if lock released + - 0 if lock wasn't held + - (SQL) NULL if no such lock */ longlong Item_func_release_lock::val_int() @@ -3698,7 +3693,7 @@ void Item_func_benchmark::print(String *str) } -/* This function is just used to create tests with time gaps */ +/** This function is just used to create tests with time gaps. */ longlong Item_func_sleep::val_int() { @@ -3856,22 +3851,22 @@ bool Item_func_set_user_var::register_field_in_read_map(uchar *arg) } -/* +/** Set value to user variable. - SYNOPSYS - update_hash() - entry - pointer to structure representing variable - set_null - should we set NULL value ? - ptr - pointer to buffer with new value - length - length of new value - type - type of new value - cs - charset info for new value - dv - derivation for new value - unsigned_arg - indiates if a value of type INT_RESULT is unsigned - - RETURN VALUE - False - success, True - failure + @param entry pointer to structure representing variable + @param set_null should we set NULL value ? + @param ptr pointer to buffer with new value + @param length length of new value + @param type type of new value + @param cs charset info for new value + @param dv derivation for new value + @param unsigned_arg indiates if a value of type INT_RESULT is unsigned + + @retval + false success + @retval + true failure */ static bool @@ -3956,7 +3951,7 @@ Item_func_set_user_var::update_hash(void *ptr, uint length, } -/* Get the value of a variable as a double */ +/** Get the value of a variable as a double. */ double user_var_entry::val_real(my_bool *null_value) { @@ -3984,7 +3979,7 @@ double user_var_entry::val_real(my_bool *null_value) } -/* Get the value of a variable as an integer */ +/** Get the value of a variable as an integer. */ longlong user_var_entry::val_int(my_bool *null_value) { @@ -4015,7 +4010,7 @@ longlong user_var_entry::val_int(my_bool *null_value) } -/* Get the value of a variable as a string */ +/** Get the value of a variable as a string. */ String *user_var_entry::val_str(my_bool *null_value, String *str, uint decimals) @@ -4046,7 +4041,7 @@ String *user_var_entry::val_str(my_bool *null_value, String *str, return(str); } -/* Get the value of a variable as a decimal */ +/** Get the value of a variable as a decimal. */ my_decimal *user_var_entry::val_decimal(my_bool *null_value, my_decimal *val) { @@ -4073,18 +4068,17 @@ my_decimal *user_var_entry::val_decimal(my_bool *null_value, my_decimal *val) return(val); } -/* - This functions is invoked on SET @variable or @variable:= expression. - Evaluate (and check expression), store results. +/** + This functions is invoked on SET \@variable or + \@variable:= expression. - SYNOPSYS - Item_func_set_user_var::check() + Evaluate (and check expression), store results. - NOTES + @note For now it always return OK. All problem with value evaluating will be caught by thd->is_error() check in sql_set_variables(). - RETURN + @retval FALSE OK. */ @@ -4133,18 +4127,17 @@ Item_func_set_user_var::check(bool use_result_field) } -/* - This functions is invoked on SET @variable or @variable:= expression. - - SYNOPSIS - Item_func_set_user_var::update() +/** + This functions is invoked on + SET \@variable or \@variable:= expression. - NOTES + @note We have to store the expression as such in the variable, independent of the value method used by the user - RETURN + @retval 0 OK + @retval 1 EOM Error */ @@ -4453,24 +4446,23 @@ longlong Item_func_get_user_var::val_int() } -/* +/** Get variable by name and, if necessary, put the record of variable use into the binary log. - - SYNOPSIS - get_var_with_binlog() - thd Current thread - name Variable name - out_entry [out] variable structure or NULL. The pointer is set - regardless of whether function succeeded or not. When a user variable is invoked from an update query (INSERT, UPDATE etc), stores this variable and its value in thd->user_var_events, so that it can be written to the binlog (will be written just before the query is written, see log.cc). - RETURN + @param thd Current thread + @param name Variable name + @param[out] out_entry variable structure or NULL. The pointer is set + regardless of whether function succeeded or not. + + @retval 0 OK + @retval 1 Failed to put appropriate record into binary log */ @@ -5125,22 +5117,20 @@ longlong Item_func_bit_xor::val_int() System variables ****************************************************************************/ -/* - Return value of an system variable base[.name] as a constant item +/** + Return value of an system variable base[.name] as a constant item. - SYNOPSIS - get_system_var() - thd Thread handler - var_type global / session - name Name of base or system variable - component Component + @param thd Thread handler + @param var_type global / session + @param name Name of base or system variable + @param component Component. - NOTES + @note If component.str = 0 then the variable name is in 'name' - RETURN - 0 error - # constant item + @return + - 0 : error + - # : constant item */ @@ -5180,16 +5170,15 @@ Item *get_system_var(THD *thd, enum_var_type var_type, LEX_STRING name, } -/* +/** Check a user level lock. - SYNOPSIS: - val_int() + Sets null_value=TRUE on error. - RETURN VALUES + @retval 1 Available - 0 Already taken - NULL Error + @retval + 0 Already taken, or error */ longlong Item_func_is_free_lock::val_int() diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc index 2da5965c94d..ac1b7738a27 100644 --- a/sql/item_geofunc.cc +++ b/sql/item_geofunc.cc @@ -14,7 +14,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* This file defines all spatial functions */ +/** + @file + + @brief + This file defines all spatial functions +*/ #ifdef USE_PRAGMA_IMPLEMENTATION #pragma implementation // gcc: Class implementation @@ -356,7 +361,7 @@ String *Item_func_point::val_str(String *str) } -/* +/** Concatenates various items into various collections with checkings for valid wkb type of items. For example, MultiPoint can be a collection of Points only. @@ -538,6 +543,10 @@ longlong Item_func_isempty::val_int() } +/** + @todo + Ramil or Holyfoot, add real IsSimple calculation +*/ longlong Item_func_issimple::val_int() { DBUG_ASSERT(fixed == 1); diff --git a/sql/item_row.cc b/sql/item_row.cc index d1d1011ab2b..369aa04930e 100644 --- a/sql/item_row.cc +++ b/sql/item_row.cc @@ -15,13 +15,18 @@ #include "mysql_priv.h" -/* +/** Row items used for comparing rows and IN operations on rows: + @verbatim (a, b, c) > (10, 10, 30) (a, b, c) = (select c, d, e, from t1 where x=12) (a, b, c) IN ((1,2,2), (3,4,5), (6,7,8) (a, b, c) IN (select c, d, e, from t1) + @endverbatim + + @todo + think placing 2-3 component items in item (as it done for function */ Item_row::Item_row(List<Item> &arg): diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index a7624c5bbcd..42314872997 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -14,9 +14,15 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* This file defines all string functions -** Warning: Some string functions doesn't always put and end-null on a String -** (This shouldn't be needed) +/** + @file + + @brief + This file defines all string functions + + @warning + Some string functions don't always put and end-null on a String. + (This shouldn't be needed) */ #ifdef USE_PRAGMA_IMPLEMENTATION @@ -267,9 +273,9 @@ void Item_func_aes_decrypt::fix_length_and_dec() } -/* +/** Concatenate args with the following premises: - If only one arg (which is ok), return value of arg + If only one arg (which is ok), return value of arg; Don't reallocate val_str() if not absolute necessary. */ @@ -425,13 +431,15 @@ void Item_func_concat::fix_length_and_dec() max_length= (ulong) max_result_length; } -/* +/** + @details Function des_encrypt() by tonu@spam.ee & monty Works only if compiled with OpenSSL library support. - This returns a binary string where first character is CHAR(128 | key-number). - If one uses a string key key_number is 127. - Encryption result is longer than original by formula: - new_length= org_length + (8-(org_length % 8))+1 + @return + A binary string where first character is CHAR(128 | key-number). + If one uses a string key key_number is 127. + Encryption result is longer than original by formula: + @code new_length= org_length + (8-(org_length % 8))+1 @endcode */ String *Item_func_des_encrypt::val_str(String *str) @@ -604,7 +612,7 @@ wrong_key: } -/* +/** concat with separator. First arg is the separator concat_ws takes at least two arguments. */ @@ -826,12 +834,14 @@ void Item_func_reverse::fix_length_and_dec() max_length = args[0]->max_length; } -/* -** Replace all occurences of string2 in string1 with string3. -** Don't reallocate val_str() if not needed -*/ +/** + Replace all occurences of string2 in string1 with string3. + + Don't reallocate val_str() if not needed. -/* TODO: Fix that this works with binary strings when using USE_MB */ + @todo + Fix that this works with binary strings when using USE_MB +*/ String *Item_func_replace::val_str(String *str) { @@ -1796,8 +1806,9 @@ String *Item_func_database::val_str(String *str) } -/* - TODO: make USER() replicate properly (currently it is replicated to "") +/** + @todo + make USER() replicate properly (currently it is replicated to "") */ bool Item_func_user::init(const char *user, const char *host) { @@ -1857,7 +1868,7 @@ void Item_func_soundex::fix_length_and_dec() } -/* +/** If alpha, map input letter to soundex code. If not alpha and remove_garbage is set then skip to next char else return 0 @@ -2001,9 +2012,10 @@ String *Item_func_soundex::val_str(String *str) } -/* -** Change a number to format '3,333,333,333.000' -** This should be 'internationalized' sometimes. +/** + Change a number to format '3,333,333,333.000'. + + This should be 'internationalized' sometimes. */ const int FORMAT_MAX_DECIMALS= 30; @@ -2022,8 +2034,9 @@ void Item_func_format::fix_length_and_dec() } -/* - TODO: This needs to be fixed for multi-byte character set where numbers +/** + @todo + This needs to be fixed for multi-byte character set where numbers are stored in more than one byte */ @@ -2370,9 +2383,9 @@ void Item_func_repeat::fix_length_and_dec() } } -/* -** Item_func_repeat::str is carefully written to avoid reallocs -** as much as possible at the cost of a local buffer +/** + Item_func_repeat::str is carefully written to avoid reallocs + as much as possible at the cost of a local buffer */ String *Item_func_repeat::val_str(String *str) @@ -2848,7 +2861,7 @@ String *Item_func_hex::val_str(String *str) return &tmp_value; } - /* Convert given hex string to a binary string */ + /** Convert given hex string to a binary string. */ String *Item_func_unhex::val_str(String *str) { @@ -3081,27 +3094,27 @@ String* Item_func_inet_ntoa::val_str(String* str) } -/* +#define get_esc_bit(mask, num) (1 & (*((mask) + ((num) >> 3))) >> ((num) & 7)) + +/** QUOTE() function returns argument string in single quotes suitable for using in a SQL statement. - DESCRIPTION - Adds a \ before all characters that needs to be escaped in a SQL string. - We also escape '^Z' (END-OF-FILE in windows) to avoid probelms when - running commands from a file in windows. + Adds a \\ before all characters that needs to be escaped in a SQL string. + We also escape '^Z' (END-OF-FILE in windows) to avoid probelms when + running commands from a file in windows. - This function is very useful when you want to generate SQL statements + This function is very useful when you want to generate SQL statements. - NOTE + @note QUOTE(NULL) returns the string 'NULL' (4 letters, without quotes). - RETURN VALUES - str Quoted string - NULL Out of memory. + @retval + str Quoted string + @retval + NULL Out of memory. */ -#define get_esc_bit(mask, num) (1 & (*((mask) + ((num) >> 3))) >> ((num) & 7)) - String *Item_func_quote::val_str(String *str) { DBUG_ASSERT(fixed == 1); @@ -3347,8 +3360,10 @@ static uint nanoseq; static ulonglong uuid_time=0; static char clock_seq_and_node_str[]="-0000-000000000000"; -/* number of 100-nanosecond intervals between - 1582-10-15 00:00:00.00 and 1970-01-01 00:00:00.00 */ +/** + number of 100-nanosecond intervals between + 1582-10-15 00:00:00.00 and 1970-01-01 00:00:00.00. +*/ #define UUID_TIME_OFFSET ((ulonglong) 141427 * 24 * 60 * 60 * 1000 * 10 ) #define UUID_VERSION 0x1000 diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index e2003f820b6..46b8d2e46cc 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -13,12 +13,15 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* - subselect Item +/** + @file + + @brief + subselect Item -SUBSELECT TODO: - - add function from mysql_select that use JOIN* as parameter to JOIN methods - (sql_select.h/sql_select.cc) + @todo + - add function from mysql_select that use JOIN* as parameter to JOIN + methods (sql_select.h/sql_select.cc) */ #ifdef USE_PRAGMA_IMPLEMENTATION @@ -403,6 +406,16 @@ void Item_singlerow_subselect::reset() } +/** + @todo + - We cant change name of Item_field or Item_ref, because it will + prevent it's correct resolving, but we should save name of + removed item => we do not make optimization if top item of + list is field or reference. + - switch off this optimization for prepare statement, + because we do not rollback this changes. + Make rollback for it, or special name resolving mode in 5.0. +*/ Item_subselect::trans_res Item_singlerow_subselect::select_transformer(JOIN *join) { @@ -1445,24 +1458,24 @@ Item_in_subselect::select_transformer(JOIN *join) } -/* +/** Prepare IN/ALL/ANY/SOME subquery transformation and call appropriate - transformation function + transformation function. - SYNOPSIS - Item_in_subselect::select_in_like_transformer() - join JOIN object of transforming subquery - func creator of condition function of subquery - - DESCRIPTION To decide which transformation procedure (scalar or row) applicable here we have to call fix_fields() for left expression to be able to call cols() method on it. Also this method make arena management for underlying transformation methods. - RETURN + @param join JOIN object of transforming subquery + @param func creator of condition function of subquery + + @retval RES_OK OK - RES_REDUCE OK, and current subquery was reduced during transformation + @retval + RES_REDUCE OK, and current subquery was reduced during + transformation + @retval RES_ERROR Error */ @@ -2425,16 +2438,15 @@ void subselect_indexsubquery_engine::print(String *str) str->append(')'); } -/* - change select_result object of engine +/** + change select_result object of engine. - SYNOPSIS - subselect_single_select_engine::change_result() - si new subselect Item - res new select_result object + @param si new subselect Item + @param res new select_result object - RETURN + @retval FALSE OK + @retval TRUE error */ @@ -2447,16 +2459,15 @@ bool subselect_single_select_engine::change_result(Item_subselect *si, } -/* - change select_result object of engine +/** + change select_result object of engine. - SYNOPSIS - subselect_single_select_engine::change_result() - si new subselect Item - res new select_result object + @param si new subselect Item + @param res new select_result object - RETURN + @retval FALSE OK + @retval TRUE error */ @@ -2470,16 +2481,15 @@ bool subselect_union_engine::change_result(Item_subselect *si, } -/* - change select_result emulation, never should be called +/** + change select_result emulation, never should be called. - SYNOPSIS - subselect_single_select_engine::change_result() - si new subselect Item - res new select_result object + @param si new subselect Item + @param res new select_result object - RETURN + @retval FALSE OK + @retval TRUE error */ @@ -2491,14 +2501,12 @@ bool subselect_uniquesubquery_engine::change_result(Item_subselect *si, } -/* - Report about presence of tables in subquery - - SYNOPSIS - subselect_single_select_engine::no_tables() +/** + Report about presence of tables in subquery. - RETURN + @retval TRUE there are not tables used in subquery + @retval FALSE there are some tables in subquery */ bool subselect_single_select_engine::no_tables() @@ -2523,14 +2531,12 @@ bool subselect_single_select_engine::may_be_null() } -/* - Report about presence of tables in subquery +/** + Report about presence of tables in subquery. - SYNOPSIS - subselect_union_engine::no_tables() - - RETURN + @retval TRUE there are not tables used in subquery + @retval FALSE there are some tables in subquery */ bool subselect_union_engine::no_tables() @@ -2544,14 +2550,12 @@ bool subselect_union_engine::no_tables() } -/* - Report about presence of tables in subquery +/** + Report about presence of tables in subquery. - SYNOPSIS - subselect_uniquesubquery_engine::no_tables() - - RETURN + @retval TRUE there are not tables used in subquery + @retval FALSE there are some tables in subquery */ diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 881f472d766..91198d0fb7e 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -14,7 +14,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* Sum functions (COUNT, MIN...) */ +/** + @file + + @brief + Sum functions (COUNT, MIN...) +*/ #ifdef USE_PRAGMA_IMPLEMENTATION #pragma implementation // gcc: Class implementation @@ -23,28 +28,25 @@ #include "mysql_priv.h" #include "sql_select.h" -/* - Prepare an aggregate function item for checking context conditions - - SYNOPSIS - init_sum_func_check() - thd reference to the thread context info +/** + Prepare an aggregate function item for checking context conditions. - DESCRIPTION The function initializes the members of the Item_sum object created for a set function that are used to check validity of the set function occurrence. If the set function is not allowed in any subquery where it occurs an error is reported immediately. - NOTES + @param thd reference to the thread context info + + @note This function is to be called for any item created for a set function object when the traversal of trees built for expressions used in the query is performed at the phase of context analysis. This function is to be invoked at the descent of this traversal. - - RETURN - TRUE if an error is reported + @retval + TRUE if an error is reported + @retval FALSE otherwise */ @@ -69,15 +71,9 @@ bool Item_sum::init_sum_func_check(THD *thd) return FALSE; } -/* - Check constraints imposed on a usage of a set function - - SYNOPSIS - check_sum_func() - thd reference to the thread context info - ref location of the pointer to this item in the embedding expression +/** + Check constraints imposed on a usage of a set function. - DESCRIPTION The method verifies whether context conditions imposed on a usage of any set function are met for this occurrence. It checks whether the set function occurs in the position where it @@ -89,13 +85,6 @@ bool Item_sum::init_sum_func_check(THD *thd) adds it to the chain of items for such set functions that is attached to the the st_select_lex structure for this subquery. - NOTES - This function is to be called for any item created for a set function - object when the traversal of trees built for expressions used in the query - is performed at the phase of context analysis. This function is to - be invoked at the ascent of this traversal. - - IMPLEMENTATION A number of designated members of the object are used to check the conditions. They are specified in the comment before the Item_sum class declaration. @@ -106,16 +95,28 @@ bool Item_sum::init_sum_func_check(THD *thd) of set functions are allowed (i.e either in the SELECT list or in the HAVING clause of the corresponding subquery) Consider the query: - SELECT SUM(t1.b) FROM t1 GROUP BY t1.a - HAVING t1.a IN (SELECT t2.c FROM t2 WHERE AVG(t1.b) > 20) AND - t1.a > (SELECT MIN(t2.d) FROM t2); + @code + SELECT SUM(t1.b) FROM t1 GROUP BY t1.a + HAVING t1.a IN (SELECT t2.c FROM t2 WHERE AVG(t1.b) > 20) AND + t1.a > (SELECT MIN(t2.d) FROM t2); + @endcode allow_sum_func will contain: - for SUM(t1.b) - 1 at the first position - for AVG(t1.b) - 1 at the first position, 0 at the second position - for MIN(t2.d) - 1 at the first position, 1 at the second position. + - for SUM(t1.b) - 1 at the first position + - for AVG(t1.b) - 1 at the first position, 0 at the second position + - for MIN(t2.d) - 1 at the first position, 1 at the second position. + + @param thd reference to the thread context info + @param ref location of the pointer to this item in the embedding expression + + @note + This function is to be called for any item created for a set function + object when the traversal of trees built for expressions used in the query + is performed at the phase of context analysis. This function is to + be invoked at the ascent of this traversal. - RETURN - TRUE if an error is reported + @retval + TRUE if an error is reported + @retval FALSE otherwise */ @@ -200,15 +201,9 @@ bool Item_sum::check_sum_func(THD *thd, Item **ref) return FALSE; } -/* - Attach a set function to the subquery where it must be aggregated +/** + Attach a set function to the subquery where it must be aggregated. - SYNOPSIS - register_sum_func() - thd reference to the thread context info - ref location of the pointer to this item in the embedding expression - - DESCRIPTION The function looks for an outer subquery where the set function must be aggregated. If it finds such a subquery then aggr_level is set to the nest level of this subquery and the item for the set function @@ -216,14 +211,18 @@ bool Item_sum::check_sum_func(THD *thd, Item **ref) inner_sum_func_list defined for each subquery. When the item is placed there the field 'ref_by' is set to ref. - NOTES. + @note Now we 'register' only set functions that are aggregated in outer subqueries. Actually it makes sense to link all set function for a subquery in one chain. It would simplify the process of 'splitting' for set functions. - RETURN + @param thd reference to the thread context info + @param ref location of the pointer to this item in the embedding expression + + @retval FALSE if the executes without failures (currently always) + @retval TRUE otherwise */ @@ -311,8 +310,8 @@ Item_sum::Item_sum(List<Item> &list) :arg_count(list.elements), } -/* - Constructor used in processing select with temporary tebles +/** + Constructor used in processing select with temporary tebles. */ Item_sum::Item_sum(THD *thd, Item_sum *item): @@ -655,6 +654,10 @@ Field *Item_sum_hybrid::create_tmp_field(bool group, TABLE *table, ** reset and add of sum_func ***********************************************************************/ +/** + @todo + check if the following assignments are really needed +*/ Item_sum_sum::Item_sum_sum(THD *thd, Item_sum_sum *item) :Item_sum_num(thd, item), hybrid_type(item->hybrid_type), curr_dec_buff(item->curr_dec_buff) @@ -833,7 +836,7 @@ Item_sum_distinct::Item_sum_distinct(THD *thd, Item_sum_distinct *original) } -/* +/** Behaves like an Integer except to fix_length_and_dec(). Additionally div() converts val with this traits to a val with true decimal traits along with conversion of integer value to decimal value. @@ -910,6 +913,10 @@ void Item_sum_distinct::fix_length_and_dec() } +/** + @todo + check that the case of CHAR(0) works OK +*/ bool Item_sum_distinct::setup(THD *thd) { List<Create_field> field_list; @@ -2004,8 +2011,8 @@ void Item_sum_bit::update_field() } -/* -** calc next value and merge it with field_value +/** + calc next value and merge it with field_value. */ void Item_sum_sum::update_field() @@ -2181,6 +2188,10 @@ Item_sum_hybrid::min_max_update_int_field() } +/** + @todo + optimize: do not get result_field in case of args[0] is NULL +*/ void Item_sum_hybrid::min_max_update_decimal_field() { @@ -2369,7 +2380,7 @@ int simple_str_key_cmp(void* arg, uchar* key1, uchar* key2) return f->cmp(key1, key2); } -/* +/** Did not make this one static - at least gcc gets confused when I try to declare a static function as a friend. If you can figure out the syntax to make a static function a friend, make this one @@ -2436,7 +2447,10 @@ void Item_sum_count_distinct::cleanup() } -/* This is used by rollup to create a separate usable copy of the function */ +/** + This is used by rollup to create a separate usable copy of + the function. +*/ void Item_sum_count_distinct::make_unique() { @@ -2804,7 +2818,7 @@ my_decimal *Item_sum_udf_int::val_decimal(my_decimal *dec) } -/* Default max_length is max argument length */ +/** Default max_length is max argument length. */ void Item_sum_udf_str::fix_length_and_dec() { @@ -2899,9 +2913,8 @@ int group_concat_key_cmp_with_distinct(void* arg, const void* key1, } -/* - function of sort for syntax: - GROUP_CONCAT(expr,... ORDER BY col,... ) +/** + function of sort for syntax: GROUP_CONCAT(expr,... ORDER BY col,... ) */ int group_concat_key_cmp_with_order(void* arg, const void* key1, @@ -2944,8 +2957,8 @@ int group_concat_key_cmp_with_order(void* arg, const void* key1, } -/* - Append data from current leaf to item->result +/** + Append data from current leaf to item->result. */ int dump_leaf_key(uchar* key, element_count count __attribute__((unused)), @@ -3016,12 +3029,13 @@ int dump_leaf_key(uchar* key, element_count count __attribute__((unused)), } -/* - Constructor of Item_func_group_concat - distinct_arg - distinct - select_list - list of expression for show values - order_list - list of sort columns - separator_arg - string value of separator +/** + Constructor of Item_func_group_concat. + + @param distinct_arg distinct + @param select_list list of expression for show values + @param order_list list of sort columns + @param separator_arg string value of separator. */ Item_func_group_concat:: diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 56a6480d859..a0beadcd481 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -14,7 +14,15 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* This file defines all time functions */ +/** + @file + + @brief + This file defines all time functions + + @todo + Move month and days to language files +*/ #ifdef USE_PRAGMA_IMPLEMENTATION #pragma implementation // gcc: Class implementation @@ -24,17 +32,16 @@ #include <m_ctype.h> #include <time.h> -/* TODO: Move month and days to language files */ - -/* Day number for Dec 31st, 9999 */ +/** Day number for Dec 31st, 9999. */ #define MAX_DAY_NUMBER 3652424L -/* - OPTIMIZATION TODO: - - Replace the switch with a function that should be called for each - date type. - - Remove sprintf and opencode the conversion, like we do in - Field_datetime. +/** + @todo + OPTIMIZATION + - Replace the switch with a function that should be called for each + date type. + - Remove sprintf and opencode the conversion, like we do in + Field_datetime. The reason for this functions existence is that as we don't have a way to know if a datetime/time value has microseconds in them @@ -226,37 +233,37 @@ static DATE_TIME_FORMAT time_ampm_format= {{0}, '\0', 0, static DATE_TIME_FORMAT time_24hrs_format= {{0}, '\0', 0, {(char *)"%H:%i:%S", 8}}; -/* +/** Extract datetime value to MYSQL_TIME struct from string value - according to format string. + according to format string. - SYNOPSIS - extract_date_time() - format date/time format specification - val String to decode - length Length of string - l_time Store result here - cached_timestamp_type - It uses to get an appropriate warning - in the case when the value is truncated. - sub_pattern_end if non-zero then we are parsing string which - should correspond compound specifier (like %T or - %r) and this parameter is pointer to place where - pointer to end of string matching this specifier - should be stored. - NOTE - Possibility to parse strings matching to patterns equivalent to compound - specifiers is mainly intended for use from inside of this function in - order to understand %T and %r conversion specifiers, so number of - conversion specifiers that can be used in such sub-patterns is limited. - Also most of checks are skipped in this case. - - If one adds new format specifiers to this function he should also - consider adding them to get_date_time_result_type() function. - - RETURN - 0 ok - 1 error + @param format date/time format specification + @param val String to decode + @param length Length of string + @param l_time Store result here + @param cached_timestamp_type It uses to get an appropriate warning + in the case when the value is truncated. + @param sub_pattern_end if non-zero then we are parsing string which + should correspond compound specifier (like %T or + %r) and this parameter is pointer to place where + pointer to end of string matching this specifier + should be stored. + + @note + Possibility to parse strings matching to patterns equivalent to compound + specifiers is mainly intended for use from inside of this function in + order to understand %T and %r conversion specifiers, so number of + conversion specifiers that can be used in such sub-patterns is limited. + Also most of checks are skipped in this case. + + @note + If one adds new format specifiers to this function he should also + consider adding them to get_date_time_result_type() function. + + @retval + 0 ok + @retval + 1 error */ static bool extract_date_time(DATE_TIME_FORMAT *format, @@ -603,8 +610,8 @@ err: } -/* - Create a formated date/time value in a string +/** + Create a formated date/time value in a string. */ bool make_date_time(DATE_TIME_FORMAT *format, MYSQL_TIME *l_time, @@ -838,7 +845,8 @@ bool make_date_time(DATE_TIME_FORMAT *format, MYSQL_TIME *l_time, } -/* +/** + @details Get a array of positive numbers from a string object. Each number is separated by 1 non digit character Return error if there is too many numbers. @@ -846,16 +854,14 @@ bool make_date_time(DATE_TIME_FORMAT *format, MYSQL_TIME *l_time, from the high end. This allows one to give: DAY_TO_SECOND as "D MM:HH:SS", "MM:HH:SS" "HH:SS" or as seconds. - SYNOPSIS - str: string value - length: length of str - cs: charset of str - values: array of results - count: count of elements in result array - transform_msec: if value is true we suppose - that the last part of string value is microseconds - and we should transform value to six digit value. - For example, '1.1' -> '1.100000' + @param length: length of str + @param cs: charset of str + @param values: array of results + @param count: count of elements in result array + @param transform_msec: if value is true we suppose + that the last part of string value is microseconds + and we should transform value to six digit value. + For example, '1.1' -> '1.100000' */ static bool get_interval_info(const char *str,uint length,CHARSET_INFO *cs, @@ -1046,7 +1052,9 @@ String* Item_func_monthname::val_str(String* str) } -// Returns the quarter of the year +/** + Returns the quarter of the year. +*/ longlong Item_func_quarter::val_int() { @@ -1072,8 +1080,10 @@ longlong Item_func_minute::val_int() (void) get_arg0_time(<ime); return ltime.minute; } -// Returns the second in time_exp in the range of 0 - 59 +/** + Returns the second in time_exp in the range of 0 - 59. +*/ longlong Item_func_second::val_int() { DBUG_ASSERT(fixed == 1); @@ -1091,7 +1101,8 @@ uint week_mode(uint mode) return week_format; } -/* +/** + @verbatim The bits in week_format(for calc_week() function) has the following meaning: WEEK_MONDAY_FIRST (0) If not set Sunday is first day of week If set Monday is first day of week @@ -1118,6 +1129,7 @@ uint week_mode(uint mode) four or more days in the new year, then it is week 1; Otherwise it is the last week of the previous year, and the next week is week 1. + @endverbatim */ longlong Item_func_week::val_int() @@ -1281,8 +1293,9 @@ longlong Item_func_time_to_sec::val_int() } -/* - Convert a string to a interval value +/** + Convert a string to a interval value. + To make code easy, allow interval objects without separators. */ @@ -1506,7 +1519,7 @@ String *Item_func_curdate::val_str(String *str) return str; } -/* +/** Converts current time in my_time_t to MYSQL_TIME represenatation for local time zone. Defines time zone (local) used for whole CURDATE function. */ @@ -1519,7 +1532,7 @@ void Item_func_curdate_local::store_now_in_TIME(MYSQL_TIME *now_time) } -/* +/** Converts current time in my_time_t to MYSQL_TIME represenatation for UTC time zone. Defines time zone (UTC) used for whole UTC_DATE function. */ @@ -1563,7 +1576,7 @@ void Item_func_curtime::fix_length_and_dec() } -/* +/** Converts current time in my_time_t to MYSQL_TIME represenatation for local time zone. Defines time zone (local) used for whole CURTIME function. */ @@ -1576,7 +1589,7 @@ void Item_func_curtime_local::store_now_in_TIME(MYSQL_TIME *now_time) } -/* +/** Converts current time in my_time_t to MYSQL_TIME represenatation for UTC time zone. Defines time zone (UTC) used for whole UTC_TIME function. */ @@ -1612,7 +1625,7 @@ void Item_func_now::fix_length_and_dec() } -/* +/** Converts current time in my_time_t to MYSQL_TIME represenatation for local time zone. Defines time zone (local) used for whole NOW function. */ @@ -1625,7 +1638,7 @@ void Item_func_now_local::store_now_in_TIME(MYSQL_TIME *now_time) } -/* +/** Converts current time in my_time_t to MYSQL_TIME represenatation for UTC time zone. Defines time zone (UTC) used for whole UTC_TIMESTAMP function. */ @@ -1655,7 +1668,7 @@ int Item_func_now::save_in_field(Field *to, bool no_conversions) } -/* +/** Converts current time in my_time_t to MYSQL_TIME represenatation for local time zone. Defines time zone (local) used for whole SYSDATE function. */ @@ -2618,7 +2631,7 @@ longlong Item_date_typecast::val_int() return (longlong) (ltime.year * 10000L + ltime.month * 100 + ltime.day); } -/* +/** MAKEDATE(a,b) is a date function that creates a date value from a year and day value. @@ -2728,7 +2741,7 @@ void Item_func_add_time::fix_length_and_dec() cached_field_type= MYSQL_TYPE_TIME; } -/* +/** ADDTIME(t,a) and SUBTIME(t,a) are time functions that calculate a time/datetime value @@ -2830,7 +2843,7 @@ void Item_func_add_time::print(String *str) } -/* +/** TIMEDIFF(t,s) is a time function that calculates the time value between a start and end time. @@ -2880,7 +2893,7 @@ null_date: return 0; } -/* +/** MAKETIME(h,m,s) is a time function that calculates a time value from the total number of hours, minutes, and seconds. Result: Time value @@ -2947,7 +2960,7 @@ String *Item_func_maketime::val_str(String *str) } -/* +/** MICROSECOND(a) is a function ( extraction) that extracts the microseconds from a. @@ -3173,25 +3186,28 @@ void Item_func_get_format::print(String *str) } -/* +/** Get type of datetime value (DATE/TIME/...) which will be produced according to format string. - SYNOPSIS - get_date_time_result_type() - format - format string - length - length of format string + @param format format string + @param length length of format string - NOTE + @note We don't process day format's characters('D', 'd', 'e') because day may be a member of all date/time types. + @note Format specifiers supported by this function should be in sync with specifiers supported by extract_date_time() function. - RETURN VALUE + @return One of date_time_format_types values: - DATE_TIME_MICROSECOND, DATE_TIME, DATE_ONLY, TIME_MICROSECOND, TIME_ONLY + - DATE_TIME_MICROSECOND + - DATE_TIME + - DATE_ONLY + - TIME_MICROSECOND + - TIME_ONLY */ static date_time_format_types diff --git a/sql/key.cc b/sql/key.cc index 6ddfe10848f..7f075674ab6 100644 --- a/sql/key.cc +++ b/sql/key.cc @@ -90,25 +90,19 @@ int find_ref_key(KEY *key, uint key_count, uchar *record, Field *field, } -/* +/** Copy part of a record that forms a key or key prefix to a buffer. - SYNOPSIS - key_copy() - to_key buffer that will be used as a key - from_record full record to be copied from - key_info descriptor of the index - key_length specifies length of all keyparts that will be copied - - DESCRIPTION The function takes a complete table record (as e.g. retrieved by handler::index_read()), and a description of an index on the same table, and extracts the first key_length bytes of the record which are part of a key into to_key. If length == 0 then copy all bytes from the record that form a key. - RETURN - None + @param to_key buffer that will be used as a key + @param from_record full record to be copied from + @param key_info descriptor of the index + @param key_length specifies length of all keyparts that will be copied */ void key_copy(uchar *to_key, uchar *from_record, KEY *key_info, @@ -150,22 +144,16 @@ void key_copy(uchar *to_key, uchar *from_record, KEY *key_info, } -/* +/** Restore a key from some buffer to record. - SYNOPSIS - key_restore() - to_record record buffer where the key will be restored to - from_key buffer that contains a key - key_info descriptor of the index - key_length specifies length of all keyparts that will be restored - - DESCRIPTION This function converts a key into record format. It can be used in cases when we want to return a key as a result row. - RETURN - None + @param to_record record buffer where the key will be restored to + @param from_key buffer that contains a key + @param key_info descriptor of the index + @param key_length specifies length of all keyparts that will be restored */ void key_restore(uchar *to_record, uchar *from_key, KEY *key_info, @@ -242,24 +230,23 @@ void key_restore(uchar *to_record, uchar *from_key, KEY *key_info, } -/* - Compare if a key has changed +/** + Compare if a key has changed. - SYNOPSIS - key_cmp_if_same() - table TABLE - key key to compare to row - idx Index used - key_length Length of key + @param table TABLE + @param key key to compare to row + @param idx Index used + @param key_length Length of key - NOTES + @note In theory we could just call field->cmp() for all field types, but as we are only interested if a key has changed (not if the key is larger or smaller than the previous value) we can do things a bit faster by using memcmp() instead. - RETURN + @retval 0 If key is equal + @retval 1 Key has changed */ @@ -318,17 +305,17 @@ bool key_cmp_if_same(TABLE *table,const uchar *key,uint idx,uint key_length) } /* - unpack key-fields from record to some buffer + unpack key-fields from record to some buffer. - SYNOPSIS - key_unpack() + This is used mainly to get a good error message. We temporary + change the column bitmap so that all columns are readable. + + @param to Store value here in an easy to read form + @param table Table to use + @param idx Key number - - NOTES - This is used mainly to get a good error message - We temporary change the column bitmap so that all columns are readable. */ void key_unpack(String *to,TABLE *table,uint idx) @@ -406,21 +393,18 @@ bool is_key_used(TABLE *table, uint idx, const MY_BITMAP *fields) } -/* - Compare key in row to a given key +/** + Compare key in row to a given key. - SYNOPSIS - key_cmp() - key_part Key part handler - key Key to compare to value in table->record[0] - key_length length of 'key' + @param key_part Key part handler + @param key Key to compare to value in table->record[0] + @param key_length length of 'key' - RETURN + @return The return value is SIGN(key_in_row - range_key): - - 0 Key is equal to range or 'range' == 0 (no range) - -1 Key is less than range - 1 Key is larger than range + - 0 Key is equal to range or 'range' == 0 (no range) + - -1 Key is less than range + - 1 Key is larger than range */ int key_cmp(KEY_PART_INFO *key_part, const uchar *key, uint key_length) diff --git a/sql/lex.h b/sql/lex.h index e311379120d..0b601de772a 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -84,6 +84,7 @@ static SYMBOL symbols[] = { { "BINLOG", SYM(BINLOG_SYM)}, { "BIT", SYM(BIT_SYM)}, { "BLOB", SYM(BLOB_SYM)}, + { "BLOCK", SYM(BLOCK_SYM)}, { "BOOL", SYM(BOOL_SYM)}, { "BOOLEAN", SYM(BOOLEAN_SYM)}, { "BOTH", SYM(BOTH)}, @@ -124,9 +125,11 @@ static SYMBOL symbols[] = { { "CONSISTENT", SYM(CONSISTENT_SYM)}, { "CONSTRAINT", SYM(CONSTRAINT)}, { "CONTAINS", SYM(CONTAINS_SYM)}, + { "CONTEXT", SYM(CONTEXT_SYM)}, { "CONTINUE", SYM(CONTINUE_SYM)}, { "CONTRIBUTORS", SYM(CONTRIBUTORS_SYM)}, { "CONVERT", SYM(CONVERT_SYM)}, + { "CPU", SYM(CPU_SYM)}, { "CREATE", SYM(CREATE)}, { "CROSS", SYM(CROSS)}, { "CUBE", SYM(CUBE_SYM)}, @@ -198,6 +201,7 @@ static SYMBOL symbols[] = { { "EXTENT_SIZE", SYM(EXTENT_SIZE_SYM)}, { "FALSE", SYM(FALSE_SYM)}, { "FAST", SYM(FAST_SYM)}, + { "FAULTS", SYM(FAULTS_SYM)}, { "FETCH", SYM(FETCH_SYM)}, { "FIELDS", SYM(COLUMNS)}, { "FILE", SYM(FILE_SYM)}, @@ -260,7 +264,9 @@ static SYMBOL symbols[] = { { "INTEGER", SYM(INT_SYM)}, { "INTERVAL", SYM(INTERVAL_SYM)}, { "INTO", SYM(INTO)}, + { "IO", SYM(IO_SYM)}, { "IO_THREAD", SYM(RELAY_THREAD)}, + { "IPC", SYM(IPC_SYM)}, { "IS", SYM(IS)}, { "ISOLATION", SYM(ISOLATION)}, { "ISSUER", SYM(ISSUER_SYM)}, @@ -381,6 +387,7 @@ static SYMBOL symbols[] = { { "PACK_KEYS", SYM(PACK_KEYS_SYM)}, { "PARSER", SYM(PARSER_SYM)}, { "PARTIAL", SYM(PARTIAL)}, + { "PAGE", SYM(PAGE_SYM)}, { "PARTITION", SYM(PARTITION_SYM)}, { "PARTITIONING", SYM(PARTITIONING_SYM)}, { "PARTITIONS", SYM(PARTITIONS_SYM)}, @@ -400,6 +407,8 @@ static SYMBOL symbols[] = { { "PROCEDURE", SYM(PROCEDURE)}, { "PROCESS" , SYM(PROCESS)}, { "PROCESSLIST", SYM(PROCESSLIST_SYM)}, + { "PROFILE", SYM(PROFILE_SYM)}, + { "PROFILES", SYM(PROFILES_SYM)}, { "PURGE", SYM(PURGE)}, { "QUARTER", SYM(QUARTER_SYM)}, { "QUERY", SYM(QUERY_SYM)}, @@ -474,6 +483,7 @@ static SYMBOL symbols[] = { { "SOME", SYM(ANY_SYM)}, { "SONAME", SYM(SONAME_SYM)}, { "SOUNDS", SYM(SOUNDS_SYM)}, + { "SOURCE", SYM(SOURCE_SYM)}, { "SPATIAL", SYM(SPATIAL_SYM)}, { "SPECIFIC", SYM(SPECIFIC_SYM)}, { "SQL", SYM(SQL_SYM)}, @@ -510,6 +520,8 @@ static SYMBOL symbols[] = { { "SUBPARTITIONS", SYM(SUBPARTITIONS_SYM)}, { "SUPER", SYM(SUPER_SYM)}, { "SUSPEND", SYM(SUSPEND_SYM)}, + { "SWAPS", SYM(SWAPS_SYM)}, + { "SWITCHES", SYM(SWITCHES_SYM)}, { "TABLE", SYM(TABLE_SYM)}, { "TABLES", SYM(TABLES)}, { "TABLESPACE", SYM(TABLESPACE)}, diff --git a/sql/lock.cc b/sql/lock.cc index ef4a0cc3d83..a0d6faa6604 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -14,8 +14,11 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* locking functions for mysql */ -/* +/** + @file + + Locking functions for mysql. + Because of the new concurrent inserts, we must first get external locks before getting internal locks. If we do it in the other order, the status information is not up to date when called from the lock handler. @@ -65,7 +68,7 @@ excluding one that caused failure. That means handler must cleanup itself in case external_lock() fails. -TODO: + @todo Change to use my_malloc() ONLY when using LOCK TABLES command or when we are forced to use mysql_lock_merge. */ @@ -252,7 +255,7 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count, break; } - thd->proc_info="System lock"; + thd_proc_info(thd, "System lock"); DBUG_PRINT("info", ("thd->proc_info %s", thd->proc_info)); if (sql_lock->table_count && lock_external(thd, sql_lock->table, sql_lock->table_count)) @@ -263,7 +266,7 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count, sql_lock=0; break; } - thd->proc_info="Table lock"; + thd_proc_info(thd, "Table lock"); DBUG_PRINT("info", ("thd->proc_info %s", thd->proc_info)); thd->locked=1; /* Copy the lock data array. thr_multi_lock() reorders its contens. */ @@ -311,7 +314,7 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count, thd->locked=0; break; } - thd->proc_info=0; + thd_proc_info(thd, 0); /* some table was altered or deleted. reopen tables marked deleted */ mysql_unlock_tables(thd,sql_lock); @@ -326,7 +329,7 @@ retry: if (wait_for_tables(thd)) break; // Couldn't open tables } - thd->proc_info=0; + thd_proc_info(thd, 0); if (thd->killed) { thd->send_kill_message(); @@ -390,10 +393,11 @@ void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock) DBUG_VOID_RETURN; } -/* - Unlock some of the tables locked by mysql_lock_tables +/** + Unlock some of the tables locked by mysql_lock_tables. + This will work even if get_lock_data fails (next unlock will free all) - */ +*/ void mysql_unlock_some_tables(THD *thd, TABLE **table,uint count) { @@ -405,8 +409,8 @@ void mysql_unlock_some_tables(THD *thd, TABLE **table,uint count) } -/* -** unlock all tables locked for read. +/** + unlock all tables locked for read. */ void mysql_unlock_read_tables(THD *thd, MYSQL_LOCK *sql_lock) @@ -567,7 +571,7 @@ void mysql_lock_downgrade_write(THD *thd, TABLE *table, } -/* abort all other threads waiting to get lock in table */ +/** Abort all other threads waiting to get lock in table. */ void mysql_lock_abort(THD *thd, TABLE *table, bool upgrade_lock) { @@ -586,16 +590,15 @@ void mysql_lock_abort(THD *thd, TABLE *table, bool upgrade_lock) } -/* - Abort one thread / table combination +/** + Abort one thread / table combination. - SYNOPSIS - mysql_lock_abort_for_thread() - thd Thread handler - table Table that should be removed from lock queue + @param thd Thread handler + @param table Table that should be removed from lock queue - RETURN + @retval 0 Table was not locked by another thread + @retval 1 Table was locked by at least one other thread */ @@ -663,28 +666,27 @@ MYSQL_LOCK *mysql_lock_merge(MYSQL_LOCK *a,MYSQL_LOCK *b) } -/* +/** Find duplicate lock in tables. - SYNOPSIS - mysql_lock_have_duplicate() - thd The current thread. - needle The table to check for duplicate lock. - haystack The list of tables to search for the dup lock. + Temporary tables are ignored here like they are ignored in + get_lock_data(). If we allow two opens on temporary tables later, + both functions should be checked. + + @param thd The current thread. + @param needle The table to check for duplicate lock. + @param haystack The list of tables to search for the dup lock. - NOTE + @note This is mainly meant for MERGE tables in INSERT ... SELECT situations. The 'real', underlying tables can be found only after the MERGE tables are opened. This function assumes that the tables are already locked. - Temporary tables are ignored here like they are ignored in - get_lock_data(). If we allow two opens on temporary tables later, - both functions should be checked. - - RETURN - NULL No duplicate lock found. - ! NULL First table from 'haystack' that matches a lock on 'needle'. + @retval + NULL No duplicate lock found. + @retval + !NULL First table from 'haystack' that matches a lock on 'needle'. */ TABLE_LIST *mysql_lock_have_duplicate(THD *thd, TABLE_LIST *needle, @@ -768,7 +770,7 @@ TABLE_LIST *mysql_lock_have_duplicate(THD *thd, TABLE_LIST *needle, } - /* unlock a set of external */ +/** Unlock a set of external. */ static int unlock_external(THD *thd, TABLE **table,uint count) { @@ -793,21 +795,17 @@ static int unlock_external(THD *thd, TABLE **table,uint count) } -/* - Get lock structures from table structs and initialize locks - - SYNOPSIS - get_lock_data() - thd Thread handler - table_ptr Pointer to tables that should be locks - flags One of: - GET_LOCK_UNLOCK: If we should send TL_IGNORE to - store lock - GET_LOCK_STORE_LOCKS: Store lock info in TABLE - write_lock_used Store pointer to last table with WRITE_ALLOW_WRITE +/** + Get lock structures from table structs and initialize locks. + + @param thd Thread handler + @param table_ptr Pointer to tables that should be locks + @param flags One of: + - GET_LOCK_UNLOCK : If we should send TL_IGNORE to store lock + - GET_LOCK_STORE_LOCKS : Store lock info in TABLE + @param write_lock_used Store pointer to last table with WRITE_ALLOW_WRITE */ - static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count, uint flags, TABLE **write_lock_used) { @@ -907,31 +905,25 @@ static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count, } -/* +/** Reset lock type in lock data. - SYNOPSIS - reset_lock_data() - sql_lock The MySQL lock. - - DESCRIPTION + After a locking error we want to quit the locking of the table(s). + The test case in the bug report for Bug #18544 has the following + cases: + -# Locking error in lock_external() due to InnoDB timeout. + -# Locking error in get_lock_data() due to missing write permission. + -# Locking error in wait_if_global_read_lock() due to lock conflict. - After a locking error we want to quit the locking of the table(s). - The test case in the bug report for Bug #18544 has the following - cases: 1. Locking error in lock_external() due to InnoDB timeout. - 2. Locking error in get_lock_data() due to missing write permission. - 3. Locking error in wait_if_global_read_lock() due to lock conflict. + In all these cases we have already set the lock type into the lock + data of the open table(s). If the table(s) are in the open table + cache, they could be reused with the non-zero lock type set. This + could lead to ignoring a different lock type with the next lock. - In all these cases we have already set the lock type into the lock - data of the open table(s). If the table(s) are in the open table - cache, they could be reused with the non-zero lock type set. This - could lead to ignoring a different lock type with the next lock. + Clear the lock type of all lock data. This ensures that the next + lock request will set its lock type properly. - Clear the lock type of all lock data. This ensures that the next - lock request will set its lock type properly. - - RETURN - void + @param sql_lock The MySQL lock. */ static void reset_lock_data(MYSQL_LOCK *sql_lock) @@ -954,20 +946,19 @@ static void reset_lock_data(MYSQL_LOCK *sql_lock) This is used when we need total access to a closed, not open table *****************************************************************************/ -/* +/** Lock and wait for the named lock. - SYNOPSIS - lock_and_wait_for_table_name() - thd Thread handler - table_list Lock first table in this list + @param thd Thread handler + @param table_list Lock first table in this list - NOTES + @note Works together with global read lock. - RETURN + @retval 0 ok + @retval 1 error */ @@ -996,30 +987,30 @@ end: } -/* +/** Put a not open table with an old refresh version in the table cache. - SYNPOSIS - lock_table_name() - thd Thread handler - table_list Lock first table in this list - check_in_use Do we need to check if table already in use by us + @param thd Thread handler + @param table_list Lock first table in this list + @param check_in_use Do we need to check if table already in use by us - WARNING + @note + One must have a lock on LOCK_open! + + @warning If you are going to update the table, you should use lock_and_wait_for_table_name instead of this function as this works together with 'FLUSH TABLES WITH READ LOCK' - NOTES + @note This will force any other threads that uses the table to release it as soon as possible. - REQUIREMENTS - One must have a lock on LOCK_open ! - - RETURN: + @return < 0 error + @return == 0 table locked + @return > 0 table locked, but someone is using it */ @@ -1116,23 +1107,22 @@ bool wait_for_locked_table_names(THD *thd, TABLE_LIST *table_list) } -/* - Lock all tables in list with a name lock +/** + Lock all tables in list with a name lock. - SYNOPSIS - lock_table_names() - thd Thread handle - table_list Names of tables to lock + REQUIREMENTS + - One must have a lock on LOCK_open when calling this - NOTES + @param thd Thread handle + @param table_list Names of tables to lock + + @note If you are just locking one table, you should use lock_and_wait_for_table_name(). - REQUIREMENTS - One must have a lock on LOCK_open when calling this - - RETURN + @retval 0 ok + @retval 1 Fatal error (end of memory ?) */ @@ -1162,12 +1152,13 @@ end: /** - @brief Lock all tables in list with an exclusive table name lock. + Unlock all tables in list with a name lock. - @param thd Thread handle. + @param thd Thread handle. @param table_list Names of tables to lock. - @note This function needs to be protected by LOCK_open. If we're + @note + This function needs to be protected by LOCK_open. If we're under LOCK TABLES, this function does not work as advertised. Namely, it does not exclude other threads from using this table and does not put an exclusive name lock on this table into the table cache. @@ -1197,7 +1188,7 @@ bool lock_table_names_exclusively(THD *thd, TABLE_LIST *table_list) /** - @brief Test is 'table' is protected by an exclusive name lock. + Test is 'table' is protected by an exclusive name lock. @param[in] thd The current thread handler @param[in] table_list Table container containing the single table to be @@ -1225,7 +1216,7 @@ is_table_name_exclusively_locked_by_this_thread(THD *thd, /** - @brief Test is 'table key' is protected by an exclusive name lock. + Test is 'table key' is protected by an exclusive name lock. @param[in] thd The current thread handler. @param[in] key @@ -1259,23 +1250,27 @@ is_table_name_exclusively_locked_by_this_thread(THD *thd, uchar *key, return FALSE; } -/* - Unlock all tables in list with a name lock +/** + Unlock all tables in list with a name lock. - SYNOPSIS - unlock_table_names() + @param thd Thread handle + @param table_list Names of tables to unlock + @param last_table Don't unlock any tables after this one. - (default 0, which will unlock all tables) + (default 0, which will unlock all tables) - NOTES + @note One must have a lock on LOCK_open when calling this. + + @note This function will broadcast refresh signals to inform other threads that the name locks are removed. - RETURN + @retval 0 ok + @retval 1 Fatal error (end of memory ?) */ @@ -1579,14 +1574,9 @@ bool make_global_read_lock_block_commit(THD *thd) } -/* +/** Broadcast COND_refresh and COND_global_read_lock. - SYNOPSIS - broadcast_refresh() - void No parameters. - - DESCRIPTION Due to a bug in a threading library it could happen that a signal did not reach its target. A condition for this was that the same condition variable was used with different mutexes in @@ -1598,12 +1588,9 @@ bool make_global_read_lock_block_commit(THD *thd) in global read lock handling. But now it is necessary to signal both conditions at the same time. - NOTE + @note When signalling COND_global_read_lock within the global read lock handling, it is not necessary to also signal COND_refresh. - - RETURN - void */ void broadcast_refresh(void) diff --git a/sql/log.cc b/sql/log.cc index 99ac9cf509d..3a09acd8fca 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -14,8 +14,15 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* logging of commands */ -/* TODO: Abort logging when we get an error in reading or writing log files */ +/** + @file + + @brief + logging of commands + + @todo + Abort logging when we get an error in reading or writing log files +*/ #include "mysql_priv.h" #include "sql_repl.h" @@ -700,7 +707,7 @@ void Log_to_file_event_handler::init_pthread_objects() } -/* Wrapper around MYSQL_LOG::write() for slow log */ +/** Wrapper around MYSQL_LOG::write() for slow log. */ bool Log_to_file_event_handler:: log_slow(THD *thd, time_t current_time, time_t query_start_arg, @@ -715,7 +722,7 @@ bool Log_to_file_event_handler:: } -/* +/** Wrapper around MYSQL_LOG::write() for general log. We need it since we want all log event handlers to have the same signature. */ @@ -817,7 +824,7 @@ void LOGGER::cleanup_end() } -/* +/** Perform basic log initialization: create file-based log handler and init error log. */ @@ -1469,9 +1476,12 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all) DBUG_RETURN(error); } -/* - NOTE: how do we handle this (unlikely but legal) case: - [transaction] + [update to non-trans table] + [rollback to savepoint] ? +/** + @note + How do we handle this (unlikely but legal) case: + @verbatim + [transaction] + [update to non-trans table] + [rollback to savepoint] ? + @endverbatim The problem occurs when a savepoint is before the update to the non-transactional table. Then when there's a rollback to the savepoint, if we simply truncate the binlog cache, we lose the part of the binlog cache where @@ -1618,11 +1628,14 @@ static void setup_windows_event_source() #endif /* __NT__ */ -/**************************************************************************** -** Find a uniq filename for 'filename.#'. -** Set # to a number as low as possible -** returns != 0 if not possible to get uniq filename -****************************************************************************/ +/** + Find a unique filename for 'filename.#'. + + Set '#' to a number as low as possible. + + @return + nonzero if not possible to get unique filename +*/ static int find_uniq_filename(char *name) { @@ -1836,7 +1849,7 @@ void MYSQL_LOG::close(uint exiting) DBUG_VOID_RETURN; } -/* this is called only once */ +/** This is called only once. */ void MYSQL_LOG::cleanup() { @@ -2163,6 +2176,11 @@ bool MYSQL_QUERY_LOG::write(THD *thd, time_t current_time, } +/** + @todo + The following should be using fn_format(); We just need to + first change fn_format() to cut the file name if it's too long. +*/ const char *MYSQL_LOG::generate_name(const char *log_name, const char *suffix, bool strip_ext, char *buff) @@ -2277,17 +2295,17 @@ bool MYSQL_BIN_LOG::open_index_file(const char *index_file_name_arg, } -/* +/** Open a (new) binlog file. - DESCRIPTION - Open the log file and the index file. Register the new - file name in it + file name in it - When calling this when the file is in use, you must have a locks - on LOCK_log and LOCK_index. + on LOCK_log and LOCK_index. - RETURN VALUES + @retval 0 ok + @retval 1 error */ @@ -2439,24 +2457,20 @@ int MYSQL_BIN_LOG::raw_get_current_log(LOG_INFO* linfo) return 0; } -/* - Move all data up in a file in an filename index file - - SYNOPSIS - copy_up_file_and_fill() - index_file File to move - offset Move everything from here to beginning - - NOTE - File will be truncated to be 'offset' shorter or filled up with - newlines +/** + Move all data up in a file in an filename index file. - IMPLEMENTATION We do the copy outside of the IO_CACHE as the cache buffers would just make things slower and more complicated. In most cases the copy loop should only do one read. - RETURN VALUES + @param index_file File to move + @param offset Move everything from here to beginning + + @note + File will be truncated to be 'offset' shorter or filled up with newlines + + @retval 0 ok */ @@ -2497,25 +2511,25 @@ err: #endif /* HAVE_REPLICATION */ -/* - Find the position in the log-index-file for the given log name +/** + Find the position in the log-index-file for the given log name. - SYNOPSIS - find_log_pos() - linfo Store here the found log file name and position to - the NEXT log file name in the index file. - log_name Filename to find in the index file. - Is a null pointer if we want to read the first entry - need_lock Set this to 1 if the parent doesn't already have a - lock on LOCK_index + @param linfo Store here the found log file name and position to + the NEXT log file name in the index file. + @param log_name Filename to find in the index file. + Is a null pointer if we want to read the first entry + @param need_lock Set this to 1 if the parent doesn't already have a + lock on LOCK_index - NOTE + @note On systems without the truncate function the file will end with one or more empty lines. These will be ignored when reading the file. - RETURN VALUES + @retval 0 ok - LOG_INFO_EOF End of log-index-file found + @retval + LOG_INFO_EOF End of log-index-file found + @retval LOG_INFO_IO Got IO error while reading file */ @@ -2571,25 +2585,27 @@ int MYSQL_BIN_LOG::find_log_pos(LOG_INFO *linfo, const char *log_name, } -/* - Find the position in the log-index-file for the given log name +/** + Find the position in the log-index-file for the given log name. - SYNOPSIS - find_next_log() + @param linfo Store here the next log file name and position to the file name after that. + @param need_lock Set this to 1 if the parent doesn't already have a lock on LOCK_index - NOTE + @note - Before calling this function, one has to call find_log_pos() - to set up 'linfo' + to set up 'linfo' - Mutex needed because we need to make sure the file pointer does not move - from under our feet + from under our feet - RETURN VALUES + @retval 0 ok - LOG_INFO_EOF End of log-index-file found + @retval + LOG_INFO_EOF End of log-index-file found + @retval LOG_INFO_IO Got IO error while reading file */ @@ -2623,21 +2639,20 @@ err: } -/* - Delete all logs refered to in the index file - Start writing to a new log file. The new index file will only contain - this file. +/** + Delete all logs refered to in the index file. + Start writing to a new log file. - SYNOPSIS - reset_logs() - thd Thread + The new index file will only contain this file. - NOTE - If not called from slave thread, write start event to new log + @param thd Thread + @note + If not called from slave thread, write start event to new log - RETURN VALUES + @retval 0 ok + @retval 1 error */ @@ -2701,38 +2716,40 @@ err: } -/* +/** Delete relay log files prior to rli->group_relay_log_name (i.e. all logs which are not involved in a non-finished group - (transaction)), remove them from the index file and start on next relay log. + (transaction)), remove them from the index file and start on next + relay log. - SYNOPSIS - purge_first_log() - rli Relay log information - included If false, all relay logs that are strictly before - rli->group_relay_log_name are deleted ; if true, the latter is - deleted too (i.e. all relay logs - read by the SQL slave thread are deleted). - - NOTE + IMPLEMENTATION + - Protects index file with LOCK_index + - Delete relevant relay log files + - Copy all file names after these ones to the front of the index file + - If the OS has truncate, truncate the file, else fill it with \n' + - Read the next file name from the index file and store in rli->linfo + + @param rli Relay log information + @param included If false, all relay logs that are strictly before + rli->group_relay_log_name are deleted ; if true, the + latter is deleted too (i.e. all relay logs + read by the SQL slave thread are deleted). + + @note - This is only called from the slave-execute thread when it has read - all commands from a relay log and want to switch to a new relay log. + all commands from a relay log and want to switch to a new relay log. - When this happens, we can be in an active transaction as - a transaction can span over two relay logs - (although it is always written as a single block to the master's binary - log, hence cannot span over two master's binary logs). - - IMPLEMENTATION - - Protects index file with LOCK_index - - Delete relevant relay log files - - Copy all file names after these ones to the front of the index file - - If the OS has truncate, truncate the file, else fill it with \n' - - Read the next file name from the index file and store in rli->linfo + a transaction can span over two relay logs + (although it is always written as a single block to the master's binary + log, hence cannot span over two master's binary logs). - RETURN VALUES + @retval 0 ok - LOG_INFO_EOF End of log-index-file found + @retval + LOG_INFO_EOF End of log-index-file found + @retval LOG_INFO_SEEK Could not allocate IO cache + @retval LOG_INFO_IO Got IO error while reading file */ @@ -2810,8 +2827,8 @@ err: DBUG_RETURN(error); } -/* - Update log index_file +/** + Update log index_file. */ int MYSQL_BIN_LOG::update_log_index(LOG_INFO* log_info, bool need_update_threads) @@ -2825,25 +2842,24 @@ int MYSQL_BIN_LOG::update_log_index(LOG_INFO* log_info, bool need_update_threads return 0; } -/* +/** Remove all logs before the given log from disk and from the index file. - SYNOPSIS - purge_logs() - to_log Delete all log file name before this file. - included If true, to_log is deleted too. - need_mutex - need_update_threads If we want to update the log coordinates of - all threads. False for relay logs, true otherwise. - freed_log_space If not null, decrement this variable of - the amount of log space freed + @param to_log Delete all log file name before this file. + @param included If true, to_log is deleted too. + @param need_mutex + @param need_update_threads If we want to update the log coordinates of + all threads. False for relay logs, true otherwise. + @param freed_log_space If not null, decrement this variable of + the amount of log space freed - NOTES + @note If any of the logs before the deleted one is in use, only purge logs up to this one. - RETURN VALUES - 0 ok + @retval + 0 ok + @retval LOG_INFO_EOF to_log not found */ @@ -2927,21 +2943,20 @@ err: DBUG_RETURN(error); } -/* +/** Remove all logs before the given file date from disk and from the index file. - SYNOPSIS - purge_logs_before_date() - thd Thread pointer - before_date Delete all log files before given date. + @param thd Thread pointer + @param before_date Delete all log files before given date. - NOTES + @note If any of the logs before the deleted one is in use, only purge logs up to this one. - RETURN VALUES + @retval 0 ok + @retval LOG_INFO_PURGE_NO_ROTATE Binary file that can't be rotated */ @@ -2991,14 +3006,12 @@ err: #endif /* HAVE_REPLICATION */ -/* - Create a new log file name +/** + Create a new log file name. - SYNOPSIS - make_log_name() - buf buf of at least FN_REFLEN where new name is stored + @param buf buf of at least FN_REFLEN where new name is stored - NOTE + @note If file name will be longer then FN_REFLEN it will be truncated */ @@ -3012,8 +3025,8 @@ void MYSQL_BIN_LOG::make_log_name(char* buf, const char* log_ident) } -/* - Check if we are writing/reading to the given log file +/** + Check if we are writing/reading to the given log file. */ bool MYSQL_BIN_LOG::is_active(const char *log_file_name_arg) @@ -3042,14 +3055,12 @@ void MYSQL_BIN_LOG::new_file_without_locking() } -/* - Start writing to a new log file or reopen the old file +/** + Start writing to a new log file or reopen the old file. - SYNOPSIS - new_file_impl() - need_lock Set to 1 if caller has not locked LOCK_log + @param need_lock Set to 1 if caller has not locked LOCK_log - NOTE + @note The new file name is stored last in the index file */ @@ -3520,8 +3531,8 @@ MYSQL_BIN_LOG::flush_and_set_pending_rows_event(THD *thd, DBUG_RETURN(error); } -/* - Write an event to the binary log +/** + Write an event to the binary log. */ bool MYSQL_BIN_LOG::write(Log_event *event_info) @@ -3960,27 +3971,25 @@ int MYSQL_BIN_LOG::write_cache(IO_CACHE *cache, bool lock_log, bool sync_log) return 0; // All OK } -/* - Write a cached log entry to the binary log - - SYNOPSIS - write() - thd - cache The cache to copy to the binlog - commit_event The commit event to print after writing the +/** + Write a cached log entry to the binary log. + - To support transaction over replication, we wrap the transaction + with BEGIN/COMMIT or BEGIN/ROLLBACK in the binary log. + We want to write a BEGIN/ROLLBACK block when a non-transactional table + was updated in a transaction which was rolled back. This is to ensure + that the same updates are run on the slave. + + @param thd + @param cache The cache to copy to the binlog + @param commit_event The commit event to print after writing the contents of the cache. - NOTE - - We only come here if there is something in the cache. - - The thing in the cache is always a complete transaction - - 'cache' needs to be reinitialized after this functions returns. - - IMPLEMENTATION - - To support transaction over replication, we wrap the transaction - with BEGIN/COMMIT or BEGIN/ROLLBACK in the binary log. - We want to write a BEGIN/ROLLBACK block when a non-transactional table - was updated in a transaction which was rolled back. This is to ensure - that the same updates are run on the slave. + @note + We only come here if there is something in the cache. + @note + The thing in the cache is always a complete transaction. + @note + 'cache' needs to be reinitialized after this functions returns. */ bool MYSQL_BIN_LOG::write(THD *thd, IO_CACHE *cache, Log_event *commit_event) @@ -4077,17 +4086,15 @@ err: } -/* - Wait until we get a signal that the binary log has been updated +/** + Wait until we get a signal that the binary log has been updated. - SYNOPSIS - wait_for_update() - thd Thread variable - is_slave If 0, the caller is the Binlog_dump thread from master; - if 1, the caller is the SQL thread from the slave. This - influences only thd->proc_info. + @param thd Thread variable + @param is_slave If 0, the caller is the Binlog_dump thread from master; + if 1, the caller is the SQL thread from the slave. This + influences only thd->proc_info. - NOTES + @note One must have a lock on LOCK_log before calling this function. This lock will be released before return! That's required by THD::enter_cond() (see NOTES in sql_class.h). @@ -4110,18 +4117,16 @@ void MYSQL_BIN_LOG::wait_for_update(THD* thd, bool is_slave) } -/* - Close the log file +/** + Close the log file. - SYNOPSIS - close() - exiting Bitmask for one or more of the following bits: - LOG_CLOSE_INDEX if we should close the index file - LOG_CLOSE_TO_BE_OPENED if we intend to call open - at once after close. - LOG_CLOSE_STOP_EVENT write a 'stop' event to the log + @param exiting Bitmask for one or more of the following bits: + - LOG_CLOSE_INDEX : if we should close the index file + - LOG_CLOSE_TO_BE_OPENED : if we intend to call open + at once after close. + - LOG_CLOSE_STOP_EVENT : write a 'stop' event to the log - NOTES + @note One can do an open on the object at once after doing a close. The internal structures are not freed until cleanup() is called */ @@ -4201,21 +4206,20 @@ void MYSQL_BIN_LOG::set_max_size(ulong max_size_arg) } -/* - Check if a string is a valid number +/** + Check if a string is a valid number. - SYNOPSIS - test_if_number() - str String to test - res Store value here - allow_wildcards Set to 1 if we should ignore '%' and '_' + @param str String to test + @param res Store value here + @param allow_wildcards Set to 1 if we should ignore '%' and '_' - NOTE + @note For the moment the allow_wildcards argument is not used Should be move to some other file. - RETURN VALUES + @retval 1 String is a number + @retval 0 Error */ @@ -4356,23 +4360,18 @@ static void print_buffer_to_nt_eventlog(enum loglevel level, char *buff, #endif /* __NT__ */ -/* +/** Prints a printf style message to the error log and, under NT, to the Windows event log. - SYNOPSIS - vprint_msg_to_log() - event_type Type of event to write (Error, Warning, or Info) - format Printf style format of message - args va_list list of arguments for the message - - NOTE + This function prints the message into a buffer and then sends that buffer + to other functions to write that message to other logging sources. - IMPLEMENTATION - This function prints the message into a buffer and then sends that buffer - to other functions to write that message to other logging sources. + @param event_type Type of event to write (Error, Warning, or Info) + @param format Printf style format of message + @param args va_list list of arguments for the message - RETURN VALUES + @returns The function always returns 0. The return value is present in the signature to be compatible with other logging routines, which could return an error (e.g. logging to the log tables) @@ -4626,16 +4625,18 @@ err: return 1; } -/* - there is no active page, let's got one from the pool +/** + there is no active page, let's got one from the pool. - two strategies here: - 1. take the first from the pool - 2. if there're waiters - take the one with the most free space + Two strategies here: + -# take the first from the pool + -# if there're waiters - take the one with the most free space. - TODO page merging. try to allocate adjacent page first, - so that they can be flushed both in one sync + @todo + TODO page merging. try to allocate adjacent page first, + so that they can be flushed both in one sync */ + void TC_LOG_MMAP::get_active_from_pool() { PAGE **p, **best_p=0; @@ -4678,6 +4679,10 @@ void TC_LOG_MMAP::get_active_from_pool() pthread_mutex_unlock(&LOCK_pool); } +/** + @todo + perhaps, increase log size ? +*/ int TC_LOG_MMAP::overflow() { /* @@ -4690,10 +4695,9 @@ int TC_LOG_MMAP::overflow() return 1; // always return 1 } -/* - Record that transaction XID is committed on the persistent storage +/** + Record that transaction XID is committed on the persistent storage. - NOTES This function is called in the middle of two-phase commit: First all resources prepare the transaction, then tc_log->log() is called, then all resources commit the transaction, then tc_log->unlog() is called. @@ -4704,18 +4708,18 @@ int TC_LOG_MMAP::overflow() threads waiting for a page, but then all these threads will be waiting for a fsync() anyway - IMPLEMENTATION If tc_log == MYSQL_LOG then tc_log writes transaction to binlog and records XID in a special Xid_log_event. If tc_log = TC_LOG_MMAP then xid is written in a special memory-mapped log. - RETURN - 0 Error - # "cookie", a number that will be passed as an argument - to unlog() call. tc_log can define it any way it wants, - and use for whatever purposes. TC_LOG_MMAP sets it - to the position in memory where xid was logged to. + @retval + 0 - error + @retval + \# - otherwise, "cookie", a number that will be passed as an argument + to unlog() call. tc_log can define it any way it wants, + and use for whatever purposes. TC_LOG_MMAP sets it + to the position in memory where xid was logged to. */ int TC_LOG_MMAP::log_xid(THD *thd, my_xid xid) @@ -4823,9 +4827,9 @@ int TC_LOG_MMAP::sync() return err; } -/* +/** erase xid from the page, update page free space counters/pointers. - cookie points directly to the memory where xid was logged + cookie points directly to the memory where xid was logged. */ void TC_LOG_MMAP::unlog(ulong cookie, my_xid xid) @@ -4936,16 +4940,17 @@ TC_LOG *tc_log; TC_LOG_DUMMY tc_log_dummy; TC_LOG_MMAP tc_log_mmap; -/* - Perform heuristic recovery, if --tc-heuristic-recover was used - - RETURN VALUE - 0 no heuristic recovery was requested - 1 heuristic recovery was performed +/** + Perform heuristic recovery, if --tc-heuristic-recover was used. - NOTE + @note no matter whether heuristic recovery was successful or not mysqld must exit. So, return value is the same in both cases. + + @retval + 0 no heuristic recovery was requested + @retval + 1 heuristic recovery was performed */ int TC_LOG::using_heuristic_recover() @@ -4963,8 +4968,9 @@ int TC_LOG::using_heuristic_recover() /****** transaction coordinator log for 2pc - binlog() based solution ******/ #define TC_LOG_BINLOG MYSQL_BIN_LOG -/* - TODO keep in-memory list of prepared transactions +/** + @todo + keep in-memory list of prepared transactions (add to list in log(), remove on unlog()) and copy it to the new binlog if rotated but let's check the behaviour of tc_log_page_waits first! @@ -5055,7 +5061,7 @@ err: return error; } -/* this is called on shutdown, after ha_panic */ +/** This is called on shutdown, after ha_panic. */ void TC_LOG_BINLOG::close() { DBUG_ASSERT(prepared_xids==0); @@ -5063,12 +5069,14 @@ void TC_LOG_BINLOG::close() pthread_cond_destroy (&COND_prep_xids); } -/* - TODO group commit +/** + @todo + group commit - RETURN - 0 - error - 1 - success + @retval + 0 error + @retval + 1 success */ int TC_LOG_BINLOG::log_xid(THD *thd, my_xid xid) { diff --git a/sql/log_event.cc b/sql/log_event.cc index 00e3dc89f6b..cf03dd5bf44 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -215,8 +215,8 @@ static void clear_all_errors(THD *thd, Relay_log_info *rli) } -/* - Ignore error code specified on command line +/** + Ignore error code specified on command line. */ inline int ignored_error_code(int err_code) @@ -273,21 +273,20 @@ static char *pretty_print_str(char *packet, char *str, int len) #endif /* !MYSQL_CLIENT */ -/* - Creates a temporary name for load data infile: +#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) - SYNOPSIS - slave_load_file_stem() - buf Store new filename here - file_id File_id (part of file name) - event_server_id Event_id (part of file name) - ext Extension for file name +/** + Creates a temporary name for load data infile:. - RETURN + @param buf Store new filename here + @param file_id File_id (part of file name) + @param event_server_id Event_id (part of file name) + @param ext Extension for file name + + @return Pointer to start of extension */ -#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) static char *slave_load_file_stem(char *buf, uint file_id, int event_server_id, const char *ext) { @@ -307,14 +306,12 @@ static char *slave_load_file_stem(char *buf, uint file_id, #endif -/* - Delete all temporary files used for SQL_LOAD. +#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) - SYNOPSIS - cleanup_load_tmpdir() +/** + Delete all temporary files used for SQL_LOAD. */ -#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) static void cleanup_load_tmpdir() { MY_DIR *dirp; @@ -382,7 +379,7 @@ static inline int read_str(const char **buf, const char *buf_end, } -/* +/** Transforms a string into "" or its expression in 0x... form. */ @@ -399,12 +396,14 @@ char *str_to_hex(char *to, const char *from, uint len) return to; // pointer to end 0 of 'to' } -/* +#ifndef MYSQL_CLIENT + +/** Append a version of the 'from' string suitable for use in a query to the 'to' string. To generate a correct escaping, the character set information in 'csinfo' is used. - */ -#ifndef MYSQL_CLIENT +*/ + int append_query_string(CHARSET_INFO *csinfo, String const *from, String *to) @@ -431,7 +430,7 @@ append_query_string(CHARSET_INFO *csinfo, #endif -/* +/** Prints a "session_var=value" string. Used by mysqlbinlog to print some SET commands just before it prints a query. */ @@ -456,8 +455,9 @@ static void print_set_option(IO_CACHE* file, uint32 bits_changed, Log_event methods (= the parent class of all events) **************************************************************************/ -/* - Log_event::get_type_str() +/** + @return + returns the human readable name of the event's type */ const char* Log_event::get_type_str() @@ -505,7 +505,7 @@ Log_event::Log_event(THD* thd_arg, uint16 flags_arg, bool using_trans) } -/* +/** This minimal constructor is for when you are not even sure that there is a valid THD. For example in the server when we are shutting down or flushing logs after receiving a SIGHUP (then we must write a Rotate to @@ -675,12 +675,9 @@ void Log_event::pack_info(Protocol *protocol) } -/* - Log_event::net_send() - +/** Only called by SHOW BINLOG EVENTS */ - int Log_event::net_send(Protocol *protocol, const char* log_name, my_off_t pos) { const char *p= strrchr(log_name, FN_LIBCHAR); @@ -701,8 +698,10 @@ int Log_event::net_send(Protocol *protocol, const char* log_name, my_off_t pos) #endif /* HAVE_REPLICATION */ -/* - Log_event::init_show_field_list() +/** + init_show_field_list() prepares the column names and types for the + output of SHOW BINLOG EVENTS; it is used only by SHOW BINLOG + EVENTS. */ void Log_event::init_show_field_list(List<Item>* field_list) @@ -798,12 +797,9 @@ bool Log_event::write_header(IO_CACHE* file, ulong event_data_length) } -/* - Log_event::read_log_event() - +/** This needn't be format-tolerant, because we only read LOG_EVENT_MINIMAL_HEADER_LEN (we just want to read the event's length). - */ int Log_event::read_log_event(IO_CACHE* file, String* packet, @@ -886,14 +882,11 @@ end: #define LOCK_MUTEX #endif -/* - Log_event::read_log_event() - - NOTE: +#ifndef MYSQL_CLIENT +/** + @note Allocates memory; The caller is responsible for clean-up. */ - -#ifndef MYSQL_CLIENT Log_event* Log_event::read_log_event(IO_CACHE* file, pthread_mutex_t* log_lock, const Format_description_log_event @@ -991,8 +984,7 @@ err: } -/* - Log_event::read_log_event() +/** Binlog format tolerance is in (buf, event_len, description_event) constructors. */ @@ -1329,12 +1321,13 @@ Log_event::continue_group(Relay_log_info *rli) #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) -/* - Query_log_event::pack_info() +/** This (which is used only for SHOW BINLOG EVENTS) could be updated to print SET @@session_var=. But this is not urgent, as SHOW BINLOG EVENTS is only an information, it does not produce suitable queries to replay (for example it does not print LOAD DATA INFILE). + @todo + show the catalog ?? */ void Query_log_event::pack_info(Protocol *protocol) @@ -1363,7 +1356,9 @@ void Query_log_event::pack_info(Protocol *protocol) #ifndef MYSQL_CLIENT -/* Utility function for the next method */ +/** + Utility function for the next method (Query_log_event::write()) . +*/ static void write_str_with_code_and_len(char **dst, const char *src, int len, uint code) { @@ -1375,10 +1370,10 @@ static void write_str_with_code_and_len(char **dst, const char *src, } -/* - Query_log_event::write() +/** + Query_log_event::write(). - NOTES: + @note In this event we have to modify the header to have the correct EVENT_LEN_OFFSET as we don't yet know how many status variables we will print! @@ -1555,9 +1550,7 @@ bool Query_log_event::write(IO_CACHE* file) my_b_safe_write(file, (uchar*) query, q_len)) ? 1 : 0; } -/* - Query_log_event::Query_log_event() - +/** The simplest constructor that could possibly work. This is used for creating static objects that have a special meaning and are invisible to the log. @@ -1756,11 +1749,10 @@ code_name(int code) } \ } while (0) -/* - Query_log_event::Query_log_event() + +/** This is used by the SQL slave thread to prepare the event before execution. */ - Query_log_event::Query_log_event(const char* buf, uint event_len, const Format_description_log_event *description_event, @@ -1969,11 +1961,13 @@ Query_log_event::Query_log_event(const char* buf, uint event_len, } -/* - Query_log_event::print() -*/ - #ifdef MYSQL_CLIENT +/** + Query_log_event::print(). + + @todo + print the catalog ?? +*/ void Query_log_event::print_query_header(IO_CACHE* file, PRINT_EVENT_INFO* print_event_info) { @@ -2158,6 +2152,23 @@ int Query_log_event::do_apply_event(Relay_log_info const *rli) } +/** + @todo + Compare the values of "affected rows" around here. Something + like: + @code + if ((uint32) affected_in_event != (uint32) affected_on_slave) + { + sql_print_error("Slave: did not get the expected number of affected \ + rows running query from master - expected %d, got %d (this numbers \ + should have matched modulo 4294967296).", 0, ...); + thd->query_error = 1; + } + @endcode + We may also want an option to tell the slave to ignore "affected" + mismatch. This mismatch could be implemented with a new ER_ code, and + to ignore it you would use --slave-skip-errors... +*/ int Query_log_event::do_apply_event(Relay_log_info const *rli, const char *query_arg, uint32 q_len_arg) { @@ -2614,30 +2625,31 @@ bool Start_log_event_v3::write(IO_CACHE* file) #endif -/* - Start_log_event_v3::do_apply_event() +#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) +/** + Start_log_event_v3::do_apply_event() . The master started - IMPLEMENTATION + IMPLEMENTATION - To handle the case where the master died without having time to write - DROP TEMPORARY TABLE, DO RELEASE_LOCK (prepared statements' deletion is - TODO), we clean up all temporary tables that we got, if we are sure we - can (see below). + DROP TEMPORARY TABLE, DO RELEASE_LOCK (prepared statements' deletion is + TODO), we clean up all temporary tables that we got, if we are sure we + can (see below). - TODO + @todo - Remove all active user locks. - Guilhem 2003-06: this is true but not urgent: the worst it can cause is - the use of a bit of memory for a user lock which will not be used - anymore. If the user lock is later used, the old one will be released. In - other words, no deadlock problem. + Guilhem 2003-06: this is true but not urgent: the worst it can cause is + the use of a bit of memory for a user lock which will not be used + anymore. If the user lock is later used, the old one will be released. In + other words, no deadlock problem. */ -#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) int Start_log_event_v3::do_apply_event(Relay_log_info const *rli) { DBUG_ENTER("Start_log_event_v3::do_apply_event"); - switch (binlog_version) { + switch (binlog_version) + { case 3: case 4: /* @@ -2685,23 +2697,20 @@ int Start_log_event_v3::do_apply_event(Relay_log_info const *rli) Format_description_log_event methods ****************************************************************************/ -/* +/** Format_description_log_event 1st ctor. - SYNOPSIS - Format_description_log_event::Format_description_log_event - binlog_version the binlog version for which we want to build - an event. Can be 1 (=MySQL 3.23), 3 (=4.0.x - x>=2 and 4.1) or 4 (MySQL 5.0). Note that the - old 4.0 (binlog version 2) is not supported; - it should not be used for replication with - 5.0. - - DESCRIPTION Ctor. Can be used to create the event to write to the binary log (when the server starts or when FLUSH LOGS), or to create artificial events to parse binlogs from MySQL 3.23 or 4.x. When in a client, only the 2nd use is possible. + + @param binlog_version the binlog version for which we want to build + an event. Can be 1 (=MySQL 3.23), 3 (=4.0.x + x>=2 and 4.1) or 4 (MySQL 5.0). Note that the + old 4.0 (binlog version 2) is not supported; + it should not be used for replication with + 5.0. */ Format_description_log_event:: @@ -2809,18 +2818,20 @@ Format_description_log_event(uint8 binlog_ver, const char* server_ver) } -/* +/** The problem with this constructor is that the fixed header may have a length different from this version, but we don't know this length as we have not read the Format_description_log_event which says it, yet. This length is in the post-header of the event, but we don't know where the post-header starts. + So this type of event HAS to: - either have the header's length at the beginning (in the header, at a fixed position which will never be changed), not in the post-header. That would make the header be "shifted" compared to other events. - or have a header of size LOG_EVENT_MINIMAL_HEADER_LEN (19), in all future versions, so that we know for sure. + I (Guilhem) chose the 2nd solution. Rotate has the same constraint (because it is sent before Format_description_log_event). */ @@ -3255,14 +3266,11 @@ Load_log_event::Load_log_event(THD *thd_arg, sql_exchange *ex, #endif /* !MYSQL_CLIENT */ -/* - Load_log_event::Load_log_event() - - NOTE +/** + @note The caller must do buf[event_len] = 0 before he starts using the constructed event. */ - Load_log_event::Load_log_event(const char *buf, uint event_len, const Format_description_log_event *description_event) :Log_event(buf, description_event), num_fields(0), fields(0), @@ -3437,17 +3445,18 @@ void Load_log_event::print(FILE* file_arg, PRINT_EVENT_INFO* print_event_info, } #endif /* MYSQL_CLIENT */ +#ifndef MYSQL_CLIENT -/* +/** Load_log_event::set_fields() - Note that this function can not use the member variable - for the database, since LOAD DATA INFILE on the slave - can be for a different database than the current one. - This is the reason for the affected_db argument to this method. + @note + This function can not use the member variable + for the database, since LOAD DATA INFILE on the slave + can be for a different database than the current one. + This is the reason for the affected_db argument to this method. */ -#ifndef MYSQL_CLIENT void Load_log_event::set_fields(const char* affected_db, List<Item> &field_list, Name_resolution_context *context) @@ -3465,32 +3474,33 @@ void Load_log_event::set_fields(const char* affected_db, #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) -/* - Does the data loading job when executing a LOAD DATA on the slave - - SYNOPSIS - Load_log_event::do_apply_event - net - rli - use_rli_only_for_errors - if set to 1, rli is provided to - Load_log_event::do_apply_event - only for this function to have - RPL_LOG_NAME and - rli->last_slave_error, both being - used by error reports. rli's - position advancing is skipped (done - by the caller which is - Execute_load_log_event::do_apply_event). - - if set to 0, rli is provided for - full use, i.e. for error reports and - position advancing. - - DESCRIPTION - Does the data loading job when executing a LOAD DATA on the slave - - RETURN VALUE +/** + Does the data loading job when executing a LOAD DATA on the slave. + + @param net + @param rli + @param use_rli_only_for_errors If set to 1, rli is provided to + Load_log_event::exec_event only for this + function to have RPL_LOG_NAME and + rli->last_slave_error, both being used by + error reports. rli's position advancing + is skipped (done by the caller which is + Execute_load_log_event::exec_event). + If set to 0, rli is provided for full use, + i.e. for error reports and position + advancing. + + @todo + fix this; this can be done by testing rules in + Create_file_log_event::exec_event() and then discarding Append_block and + al. + @todo + this is a bug - this needs to be moved to the I/O thread + + @retval 0 Success - 1 Failure + @retval + 1 Failure */ int Load_log_event::do_apply_event(NET* net, Relay_log_info const *rli, @@ -3869,24 +3879,21 @@ bool Rotate_log_event::write(IO_CACHE* file) #endif -/* - Rotate_log_event::do_apply_event() +#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) - Got a rotate log event from the master +/* + Got a rotate log event from the master. - IMPLEMENTATION - This is mainly used so that we can later figure out the logname and - position for the master. + This is mainly used so that we can later figure out the logname and + position for the master. - We can't rotate the slave's BINlog as this will cause infinitive rotations - in a A -> B -> A setup. - The NOTES below is a wrong comment which will disappear when 4.1 is merged. + We can't rotate the slave's BINlog as this will cause infinitive rotations + in a A -> B -> A setup. + The NOTES below is a wrong comment which will disappear when 4.1 is merged. - RETURN VALUES + @retval 0 ok */ - -#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) int Rotate_log_event::do_update_pos(Relay_log_info *rli) { DBUG_ENTER("Rotate_log_event::do_update_pos"); @@ -4238,12 +4245,12 @@ void Xid_log_event::pack_info(Protocol *protocol) } #endif -/* - NOTE it's ok not to use int8store here, +/** + @note + It's ok not to use int8store here, as long as xid_t::set(ulonglong) and - xid_t::get_my_xid doesn't do it either - - we don't care about actual values of xids as long as + xid_t::get_my_xid doesn't do it either. + We don't care about actual values of xids as long as identical numbers compare identically */ @@ -4722,6 +4729,10 @@ void Slave_log_event::pack_info(Protocol *protocol) #ifndef MYSQL_CLIENT +/** + @todo + re-write this better without holding both locks at the same time +*/ Slave_log_event::Slave_log_event(THD* thd_arg, Relay_log_info* rli) :Log_event(thd_arg, 0, 0) , mem_pool(0), master_host(0) @@ -4817,7 +4828,7 @@ void Slave_log_event::init_from_mem_pool(int data_size) } -/* This code is not used, so has not been updated to be format-tolerant */ +/** This code is not used, so has not been updated to be format-tolerant. */ Slave_log_event::Slave_log_event(const char* buf, uint event_len) :Log_event(buf,0) /*unused event*/ ,mem_pool(0),master_host(0) { @@ -4865,9 +4876,8 @@ void Stop_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) #endif /* MYSQL_CLIENT */ +#ifndef MYSQL_CLIENT /* - Stop_log_event::do_apply_event() - The master stopped. We used to clean up all temporary tables but this is useless as, as the master has shut down properly, it has written all DROP TEMPORARY TABLE (prepared statements' deletion is @@ -4878,8 +4888,6 @@ void Stop_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) Start_log_event_v3::do_apply_event(), not here. Because if we come here, the master was sane. */ - -#ifndef MYSQL_CLIENT int Stop_log_event::do_update_pos(Relay_log_info *rli) { /* @@ -5104,7 +5112,7 @@ int Create_file_log_event::do_apply_event(Relay_log_info const *rli) bzero((char*)&file, sizeof(file)); fname_buf= strmov(proc_info, "Making temp file "); ext= slave_load_file_stem(fname_buf, file_id, server_id, ".info"); - thd->proc_info= proc_info; + thd_proc_info(thd, proc_info); my_delete(fname_buf, MYF(0)); // old copy may exist already if ((fd= my_create(fname_buf, CREATE_MODE, O_WRONLY | O_BINARY | O_EXCL | O_NOFOLLOW, @@ -5157,7 +5165,7 @@ err: end_io_cache(&file); if (fd >= 0) my_close(fd, MYF(0)); - thd->proc_info= 0; + thd_proc_info(thd, 0); return error == 0; } #endif /* defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) */ @@ -5279,7 +5287,7 @@ int Append_block_log_event::do_apply_event(Relay_log_info const *rli) fname= strmov(proc_info, "Making temp file "); slave_load_file_stem(fname, file_id, server_id, ".data"); - thd->proc_info= proc_info; + thd_proc_info(thd, proc_info); if (get_create_or_append()) { my_delete(fname, MYF(0)); // old copy may exist already @@ -5313,7 +5321,7 @@ int Append_block_log_event::do_apply_event(Relay_log_info const *rli) err: if (fd >= 0) my_close(fd, MYF(0)); - thd->proc_info= 0; + thd_proc_info(thd, 0); DBUG_RETURN(error); } #endif @@ -5703,7 +5711,9 @@ void Execute_load_query_log_event::print(FILE* file, print(file, print_event_info, 0); } - +/** + Prints the query as LOAD DATA LOCAL and with rewritten filename. +*/ void Execute_load_query_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info, const char *local_fname) @@ -6762,15 +6772,17 @@ void Rows_log_event::print_helper(FILE *file, type used is uint32. */ +#if !defined(MYSQL_CLIENT) /** Save the field metadata based on the real_type of the field. The metadata saved depends on the type of the field. Some fields store a single byte for pack_length() while others store two bytes for field_length (max length). - @retval 0 Ok. + @retval 0 Ok. - TODO: We may want to consider changing the encoding of the information. + @todo + We may want to consider changing the encoding of the information. Currently, the code attempts to minimize the number of bytes written to the tablemap. There are at least two other alternatives; 1) using net_store_length() to store the data allowing it to choose the number of @@ -6785,7 +6797,6 @@ void Rows_log_event::print_helper(FILE *file, is less wasteful for space but does waste 1 byte for every field that does not encode 2 parts. */ -#if !defined(MYSQL_CLIENT) int Table_map_log_event::save_field_metadata() { DBUG_ENTER("Table_map_log_event::save_field_metadata"); diff --git a/sql/mf_iocache.cc b/sql/mf_iocache.cc index 5d9d6d834b4..8c2d16c40b0 100644 --- a/sql/mf_iocache.cc +++ b/sql/mf_iocache.cc @@ -13,8 +13,11 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* - Cashing of files with only does (sequential) read or writes of fixed- +/** + @file + + @details + Caching of files with only does (sequential) read or writes of fixed- length records. A read isn't allowed to go over file-length. A read is ok if it ends at file-length and next read can try to read after file-length (and get a EOF-error). @@ -34,11 +37,15 @@ extern "C" { - /* - ** Read buffered from the net. - ** Returns 1 if can't read requested characters - ** Returns 0 if record read - */ +/** + Read buffered from the net. + + @retval + 1 if can't read requested characters + @retval + 0 if record read +*/ + int _my_b_net_read(register IO_CACHE *info, uchar *Buffer, size_t Count __attribute__((unused))) diff --git a/sql/my_decimal.cc b/sql/my_decimal.cc index 54cef6abdb5..651ff22d198 100644 --- a/sql/my_decimal.cc +++ b/sql/my_decimal.cc @@ -18,17 +18,15 @@ #ifndef MYSQL_CLIENT -/* - report result of decimal operation +/** + report result of decimal operation. - SYNOPSIS - decimal_operation_results() - result decimal library return code (E_DEC_* see include/decimal.h) + @param result decimal library return code (E_DEC_* see include/decimal.h) - TODO + @todo Fix error messages - RETURN + @return result */ diff --git a/sql/my_decimal.h b/sql/my_decimal.h index 800ae23425b..1885036f42b 100644 --- a/sql/my_decimal.h +++ b/sql/my_decimal.h @@ -13,7 +13,9 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* +/** + @file + It is interface module to fixed precision decimals library. Most functions use 'uint mask' as parameter, if during operation error @@ -34,14 +36,14 @@ C_MODE_END #define DECIMAL_LONG_DIGITS 10 #define DECIMAL_LONG3_DIGITS 8 -/* maximum length of buffer in our big digits (uint32) */ +/** maximum length of buffer in our big digits (uint32). */ #define DECIMAL_BUFF_LENGTH 9 /* the number of digits that my_decimal can possibly contain */ #define DECIMAL_MAX_POSSIBLE_PRECISION (DECIMAL_BUFF_LENGTH * 9) -/* +/** maximum guaranteed precision of number in decimal digits (number of our digits * number of decimal digits in one our big digit - number of decimal digits in one our big digit decreased by 1 (because we always put decimal @@ -51,13 +53,14 @@ C_MODE_END #define DECIMAL_MAX_SCALE 30 #define DECIMAL_NOT_SPECIFIED 31 -/* +/** maximum length of string representation (number of maximum decimal digits + 1 position for sign + 1 position for decimal point) */ #define DECIMAL_MAX_STR_LENGTH (DECIMAL_MAX_POSSIBLE_PRECISION + 2) -/* - maximum size of packet length + +/** + maximum size of packet length. */ #define DECIMAL_MAX_FIELD_SIZE DECIMAL_MAX_PRECISION @@ -78,11 +81,12 @@ inline int my_decimal_int_part(uint precision, uint decimals) } -/* - my_decimal class limits 'decimal_t' type to what we need in MySQL +/** + my_decimal class limits 'decimal_t' type to what we need in MySQL. + It contains internally all necessary space needed by the instance so no extra memory is needed. One should call fix_buffer_pointer() function - when he moves my_decimal objects in memory + when he moves my_decimal objects in memory. */ class my_decimal :public decimal_t @@ -384,7 +388,10 @@ int my_decimal_mod(uint mask, my_decimal *res, const my_decimal *a, } -/* Returns -1 if a<b, 1 if a>b and 0 if a==b */ +/** + @return + -1 if a<b, 1 if a>b and 0 if a==b +*/ inline int my_decimal_cmp(const my_decimal *a, const my_decimal *b) { diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index f61267711b0..0adf90dc258 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -13,10 +13,13 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* +/** + @file + + @details Mostly this file is used in the server. But a little part of it is used in mysqlbinlog too (definition of SELECT_DISTINCT and others). - The consequence is that 90% of the file is wrapped in #ifndef MYSQL_CLIENT, + The consequence is that 90% of the file is wrapped in \#ifndef MYSQL_CLIENT, except the part which must be in the server and in the client. */ @@ -253,12 +256,12 @@ protected: Feel free to raise this by the smallest amount you can to get the "execution_constants" test to pass. */ -#define STACK_MIN_SIZE 12000 // Abort if less stack during eval. +#define STACK_MIN_SIZE 12000 ///< Abort if less stack during eval. #define STACK_MIN_SIZE_FOR_OPEN 1024*80 -#define STACK_BUFF_ALLOC 352 // For stack overrun checks +#define STACK_BUFF_ALLOC 352 ///< For stack overrun checks #ifndef MYSQLD_NET_RETRY_COUNT -#define MYSQLD_NET_RETRY_COUNT 10 // Abort read after this many int. +#define MYSQLD_NET_RETRY_COUNT 10 ///< Abort read after this many int. #endif #define TEMP_POOL_SIZE 128 @@ -273,6 +276,8 @@ protected: #define BDB_LOG_ALLOC_BLOCK_SIZE 1024 #define WARN_ALLOC_BLOCK_SIZE 2048 #define WARN_ALLOC_PREALLOC_SIZE 1024 +#define PROFILE_ALLOC_BLOCK_SIZE 2048 +#define PROFILE_ALLOC_PREALLOC_SIZE 1024 /* The following parameters is to decide when to use an extra cache to @@ -282,14 +287,14 @@ protected: #define MIN_ROWS_TO_USE_TABLE_CACHE 100 #define MIN_ROWS_TO_USE_BULK_INSERT 100 -/* +/** The following is used to decide if MySQL should use table scanning instead of reading with keys. The number says how many evaluation of the WHERE clause is comparable to reading one extra row from a table. */ #define TIME_FOR_COMPARE 5 // 5 compares == one read -/* +/** Number of comparisons of table rowids equivalent to reading one row from a table. */ @@ -309,17 +314,17 @@ protected: #define DISK_SEEK_PROP_COST ((double)0.5/BLOCKS_IN_AVG_SEEK) -/* +/** Number of rows in a reference table when refereed through a not unique key. This value is only used when we don't know anything about the key distribution. */ #define MATCHING_ROWS_IN_OTHER_TABLE 10 -/* Don't pack string keys shorter than this (if PACK_KEYS=1 isn't used) */ +/** Don't pack string keys shorter than this (if PACK_KEYS=1 isn't used). */ #define KEY_DEFAULT_PACK_LENGTH 8 -/* Characters shown for the command in 'show processlist' */ +/** Characters shown for the command in 'show processlist'. */ #define PROCESS_LIST_WIDTH 100 /* Characters shown for the command in 'information_schema.processlist' */ #define PROCESS_LIST_INFO_WIDTH 65535 @@ -335,11 +340,11 @@ protected: /* The following can also be changed from the command line */ #define DEFAULT_CONCURRENCY 10 -#define DELAYED_LIMIT 100 /* pause after xxx inserts */ +#define DELAYED_LIMIT 100 /**< pause after xxx inserts */ #define DELAYED_QUEUE_SIZE 1000 -#define DELAYED_WAIT_TIMEOUT 5*60 /* Wait for delayed insert */ -#define FLUSH_TIME 0 /* Don't flush tables */ -#define MAX_CONNECT_ERRORS 10 // errors before disabling host +#define DELAYED_WAIT_TIMEOUT 5*60 /**< Wait for delayed insert */ +#define FLUSH_TIME 0 /**< Don't flush tables */ +#define MAX_CONNECT_ERRORS 10 ///< errors before disabling host #ifdef __NETWARE__ #define IF_NETWARE(A,B) A @@ -349,7 +354,7 @@ protected: #if defined(__WIN__) #undef FLUSH_TIME -#define FLUSH_TIME 1800 /* Flush every half hour */ +#define FLUSH_TIME 1800 /**< Flush every half hour */ #define INTERRUPT_PRIOR -2 #define CONNECT_PRIOR -1 @@ -368,12 +373,12 @@ protected: #define TEST_MIT_THREAD 4 #define TEST_BLOCKING 8 #define TEST_KEEP_TMP_TABLES 16 -#define TEST_READCHECK 64 /* Force use of readcheck */ +#define TEST_READCHECK 64 /**< Force use of readcheck */ #define TEST_NO_EXTRA 128 -#define TEST_CORE_ON_SIGNAL 256 /* Give core if signal */ +#define TEST_CORE_ON_SIGNAL 256 /**< Give core if signal */ #define TEST_NO_STACKTRACE 512 -#define TEST_SIGINT 1024 /* Allow sigint on threads */ -#define TEST_SYNCHRONIZATION 2048 /* get server to do sleep in +#define TEST_SIGINT 1024 /**< Allow sigint on threads */ +#define TEST_SYNCHRONIZATION 2048 /**< get server to do sleep in some places */ #endif @@ -423,26 +428,28 @@ protected: /* The following is used to detect a conflict with DISTINCT */ #define SELECT_ALL (ULL(1) << 24) // SELECT, user, parser -/* The following can be set when importing tables in a 'wrong order' +/** The following can be set when importing tables in a 'wrong order' to suppress foreign key checks */ #define OPTION_NO_FOREIGN_KEY_CHECKS (ULL(1) << 26) // THD, user, binlog -/* The following speeds up inserts to InnoDB tables by suppressing unique +/** The following speeds up inserts to InnoDB tables by suppressing unique key checks in some cases */ #define OPTION_RELAXED_UNIQUE_CHECKS (ULL(1) << 27) // THD, user, binlog #define SELECT_NO_UNLOCK (ULL(1) << 28) // SELECT, intern #define OPTION_SCHEMA_TABLE (ULL(1) << 29) // SELECT, intern -/* Flag set if setup_tables already done */ +/** Flag set if setup_tables already done */ #define OPTION_SETUP_TABLES_DONE (ULL(1) << 30) // intern -/* If not set then the thread will ignore all warnings with level notes. */ +/** If not set then the thread will ignore all warnings with level notes. */ #define OPTION_SQL_NOTES (ULL(1) << 31) // THD, user -/* +/** Force the used temporary table to be a MyISAM table (because we will use fulltext functions when reading from it. */ #define TMP_TABLE_FORCE_MYISAM (ULL(1) << 32) +#define OPTION_PROFILING (ULL(1) << 33) -/* + +/** Maximum length of time zone name that we support (Time zone name is char(64) in db). mysqlbinlog needs it. */ @@ -505,9 +512,9 @@ protected: #define UNCACHEABLE_DEPENDENT 1 #define UNCACHEABLE_RAND 2 #define UNCACHEABLE_SIDEEFFECT 4 -// forcing to save JOIN for explain +/// forcing to save JOIN for explain #define UNCACHEABLE_EXPLAIN 8 -/* Don't evaluate subqueries in prepare even if they're not correlated */ +/** Don't evaluate subqueries in prepare even if they're not correlated */ #define UNCACHEABLE_PREPARE 16 /* For uncorrelated SELECT in an UNION with some correlated SELECTs */ #define UNCACHEABLE_UNITED 32 @@ -515,7 +522,7 @@ protected: /* Used to check GROUP BY list in the MODE_ONLY_FULL_GROUP_BY mode */ #define UNDEF_POS (-1) #ifdef EXTRA_DEBUG -/* +/** Sync points allow us to force the server to reach a certain line of code and block there until the client tells the server it is ok to go on. The client tells the server to block with SELECT GET_LOCK() @@ -551,7 +558,7 @@ void view_store_options(THD *thd, TABLE_LIST *table, String *buff); #define portable_sizeof_char_ptr 8 -#define tmp_file_prefix "#sql" /* Prefix for tmp tables */ +#define tmp_file_prefix "#sql" /**< Prefix for tmp tables */ #define tmp_file_prefix_length 4 /* Flags for calc_week() function. */ @@ -578,6 +585,8 @@ enum enum_parsing_place }; struct st_table; + +#define thd_proc_info(thd, msg) set_thd_proc_info(thd, msg, __func__, __FILE__, __LINE__) class THD; enum enum_check_fields @@ -586,9 +595,9 @@ enum enum_check_fields CHECK_FIELD_WARN, CHECK_FIELD_ERROR_FOR_NULL }; - -/* Struct to handle simple linked lists */ + +/** Struct to handle simple linked lists. */ typedef struct st_sql_list { uint elements; uchar *first; @@ -638,6 +647,15 @@ inline THD *_current_thd(void) } #define current_thd _current_thd() +/** + The meat of thd_proc_info(THD*, char*), a macro that packs the last + three calling-info parameters. +*/ +extern "C" +const char *set_thd_proc_info(THD *thd, const char *info, + const char *calling_func, + const char *calling_file, + const unsigned int calling_line); /* External variables @@ -659,6 +677,7 @@ typedef my_bool (*qc_engine_callback)(THD *thd, char *table_key, #include "field.h" /* Field definitions */ #include "protocol.h" #include "sql_udf.h" +#include "sql_profile.h" #include "sql_partition.h" class user_var_entry; @@ -1765,7 +1784,7 @@ extern int creating_table; // How many mysql_create_table() are running External variables */ -extern time_t server_start_time; +extern time_t server_start_time, flush_status_time; #endif /* MYSQL_SERVER */ #if defined MYSQL_SERVER || defined INNODB_COMPATIBILITY_HOOKS extern uint mysql_data_home_len; @@ -1940,6 +1959,7 @@ extern uint sql_command_flags[]; extern TYPELIB log_output_typelib; /* optional things, have_* variables */ +extern SHOW_COMP_OPTION have_community_features; extern handlerton *partition_hton; extern handlerton *myisam_hton; @@ -1951,6 +1971,7 @@ extern SHOW_COMP_OPTION have_geometry, have_rtree_keys; extern SHOW_COMP_OPTION have_crypt; extern SHOW_COMP_OPTION have_compress; + #ifndef __WIN__ extern pthread_t signal_thread; #endif @@ -2246,16 +2267,15 @@ Item * all_any_subquery_creator(Item *left_expr, bool all, SELECT_LEX *select_lex); -/* - clean/setup table fields and map +/** + clean/setup table fields and map. - SYNOPSYS - setup_table_map() - table - TABLE structure pointer (which should be setup) - table_list TABLE_LIST structure pointer (owner of TABLE) - tablenr - table number + @param table TABLE structure pointer (which should be setup) + @param table_list TABLE_LIST structure pointer (owner of TABLE) + @param tablenr table number */ + inline void setup_table_map(TABLE *table, TABLE_LIST *table_list, uint tablenr) { table->used_fields= 0; @@ -2277,10 +2297,8 @@ inline void setup_table_map(TABLE *table, TABLE_LIST *table_list, uint tablenr) } -/* - SYNOPSYS - hexchar_to_int() - convert a hex digit into number +/** + convert a hex digit into number. */ inline int hexchar_to_int(char c) @@ -2293,11 +2311,9 @@ inline int hexchar_to_int(char c) return -1; } -/* - is_user_table() - return true if the table was created explicitly +/** + return true if the table was created explicitly. */ - inline bool is_user_table(TABLE * table) { const char *name= table->s->table_name.str; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 2f264482d94..2471ab3f81f 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -170,10 +170,10 @@ int initgroups(const char *,unsigned int); typedef fp_except fp_except_t; #endif - /* We can't handle floating point exceptions with threads, so disable - this on freebsd - */ - +/** + We can't handle floating point exceptions with threads, so disable + this on freebsd. +*/ inline void set_proper_floating_point_mode() { /* Don't fall for overflow, underflow,divide-by-zero or loss of precision */ @@ -339,7 +339,7 @@ static my_bool opt_short_log_format= 0; static uint kill_cached_threads, wake_thread; static ulong killed_threads, thread_created; static ulong max_used_connections; -static ulong my_bind_addr; /* the address we bind to */ +static ulong my_bind_addr; /**< the address we bind to */ static volatile ulong cached_thread_count= 0; static const char *sql_mode_str= "OFF"; static char *mysqld_user, *mysqld_chroot, *log_error_file_ptr; @@ -380,7 +380,7 @@ bool volatile shutdown_in_progress; */ bool volatile grant_option; -my_bool opt_skip_slave_start = 0; // If set, slave is not autostarted +my_bool opt_skip_slave_start = 0; ///< If set, slave is not autostarted my_bool opt_reckless_slave = 0; my_bool opt_enable_named_pipe= 0; my_bool opt_local_infile, opt_slave_compressed_protocol; @@ -444,7 +444,7 @@ TYPELIB binlog_format_typelib= ulong opt_binlog_format_id= (ulong) BINLOG_FORMAT_UNSPEC; const char *opt_binlog_format= binlog_format_names[opt_binlog_format_id]; #ifdef HAVE_INITGROUPS -static bool calling_initgroups= FALSE; /* Used in SIGSEGV handler. */ +static bool calling_initgroups= FALSE; /**< Used in SIGSEGV handler. */ #endif uint mysqld_port, test_flags, select_errors, dropping_tables, ha_open_options; uint mysqld_port_timeout; @@ -472,12 +472,12 @@ ulong specialflag=0; ulong binlog_cache_use= 0, binlog_cache_disk_use= 0; ulong max_connections, max_connect_errors; uint max_user_connections= 0; -/* +/** Limit of the total number of prepared statements in the server. Is necessary to protect the server against out-of-memory attacks. */ ulong max_prepared_stmt_count; -/* +/** Current total number of prepared statements in the server. This number is exact, and therefore may not be equal to the difference between `com_stmt_prepare' and `com_stmt_close' (global status variables), as @@ -494,7 +494,7 @@ ulong expire_logs_days = 0; ulong rpl_recovery_rank=0; const char *log_output_str= "FILE"; -time_t server_start_time; +time_t server_start_time, flush_status_time; char mysql_home[FN_REFLEN], pidfile_name[FN_REFLEN], system_time_zone[30]; char *default_tz_name; @@ -513,13 +513,13 @@ uint mysql_data_home_len; char mysql_data_home_buff[2], *mysql_data_home=mysql_real_data_home; char server_version[SERVER_VERSION_LENGTH]; char *mysqld_unix_port, *opt_mysql_tmpdir; -const char **errmesg; /* Error messages */ +const char **errmesg; /**< Error messages */ const char *myisam_recover_options_str="OFF"; const char *myisam_stats_method_str="nulls_unequal"; -/* name of reference on left espression in rewritten IN subquery */ +/** name of reference on left espression in rewritten IN subquery */ const char *in_left_expr_name= "<left expr>"; -/* name of additional condition */ +/** name of additional condition */ const char *in_additional_cond= "<IN COND>"; const char *in_having_cond= "<IN HAVING>"; @@ -557,6 +557,7 @@ MY_LOCALE *my_default_lc_time_names; SHOW_COMP_OPTION have_ssl, have_symlink, have_dlopen, have_query_cache; SHOW_COMP_OPTION have_geometry, have_rtree_keys; SHOW_COMP_OPTION have_crypt, have_compress; +SHOW_COMP_OPTION have_community_features; /* Thread specific variables */ @@ -569,7 +570,7 @@ pthread_mutex_t LOCK_mysql_create_db, LOCK_Acl, LOCK_open, LOCK_thread_count, LOCK_crypt, LOCK_bytes_sent, LOCK_bytes_received, LOCK_global_system_variables, LOCK_user_conn, LOCK_slave_list, LOCK_active_mi; -/* +/** The below lock protects access to two global server variables: max_prepared_stmt_count and prepared_stmt_count. These variables set the limit and hold the current total number of prepared statements @@ -618,7 +619,7 @@ static char **defaults_argv; static char *opt_bin_logname; static my_socket unix_sock,ip_sock; -struct rand_struct sql_rand; // used by sql_class.cc:THD::THD() +struct rand_struct sql_rand; ///< used by sql_class.cc:THD::THD() #ifndef EMBEDDED_LIBRARY struct passwd *user_info; @@ -642,7 +643,7 @@ static char **opt_argv; static HANDLE hEventShutdown; static char shutdown_event_name[40]; #include "nt_servc.h" -static NTService Service; // Service object for WinNT +static NTService Service; ///< Service object for WinNT #endif /* EMBEDDED_LIBRARY */ #endif /* __WIN__ */ @@ -1023,19 +1024,15 @@ void kill_mysql(void) DBUG_VOID_RETURN; } -/* - Force server down. Kill all connections and threads and exit - - SYNOPSIS - kill_server +/** + Force server down. Kill all connections and threads and exit. - sig_ptr Signal number that caused kill_server to be called. + @param sig_ptr Signal number that caused kill_server to be called. - NOTE! + @note A signal number of 0 mean that the function was not called from a signal handler and there is thus no signal to block or stop, we just want to kill the server. - */ #if defined(__NETWARE__) @@ -1128,21 +1125,18 @@ extern "C" sig_handler print_signal_warning(int sig) #endif } -/* - cleanup all memory and end program nicely - - SYNOPSIS - unireg_end() +#ifndef EMBEDDED_LIBRARY - NOTES - This function never returns. +/** + cleanup all memory and end program nicely. If SIGNALS_DONT_BREAK_READ is defined, this function is called by the main thread. To get MySQL to shut down nicely in this case (Mac OS X) we have to call exit() instead if pthread_exit(). -*/ -#ifndef EMBEDDED_LIBRARY + @note + This function never returns. +*/ void unireg_end(void) { clean_up(1); @@ -1291,11 +1285,10 @@ void clean_up(bool print_message) #ifndef EMBEDDED_LIBRARY -/* +/** This is mainly needed when running with purify, but it's still nice to - know that all child threads have died when mysqld exits + know that all child threads have died when mysqld exits. */ - static void wait_for_signal_thread_to_end() { #ifndef __NETWARE__ @@ -1375,7 +1368,6 @@ static void set_ports() char *env; if (!mysqld_port && !opt_disable_networking) { // Get port if not from commandline - struct servent *serv_ptr; mysqld_port= MYSQL_PORT; /* @@ -1389,6 +1381,7 @@ static void set_ports() */ #if MYSQL_PORT_DEFAULT == 0 + struct servent *serv_ptr; if ((serv_ptr= getservbyname("mysql", "tcp"))) mysqld_port= ntohs((u_short) serv_ptr->s_port); /* purecov: inspected */ #endif @@ -1522,8 +1515,7 @@ static void set_effective_user(struct passwd *user_info_arg) } -/* Change root user if started with --chroot */ - +/** Change root user if started with @c --chroot . */ static void set_root(const char *path) { #if !defined(__WIN__) && !defined(__NETWARE__) @@ -1712,19 +1704,16 @@ static void network_init(void) #ifndef EMBEDDED_LIBRARY -/* - Close a connection +/** + Close a connection. - SYNOPSIS - close_connection() - thd Thread handle - errcode Error code to print to console - lock 1 if we have have to lock LOCK_thread_count + @param thd Thread handle + @param errcode Error code to print to console + @param lock 1 if we have have to lock LOCK_thread_count - NOTES + @note For the connection that is doing shutdown, this is called twice */ - void close_connection(THD *thd, uint errcode, bool lock) { st_vio *vio; @@ -1749,9 +1738,8 @@ void close_connection(THD *thd, uint errcode, bool lock) #endif /* EMBEDDED_LIBRARY */ - /* Called when a thread is aborted */ - /* ARGSUSED */ - +/** Called when a thread is aborted. */ +/* ARGSUSED */ extern "C" sig_handler end_thread_signal(int sig __attribute__((unused))) { THD *thd=current_thd; @@ -1893,13 +1881,13 @@ void flush_thread_cache() } -/* - Aborts a thread nicely. Commes here on SIGPIPE - TODO: One should have to fix that thr_alarm know about this - thread too. -*/ - #ifdef THREAD_SPECIFIC_SIGPIPE +/** + Aborts a thread nicely. Comes here on SIGPIPE. + + @todo + One should have to fix that thr_alarm know about this thread too. +*/ extern "C" sig_handler abort_thread(int sig __attribute__((unused))) { THD *thd=current_thd; @@ -1947,7 +1935,7 @@ static void check_data_home(const char *path) #elif defined(__NETWARE__) -// down server event callback +/// down server event callback. void mysql_down_server_cb(void *, void *) { event_flag= TRUE; @@ -1955,7 +1943,7 @@ void mysql_down_server_cb(void *, void *) } -// destroy callback resources +/// destroy callback resources. void mysql_cb_destroy(void *) { UnRegisterEventNotification(eh); // cleanup down event notification @@ -1967,7 +1955,7 @@ void mysql_cb_destroy(void *) } -// initialize callbacks +/// initialize callbacks. void mysql_cb_init() { // register for down server event @@ -1990,8 +1978,7 @@ void mysql_cb_init() } -/* To get the name of the NetWare volume having MySQL data folder */ - +/** To get the name of the NetWare volume having MySQL data folder. */ static void getvolumename() { char *p; @@ -2005,8 +1992,8 @@ static void getvolumename() } -/* - Registering with NEB for NSS Volume Deactivation event +/** + Registering with NEB for NSS Volume Deactivation event. */ static void registerwithneb() @@ -2058,8 +2045,8 @@ static void registerwithneb() } -/* - Callback for NSS Volume Deactivation event +/** + Callback for NSS Volume Deactivation event. */ ulong neb_event_callback(struct EventBlock *eblock) @@ -2091,12 +2078,11 @@ ulong neb_event_callback(struct EventBlock *eblock) } -/* - Function to get NSS volume ID of the MySQL data -*/ - #define ADMIN_VOL_PATH "_ADMIN:/Volumes/" +/** + Function to get NSS volume ID of the MySQL data. +*/ static void getvolumeID(BYTE *volumeName) { char path[zMAX_FULL_NAME]; @@ -2171,10 +2157,10 @@ static void start_signal_handler(void) } -/* - Warn if the data is on a Traditional volume +/** + Warn if the data is on a Traditional volume. - NOTE + @note Already done by mysqld_safe */ @@ -2435,8 +2421,7 @@ static void start_signal_handler(void) } -/* This threads handles all signals and alarms */ - +/** This threads handles all signals and alarms. */ /* ARGSUSED */ pthread_handler_t signal_hand(void *arg __attribute__((unused))) { @@ -2574,12 +2559,10 @@ static void check_data_home(const char *path) #endif /* __WIN__*/ -/* +/** All global error messages are sent here where the first one is stored - for the client + for the client. */ - - /* ARGSUSED */ extern "C" int my_message_sql(uint error, const char *str, myf MyFlags); @@ -2722,20 +2705,19 @@ sizeof(load_default_groups)/sizeof(load_default_groups[0]); #endif /*!EMBEDDED_LIBRARY*/ -/* - Initialize one of the global date/time format variables +/** + Initialize one of the global date/time format variables. - SYNOPSIS - init_global_datetime_format() - format_type What kind of format should be supported - var_ptr Pointer to variable that should be updated + @param format_type What kind of format should be supported + @param var_ptr Pointer to variable that should be updated - NOTES + @note The default value is taken from either opt_date_time_formats[] or the ISO format (ANSI SQL) - RETURN + @retval 0 ok + @retval 1 error */ @@ -2763,6 +2745,156 @@ static bool init_global_datetime_format(timestamp_type format_type, return 0; } +SHOW_VAR com_status_vars[]= { + {"admin_commands", (char*) offsetof(STATUS_VAR, com_other), SHOW_LONG_STATUS}, + {"assign_to_keycache", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ASSIGN_TO_KEYCACHE]), SHOW_LONG_STATUS}, + {"alter_db", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_DB]), SHOW_LONG_STATUS}, + {"alter_db_upgrade", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_DB_UPGRADE]), SHOW_LONG_STATUS}, + {"alter_event", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_EVENT]), SHOW_LONG_STATUS}, + {"alter_function", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_FUNCTION]), SHOW_LONG_STATUS}, + {"alter_procedure", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_PROCEDURE]), SHOW_LONG_STATUS}, + {"alter_server", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_SERVER]), SHOW_LONG_STATUS}, + {"alter_table", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_TABLE]), SHOW_LONG_STATUS}, + {"alter_tablespace", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_TABLESPACE]), SHOW_LONG_STATUS}, + {"analyze", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ANALYZE]), SHOW_LONG_STATUS}, + {"backup_table", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_BACKUP_TABLE]), SHOW_LONG_STATUS}, + {"begin", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_BEGIN]), SHOW_LONG_STATUS}, + {"binlog", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_BINLOG_BASE64_EVENT]), SHOW_LONG_STATUS}, + {"call_procedure", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CALL]), SHOW_LONG_STATUS}, + {"change_db", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CHANGE_DB]), SHOW_LONG_STATUS}, + {"change_master", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CHANGE_MASTER]), SHOW_LONG_STATUS}, + {"check", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CHECK]), SHOW_LONG_STATUS}, + {"checksum", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CHECKSUM]), SHOW_LONG_STATUS}, + {"commit", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_COMMIT]), SHOW_LONG_STATUS}, + {"create_db", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_DB]), SHOW_LONG_STATUS}, + {"create_event", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_EVENT]), SHOW_LONG_STATUS}, + {"create_function", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_SPFUNCTION]), SHOW_LONG_STATUS}, + {"create_index", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_INDEX]), SHOW_LONG_STATUS}, + {"create_procedure", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_PROCEDURE]), SHOW_LONG_STATUS}, + {"create_server", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_SERVER]), SHOW_LONG_STATUS}, + {"create_table", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_TABLE]), SHOW_LONG_STATUS}, + {"create_trigger", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_TRIGGER]), SHOW_LONG_STATUS}, + {"create_udf", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_FUNCTION]), SHOW_LONG_STATUS}, + {"create_user", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_USER]), SHOW_LONG_STATUS}, + {"create_view", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_VIEW]), SHOW_LONG_STATUS}, + {"dealloc_sql", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DEALLOCATE_PREPARE]), SHOW_LONG_STATUS}, + {"delete", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DELETE]), SHOW_LONG_STATUS}, + {"delete_multi", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DELETE_MULTI]), SHOW_LONG_STATUS}, + {"do", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DO]), SHOW_LONG_STATUS}, + {"drop_db", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_DB]), SHOW_LONG_STATUS}, + {"drop_event", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_EVENT]), SHOW_LONG_STATUS}, + {"drop_function", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_FUNCTION]), SHOW_LONG_STATUS}, + {"drop_index", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_INDEX]), SHOW_LONG_STATUS}, + {"drop_procedure", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_PROCEDURE]), SHOW_LONG_STATUS}, + {"drop_server", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_SERVER]), SHOW_LONG_STATUS}, + {"drop_table", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_TABLE]), SHOW_LONG_STATUS}, + {"drop_trigger", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_TRIGGER]), SHOW_LONG_STATUS}, + {"drop_user", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_USER]), SHOW_LONG_STATUS}, + {"drop_view", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_VIEW]), SHOW_LONG_STATUS}, + {"empty_query", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_EMPTY_QUERY]), SHOW_LONG_STATUS}, + {"execute_sql", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_EXECUTE]), SHOW_LONG_STATUS}, + {"flush", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_FLUSH]), SHOW_LONG_STATUS}, + {"grant", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_GRANT]), SHOW_LONG_STATUS}, + {"ha_close", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_HA_CLOSE]), SHOW_LONG_STATUS}, + {"ha_open", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_HA_OPEN]), SHOW_LONG_STATUS}, + {"ha_read", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_HA_READ]), SHOW_LONG_STATUS}, + {"help", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_HELP]), SHOW_LONG_STATUS}, + {"insert", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_INSERT]), SHOW_LONG_STATUS}, + {"insert_select", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_INSERT_SELECT]), SHOW_LONG_STATUS}, + {"install_plugin", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_INSTALL_PLUGIN]), SHOW_LONG_STATUS}, + {"kill", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_KILL]), SHOW_LONG_STATUS}, + {"load", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_LOAD]), SHOW_LONG_STATUS}, + {"load_master_data", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_LOAD_MASTER_DATA]), SHOW_LONG_STATUS}, + {"load_master_table", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_LOAD_MASTER_TABLE]), SHOW_LONG_STATUS}, + {"lock_tables", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_LOCK_TABLES]), SHOW_LONG_STATUS}, + {"optimize", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_OPTIMIZE]), SHOW_LONG_STATUS}, + {"preload_keys", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_PRELOAD_KEYS]), SHOW_LONG_STATUS}, + {"prepare_sql", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_PREPARE]), SHOW_LONG_STATUS}, + {"purge", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_PURGE]), SHOW_LONG_STATUS}, + {"purge_before_date", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_PURGE_BEFORE]), SHOW_LONG_STATUS}, + {"release_savepoint", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RELEASE_SAVEPOINT]), SHOW_LONG_STATUS}, + {"rename_table", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RENAME_TABLE]), SHOW_LONG_STATUS}, + {"rename_user", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RENAME_USER]), SHOW_LONG_STATUS}, + {"repair", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REPAIR]), SHOW_LONG_STATUS}, + {"replace", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REPLACE]), SHOW_LONG_STATUS}, + {"replace_select", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REPLACE_SELECT]), SHOW_LONG_STATUS}, + {"reset", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RESET]), SHOW_LONG_STATUS}, + {"restore_table", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RESTORE_TABLE]), SHOW_LONG_STATUS}, + {"revoke", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REVOKE]), SHOW_LONG_STATUS}, + {"revoke_all", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REVOKE_ALL]), SHOW_LONG_STATUS}, + {"rollback", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ROLLBACK]), SHOW_LONG_STATUS}, + {"rollback_to_savepoint",(char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ROLLBACK_TO_SAVEPOINT]), SHOW_LONG_STATUS}, + {"savepoint", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SAVEPOINT]), SHOW_LONG_STATUS}, + {"select", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SELECT]), SHOW_LONG_STATUS}, + {"set_option", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SET_OPTION]), SHOW_LONG_STATUS}, + {"show_authors", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_AUTHORS]), SHOW_LONG_STATUS}, + {"show_binlog_events", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_BINLOG_EVENTS]), SHOW_LONG_STATUS}, + {"show_binlogs", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_BINLOGS]), SHOW_LONG_STATUS}, + {"show_charsets", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CHARSETS]), SHOW_LONG_STATUS}, + {"show_collations", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_COLLATIONS]), SHOW_LONG_STATUS}, + {"show_column_types", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_COLUMN_TYPES]), SHOW_LONG_STATUS}, + {"show_contributors", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CONTRIBUTORS]), SHOW_LONG_STATUS}, + {"show_create_db", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CREATE_DB]), SHOW_LONG_STATUS}, + {"show_create_event", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CREATE_EVENT]), SHOW_LONG_STATUS}, + {"show_create_func", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CREATE_FUNC]), SHOW_LONG_STATUS}, + {"show_create_proc", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CREATE_PROC]), SHOW_LONG_STATUS}, + {"show_create_table", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CREATE]), SHOW_LONG_STATUS}, + {"show_create_trigger", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CREATE_TRIGGER]), SHOW_LONG_STATUS}, + {"show_databases", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_DATABASES]), SHOW_LONG_STATUS}, + {"show_engine_logs", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_ENGINE_LOGS]), SHOW_LONG_STATUS}, + {"show_engine_mutex", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_ENGINE_MUTEX]), SHOW_LONG_STATUS}, + {"show_engine_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_ENGINE_STATUS]), SHOW_LONG_STATUS}, + {"show_events", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_EVENTS]), SHOW_LONG_STATUS}, + {"show_errors", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_ERRORS]), SHOW_LONG_STATUS}, + {"show_fields", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_FIELDS]), SHOW_LONG_STATUS}, +#ifndef DBUG_OFF + {"show_function_code", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_FUNC_CODE]), SHOW_LONG_STATUS}, +#endif + {"show_function_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STATUS_FUNC]), SHOW_LONG_STATUS}, + {"show_grants", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_GRANTS]), SHOW_LONG_STATUS}, + {"show_keys", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_KEYS]), SHOW_LONG_STATUS}, + {"show_master_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_MASTER_STAT]), SHOW_LONG_STATUS}, + {"show_new_master", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_NEW_MASTER]), SHOW_LONG_STATUS}, + {"show_open_tables", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_OPEN_TABLES]), SHOW_LONG_STATUS}, + {"show_plugins", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PLUGINS]), SHOW_LONG_STATUS}, + {"show_privileges", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PRIVILEGES]), SHOW_LONG_STATUS}, +#ifndef DBUG_OFF + {"show_procedure_code", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PROC_CODE]), SHOW_LONG_STATUS}, +#endif + {"show_procedure_status",(char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STATUS_PROC]), SHOW_LONG_STATUS}, + {"show_processlist", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PROCESSLIST]), SHOW_LONG_STATUS}, + {"show_profile", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PROFILE]), SHOW_LONG_STATUS}, + {"show_profiles", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PROFILES]), SHOW_LONG_STATUS}, + {"show_slave_hosts", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_SLAVE_HOSTS]), SHOW_LONG_STATUS}, + {"show_slave_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_SLAVE_STAT]), SHOW_LONG_STATUS}, + {"show_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STATUS]), SHOW_LONG_STATUS}, + {"show_storage_engines", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STORAGE_ENGINES]), SHOW_LONG_STATUS}, + {"show_table_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_TABLE_STATUS]), SHOW_LONG_STATUS}, + {"show_tables", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_TABLES]), SHOW_LONG_STATUS}, + {"show_triggers", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_TRIGGERS]), SHOW_LONG_STATUS}, + {"show_variables", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_VARIABLES]), SHOW_LONG_STATUS}, + {"show_warnings", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_WARNS]), SHOW_LONG_STATUS}, + {"slave_start", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SLAVE_START]), SHOW_LONG_STATUS}, + {"slave_stop", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SLAVE_STOP]), SHOW_LONG_STATUS}, + {"stmt_close", (char*) offsetof(STATUS_VAR, com_stmt_close), SHOW_LONG_STATUS}, + {"stmt_execute", (char*) offsetof(STATUS_VAR, com_stmt_execute), SHOW_LONG_STATUS}, + {"stmt_fetch", (char*) offsetof(STATUS_VAR, com_stmt_fetch), SHOW_LONG_STATUS}, + {"stmt_prepare", (char*) offsetof(STATUS_VAR, com_stmt_prepare), SHOW_LONG_STATUS}, + {"stmt_reset", (char*) offsetof(STATUS_VAR, com_stmt_reset), SHOW_LONG_STATUS}, + {"stmt_send_long_data", (char*) offsetof(STATUS_VAR, com_stmt_send_long_data), SHOW_LONG_STATUS}, + {"truncate", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_TRUNCATE]), SHOW_LONG_STATUS}, + {"uninstall_plugin", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_UNINSTALL_PLUGIN]), SHOW_LONG_STATUS}, + {"unlock_tables", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_UNLOCK_TABLES]), SHOW_LONG_STATUS}, + {"update", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_UPDATE]), SHOW_LONG_STATUS}, + {"update_multi", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_UPDATE_MULTI]), SHOW_LONG_STATUS}, + {"xa_commit", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_COMMIT]),SHOW_LONG_STATUS}, + {"xa_end", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_END]),SHOW_LONG_STATUS}, + {"xa_prepare", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_PREPARE]),SHOW_LONG_STATUS}, + {"xa_recover", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_RECOVER]),SHOW_LONG_STATUS}, + {"xa_rollback", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_ROLLBACK]),SHOW_LONG_STATUS}, + {"xa_start", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_START]),SHOW_LONG_STATUS}, + {NullS, NullS, SHOW_LONG} +}; static int init_common_variables(const char *conf_file_name, int argc, char **argv, const char **groups) @@ -2773,10 +2905,10 @@ static int init_common_variables(const char *conf_file_name, int argc, tzset(); // Set tzname max_system_variables.pseudo_thread_id= (ulong)~0; - server_start_time= my_time(0); + server_start_time= flush_status_time= my_time(0); rpl_filter= new Rpl_filter; binlog_filter= new Rpl_filter; - if (!rpl_filter || !binlog_filter) + if (!rpl_filter || !binlog_filter) { sql_perror("Could not allocate replication and binlog filters"); exit(1); @@ -2796,13 +2928,13 @@ static int init_common_variables(const char *conf_file_name, int argc, } #endif /* - We set SYSTEM time zone as reasonable default and + We set SYSTEM time zone as reasonable default and also for failure of my_tz_init() and bootstrap mode. If user explicitly set time zone with --default-time-zone option we will change this value in my_tz_init(). */ global_system_variables.time_zone= my_tz_SYSTEM; - + /* Init mutexes for the global MYSQL_BIN_LOG objects. As safe_mutex depends on what MY_INIT() does, we can't init the mutexes of @@ -2831,6 +2963,31 @@ static int init_common_variables(const char *conf_file_name, int argc, if (add_status_vars(status_vars)) return 1; // an error was already reported +#ifndef DBUG_OFF + /* + We have few debug-only commands in com_status_vars, only visible in debug + builds. for simplicity we enable the assert only in debug builds + + There are 7 Com_ variables which don't have corresponding SQLCOM_ values: + (TODO strictly speaking they shouldn't be here, should not have Com_ prefix + that is. Perhaps Stmt_ ? Comstmt_ ? Prepstmt_ ?) + + Com_admin_commands => com_other + Com_stmt_close => com_stmt_close + Com_stmt_execute => com_stmt_execute + Com_stmt_fetch => com_stmt_fetch + Com_stmt_prepare => com_stmt_prepare + Com_stmt_reset => com_stmt_reset + Com_stmt_send_long_data => com_stmt_send_long_data + + With this correction the number of Com_ variables (number of elements in + the array, excluding the last element - terminator) must match the number + of SQLCOM_ constants. + */ + compile_time_assert(sizeof(com_status_vars)/sizeof(com_status_vars[0]) - 1 == + SQLCOM_END + 7); +#endif + load_defaults(conf_file_name, groups, &argc, &argv); defaults_argv=argv; defaults_argc=argc; @@ -2887,7 +3044,7 @@ static int init_common_variables(const char *conf_file_name, int argc, */ table_cache_size= (ulong) min(max((files-10-max_connections)/2, TABLE_OPEN_CACHE_MIN), - table_cache_size); + table_cache_size); DBUG_PRINT("warning", ("Changed limits: max_open_files: %u max_connections: %ld table_cache: %ld", files, max_connections, table_cache_size)); @@ -4077,21 +4234,20 @@ static char *add_quoted_string(char *to, const char *from, char *to_end) } -/* - Handle basic handling of services, like installation and removal +/** + Handle basic handling of services, like installation and removal. - SYNOPSIS - default_service_handling() - argv Pointer to argument list - servicename Internal name of service - displayname Display name of service (in taskbar ?) - file_path Path to this program - startup_option Startup option to mysqld - - RETURN VALUES + @param argv Pointer to argument list + @param servicename Internal name of service + @param displayname Display name of service (in taskbar ?) + @param file_path Path to this program + @param startup_option Startup option to mysqld + + @retval 0 option handled + @retval 1 Could not handle option - */ +*/ static bool default_service_handling(char **argv, @@ -4240,7 +4396,7 @@ int main(int argc, char **argv) #endif -/* +/** Execute all commands from a file. Used by the mysql_install_db script to create MySQL privilege tables without having to start a full MySQL server. */ @@ -4369,23 +4525,17 @@ void create_thread_to_handle_connection(THD *thd) } -/* +/** Create new thread to handle incoming connection. - SYNOPSIS - create_new_thread() - thd in/out Thread handle of future thread. - - DESCRIPTION This function will create new thread to handle the incoming connection. If there are idle cached threads one will be used. 'thd' will be pushed into 'threads'. - In single-threaded mode (#define ONE_THREAD) connection will be + In single-threaded mode (\#define ONE_THREAD) connection will be handled inside this function. - RETURN VALUE - none + @param[in,out] thd Thread handle of future thread. */ static void create_new_thread(THD *thd) @@ -4739,15 +4889,13 @@ pthread_handler_t handle_connections_namedpipes(void *arg) #endif /* __NT__ */ -/* - Thread of shared memory's service +#ifdef HAVE_SMEM - SYNOPSIS - handle_connections_shared_memory() - arg Arguments of thread -*/ +/** + Thread of shared memory's service. -#ifdef HAVE_SMEM + @param arg Arguments of thread +*/ pthread_handler_t handle_connections_shared_memory(void *arg) { /* file-mapping object, use for create shared memory */ @@ -5134,6 +5282,7 @@ enum options_mysqld OPT_PLUGIN_DIR, OPT_LOG_OUTPUT, OPT_PORT_OPEN_TIMEOUT, + OPT_PROFILING, OPT_KEEP_FILES_ON_CREATE, OPT_GENERAL_LOG, OPT_SLOW_LOG, @@ -5686,6 +5835,12 @@ master-ssl", "Maximum time in seconds to wait for the port to become free. " "(Default: no wait)", (uchar**) &mysqld_port_timeout, (uchar**) &mysqld_port_timeout, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, +#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) + {"profiling_history_size", OPT_PROFILING, "Limit of query profiling memory", + (uchar**) &global_system_variables.profiling_history_size, + (uchar**) &max_system_variables.profiling_history_size, + 0, GET_ULONG, REQUIRED_ARG, 15, 0, 100, 0, 0, 0}, +#endif {"relay-log", OPT_RELAY_LOG, "The location and name to use for relay logs.", (uchar**) &opt_relay_logname, (uchar**) &opt_relay_logname, 0, @@ -6459,6 +6614,16 @@ static int show_starttime(THD *thd, SHOW_VAR *var, char *buff) return 0; } +#ifdef COMMUNITY_SERVER +static int show_flushstatustime(THD *thd, SHOW_VAR *var, char *buff) +{ + var->type= SHOW_LONG; + var->value= buff; + *((long *)buff)= (long) (thd->query_start() - flush_status_time); + return 0; +} +#endif + #ifdef HAVE_REPLICATION static int show_rpl_status(THD *thd, SHOW_VAR *var, char *buff) { @@ -6796,115 +6961,7 @@ SHOW_VAR status_vars[]= { {"Binlog_cache_use", (char*) &binlog_cache_use, SHOW_LONG}, {"Bytes_received", (char*) offsetof(STATUS_VAR, bytes_received), SHOW_LONGLONG_STATUS}, {"Bytes_sent", (char*) offsetof(STATUS_VAR, bytes_sent), SHOW_LONGLONG_STATUS}, - {"Com_admin_commands", (char*) offsetof(STATUS_VAR, com_other), SHOW_LONG_STATUS}, - {"Com_alter_db", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_DB]), SHOW_LONG_STATUS}, - {"Com_alter_event", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_EVENT]), SHOW_LONG_STATUS}, - {"Com_alter_table", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_TABLE]), SHOW_LONG_STATUS}, - {"Com_analyze", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ANALYZE]), SHOW_LONG_STATUS}, - {"Com_backup_table", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_BACKUP_TABLE]), SHOW_LONG_STATUS}, - {"Com_begin", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_BEGIN]), SHOW_LONG_STATUS}, - {"Com_call_procedure", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CALL]), SHOW_LONG_STATUS}, - {"Com_change_db", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CHANGE_DB]), SHOW_LONG_STATUS}, - {"Com_change_master", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CHANGE_MASTER]), SHOW_LONG_STATUS}, - {"Com_check", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CHECK]), SHOW_LONG_STATUS}, - {"Com_checksum", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CHECKSUM]), SHOW_LONG_STATUS}, - {"Com_commit", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_COMMIT]), SHOW_LONG_STATUS}, - {"Com_create_db", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_DB]), SHOW_LONG_STATUS}, - {"Com_create_event", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_EVENT]), SHOW_LONG_STATUS}, - {"Com_create_function", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_FUNCTION]), SHOW_LONG_STATUS}, - {"Com_create_index", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_INDEX]), SHOW_LONG_STATUS}, - {"Com_create_table", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_TABLE]), SHOW_LONG_STATUS}, - {"Com_create_user", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_USER]), SHOW_LONG_STATUS}, - {"Com_dealloc_sql", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DEALLOCATE_PREPARE]), SHOW_LONG_STATUS}, - {"Com_delete", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DELETE]), SHOW_LONG_STATUS}, - {"Com_delete_multi", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DELETE_MULTI]), SHOW_LONG_STATUS}, - {"Com_do", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DO]), SHOW_LONG_STATUS}, - {"Com_drop_db", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_DB]), SHOW_LONG_STATUS}, - {"Com_drop_event", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_EVENT]), SHOW_LONG_STATUS}, - {"Com_drop_function", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_FUNCTION]), SHOW_LONG_STATUS}, - {"Com_drop_index", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_INDEX]), SHOW_LONG_STATUS}, - {"Com_drop_table", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_TABLE]), SHOW_LONG_STATUS}, - {"Com_drop_user", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_USER]), SHOW_LONG_STATUS}, - {"Com_execute_sql", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_EXECUTE]), SHOW_LONG_STATUS}, - {"Com_flush", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_FLUSH]), SHOW_LONG_STATUS}, - {"Com_grant", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_GRANT]), SHOW_LONG_STATUS}, - {"Com_ha_close", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_HA_CLOSE]), SHOW_LONG_STATUS}, - {"Com_ha_open", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_HA_OPEN]), SHOW_LONG_STATUS}, - {"Com_ha_read", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_HA_READ]), SHOW_LONG_STATUS}, - {"Com_help", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_HELP]), SHOW_LONG_STATUS}, - {"Com_insert", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_INSERT]), SHOW_LONG_STATUS}, - {"Com_insert_select", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_INSERT_SELECT]), SHOW_LONG_STATUS}, - {"Com_kill", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_KILL]), SHOW_LONG_STATUS}, - {"Com_load", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_LOAD]), SHOW_LONG_STATUS}, - {"Com_load_master_data", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_LOAD_MASTER_DATA]), SHOW_LONG_STATUS}, - {"Com_load_master_table", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_LOAD_MASTER_TABLE]), SHOW_LONG_STATUS}, - {"Com_lock_tables", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_LOCK_TABLES]), SHOW_LONG_STATUS}, - {"Com_optimize", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_OPTIMIZE]), SHOW_LONG_STATUS}, - {"Com_preload_keys", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_PRELOAD_KEYS]), SHOW_LONG_STATUS}, - {"Com_prepare_sql", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_PREPARE]), SHOW_LONG_STATUS}, - {"Com_purge", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_PURGE]), SHOW_LONG_STATUS}, - {"Com_purge_before_date", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_PURGE_BEFORE]), SHOW_LONG_STATUS}, - {"Com_rename_table", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RENAME_TABLE]), SHOW_LONG_STATUS}, - {"Com_repair", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REPAIR]), SHOW_LONG_STATUS}, - {"Com_replace", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REPLACE]), SHOW_LONG_STATUS}, - {"Com_replace_select", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REPLACE_SELECT]), SHOW_LONG_STATUS}, - {"Com_reset", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RESET]), SHOW_LONG_STATUS}, - {"Com_restore_table", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RESTORE_TABLE]), SHOW_LONG_STATUS}, - {"Com_revoke", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REVOKE]), SHOW_LONG_STATUS}, - {"Com_revoke_all", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REVOKE_ALL]), SHOW_LONG_STATUS}, - {"Com_rollback", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ROLLBACK]), SHOW_LONG_STATUS}, - {"Com_savepoint", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SAVEPOINT]), SHOW_LONG_STATUS}, - {"Com_select", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SELECT]), SHOW_LONG_STATUS}, - {"Com_set_option", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SET_OPTION]), SHOW_LONG_STATUS}, - {"Com_show_binlog_events", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_BINLOG_EVENTS]), SHOW_LONG_STATUS}, - {"Com_show_binlogs", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_BINLOGS]), SHOW_LONG_STATUS}, - {"Com_show_charsets", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CHARSETS]), SHOW_LONG_STATUS}, - {"Com_show_collations", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_COLLATIONS]), SHOW_LONG_STATUS}, - {"Com_show_column_types", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_COLUMN_TYPES]), SHOW_LONG_STATUS}, - {"Com_show_create_db", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CREATE_DB]), SHOW_LONG_STATUS}, - {"Com_show_create_event", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CREATE_EVENT]), SHOW_LONG_STATUS}, - {"Com_show_create_table", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CREATE]), SHOW_LONG_STATUS}, - {"Com_show_databases", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_DATABASES]), SHOW_LONG_STATUS}, - {"Com_show_engine_logs", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_ENGINE_LOGS]), SHOW_LONG_STATUS}, - {"Com_show_engine_mutex", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_ENGINE_MUTEX]), SHOW_LONG_STATUS}, - {"Com_show_engine_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_ENGINE_STATUS]), SHOW_LONG_STATUS}, - {"Com_show_events", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_EVENTS]), SHOW_LONG_STATUS}, - {"Com_show_errors", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_ERRORS]), SHOW_LONG_STATUS}, - {"Com_show_fields", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_FIELDS]), SHOW_LONG_STATUS}, - {"Com_show_grants", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_GRANTS]), SHOW_LONG_STATUS}, - {"Com_show_keys", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_KEYS]), SHOW_LONG_STATUS}, - {"Com_show_master_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_MASTER_STAT]), SHOW_LONG_STATUS}, - {"Com_show_new_master", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_NEW_MASTER]), SHOW_LONG_STATUS}, - {"Com_show_open_tables", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_OPEN_TABLES]), SHOW_LONG_STATUS}, - {"Com_show_plugins", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PLUGINS]), SHOW_LONG_STATUS}, - {"Com_show_privileges", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PRIVILEGES]), SHOW_LONG_STATUS}, - {"Com_show_processlist", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PROCESSLIST]), SHOW_LONG_STATUS}, - {"Com_show_slave_hosts", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_SLAVE_HOSTS]), SHOW_LONG_STATUS}, - {"Com_show_slave_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_SLAVE_STAT]), SHOW_LONG_STATUS}, - {"Com_show_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STATUS]), SHOW_LONG_STATUS}, - {"Com_show_storage_engines", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STORAGE_ENGINES]), SHOW_LONG_STATUS}, - {"Com_show_tables", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_TABLES]), SHOW_LONG_STATUS}, - {"Com_show_triggers", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_TRIGGERS]), SHOW_LONG_STATUS}, - {"Com_show_variables", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_VARIABLES]), SHOW_LONG_STATUS}, - {"Com_show_warnings", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_WARNS]), SHOW_LONG_STATUS}, - {"Com_slave_start", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SLAVE_START]), SHOW_LONG_STATUS}, - {"Com_slave_stop", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SLAVE_STOP]), SHOW_LONG_STATUS}, - {"Com_stmt_close", (char*) offsetof(STATUS_VAR, com_stmt_close), SHOW_LONG_STATUS}, - {"Com_stmt_execute", (char*) offsetof(STATUS_VAR, com_stmt_execute), SHOW_LONG_STATUS}, - {"Com_stmt_fetch", (char*) offsetof(STATUS_VAR, com_stmt_fetch), SHOW_LONG_STATUS}, - {"Com_stmt_prepare", (char*) offsetof(STATUS_VAR, com_stmt_prepare), SHOW_LONG_STATUS}, - {"Com_stmt_reset", (char*) offsetof(STATUS_VAR, com_stmt_reset), SHOW_LONG_STATUS}, - {"Com_stmt_send_long_data", (char*) offsetof(STATUS_VAR, com_stmt_send_long_data), SHOW_LONG_STATUS}, - {"Com_truncate", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_TRUNCATE]), SHOW_LONG_STATUS}, - {"Com_unlock_tables", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_UNLOCK_TABLES]), SHOW_LONG_STATUS}, - {"Com_update", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_UPDATE]), SHOW_LONG_STATUS}, - {"Com_update_multi", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_UPDATE_MULTI]), SHOW_LONG_STATUS}, - {"Com_xa_commit", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_COMMIT]),SHOW_LONG_STATUS}, - {"Com_xa_end", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_END]),SHOW_LONG_STATUS}, - {"Com_xa_prepare", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_PREPARE]),SHOW_LONG_STATUS}, - {"Com_xa_recover", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_RECOVER]),SHOW_LONG_STATUS}, - {"Com_xa_rollback", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_ROLLBACK]),SHOW_LONG_STATUS}, - {"Com_xa_start", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_START]),SHOW_LONG_STATUS}, + {"Com", (char*) com_status_vars, SHOW_ARRAY}, {"Compression", (char*) &show_net_compression, SHOW_FUNC}, {"Connections", (char*) &thread_id, SHOW_LONG_NOFLUSH}, {"Created_tmp_disk_tables", (char*) offsetof(STATUS_VAR, created_tmp_disk_tables), SHOW_LONG_STATUS}, @@ -7013,6 +7070,9 @@ SHOW_VAR status_vars[]= { {"Threads_created", (char*) &thread_created, SHOW_LONG_NOFLUSH}, {"Threads_running", (char*) &thread_running, SHOW_INT}, {"Uptime", (char*) &show_starttime, SHOW_FUNC}, +#ifdef COMMUNITY_SERVER + {"Uptime_since_flush_status",(char*) &show_flushstatustime, SHOW_FUNC}, +#endif {NullS, NullS, SHOW_LONG} }; @@ -7076,13 +7136,13 @@ To see what values a running MySQL server is using, type\n\ #endif /*!EMBEDDED_LIBRARY*/ -/* - Initialize all MySQL global variables to default values +/** + Initialize all MySQL global variables to default values. - SYNOPSIS - mysql_init_variables() + We don't need to set numeric variables refered to in my_long_options + as these are initialized by my_getopt. - NOTES + @note The reason to set a lot of global variables to zero is to allow one to restart the embedded server with a clean environment It's also needed on some exotic platforms where global variables are @@ -7220,7 +7280,10 @@ static void mysql_init_variables(void) "d:t:i:o,/tmp/mysqld.trace"); #endif opt_error_log= IF_WIN(1,0); -#ifdef WITH_NDBCLUSTER_STORAGE_ENGINE +#ifdef COMMUNITY_SERVER + have_community_features = SHOW_OPTION_YES; +#else + have_community_features = SHOW_OPTION_NO; global_system_variables.ndb_index_stat_enable=FALSE; max_system_variables.ndb_index_stat_enable=TRUE; global_system_variables.ndb_index_stat_cache_entries=32; @@ -7809,7 +7872,7 @@ mysqld_get_one_option(int optid, } -/* Handle arguments for multiple key caches */ +/** Handle arguments for multiple key caches. */ extern "C" uchar **mysql_getopt_value(const char *keyname, uint key_length, const struct my_option *option); @@ -7860,6 +7923,10 @@ void option_error_reporter(enum loglevel level, const char *format, ...) } +/** + @todo + - FIXME add EXIT_TOO_MANY_ARGUMENTS to "mysys_err.h" and return that code? +*/ static void get_options(int *argc,char **argv) { int ho_error; @@ -7991,10 +8058,11 @@ static char *get_relative_path(const char *path) } -/* +/** Fix filename and replace extension where 'dir' is relative to mysql_real_data_home. - Return 1 if len(path) > FN_REFLEN + @return + 1 if len(path) > FN_REFLEN */ bool @@ -8099,9 +8167,11 @@ static ulong find_bit_type_or_exit(const char *x, TYPELIB *bit_lib, } -/* - Return a bitfield from a string of substrings separated by ',' - returns ~(ulong) 0 on error. +/** + @return + a bitfield from a string of substrings separated by ',' + or + ~(ulong) 0 on error. */ static ulong find_bit_type(const char *x, TYPELIB *bit_lib) @@ -8160,16 +8230,16 @@ skip: ; } /* find_bit_type */ -/* - Check if file system used for databases is case insensitive +/** + Check if file system used for databases is case insensitive. - SYNOPSIS - test_if_case_sensitive() - dir_name Directory to test + @param dir_name Directory to test - RETURN + @retval -1 Don't know (Test failed) + @retval 0 File system is case sensitive + @retval 1 File system is case insensitive */ @@ -8200,10 +8270,11 @@ static int test_if_case_insensitive(const char *dir_name) } -/* Create file to store pid number */ - #ifndef EMBEDDED_LIBRARY +/** + Create file to store pid number. +*/ static void create_pid_file() { File file; @@ -8225,7 +8296,7 @@ static void create_pid_file() } #endif /* EMBEDDED_LIBRARY */ -/* Clear most status variables */ +/** Clear most status variables. */ void refresh_status(THD *thd) { pthread_mutex_lock(&LOCK_status); @@ -8241,6 +8312,9 @@ void refresh_status(THD *thd) /* Reset the counters of all key caches (default and named). */ process_key_caches(reset_key_cache_counters); +#ifdef COMMUNITY_SERVER + flush_status_time= time((time_t*) 0); +#endif pthread_mutex_unlock(&LOCK_status); /* diff --git a/sql/mysqld_suffix.h b/sql/mysqld_suffix.h index b348f272db1..654d7cf88c1 100644 --- a/sql/mysqld_suffix.h +++ b/sql/mysqld_suffix.h @@ -13,8 +13,11 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* - Set MYSQL_SERVER_SUFFIX_STR +/** + @file + + Set MYSQL_SERVER_SUFFIX_STR. + The following code is quite ugly as there is no portable way to easily set a string to the value of a macro */ diff --git a/sql/net_serv.cc b/sql/net_serv.cc index 73eb340fbc0..ad653a2267d 100644 --- a/sql/net_serv.cc +++ b/sql/net_serv.cc @@ -13,15 +13,16 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* +/** + @file + This file is the net layer API for the MySQL client/server protocol, which is a tightly coupled, proprietary protocol owned by MySQL AB. + @note Any re-implementations of this protocol must also be under GPL unless one has got an license from MySQL AB stating otherwise. -*/ -/* - Write and read of logical packets to/from socket + Write and read of logical packets to/from socket. Writes are cached into net_buffer_length big packets. Read packets are reallocated dynamicly when reading big packets. @@ -111,7 +112,7 @@ extern void query_cache_insert(NET *net, const char *packet, ulong length); static my_bool net_write_buff(NET *net,const uchar *packet,ulong len); - /* Init with packet info */ +/** Init with packet info. */ my_bool my_net_init(NET *net, Vio* vio) { @@ -161,7 +162,7 @@ void net_end(NET *net) } -/* Realloc the packet buffer */ +/** Realloc the packet buffer. */ my_bool net_realloc(NET *net, size_t length) { @@ -203,20 +204,17 @@ my_bool net_realloc(NET *net, size_t length) } -/* - Check if there is any data to be read from the socket - - SYNOPSIS - net_data_is_ready() - sd socket descriptor +/** + Check if there is any data to be read from the socket. - DESCRIPTION - Check if there is any data to be read from the socket. + @param sd socket descriptor - RETURN VALUES - 0 No data to read - 1 Data or EOF to read - -1 Don't know if data is ready or not + @retval + 0 No data to read + @retval + 1 Data or EOF to read + @retval + -1 Don't know if data is ready or not */ #if !defined(EMBEDDED_LIBRARY) @@ -260,16 +258,10 @@ static int net_data_is_ready(my_socket sd) #endif /* EMBEDDED_LIBRARY */ -/* +/** Remove unwanted characters from connection - and check if disconnected + and check if disconnected. - SYNOPSIS - net_clear() - net NET handler - clear_buffer If <> 0, then clear all data from communication buffer - - DESCRIPTION Read from socket until there is nothing more to read. Discard what is read. @@ -280,6 +272,8 @@ static int net_data_is_ready(my_socket sd) a FIN packet), then select() considers a socket "ready to read", in the sense that there's EOF to read, but read() returns 0. + @param net NET handler + @param clear_buffer if <> 0, then clear all data from comm buff */ void net_clear(NET *net, my_bool clear_buffer) @@ -337,7 +331,7 @@ void net_clear(NET *net, my_bool clear_buffer) } - /* Flush write_buffer if not empty. */ +/** Flush write_buffer if not empty. */ my_bool net_flush(NET *net) { @@ -360,12 +354,13 @@ my_bool net_flush(NET *net) ** Write something to server/client buffer *****************************************************************************/ -/* - Write a logical packet with packet header +/** + Write a logical packet with packet header. + Format: Packet length (3 bytes), packet number(1 byte) When compression is used a 3 byte compression length is added - NOTE + @note If compression is used the original package is modified! */ @@ -402,19 +397,9 @@ my_net_write(NET *net,const uchar *packet,size_t len) return test(net_write_buff(net,packet,len)); } -/* +/** Send a command to the server. - SYNOPSIS - net_write_command() - net NET handler - command Command in MySQL server (enum enum_server_command) - header Header to write after command - head_len Length of header - packet Query or parameter to query - len Length of packet - - DESCRIPTION The reason for having both header and packet is so that libmysql can easy add a header to a special command (like prepared statements) without having to re-alloc the string. @@ -422,11 +407,20 @@ my_net_write(NET *net,const uchar *packet,size_t len) As the command is part of the first data packet, we have to do some data juggling to put the command in there, without having to create a new packet. + This function will split big packets into sub-packets if needed. (Each sub packet can only be 2^24 bytes) - RETURN VALUES + @param net NET handler + @param command Command in MySQL server (enum enum_server_command) + @param header Header to write after command + @param head_len Length of header + @param packet Query or parameter to query + @param len Length of packet + + @retval 0 ok + @retval 1 error */ @@ -470,33 +464,30 @@ net_write_command(NET *net,uchar command, net_write_buff(net, packet, len) || net_flush(net))); } -/* +/** Caching the data in a local buffer before sending it. - SYNOPSIS - net_write_buff() - net Network handler - packet Packet to send - len Length of packet - - DESCRIPTION - Fill up net->buffer and send it to the client when full. + Fill up net->buffer and send it to the client when full. If the rest of the to-be-sent-packet is bigger than buffer, send it in one big block (to avoid copying to internal buffer). If not, copy the rest of the data to the buffer and return without sending data. - NOTES - The cached buffer can be sent as it is with 'net_flush()'. + @param net Network handler + @param packet Packet to send + @param len Length of packet + @note + The cached buffer can be sent as it is with 'net_flush()'. In this code we have to be careful to not send a packet longer than MAX_PACKET_LENGTH to net_real_write() if we are using the compressed protocol as we store the length of the compressed packet in 3 bytes. - RETURN - 0 ok - 1 + @retval + 0 ok + @retval + 1 */ static my_bool @@ -549,9 +540,12 @@ net_write_buff(NET *net, const uchar *packet, ulong len) } -/* +/** Read and write one packet using timeouts. If needed, the packet is compressed before sending. + + @todo + - TODO is it needed to set this variable if we have no socket */ int @@ -725,18 +719,17 @@ static my_bool net_safe_read(NET *net, uchar *buff, size_t length, return 0; } -/* +/** Help function to clear the commuication buffer when we get a too big packet. - SYNOPSIS - my_net_skip_rest() - net Communication handle - remain Bytes to read - alarmed Parameter for thr_alarm() - alarm_buff Parameter for thr_alarm() + @param net Communication handle + @param remain Bytes to read + @param alarmed Parameter for thr_alarm() + @param alarm_buff Parameter for thr_alarm() - RETURN VALUES + @retval 0 Was able to read the whole packet + @retval 1 Got mailformed packet from client */ @@ -779,10 +772,13 @@ static my_bool my_net_skip_rest(NET *net, uint32 remain, thr_alarm_t *alarmed, #endif /* NO_ALARM */ -/* - Reads one packet to net->buff + net->where_b - Returns length of packet. Long packets are handled by my_net_read(). +/** + Reads one packet to net->buff + net->where_b. + Long packets are handled by my_net_read(). This function reallocates the net->buff buffer if necessary. + + @return + Returns length of packet. */ static ulong @@ -972,15 +968,18 @@ end: } -/* +/** Read a packet from the client/server and return it without the internal package header. + If the packet is the first packet of a multi-packet packet (which is indicated by the length of the packet = 0xffffff) then all sub packets are read and concatenated. + If the packet was compressed, its uncompressed and the length of the uncompressed packet is returned. + @return The function returns the length of the found packet or packet_error. net->read_pos points to the read data. */ diff --git a/sql/nt_servc.cc b/sql/nt_servc.cc index a04f284a3de..7ff06d5bdf5 100644 --- a/sql/nt_servc.cc +++ b/sql/nt_servc.cc @@ -1,8 +1,12 @@ -/* ------------------------------------------------------------------------ - Windows NT Service class library - Copyright Abandoned 1998 Irena Pancirov - Irnet Snc - This file is public domain and comes with NO WARRANTY of any kind - -------------------------------------------------------------------------- */ +/** + @file + + @brief + Windows NT Service class library. + + Copyright Abandoned 1998 Irena Pancirov - Irnet Snc + This file is public domain and comes with NO WARRANTY of any kind +*/ #include <windows.h> #include <process.h> #include <stdio.h> @@ -73,12 +77,13 @@ BOOL NTService::GetOS() } -/* ------------------------------------------------------------------------ - Init() Registers the main service thread with the service manager +/** + Registers the main service thread with the service manager. + + @param ServiceThread pointer to the main programs entry function + when the service is started +*/ - ServiceThread - pointer to the main programs entry function - when the service is started - -------------------------------------------------------------------------- */ long NTService::Init(LPCSTR szInternName,void *ServiceThread) { @@ -99,13 +104,15 @@ long NTService::Init(LPCSTR szInternName,void *ServiceThread) } -/* ------------------------------------------------------------------------ - Install() - Installs the service with Service manager +/** + Installs the service with Service manager. + nError values: - 0 success - 1 Can't open the Service manager - 2 Failed to create service - -------------------------------------------------------------------------- */ + - 0 success + - 1 Can't open the Service manager + - 2 Failed to create service. +*/ + BOOL NTService::Install(int startType, LPCSTR szInternName, LPCSTR szDisplayName, @@ -155,14 +162,16 @@ BOOL NTService::Install(int startType, LPCSTR szInternName, } -/* ------------------------------------------------------------------------ - Remove() - Removes the service +/** + Removes the service. + nError values: - 0 success - 1 Can't open the Service manager - 2 Failed to locate service - 3 Failed to delete service - -------------------------------------------------------------------------- */ + - 0 success + - 1 Can't open the Service manager + - 2 Failed to locate service + - 3 Failed to delete service. +*/ + BOOL NTService::Remove(LPCSTR szInternName) { @@ -199,10 +208,10 @@ BOOL NTService::Remove(LPCSTR szInternName) return ret_value; } -/* ------------------------------------------------------------------------ - Stop() - this function should be called before the app. exits to stop - the service - -------------------------------------------------------------------------- */ +/** + this function should be called before the app. exits to stop + the service +*/ void NTService::Stop(void) { SetStatus(SERVICE_STOP_PENDING,NO_ERROR, 0, 1, 60000); @@ -210,10 +219,11 @@ void NTService::Stop(void) SetStatus(SERVICE_STOPPED, NO_ERROR, 0, 1, 1000); } -/* ------------------------------------------------------------------------ - ServiceMain() - This is the function that is called from the - service manager to start the service - -------------------------------------------------------------------------- */ +/** + This is the function that is called from the + service manager to start the service. +*/ + void NTService::ServiceMain(DWORD argc, LPTSTR *argv) { @@ -264,9 +274,9 @@ error: return; } -/* ------------------------------------------------------------------------ - StartService() - starts the appliaction thread - -------------------------------------------------------------------------- */ +/** + starts the appliaction thread. +*/ BOOL NTService::StartService() { diff --git a/sql/nt_servc.h b/sql/nt_servc.h index a3c12569114..525f709388b 100644 --- a/sql/nt_servc.h +++ b/sql/nt_servc.h @@ -1,8 +1,12 @@ -/* ------------------------------------------------------------------------ - Windows NT Service class library - Copyright Abandoned 1998 Irena Pancirov - Irnet Snc - This file is public domain and comes with NO WARRANTY of any kind - -------------------------------------------------------------------------- */ +/** + @file + + @brief + Windows NT Service class library + + Copyright Abandoned 1998 Irena Pancirov - Irnet Snc + This file is public domain and comes with NO WARRANTY of any kind +*/ // main application thread typedef void (*THREAD_FC)(void *); @@ -13,7 +17,7 @@ class NTService NTService(); ~NTService(); - BOOL bOsNT; // true if OS is NT, false for Win95 + BOOL bOsNT; ///< true if OS is NT, false for Win95 //install optinos DWORD dwDesiredAccess; DWORD dwServiceType; diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc index 91786ff3f4b..42d36756845 100644 --- a/sql/opt_sum.cc +++ b/sql/opt_sum.cc @@ -14,7 +14,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* +/** + @file + Optimising of MIN(), MAX() and COUNT(*) queries without 'group by' clause by replacing the aggregate expression with a constant. @@ -22,6 +24,7 @@ types of queries are optimised (assuming the table handler supports the required methods) + @verbatim SELECT COUNT(*) FROM t1[,t2,t3,...] SELECT MIN(b) FROM t1 WHERE a=const SELECT MAX(c) FROM t1 WHERE a=const AND b=const @@ -29,6 +32,7 @@ SELECT MIN(b) FROM t1 WHERE a=const AND b>const SELECT MIN(b) FROM t1 WHERE a=const AND b BETWEEN const AND const SELECT MAX(b) FROM t1 WHERE a=const AND b BETWEEN const AND const + @endverbatim Instead of '<' one can use '<=', '>', '>=' and '=' as well. Instead of 'a=const' the condition 'a IS NULL' can be used. @@ -36,10 +40,11 @@ If all selected fields are replaced then we will also remove all involved tables and return the answer without any join. Thus, the following query will be replaced with a row of two constants: + @verbatim SELECT MAX(b), MIN(d) FROM t1,t2 WHERE a=const AND b<const AND d>const + @endverbatim (assuming a index for column d of table t2 is defined) - */ #include "mysql_priv.h" @@ -83,25 +88,25 @@ static ulonglong get_exact_record_count(TABLE_LIST *tables) } -/* +/** Substitutes constants for some COUNT(), MIN() and MAX() functions. - SYNOPSIS - opt_sum_query() - tables list of leaves of join table tree - all_fields All fields to be returned - conds WHERE clause + @param tables list of leaves of join table tree + @param all_fields All fields to be returned + @param conds WHERE clause - NOTE: + @note This function is only called for queries with sum functions and no GROUP BY part. - RETURN VALUES + @retval 0 no errors + @retval 1 if all items were resolved + @retval HA_ERR_KEY_NOT_FOUND on impossible conditions - OR an error number from my_base.h HA_ERR_... if a deadlock or a lock - wait timeout happens, for example + @retval + HA_ERR_... if a deadlock or a lock wait timeout happens, for example */ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds) @@ -475,19 +480,18 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds) } -/* - Test if the predicate compares a field with constants +/** + Test if the predicate compares a field with constants. - SYNOPSIS - simple_pred() - func_item Predicate item - args out: Here we store the field followed by constants - inv_order out: Is set to 1 if the predicate is of the form - 'const op field' + @param func_item Predicate item + @param[out] args Here we store the field followed by constants + @param[out] inv_order Is set to 1 if the predicate is of the form + 'const op field' - RETURN + @retval 0 func_item is a simple predicate: a field is compared with - constants + constants + @retval 1 Otherwise */ @@ -559,34 +563,33 @@ bool simple_pred(Item_func *func_item, Item **args, bool *inv_order) } -/* - Check whether a condition matches a key to get {MAX|MIN}(field): - - SYNOPSIS - matching_cond() - max_fl in: Set to 1 if we are optimising MAX() - ref in/out: Reference to the structure we store the key value - keyinfo in Reference to the key info - field_part in: Pointer to the key part for the field - cond in WHERE condition - key_part_used in/out: Map of matchings parts - range_fl in/out: Says whether including key will be used - prefix_len out: Length of common key part for the range - where MAX/MIN is searched for +/** + Check whether a condition matches a key to get {MAX|MIN}(field):. - DESCRIPTION For the index specified by the keyinfo parameter, index that contains field as its component (field_part), the function checks whether the condition cond is a conjunction and all its conjuncts referring to the columns of the same table as column field are one of the following forms: - f_i= const_i or const_i= f_i or f_i is null, - where f_i is part of the index + where f_i is part of the index - field {<|<=|>=|>|=} const or const {<|<=|>=|>|=} field - field between const1 and const2 - RETURN + @param[in] max_fl Set to 1 if we are optimising MAX() + @param[in,out] ref Reference to the structure we store the key + value + @param[in] keyinfo Reference to the key info + @param[in] field_part Pointer to the key part for the field + @param[in] cond WHERE condition + @param[in,out] key_part_used Map of matchings parts + @param[in,out] range_fl Says whether including key will be used + @param[out] prefix_len Length of common key part for the range + where MAX/MIN is searched for + + @retval 0 Index can't be used. + @retval 1 We can use index to get MIN/MAX value */ @@ -751,31 +754,21 @@ static bool matching_cond(bool max_fl, TABLE_REF *ref, KEY *keyinfo, } -/* +/** Check whether we can get value for {max|min}(field) by using a key. - SYNOPSIS - find_key_for_maxmin() - max_fl in: 0 for MIN(field) / 1 for MAX(field) - ref in/out Reference to the structure we store the key value - field in: Field used inside MIN() / MAX() - cond in: WHERE condition - range_fl out: Bit flags for how to search if key is ok - prefix_len out: Length of prefix for the search range - - DESCRIPTION - If where condition is not a conjunction of 0 or more conjuct the - function returns false, otherwise it checks whether there is an - index including field as its k-th component/part such that: - - 1. for each previous component f_i there is one and only one conjunct + If where-condition is not a conjunction of 0 or more conjuct the + function returns false, otherwise it checks whether there is an + index including field as its k-th component/part such that: + + -# for each previous component f_i there is one and only one conjunct of the form: f_i= const_i or const_i= f_i or f_i is null - 2. references to field occur only in conjucts of the form: + -# references to field occur only in conjucts of the form: field {<|<=|>=|>|=} const or const {<|<=|>=|>|=} field or field BETWEEN const1 AND const2 - 3. all references to the columns from the same table as column field + -# all references to the columns from the same table as column field occur only in conjucts mentioned above. - 4. each of k first components the index is not partial, i.e. is not + -# each of k first components the index is not partial, i.e. is not defined on a fixed length proper prefix of the field. If such an index exists the function through the ref parameter @@ -783,17 +776,26 @@ static bool matching_cond(bool max_fl, TABLE_REF *ref, KEY *keyinfo, the length of first (k-1) components of the key and flags saying how to apply the key for the search max/min value. (if we have a condition field = const, prefix_len contains the length - of the whole search key) + of the whole search key) + + @param[in] max_fl 0 for MIN(field) / 1 for MAX(field) + @param[in,out] ref Reference to the structure we store the key value + @param[in] field Field used inside MIN() / MAX() + @param[in] cond WHERE condition + @param[out] range_fl Bit flags for how to search if key is ok + @param[out] prefix_len Length of prefix for the search range - NOTE + @note This function may set table->key_read to 1, which must be reset after index is used! (This can only happen when function returns 1) - RETURN + @retval 0 Index can not be used to optimize MIN(field)/MAX(field) - 1 Can use key to optimize MIN()/MAX() - In this case ref, range_fl and prefix_len are updated -*/ + @retval + 1 Can use key to optimize MIN()/MAX(). + In this case ref, range_fl and prefix_len are updated +*/ + static bool find_key_for_maxmin(bool max_fl, TABLE_REF *ref, Field* field, COND *cond, @@ -886,20 +888,19 @@ static bool find_key_for_maxmin(bool max_fl, TABLE_REF *ref, } -/* - Check whether found key is in range specified by conditions +/** + Check whether found key is in range specified by conditions. - SYNOPSIS - reckey_in_range() - max_fl in: 0 for MIN(field) / 1 for MAX(field) - ref in: Reference to the key value and info - field in: Field used the MIN/MAX expression - cond in: WHERE condition - range_fl in: Says whether there is a condition to to be checked - prefix_len in: Length of the constant part of the key + @param[in] max_fl 0 for MIN(field) / 1 for MAX(field) + @param[in] ref Reference to the key value and info + @param[in] field Field used the MIN/MAX expression + @param[in] cond WHERE condition + @param[in] range_fl Says whether there is a condition to to be checked + @param[in] prefix_len Length of the constant part of the key - RETURN + @retval 0 ok + @retval 1 WHERE was not true for the found row */ @@ -914,16 +915,16 @@ static int reckey_in_range(bool max_fl, TABLE_REF *ref, Field* field, } -/* - Check whether {MAX|MIN}(field) is in range specified by conditions - SYNOPSIS - maxmin_in_range() - max_fl in: 0 for MIN(field) / 1 for MAX(field) - field in: Field used the MIN/MAX expression - cond in: WHERE condition +/** + Check whether {MAX|MIN}(field) is in range specified by conditions. - RETURN + @param[in] max_fl 0 for MIN(field) / 1 for MAX(field) + @param[in] field Field used the MIN/MAX expression + @param[in] cond WHERE condition + + @retval 0 ok + @retval 1 WHERE was not true for the found row */ diff --git a/sql/parse_file.cc b/sql/parse_file.cc index 19fb11ac0cc..1f0a45edd5e 100644 --- a/sql/parse_file.cc +++ b/sql/parse_file.cc @@ -13,7 +13,12 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -// Text .frm files management routines +/** + @file + + @brief + Text .frm files management routines +*/ #include "mysql_priv.h" #include <errno.h> @@ -22,17 +27,16 @@ #include <my_dir.h> -/* - write string with escaping +/** + Write string with escaping. - SYNOPSIS - write_escaped_string() - file - IO_CACHE for record - val_s - string for writing + @param file IO_CACHE for record + @param val_s string for writing - RETURN - FALSE - OK - TRUE - error + @retval + FALSE OK + @retval + TRUE error */ static my_bool @@ -77,21 +81,21 @@ write_escaped_string(IO_CACHE *file, LEX_STRING *val_s) } -/* - write parameter value to IO_CACHE +/** + Write parameter value to IO_CACHE. - SYNOPSIS - write_parameter() - file pointer to IO_CACHE structure for writing - base pointer to data structure - parameter pointer to parameter descriptor - old_version for returning back old version number value + @param file pointer to IO_CACHE structure for writing + @param base pointer to data structure + @param parameter pointer to parameter descriptor + @param old_version for returning back old version number value - RETURN - FALSE - OK - TRUE - error + @retval + FALSE OK + @retval + TRUE error */ + static my_bool write_parameter(IO_CACHE *file, uchar* base, File_option *parameter, ulonglong *old_version) @@ -191,24 +195,24 @@ write_parameter(IO_CACHE *file, uchar* base, File_option *parameter, } -/* - write new .frm +/** + Write new .frm. - SYNOPSIS - sql_create_definition_file() - dir directory where put .frm - file .frm file name - type .frm type string (VIEW, TABLE) - base base address for parameter reading (structure like - TABLE) - parameters parameters description - max_versions number of versions to save + @param dir directory where put .frm + @param file_name .frm file name + @param type .frm type string (VIEW, TABLE) + @param base base address for parameter reading (structure like + TABLE) + @param parameters parameters description + @param max_versions number of versions to save - RETURN - FALSE - OK - TRUE - error + @retval + FALSE OK + @retval + TRUE error */ + my_bool sql_create_definition_file(const LEX_STRING *dir, const LEX_STRING *file_name, const LEX_STRING *type, @@ -345,21 +349,19 @@ err_w_file: DBUG_RETURN(TRUE); } -/* - Renames a frm file (including backups) in same schema - - SYNOPSIS - rename_in_schema_file - schema name of given schema - old_name original file name - new_name new file name - revision revision number - num_view_backups number of backups +/** + Renames a frm file (including backups) in same schema. - RETURN - 0 - OK - 1 - Error (only if renaming of frm failed) + @param schema name of given schema + @param old_name original file name + @param new_name new file name + @param revision revision number + @param num_view_backups number of backups + @retval + 0 OK + @retval + 1 Error (only if renaming of frm failed) */ my_bool rename_in_schema_file(const char *schema, const char *old_name, const char *new_name, ulonglong revision, @@ -401,21 +403,20 @@ my_bool rename_in_schema_file(const char *schema, const char *old_name, return 0; } -/* - Prepare frm to parse (read to memory) +/** + Prepare frm to parse (read to memory). + + @param file_name path & filename to .frm file + @param mem_root MEM_ROOT for buffer allocation + @param bad_format_errors send errors on bad content - SYNOPSIS - sql_parse_prepare() - file_name - path & filename to .frm file - mem_root - MEM_ROOT for buffer allocation - bad_format_errors - send errors on bad content + @note + returned pointer + 1 will be type of .frm - RETURN + @return 0 - error + @return parser object - - NOTE - returned pointer + 1 will be type of .frm */ File_parser * @@ -506,22 +507,22 @@ frm_error: } -/* - parse LEX_STRING +/** + parse LEX_STRING. - SYNOPSIS - parse_string() - ptr - pointer on string beginning - end - pointer on symbol after parsed string end (still owned - by buffer and can be accessed - mem_root - MEM_ROOT for parameter allocation - str - pointer on string, where results should be stored + @param ptr pointer on string beginning + @param end pointer on symbol after parsed string end (still owned + by buffer and can be accessed + @param mem_root MEM_ROOT for parameter allocation + @param str pointer on string, where results should be stored - RETURN - 0 - error - # - pointer on symbol after string + @retval + 0 error + @retval + \# pointer on symbol after string */ + static char * parse_string(char *ptr, char *end, MEM_ROOT *mem_root, LEX_STRING *str) { @@ -539,18 +540,17 @@ parse_string(char *ptr, char *end, MEM_ROOT *mem_root, LEX_STRING *str) } -/* - read escaped string from ptr to eol in already allocated str +/** + read escaped string from ptr to eol in already allocated str. - SYNOPSIS - read_escaped_string() - ptr - pointer on string beginning - eol - pointer on character after end of string - str - target string + @param ptr pointer on string beginning + @param eol pointer on character after end of string + @param str target string - RETURN - FALSE - OK - TRUE - error + @retval + FALSE OK + @retval + TRUE error */ my_bool @@ -598,22 +598,22 @@ read_escaped_string(char *ptr, char *eol, LEX_STRING *str) } -/* - parse \n delimited escaped string +/** + parse \\n delimited escaped string. - SYNOPSIS - parse_escaped_string() - ptr - pointer on string beginning - end - pointer on symbol after parsed string end (still owned - by buffer and can be accessed - mem_root - MEM_ROOT for parameter allocation - str - pointer on string, where results should be stored + @param ptr pointer on string beginning + @param end pointer on symbol after parsed string end (still owned + by buffer and can be accessed + @param mem_root MEM_ROOT for parameter allocation + @param str pointer on string, where results should be stored - RETURN - 0 - error - # - pointer on symbol after string + @retval + 0 error + @retval + \# pointer on symbol after string */ + char * parse_escaped_string(char *ptr, char *end, MEM_ROOT *mem_root, LEX_STRING *str) { @@ -628,20 +628,19 @@ parse_escaped_string(char *ptr, char *end, MEM_ROOT *mem_root, LEX_STRING *str) } -/* - parse '' delimited escaped string +/** + parse '' delimited escaped string. - SYNOPSIS - parse_quoted_escaped_string() - ptr - pointer on string beginning - end - pointer on symbol after parsed string end (still owned - by buffer and can be accessed - mem_root - MEM_ROOT for parameter allocation - str - pointer on string, where results should be stored + @param ptr pointer on string beginning + @param end pointer on symbol after parsed string end (still owned + by buffer and can be accessed + @param mem_root MEM_ROOT for parameter allocation + @param str pointer on string, where results should be stored - RETURN - 0 - error - # - pointer on symbol after string + @retval + 0 error + @retval + \# pointer on symbol after string */ static char * @@ -673,18 +672,16 @@ parse_quoted_escaped_string(char *ptr, char *end, } -/* +/** Parser for FILE_OPTIONS_ULLLIST type value. - SYNOPSIS - get_file_options_ulllist() - ptr [in/out] pointer to parameter - end [in] end of the configuration - line [in] pointer to the line begining - base [in] base address for parameter writing (structure - like TABLE) - parameter [in] description - mem_root [in] MEM_ROOT for parameters allocation + @param[in,out] ptr pointer to parameter + @param[in] end end of the configuration + @param[in] line pointer to the line begining + @param[in] base base address for parameter writing (structure + like TABLE) + @param[in] parameter description + @param[in] mem_root MEM_ROOT for parameters allocation */ bool get_file_options_ulllist(char *&ptr, char *end, char *line, @@ -728,28 +725,28 @@ nlist_err: } -/* - parse parameters - - SYNOPSIS - File_parser::parse() - base base address for parameter writing (structure like - TABLE) - mem_root MEM_ROOT for parameters allocation - parameters parameters description - required number of parameters in the above list. If the file - contains more parameters than "required", they will - be ignored. If the file contains less parameters - then "required", non-existing parameters will - remain their values. - hook hook called for unknown keys - hook_data some data specific for the hook - - RETURN - FALSE - OK - TRUE - error +/** + parse parameters. + + @param base base address for parameter writing (structure like + TABLE) + @param mem_root MEM_ROOT for parameters allocation + @param parameters parameters description + @param required number of required parameters in above list. If the file + contains more parameters than "required", they will + be ignored. If the file contains less parameters + then "required", non-existing parameters will + remain their values. + @param hook hook called for unknown keys + @param hook_data some data specific for the hook + + @retval + FALSE OK + @retval + TRUE error */ + my_bool File_parser::parse(uchar* base, MEM_ROOT *mem_root, struct File_option *parameters, uint required, @@ -935,26 +932,25 @@ list_err: } -/* - Dummy unknown key hook +/** + Dummy unknown key hook. - SYNOPSIS - File_parser_dummy_hook::process_unknown_string() - unknown_key [in/out] reference on the line with unknown - parameter and the parsing point - base [in] base address for parameter writing (structure like - TABLE) - mem_root [in] MEM_ROOT for parameters allocation - end [in] the end of the configuration + @param[in,out] unknown_key reference on the line with unknown + parameter and the parsing point + @param[in] base base address for parameter writing + (structure like TABLE) + @param[in] mem_root MEM_ROOT for parameters allocation + @param[in] end the end of the configuration - NOTE + @note This hook used to catch no longer supported keys and process them for backward compatibility, but it will not slow down processing of modern format files. This hook does nothing except debug output. - RETURN + @retval FALSE OK + @retval TRUE Error */ diff --git a/sql/parse_file.h b/sql/parse_file.h index 91700959681..30c902478b8 100644 --- a/sql/parse_file.h +++ b/sql/parse_file.h @@ -20,27 +20,27 @@ #define PARSE_FILE_TIMESTAMPLENGTH 19 enum file_opt_type { - FILE_OPTIONS_STRING, /* String (LEX_STRING) */ - FILE_OPTIONS_ESTRING, /* Escaped string (LEX_STRING) */ - FILE_OPTIONS_ULONGLONG, /* ulonglong parameter (ulonglong) */ - FILE_OPTIONS_REV, /* Revision version number (ulonglong) */ - FILE_OPTIONS_TIMESTAMP, /* timestamp (LEX_STRING have to be + FILE_OPTIONS_STRING, /**< String (LEX_STRING) */ + FILE_OPTIONS_ESTRING, /**< Escaped string (LEX_STRING) */ + FILE_OPTIONS_ULONGLONG, /**< ulonglong parameter (ulonglong) */ + FILE_OPTIONS_REV, /**< Revision version number (ulonglong) */ + FILE_OPTIONS_TIMESTAMP, /**< timestamp (LEX_STRING have to be allocated with length 20 (19+1) */ - FILE_OPTIONS_STRLIST, /* list of escaped strings + FILE_OPTIONS_STRLIST, /**< list of escaped strings (List<LEX_STRING>) */ - FILE_OPTIONS_ULLLIST /* list of ulonglong values + FILE_OPTIONS_ULLLIST /**< list of ulonglong values (List<ulonglong>) */ }; struct File_option { - LEX_STRING name; /* Name of the option */ - int offset; /* offset to base address of value */ - file_opt_type type; /* Option type */ + LEX_STRING name; /**< Name of the option */ + int offset; /**< offset to base address of value */ + file_opt_type type; /**< Option type */ }; -/* +/** This hook used to catch no longer supported keys and process them for backward compatibility. */ @@ -55,7 +55,7 @@ public: }; -/* Dummy hook for parsers which do not need hook for unknown keys */ +/** Dummy hook for parsers which do not need hook for unknown keys. */ class File_parser_dummy_hook: public Unknown_key_hook { diff --git a/sql/procedure.cc b/sql/procedure.cc index bbfabc46608..c993ba976ac 100644 --- a/sql/procedure.cc +++ b/sql/procedure.cc @@ -68,10 +68,13 @@ my_decimal *Item_proc_real::val_decimal(my_decimal *decimal_value) } -/***************************************************************************** -** Setup handling of procedure -** Return 0 if everything is ok -*****************************************************************************/ +/** + Setup handling of procedure. + + @return + Return 0 if everything is ok +*/ + Procedure * setup_procedure(THD *thd,ORDER *param,select_result *result, diff --git a/sql/procedure.h b/sql/procedure.h index 6a731766046..4578fcb87f1 100644 --- a/sql/procedure.h +++ b/sql/procedure.h @@ -20,8 +20,8 @@ #pragma interface /* gcc class implementation */ #endif -#define PROC_NO_SORT 1 /* Bits in flags */ -#define PROC_GROUP 2 /* proc must have group */ +#define PROC_NO_SORT 1 /**< Bits in flags */ +#define PROC_GROUP 2 /**< proc must have group */ /* Procedure items used by procedures to store values for send_fields */ diff --git a/sql/protocol.cc b/sql/protocol.cc index 420912b0b63..9e1b3c65538 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -13,8 +13,10 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* - Low level functions for storing data to be send to the MySQL client +/** + @file + + Low level functions for storing data to be send to the MySQL client. The actual communction is handled by the net_xxx functions in net_serv.cc */ @@ -28,12 +30,8 @@ static const unsigned int PACKET_BUFFER_EXTRA_ALLOC= 1024; /* Declared non-static only because of the embedded library. */ void net_send_error_packet(THD *thd, uint sql_errno, const char *err); -void -net_send_ok(THD *thd, - uint server_status, uint total_warn_count, - ha_rows affected_rows, ulonglong id, const char *message); -void -net_send_eof(THD *thd, uint server_status, uint total_warn_count); +void net_send_ok(THD *, uint, uint, ha_rows, ulonglong, const char *); +void net_send_eof(THD *thd, uint server_status, uint total_warn_count); #ifndef EMBEDDED_LIBRARY static void write_eof_packet(THD *thd, NET *net, uint server_status, uint total_warn_count); @@ -60,17 +58,18 @@ bool Protocol_binary::net_store_data(const uchar *from, size_t length) } -/* - Send a error string to client +/** + Send a error string to client. + + Design note: - Design note: + net_printf_error and net_send_error are low-level functions + that shall be used only when a new connection is being + established or at server startup. - net_send_error is a low-level functions - that shall be used only when a new connection is being - established or at server startup. - For SIGNAL/RESIGNAL and GET DIAGNOSTICS functionality it's - critical that every error that can be intercepted is issued in one - place only, my_message_sql. + For SIGNAL/RESIGNAL and GET DIAGNOSTICS functionality it's + critical that every error that can be intercepted is issued in one + place only, my_message_sql. */ void net_send_error(THD *thd, uint sql_errno, const char *err) { @@ -98,30 +97,28 @@ void net_send_error(THD *thd, uint sql_errno, const char *err) DBUG_VOID_RETURN; } - -/* +/** Return ok to the client. - SYNOPSIS - send_ok() - thd Thread handler - affected_rows Number of rows changed by statement - id Auto_increment id for first row (if used) - message Message to send to the client (Used by mysql_status) - - DESCRIPTION - The ok packet has the following structure - - 0 Marker (1 byte) - affected_rows Stored in 1-9 bytes - id Stored in 1-9 bytes - server_status Copy of thd->server_status; Can be used by client - to check if we are inside an transaction - New in 4.0 protocol - warning_count Stored in 2 bytes; New in 4.1 protocol - message Stored as packed length (1-9 bytes) + message - Is not stored if no message -*/ + The ok packet has the following structure: + + - 0 : Marker (1 byte) + - affected_rows : Stored in 1-9 bytes + - id : Stored in 1-9 bytes + - server_status : Copy of thd->server_status; Can be used by client + to check if we are inside an transaction. + New in 4.0 protocol + - warning_count : Stored in 2 bytes; New in 4.1 protocol + - message : Stored as packed length (1-9 bytes) + message. + Is not stored if no message. + + If net->no_send_ok return without sending packet. + + @param thd Thread handler + @param affected_rows Number of rows changed by statement + @param id Auto_increment id for first row (if used) + @param message Message to send to the client (Used by mysql_status) +*/ #ifndef EMBEDDED_LIBRARY void @@ -178,26 +175,23 @@ net_send_ok(THD *thd, static uchar eof_buff[1]= { (uchar) 254 }; /* Marker for end of fields */ -/* - Send eof (= end of result set) to the client +/** + Send eof (= end of result set) to the client. - SYNOPSIS - net_send_eof() - thd Thread handler - no_flush Set to 1 if there will be more data to the client, - like in send_fields(). + The eof packet has the following structure: - DESCRIPTION - The eof packet has the following structure + - 254 : Marker (1 byte) + - warning_count : Stored in 2 bytes; New in 4.1 protocol + - status_flag : Stored in 2 bytes; + For flags like SERVER_MORE_RESULTS_EXISTS. - 254 Marker (1 byte) - warning_count Stored in 2 bytes; New in 4.1 protocol - status_flag Stored in 2 bytes; - For flags like SERVER_MORE_RESULTS_EXISTS + Note that the warning count will not be sent if 'no_flush' is set as + we don't want to report the warning count until all data is sent to the + client. - Note that the warning count will not be sent if 'no_flush' is set as - we don't want to report the warning count until all data is sent to the - client. + @param thd Thread handler + @param no_flush Set to 1 if there will be more data to the client, + like in send_fields(). */ void @@ -218,7 +212,7 @@ net_send_eof(THD *thd, uint server_status, uint total_warn_count) } -/* +/** Format EOF packet according to the current protocol and write it to the network output buffer. */ @@ -251,14 +245,14 @@ static void write_eof_packet(THD *thd, NET *net, VOID(my_net_write(net, eof_buff, 1)); } -/* - Please client to send scrambled_password in old format. - SYNOPSYS - send_old_password_request() - thd thread handle +/** + Please client to send scrambled_password in old format. - RETURN VALUE + @param thd thread handle + + @retval 0 ok + @retval !0 error */ @@ -316,14 +310,15 @@ void net_send_error_packet(THD *thd, uint sql_errno, const char *err) #endif /* EMBEDDED_LIBRARY */ -/* +/** Faster net_store_length when we know that length is less than 65536. We keep a separate version for that range because it's widely used in libmysql. + uint is used as agrument type because of MySQL type conventions: - uint for 0..65536 - ulong for 0..4294967296 - ulonglong for bigger numbers. + - uint for 0..65536 + - ulong for 0..4294967296 + - ulonglong for bigger numbers. */ static uchar *net_store_length_fast(uchar *packet, uint length) @@ -497,27 +492,26 @@ bool Protocol::flush() #endif } -/* +#ifndef EMBEDDED_LIBRARY + +/** Send name and type of result to client. - SYNOPSIS - send_fields() - THD Thread data object - list List of items to send to client - flag Bit mask with the following functions: - 1 send number of rows - 2 send default values - 4 don't write eof packet + Sum fields has table name empty and field_name. - DESCRIPTION - Sum fields has table name empty and field_name. + @param THD Thread data object + @param list List of items to send to client + @param flag Bit mask with the following functions: + - 1 send number of rows + - 2 send default values + - 4 don't write eof packet - RETURN VALUES + @retval 0 ok - 1 Error (Note that in this case the error is not sent to the client) + @retval + 1 Error (Note that in this case the error is not sent to the + client) */ - -#ifndef EMBEDDED_LIBRARY bool Protocol::send_fields(List<Item> *list, uint flags) { List_iterator_fast<Item> it(*list); @@ -678,18 +672,17 @@ bool Protocol::write() #endif /* EMBEDDED_LIBRARY */ -/* - Send \0 end terminated string +/** + Send \\0 end terminated string. - SYNOPSIS - store() - from NullS or \0 terminated string + @param from NullS or \\0 terminated string - NOTES + @note In most cases one should use store(from, length) instead of this function - RETURN VALUES + @retval 0 ok + @retval 1 error */ @@ -702,8 +695,8 @@ bool Protocol::store(const char *from, CHARSET_INFO *cs) } -/* - Send a set of strings as one long string with ',' in between +/** + Send a set of strings as one long string with ',' in between. */ bool Protocol::store(I_List<i_string>* str_list) @@ -755,7 +748,7 @@ bool Protocol_text::store_null() #endif -/* +/** Auxilary function to convert string to the given character set and store in network buffer. */ @@ -932,13 +925,12 @@ bool Protocol_text::store(Field *field) } -/* - TODO: - Second_part format ("%06") needs to change when - we support 0-6 decimals for time. +/** + @todo + Second_part format ("%06") needs to change when + we support 0-6 decimals for time. */ - bool Protocol_text::store(MYSQL_TIME *tm) { #ifndef DBUG_OFF @@ -976,10 +968,10 @@ bool Protocol_text::store_date(MYSQL_TIME *tm) } -/* - TODO: - Second_part format ("%06") needs to change when - we support 0-6 decimals for time. +/** + @todo + Second_part format ("%06") needs to change when + we support 0-6 decimals for time. */ bool Protocol_text::store_time(MYSQL_TIME *tm) diff --git a/sql/protocol.h b/sql/protocol.h index cd58ec93bbb..a4770e9b6e3 100644 --- a/sql/protocol.h +++ b/sql/protocol.h @@ -111,7 +111,7 @@ public: }; -/* Class used for the old (MySQL 4.0 protocol) */ +/** Class used for the old (MySQL 4.0 protocol). */ class Protocol_text :public Protocol { diff --git a/sql/records.cc b/sql/records.cc index 349cc4a8329..cfcaf9df8e6 100644 --- a/sql/records.cc +++ b/sql/records.cc @@ -14,7 +14,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* Functions for easy reading of records, possible through a cache */ +/** + @file + + @brief + Functions for easy reading of records, possible through a cache +*/ #include "mysql_priv.h" @@ -31,25 +36,20 @@ static int rr_index_first(READ_RECORD *info); static int rr_index(READ_RECORD *info); -/* - Initialize READ_RECORD structure to perform full index scan - - SYNOPSIS - init_read_record_idx() - info READ_RECORD structure to initialize. - thd Thread handle - table Table to be accessed - print_error If true, call table->file->print_error() if an error - occurs (except for end-of-records error) - idx index to scan - - DESCRIPTION - Initialize READ_RECORD structure to perform full index scan (in forward - direction) using read_record.read_record() interface. - +/** + Initialize READ_RECORD structure to perform full index scan (in forward + direction) using read_record.read_record() interface. + This function has been added at late stage and is used only by UPDATE/DELETE. Other statements perform index scans using join_read_first/next functions. + + @param info READ_RECORD structure to initialize. + @param thd Thread handle + @param table Table to be accessed + @param print_error If true, call table->file->print_error() if an error + occurs (except for end-of-records error) + @param idx index to scan */ void init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table, @@ -286,7 +286,7 @@ static int rr_handle_error(READ_RECORD *info, int error) } - /* Read a record from head-database */ +/** Read a record from head-database. */ static int rr_quick(READ_RECORD *info) { @@ -308,20 +308,19 @@ static int rr_quick(READ_RECORD *info) } -/* - Reads first row in an index scan +/** + Reads first row in an index scan. - SYNOPSIS - rr_index_first() - info Scan info - - RETURN + @param info Scan info + + @retval 0 Ok - -1 End of records - 1 Error + @retval + -1 End of records + @retval + 1 Error */ - static int rr_index_first(READ_RECORD *info) { int tmp= info->file->index_first(info->record); @@ -332,24 +331,22 @@ static int rr_index_first(READ_RECORD *info) } -/* - Reads index sequentially after first row +/** + Reads index sequentially after first row. - SYNOPSIS - rr_index() - info Scan info - - DESCRIPTION - Read the next index record (in forward direction) and translate return - value. - - RETURN + Read the next index record (in forward direction) and translate return + value. + + @param info Scan info + + @retval 0 Ok - -1 End of records - 1 Error + @retval + -1 End of records + @retval + 1 Error */ - static int rr_index(READ_RECORD *info) { int tmp= info->file->index_next(info->record); @@ -403,22 +400,20 @@ static int rr_from_tempfile(READ_RECORD *info) } /* rr_from_tempfile */ -/* - Read a result set record from a temporary file after sorting +/** + Read a result set record from a temporary file after sorting. - SYNOPSIS - rr_unpack_from_tempfile() - info Reference to the context including record descriptors + The function first reads the next sorted record from the temporary file. + into a buffer. If a success it calls a callback function that unpacks + the fields values use in the result set from this buffer into their + positions in the regular record buffer. - DESCRIPTION - The function first reads the next sorted record from the temporary file. - into a buffer. If a success it calls a callback function that unpacks - the fields values use in the result set from this buffer into their - positions in the regular record buffer. + @param info Reference to the context including record descriptors - RETURN - 0 - Record successfully read. - -1 - There is no record to be read anymore. + @retval + 0 Record successfully read. + @retval + -1 There is no record to be read anymore. */ static int rr_unpack_from_tempfile(READ_RECORD *info) @@ -456,22 +451,20 @@ static int rr_from_pointers(READ_RECORD *info) return tmp; } -/* - Read a result set record from a buffer after sorting +/** + Read a result set record from a buffer after sorting. - SYNOPSIS - rr_unpack_from_buffer() - info Reference to the context including record descriptors + The function first reads the next sorted record from the sort buffer. + If a success it calls a callback function that unpacks + the fields values use in the result set from this buffer into their + positions in the regular record buffer. - DESCRIPTION - The function first reads the next sorted record from the sort buffer. - If a success it calls a callback function that unpacks - the fields values use in the result set from this buffer into their - positions in the regular record buffer. + @param info Reference to the context including record descriptors - RETURN - 0 - Record successfully read. - -1 - There is no record to be read anymore. + @retval + 0 Record successfully read. + @retval + -1 There is no record to be read anymore. */ static int rr_unpack_from_buffer(READ_RECORD *info) diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc index 69f4df723b7..589ee8b2605 100644 --- a/sql/repl_failsafe.cc +++ b/sql/repl_failsafe.cc @@ -13,6 +13,16 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/** + @file + + All of the functions defined in this file which are not used (the ones to + handle failsafe) are not used; their code has not been updated for more + than one year now so should be considered as BADLY BROKEN. Do not enable + it. The used functions (to handle LOAD DATA FROM MASTER, plus some small + functions like register_slave()) are working. +*/ + #include "mysql_priv.h" #ifdef HAVE_REPLICATION @@ -91,7 +101,7 @@ static int init_failsafe_rpl_thread(THD* thd) if (thd->variables.max_join_size == HA_POS_ERROR) thd->options|= OPTION_BIG_SELECTS; - thd->proc_info="Thread initialized"; + thd_proc_info(thd, "Thread initialized"); thd->version=refresh_version; thd->set_time(); DBUG_RETURN(0); @@ -144,12 +154,13 @@ void unregister_slave(THD* thd, bool only_mine, bool need_mutex) } -/* - Register slave in 'slave_list' hash table +/** + Register slave in 'slave_list' hash table. - RETURN VALUES - 0 ok - 1 Error. Error message sent to client + @return + 0 ok + @return + 1 Error. Error message sent to client */ int register_slave(THD* thd, uchar* packet, uint packet_length) @@ -252,7 +263,8 @@ static int find_target_pos(LEX_MASTER_INFO *mi, IO_CACHE *log, char *errmsg) /* Impossible */ } -/* +/** + @details Before 4.0.15 we had a member of THD called log_pos, it was meant for failsafe replication code in repl_failsafe.cc which is disabled until it is reworked. Event's log_pos used to be preserved through @@ -388,8 +400,8 @@ err: } -/* - Caller must delete result when done +/** + Caller must delete result when done. */ static Slave_log_event* find_slave_event(IO_CACHE* log, @@ -428,9 +440,11 @@ static Slave_log_event* find_slave_event(IO_CACHE* log, return (Slave_log_event*)ev; } -/* - This function is broken now. See comment for translate_master(). - */ +/** + This function is broken now. + + @seealso translate_master() +*/ bool show_new_master(THD* thd) { @@ -466,20 +480,19 @@ bool show_new_master(THD* thd) } } -/* +/** Asks the master for the list of its other connected slaves. - This is for failsafe replication: + + This is for failsafe replication: in order for failsafe replication to work, the servers involved in replication must know of each other. We accomplish this by having each slave report to the master how to reach it, and on connection, each slave receives information about where the other slaves are. - SYNOPSIS - update_slave_list() - mysql pre-existing connection to the master - mi master info + @param mysql pre-existing connection to the master + @param mi master info - NOTES + @note mi is used only to give detailed error messages which include the hostname/port of the master, the username used by the slave to connect to the master. @@ -487,10 +500,11 @@ bool show_new_master(THD* thd) REPLICATION SLAVE privilege, it will pop in this function because SHOW SLAVE HOSTS will fail on the master. - RETURN VALUES + @retval 1 error + @retval 0 success - */ +*/ int update_slave_list(MYSQL* mysql, Master_info* mi) { @@ -599,7 +613,7 @@ pthread_handler_t handle_failsafe_rpl(void *arg) { bool break_req_chain = 0; pthread_cond_wait(&COND_rpl_status, &LOCK_rpl_status); - thd->proc_info="Processing request"; + thd_proc_info(thd, "Processing request"); while (!break_req_chain) { switch (rpl_status) { @@ -754,11 +768,16 @@ static int fetch_db_tables(THD *thd, MYSQL *mysql, const char *db, return 0; } -/* +/** Load all MyISAM tables from master to this slave. REQUIREMENTS - - No active transaction (flush_relay_log_info would not work in this case) + - No active transaction (flush_relay_log_info would not work in this case). + + @todo + - add special option, not enabled + by default, to allow inclusion of mysql database into load + data from master */ bool load_master_data(THD* thd) @@ -949,7 +968,7 @@ bool load_master_data(THD* thd) goto err; } } - thd->proc_info="purging old relay logs"; + thd_proc_info(thd, "purging old relay logs"); if (purge_relay_logs(&active_mi->rli,thd, 0 /* not only reset, but also reinit */, &errmsg)) @@ -976,7 +995,7 @@ bool load_master_data(THD* thd) flush_relay_log_info(&active_mi->rli); pthread_cond_broadcast(&active_mi->rli.data_cond); pthread_mutex_unlock(&active_mi->rli.data_lock); - thd->proc_info = "starting slave"; + thd_proc_info(thd, "starting slave"); if (restart_thread_mask) { error=start_slave_threads(0 /* mutex not needed */, @@ -988,7 +1007,7 @@ bool load_master_data(THD* thd) err: unlock_slave_threads(active_mi); pthread_mutex_unlock(&LOCK_active_mi); - thd->proc_info = 0; + thd_proc_info(thd, 0); mysql_close(&mysql); // safe to call since we always do mysql_init() if (!error) diff --git a/sql/set_var.cc b/sql/set_var.cc index a01a0b49dbc..7dce5bf1a46 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -13,9 +13,13 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* +/** + @file + + @brief Handling of MySQL SQL variables + @details To add a new variable, one has to do the following: - Use one of the 'sys_var... classes from set_var.h or write a specific @@ -28,18 +32,19 @@ - Don't forget to initialize new fields in global_system_variables and max_system_variables! - NOTES: - - Be careful with var->save_result: sys_var::check() only updates + @todo + Add full support for the variable character_set (for 4.1) + + @todo + When updating myisam_delay_key_write, we should do a 'flush tables' + of all MyISAM tables to ensure that they are reopen with the + new attribute. + + @note + Be careful with var->save_result: sys_var::check() only updates ulonglong_value; so other members of the union are garbage then; to use them you must first assign a value to them (in specific ::check() for example). - - TODO: - - Add full support for the variable character_set (for 4.1) - - - When updating myisam_delay_key_write, we should do a 'flush tables' - of all MyISAM tables to ensure that they are reopen with the - new attribute. */ #ifdef USE_PRAGMA_IMPLEMENTATION @@ -120,8 +125,7 @@ static int check_max_delayed_threads(THD *thd, set_var *var); static void fix_thd_mem_root(THD *thd, enum_var_type type); static void fix_trans_mem_root(THD *thd, enum_var_type type); static void fix_server_id(THD *thd, enum_var_type type); -static ulonglong fix_unsigned(THD *thd, ulonglong num, - const struct my_option *option_limits); +static ulonglong fix_unsigned(THD *, ulonglong, const struct my_option *); static bool get_unsigned(THD *thd, set_var *var); static void throw_bounds_warning(THD *thd, const char *name, ulonglong num); static KEY_CACHE *create_key_cache(const char *name, uint length); @@ -587,6 +591,13 @@ static sys_var_thd_bit sys_unique_checks(&vars, "unique_checks", 0, set_option_bit, OPTION_RELAXED_UNIQUE_CHECKS, 1); +#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) +static sys_var_thd_bit sys_profiling(&vars, "profiling", NULL, + set_option_bit, + ulonglong(OPTION_PROFILING)); +static sys_var_thd_ulong sys_profiling_history_size(&vars, "profiling_history_size", + &SV::profiling_history_size); +#endif /* Local state variables */ @@ -639,6 +650,7 @@ static sys_var_have_variable sys_have_ssl(&vars, "have_ssl", &have_ssl); static sys_var_have_plugin sys_have_partition_db(&vars, "have_partitioning", C_STRING_WITH_LEN("partition"), MYSQL_STORAGE_ENGINE_PLUGIN); static sys_var_have_variable sys_have_query_cache(&vars, "have_query_cache", &have_query_cache); +static sys_var_have_variable sys_have_community_features(&vars, "have_community_features", &have_community_features); static sys_var_have_variable sys_have_rtree_keys(&vars, "have_rtree_keys", &have_rtree_keys); static sys_var_have_variable sys_have_symlink(&vars, "have_symlink", &have_symlink); /* Global read-only variable describing server license */ @@ -828,9 +840,9 @@ static void sys_default_ftb_syntax(THD *thd, enum_var_type type) } -/* +/** If one sets the LOW_PRIORIY UPDATES flag, we also must change the - used lock type + used lock type. */ static void fix_low_priority_updates(THD *thd, enum_var_type type) @@ -852,8 +864,8 @@ fix_myisam_max_sort_file_size(THD *thd, enum_var_type type) (my_off_t) global_system_variables.myisam_max_sort_file_size; } -/* - Set the OPTION_BIG_SELECTS flag if max_join_size == HA_POS_ERROR +/** + Set the OPTION_BIG_SELECTS flag if max_join_size == HA_POS_ERROR. */ static void fix_max_join_size(THD *thd, enum_var_type type) @@ -868,7 +880,7 @@ static void fix_max_join_size(THD *thd, enum_var_type type) } -/* +/** Can't change the 'next' tx_isolation while we are already in a transaction */ @@ -884,7 +896,7 @@ static int check_tx_isolation(THD *thd, set_var *var) /* If one doesn't use the SESSION modifier, the isolation level - is only active for the next command + is only active for the next command. */ static void fix_tx_isolation(THD *thd, enum_var_type type) { @@ -1178,8 +1190,10 @@ bool sys_var_long_ptr_global::update(THD *thd, set_var *var) void sys_var_long_ptr_global::set_default(THD *thd, enum_var_type type) { + bool not_used; pthread_mutex_lock(guard); - *value= (ulong) option_limits->def_value; + *value= (ulong) getopt_ull_limit_value((ulong) option_limits->def_value, + option_limits, ¬_used); pthread_mutex_unlock(guard); } @@ -1199,8 +1213,10 @@ bool sys_var_ulonglong_ptr::update(THD *thd, set_var *var) void sys_var_ulonglong_ptr::set_default(THD *thd, enum_var_type type) { + bool not_used; pthread_mutex_lock(&LOCK_global_system_variables); - *value= (ulonglong) option_limits->def_value; + *value= getopt_ull_limit_value((ulonglong) option_limits->def_value, + option_limits, ¬_used); pthread_mutex_unlock(&LOCK_global_system_variables); } @@ -1277,8 +1293,11 @@ void sys_var_thd_ulong::set_default(THD *thd, enum_var_type type) { if (type == OPT_GLOBAL) { + bool not_used; /* We will not come here if option_limits is not set */ - global_system_variables.*offset= (ulong) option_limits->def_value; + global_system_variables.*offset= + (ulong) getopt_ull_limit_value((ulong) option_limits->def_value, + option_limits, ¬_used); } else thd->variables.*offset= global_system_variables.*offset; @@ -1321,9 +1340,12 @@ void sys_var_thd_ha_rows::set_default(THD *thd, enum_var_type type) { if (type == OPT_GLOBAL) { + bool not_used; /* We will not come here if option_limits is not set */ pthread_mutex_lock(&LOCK_global_system_variables); - global_system_variables.*offset= (ha_rows) option_limits->def_value; + global_system_variables.*offset= + (ha_rows) getopt_ull_limit_value((ha_rows) option_limits->def_value, + option_limits, ¬_used); pthread_mutex_unlock(&LOCK_global_system_variables); } else @@ -1370,8 +1392,11 @@ void sys_var_thd_ulonglong::set_default(THD *thd, enum_var_type type) { if (type == OPT_GLOBAL) { + bool not_used; pthread_mutex_lock(&LOCK_global_system_variables); - global_system_variables.*offset= (ulonglong) option_limits->def_value; + global_system_variables.*offset= + getopt_ull_limit_value((ulonglong) option_limits->def_value, + option_limits, ¬_used); pthread_mutex_unlock(&LOCK_global_system_variables); } else @@ -1501,9 +1526,12 @@ err: } -/* - Return an Item for a variable. Used with @@[global.]variable_name - If type is not given, return local value if exists, else global +/** + Return an Item for a variable. + + Used with @@[global.]variable_name. + + If type is not given, return local value if exists, else global. */ Item *sys_var::item(THD *thd, enum_var_type var_type, LEX_STRING *base) @@ -1665,7 +1693,7 @@ uchar *sys_var_thd_bit::value_ptr(THD *thd, enum_var_type type, } -/* Update a date_time format variable based on given value */ +/** Update a date_time format variable based on given value. */ void sys_var_thd_date_time_format::update2(THD *thd, enum_var_type type, DATE_TIME_FORMAT *new_value) @@ -2097,6 +2125,12 @@ end: } +/** + @todo + Abort if some other thread is changing the key cache. + This should be changed so that we wait until the previous + assignment is done and then do the new assign +*/ bool sys_var_key_cache_long::update(THD *thd, set_var *var) { ulong tmp= (ulong) var->value->val_int(); @@ -2807,23 +2841,20 @@ static uchar *get_error_count(THD *thd) } -/* - Get the tmpdir that was specified or chosen by default +/** + Get the tmpdir that was specified or chosen by default. - SYNOPSIS - get_tmpdir() - thd thread handle + This is necessary because if the user does not specify a temporary + directory via the command line, one is chosen based on the environment + or system defaults. But we can't just always use mysql_tmpdir, because + that is actually a call to my_tmpdir() which cycles among possible + temporary directories. - DESCRIPTION - This is necessary because if the user does not specify a temporary - directory via the command line, one is chosen based on the environment - or system defaults. But we can't just always use mysql_tmpdir, because - that is actually a call to my_tmpdir() which cycles among possible - temporary directories. + @param thd thread handle - RETURN VALUES + @retval ptr pointer to NUL-terminated string - */ +*/ static uchar *get_tmpdir(THD *thd) { if (opt_mysql_tmpdir) @@ -2838,16 +2869,16 @@ static uchar *get_tmpdir(THD *thd) - Update loop ****************************************************************************/ -/* - Find variable name in option my_getopt structure used for command line args +/** + Find variable name in option my_getopt structure used for + command line args. - SYNOPSIS - find_option() - opt option structure array to search in - name variable name + @param opt option structure array to search in + @param name variable name - RETURN VALUES + @retval 0 Error + @retval ptr pointer to option structure */ @@ -2870,8 +2901,8 @@ static struct my_option *find_option(struct my_option *opt, const char *name) } -/* - Return variable name and length for hashing of variables +/** + Return variable name and length for hashing of variables. */ static uchar *get_sys_var_length(const sys_var *var, size_t *length, @@ -3074,17 +3105,17 @@ int mysql_append_static_vars(const SHOW_VAR *show_vars, uint count) } -/* - Find a user set-table variable +/** + Find a user set-table variable. - SYNOPSIS - intern_find_sys_var() - str Name of system variable to find - length Length of variable. zero means that we should use strlen() - on the variable + @param str Name of system variable to find + @param length Length of variable. zero means that we should use strlen() + on the variable + @param no_error Refuse to emit an error, even if one occurred. - RETURN VALUES + @retval pointer pointer to variable definitions + @retval 0 Unknown variable (error message is given) */ @@ -3105,25 +3136,23 @@ sys_var *intern_find_sys_var(const char *str, uint length, bool no_error) } -/* - Execute update of all variables - - SYNOPSIS +/** + Execute update of all variables. - sql_set - THD Thread id - set_var List of variables to update + First run a check of all variables that all updates will go ok. + If yes, then execute all updates, returning an error if any one failed. - DESCRIPTION - First run a check of all variables that all updates will go ok. - If yes, then execute all updates, returning an error if any one failed. + This should ensure that in all normal cases none all or variables are + updated. - This should ensure that in all normal cases none all or variables are - updated + @param THD Thread id + @param var_list List of variables to update - RETURN VALUE + @retval 0 ok + @retval 1 ERROR, message sent (normally no variables was updated) + @retval -1 ERROR, message not sent */ @@ -3152,20 +3181,19 @@ err: } -/* - Say if all variables set by a SET support the ONE_SHOT keyword (currently, - only character set and collation do; later timezones will). - - SYNOPSIS +/** + Say if all variables set by a SET support the ONE_SHOT keyword + (currently, only character set and collation do; later timezones + will). - not_all_support_one_shot - set_var List of variables to update + @param var_list List of variables to update - NOTES + @note It has a "not_" because it makes faster tests (no need to "!") - RETURN VALUE + @retval 0 all variables of the list support ONE_SHOT + @retval 1 at least one does not support ONE_SHOT */ @@ -3224,17 +3252,17 @@ int set_var::check(THD *thd) } -/* - Check variable, but without assigning value (used by PS) +/** + Check variable, but without assigning value (used by PS). - SYNOPSIS - set_var::light_check() - thd thread handler + @param thd thread handler - RETURN VALUE + @retval 0 ok + @retval 1 ERROR, message sent (normally no variables was updated) - -1 ERROR, message not sent + @retval + -1 ERROR, message not sent */ int set_var::light_check(THD *thd) { @@ -3281,17 +3309,17 @@ int set_var_user::check(THD *thd) } -/* - Check variable, but without assigning value (used by PS) +/** + Check variable, but without assigning value (used by PS). - SYNOPSIS - set_var_user::light_check() - thd thread handler + @param thd thread handler - RETURN VALUE + @retval 0 ok + @retval 1 ERROR, message sent (normally no variables was updated) - -1 ERROR, message not sent + @retval + -1 ERROR, message not sent */ int set_var_user::light_check(THD *thd) { @@ -3465,13 +3493,15 @@ bool sys_var_thd_table_type::update(THD *thd, set_var *var) Functions to handle sql_mode ****************************************************************************/ -/* - Make string representation of mode +/** + Make string representation of mode. - SYNOPSIS - thd in thread handler - val in sql_mode value - rep out pointer pointer to string with sql_mode representation + @param[in] thd thread handler + @param[in] val sql_mode value + @param[out] len pointer on length of string + + @return + pointer to string with sql_mode representation */ bool @@ -3542,7 +3572,7 @@ void fix_sql_mode_var(THD *thd, enum_var_type type) } } -/* Map database specific bits to function bits */ +/** Map database specific bits to function bits. */ ulong fix_sql_mode(ulong sql_mode) { diff --git a/sql/slave.cc b/sql/slave.cc index 7aa24319c86..45e3d4da090 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1004,8 +1004,8 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db, /* Create the table. We do not want to log the "create table" statement */ save_options = thd->options; - thd->options &= ~(ulong) (OPTION_BIN_LOG); - thd->proc_info = "Creating table from master dump"; + thd->options &= ~ (OPTION_BIN_LOG); + thd_proc_info(thd, "Creating table from master dump"); // save old db in case we are creating in a different database save_db = thd->db; save_db_length= thd->db_length; @@ -1020,8 +1020,8 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db, if (thd->is_slave_error) goto err; // mysql_parse took care of the error send + thd_proc_info(thd, "Opening master dump table"); thd->main_da.reset_diagnostics_area(); /* cleanup from CREATE_TABLE */ - thd->proc_info = "Opening master dump table"; /* Note: If this function starts to fail for MERGE tables, change the next two lines to these: @@ -1036,7 +1036,7 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db, } file = tables.table->file; - thd->proc_info = "Reading master dump table data"; + thd_proc_info(thd, "Reading master dump table data"); /* Copy the data file */ if (file->net_read_dump(net)) { @@ -1048,7 +1048,7 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db, check_opt.init(); check_opt.flags|= T_VERY_SILENT | T_CALC_CHECKSUM | T_QUICK; - thd->proc_info = "Rebuilding the index on master dump table"; + thd_proc_info(thd, "Rebuilding the index on master dump table"); /* We do not want repair() to spam us with messages just send them to the error log, and report the failure in case of @@ -1526,9 +1526,9 @@ static int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type) lex_start(thd); if (thd_type == SLAVE_THD_SQL) - thd->proc_info= "Waiting for the next event in relay log"; + thd_proc_info(thd, "Waiting for the next event in relay log"); else - thd->proc_info= "Waiting for master update"; + thd_proc_info(thd, "Waiting for master update"); thd->version=refresh_version; thd->set_time(); DBUG_RETURN(0); @@ -2164,7 +2164,7 @@ pthread_handler_t handle_slave_io(void *arg) goto err; } - thd->proc_info = "Connecting to master"; + thd_proc_info(thd, "Connecting to master"); // we can get killed during safe_connect if (!safe_connect(thd, mysql, mi)) { @@ -2191,7 +2191,7 @@ connected: // TODO: the assignment below should be under mutex (5.0) mi->slave_running= MYSQL_SLAVE_RUN_CONNECT; thd->slave_net = &mysql->net; - thd->proc_info = "Checking master version"; + thd_proc_info(thd, "Checking master version"); if (get_master_version_and_clock(mysql, mi)) goto err; @@ -2200,7 +2200,7 @@ connected: /* Register ourselves with the master. */ - thd->proc_info = "Registering slave on master"; + thd_proc_info(thd, "Registering slave on master"); if (register_slave_on_master(mysql, mi, &suppress_warnings)) { if (!check_io_slave_killed(thd, mi, "Slave I/O thread killed " @@ -2230,7 +2230,7 @@ connected: DBUG_PRINT("info",("Starting reading binary log from master")); while (!io_slave_killed(thd,mi)) { - thd->proc_info = "Requesting binlog dump"; + thd_proc_info(thd, "Requesting binlog dump"); if (request_dump(mysql, mi, &suppress_warnings)) { sql_print_error("Failed on request_dump()"); @@ -2261,7 +2261,7 @@ requesting master dump") || important thing is to not confuse users by saying "reading" whereas we're in fact receiving nothing. */ - thd->proc_info= "Waiting for master to send event"; + thd_proc_info(thd, "Waiting for master to send event"); event_len= read_event(mysql, mi, &suppress_warnings); if (check_io_slave_killed(thd, mi, "Slave I/O thread killed while \ reading event")) @@ -2305,7 +2305,7 @@ Stopping slave I/O thread due to out-of-memory error from master"); } // if (event_len == packet_error) retry_count=0; // ok event, reset retry counter - thd->proc_info = "Queueing master event to the relay log"; + thd_proc_info(thd, "Queueing master event to the relay log"); if (queue_event(mi,(const char*)mysql->net.read_pos + 1, event_len)) { @@ -2380,7 +2380,7 @@ err: mi->mysql=0; } write_ignored_events_info_to_relay_log(thd, mi); - thd->proc_info = "Waiting for slave mutex on exit"; + thd_proc_info(thd, "Waiting for slave mutex on exit"); pthread_mutex_lock(&mi->run_lock); /* Forget the relay log's format */ @@ -2551,7 +2551,7 @@ Slave SQL thread aborted. Can't execute init_slave query"); while (!sql_slave_killed(thd,rli)) { - thd->proc_info = "Reading event from the relay log"; + thd_proc_info(thd, "Reading event from the relay log"); DBUG_ASSERT(rli->sql_thd == thd); THD_CHECK_SENTRY(thd); if (exec_relay_log_event(thd,rli)) @@ -2638,7 +2638,7 @@ the slave SQL thread with \"SLAVE START\". We stopped at log \ thd->query= thd->db= thd->catalog= 0; thd->query_length= thd->db_length= 0; VOID(pthread_mutex_unlock(&LOCK_thread_count)); - thd->proc_info = "Waiting for slave mutex on exit"; + thd_proc_info(thd, "Waiting for slave mutex on exit"); pthread_mutex_lock(&rli->run_lock); /* We need data_lock, at least to wake up any waiting master_pos_wait() */ pthread_mutex_lock(&rli->data_lock); diff --git a/sql/sp.cc b/sql/sp.cc index b4f0ec7729b..99ffc18deea 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -249,19 +249,18 @@ Stored_routine_creation_ctx::load_from_db(THD *thd, /*************************************************************************/ -/* +/** Open the mysql.proc table for read. - SYNOPSIS - open_proc_table_for_read() - thd Thread context - backup Pointer to Open_tables_state instance where information about - currently open tables will be saved, and from which will be - restored when we will end work with mysql.proc. + @param thd Thread context + @param backup Pointer to Open_tables_state instance where information about + currently open tables will be saved, and from which will be + restored when we will end work with mysql.proc. - RETURN + @retval 0 Error - # Pointer to TABLE object of mysql.proc + @retval + \# Pointer to TABLE object of mysql.proc */ TABLE *open_proc_table_for_read(THD *thd, Open_tables_state *backup) @@ -281,19 +280,18 @@ TABLE *open_proc_table_for_read(THD *thd, Open_tables_state *backup) } -/* +/** Open the mysql.proc table for update. - SYNOPSIS - open_proc_table_for_update() - thd Thread context + @param thd Thread context - NOTES + @note Table opened with this call should closed using close_thread_tables(). - RETURN + @retval 0 Error - # Pointer to TABLE object of mysql.proc + @retval + \# Pointer to TABLE object of mysql.proc */ static TABLE *open_proc_table_for_update(THD *thd) @@ -310,19 +308,18 @@ static TABLE *open_proc_table_for_update(THD *thd) } -/* +/** Find row in open mysql.proc table representing stored routine. - SYNOPSIS - db_find_routine_aux() - thd Thread context - type Type of routine to find (function or procedure) - name Name of routine - table TABLE object for open mysql.proc table. + @param thd Thread context + @param type Type of routine to find (function or procedure) + @param name Name of routine + @param table TABLE object for open mysql.proc table. - RETURN VALUE - SP_OK - Routine found - SP_KEY_NOT_FOUND- No routine with given name + @retval + SP_OK Routine found + @retval + SP_KEY_NOT_FOUND No routine with given name */ static int @@ -357,25 +354,24 @@ db_find_routine_aux(THD *thd, int type, sp_name *name, TABLE *table) } -/* +/** Find routine definition in mysql.proc table and create corresponding sp_head object for it. - SYNOPSIS - db_find_routine() - thd Thread context - type Type of routine (TYPE_ENUM_PROCEDURE/...) - name Name of routine - sphp Out parameter in which pointer to created sp_head - object is returned (0 in case of error). + @param thd Thread context + @param type Type of routine (TYPE_ENUM_PROCEDURE/...) + @param name Name of routine + @param sphp Out parameter in which pointer to created sp_head + object is returned (0 in case of error). - NOTE + @note This function may damage current LEX during execution, so it is good idea to create temporary LEX and make it active before calling it. - RETURN VALUE - 0 - Success - non-0 - Error (may be one of special codes like SP_KEY_NOT_FOUND) + @retval + 0 Success + @retval + non-0 Error (may be one of special codes like SP_KEY_NOT_FOUND) */ static int @@ -1337,22 +1333,21 @@ sp_show_create_routine(THD *thd, int type, sp_name *name) } -/* +/** Obtain object representing stored procedure/function by its name from stored procedures cache and looking into mysql.proc if needed. - SYNOPSIS - sp_find_routine() - thd - thread context - type - type of object (TYPE_ENUM_FUNCTION or TYPE_ENUM_PROCEDURE) - name - name of procedure - cp - hash to look routine in - cache_only - if true perform cache-only lookup - (Don't look in mysql.proc). - - RETURN VALUE - Non-0 pointer to sp_head object for the procedure, or - 0 - in case of error. + @param thd thread context + @param type type of object (TYPE_ENUM_FUNCTION or TYPE_ENUM_PROCEDURE) + @param name name of procedure + @param cp hash to look routine in + @param cache_only if true perform cache-only lookup + (Don't look in mysql.proc). + + @retval + NonNULL pointer to sp_head object for the procedure + @retval + NULL in case of error. */ sp_head * @@ -1448,7 +1443,7 @@ sp_find_routine(THD *thd, int type, sp_name *name, sp_cache **cp, } -/* +/** This is used by sql_acl.cc:mysql_routine_grant() and is used to find the routines in 'routines'. */ @@ -1497,18 +1492,17 @@ sp_exist_routines(THD *thd, TABLE_LIST *routines, bool any, bool no_error) } -/* +/** Check if a routine exists in the mysql.proc table, without actually - parsing the definition. (Used for dropping) + parsing the definition. (Used for dropping). - SYNOPSIS - sp_routine_exists_in_table() - thd - thread context - name - name of procedure + @param thd thread context + @param name name of procedure - RETURN VALUE - 0 - Success - non-0 - Error; SP_OPEN_TABLE_FAILED or SP_KEY_NOT_FOUND + @retval + 0 Success + @retval + non-0 Error; SP_OPEN_TABLE_FAILED or SP_KEY_NOT_FOUND */ int @@ -1530,7 +1524,7 @@ sp_routine_exists_in_table(THD *thd, int type, sp_name *name) } -/* +/** Structure that represents element in the set of stored routines used by statement or routine. */ @@ -1538,14 +1532,16 @@ struct Sroutine_hash_entry; struct Sroutine_hash_entry { - /* Set key consisting of one-byte routine type and quoted routine name. */ + /** + Set key consisting of one-byte routine type and quoted routine name. + */ LEX_STRING key; - /* + /** Next element in list linking all routines in set. See also comments for LEX::sroutine/sroutine_list and sp_head::m_sroutines. */ Sroutine_hash_entry *next; - /* + /** Uppermost view which directly or indirectly uses this routine. 0 if routine is not used in view. Note that it also can be 0 if statement uses routine both via view and directly. @@ -1563,24 +1559,22 @@ extern "C" uchar* sp_sroutine_key(const uchar *ptr, size_t *plen, } -/* +/** Check if - current statement (the one in thd->lex) needs table prelocking - first routine in thd->lex->sroutines_list needs to execute its body in prelocked mode. - SYNOPSIS - sp_get_prelocking_info() - thd Current thread, thd->lex is the statement to be - checked. - need_prelocking OUT TRUE - prelocked mode should be activated - before executing the statement - FALSE - Don't activate prelocking - first_no_prelocking OUT TRUE - Tables used by first routine in - thd->lex->sroutines_list should be - prelocked. - FALSE - Otherwise. - NOTES + @param thd Current thread, thd->lex is the statement to be + checked. + @param[out] need_prelocking TRUE - prelocked mode should be activated + before executing the statement; + FALSE - Don't activate prelocking + @param[out] first_no_prelocking TRUE - Tables used by first routine in + thd->lex->sroutines_list should be + prelocked. FALSE - Otherwise. + + @note This function assumes that for any "CALL proc(...)" statement routines_list will have 'proc' as first element (it may have several, consider e.g. "proc(sp_func(...)))". This property is currently guaranted by the parser. @@ -1600,36 +1594,37 @@ void sp_get_prelocking_info(THD *thd, bool *need_prelocking, } -/* +/** Auxilary function that adds new element to the set of stored routines used by statement. - SYNOPSIS - add_used_routine() - lex LEX representing statement - arena Arena in which memory for new element will be allocated - key Key for the hash representing set - belong_to_view Uppermost view which uses this routine - (0 if routine is not used by view) + In case when statement uses stored routines but does not need + prelocking (i.e. it does not use any tables) we will access the + elements of LEX::sroutines set on prepared statement re-execution. + Because of this we have to allocate memory for both hash element + and copy of its key in persistent arena. - NOTES - Will also add element to end of 'LEX::sroutines_list' list. + @param lex LEX representing statement + @param arena Arena in which memory for new element will be + allocated + @param key Key for the hash representing set + @param belong_to_view Uppermost view which uses this routine + (0 if routine is not used by view) - In case when statement uses stored routines but does not need - prelocking (i.e. it does not use any tables) we will access the - elements of LEX::sroutines set on prepared statement re-execution. - Because of this we have to allocate memory for both hash element - and copy of its key in persistent arena. + @note + Will also add element to end of 'LEX::sroutines_list' list. - TODO + @todo When we will got rid of these accesses on re-executions we will be able to allocate memory for hash elements in non-persitent arena and directly use key values from sp_head::m_sroutines sets instead of making their copies. - RETURN VALUE - TRUE - new element was added. - FALSE - element was not added (because it is already present in the set). + @retval + TRUE new element was added. + @retval + FALSE element was not added (because it is already present in + the set). */ static bool add_used_routine(LEX *lex, Query_arena *arena, @@ -1659,24 +1654,22 @@ static bool add_used_routine(LEX *lex, Query_arena *arena, } -/* +/** Add routine which is explicitly used by statement to the set of stored routines used by this statement. - SYNOPSIS - sp_add_used_routine() - lex - LEX representing statement - arena - arena in which memory for new element of the set - will be allocated - rt - routine name - rt_type - routine type (one of TYPE_ENUM_PROCEDURE/...) + To be friendly towards prepared statements one should pass + persistent arena as second argument. + + @param lex LEX representing statement + @param arena arena in which memory for new element of the set + will be allocated + @param rt routine name + @param rt_type routine type (one of TYPE_ENUM_PROCEDURE/...) - NOTES + @note Will also add element to end of 'LEX::sroutines_list' list (and will take into account that this is explicitly used routine). - - To be friendly towards prepared statements one should pass - persistent arena as second argument. */ void sp_add_used_routine(LEX *lex, Query_arena *arena, @@ -1689,13 +1682,11 @@ void sp_add_used_routine(LEX *lex, Query_arena *arena, } -/* +/** Remove routines which are only indirectly used by statement from the set of routines used by this statement. - SYNOPSIS - sp_remove_not_own_routines() - lex LEX representing statement + @param lex LEX representing statement */ void sp_remove_not_own_routines(LEX *lex) @@ -1718,16 +1709,14 @@ void sp_remove_not_own_routines(LEX *lex) } -/* +/** Merge contents of two hashes representing sets of routines used by statements or by other routines. - SYNOPSIS - sp_update_sp_used_routines() - dst - hash to which elements should be added - src - hash from which elements merged + @param dst hash to which elements should be added + @param src hash from which elements merged - NOTE + @note This procedure won't create new Sroutine_hash_entry objects, instead it will simply add elements from source to destination hash. Thus time of life of elements in destination hash becomes @@ -1747,18 +1736,17 @@ void sp_update_sp_used_routines(HASH *dst, HASH *src) } -/* +/** Add contents of hash representing set of routines to the set of routines used by statement. - SYNOPSIS - sp_update_stmt_used_routines() - thd Thread context - lex LEX representing statement - src Hash representing set from which routines will be added - belong_to_view Uppermost view which uses these routines, 0 if none + @param thd Thread context + @param lex LEX representing statement + @param src Hash representing set from which routines will + be added + @param belong_to_view Uppermost view which uses these routines, 0 if none - NOTE + @note It will also add elements to end of 'LEX::sroutines_list' list. */ @@ -1774,18 +1762,17 @@ sp_update_stmt_used_routines(THD *thd, LEX *lex, HASH *src, } -/* +/** Add contents of list representing set of routines to the set of routines used by statement. - SYNOPSIS - sp_update_stmt_used_routines() - thd Thread context - lex LEX representing statement - src List representing set from which routines will be added - belong_to_view Uppermost view which uses these routines, 0 if none + @param thd Thread context + @param lex LEX representing statement + @param src List representing set from which routines will + be added + @param belong_to_view Uppermost view which uses these routines, 0 if none - NOTE + @note It will also add elements to end of 'LEX::sroutines_list' list. */ @@ -1798,27 +1785,28 @@ static void sp_update_stmt_used_routines(THD *thd, LEX *lex, SQL_LIST *src, } -/* +/** Cache sub-set of routines used by statement, add tables used by these routines to statement table list. Do the same for all routines used by these routines. - SYNOPSIS - sp_cache_routines_and_add_tables_aux() - thd - thread context - lex - LEX representing statement - start - first routine from the list of routines to be cached - (this list defines mentioned sub-set). - first_no_prelock - If true, don't add tables or cache routines used by - the body of the first routine (i.e. *start) - will be executed in non-prelocked mode. - NOTE + @param thd thread context + @param lex LEX representing statement + @param start first routine from the list of routines to be cached + (this list defines mentioned sub-set). + @param first_no_prelock If true, don't add tables or cache routines used by + the body of the first routine (i.e. *start) + will be executed in non-prelocked mode. + @param tabs_changed Set to TRUE some tables were added, FALSE otherwise + + @note If some function is missing this won't be reported here. Instead this fact will be discovered during query execution. - RETURN VALUE - 0 - success - non-0 - failure + @retval + 0 success + @retval + non-0 failure */ static int @@ -1903,21 +1891,20 @@ sp_cache_routines_and_add_tables_aux(THD *thd, LEX *lex, } -/* +/** Cache all routines from the set of used by statement, add tables used by those routines to statement table list. Do the same for all routines used by those routines. - SYNOPSIS - sp_cache_routines_and_add_tables() - thd - thread context - lex - LEX representing statement - first_no_prelock - If true, don't add tables or cache routines used by - the body of the first routine (i.e. *start) + @param thd thread context + @param lex LEX representing statement + @param first_no_prelock If true, don't add tables or cache routines used by + the body of the first routine (i.e. *start) - RETURN VALUE - 0 - success - non-0 - failure + @retval + 0 success + @retval + non-0 failure */ int @@ -1929,20 +1916,21 @@ sp_cache_routines_and_add_tables(THD *thd, LEX *lex, bool first_no_prelock) } -/* - Add all routines used by view to the set of routines used by statement. +/** + Add all routines used by view to the set of routines used by + statement. + Add tables used by those routines to statement table list. Do the same for all routines used by these routines. - SYNOPSIS - sp_cache_routines_and_add_tables_for_view() - thd Thread context - lex LEX representing statement - view Table list element representing view + @param thd Thread context + @param lex LEX representing statement + @param view Table list element representing view - RETURN VALUE - 0 - success - non-0 - failure + @retval + 0 success + @retval + non-0 failure */ int @@ -1957,20 +1945,19 @@ sp_cache_routines_and_add_tables_for_view(THD *thd, LEX *lex, TABLE_LIST *view) } -/* +/** Add triggers for table to the set of routines used by statement. Add tables used by them to statement table list. Do the same for all implicitly used routines. - SYNOPSIS - sp_cache_routines_and_add_tables_for_triggers() - thd thread context - lex LEX respresenting statement - table Table list element for table with trigger + @param thd thread context + @param lex LEX respresenting statement + @param table Table list element for table with trigger - RETURN VALUE - 0 - success - non-0 - failure + @retval + 0 success + @retval + non-0 failure */ int @@ -2016,10 +2003,12 @@ sp_cache_routines_and_add_tables_for_triggers(THD *thd, LEX *lex, } -/* - * Generates the CREATE... string from the table information. - * Returns TRUE on success, FALSE on (alloc) failure. - */ +/** + Generates the CREATE... string from the table information. + + @return + Returns TRUE on success, FALSE on (alloc) failure. +*/ static bool create_string(THD *thd, String *buf, int type, diff --git a/sql/sp_head.cc b/sql/sp_head.cc index bae85d8c092..4a0e18129ad 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -80,19 +80,20 @@ sp_map_item_type(enum enum_field_types type) } -/* +/** Return a string representation of the Item value. - NOTE: If the item has a string result type, the string is escaped - according to its character set. + @param thd thread handle + @param str string buffer for representation of the value - SYNOPSIS - item a pointer to the Item - str string buffer for representation of the value + @note + If the item has a string result type, the string is escaped + according to its character set. - RETURN - NULL on error - a pointer to valid a valid string on success + @retval + NULL on error + @retval + non-NULL a pointer to valid a valid string on success */ static String * @@ -138,16 +139,12 @@ sp_get_item_value(THD *thd, Item *item, String *str) } -/* - SYNOPSIS - sp_get_flags_for_command() - - DESCRIPTION - Returns a combination of: - * sp_head::MULTI_RESULTS: added if the 'cmd' is a command that might - result in multiple result sets being sent back. - * sp_head::CONTAINS_DYNAMIC_SQL: added if 'cmd' is one of PREPARE, - EXECUTE, DEALLOCATE. +/** + Returns a combination of: + - sp_head::MULTI_RESULTS: added if the 'cmd' is a command that might + result in multiple result sets being sent back. + - sp_head::CONTAINS_DYNAMIC_SQL: added if 'cmd' is one of PREPARE, + EXECUTE, DEALLOCATE. */ uint @@ -287,17 +284,16 @@ sp_get_flags_for_command(LEX *lex) return flags; } -/* +/** Prepare an Item for evaluation (call of fix_fields). - SYNOPSIS - sp_prepare_func_item() - thd thread handler - it_addr pointer on item refernce + @param thd thread handler + @param it_addr pointer on item refernce - RETURN - NULL error - prepared item + @retval + NULL error + @retval + non-NULL prepared item */ Item * @@ -317,17 +313,16 @@ sp_prepare_func_item(THD* thd, Item **it_addr) } -/* +/** Evaluate an expression and store the result in the field. - SYNOPSIS - sp_eval_expr() - thd - current thread object - expr_item - the root item of the expression - result_field - the field to store the result + @param thd current thread object + @param result_field the field to store the result + @param expr_item_ptr the root item of the expression - RETURN VALUES + @retval FALSE on success + @retval TRUE on error */ @@ -410,6 +405,10 @@ sp_name::sp_name(THD *thd, char *key, uint key_len) m_explicit_name= false; } + +/** + Init the qualified name from the db and name. +*/ void sp_name::init_qname(THD *thd) { @@ -427,16 +426,17 @@ sp_name::init_qname(THD *thd) } -/* - Check that the name 'ident' is ok. It's assumed to be an 'ident' +/** + Check that the name 'ident' is ok. It's assumed to be an 'ident' from the parser, so we only have to check length and trailing spaces. The former is a standard requirement (and 'show status' assumes a non-empty name), the latter is a mysql:ism as trailing spaces are removed by get_field(). - - RETURN - TRUE - bad name - FALSE - name is ok + + @retval + TRUE bad name + @retval + FALSE name is ok */ bool @@ -444,7 +444,7 @@ check_routine_name(LEX_STRING *ident) { if (!ident || !ident->str || !ident->str[0] || ident->str[ident->length-1] == ' ') - { + { my_error(ER_SP_WRONG_NAME, MYF(0), ident->str); return TRUE; } @@ -778,7 +778,7 @@ sp_head::destroy() } -/* +/** This is only used for result fields from functions (both during fix_length_and_dec() and evaluation). */ @@ -897,29 +897,23 @@ int cmp_splocal_locations(Item_splocal * const *a, Item_splocal * const *b) */ -/* - Replace thd->query{_length} with a string that one can write to the binlog - or the query cache. - - SYNOPSIS - subst_spvars() - thd Current thread. - instr Instruction (we look for Item_splocal instances in - instr->free_list) - query_str Original query string - - DESCRIPTION +/** + Replace thd->query{_length} with a string that one can write to + the binlog. The binlog-suitable string is produced by replacing references to SP local - variables with NAME_CONST('sp_var_name', value) calls. To make this string - suitable for the query cache this function allocates some additional space - for the query cache flags. - - RETURN - FALSE on success - thd->query{_length} either has been appropriately replaced or there - is no need for replacements. - TRUE out of memory error. + variables with NAME_CONST('sp_var_name', value) calls. + + @param thd Current thread. + @param instr Instruction (we look for Item_splocal instances in + instr->free_list) + @param query_str Original query string + + @return + - FALSE on success. + thd->query{_length} either has been appropriately replaced or there + is no need for replacements. + - TRUE out of memory error. */ static bool @@ -1038,14 +1032,17 @@ void sp_head::recursion_level_error(THD *thd) } -/* - Execute the routine. The main instruction jump loop is there +/** + Execute the routine. The main instruction jump loop is there. Assume the parameters already set. - - RETURN + @todo + - Will write this SP statement into binlog separately + (TODO: consider changing the condition to "not inside event union") + + @retval FALSE on success + @retval TRUE on error - */ bool @@ -1172,15 +1169,36 @@ sp_head::execute(THD *thd) */ thd->spcont->callers_arena= &backup_arena; +#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) + /* Discard the initial part of executing routines. */ + thd->profiling.discard_current_query(); +#endif do { sp_instr *i; uint hip; // Handler ip +#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) + /* + Treat each "instr" of a routine as discrete unit that could be profiled. + Profiling only records information for segments of code that set the + source of the query, and almost all kinds of instructions in s-p do not. + */ + thd->profiling.finish_current_query(); + thd->profiling.start_new_query("continuing inside routine"); +#endif + i = get_instr(ip); // Returns NULL when we're done. if (i == NULL) + { +#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) + thd->profiling.discard_current_query(); +#endif break; + } + DBUG_PRINT("execute", ("Instruction %u", ip)); + /* Don't change NOW() in FUNCTION or TRIGGER */ if (!thd->in_sub_stmt) thd->set_time(); // Make current_time() et al work @@ -1252,6 +1270,11 @@ sp_head::execute(THD *thd) } } while (!err_status && !thd->killed); +#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) + thd->profiling.finish_current_query(); + thd->profiling.start_new_query("tail end of routine"); +#endif + /* Restore query context. */ m_creation_ctx->restore_env(thd, saved_creation_ctx); @@ -1329,22 +1352,26 @@ sp_head::execute(THD *thd) #ifndef NO_EMBEDDED_ACCESS_CHECKS -/* +/** set_routine_security_ctx() changes routine security context, and checks if there is an EXECUTE privilege in new context. If there is no EXECUTE privilege, it changes the context back and returns a error. - SYNOPSIS - set_routine_security_ctx() - thd thread handle - sp stored routine to change the context for - is_proc TRUE is procedure, FALSE if function - save_ctx pointer to an old security context - - RETURN - TRUE if there was a error, and the context wasn't changed. - FALSE if the context was changed. + @param thd thread handle + @param sp stored routine to change the context for + @param is_proc TRUE is procedure, FALSE if function + @param save_ctx pointer to an old security context + + @todo + - Cache if the definer has the right to use the object on the + first usage and only reset the cache if someone does a GRANT + statement that 'may' affect this. + + @retval + TRUE if there was a error, and the context wasn't changed. + @retval + FALSE if the context was changed. */ bool @@ -1386,22 +1413,27 @@ set_routine_security_ctx(THD *thd, sp_head *sp, bool is_proc, /** Execute trigger stored program. - Execute a trigger: - - changes security context for triggers; - - switch to new memroot; - - call sp_head::execute; - - restore old memroot; - - restores security context. - - @param thd Thread context. - @param db_name Database name. - @param table_name Table name. - @param grant_info GRANT_INFO structure to be filled with information - about definer's privileges on subject table. + - changes security context for triggers + - switch to new memroot + - call sp_head::execute + - restore old memroot + - restores security context + + @param thd Thread handle + @param db database name + @param table table name + @param grant_info GRANT_INFO structure to be filled with + information about definer's privileges + on subject table + + @todo + - TODO: we should create sp_rcontext once per command and reuse it + on subsequent executions of a trigger. - @return Error status. - @retval FALSE on success. - @retval TRUE on error. + @retval + FALSE on success + @retval + TRUE on error */ bool @@ -1509,8 +1541,9 @@ err_with_cleanup: } -/* - Execute a function: +/** + Execute a function. + - evaluate parameters - changes security context for SUID routines - switch to new memroot @@ -1519,17 +1552,25 @@ err_with_cleanup: - evaluate the return value - restores security context - SYNOPSIS - sp_head::execute_function() - thd Thread handle - argp Passed arguments (these are items from containing - statement?) - argcount Number of passed arguments. We need to check if this is - correct. - return_value_fld Save result here. - - RETURN + @param thd Thread handle + @param argp Passed arguments (these are items from containing + statement?) + @param argcount Number of passed arguments. We need to check if + this is correct. + @param return_value_fld Save result here. + + @todo + We should create sp_rcontext once per command and reuse + it on subsequent executions of a function/trigger. + + @todo + In future we should associate call arena/mem_root with + sp_rcontext and allocate all these objects (and sp_rcontext + itself) on it directly rather than juggle with arenas. + + @retval FALSE on success + @retval TRUE on error */ @@ -1746,14 +1787,8 @@ err_with_cleanup: } -/* +/** Execute a procedure. - SYNOPSIS - sp_head::execute_procedure() - thd Thread handle - args List of values passed as arguments. - - DESCRIPTION The function does the following steps: - Set all parameters @@ -1762,8 +1797,12 @@ err_with_cleanup: - copy back values of INOUT and OUT parameters - restores security context - RETURN + @param thd Thread handle + @param args List of values passed as arguments. + + @retval FALSE on success + @retval TRUE on error */ @@ -1966,7 +2005,7 @@ sp_head::execute_procedure(THD *thd, List<Item> *args) /** - @brief Reset lex during parsing, before we parse a sub statement. + Reset lex during parsing, before we parse a sub statement. @param thd Thread handler. @@ -2011,7 +2050,7 @@ sp_head::reset_lex(THD *thd) DBUG_RETURN(FALSE); } -// Restore lex during parsing, after we have parsed a sub statement. +/// Restore lex during parsing, after we have parsed a sub statement. void sp_head::restore_lex(THD *thd) { @@ -2054,6 +2093,9 @@ sp_head::restore_lex(THD *thd) DBUG_VOID_RETURN; } +/** + Put the instruction on the backpatch list, associated with the label. +*/ void sp_head::push_backpatch(sp_instr *i, sp_label_t *lab) { @@ -2067,6 +2109,10 @@ sp_head::push_backpatch(sp_instr *i, sp_label_t *lab) } } +/** + Update all instruction with this label in the backpatch list to + the current position. +*/ void sp_head::backpatch(sp_label_t *lab) { @@ -2081,19 +2127,18 @@ sp_head::backpatch(sp_label_t *lab) } } -/* +/** Prepare an instance of Create_field for field creation (fill all necessary attributes). - SYNOPSIS - sp_head::fill_field_definition() - thd [IN] Thread handle - lex [IN] Yacc parsing context - field_type [IN] Field type - field_def [OUT] An instance of Create_field to be filled + @param[in] thd Thread handle + @param[in] lex Yacc parsing context + @param[in] field_type Field type + @param[out] field_def An instance of create_field to be filled - RETURN + @retval FALSE on success + @retval TRUE on error */ @@ -2239,18 +2284,17 @@ sp_head::restore_thd_mem_root(THD *thd) } -/* - Check if a user has access right to a routine - - SYNOPSIS - check_show_routine_access() - thd Thread handler - sp SP - full_access Set to 1 if the user has SELECT right to the - 'mysql.proc' able or is the owner of the routine - RETURN - 0 ok - 1 error +/** + Check if a user has access right to a routine. + + @param thd Thread handler + @param sp SP + @param full_access Set to 1 if the user has SELECT right to the + 'mysql.proc' able or is the owner of the routine + @retval + false ok + @retval + true error */ bool check_show_routine_access(THD *thd, sp_head *sp, bool *full_access) @@ -2377,12 +2421,10 @@ sp_head::show_create_routine(THD *thd, int type) -/* - Add instruction to SP +/** + Add instruction to SP. - SYNOPSIS - sp_head::add_instr() - instr Instruction + @param instr Instruction */ void sp_head::add_instr(sp_instr *instr) @@ -2400,20 +2442,20 @@ void sp_head::add_instr(sp_instr *instr) } -/* +/** Do some minimal optimization of the code: - 1) Mark used instructions - 1.1) While doing this, shortcut jumps to jump instructions - 2) Compact the code, removing unused instructions + -# Mark used instructions + -# While doing this, shortcut jumps to jump instructions + -# Compact the code, removing unused instructions. This is the main mark and move loop; it relies on the following methods in sp_instr and its subclasses: - opt_mark() Mark instruction as reachable - opt_shortcut_jump() Shortcut jumps to the final destination; - used by opt_mark(). - opt_move() Update moved instruction - set_destination() Set the new destination (jump instructions only) + - opt_mark() : Mark instruction as reachable + - opt_shortcut_jump(): Shortcut jumps to the final destination; + used by opt_mark(). + - opt_move() : Update moved instruction + - set_destination() : Set the new destination (jump instructions only) */ void sp_head::optimize() @@ -2504,9 +2546,10 @@ sp_head::opt_mark() #ifndef DBUG_OFF -/* +/** Return the routine instructions as a result set. - Returns 0 if ok, !=0 on error. + @return + 0 if ok, !=0 on error. */ int sp_head::show_routine_code(THD *thd) @@ -2569,27 +2612,25 @@ sp_head::show_routine_code(THD *thd) #endif // ifndef DBUG_OFF -/* +/** Prepare LEX and thread for execution of instruction, if requested open and lock LEX's tables, execute instruction's core function, perform cleanup afterwards. - SYNOPSIS - reset_lex_and_exec_core() - thd - thread context - nextp - out - next instruction - open_tables - if TRUE then check read access to tables in LEX's table - list and open and lock them (used in instructions which - need to calculate some expression and don't execute - complete statement). - sp_instr - instruction for which we prepare context, and which core - function execute by calling its exec_core() method. + @param thd thread context + @param nextp out - next instruction + @param open_tables if TRUE then check read access to tables in LEX's table + list and open and lock them (used in instructions which + need to calculate some expression and don't execute + complete statement). + @param sp_instr instruction for which we prepare context, and which core + function execute by calling its exec_core() method. - NOTE + @note We are not saving/restoring some parts of THD which may need this because we do this once for whole routine execution in sp_head::execute(). - RETURN VALUE + @return 0/non-0 - Success/Failure */ @@ -2652,9 +2693,9 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp, m_lex->unit.cleanup(); - thd->proc_info="closing tables"; + thd_proc_info(thd, "closing tables"); close_thread_tables(thd); - thd->proc_info= 0; + thd_proc_info(thd, 0); if (m_lex->query_tables_own_last) { @@ -2742,6 +2783,10 @@ sp_instr_stmt::execute(THD *thd, uint *nextp) query= thd->query; query_length= thd->query_length; +#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) + /* This s-p instr is profilable and will be captured. */ + thd->profiling.set_query_source(m_query.str, m_query.length); +#endif if (!(res= alloc_query(thd, m_query.str, m_query.length)) && !(res=subst_spvars(thd, this, &m_query))) { @@ -3351,6 +3396,11 @@ sp_instr_cpop::print(String *str) sp_instr_copen class functions */ +/** + @todo + Assert that we either have an error or a cursor +*/ + int sp_instr_copen::execute(THD *thd, uint *nextp) { @@ -3672,24 +3722,23 @@ uchar *sp_table_key(const uchar *ptr, size_t *plen, my_bool first) } -/* +/** Merge the list of tables used by some query into the multi-set of tables used by routine. - SYNOPSIS - merge_table_list() - thd - thread context - table - table list - lex_for_tmp_check - LEX of the query for which we are merging - table list. + @param thd thread context + @param table table list + @param lex_for_tmp_check LEX of the query for which we are merging + table list. - NOTE + @note This method will use LEX provided to check whenever we are creating temporary table and mark it as such in target multi-set. - RETURN VALUE - TRUE - Success - FALSE - Error + @retval + TRUE Success + @retval + FALSE Error */ bool @@ -3777,27 +3826,26 @@ sp_head::merge_table_list(THD *thd, TABLE_LIST *table, LEX *lex_for_tmp_check) } -/* +/** Add tables used by routine to the table list. - SYNOPSIS - add_used_tables_to_table_list() - thd [in] Thread context - query_tables_last_ptr [in/out] Pointer to the next_global member of - last element of the list where tables - will be added (or to its root). - belong_to_view [in] Uppermost view which uses this routine, - 0 if none. - - DESCRIPTION Converts multi-set of tables used by this routine to table list and adds this list to the end of table list specified by 'query_tables_last_ptr'. Elements of list will be allocated in PS memroot, so this list will be persistent between PS executions. - RETURN VALUE - TRUE - if some elements were added, FALSE - otherwise. + @param[in] thd Thread context + @param[in,out] query_tables_last_ptr Pointer to the next_global member of + last element of the list where tables + will be added (or to its root). + @param[in] belong_to_view Uppermost view which uses this routine, + 0 if none. + + @retval + TRUE if some elements were added + @retval + FALSE otherwise. */ bool @@ -3867,7 +3915,7 @@ sp_head::add_used_tables_to_table_list(THD *thd, } -/* +/** Simple function for adding an explicetly named (systems) table to the global table list, e.g. "mysql", "proc". */ diff --git a/sql/sp_head.h b/sql/sp_head.h index 86a77a434ff..01a4cb73704 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -109,7 +109,7 @@ public: LEX_STRING m_db; LEX_STRING m_name; LEX_STRING m_qname; - /* + /** Key representing routine in the set of stored routines used by statement. Consists of 1-byte routine type and m_qname (which usually refences to same buffer). Note that one must complete initialization of the key by @@ -125,7 +125,7 @@ public: m_qname.length= m_sroutines_key.length= 0; } - /* + /** Creates temporary sp_name object from key, used mainly for SP-cache lookups. */ @@ -149,12 +149,12 @@ check_routine_name(LEX_STRING *ident); class sp_head :private Query_arena { - sp_head(const sp_head &); /* Prevent use of these */ + sp_head(const sp_head &); /**< Prevent use of these */ void operator=(sp_head &); MEM_ROOT main_mem_root; public: - /* Possible values of m_flags */ + /** Possible values of m_flags */ enum { HAS_RETURN= 1, // For FUNCTIONs only: is set if has RETURN MULTI_RESULTS= 8, // Is set if a procedure with SELECT(s) @@ -170,16 +170,16 @@ public: HAS_SQLCOM_FLUSH= 4096 }; - /* TYPE_ENUM_FUNCTION, TYPE_ENUM_PROCEDURE or TYPE_ENUM_TRIGGER */ + /** TYPE_ENUM_FUNCTION, TYPE_ENUM_PROCEDURE or TYPE_ENUM_TRIGGER */ int m_type; uint m_flags; // Boolean attributes of a stored routine - Create_field m_return_field_def; /* This is used for FUNCTIONs only. */ + Create_field m_return_field_def; /**< This is used for FUNCTIONs only. */ - const char *m_tmp_query; // Temporary pointer to sub query string + const char *m_tmp_query; ///< Temporary pointer to sub query string st_sp_chistics *m_chistics; - ulong m_sql_mode; // For SHOW CREATE and execution - LEX_STRING m_qname; // db.name + ulong m_sql_mode; ///< For SHOW CREATE and execution + LEX_STRING m_qname; ///< db.name /** Key representing routine in the set of stored routines used by statement. [routine_type]db.name @@ -211,20 +211,20 @@ public: longlong m_created; longlong m_modified; - /* Recursion level of the current SP instance. The levels are numbered from 0 */ + /** Recursion level of the current SP instance. The levels are numbered from 0 */ ulong m_recursion_level; - /* + /** A list of diferent recursion level instances for the same procedure. For every recursion level we have a sp_head instance. This instances connected in the list. The list ordered by increasing recursion level (m_recursion_level). */ sp_head *m_next_cached_sp; - /* + /** Pointer to the first element of the above list */ sp_head *m_first_instance; - /* + /** Pointer to the first free (non-INVOKED) routine in the list of cached instances for this SP. This pointer is set only for the first SP in the list of instences (see above m_first_cached_sp pointer). @@ -232,12 +232,12 @@ public: For non-first instance value of this pointer meanless (point to itself); */ sp_head *m_first_free_instance; - /* + /** Pointer to the last element in the list of instances of the SP. For non-first instance value of this pointer meanless (point to itself); */ sp_head *m_last_cached_sp; - /* + /** Set containing names of stored routines used by this routine. Note that unlike elements of similar set for statement elements of this set are not linked in one list. Because of this we are able save memory @@ -267,11 +267,11 @@ public: sp_head(); - // Initialize after we have reset mem_root + /// Initialize after we have reset mem_root void init(LEX *lex); - /* Copy sp name from parser. */ + /** Copy sp name from parser. */ void init_sp_name(THD *thd, sp_name *spname); @@ -288,7 +288,7 @@ public: virtual ~sp_head(); - // Free memory + /// Free memory void destroy(); @@ -325,33 +325,41 @@ public: return i; } - // Resets lex in 'thd' and keeps a copy of the old one. + /* + Resets lex in 'thd' and keeps a copy of the old one. + + @todo Conflicting comment in sp_head.cc + */ bool reset_lex(THD *thd); - // Restores lex in 'thd' from our copy, but keeps some status from the - // one in 'thd', like ptr, tables, fields, etc. + /** + Restores lex in 'thd' from our copy, but keeps some status from the + one in 'thd', like ptr, tables, fields, etc. + + @todo Conflicting comment in sp_head.cc + */ void restore_lex(THD *thd); - // Put the instruction on the backpatch list, associated with the label. + /// Put the instruction on the backpatch list, associated with the label. void push_backpatch(sp_instr *, struct sp_label *); - // Update all instruction with this label in the backpatch list to - // the current position. + /// Update all instruction with this label in the backpatch list to + /// the current position. void backpatch(struct sp_label *); - // Start a new cont. backpatch level. If 'i' is NULL, the level is just incr. + /// Start a new cont. backpatch level. If 'i' is NULL, the level is just incr. void new_cont_backpatch(sp_instr_opt_meta *i); - // Add an instruction to the current level + /// Add an instruction to the current level void add_cont_backpatch(sp_instr_opt_meta *i); - // Backpatch (and pop) the current level to the current position. + /// Backpatch (and pop) the current level to the current position. void do_cont_backpatch(); @@ -414,7 +422,7 @@ public: TABLE_LIST ***query_tables_last_ptr, TABLE_LIST *belong_to_view); - /* + /** Check if this stored routine contains statements disallowed in a stored function or trigger, and set an appropriate error message if this is the case. @@ -463,19 +471,19 @@ public: private: - MEM_ROOT *m_thd_root; // Temp. store for thd's mem_root - THD *m_thd; // Set if we have reset mem_root + MEM_ROOT *m_thd_root; ///< Temp. store for thd's mem_root + THD *m_thd; ///< Set if we have reset mem_root - sp_pcontext *m_pcont; // Parse context - List<LEX> m_lex; // Temp. store for the other lex - DYNAMIC_ARRAY m_instr; // The "instructions" + sp_pcontext *m_pcont; ///< Parse context + List<LEX> m_lex; ///< Temp. store for the other lex + DYNAMIC_ARRAY m_instr; ///< The "instructions" typedef struct { struct sp_label *lab; sp_instr *instr; } bp_t; - List<bp_t> m_backpatch; // Instructions needing backpatching - /* + List<bp_t> m_backpatch; ///< Instructions needing backpatching + /** We need a special list for backpatching of instructions with a continue destination (in the case of a continue handler catching an error in the test), since it would otherwise interfere with the normal backpatch @@ -483,15 +491,16 @@ private: which are to be patched differently. Since these occur in a more restricted way (always the same "level" in the code), we don't need the label. - */ + */ List<sp_instr_opt_meta> m_cont_backpatch; uint m_cont_level; // The current cont. backpatch level - /* + /** Multi-set representing optimized list of tables to be locked by this routine. Does not include tables which are used by invoked routines. - Note: for prelocking-free SPs this multiset is constructed too. + @note + For prelocking-free SPs this multiset is constructed too. We do so because the same instance of sp_head may be called both in prelocked mode and in non-prelocked mode. */ @@ -506,7 +515,7 @@ private: */ void opt_mark(); - /* + /** Merge the list of tables used by query into the multi-set of tables used by routine. */ @@ -520,16 +529,16 @@ private: class sp_instr :public Query_arena, public Sql_alloc { - sp_instr(const sp_instr &); /* Prevent use of these */ + sp_instr(const sp_instr &); /**< Prevent use of these */ void operator=(sp_instr &); public: uint marked; - uint m_ip; // My index - sp_pcontext *m_ctx; // My parse context + uint m_ip; ///< My index + sp_pcontext *m_ctx; ///< My parse context - // Should give each a name or type code for debugging purposes? + /// Should give each a name or type code for debugging purposes? sp_instr(uint ip, sp_pcontext *ctx) :Query_arena(0, INITIALIZED_FOR_SP), marked(0), m_ip(ip), m_ctx(ctx) {} @@ -538,21 +547,19 @@ public: { free_items(); } - /* + /** Execute this instruction - SYNOPSIS - execute() - thd Thread handle - nextp OUT index of the next instruction to execute. (For most - instructions this will be the instruction following this - one). Note that this parameter is undefined in case of - errors, use get_cont_dest() to find the continuation - instruction for CONTINUE error handlers. - - RETURN - 0 on success, - other if some error occurred + + @param thd Thread handle + @param[out] nextp index of the next instruction to execute. (For most + instructions this will be the instruction following this + one). Note that this parameter is undefined in case of + errors, use get_cont_dest() to find the continuation + instruction for CONTINUE error handlers. + + @retval 0 on success, + @retval other if some error occured */ virtual int execute(THD *thd, uint *nextp) = 0; @@ -590,7 +597,7 @@ public: virtual void backpatch(uint dest, sp_pcontext *dst_ctx) {} - /* + /** Mark this instruction as reachable during optimization and return the index to the next instruction. Jump instruction will add their destination to the leads list. @@ -601,7 +608,7 @@ public: return m_ip+1; } - /* + /** Short-cut jumps to jumps during optimization. This is used by the jump instructions' opt_mark() methods. 'start' is the starting point, used to prevent the mark sweep from looping for ever. Return the @@ -612,7 +619,7 @@ public: return m_ip; } - /* + /** Inform the instruction that it has been moved during optimization. Most instructions will simply update its index, but jump instructions must also take care of their destination pointers. Forward jumps get @@ -626,7 +633,7 @@ public: }; // class sp_instr : public Sql_alloc -/* +/** Auxilary class to which instructions delegate responsibility for handling LEX and preparations before executing statement or calculating complex expression. @@ -634,13 +641,14 @@ public: Exist mainly to avoid having double hierarchy between instruction classes. - TODO: Add ability to not store LEX and do any preparations if - expression used is simple. + @todo + Add ability to not store LEX and do any preparations if + expression used is simple. */ class sp_lex_keeper { - /* Prevent use of these */ + /** Prevent use of these */ sp_lex_keeper(const sp_lex_keeper &); void operator=(sp_lex_keeper &); public: @@ -660,10 +668,12 @@ public: } } - /* + /** Prepare execution of instruction using LEX, if requested check whenever we have read access to tables used and open/lock them, call instruction's exec_core() method, perform cleanup afterwards. + + @todo Conflicting comment in sp_head.cc */ int reset_lex_and_exec_core(THD *thd, uint *nextp, bool open_tables, sp_instr* instr); @@ -680,7 +690,7 @@ public: private: LEX *m_lex; - /* + /** Indicates whenever this sp_lex_keeper instance responsible for LEX deletion. */ @@ -693,13 +703,13 @@ private: prelocked mode itself. */ - /* + /** List of additional tables this statement needs to lock when it enters/leaves prelocked mode on its own. */ TABLE_LIST *prelocking_tables; - /* + /** The value m_lex->query_tables_own_last should be set to this when the statement enters/leaves prelocked mode on its own. */ @@ -707,17 +717,17 @@ private: }; -// -// Call out to some prepared SQL statement. -// +/** + Call out to some prepared SQL statement. +*/ class sp_instr_stmt : public sp_instr { - sp_instr_stmt(const sp_instr_stmt &); /* Prevent use of these */ + sp_instr_stmt(const sp_instr_stmt &); /**< Prevent use of these */ void operator=(sp_instr_stmt &); public: - LEX_STRING m_query; // For thd->query + LEX_STRING m_query; ///< For thd->query sp_instr_stmt(uint ip, sp_pcontext *ctx, LEX *lex) : sp_instr(ip, ctx), m_lex_keeper(lex, TRUE) @@ -744,7 +754,7 @@ private: class sp_instr_set : public sp_instr { - sp_instr_set(const sp_instr_set &); /* Prevent use of these */ + sp_instr_set(const sp_instr_set &); /**< Prevent use of these */ void operator=(sp_instr_set &); public: @@ -767,15 +777,15 @@ public: private: - uint m_offset; // Frame offset + uint m_offset; ///< Frame offset Item *m_value; - enum enum_field_types m_type; // The declared type + enum enum_field_types m_type; ///< The declared type sp_lex_keeper m_lex_keeper; }; // class sp_instr_set : public sp_instr -/* +/** Set NEW/OLD row field value instruction. Used in triggers. */ class sp_instr_set_trigger_field : public sp_instr @@ -809,18 +819,19 @@ private: }; // class sp_instr_trigger_field : public sp_instr -/* +/** An abstract class for all instructions with destinations that needs to be updated by the optimizer. + Even if not all subclasses will use both the normal destination and the continuation destination, we put them both here for simplicity. - */ +*/ class sp_instr_opt_meta : public sp_instr { public: - uint m_dest; // Where we will go - uint m_cont_dest; // Where continue handlers will go + uint m_dest; ///< Where we will go + uint m_cont_dest; ///< Where continue handlers will go sp_instr_opt_meta(uint ip, sp_pcontext *ctx) : sp_instr(ip, ctx), @@ -842,14 +853,14 @@ public: protected: - sp_instr *m_optdest; // Used during optimization - sp_instr *m_cont_optdest; // Used during optimization + sp_instr *m_optdest; ///< Used during optimization + sp_instr *m_cont_optdest; ///< Used during optimization }; // class sp_instr_opt_meta : public sp_instr class sp_instr_jump : public sp_instr_opt_meta { - sp_instr_jump(const sp_instr_jump &); /* Prevent use of these */ + sp_instr_jump(const sp_instr_jump &); /**< Prevent use of these */ void operator=(sp_instr_jump &); public: @@ -881,7 +892,7 @@ public: m_dest= dest; } - /* + /** Update the destination; used by the optimizer. */ virtual void set_destination(uint old_dest, uint new_dest) @@ -895,7 +906,7 @@ public: class sp_instr_jump_if_not : public sp_instr_jump { - sp_instr_jump_if_not(const sp_instr_jump_if_not &); /* Prevent use of these */ + sp_instr_jump_if_not(const sp_instr_jump_if_not &); /**< Prevent use of these */ void operator=(sp_instr_jump_if_not &); public: @@ -921,7 +932,7 @@ public: virtual uint opt_mark(sp_head *sp, List<sp_instr> *leads); - /* Override sp_instr_jump's shortcut; we stop here */ + /** Override sp_instr_jump's shortcut; we stop here */ virtual uint opt_shortcut_jump(sp_head *sp, sp_instr *start) { return m_ip; @@ -938,7 +949,7 @@ public: private: - Item *m_expr; // The condition + Item *m_expr; ///< The condition sp_lex_keeper m_lex_keeper; }; // class sp_instr_jump_if_not : public sp_instr_jump @@ -946,7 +957,7 @@ private: class sp_instr_freturn : public sp_instr { - sp_instr_freturn(const sp_instr_freturn &); /* Prevent use of these */ + sp_instr_freturn(const sp_instr_freturn &); /**< Prevent use of these */ void operator=(sp_instr_freturn &); public: @@ -983,7 +994,7 @@ protected: class sp_instr_hpush_jump : public sp_instr_jump { - sp_instr_hpush_jump(const sp_instr_hpush_jump &); /* Prevent use of these */ + sp_instr_hpush_jump(const sp_instr_hpush_jump &); /**< Prevent use of these */ void operator=(sp_instr_hpush_jump &); public: @@ -1005,7 +1016,7 @@ public: virtual uint opt_mark(sp_head *sp, List<sp_instr> *leads); - /* Override sp_instr_jump's shortcut; we stop here. */ + /** Override sp_instr_jump's shortcut; we stop here. */ virtual uint opt_shortcut_jump(sp_head *sp, sp_instr *start) { return m_ip; @@ -1018,7 +1029,7 @@ public: private: - int m_type; // Handler type + int m_type; ///< Handler type uint m_frame; List<struct sp_cond_type> m_cond; @@ -1027,7 +1038,7 @@ private: class sp_instr_hpop : public sp_instr { - sp_instr_hpop(const sp_instr_hpop &); /* Prevent use of these */ + sp_instr_hpop(const sp_instr_hpop &); /**< Prevent use of these */ void operator=(sp_instr_hpop &); public: @@ -1052,7 +1063,7 @@ private: class sp_instr_hreturn : public sp_instr_jump { - sp_instr_hreturn(const sp_instr_hreturn &); /* Prevent use of these */ + sp_instr_hreturn(const sp_instr_hreturn &); /**< Prevent use of these */ void operator=(sp_instr_hreturn &); public: @@ -1083,10 +1094,10 @@ private: }; // class sp_instr_hreturn : public sp_instr_jump -/* This is DECLARE CURSOR */ +/** This is DECLARE CURSOR */ class sp_instr_cpush : public sp_instr { - sp_instr_cpush(const sp_instr_cpush &); /* Prevent use of these */ + sp_instr_cpush(const sp_instr_cpush &); /**< Prevent use of these */ void operator=(sp_instr_cpush &); public: @@ -1102,7 +1113,7 @@ public: virtual void print(String *str); - /* + /** This call is used to cleanup the instruction when a sensitive cursor is closed. For now stored procedures always use materialized cursors and the call is not used. @@ -1111,14 +1122,14 @@ public: private: sp_lex_keeper m_lex_keeper; - uint m_cursor; /* Frame offset (for debugging) */ + uint m_cursor; /**< Frame offset (for debugging) */ }; // class sp_instr_cpush : public sp_instr class sp_instr_cpop : public sp_instr { - sp_instr_cpop(const sp_instr_cpop &); /* Prevent use of these */ + sp_instr_cpop(const sp_instr_cpop &); /**< Prevent use of these */ void operator=(sp_instr_cpop &); public: @@ -1143,7 +1154,7 @@ private: class sp_instr_copen : public sp_instr { - sp_instr_copen(const sp_instr_copen &); /* Prevent use of these */ + sp_instr_copen(const sp_instr_copen &); /**< Prevent use of these */ void operator=(sp_instr_copen &); public: @@ -1163,14 +1174,14 @@ public: private: - uint m_cursor; // Stack index + uint m_cursor; ///< Stack index }; // class sp_instr_copen : public sp_instr_stmt class sp_instr_cclose : public sp_instr { - sp_instr_cclose(const sp_instr_cclose &); /* Prevent use of these */ + sp_instr_cclose(const sp_instr_cclose &); /**< Prevent use of these */ void operator=(sp_instr_cclose &); public: @@ -1195,7 +1206,7 @@ private: class sp_instr_cfetch : public sp_instr { - sp_instr_cfetch(const sp_instr_cfetch &); /* Prevent use of these */ + sp_instr_cfetch(const sp_instr_cfetch &); /**< Prevent use of these */ void operator=(sp_instr_cfetch &); public: @@ -1228,7 +1239,7 @@ private: class sp_instr_error : public sp_instr { - sp_instr_error(const sp_instr_error &); /* Prevent use of these */ + sp_instr_error(const sp_instr_error &); /**< Prevent use of these */ void operator=(sp_instr_error &); public: diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 763195f6516..41596b4faf2 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1020,7 +1020,7 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables, bool have_lock, */ thd->mysys_var->current_mutex= &LOCK_open; thd->mysys_var->current_cond= &COND_refresh; - thd->proc_info="Flushing tables"; + thd_proc_info(thd, "Flushing tables"); close_old_data_files(thd,thd->open_tables,1,1); mysql_ha_flush(thd); @@ -1088,7 +1088,7 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables, bool have_lock, pthread_mutex_lock(&thd->mysys_var->mutex); thd->mysys_var->current_mutex= 0; thd->mysys_var->current_cond= 0; - thd->proc_info=0; + thd_proc_info(thd, 0); pthread_mutex_unlock(&thd->mysys_var->mutex); } DBUG_RETURN(result); @@ -1404,7 +1404,7 @@ void close_thread_tables(THD *thd) good idea to turn off OPTION_TABLE_LOCK flag. */ DBUG_ASSERT(thd->lex->requires_prelocking()); - thd->options&= ~(ulong) (OPTION_TABLE_LOCK); + thd->options&= ~(OPTION_TABLE_LOCK); } DBUG_VOID_RETURN; @@ -2024,7 +2024,7 @@ static void relink_unused(TABLE *table) /** - @brief Prepare an open merge table for close. + Prepare an open merge table for close. @param[in] thd thread context @param[in] table table to prepare @@ -2095,8 +2095,8 @@ static void unlink_open_merge(THD *thd, TABLE *table, TABLE ***prev_pp) /** - @brief Remove all instances of table from thread's open list and - table cache. + Remove all instances of table from thread's open list and + table cache. @param thd Thread context @param find Table to remove @@ -2159,7 +2159,7 @@ void unlink_open_table(THD *thd, TABLE *find, bool unlock) /** - @brief Auxiliary routine which closes and drops open table. + Auxiliary routine which closes and drops open table. @param thd Thread handle @param table TABLE object for table to be dropped @@ -2215,7 +2215,7 @@ void wait_for_condition(THD *thd, pthread_mutex_t *mutex, pthread_cond_t *cond) thd->mysys_var->current_mutex= mutex; thd->mysys_var->current_cond= cond; proc_info=thd->proc_info; - thd->proc_info="Waiting for table"; + thd_proc_info(thd, "Waiting for table"); DBUG_ENTER("wait_for_condition"); if (!thd->killed) (void) pthread_cond_wait(cond, mutex); @@ -2235,7 +2235,7 @@ void wait_for_condition(THD *thd, pthread_mutex_t *mutex, pthread_cond_t *cond) pthread_mutex_lock(&thd->mysys_var->mutex); thd->mysys_var->current_mutex= 0; thd->mysys_var->current_cond= 0; - thd->proc_info= proc_info; + thd_proc_info(thd, proc_info); pthread_mutex_unlock(&thd->mysys_var->mutex); DBUG_VOID_RETURN; } @@ -2366,9 +2366,9 @@ bool reopen_name_locked_table(THD* thd, TABLE_LIST* table_list, bool link_in) /** - @brief Create and insert into table cache placeholder for table - which will prevent its opening (or creation) (a.k.a lock - table name). + Create and insert into table cache placeholder for table + which will prevent its opening (or creation) (a.k.a lock + table name). @param thd Thread context @param key Table cache key for name to be locked @@ -2417,8 +2417,8 @@ TABLE *table_cache_insert_placeholder(THD *thd, const char *key, /** - @brief Obtain an exclusive name lock on the table if it is not cached - in the table cache. + Obtain an exclusive name lock on the table if it is not cached + in the table cache. @param thd Thread context @param db Name of database @@ -2469,8 +2469,8 @@ bool lock_table_name_if_not_cached(THD *thd, const char *db, /** - @brief Check that table exists in table definition cache, on disk - or in some storage engine. + Check that table exists in table definition cache, on disk + or in some storage engine. @param thd Thread context @param table Table list element @@ -3184,8 +3184,8 @@ bool reopen_table(TABLE *table) /** - @brief Close all instances of a table open by this thread and replace - them with exclusive name-locks. + Close all instances of a table open by this thread and replace + them with exclusive name-locks. @param thd Thread context @param db Database name for the table to be closed @@ -3254,7 +3254,7 @@ void close_data_files_and_morph_locks(THD *thd, const char *db, /** - @brief Reattach MERGE children after reopen. + Reattach MERGE children after reopen. @param[in] thd thread context @param[in,out] err_tables_p pointer to pointer of tables in error @@ -3310,7 +3310,7 @@ static bool reattach_merge(THD *thd, TABLE **err_tables_p) /** - @brief Reopen all tables with closed data files. + Reopen all tables with closed data files. @param thd Thread context @param get_locks Should we get locks after reopening tables ? @@ -3458,8 +3458,8 @@ bool reopen_tables(THD *thd, bool get_locks, bool mark_share_as_old) /** - @brief Close handlers for tables in list, but leave the TABLE structure - intact so that we can re-open these quickly. + Close handlers for tables in list, but leave the TABLE structure + intact so that we can re-open these quickly. @param thd Thread context @param table Head of the list of TABLE objects @@ -3607,7 +3607,7 @@ bool wait_for_tables(THD *thd) bool result; DBUG_ENTER("wait_for_tables"); - thd->proc_info="Waiting for tables"; + thd_proc_info(thd, "Waiting for tables"); pthread_mutex_lock(&LOCK_open); while (!thd->killed) { @@ -3623,12 +3623,12 @@ bool wait_for_tables(THD *thd) else { /* Now we can open all tables without any interference */ - thd->proc_info="Reopen tables"; + thd_proc_info(thd, "Reopen tables"); thd->version= refresh_version; result=reopen_tables(thd,0,0); } pthread_mutex_unlock(&LOCK_open); - thd->proc_info=0; + thd_proc_info(thd, 0); DBUG_RETURN(result); } @@ -4389,7 +4389,7 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags) restart: *counter= 0; query_tables_last_own= 0; - thd->proc_info="Opening tables"; + thd_proc_info(thd, "Opening tables"); /* If we are not already executing prelocked statement and don't have @@ -4644,7 +4644,7 @@ process_view_routines: } err: - thd->proc_info=0; + thd_proc_info(thd, 0); free_root(&new_frm_mem, MYF(0)); // Free pre-alloced block if (query_tables_last_own) @@ -4789,7 +4789,7 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type, bool refresh; DBUG_ENTER("open_ltable"); - thd->proc_info="Opening table"; + thd_proc_info(thd, "Opening table"); thd->current_tablenr= 0; /* open_ltable can be used only for BASIC TABLEs */ table_list->required_type= FRMTYPE_TABLE; @@ -4829,7 +4829,7 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type, } end: - thd->proc_info=0; + thd_proc_info(thd, 0); DBUG_RETURN(table); } @@ -5175,7 +5175,7 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, bool *need_reopen) { if (thd->lex->requires_prelocking()) { - thd->options&= ~(ulong) (OPTION_TABLE_LOCK); + thd->options&= ~(OPTION_TABLE_LOCK); thd->in_lock_tables=0; } DBUG_RETURN(-1); @@ -5219,7 +5219,7 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, bool *need_reopen) ha_rollback_stmt(thd); mysql_unlock_tables(thd, thd->locked_tables); thd->locked_tables= 0; - thd->options&= ~(ulong) (OPTION_TABLE_LOCK); + thd->options&= ~(OPTION_TABLE_LOCK); DBUG_RETURN(-1); } } @@ -8360,7 +8360,7 @@ int init_ftfuncs(THD *thd, SELECT_LEX *select_lex, bool no_order) List_iterator<Item_func_match> li(*(select_lex->ftfunc_list)); Item_func_match *ifm; DBUG_PRINT("info",("Performing FULLTEXT search")); - thd->proc_info="FULLTEXT initialization"; + thd_proc_info(thd, "FULLTEXT initialization"); while ((ifm=li++)) ifm->init_search(no_order); diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index f1803a329c5..e51c53f644e 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -704,6 +704,7 @@ void query_cache_insert(NET *net, const char *packet, ulong length) void query_cache_abort(NET *net) { DBUG_ENTER("query_cache_abort"); + THD *thd= current_thd; /* See the comment on double-check locking usage above. */ if (net->query_cache_query == 0) @@ -726,6 +727,7 @@ void query_cache_abort(NET *net) net->query_cache_query); if (query_block) { + thd_proc_info(thd, "storing result in query cache"); DUMP(&query_cache); BLOCK_LOCK_WR(query_block); // The following call will remove the lock on query_block @@ -778,6 +780,7 @@ void query_cache_end_of_result(THD *thd) suitable size if needed and setting block type. Since this is the last block, the writer should be dropped. */ + thd_proc_info(thd, "storing result in query cache"); DUMP(&query_cache); BLOCK_LOCK_WR(query_block); Query_cache_query *header= query_block->query(); @@ -1201,6 +1204,8 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length) DBUG_PRINT("qcache", ("No active database")); } + thd_proc_info(thd, "checking query cache for query"); + // fill all gaps between fields with 0 to get repeatable key bzero(&flags, QUERY_CACHE_FLAGS_SIZE); flags.client_long_flag= test(thd->client_capabilities & CLIENT_LONG_FLAG); @@ -1283,6 +1288,7 @@ def_week_frmt: %lu", } // Check access; + thd_proc_info(thd, "checking privileges on cached query"); block_table= query_block->table(0); block_table_end= block_table+query_block->n_tables; for (; block_table != block_table_end; block_table++) @@ -1377,6 +1383,7 @@ def_week_frmt: %lu", Send cached result to client */ #ifndef EMBEDDED_LIBRARY + thd_proc_info(thd, "sending cached result to client"); do { DBUG_PRINT("qcache", ("Results (len: %lu used: %lu headers: %lu)", @@ -1453,6 +1460,7 @@ void Query_cache::invalidate(CHANGED_TABLE_LIST *tables_used) THD *thd= current_thd; for (; tables_used; tables_used= tables_used->next) { + thd_proc_info(thd, "invalidating query cache entries (table list)"); invalidate_table(thd, (uchar*) tables_used->key, tables_used->key_length); DBUG_PRINT("qcache", ("db: %s table: %s", tables_used->key, tables_used->key+ @@ -1474,9 +1482,11 @@ void Query_cache::invalidate(CHANGED_TABLE_LIST *tables_used) */ void Query_cache::invalidate_locked_for_write(TABLE_LIST *tables_used) { + THD *thd= current_thd; DBUG_ENTER("Query_cache::invalidate_locked_for_write"); for (; tables_used; tables_used= tables_used->next_local) { + thd_proc_info(thd, "invalidating query cache entries (table)"); if (tables_used->lock_type & (TL_WRITE_LOW_PRIORITY | TL_WRITE) && tables_used->table) { @@ -1525,7 +1535,7 @@ void Query_cache::invalidate(THD *thd, const char *key, uint32 key_length, /** - @brief Synchronize the thread with any flushing operations. + Synchronize the thread with any flushing operations. This helper function is called whenever a thread needs to operate on the query cache structure (example: during invalidation). If a table flush is in @@ -1566,7 +1576,7 @@ void Query_cache::wait_while_table_flush_is_in_progress(bool *interrupt) /** - @brief Remove all cached queries that uses the given database + Remove all cached queries that uses the given database. */ void Query_cache::invalidate(char *db) @@ -1676,8 +1686,8 @@ void Query_cache::flush() /** - @brief Rearrange the memory blocks and join result in cache in 1 block (if - result length > join_limit) + Rearrange the memory blocks and join result in cache in 1 block (if + result length > join_limit) @param[in] join_limit If the minimum length of a result block to be joined. @param[in] iteration_limit The maximum number of packing and joining @@ -1947,7 +1957,7 @@ void Query_cache::make_disabled() /** @class Query_cache - @brief Free all resources allocated by the cache. + Free all resources allocated by the cache. This function frees all resources allocated by the cache. You have to call init_cache() before using the cache again. This function @@ -1971,7 +1981,7 @@ void Query_cache::free_cache() /** - @brief Flush the cache. + Flush the cache. This function will flush cache contents. It assumes we have 'structure_guard_mutex' locked. The function sets the m_cache_status flag and @@ -2517,7 +2527,7 @@ Query_cache::invalidate_table_internal(THD *thd, uchar *key, uint32 key_length) } /** - @brief Invalidate a linked list of query cache blocks. + Invalidate a linked list of query cache blocks. Each block tries to aquire a block level lock before free_query is a called. This function will in turn affect @@ -2685,7 +2695,7 @@ my_bool Query_cache::register_all_tables(Query_cache_block *block, /** - @brief Insert used table name into the cache. + Insert used table name into the cache. @return Error status @retval FALSE On error @@ -3414,8 +3424,8 @@ my_bool Query_cache::ask_handler_allowance(THD *thd, /** - @brief Rearrange all memory blocks so that free memory joins at the - 'bottom' of the allocated memory block containing all cache data. + Rearrange all memory blocks so that free memory joins at the + 'bottom' of the allocated memory block containing all cache data. @see Query_cache::pack(ulong join_limit, uint iteration_limit) */ @@ -4029,7 +4039,7 @@ void Query_cache::tables_dump() /** - @brief Checks integrity of the various linked lists + Checks integrity of the various linked lists @return Error status code @retval FALSE Query cache is operational. diff --git a/sql/sql_cache.h b/sql/sql_cache.h index b47e2e9a43b..f2c33eff614 100644 --- a/sql/sql_cache.h +++ b/sql/sql_cache.h @@ -66,8 +66,8 @@ struct Query_cache_result; class Query_cache; /** - @brief This class represents a node in the linked chain of queries - belonging to one table. + This class represents a node in the linked chain of queries + belonging to one table. @note The root of this linked list is not a query-type block, but the table- type block which all queries has in common. diff --git a/sql/sql_class.cc b/sql/sql_class.cc index b4d728daa5e..75376c53f68 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -247,9 +247,16 @@ int thd_tablespace_op(const THD *thd) extern "C" -const char *thd_proc_info(THD *thd, const char *info) +const char *set_thd_proc_info(THD *thd, const char *info, + const char *calling_function, + const char *calling_file, + const unsigned int calling_line) { const char *old_info= thd->proc_info; + DBUG_PRINT("proc_info", ("%s:%d %s", calling_file, calling_line, info)); +#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) + thd->profiling.status_change(info, calling_function, calling_file, calling_line); +#endif thd->proc_info= info; return old_info; } @@ -573,6 +580,9 @@ THD::THD() init(); /* Initialize sub structures */ init_sql_alloc(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE); +#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) + profiling.set_thd(this); +#endif user_connect=(USER_CONN *)0; hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0, (hash_get_key) get_var_key, @@ -1069,7 +1079,7 @@ void THD::cleanup_after_query() /** - Create a LEX_STRING in this connection + Create a LEX_STRING in this connection. @param lex_str pointer to LEX_STRING object to be initialized @param str initializer to be copied into lex_str diff --git a/sql/sql_class.h b/sql/sql_class.h index 8c2c2dce1de..e8f28b19213 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -77,10 +77,10 @@ typedef struct st_user_var_events was actually changed or not. */ typedef struct st_copy_info { - ha_rows records; /* Number of processed records */ - ha_rows deleted; /* Number of deleted records */ - ha_rows updated; /* Number of updated records */ - ha_rows copied; /* Number of copied records */ + ha_rows records; /**< Number of processed records */ + ha_rows deleted; /**< Number of deleted records */ + ha_rows updated; /**< Number of updated records */ + ha_rows copied; /**< Number of copied records */ ha_rows error_count; ha_rows touched; /* Number of touched records */ enum enum_duplicates handle_duplicates; @@ -274,6 +274,7 @@ struct system_variables ulong optimizer_prune_level; ulong optimizer_search_depth; ulong preload_buff_size; + ulong profiling_history_size; ulong query_cache_type; ulong read_buff_size; ulong read_rnd_buff_size; @@ -1162,14 +1163,17 @@ public: */ char *catalog; - /* - WARNING: some members of THD (currently 'Statement::db', + /** + @note + Some members of THD (currently 'Statement::db', 'catalog' and 'query') are set and alloced by the slave SQL thread (for the THD of that thread); that thread is (and must remain, for now) the only responsible for freeing these 3 members. If you add members here, and you add code to set them in replication, don't forget to free_them_and_set_them_to_0 in replication properly. For details see the 'err:' label of the handle_slave_sql() in sql/slave.cc. + + @see handle_slave_sql */ Security_context main_security_ctx; @@ -1179,6 +1183,9 @@ public: Points to info-string that we show in SHOW PROCESSLIST You are supposed to update thd->proc_info only if you have coded a time-consuming piece that MySQL can get stuck in for a long time. + + Set it using the thd_proc_info(THD *thread, const char *message) + macro/function. */ const char *proc_info; @@ -1515,6 +1522,10 @@ public: uint warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_END]; uint total_warn_count; Diagnostics_area main_da; +#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) + PROFILING profiling; +#endif + /* Id of current query. Statement can be reused to execute several queries query_id is global in context of the whole MySQL server. diff --git a/sql/sql_cursor.cc b/sql/sql_cursor.cc index d31c0af1163..2301b561797 100644 --- a/sql/sql_cursor.cc +++ b/sql/sql_cursor.cc @@ -24,9 +24,9 @@ Declarations. ****************************************************************************/ -/* +/** Sensitive_cursor -- a sensitive non-materialized server side - cursor An instance of this class cursor has its own runtime + cursor. An instance of this class cursor has its own runtime state -- list of used items and memory root for runtime memory, open and locked tables, change list for the changes of the parsed tree. This state is freed when the cursor is closed. @@ -69,7 +69,7 @@ public: }; -/* +/** Materialized_cursor -- an insensitive materialized server-side cursor. The result set of this cursor is saved in a temporary table at open. The cursor itself is simply an interface for the @@ -96,7 +96,7 @@ public: }; -/* +/** Select_materialize -- a mediator between a cursor query and the protocol. In case we were not able to open a non-materialzed cursor, it creates an internal temporary HEAP table, and insert @@ -107,7 +107,7 @@ public: class Select_materialize: public select_union { - select_result *result; /* the result object of the caller (PS or SP) */ + select_result *result; /**< the result object of the caller (PS or SP) */ public: Select_materialize(select_result *result_arg) :result(result_arg) {} virtual bool send_fields(List<Item> &list, uint flags); @@ -116,22 +116,21 @@ public: /**************************************************************************/ -/* +/** Attempt to open a materialized or non-materialized cursor. - SYNOPSIS - mysql_open_cursor() - thd thread handle - flags [in] create a materialized cursor or not - result [in] result class of the caller used as a destination - for the rows fetched from the cursor - pcursor [out] a pointer to store a pointer to cursor in - - RETURN VALUE - 0 the query has been successfully executed; in this - case pcursor may or may not contain - a pointer to an open cursor. - non-zero an error, 'pcursor' has been left intact. + @param thd thread handle + @param[in] flags create a materialized cursor or not + @param[in] result result class of the caller used as a destination + for the rows fetched from the cursor + @param[out] pcursor a pointer to store a pointer to cursor in + + @retval + 0 the query has been successfully executed; in this + case pcursor may or may not contain + a pointer to an open cursor. + @retval + non-zero an error, 'pcursor' has been left intact. */ int mysql_open_cursor(THD *thd, uint flags, select_result *result, @@ -279,6 +278,14 @@ Sensitive_cursor::Sensitive_cursor(THD *thd, select_result *result_arg) } +/** + Save THD state into cursor. + + @todo + - XXX: thd->locked_tables is not changed. + - What problems can we have with it if cursor is open? + - TODO: must be fixed because of the prelocked mode. +*/ void Sensitive_cursor::post_open(THD *thd) { @@ -334,6 +341,10 @@ Sensitive_cursor::post_open(THD *thd) } +/** + bzero cursor state in THD. +*/ + void Sensitive_cursor::reset_thd(THD *thd) { @@ -393,20 +404,13 @@ Sensitive_cursor::open(JOIN *join_arg) } -/* - SYNOPSIS - Sensitive_cursor::fetch() - num_rows fetch up to this number of rows (maybe less) - - DESCRIPTION - Fetch next num_rows rows from the cursor and send them to the client +/** + Fetch next num_rows rows from the cursor and send them to the client. - Precondition: - Sensitive_cursor is open + Precondition: + - Sensitive_cursor is open - RETURN VALUES: - none, this function will send OK to the clinet or set an error - message in THD + @param num_rows fetch up to this number of rows (maybe less) */ void @@ -478,6 +482,11 @@ Sensitive_cursor::fetch(ulong num_rows) } +/** + @todo + Another hack: we need to set THD state as if in a fetch to be + able to call stmt close. +*/ void Sensitive_cursor::close() { @@ -579,10 +588,9 @@ int Materialized_cursor::open(JOIN *join __attribute__((unused))) } -/* +/** Fetch up to the given number of rows from a materialized cursor. - DESCRIPTION Precondition: the cursor is open. If the cursor points after the last row, the fetch will automatically @@ -590,10 +598,6 @@ int Materialized_cursor::open(JOIN *join __attribute__((unused))) with SERVER_STATUS_LAST_ROW_SENT). This is an extra round trip and probably should be improved to return SERVER_STATUS_LAST_ROW_SENT along with the last row. - - RETURN VALUE - none, in case of success the row is sent to the client, otherwise - an error message is set in THD */ void Materialized_cursor::fetch(ulong num_rows) diff --git a/sql/sql_cursor.h b/sql/sql_cursor.h index 6edd6b24b36..1f19cbfdbcf 100644 --- a/sql/sql_cursor.h +++ b/sql/sql_cursor.h @@ -20,12 +20,14 @@ #pragma interface /* gcc class interface */ #endif -/* +/** + @file + Declarations for implementation of server side cursors. Only read-only non-scrollable cursors are currently implemented. */ -/* +/** Server_side_cursor -- an interface for materialized and sensitive (non-materialized) implementation of cursors. All cursors are self-contained (created in their own memory root). @@ -36,7 +38,7 @@ class Server_side_cursor: protected Query_arena, public Sql_alloc { protected: - /* Row destination used for fetch */ + /** Row destination used for fetch */ select_result *result; public: Server_side_cursor(MEM_ROOT *mem_root_arg, select_result *result_arg) @@ -58,8 +60,7 @@ int mysql_open_cursor(THD *thd, uint flags, select_result *result, Server_side_cursor **res); -/* Possible values for flags */ - +/** Possible values for flags */ enum { ANY_CURSOR= 1, ALWAYS_MATERIALIZED_CURSOR= 2 }; #endif /* _sql_cusor_h_ */ diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index a73963d7f86..56748772523 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -50,7 +50,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, table_list->view_db.str, table_list->view_name.str); DBUG_RETURN(TRUE); } - thd->proc_info="init"; + thd_proc_info(thd, "init"); table->map=1; if (mysql_prepare_delete(thd, table_list, &conds)) @@ -240,7 +240,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, init_read_record_idx(&info, thd, table, 1, usable_index); init_ftfuncs(thd, select_lex, 1); - thd->proc_info="updating"; + thd_proc_info(thd, "updating"); if (table->triggers && table->triggers->has_triggers(TRG_EVENT_DELETE, TRG_ACTION_AFTER)) @@ -317,7 +317,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, table->file->print_error(loc_error,MYF(0)); error=1; } - thd->proc_info= "end"; + thd_proc_info(thd, "end"); end_read_record(&info); if (options & OPTION_QUICK) (void) table->file->extra(HA_EXTRA_NORMAL); @@ -561,7 +561,7 @@ multi_delete::prepare(List<Item> &values, SELECT_LEX_UNIT *u) DBUG_ENTER("multi_delete::prepare"); unit= u; do_delete= 1; - thd->proc_info="deleting from main table"; + thd_proc_info(thd, "deleting from main table"); DBUG_RETURN(0); } @@ -880,7 +880,7 @@ int multi_delete::do_deletes() bool multi_delete::send_eof() { THD::killed_state killed_status= THD::NOT_KILLED; - thd->proc_info="deleting from reference tables"; + thd_proc_info(thd, "deleting from reference tables"); /* Does deletes for the last n - 1 tables, returns 0 if ok */ int local_error= do_deletes(); // returns 0 if success @@ -889,7 +889,7 @@ bool multi_delete::send_eof() local_error= local_error || error; killed_status= (local_error == 0)? THD::NOT_KILLED : thd->killed; /* reset used flags */ - thd->proc_info="end"; + thd_proc_info(thd, "end"); /* We must invalidate the query cache before binlog writing and @@ -1047,7 +1047,7 @@ trunc_by_del: /* Probably InnoDB table */ ulonglong save_options= thd->options; table_list->lock_type= TL_WRITE; - thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_NOT_AUTOCOMMIT); + thd->options&= ~(OPTION_BEGIN | OPTION_NOT_AUTOCOMMIT); ha_enable_transaction(thd, FALSE); mysql_init_select(thd->lex); bool save_binlog_row_based= thd->current_stmt_binlog_row_based; diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 1dd915fb9b6..f9dbd402de7 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -611,7 +611,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, } lock_type= table_list->lock_type; - thd->proc_info="init"; + thd_proc_info(thd, "init"); thd->used_tables=0; values= its++; value_count= values->elements; @@ -695,7 +695,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, #endif error=0; - thd->proc_info="update"; + thd_proc_info(thd, "update"); if (duplic != DUP_ERROR || ignore) table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); if (duplic == DUP_REPLACE && @@ -911,7 +911,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, thd->lock=0; } } - thd->proc_info="end"; + thd_proc_info(thd, "end"); /* We'll report to the client this id: - if the table contains an autoincrement column and we successfully @@ -1770,7 +1770,7 @@ I_List<Delayed_insert> delayed_threads; static Delayed_insert *find_handler(THD *thd, TABLE_LIST *table_list) { - thd->proc_info="waiting for delay_list"; + thd_proc_info(thd, "waiting for delay_list"); pthread_mutex_lock(&LOCK_delayed_insert); // Protect master list I_List_iterator<Delayed_insert> it(delayed_threads); Delayed_insert *di; @@ -1852,7 +1852,7 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list) */ if (delayed_insert_threads >= thd->variables.max_insert_delayed_threads) DBUG_RETURN(0); - thd->proc_info="Creating delayed handler"; + thd_proc_info(thd, "Creating delayed handler"); pthread_mutex_lock(&LOCK_delayed_create); /* The first search above was done without LOCK_delayed_create. @@ -1899,13 +1899,13 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list) } /* Wait until table is open */ - thd->proc_info="waiting for handler open"; + thd_proc_info(thd, "waiting for handler open"); while (!di->thd.killed && !di->table && !thd->killed) { pthread_cond_wait(&di->cond_client, &di->mutex); } pthread_mutex_unlock(&di->mutex); - thd->proc_info="got old table"; + thd_proc_info(thd, "got old table"); if (di->thd.killed) { if (di->thd.is_error()) @@ -1982,13 +1982,13 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd) tables_in_use++; if (!thd.lock) // Table is not locked { - client_thd->proc_info="waiting for handler lock"; + thd_proc_info(client_thd, "waiting for handler lock"); pthread_cond_signal(&cond); // Tell handler to lock table while (!dead && !thd.lock && ! client_thd->killed) { pthread_cond_wait(&cond_client,&mutex); } - client_thd->proc_info="got handler lock"; + thd_proc_info(client_thd, "got handler lock"); if (client_thd->killed) goto error; if (dead) @@ -2006,7 +2006,7 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd) bytes. Since the table copy is used for creating one record only, the other record buffers and alignment are unnecessary. */ - client_thd->proc_info="allocating local table"; + thd_proc_info(client_thd, "allocating local table"); copy= (TABLE*) client_thd->alloc(sizeof(*copy)+ (share->fields+1)*sizeof(Field**)+ share->reclength + @@ -2091,11 +2091,11 @@ int write_delayed(THD *thd, TABLE *table, enum_duplicates duplic, DBUG_PRINT("enter", ("query = '%s' length %lu", query.str, (ulong) query.length)); - thd->proc_info="waiting for handler insert"; + thd_proc_info(thd, "waiting for handler insert"); pthread_mutex_lock(&di->mutex); while (di->stacked_inserts >= delayed_queue_size && !thd->killed) pthread_cond_wait(&di->cond_client,&di->mutex); - thd->proc_info="storing row into queue"; + thd_proc_info(thd, "storing row into queue"); if (thd->killed) goto err; @@ -2341,7 +2341,7 @@ pthread_handler_t handle_delayed_insert(void *arg) /* Information for pthread_kill */ di->thd.mysys_var->current_mutex= &di->mutex; di->thd.mysys_var->current_cond= &di->cond; - di->thd.proc_info="Waiting for INSERT"; + thd_proc_info(&(di->thd), "Waiting for INSERT"); DBUG_PRINT("info",("Waiting for someone to insert rows")); while (!thd->killed) @@ -2376,7 +2376,7 @@ pthread_handler_t handle_delayed_insert(void *arg) pthread_mutex_unlock(&di->thd.mysys_var->mutex); pthread_mutex_lock(&di->mutex); } - di->thd.proc_info=0; + thd_proc_info(&(di->thd), 0); if (di->tables_in_use && ! thd->lock) { @@ -2517,7 +2517,7 @@ bool Delayed_insert::handle_inserts(void) table->next_number_field=table->found_next_number_field; table->use_all_columns(); - thd.proc_info="upgrading lock"; + thd_proc_info(&thd, "upgrading lock"); if (thr_upgrade_write_delay_lock(*thd.lock->locks)) { /* This can only happen if thread is killed by shutdown */ @@ -2525,7 +2525,7 @@ bool Delayed_insert::handle_inserts(void) goto err; } - thd.proc_info="insert"; + thd_proc_info(&thd, "insert"); max_rows= delayed_insert_limit; if (thd.killed || table->needs_reopen_or_name_lock()) { @@ -2663,7 +2663,7 @@ bool Delayed_insert::handle_inserts(void) { if (tables_in_use) pthread_cond_broadcast(&cond_client); // If waiting clients - thd.proc_info="reschedule"; + thd_proc_info(&thd, "reschedule"); pthread_mutex_unlock(&mutex); if ((error=table->file->extra(HA_EXTRA_NO_CACHE))) { @@ -2683,13 +2683,13 @@ bool Delayed_insert::handle_inserts(void) if (!using_bin_log) table->file->extra(HA_EXTRA_WRITE_CACHE); pthread_mutex_lock(&mutex); - thd.proc_info="insert"; + thd_proc_info(&thd, "insert"); } if (tables_in_use) pthread_cond_broadcast(&cond_client); // If waiting clients } } - thd.proc_info=0; + thd_proc_info(&thd, 0); pthread_mutex_unlock(&mutex); /* diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 7d6f21cad05..5352f8efbbb 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -343,7 +343,7 @@ void lex_start(THD *thd) lex->name.str= 0; lex->name.length= 0; lex->event_parse_data= NULL; - + lex->profile_options= PROFILE_NONE; lex->nest_level=0 ; lex->allow_sum_func= 0; lex->in_sum_func= NULL; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index cdae7449cc7..ef0a9bb11ef 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -117,9 +117,13 @@ enum enum_sql_command { SQLCOM_SHOW_CREATE_EVENT, SQLCOM_SHOW_EVENTS, SQLCOM_SHOW_CREATE_TRIGGER, SQLCOM_ALTER_DB_UPGRADE, + SQLCOM_SHOW_PROFILE, SQLCOM_SHOW_PROFILES, + /* + When a command is added here, be sure it's also added in mysqld.cc + in "struct show_var_st status_vars[]= {" ... + */ /* This should be the last !!! */ - SQLCOM_END }; @@ -1595,6 +1599,9 @@ typedef struct st_lex : public Query_tables_list enum enum_var_type option_type; enum enum_view_create_mode create_view_mode; enum enum_drop_mode drop_mode; + + uint profile_query_id; + uint profile_options; uint uint_geom_type; uint grant, grant_tot_col, which_columns; uint fk_delete_opt, fk_update_opt, fk_match_option; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index b60a72e4c53..ecee3fcb97f 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -115,7 +115,7 @@ bool end_active_trans(THD *thd) if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN | OPTION_TABLE_LOCK)) { - DBUG_PRINT("info",("options: 0x%lx", (ulong) thd->options)); + DBUG_PRINT("info",("options: 0x%llx", thd->options)); /* Safety if one did "drop table" on locked tables */ if (!thd->locked_tables) thd->options&= ~OPTION_TABLE_LOCK; @@ -157,8 +157,8 @@ bool begin_trans(THD *thd) } #ifdef HAVE_REPLICATION -/* - Returns true if all tables should be ignored +/** + Returns true if all tables should be ignored. */ inline bool all_tables_not_ok(THD *thd, TABLE_LIST *tables) { @@ -181,9 +181,10 @@ static bool some_non_temp_table_to_be_updated(THD *thd, TABLE_LIST *tables) } -/* - Mark all commands that somehow changes a table - This is used to check number of updates / hour +/** + Mark all commands that somehow changes a table. + + This is used to check number of updates / hour. sql_command is actually set to SQLCOM_END sometimes so we need the +1 to include it in the array. @@ -265,6 +266,8 @@ void init_update_queries(void) sql_command_flags[SQLCOM_SHOW_PROC_CODE]= CF_STATUS_COMMAND; sql_command_flags[SQLCOM_SHOW_FUNC_CODE]= CF_STATUS_COMMAND; sql_command_flags[SQLCOM_SHOW_CREATE_EVENT]= CF_STATUS_COMMAND; + sql_command_flags[SQLCOM_SHOW_PROFILES]= CF_STATUS_COMMAND; + sql_command_flags[SQLCOM_SHOW_PROFILE]= CF_STATUS_COMMAND; sql_command_flags[SQLCOM_SHOW_TABLES]= (CF_STATUS_COMMAND | CF_SHOW_TABLE_COMMAND); @@ -313,7 +316,7 @@ void execute_init_command(THD *thd, sys_var_str *init_command_var, Vio* save_vio; ulong save_client_capabilities; - thd->proc_info= "Execution of init_command"; + thd_proc_info(thd, "Execution of init_command"); /* We need to lock init_command_var because during execution of init_command_var query @@ -337,9 +340,10 @@ void execute_init_command(THD *thd, sys_var_str *init_command_var, } -/* +/** Execute commands from bootstrap_file. - Used when creating the initial grant tables + + Used when creating the initial grant tables. */ pthread_handler_t handle_bootstrap(void *arg) @@ -369,7 +373,7 @@ pthread_handler_t handle_bootstrap(void *arg) if (thd->variables.max_join_size == HA_POS_ERROR) thd->options |= OPTION_BIG_SELECTS; - thd->proc_info=0; + thd_proc_info(thd, 0); thd->version=refresh_version; thd->security_ctx->priv_user= thd->security_ctx->user= (char*) my_strdup("boot", MYF(MY_WME)); @@ -423,6 +427,10 @@ pthread_handler_t handle_bootstrap(void *arg) QUERY_CACHE_FLAGS_SIZE); thd->query[length] = '\0'; DBUG_PRINT("query",("%-.4096s",thd->query)); +#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) + thd->profiling.set_query_source(thd->query, length); +#endif + /* We don't need to obtain LOCK_thread_count here because in bootstrap mode we have only one thread. @@ -525,21 +533,20 @@ void cleanup_items(Item *item) DBUG_VOID_RETURN; } -/* - Handle COM_TABLE_DUMP command +/** + Handle COM_TABLE_DUMP command. - SYNOPSIS - mysql_table_dump - thd thread handle - db database name or an empty string. If empty, - the current database of the connection is used - tbl_name name of the table to dump + @param thd thread handle + @param db database name or an empty string. If empty, + the current database of the connection is used + @param tbl_name name of the table to dump - NOTES + @note This function is written to handle one specific command only. - RETURN VALUE + @retval 0 success + @retval 1 error, the error message is set in THD */ @@ -593,16 +600,14 @@ err: DBUG_RETURN(error); } -/* - Ends the current transaction and (maybe) begin the next +/** + Ends the current transaction and (maybe) begin the next. - SYNOPSIS - end_trans() - thd Current thread - completion Completion type + @param thd Current thread + @param completion Completion type - RETURN - 0 - OK + @retval + 0 OK */ int end_trans(THD *thd, enum enum_mysql_completiontype completion) @@ -631,7 +636,7 @@ int end_trans(THD *thd, enum enum_mysql_completiontype completion) */ thd->server_status&= ~SERVER_STATUS_IN_TRANS; res= ha_commit(thd); - thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_KEEP_LOG); + thd->options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG); thd->transaction.all.modified_non_trans_table= FALSE; break; case COMMIT_RELEASE: @@ -649,7 +654,7 @@ int end_trans(THD *thd, enum enum_mysql_completiontype completion) thd->server_status&= ~SERVER_STATUS_IN_TRANS; if (ha_rollback(thd)) res= -1; - thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_KEEP_LOG); + thd->options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG); thd->transaction.all.modified_non_trans_table= FALSE; if (!res && (completion == ROLLBACK_AND_CHAIN)) res= begin_trans(thd); @@ -671,18 +676,21 @@ int end_trans(THD *thd, enum enum_mysql_completiontype completion) #ifndef EMBEDDED_LIBRARY -/* +/** Read one command from connection and execute it (query or simple command). This function is called in loop from thread function. - SYNOPSIS - do_command() - RETURN VALUE + + For profiling to work, it must never be called recursively. + + @retval 0 success + @retval 1 request of thread shutdown (see dispatch_command() description) */ bool do_command(THD *thd) { + bool return_value; char *packet= 0; ulong packet_length; NET *net= &thd->net; @@ -711,7 +719,12 @@ bool do_command(THD *thd) thd->main_da.reset_diagnostics_area(); net_new_transaction(net); - if ((packet_length=my_net_read(net)) == packet_error) + + packet_length= my_net_read(net); +#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) + thd->profiling.start_new_query(); +#endif + if (packet_length == packet_error) { DBUG_PRINT("info",("Got error %d reading command from socket %s", net->error, @@ -724,10 +737,14 @@ bool do_command(THD *thd) net_end_statement(thd); if (net->error != 3) - DBUG_RETURN(TRUE); // We have to close it. + { + return_value= TRUE; // We have to close it. + goto out; + } net->error= 0; - DBUG_RETURN(FALSE); + return_value= FALSE; + goto out; } packet= (char*) net->read_pos; @@ -761,11 +778,16 @@ bool do_command(THD *thd) my_net_set_read_timeout(net, thd->variables.net_read_timeout); DBUG_ASSERT(packet_length); - DBUG_RETURN(dispatch_command(command, thd, packet+1, (uint) (packet_length-1))); + return_value= dispatch_command(command, thd, packet+1, (uint) (packet_length-1)); + +out: +#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) + thd->profiling.finish_current_query(); +#endif + DBUG_RETURN(return_value); } #endif /* EMBEDDED_LIBRARY */ - /** @brief Determine if an attempt to update a non-temporary table while the read-only option was enabled has been made. @@ -834,21 +856,27 @@ static my_bool deny_updates_if_read_only_option(THD *thd, DBUG_RETURN(FALSE); } -/* - Perform one connection-level (COM_XXXX) command. +/** + Perform one connection-level (COM_XXXX) command. - SYNOPSIS - dispatch_command() - thd connection handle - command type of command to perform - packet data for the command, packet is always null-terminated - packet_length length of packet. Can be zero, e.g. in case of COM_SLEEP. - RETURN VALUE + @param command type of command to perform + @param thd connection handle + @param packet data for the command, packet is always null-terminated + @param packet_length length of packet + 1 (to show that data is + null-terminated) except for COM_SLEEP, where it + can be zero. + + @todo + set thd->lex->sql_command to SQLCOM_END here. + @todo + The following has to be changed to an 8 byte integer + + @retval 0 ok + @retval 1 request of thread shutdown, i. e. if command is COM_QUIT/COM_SHUTDOWN */ - bool dispatch_command(enum enum_server_command command, THD *thd, char* packet, uint packet_length) { @@ -1079,19 +1107,22 @@ bool dispatch_command(enum enum_server_command command, THD *thd, break; // fatal error is set char *packet_end= thd->query + thd->query_length; /* 'b' stands for 'buffer' parameter', special for 'my_snprintf' */ - const char* found_semicolon= NULL; + const char* end_of_stmt= NULL; general_log_write(thd, command, thd->query, thd->query_length); DBUG_PRINT("query",("%-.4096s",thd->query)); +#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) + thd->profiling.set_query_source(thd->query, thd->query_length); +#endif if (!(specialflag & SPECIAL_NO_PRIOR)) my_pthread_setprio(pthread_self(),QUERY_PRIOR); - mysql_parse(thd, thd->query, thd->query_length, & found_semicolon); + mysql_parse(thd, thd->query, thd->query_length, &end_of_stmt); - while (!thd->killed && found_semicolon && ! thd->is_error()) + while (!thd->killed && (end_of_stmt != NULL) && ! thd->is_error()) { - char *next_packet= (char*) found_semicolon; + char *beginning_of_next_stmt= (char*) end_of_stmt; net_end_statement(thd); query_cache_end_of_result(thd); @@ -1099,24 +1130,31 @@ bool dispatch_command(enum enum_server_command command, THD *thd, Multiple queries exits, execute them individually */ close_thread_tables(thd); - ulong length= (ulong)(packet_end - next_packet); + ulong length= (ulong)(packet_end - beginning_of_next_stmt); log_slow_statement(thd); /* Remove garbage at start of query */ - while (my_isspace(thd->charset(), *next_packet) && length > 0) + while (length > 0 && my_isspace(thd->charset(), *beginning_of_next_stmt)) { - next_packet++; + beginning_of_next_stmt++; length--; } + +#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) + thd->profiling.finish_current_query(); + thd->profiling.start_new_query("continuing"); + thd->profiling.set_query_source(beginning_of_next_stmt, length); +#endif + VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->query_length= length; - thd->query= next_packet; + thd->query= beginning_of_next_stmt; thd->query_id= next_query_id(); thd->set_time(); /* Reset the query start time. */ /* TODO: set thd->lex->sql_command to SQLCOM_END here */ VOID(pthread_mutex_unlock(&LOCK_thread_count)); - mysql_parse(thd, next_packet, length, & found_semicolon); + mysql_parse(thd, beginning_of_next_stmt, length, &end_of_stmt); } if (!(specialflag & SPECIAL_NO_PRIOR)) @@ -1427,7 +1465,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, break; } - thd->proc_info= "closing tables"; + thd_proc_info(thd, "closing tables"); /* Free tables */ close_thread_tables(thd); @@ -1460,9 +1498,9 @@ bool dispatch_command(enum enum_server_command command, THD *thd, log_slow_statement(thd); - thd->proc_info="cleaning up"; + thd_proc_info(thd, "cleaning up"); VOID(pthread_mutex_lock(&LOCK_thread_count)); // For process list - thd->proc_info=0; + thd_proc_info(thd, 0); thd->command=COM_SLEEP; thd->query=0; thd->query_length=0; @@ -1493,8 +1531,8 @@ void log_slow_statement(THD *thd) if (thd->enable_slow_log && !thd->user_time) { ulonglong end_utime_of_query= thd->current_utime(); + thd_proc_info(thd, "logging slow query"); - thd->proc_info="logging slow query"; if (((end_utime_of_query - thd->utime_after_lock) > thd->variables.long_query_time || ((thd->server_status & @@ -1503,6 +1541,7 @@ void log_slow_statement(THD *thd) !(sql_command_flags[thd->lex->sql_command] & CF_STATUS_COMMAND))) && thd->examined_row_count >= thd->variables.min_examined_row_limit) { + thd_proc_info(thd, "logging slow query"); thd->status_var.long_query_count++; slow_log_print(thd, thd->query, thd->query_length, end_utime_of_query); } @@ -1511,30 +1550,28 @@ void log_slow_statement(THD *thd) } -/* +/** Create a TABLE_LIST object for an INFORMATION_SCHEMA table. - SYNOPSIS - prepare_schema_table() - thd thread handle - lex current lex - table_ident table alias if it's used - schema_table_idx the type of the INFORMATION_SCHEMA table to be - created - - DESCRIPTION This function is used in the parser to convert a SHOW or DESCRIBE table_name command to a SELECT from INFORMATION_SCHEMA. It prepares a SELECT_LEX and a TABLE_LIST object to represent the given command as a SELECT parse tree. - NOTES + @param thd thread handle + @param lex current lex + @param table_ident table alias if it's used + @param schema_table_idx the type of the INFORMATION_SCHEMA table to be + created + + @note Due to the way this function works with memory and LEX it cannot be used outside the parser (parse tree transformations outside the parser break PS and SP). - RETURN VALUE + @retval 0 success + @retval 1 out of memory or SHOW commands are not allowed in this version of the server. */ @@ -1606,6 +1643,15 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident, break; } #endif + case SCH_PROFILES: + /* + Mark this current profiling record to be discarded. We don't + wish to have SHOW commands show up in profiling. + */ +#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) + thd->profiling.discard_current_query(); +#endif + break; case SCH_OPEN_TABLES: case SCH_VARIABLES: case SCH_STATUS: @@ -1636,17 +1682,17 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident, } -/* - Read query from packet and store in thd->query - Used in COM_QUERY and COM_STMT_PREPARE +/** + Read query from packet and store in thd->query. + Used in COM_QUERY and COM_STMT_PREPARE. - DESCRIPTION Sets the following THD variables: - query - query_length + - query + - query_length - RETURN VALUES + @retval FALSE ok + @retval TRUE error; In this case thd->fatal_error is set */ @@ -1785,14 +1831,8 @@ bool sp_process_definer(THD *thd) } -/* - Execute command saved in thd and lex->sql_command - - SYNOPSIS - mysql_execute_command() - thd Thread handle - - IMPLEMENTATION +/** + Execute command saved in thd and lex->sql_command. Before every operation that can request a write lock for a table wait if a global read lock exists. However do not wait if this @@ -1804,8 +1844,20 @@ bool sp_process_definer(THD *thd) global read lock when it succeeds. This needs to be released by start_waiting_global_read_lock() after the operation. - RETURN + @param thd Thread handle + + @todo + - Invalidate the table in the query cache if something changed + after unlocking when changes become visible. + TODO: this is workaround. right way will be move invalidating in + the unlock procedure. + - TODO: use check_change_password() + - JOIN is not supported yet. TODO + - SUSPEND and FOR MIGRATE are not supported yet. TODO + + @retval FALSE OK + @retval TRUE Error */ @@ -1987,6 +2039,7 @@ mysql_execute_command(THD *thd) case SQLCOM_SHOW_CHARSETS: case SQLCOM_SHOW_COLLATIONS: case SQLCOM_SHOW_STORAGE_ENGINES: + case SQLCOM_SHOW_PROFILE: case SQLCOM_SELECT: thd->status_var.last_query_cost= 0.0; if (all_tables) @@ -2082,6 +2135,19 @@ mysql_execute_command(THD *thd) (1L << (uint) MYSQL_ERROR::WARN_LEVEL_ERROR)); break; } + case SQLCOM_SHOW_PROFILES: + { +#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) + thd->profiling.discard_current_query(); + res= thd->profiling.show_profiles(); + if (res) + goto error; +#else + my_error(ER_FEATURE_DISABLED, MYF(0), "SHOW PROFILES", "enable-profiling"); + goto error; +#endif + break; + } case SQLCOM_SHOW_NEW_MASTER: { if (check_global_access(thd, REPL_SLAVE_ACL)) @@ -3029,7 +3095,7 @@ end_with_restore_list: if (add_item_to_list(thd, new Item_null())) goto error; - thd->proc_info="init"; + thd_proc_info(thd, "init"); if ((res= open_and_lock_tables(thd, all_tables))) break; @@ -3199,7 +3265,7 @@ end_with_restore_list: if (thd->options & OPTION_TABLE_LOCK) { end_active_trans(thd); - thd->options&= ~(ulong) (OPTION_TABLE_LOCK); + thd->options&= ~(OPTION_TABLE_LOCK); } if (thd->global_read_lock) unlock_global_read_lock(thd); @@ -3233,7 +3299,7 @@ end_with_restore_list: that it can't lock a table in its list */ end_active_trans(thd); - thd->options&= ~(ulong) (OPTION_TABLE_LOCK); + thd->options&= ~(OPTION_TABLE_LOCK); } thd->in_lock_tables=0; break; @@ -4592,8 +4658,7 @@ create_sp_error: send_ok(thd); break; } - - thd->proc_info="query end"; + thd_proc_info(thd, "query end"); /* Binlog-related cleanup: @@ -4692,20 +4757,19 @@ static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables) #ifndef NO_EMBEDDED_ACCESS_CHECKS -/* +/** Check grants for commands which work only with one table. - SYNOPSIS - check_single_table_access() - thd Thread handler - privilege requested privilege - all_tables global table list of query - no_errors FALSE/TRUE - report/don't report error to + @param thd Thread handler + @param privilege requested privilege + @param all_tables global table list of query + @param no_errors FALSE/TRUE - report/don't report error to the client (using my_error() call). - RETURN - 0 - OK - 1 - access denied, error is sent to client + @retval + 0 OK + @retval + 1 access denied, error is sent to client */ bool check_single_table_access(THD *thd, ulong privilege, @@ -4743,19 +4807,18 @@ deny: return 1; } -/* +/** Check grants for commands which work only with one table and all other tables belonging to subselects or implicitly opened tables. - SYNOPSIS - check_one_table_access() - thd Thread handler - privilege requested privilege - all_tables global table list of query + @param thd Thread handler + @param privilege requested privilege + @param all_tables global table list of query - RETURN - 0 - OK - 1 - access denied, error is sent to client + @retval + 0 OK + @retval + 1 access denied, error is sent to client */ bool check_one_table_access(THD *thd, ulong privilege, TABLE_LIST *all_tables) @@ -4785,25 +4848,26 @@ bool check_one_table_access(THD *thd, ulong privilege, TABLE_LIST *all_tables) } -/**************************************************************************** - Get the user (global) and database privileges for all used tables +/** + Get the user (global) and database privileges for all used tables. + + @param save_priv In this we store global and db level grants for the + table. Note that we don't store db level grants if the + global grants is enough to satisfy the request and the + global grants contains a SELECT grant. - NOTES + @note The idea of EXTRA_ACL is that one will be granted access to the table if one has the asked privilege on any column combination of the table; For example to be able to check a table one needs to have SELECT privilege on any column of the table. - RETURN + @retval 0 ok - 1 If we can't get the privileges and we don't use table/column grants. - - save_priv In this we store global and db level grants for the table - Note that we don't store db level grants if the global grants - is enough to satisfy the request and the global grants contains - a SELECT grant. -****************************************************************************/ - + @retval + 1 If we can't get the privileges and we don't use table/column + grants. +*/ bool check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, bool dont_check_global_grants, bool no_errors, bool schema_db) @@ -4830,6 +4894,7 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, else save_priv= &dummy; + thd_proc_info(thd, "checking permissions"); if ((!db || !db[0]) && !thd->db && !dont_check_global_grants) { DBUG_PRINT("error",("No database")); @@ -4919,22 +4984,21 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, } -/* - check for global access and give descriptive error message if it fails +/** + check for global access and give descriptive error message if it fails. - SYNOPSIS - check_global_access() - thd Thread handler - want_access Use should have any of these global rights + @param thd Thread handler + @param want_access Use should have any of these global rights - WARNING - One gets access right if one has ANY of the rights in want_access + @warning + One gets access right if one has ANY of the rights in want_access. This is useful as one in most cases only need one global right, but in some case we want to check if the user has SUPER or REPL_CLIENT_ACL rights. - RETURN + @retval 0 ok + @retval 1 Access denied. In this case an error is sent to the client */ @@ -5008,27 +5072,26 @@ static bool check_show_access(THD *thd, TABLE_LIST *table) } -/* +/** Check the privilege for all used tables. - SYNOPSYS - check_table_access() - thd Thread context - want_access Privileges requested - tables List of tables to be checked - no_errors FALSE/TRUE - report/don't report error to + @param thd Thread context + @param want_access Privileges requested + @param tables List of tables to be checked + @param no_errors FALSE/TRUE - report/don't report error to the client (using my_error() call). - NOTES + @note Table privileges are cached in the table list for GRANT checking. This functions assumes that table list used and thd->lex->query_tables_own_last value correspond to each other (the latter should be either 0 or point to next_global member of one of elements of this table list). - RETURN VALUE - FALSE - OK - TRUE - Access denied + @retval + FALSE OK + @retval + TRUE Access denied */ bool @@ -5126,17 +5189,16 @@ check_routine_access(THD *thd, ulong want_access,char *db, char *name, } -/* - Check if the routine has any of the routine privileges +/** + Check if the routine has any of the routine privileges. - SYNOPSIS - check_some_routine_access() - thd Thread handler - db Database name - name Routine name + @param thd Thread handler + @param db Database name + @param name Routine name - RETURN + @retval 0 ok + @retval 1 error */ @@ -5160,17 +5222,15 @@ bool check_some_routine_access(THD *thd, const char *db, const char *name, /* Check if the given table has any of the asked privileges - SYNOPSIS - check_some_access() - thd Thread handler - want_access Bitmap of possible privileges to check for + @param thd Thread handler + @param want_access Bitmap of possible privileges to check for - RETURN + @retval 0 ok + @retval 1 error */ - bool check_some_access(THD *thd, ulong want_access, TABLE_LIST *table) { ulong access; @@ -5210,12 +5270,13 @@ bool check_some_access(THD *thd, ulong want_access, TABLE_LIST *table) long max_stack_used; #endif -/* +/** + @note Note: The 'buf' parameter is necessary, even if it is unused here. - fix_fields functions has a "dummy" buffer large enough for the corresponding exec. (Thus we only have to check in fix_fields.) - Passing to check_stack_overrun() prevents the compiler from removing it. - */ +*/ bool check_stack_overrun(THD *thd, long margin, uchar *buf __attribute__((unused))) { @@ -5269,17 +5330,17 @@ bool my_yyoverflow(short **yyss, YYSTYPE **yyvs, ulong *yystacksize) } -/* +/** Reset THD part responsible for command processing state. - DESCRIPTION This needs to be called before execution of every statement (prepared or conventional). It is not called by substatements of routines. - TODO + @todo Make it a method of THD and align its name with the rest of reset/end/start/init methods. + @todo Call it after we use THD for queries, not before. */ @@ -5425,17 +5486,14 @@ mysql_new_select(LEX *lex, bool move_down) DBUG_RETURN(0); } -/* +/** Create a select to return the same output as 'SELECT @@var_name'. - SYNOPSIS - create_select_for_variable() - var_name Variable name + Used for SHOW COUNT(*) [ WARNINGS | ERROR]. - DESCRIPTION - Used for SHOW COUNT(*) [ WARNINGS | ERROR] + This will crash with a core dump if the variable doesn't exists. - This will crash with a core dump if the variable doesn't exists + @param var_name Variable name */ void create_select_for_variable(const char *var_name) @@ -5580,7 +5638,7 @@ void mysql_parse(THD *thd, const char *inBuf, uint length, thd->lex->sphead= 0; } lex->unit.cleanup(); - thd->proc_info="freeing items"; + thd_proc_info(thd, "freeing items"); thd->end_statement(); thd->cleanup_after_query(); DBUG_ASSERT(thd->change_list.is_empty()); @@ -5600,8 +5658,9 @@ void mysql_parse(THD *thd, const char *inBuf, uint length, Usable by the replication SQL thread only: just parse a query to know if it can be ignored because of replicate-*-table rules. - RETURN VALUES + @retval 0 cannot be ignored + @retval 1 can be ignored */ @@ -5626,10 +5685,12 @@ bool mysql_test_parse_for_slave(THD *thd, char *inBuf, uint length) -/***************************************************************************** -** Store field definition for create -** Return 0 if ok -******************************************************************************/ +/** + Store field definition for create. + + @return + Return 0 if ok +*/ bool add_field_to_list(THD *thd, LEX_STRING *field_name, enum_field_types type, char *length, char *decimals, @@ -5733,7 +5794,7 @@ bool add_field_to_list(THD *thd, LEX_STRING *field_name, enum_field_types type, } -/* Store position for column in ALTER TABLE .. ADD column */ +/** Store position for column in ALTER TABLE .. ADD column. */ void store_position_for_column(const char *name) { @@ -5757,10 +5818,9 @@ add_proc_to_list(THD* thd, Item *item) } -/**************************************************************************** -** save order by and tables in own lists -****************************************************************************/ - +/** + save order by and tables in own lists. +*/ bool add_to_list(THD *thd, SQL_LIST &list,Item *item,bool asc) { @@ -5779,24 +5839,23 @@ bool add_to_list(THD *thd, SQL_LIST &list,Item *item,bool asc) } -/* - Add a table to list of used tables - - SYNOPSIS - add_table_to_list() - table Table to add - alias alias for table (or null if no alias) - table_options A set of the following bits: - TL_OPTION_UPDATING Table will be updated - TL_OPTION_FORCE_INDEX Force usage of index - TL_OPTION_ALIAS an alias in multi table DELETE - lock_type How table should be locked - use_index List of indexed used in USE INDEX - ignore_index List of indexed used in IGNORE INDEX - - RETURN +/** + Add a table to list of used tables. + + @param table Table to add + @param alias alias for table (or null if no alias) + @param table_options A set of the following bits: + - TL_OPTION_UPDATING : Table will be updated + - TL_OPTION_FORCE_INDEX : Force usage of index + - TL_OPTION_ALIAS : an alias in multi table DELETE + @param lock_type How table should be locked + @param use_index List of indexed used in USE INDEX + @param ignore_index List of indexed used in IGNORE INDEX + + @retval 0 Error - # Pointer to TABLE_LIST element added to the total table list + @retval + \# Pointer to TABLE_LIST element added to the total table list */ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd, @@ -5939,14 +5998,9 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd, } -/* - Initialize a new table list for a nested join - - SYNOPSIS - init_nested_join() - thd current thread +/** + Initialize a new table list for a nested join. - DESCRIPTION The function initializes a structure of the TABLE_LIST type for a nested join. It sets up its nested join list as empty. The created structure is added to the front of the current @@ -5955,9 +6009,12 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd, created empty list after having saved the info on the old level in the initialized structure. - RETURN VALUE - 0, if success - 1, otherwise + @param thd current thread + + @retval + 0 if success + @retval + 1 otherwise */ bool st_select_lex::init_nested_join(THD *thd) @@ -5983,21 +6040,18 @@ bool st_select_lex::init_nested_join(THD *thd) } -/* - End a nested join table list - - SYNOPSIS - end_nested_join() - thd current thread +/** + End a nested join table list. - DESCRIPTION The function returns to the previous join nest level. If the current level contains only one member, the function moves it one level up, eliminating the nest. - RETURN VALUE - Pointer to TABLE_LIST element added to the total table list, if success - 0, otherwise + @param thd current thread + + @return + - Pointer to TABLE_LIST element added to the total table list, if success + - 0, otherwise */ TABLE_LIST *st_select_lex::end_nested_join(THD *thd) @@ -6029,20 +6083,17 @@ TABLE_LIST *st_select_lex::end_nested_join(THD *thd) } -/* - Nest last join operation - - SYNOPSIS - nest_last_join() - thd current thread +/** + Nest last join operation. - DESCRIPTION The function nest last join operation as if it was enclosed in braces. - RETURN VALUE - 0 Error - # Pointer to TABLE_LIST element created for the new nested join + @param thd current thread + @retval + 0 Error + @retval + \# Pointer to TABLE_LIST element created for the new nested join */ TABLE_LIST *st_select_lex::nest_last_join(THD *thd) @@ -6087,20 +6138,17 @@ TABLE_LIST *st_select_lex::nest_last_join(THD *thd) } -/* - Add a table to the current join list - - SYNOPSIS - add_joined_table() - table the table to add +/** + Add a table to the current join list. - DESCRIPTION The function puts a table in front of the current join list of st_select_lex object. Thus, joined tables are put into this list in the reverse order (the most outer join operation follows first). - RETURN VALUE + @param table the table to add + + @return None */ @@ -6114,14 +6162,9 @@ void st_select_lex::add_joined_table(TABLE_LIST *table) } -/* - Convert a right join into equivalent left join - - SYNOPSIS - convert_right_join() - thd current thread +/** + Convert a right join into equivalent left join. - DESCRIPTION The function takes the current join list t[0],t[1] ... and effectively converts it into the list t[1],t[0] ... Although the outer_join flag for the new nested table contains @@ -6129,6 +6172,7 @@ void st_select_lex::add_joined_table(TABLE_LIST *table) operation. EXAMPLES + @verbatim SELECT * FROM t1 RIGHT JOIN t2 ON on_expr => SELECT * FROM t2 LEFT JOIN t1 ON on_expr @@ -6140,10 +6184,13 @@ void st_select_lex::add_joined_table(TABLE_LIST *table) SELECT * FROM t1 LEFT JOIN t2 ON on_expr1 RIGHT JOIN t3 ON on_expr2 => SELECT * FROM t3 LEFT JOIN (t1 LEFT JOIN t2 ON on_expr2) ON on_expr1 + @endverbatim - RETURN - Pointer to the table representing the inner table, if success - 0, otherwise + @param thd current thread + + @return + - Pointer to the table representing the inner table, if success + - 0, otherwise */ TABLE_LIST *st_select_lex::convert_right_join() @@ -6159,14 +6206,12 @@ TABLE_LIST *st_select_lex::convert_right_join() DBUG_RETURN(tab1); } -/* - Set lock for all tables in current select level +/** + Set lock for all tables in current select level. - SYNOPSIS: - set_lock_for_tables() - lock_type Lock to set for tables + @param lock_type Lock to set for tables - NOTE: + @note If lock is a write lock, then tables->updating is set 1 This is to get tables_ok to know that the table is updated by the query @@ -6190,27 +6235,29 @@ void st_select_lex::set_lock_for_tables(thr_lock_type lock_type) } -/* - Create a fake SELECT_LEX for a unit - - SYNOPSIS: - add_fake_select_lex() - thd thread handle +/** + Create a fake SELECT_LEX for a unit. - DESCRIPTION The method create a fake SELECT_LEX object for a unit. This object is created for any union construct containing a union operation and also for any single select union construct of the form + @verbatim (SELECT ... ORDER BY order_list [LIMIT n]) ORDER BY ... + @endvarbatim or of the form + @varbatim (SELECT ... ORDER BY LIMIT n) ORDER BY ... + @endvarbatim - NOTES + @param thd_arg thread handle + + @note The object is used to retrieve rows from the temporary table where the result on the union is obtained. - RETURN VALUES + @retval 1 on failure to create the object + @retval 0 on success */ @@ -6252,24 +6299,22 @@ bool st_select_lex_unit::add_fake_select_lex(THD *thd_arg) } -/* +/** Push a new name resolution context for a JOIN ... ON clause to the context stack of a query block. - SYNOPSIS - push_new_name_resolution_context() - thd pointer to current thread - left_op left operand of the JOIN - right_op rigth operand of the JOIN - - DESCRIPTION Create a new name resolution context for a JOIN ... ON clause, set the first and last leaves of the list of table references to be used for name resolution, and push the newly created context to the stack of contexts of the query. - RETURN + @param thd pointer to current thread + @param left_op left operand of the JOIN + @param right_op rigth operand of the JOIN + + @retval FALSE if all is OK + @retval TRUE if a memory allocation error occured */ @@ -6289,19 +6334,17 @@ push_new_name_resolution_context(THD *thd, } -/* +/** Add an ON condition to the second operand of a JOIN ... ON. - SYNOPSIS - add_join_on - b the second operand of a JOIN ... ON - expr the condition to be added to the ON clause - - DESCRIPTION Add an ON condition to the right operand of a JOIN ... ON clause. - RETURN + @param b the second operand of a JOIN ... ON + @param expr the condition to be added to the ON clause + + @retval FALSE if there was some error + @retval TRUE if all is OK */ @@ -6325,18 +6368,10 @@ void add_join_on(TABLE_LIST *b, Item *expr) } -/* +/** Mark that there is a NATURAL JOIN or JOIN ... USING between two tables. - SYNOPSIS - add_join_natural() - a Left join argument - b Right join argument - using_fields Field names from USING clause - lex The current st_select_lex - - IMPLEMENTATION This function marks that table b should be joined with a either via a NATURAL JOIN or via JOIN ... USING. Both join types are special cases of each other, so we treat them together. The function @@ -6347,6 +6382,7 @@ void add_join_on(TABLE_LIST *b, Item *expr) was an outer join. EXAMPLE + @verbatim SELECT * FROM t1 NATURAL LEFT JOIN t2 <=> SELECT * FROM t1 LEFT JOIN t2 ON (t1.i=t2.i and t1.j=t2.j ... ) @@ -6358,9 +6394,11 @@ void add_join_on(TABLE_LIST *b, Item *expr) SELECT * FROM t1 JOIN t2 USING(j) WHERE <some_cond> <=> SELECT * FROM t1, t2 WHERE (t1.j=t2.j and <some_cond>) + @endverbatim - RETURN - None + @param a Left join argument + @param b Right join argument + @param using_fields Field names from USING clause */ void add_join_natural(TABLE_LIST *a, TABLE_LIST *b, List<String> *using_fields, @@ -6372,7 +6410,7 @@ void add_join_natural(TABLE_LIST *a, TABLE_LIST *b, List<String> *using_fields, /** - @brief Reload/resets privileges and the different caches. + Reload/resets privileges and the different caches. @param thd Thread handler (can be NULL!) @param options What should be reset/reloaded (tables, privileges, slave...) @@ -6562,16 +6600,14 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables, } -/* - kills a thread +/** + kill on thread. - SYNOPSIS - kill_one_thread() - thd Thread class - id Thread id - only_kill_query Should it kill the query or the connection + @param thd Thread class + @param id Thread id + @param only_kill_query Should it kill the query or the connection - NOTES + @note This is written such that we have a short lock on LOCK_thread_count */ @@ -6631,7 +6667,7 @@ void sql_kill(THD *thd, ulong id, bool only_kill_query) } - /* If pointer is not a null pointer, append filename to it */ +/** If pointer is not a null pointer, append filename to it. */ bool append_file_to_dir(THD *thd, const char **filename_ptr, const char *table_name) @@ -6658,14 +6694,12 @@ bool append_file_to_dir(THD *thd, const char **filename_ptr, } -/* - Check if the select is a simple select (not an union) - - SYNOPSIS - check_simple_select() +/** + Check if the select is a simple select (not an union). - RETURN VALUES + @retval 0 ok + @retval 1 error ; In this case the error messege is sent to the client */ @@ -6722,17 +6756,15 @@ Comp_creator *comp_ne_creator(bool invert) } -/* - Construct ALL/ANY/SOME subquery Item +/** + Construct ALL/ANY/SOME subquery Item. - SYNOPSIS - all_any_subquery_creator() - left_expr - pointer to left expression - cmp - compare function creator - all - true if we create ALL subquery - select_lex - pointer on parsed subquery structure + @param left_expr pointer to left expression + @param cmp compare function creator + @param all true if we create ALL subquery + @param select_lex pointer on parsed subquery structure - RETURN VALUE + @return constructed Item (or 0 if out of memory) */ Item * all_any_subquery_creator(Item *left_expr, @@ -6755,16 +6787,15 @@ Item * all_any_subquery_creator(Item *left_expr, } -/* - Multi update query pre-check +/** + Multi update query pre-check. - SYNOPSIS - multi_update_precheck() - thd Thread handler - tables Global/local table list (have to be the same) + @param thd Thread handler + @param tables Global/local table list (have to be the same) - RETURN VALUE + @retval FALSE OK + @retval TRUE Error */ @@ -6832,16 +6863,15 @@ bool multi_update_precheck(THD *thd, TABLE_LIST *tables) DBUG_RETURN(FALSE); } -/* - Multi delete query pre-check +/** + Multi delete query pre-check. - SYNOPSIS - multi_delete_precheck() - thd Thread handler - tables Global/local table list + @param thd Thread handler + @param tables Global/local table list - RETURN VALUE + @retval FALSE OK + @retval TRUE error */ @@ -6881,17 +6911,16 @@ bool multi_delete_precheck(THD *thd, TABLE_LIST *tables) } -/* +/** Link tables in auxilary table list of multi-delete with corresponding elements in main table list, and set proper locks for them. - SYNOPSIS - multi_delete_set_locks_and_link_aux_tables() - lex - pointer to LEX representing multi-delete + @param lex pointer to LEX representing multi-delete - RETURN VALUE - FALSE - success - TRUE - error + @retval + FALSE success + @retval + TRUE error */ bool multi_delete_set_locks_and_link_aux_tables(LEX *lex) @@ -6934,16 +6963,15 @@ bool multi_delete_set_locks_and_link_aux_tables(LEX *lex) } -/* - simple UPDATE query pre-check +/** + simple UPDATE query pre-check. - SYNOPSIS - update_precheck() - thd Thread handler - tables Global table list + @param thd Thread handler + @param tables Global table list - RETURN VALUE + @retval FALSE OK + @retval TRUE Error */ @@ -6959,16 +6987,15 @@ bool update_precheck(THD *thd, TABLE_LIST *tables) } -/* - simple DELETE query pre-check +/** + simple DELETE query pre-check. - SYNOPSIS - delete_precheck() - thd Thread handler - tables Global table list + @param thd Thread handler + @param tables Global table list - RETURN VALUE + @retval FALSE OK + @retval TRUE error */ @@ -6983,16 +7010,15 @@ bool delete_precheck(THD *thd, TABLE_LIST *tables) } -/* - simple INSERT query pre-check +/** + simple INSERT query pre-check. - SYNOPSIS - insert_precheck() - thd Thread handler - tables Global table list + @param thd Thread handler + @param tables Global table list - RETURN VALUE + @retval FALSE OK + @retval TRUE error */ @@ -7040,17 +7066,16 @@ static bool check_show_create_table_access(THD *thd, TABLE_LIST *table) } -/* - CREATE TABLE query pre-check +/** + CREATE TABLE query pre-check. - SYNOPSIS - create_table_precheck() - thd Thread handler - tables Global table list - create_table Table which will be created + @param thd Thread handler + @param tables Global table list + @param create_table Table which will be created - RETURN VALUE + @retval FALSE OK + @retval TRUE Error */ @@ -7123,15 +7148,13 @@ err: } -/* - negate given expression +/** + negate given expression. - SYNOPSIS - negate_expression() - thd thread handler - expr expression for negation + @param thd thread handler + @param expr expression for negation - RETURN + @return negated expression */ @@ -7158,14 +7181,12 @@ Item *negate_expression(THD *thd, Item *expr) return new Item_func_not(expr); } -/* - Set the specified definer to the default value, which is the current user in - the thread. +/** + Set the specified definer to the default value, which is the + current user in the thread. - SYNOPSIS - get_default_definer() - thd [in] thread handler - definer [out] definer + @param[in] thd thread handler + @param[out] definer definer */ void get_default_definer(THD *thd, LEX_USER *definer) @@ -7180,17 +7201,15 @@ void get_default_definer(THD *thd, LEX_USER *definer) } -/* +/** Create default definer for the specified THD. - SYNOPSIS - create_default_definer() - thd [in] thread handler + @param[in] thd thread handler - RETURN - On success, return a valid pointer to the created and initialized + @return + - On success, return a valid pointer to the created and initialized LEX_USER, which contains definer information. - On error, return 0. + - On error, return 0. */ LEX_USER *create_default_definer(THD *thd) @@ -7206,19 +7225,17 @@ LEX_USER *create_default_definer(THD *thd) } -/* +/** Create definer with the given user and host names. - SYNOPSIS - create_definer() - thd [in] thread handler - user_name [in] user name - host_name [in] host name + @param[in] thd thread handler + @param[in] user_name user name + @param[in] host_name host name - RETURN - On success, return a valid pointer to the created and initialized + @return + - On success, return a valid pointer to the created and initialized LEX_USER, which contains definer information. - On error, return 0. + - On error, return 0. */ LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name) @@ -7237,18 +7254,16 @@ LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name) } -/* +/** Retuns information about user or current user. - SYNOPSIS - get_current_user() - thd [in] thread handler - user [in] user + @param[in] thd thread handler + @param[in] user user - RETURN - On success, return a valid pointer to initialized + @return + - On success, return a valid pointer to initialized LEX_USER, which contains user information. - On error, return 0. + - On error, return 0. */ LEX_USER *get_current_user(THD *thd, LEX_USER *user) @@ -7260,17 +7275,16 @@ LEX_USER *get_current_user(THD *thd, LEX_USER *user) } -/* +/** Check that byte length of a string does not exceed some limit. - SYNOPSIS - check_string_byte_length() - str string to be checked - err_msg error message to be displayed if the string is too long - max_byte_length max length in bytes + @param str string to be checked + @param err_msg error message to be displayed if the string is too long + @param max_length max length - RETURN + @retval FALSE the passed string is not longer than max_length + @retval TRUE the passed string is longer than max_length NOTE diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 52e6fcc5d58..c0178a231c9 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -13,7 +13,9 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/********************************************************************** +/** + @file + This file contains the implementation of prepared statements. When one prepares a statement: @@ -28,11 +30,13 @@ When one prepares a statement: - Without executing the query, return back to client the total number of parameters along with result-set metadata information (if any) in the following format: + @verbatim [STMT_ID:4] [Column_count:2] [Param_count:2] [Params meta info (stubs only for now)] (if Param_count > 0) [Columns meta info] (if Column_count > 0) + @endverbatim During prepare the tables used in a statement are opened, but no locks are acquired. Table opening will block any DDL during the @@ -45,12 +49,14 @@ When one executes a statement: - Server gets the command 'COM_STMT_EXECUTE' to execute the previously prepared query. If there are any parameter markers, then the client will send the data in the following format: + @verbatim [COM_STMT_EXECUTE:1] [STMT_ID:4] [NULL_BITS:(param_count+7)/8)] [TYPES_SUPPLIED_BY_CLIENT(0/1):1] [[length]data] [[length]data] .. [[length]data]. + @endverbatim (Note: Except for string/binary types; all other types will not be supplied with length field) - If it is a first execute or types of parameters were altered by client, @@ -75,8 +81,7 @@ When one supplies long data for a placeholder: server doesn't care; also, the server doesn't notify the client whether it got the data or not; if there is any error, then it will be returned at statement execute. - -***********************************************************************/ +*/ #include "mysql_priv.h" #include "sql_select.h" // for JOIN @@ -91,7 +96,9 @@ When one supplies long data for a placeholder: #include <mysql_com.h> #endif -/* A result class used to send cursor rows using the binary protocol. */ +/** + A result class used to send cursor rows using the binary protocol. +*/ class Select_fetch_protocol_binary: public select_send { @@ -112,7 +119,7 @@ public: /****************************************************************************/ /** - @brief Prepared_statement: a statement that can contain placeholders + Prepared_statement: a statement that can contain placeholders. */ class Prepared_statement: public Statement @@ -176,20 +183,17 @@ inline bool is_param_null(const uchar *pos, ulong param_no) return pos[param_no/8] & (1 << (param_no & 7)); } -/* +/** Find a prepared statement in the statement map by id. - SYNOPSIS - find_prepared_statement() - thd thread handle - id statement id - where the place from which this function is called (for - error reporting). - - DESCRIPTION Try to find a prepared statement and set THD error if it's not found. - RETURN VALUE + @param thd thread handle + @param id statement id + @param where the place from which this function is called (for + error reporting). + + @return 0 if the statement was not found, a pointer otherwise. */ @@ -214,13 +218,13 @@ find_prepared_statement(THD *thd, ulong id, const char *where) } -/* +/** Send prepared statement id and metadata to the client after prepare. - SYNOPSIS - send_prep_stmt() + @todo + Fix this nasty upcast from List<Item_param> to List<Item> - RETURN VALUE + @return 0 in case of success, 1 otherwise */ @@ -273,24 +277,22 @@ static bool send_prep_stmt(Prepared_statement *stmt, #endif /*!EMBEDDED_LIBRARY*/ -/* +#ifndef EMBEDDED_LIBRARY + +/** Read the length of the parameter data and return it back to the caller. - SYNOPSIS - get_param_length() - packet a pointer to the data - len remaining packet length - - DESCRIPTION Read data length, position the packet to the first byte after it, and return the length to the caller. - RETURN VALUE + @param packet a pointer to the data + @param len remaining packet length + + @return Length of data piece. */ -#ifndef EMBEDDED_LIBRARY static ulong get_param_length(uchar **packet, ulong len) { reg1 uchar *pos= *packet; @@ -331,16 +333,9 @@ static ulong get_param_length(uchar **packet, ulong len) #define get_param_length(packet, len) len #endif /*!EMBEDDED_LIBRARY*/ - /* - Data conversion routines. - - SYNOPSIS - set_param_xx() - param parameter item - pos input data buffer - len length of data in the buffer +/** + Data conversion routines. - DESCRIPTION All these functions read the data from pos, convert it to requested type and assign to param; pos is advanced to predefined length. @@ -348,8 +343,9 @@ static ulong get_param_length(uchar **packet, ulong len) (i.e. when input types altered) and for all subsequent executions we don't read any values for this. - RETURN VALUE - none + @param param parameter item + @param pos input data buffer + @param len length of data in the buffer */ static void set_param_tiny(Item_param *param, uchar **pos, ulong len) @@ -451,6 +447,10 @@ static void set_param_decimal(Item_param *param, uchar **pos, ulong len) libmysql.c (store_param_{time,date,datetime}). */ +/** + @todo + Add warning 'Data truncated' here +*/ static void set_param_time(Item_param *param, uchar **pos, ulong len) { MYSQL_TIME tm; @@ -540,6 +540,10 @@ static void set_param_date(Item_param *param, uchar **pos, ulong len) } #else/*!EMBEDDED_LIBRARY*/ +/** + @todo + Add warning 'Data truncated' here +*/ void set_param_time(Item_param *param, uchar **pos, ulong len) { MYSQL_TIME tm= *((MYSQL_TIME*)*pos); @@ -692,14 +696,13 @@ static void setup_one_conversion_function(THD *thd, Item_param *param, } #ifndef EMBEDDED_LIBRARY -/* +/** Routines to assign parameters from data supplied by the client. - DESCRIPTION Update the parameter markers by reading data from the packet and and generate a valid query for logging. - NOTES + @note This function, along with other _with_log functions is called when one of binary, slow or general logs is open. Logging of prepared statements in all cases is performed by means of conventional queries: if parameter @@ -707,21 +710,28 @@ static void setup_one_conversion_function(THD *thd, Item_param *param, replaced with its actual value; if we're logging a [Dynamic] SQL prepared statement, parameter markers are replaced with variable names. Example: + @verbatim mysql_stmt_prepare("UPDATE t1 SET a=a*1.25 WHERE a=?") --> general logs gets [Prepare] UPDATE t1 SET a*1.25 WHERE a=?" mysql_stmt_execute(stmt); --> general and binary logs get [Execute] UPDATE t1 SET a*1.25 WHERE a=1" - If a statement has been prepared using SQL syntax: + @endverbatim + + If a statement has been prepared using SQL syntax: + @verbatim PREPARE stmt FROM "UPDATE t1 SET a=a*1.25 WHERE a=?" --> general log gets [Query] PREPARE stmt FROM "UPDATE ..." EXECUTE stmt USING @a --> general log gets - [Query] EXECUTE stmt USING @a; + [Query] EXECUTE stmt USING @a; + @endverbatim - RETURN VALUE - 0 if success, 1 otherwise + @retval + 0 if success + @retval + 1 otherwise */ static bool insert_params_with_log(Prepared_statement *stmt, uchar *null_array, @@ -837,12 +847,12 @@ static bool setup_conversion_functions(Prepared_statement *stmt, #else -/* +/** Embedded counterparts of parameter assignment routines. - DESCRIPTION The main difference between the embedded library and the server is that in embedded case we don't serialize/deserialize parameters data. + Additionally, for unknown reason, the client-side flag raised for changed types of placeholders is ignored and we simply setup conversion functions at each execute (TODO: fix). @@ -936,15 +946,14 @@ static bool emb_insert_params_with_log(Prepared_statement *stmt, #endif /*!EMBEDDED_LIBRARY*/ -/* +/** Assign prepared statement parameters from user variables. - SYNOPSIS - insert_params_from_vars() - stmt Statement - varnames List of variables. Caller must ensure that number of variables - in the list is equal to number of statement parameters - query Ignored + @param stmt Statement + @param varnames List of variables. Caller must ensure that number + of variables in the list is equal to number of statement + parameters + @param query Ignored */ static bool insert_params_from_vars(Prepared_statement *stmt, @@ -973,17 +982,16 @@ static bool insert_params_from_vars(Prepared_statement *stmt, } -/* +/** Do the same as insert_params_from_vars but also construct query text for binary log. - SYNOPSIS - insert_params_from_vars() - stmt Prepared statement - varnames List of variables. Caller must ensure that number of variables - in the list is equal to number of statement parameters - query The query with parameter markers replaced with corresponding - user variables that were used to execute the query. + @param stmt Prepared statement + @param varnames List of variables. Caller must ensure that number of + variables in the list is equal to number of statement + parameters + @param query The query with parameter markers replaced with corresponding + user variables that were used to execute the query. */ static bool insert_params_from_vars_with_log(Prepared_statement *stmt, @@ -1032,17 +1040,16 @@ static bool insert_params_from_vars_with_log(Prepared_statement *stmt, DBUG_RETURN(0); } -/* +/** Validate INSERT statement. - SYNOPSIS - mysql_test_insert() - stmt prepared statement - tables global/local table list + @param stmt prepared statement + @param tables global/local table list - RETURN VALUE - FALSE success - TRUE error, error message is set in THD + @retval + FALSE success + @retval + TRUE error, error message is set in THD */ static bool mysql_test_insert(Prepared_statement *stmt, @@ -1120,18 +1127,21 @@ error: } -/* - Validate UPDATE statement +/** + Validate UPDATE statement. - SYNOPSIS - mysql_test_update() - stmt prepared statement - tables list of tables used in this query + @param stmt prepared statement + @param tables list of tables used in this query - RETURN VALUE - 0 success - 1 error, error message is set in THD - 2 convert to multi_update + @todo + - here we should send types of placeholders to the client. + + @retval + 0 success + @retval + 1 error, error message is set in THD + @retval + 2 convert to multi_update */ static int mysql_test_update(Prepared_statement *stmt, @@ -1204,17 +1214,16 @@ error: } -/* +/** Validate DELETE statement. - SYNOPSIS - mysql_test_delete() - stmt prepared statement - tables list of tables used in this query + @param stmt prepared statement + @param tables list of tables used in this query - RETURN VALUE - FALSE success - TRUE error, error message is set in THD + @retval + FALSE success + @retval + TRUE error, error message is set in THD */ static bool mysql_test_delete(Prepared_statement *stmt, @@ -1241,22 +1250,21 @@ error: } -/* +/** Validate SELECT statement. - SYNOPSIS - mysql_test_select() - stmt prepared statement - tables list of tables used in the query - - DESCRIPTION In case of success, if this query is not EXPLAIN, send column list info back to the client. - RETURN VALUE - 0 success - 1 error, error message is set in THD - 2 success, and statement metadata has been sent + @param stmt prepared statement + @param tables list of tables used in the query + + @retval + 0 success + @retval + 1 error, error message is set in THD + @retval + 2 success, and statement metadata has been sent */ static int mysql_test_select(Prepared_statement *stmt, @@ -1321,18 +1329,17 @@ error: } -/* +/** Validate and prepare for execution DO statement expressions. - SYNOPSIS - mysql_test_do_fields() - stmt prepared statement - tables list of tables used in this query - values list of expressions + @param stmt prepared statement + @param tables list of tables used in this query + @param values list of expressions - RETURN VALUE - FALSE success - TRUE error, error message is set in THD + @retval + FALSE success + @retval + TRUE error, error message is set in THD */ static bool mysql_test_do_fields(Prepared_statement *stmt, @@ -1351,18 +1358,17 @@ static bool mysql_test_do_fields(Prepared_statement *stmt, } -/* - Validate and prepare for execution SET statement expressions +/** + Validate and prepare for execution SET statement expressions. - SYNOPSIS - mysql_test_set_fields() - stmt prepared statement - tables list of tables used in this query - values list of expressions + @param stmt prepared statement + @param tables list of tables used in this query + @param values list of expressions - RETURN VALUE - FALSE success - TRUE error, error message is set in THD + @retval + FALSE success + @retval + TRUE error, error message is set in THD */ static bool mysql_test_set_fields(Prepared_statement *stmt, @@ -1389,23 +1395,22 @@ error: } -/* - Check internal SELECT of the prepared command +/** + Check internal SELECT of the prepared command. - SYNOPSIS - select_like_stmt_test() - stmt prepared statement - specific_prepare function of command specific prepare - setup_tables_done_option options to be passed to LEX::unit.prepare() + @param stmt prepared statement + @param specific_prepare function of command specific prepare + @param setup_tables_done_option options to be passed to LEX::unit.prepare() - NOTE + @note This function won't directly open tables used in select. They should be opened either by calling function (and in this case you probably should use select_like_stmt_test_with_open()) or by "specific_prepare" call (like this happens in case of multi-update). - RETURN VALUE + @retval FALSE success + @retval TRUE error, error message is set in THD */ @@ -1428,20 +1433,19 @@ static bool select_like_stmt_test(Prepared_statement *stmt, DBUG_RETURN(lex->unit.prepare(thd, 0, setup_tables_done_option)); } -/* +/** Check internal SELECT of the prepared command (with opening of used tables). - SYNOPSIS - select_like_stmt_test_with_open() - stmt prepared statement - tables list of tables to be opened before calling - specific_prepare function - specific_prepare function of command specific prepare - setup_tables_done_option options to be passed to LEX::unit.prepare() + @param stmt prepared statement + @param tables list of tables to be opened + before calling specific_prepare function + @param specific_prepare function of command specific prepare + @param setup_tables_done_option options to be passed to LEX::unit.prepare() - RETURN VALUE + @retval FALSE success + @retval TRUE error */ @@ -1467,17 +1471,16 @@ select_like_stmt_test_with_open(Prepared_statement *stmt, } -/* - Validate and prepare for execution CREATE TABLE statement +/** + Validate and prepare for execution CREATE TABLE statement. - SYNOPSIS - mysql_test_create_table() - stmt prepared statement - tables list of tables used in this query + @param stmt prepared statement + @param tables list of tables used in this query - RETURN VALUE - FALSE success - TRUE error, error message is set in THD + @retval + FALSE success + @retval + TRUE error, error message is set in THD */ static bool mysql_test_create_table(Prepared_statement *stmt) @@ -1520,18 +1523,17 @@ static bool mysql_test_create_table(Prepared_statement *stmt) } -/* +/** Validate and prepare for execution a multi update statement. - SYNOPSIS - mysql_test_multiupdate() - stmt prepared statement - tables list of tables used in this query - converted converted to multi-update from usual update + @param stmt prepared statement + @param tables list of tables used in this query + @param converted converted to multi-update from usual update - RETURN VALUE - FALSE success - TRUE error, error message is set in THD + @retval + FALSE success + @retval + TRUE error, error message is set in THD */ static bool mysql_test_multiupdate(Prepared_statement *stmt, @@ -1547,17 +1549,16 @@ static bool mysql_test_multiupdate(Prepared_statement *stmt, } -/* +/** Validate and prepare for execution a multi delete statement. - SYNOPSIS - mysql_test_multidelete() - stmt prepared statement - tables list of tables used in this query + @param stmt prepared statement + @param tables list of tables used in this query - RETURN VALUE - FALSE success - TRUE error, error message in THD is set. + @retval + FALSE success + @retval + TRUE error, error message in THD is set. */ static bool mysql_test_multidelete(Prepared_statement *stmt, @@ -1587,15 +1588,13 @@ error: } -/* +/** Wrapper for mysql_insert_select_prepare, to make change of local tables after open_normal_and_derived_tables() call. - SYNOPSIS - mysql_insert_select_prepare_tester() - thd thread handle + @param thd thread handle - NOTE + @note We need to remove the first local table after open_normal_and_derived_tables(), because mysql_handle_derived uses local tables lists. @@ -1616,17 +1615,16 @@ static bool mysql_insert_select_prepare_tester(THD *thd) } -/* +/** Validate and prepare for execution INSERT ... SELECT statement. - SYNOPSIS - mysql_test_insert_select() - stmt prepared statement - tables list of tables used in this query + @param stmt prepared statement + @param tables list of tables used in this query - RETURN VALUE - FALSE success - TRUE error, error message is set in THD + @retval + FALSE success + @retval + TRUE error, error message is set in THD */ static bool mysql_test_insert_select(Prepared_statement *stmt, @@ -1659,23 +1657,21 @@ static bool mysql_test_insert_select(Prepared_statement *stmt, } -/* +/** Perform semantic analysis of the parsed tree and send a response packet to the client. - SYNOPSIS - check_prepared_statement() - stmt prepared statement - - DESCRIPTION This function - opens all tables and checks access rights - validates semantics of statement columns and SQL functions by calling fix_fields. - RETURN VALUE - FALSE success, statement metadata is sent to client - TRUE error, error message is set in THD (but not sent) + @param stmt prepared statement + + @retval + FALSE success, statement metadata is sent to client + @retval + TRUE error, error message is set in THD (but not sent) */ static bool check_prepared_statement(Prepared_statement *stmt, @@ -1842,7 +1838,7 @@ error: DBUG_RETURN(TRUE); } -/* +/** Initialize array of parameters in statement from LEX. (We need to have quick access to items by number in mysql_stmt_get_longdata). This is to avoid using malloc/realloc in the parser. @@ -1878,31 +1874,28 @@ static bool init_param_array(Prepared_statement *stmt) } -/* +/** COM_STMT_PREPARE handler. - SYNOPSIS - mysql_stmt_prepare() - packet query to be prepared - packet_length query string length, including ignored - trailing NULL or quote char. - - DESCRIPTION Given a query string with parameter markers, create a prepared statement from it and send PS info back to the client. - NOTES - This function parses the query and sends the total number of parameters - and resultset metadata information back to client (if any), without - executing the query i.e. without any log/disk writes. This allows the - queries to be re-executed without re-parsing during execute. - If parameter markers are found in the query, then store the information using Item_param along with maintaining a list in lex->param_array, so that a fast and direct retrieval can be made without going through all field items. - RETURN VALUE + @param packet query to be prepared + @param packet_length query string length, including ignored + trailing NULL or quote char. + + @note + This function parses the query and sends the total number of parameters + and resultset metadata information back to client (if any), without + executing the query i.e. without any log/disk writes. This allows the + queries to be re-executed without re-parsing during execute. + + @return none: in case of success a new statement id and metadata is sent to the client, otherwise an error message is set in THD. */ @@ -1952,22 +1945,22 @@ void mysql_stmt_prepare(THD *thd, const char *packet, uint packet_length) DBUG_VOID_RETURN; } -/* - SYNOPSIS - get_dynamic_sql_string() - lex in main lex - query_len out length of the SQL statement (is set only - in case of success) - - DESCRIPTION - Get an SQL statement text from a user variable or from plain - text. If the statement is plain text, just assign the - pointers, otherwise allocate memory in thd->mem_root and copy - the contents of the variable, possibly with character - set conversion. - - RETURN VALUE - non-zero success, 0 in case of error (out of memory) +/** + Get an SQL statement text from a user variable or from plain text. + + If the statement is plain text, just assign the + pointers, otherwise allocate memory in thd->mem_root and copy + the contents of the variable, possibly with character + set conversion. + + @param[in] lex main lex + @param[out] query_len length of the SQL statement (is set only + in case of success) + + @retval + non-zero success + @retval + 0 in case of error (out of memory) */ static const char *get_dynamic_sql_string(LEX *lex, uint *query_len) @@ -2045,7 +2038,7 @@ end: } -/* Init PS/SP specific parse tree members. */ +/** Init PS/SP specific parse tree members. */ static void init_stmt_after_parse(LEX *lex) { @@ -2058,19 +2051,16 @@ static void init_stmt_after_parse(LEX *lex) sl->uncacheable&= ~UNCACHEABLE_PREPARE; } -/* +/** SQLCOM_PREPARE implementation. - SYNOPSIS - mysql_sql_stmt_prepare() - thd thread handle - - DESCRIPTION Prepare an SQL prepared statement. This is called from mysql_execute_command and should therefore behave like an ordinary query (e.g. should not reset any global THD data). - RETURN VALUE + @param thd thread handle + + @return none: in case of success, OK packet is sent to the client, otherwise an error message is set in THD */ @@ -2126,7 +2116,14 @@ void mysql_sql_stmt_prepare(THD *thd) DBUG_VOID_RETURN; } -/* Reinit prepared statement/stored procedure before execution */ +/** + Reinit prepared statement/stored procedure before execution. + + @todo + When the new table structure is ready, then have a status bit + to indicate the table is altered, and re-do the setup_* + and open the tables back. +*/ void reinit_stmt_before_use(THD *thd, LEX *lex) { @@ -2232,13 +2229,11 @@ void reinit_stmt_before_use(THD *thd, LEX *lex) } -/* - Clears parameters from data left from previous execution or long data +/** + Clears parameters from data left from previous execution or long data. - SYNOPSIS - reset_stmt_params() - stmt prepared statement for which parameters should - be reset + @param stmt prepared statement for which parameters should + be reset */ static void reset_stmt_params(Prepared_statement *stmt) @@ -2250,22 +2245,19 @@ static void reset_stmt_params(Prepared_statement *stmt) } -/* +/** COM_STMT_EXECUTE handler: execute a previously prepared statement. - SYNOPSIS - mysql_stmt_execute() - thd current thread - packet parameter types and data, if any - packet_length packet length, including the terminator character. - - DESCRIPTION If there are any parameters, then replace parameter markers with the data supplied from the client, and then execute the statement. This function uses binary protocol to send a possible result set to the client. - RETURN VALUE + @param thd current thread + @param packet_arg parameter types and data, if any + @param packet_length packet length, including the terminator character. + + @return none: in case of success OK packet or a result set is sent to the client, otherwise an error message is set in THD. */ @@ -2292,6 +2284,9 @@ void mysql_stmt_execute(THD *thd, char *packet_arg, uint packet_length) if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_execute"))) DBUG_VOID_RETURN; +#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) + thd->profiling.set_query_source(stmt->query, stmt->query_length); +#endif DBUG_PRINT("exec_query", ("%s", stmt->query)); DBUG_PRINT("info",("stmt: 0x%lx", (long) stmt)); @@ -2339,14 +2334,9 @@ set_params_data_err: } -/* +/** SQLCOM_EXECUTE implementation. - SYNOPSIS - mysql_sql_stmt_execute() - thd thread handle - - DESCRIPTION Execute prepared statement using parameter values from lex->prepared_stmt_params and send result to the client using text protocol. This is called from mysql_execute_command and @@ -2354,7 +2344,9 @@ set_params_data_err: global THD data, such as warning count, server status, etc). This function uses text protocol to send a possible result set. - RETURN + @param thd thread handle + + @return none: in case of success, OK (or result set) packet is sent to the client, otherwise an error is set in THD */ @@ -2406,14 +2398,12 @@ set_params_data_err: } -/* - COM_STMT_FETCH handler: fetches requested amount of rows from cursor +/** + COM_STMT_FETCH handler: fetches requested amount of rows from cursor. - SYNOPSIS - mysql_stmt_fetch() - thd Thread handle - packet Packet from client (with stmt_id & num_rows) - packet_length Length of packet + @param thd Thread handle + @param packet Packet from client (with stmt_id & num_rows) + @param packet_length Length of packet */ void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length) @@ -2464,22 +2454,20 @@ void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length) } -/* +/** Reset a prepared statement in case there was a recoverable error. - SYNOPSIS - mysql_stmt_reset() - thd Thread handle - packet Packet with stmt id - DESCRIPTION This function resets statement to the state it was right after prepare. It can be used to: - - clear an error happened during mysql_stmt_send_long_data - - cancel long data stream for all placeholders without - having to call mysql_stmt_execute. - - close an open cursor + - clear an error happened during mysql_stmt_send_long_data + - cancel long data stream for all placeholders without + having to call mysql_stmt_execute. + - close an open cursor Sends 'OK' packet in case of success (statement was reset) or 'ERROR' packet (unrecoverable error/statement not found/etc). + + @param thd Thread handle + @param packet Packet with stmt id */ void mysql_stmt_reset(THD *thd, char *packet) @@ -2512,9 +2500,11 @@ void mysql_stmt_reset(THD *thd, char *packet) } -/* +/** Delete a prepared statement from memory. - Note: we don't send any reply to this command. + + @note + we don't send any reply to this command. */ void mysql_stmt_close(THD *thd, char *packet) @@ -2540,15 +2530,14 @@ void mysql_stmt_close(THD *thd, char *packet) } -/* +/** SQLCOM_DEALLOCATE implementation. - DESCRIPTION Close an SQL prepared statement. As this can be called from Dynamic SQL, we should be careful to not close a statement that is currently being executed. - RETURN VALUE + @return none: OK packet is sent in case of success, otherwise an error message is set in THD */ @@ -2571,21 +2560,18 @@ void mysql_sql_stmt_close(THD *thd) send_ok(thd); } -/* +/** Handle long data in pieces from client. - SYNOPSIS - mysql_stmt_get_longdata() - thd Thread handle - packet String to append - packet_length Length of string (including end \0) - - DESCRIPTION Get a part of a long data. To make the protocol efficient, we are not sending any return packets here. If something goes wrong, then we will send the error on 'execute' We assume that the client takes care of checking that all parts are sent to the server. (No checking that we get a 'end of column' in the server is performed). + + @param thd Thread handle + @param packet String to append + @param packet_length Length of string (including end \\0) */ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length) @@ -2750,12 +2736,12 @@ void Prepared_statement::setup_set_params() } -/* - DESCRIPTION - Destroy this prepared statement, cleaning up all used memory - and resources. This is called from ::deallocate() to - handle COM_STMT_CLOSE and DEALLOCATE PREPARE or when - THD ends and all prepared statements are freed. +/** + Destroy this prepared statement, cleaning up all used memory + and resources. + + This is called from ::deallocate() to handle COM_STMT_CLOSE and + DEALLOCATE PREPARE or when THD ends and all prepared statements are freed. */ Prepared_statement::~Prepared_statement() @@ -2812,28 +2798,24 @@ bool Prepared_statement::set_name(LEX_STRING *name_arg) global THD state management to the caller. ***************************************************************************/ -/* +/** Parse statement text, validate the statement, and prepare it for execution. - SYNOPSIS - Prepared_statement::prepare() - packet statement text - packet_len - - DESCRIPTION You should not change global THD state in this function, if at all possible: it may be called from any context, e.g. when executing a COM_* command, and SQLCOM_* command, or a stored procedure. - NOTES - Precondition. - ------------- + @param packet statement text + @param packet_len + + @note + Precondition: The caller must ensure that thd->change_list and thd->free_list is empty: this function will not back them up but will free in the end of its execution. - Postcondition. - -------------- + @note + Postcondition: thd->mem_root contains unused memory allocated during validation. */ @@ -2960,28 +2942,25 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len) DBUG_RETURN(error); } -/* +/** Execute a prepared statement. - SYNOPSIS - Prepared_statement::execute() - expanded_query A query for binlogging which has all parameter - markers ('?') replaced with their actual values. - open_cursor True if an attempt to open a cursor should be made. - Currenlty used only in the binary protocol. - - DESCRIPTION You should not change global THD state in this function, if at all possible: it may be called from any context, e.g. when executing a COM_* command, and SQLCOM_* command, or a stored procedure. - NOTES - Preconditions, postconditions. - ------------------------------ - See the comment for Prepared_statement::prepare(). + @param expanded_query A query for binlogging which has all parameter + markers ('?') replaced with their actual values. + @param open_cursor True if an attempt to open a cursor should be made. + Currenlty used only in the binary protocol. + + @note + Preconditions, postconditions. + - See the comment for Prepared_statement::prepare(). - RETURN - FALSE ok + @retval + FALSE ok + @retval TRUE Error */ @@ -3160,7 +3139,7 @@ error: } -/* Common part of DEALLOCATE PREPARE and mysql_stmt_close */ +/** Common part of DEALLOCATE PREPARE and mysql_stmt_close. */ bool Prepared_statement::deallocate() { diff --git a/sql/sql_profile.cc b/sql/sql_profile.cc new file mode 100644 index 00000000000..1922fa3bc2b --- /dev/null +++ b/sql/sql_profile.cc @@ -0,0 +1,672 @@ +/* Copyright (C) 2007 MySQL AB + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +/** + @file + + Implement query profiling as as list of metaphorical fences, with one fence + per query, and each fencepost a change of thd->proc_info state (with a + snapshot of system statistics). When asked, we can then iterate over the + fenceposts and calculate the distance between them, to inform the user what + happened during a particular query or thd->proc_info state. + + User variables that inform profiling behavior: + - "profiling", boolean, session only, "Are queries profiled?" + - "profiling_history_size", integer, session + global, "Num queries stored?" +*/ + + +#include "mysql_priv.h" +#include "my_sys.h" + +#define TIME_FLOAT_DIGITS 9 +/** two vals encoded: (dec*100)+len */ +#define TIME_I_S_DECIMAL_SIZE (TIME_FLOAT_DIGITS*100)+(TIME_FLOAT_DIGITS-3) + +#define MAX_QUERY_LENGTH 300 + +/* Reserved for systems that can't record the function name in source. */ +const char * const _unknown_func_ = "<unknown>"; + +/** + Connects Information_Schema and Profiling. +*/ +int fill_query_profile_statistics_info(THD *thd, TABLE_LIST *tables, + Item *cond) +{ +#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) + return(thd->profiling.fill_statistics_info(thd, tables, cond)); +#else + my_error(ER_FEATURE_DISABLED, MYF(0), "SHOW PROFILE", "enable-profiling"); + return(1); +#endif +} + +ST_FIELD_INFO query_profile_statistics_info[]= +{ + /* name, length, type, value, maybe_null, old_name, open_method */ + {"QUERY_ID", 20, MYSQL_TYPE_LONG, 0, false, "Query_id", SKIP_OPEN_TABLE}, + {"SEQ", 20, MYSQL_TYPE_LONG, 0, false, "Seq", SKIP_OPEN_TABLE}, + {"STATE", 30, MYSQL_TYPE_STRING, 0, false, "Status", SKIP_OPEN_TABLE}, + {"DURATION", TIME_I_S_DECIMAL_SIZE, MYSQL_TYPE_DECIMAL, 0, false, "Duration", SKIP_OPEN_TABLE}, + {"CPU_USER", TIME_I_S_DECIMAL_SIZE, MYSQL_TYPE_DECIMAL, 0, true, "CPU_user", SKIP_OPEN_TABLE}, + {"CPU_SYSTEM", TIME_I_S_DECIMAL_SIZE, MYSQL_TYPE_DECIMAL, 0, true, "CPU_system", SKIP_OPEN_TABLE}, + {"CONTEXT_VOLUNTARY", 20, MYSQL_TYPE_LONG, 0, true, "Context_voluntary", SKIP_OPEN_TABLE}, + {"CONTEXT_INVOLUNTARY", 20, MYSQL_TYPE_LONG, 0, true, "Context_involuntary", SKIP_OPEN_TABLE}, + {"BLOCK_OPS_IN", 20, MYSQL_TYPE_LONG, 0, true, "Block_ops_in", SKIP_OPEN_TABLE}, + {"BLOCK_OPS_OUT", 20, MYSQL_TYPE_LONG, 0, true, "Block_ops_out", SKIP_OPEN_TABLE}, + {"MESSAGES_SENT", 20, MYSQL_TYPE_LONG, 0, true, "Messages_sent", SKIP_OPEN_TABLE}, + {"MESSAGES_RECEIVED", 20, MYSQL_TYPE_LONG, 0, true, "Messages_received", SKIP_OPEN_TABLE}, + {"PAGE_FAULTS_MAJOR", 20, MYSQL_TYPE_LONG, 0, true, "Page_faults_major", SKIP_OPEN_TABLE}, + {"PAGE_FAULTS_MINOR", 20, MYSQL_TYPE_LONG, 0, true, "Page_faults_minor", SKIP_OPEN_TABLE}, + {"SWAPS", 20, MYSQL_TYPE_LONG, 0, true, "Swaps", SKIP_OPEN_TABLE}, + {"SOURCE_FUNCTION", 30, MYSQL_TYPE_STRING, 0, true, "Source_function", SKIP_OPEN_TABLE}, + {"SOURCE_FILE", 20, MYSQL_TYPE_STRING, 0, true, "Source_file", SKIP_OPEN_TABLE}, + {"SOURCE_LINE", 20, MYSQL_TYPE_LONG, 0, true, "Source_line", SKIP_OPEN_TABLE}, + {NULL, 0, MYSQL_TYPE_STRING, 0, true, NULL, 0} +}; + + +int make_profile_table_for_show(THD *thd, ST_SCHEMA_TABLE *schema_table) +{ + int profile_options = thd->lex->profile_options; + int fields_include_condition_truth_values[]= { + FALSE, /* Query_id */ + FALSE, /* Seq */ + TRUE, /* Status */ + TRUE, /* Duration */ + profile_options & PROFILE_CPU, /* CPU_user */ + profile_options & PROFILE_CPU, /* CPU_system */ + profile_options & PROFILE_CONTEXT, /* Context_voluntary */ + profile_options & PROFILE_CONTEXT, /* Context_involuntary */ + profile_options & PROFILE_BLOCK_IO, /* Block_ops_in */ + profile_options & PROFILE_BLOCK_IO, /* Block_ops_out */ + profile_options & PROFILE_IPC, /* Messages_sent */ + profile_options & PROFILE_IPC, /* Messages_received */ + profile_options & PROFILE_PAGE_FAULTS, /* Page_faults_major */ + profile_options & PROFILE_PAGE_FAULTS, /* Page_faults_minor */ + profile_options & PROFILE_SWAPS, /* Swaps */ + profile_options & PROFILE_SOURCE, /* Source_function */ + profile_options & PROFILE_SOURCE, /* Source_file */ + profile_options & PROFILE_SOURCE, /* Source_line */ + }; + + ST_FIELD_INFO *field_info; + Name_resolution_context *context= &thd->lex->select_lex.context; + int i; + + for (i= 0; schema_table->fields_info[i].field_name != NULL; i++) + { + if (! fields_include_condition_truth_values[i]) + continue; + + field_info= &schema_table->fields_info[i]; + Item_field *field= new Item_field(context, + NullS, NullS, field_info->field_name); + if (field) + { + field->set_name(field_info->old_name, + strlen(field_info->old_name), + system_charset_info); + if (add_item_to_list(thd, field)) + return 1; + } + } + return 0; +} + + +#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) + +#define RUSAGE_USEC(tv) ((tv).tv_sec*1000*1000 + (tv).tv_usec) +#define RUSAGE_DIFF_USEC(tv1, tv2) (RUSAGE_USEC((tv1))-RUSAGE_USEC((tv2))) + + +PROF_MEASUREMENT::PROF_MEASUREMENT(QUERY_PROFILE *profile_arg, const char + *status_arg) + :profile(profile_arg) +{ + collect(); + set_label(status_arg, NULL, NULL, 0); +} + +PROF_MEASUREMENT::PROF_MEASUREMENT(QUERY_PROFILE *profile_arg, + const char *status_arg, + const char *function_arg, + const char *file_arg, + unsigned int line_arg) + :profile(profile_arg) +{ + collect(); + set_label(status_arg, function_arg, file_arg, line_arg); +} + +PROF_MEASUREMENT::~PROF_MEASUREMENT() +{ + if (allocated_status_memory != NULL) + my_free(allocated_status_memory, MYF(0)); + status= function= file= NULL; +} + +void PROF_MEASUREMENT::set_label(const char *status_arg, + const char *function_arg, + const char *file_arg, unsigned int line_arg) +{ + size_t sizes[3]; /* 3 == status+function+file */ + char *cursor; + + /* + Compute all the space we'll need to allocate one block for everything + we'll need, instead of N mallocs. + */ + sizes[0]= (status_arg == NULL) ? 0 : strlen(status_arg) + 1; + sizes[1]= (function_arg == NULL) ? 0 : strlen(function_arg) + 1; + sizes[2]= (file_arg == NULL) ? 0 : strlen(file_arg) + 1; + + allocated_status_memory= (char *) my_malloc(sizes[0] + sizes[1] + sizes[2], MYF(0)); + DBUG_ASSERT(allocated_status_memory != NULL); + + cursor= allocated_status_memory; + + if (status_arg != NULL) + { + strcpy(cursor, status_arg); + status= cursor; + cursor+= sizes[0]; + } + else + status= NULL; + + if (function_arg != NULL) + { + strcpy(cursor, function_arg); + function= cursor; + cursor+= sizes[1]; + } + else + function= NULL; + + if (file_arg != NULL) + { + strcpy(cursor, file_arg); + file= cursor; + cursor+= sizes[2]; + } + else + file= NULL; + + line= line_arg; +} + +/** + This updates the statistics for this moment of time. It captures the state + of the running system, so later we can compare points in time and infer what + happened in the mean time. It should only be called immediately upon + instantiation of this PROF_MEASUREMENT. + + @todo Implement resource capture for OSes not like BSD. +*/ +void PROF_MEASUREMENT::collect() +{ + time_usecs= (double) my_getsystime() / 10.0; /* 1 sec was 1e7, now is 1e6 */ +#ifdef HAVE_GETRUSAGE + getrusage(RUSAGE_SELF, &rusage); +#endif +} + + +QUERY_PROFILE::QUERY_PROFILE(PROFILING *profiling_arg, const char *status_arg) + :profiling(profiling_arg), profiling_query_id(0), query_source(NULL) +{ + profile_start= new PROF_MEASUREMENT(this, status_arg); + entries.push_back(profile_start); + profile_end= profile_start; +} + +QUERY_PROFILE::~QUERY_PROFILE() +{ + while (! entries.is_empty()) + delete entries.pop(); + + if (query_source != NULL) + my_free(query_source, MYF(0)); +} + +/** + @todo Provide a way to include the full text, as in SHOW PROCESSLIST. +*/ +void QUERY_PROFILE::set_query_source(char *query_source_arg, + uint query_length_arg) +{ + /* Truncate to avoid DoS attacks. */ + uint length= min(MAX_QUERY_LENGTH, query_length_arg); + + DBUG_ASSERT(query_source == NULL); /* we don't leak memory */ + if (query_source_arg != NULL) + query_source= my_strndup(query_source_arg, length, MYF(0)); +} + +void QUERY_PROFILE::new_status(const char *status_arg, + const char *function_arg, const char *file_arg, + unsigned int line_arg) +{ + PROF_MEASUREMENT *prof; + DBUG_ENTER("QUERY_PROFILE::status"); + + DBUG_ASSERT(status_arg != NULL); + + if ((function_arg != NULL) && (file_arg != NULL)) + prof= new PROF_MEASUREMENT(this, status_arg, function_arg, file_arg, line_arg); + else + prof= new PROF_MEASUREMENT(this, status_arg); + + profile_end= prof; + entries.push_back(prof); + + DBUG_VOID_RETURN; +} + + + +PROFILING::PROFILING() + :profile_id_counter(1), current(NULL), last(NULL) +{ +} + +PROFILING::~PROFILING() +{ + while (! history.is_empty()) + delete history.pop(); + + if (current != NULL) + delete current; +} + +/** + A new state is given, and that signals the profiler to start a new + timed step for the current query's profile. + + @param status_arg name of this step + @param function_arg calling function (usually supplied from compiler) + @param function_arg calling file (usually supplied from compiler) + @param function_arg calling line number (usually supplied from compiler) +*/ +void PROFILING::status_change(const char *status_arg, + const char *function_arg, + const char *file_arg, unsigned int line_arg) +{ + DBUG_ENTER("PROFILING::status_change"); + + if (status_arg == NULL) /* We don't know how to handle that */ + DBUG_VOID_RETURN; + + if (current == NULL) /* This profile was already discarded. */ + DBUG_VOID_RETURN; + + if (unlikely(enabled)) + current->new_status(status_arg, function_arg, file_arg, line_arg); + + DBUG_VOID_RETURN; +} + +/** + Prepare to start processing a new query. It is an error to do this + if there's a query already in process; nesting is not supported. + + @param initial_state (optional) name of period before first state change +*/ +void PROFILING::start_new_query(const char *initial_state) +{ + DBUG_ENTER("PROFILING::start_new_query"); + + /* This should never happen unless the server is radically altered. */ + if (unlikely(current != NULL)) + { + DBUG_PRINT("warning", ("profiling code was asked to start a new query " + "before the old query was finished. This is " + "probably a bug.")); + finish_current_query(); + } + + enabled= (((thd)->options & OPTION_PROFILING) != 0); + + if (! enabled) DBUG_VOID_RETURN; + + DBUG_ASSERT(current == NULL); + current= new QUERY_PROFILE(this, initial_state); + + DBUG_VOID_RETURN; +} + +/** + Throw away the current profile, because it's useless or unwanted + or corrupted. +*/ +void PROFILING::discard_current_query() +{ + DBUG_ENTER("PROFILING::discard_current_profile"); + + delete current; + current= NULL; + + DBUG_VOID_RETURN; +} + +/** + Try to save the current profile entry, clean up the data if it shouldn't be + saved, and maintain the profile history size. Naturally, this may not + succeed if the profile was previously discarded, and that's expected. +*/ +void PROFILING::finish_current_query() +{ + DBUG_ENTER("PROFILING::finish_current_profile"); + if (current != NULL) + { + /* The last fence-post, so we can support the span before this. */ + status_change("ending", NULL, NULL, 0); + + if ((enabled) && /* ON at start? */ + ((thd->options & OPTION_PROFILING) != 0) && /* and ON at end? */ + (current->query_source != NULL) && + (! current->entries.is_empty())) + { + current->profiling_query_id= next_profile_id(); /* assign an id */ + + history.push_back(current); + last= current; /* never contains something that is not in the history. */ + current= NULL; + } + else + { + delete current; + current= NULL; + } + } + + /* Maintain the history size. */ + while (history.elements > thd->variables.profiling_history_size) + delete history.pop(); + + DBUG_VOID_RETURN; +} + +bool PROFILING::show_profiles() +{ + DBUG_ENTER("PROFILING::show_profiles"); + QUERY_PROFILE *prof; + List<Item> field_list; + + field_list.push_back(new Item_return_int("Query_ID", 10, + MYSQL_TYPE_LONG)); + field_list.push_back(new Item_return_int("Duration", TIME_FLOAT_DIGITS-1, + MYSQL_TYPE_DOUBLE)); + field_list.push_back(new Item_empty_string("Query", 40)); + + if (thd->protocol->send_fields(&field_list, + Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) + DBUG_RETURN(TRUE); + + SELECT_LEX *sel= &thd->lex->select_lex; + SELECT_LEX_UNIT *unit= &thd->lex->unit; + ha_rows idx= 0; + Protocol *protocol= thd->protocol; + + unit->set_limit(sel); + + void *iterator; + for (iterator= history.new_iterator(); + iterator != NULL; + iterator= history.iterator_next(iterator)) + { + prof= history.iterator_value(iterator); + + String elapsed; + + PROF_MEASUREMENT *ps= prof->profile_start; + PROF_MEASUREMENT *pe= prof->profile_end; + + if (++idx <= unit->offset_limit_cnt) + continue; + if (idx > unit->select_limit_cnt) + break; + + protocol->prepare_for_resend(); + protocol->store((uint32)(prof->profiling_query_id)); + protocol->store((double)(pe->time_usecs - ps->time_usecs)/(1000.0*1000), + (uint32) TIME_FLOAT_DIGITS-1, &elapsed); + if (prof->query_source != NULL) + protocol->store(prof->query_source, strlen(prof->query_source), + system_charset_info); + else + protocol->store_null(); + + if (protocol->write()) + DBUG_RETURN(TRUE); + } + send_eof(thd); + DBUG_RETURN(FALSE); +} + +/** + At a point in execution where we know the query source, save the text + of it in the query profile. + + This must be called exactly once per descrete statement. +*/ +void PROFILING::set_query_source(char *query_source_arg, uint query_length_arg) +{ + DBUG_ENTER("PROFILING::set_query_source"); + + if (! enabled) + DBUG_VOID_RETURN; + + if (current != NULL) + current->set_query_source(query_source_arg, query_length_arg); + else + DBUG_PRINT("info", ("no current profile to send query source to")); + DBUG_VOID_RETURN; +} + +/** + Fill the information schema table, "query_profile", as defined in show.cc . + There are two ways to get to this function: Selecting from the information + schema, and a SHOW command. +*/ +int PROFILING::fill_statistics_info(THD *thd, TABLE_LIST *tables, Item *cond) +{ + DBUG_ENTER("PROFILING::fill_statistics_info"); + TABLE *table= tables->table; + ulonglong row_number= 0; + + QUERY_PROFILE *query; + /* Go through each query in this thread's stored history... */ + void *history_iterator; + for (history_iterator= history.new_iterator(); + history_iterator != NULL; + history_iterator= history.iterator_next(history_iterator)) + { + query= history.iterator_value(history_iterator); + + /* + Because we put all profiling info into a table that may be reordered, let + us also include a numbering of each state per query. The query_id and + the "seq" together are unique. + */ + ulonglong seq; + + void *entry_iterator; + PROF_MEASUREMENT *entry, *previous= NULL; + /* ...and for each query, go through all its state-change steps. */ + for (seq= 0, entry_iterator= query->entries.new_iterator(); + entry_iterator != NULL; + entry_iterator= query->entries.iterator_next(entry_iterator), + seq++, previous=entry, row_number++) + { + entry= query->entries.iterator_value(entry_iterator); + + /* Skip the first. We count spans of fence, not fence-posts. */ + if (previous == NULL) continue; + + if (thd->lex->sql_command == SQLCOM_SHOW_PROFILE) + { + /* + We got here via a SHOW command. That means that we stored + information about the query we wish to show and that isn't + in a WHERE clause at a higher level to filter out rows we + wish to exclude. + + Because that functionality isn't available in the server yet, + we must filter here, at the wrong level. Once one can con- + struct where and having conditions at the SQL layer, then this + condition should be ripped out. + */ + if (thd->lex->profile_query_id == 0) /* 0 == show final query */ + { + if (query != last) + continue; + } + else + { + if (thd->lex->profile_query_id != query->profiling_query_id) + continue; + } + } + + /* Set default values for this row. */ + restore_record(table, s->default_values); + + /* + The order of these fields is set by the query_profile_statistics_info + array. + */ + table->field[0]->store((ulonglong) query->profiling_query_id); + table->field[1]->store((ulonglong) seq); /* the step in the sequence */ + /* + This entry, n, has a point in time, T(n), and a status phrase, S(n). + The status phrase S(n) describes the period of time that begins at + T(n). The previous status phrase S(n-1) describes the period of time + that starts at T(n-1) and ends at T(n). Since we want to describe the + time that a status phrase took T(n)-T(n-1), this line must describe the + previous status. + */ + table->field[2]->store(previous->status, strlen(previous->status), + system_charset_info); + + my_decimal duration_decimal; + double2my_decimal(E_DEC_FATAL_ERROR, + (entry->time_usecs-previous->time_usecs)/(1000.0*1000), + &duration_decimal); + + table->field[3]->store_decimal(&duration_decimal); + + +#ifdef HAVE_GETRUSAGE + + my_decimal cpu_utime_decimal, cpu_stime_decimal; + + double2my_decimal(E_DEC_FATAL_ERROR, + RUSAGE_DIFF_USEC(entry->rusage.ru_utime, + previous->rusage.ru_utime) / + (1000.0*1000), + &cpu_utime_decimal); + + double2my_decimal(E_DEC_FATAL_ERROR, + RUSAGE_DIFF_USEC(entry->rusage.ru_stime, + previous->rusage.ru_stime) / + (1000.0*1000), + &cpu_stime_decimal); + + table->field[4]->store_decimal(&cpu_utime_decimal); + table->field[5]->store_decimal(&cpu_stime_decimal); + table->field[4]->set_notnull(); + table->field[5]->set_notnull(); +#else + /* TODO: Add CPU-usage info for non-BSD systems */ +#endif + +#ifdef HAVE_GETRUSAGE + table->field[6]->store((uint32)(entry->rusage.ru_nvcsw - + previous->rusage.ru_nvcsw)); + table->field[6]->set_notnull(); + table->field[7]->store((uint32)(entry->rusage.ru_nivcsw - + previous->rusage.ru_nivcsw)); + table->field[7]->set_notnull(); +#else + /* TODO: Add context switch info for non-BSD systems */ +#endif + +#ifdef HAVE_GETRUSAGE + table->field[8]->store((uint32)(entry->rusage.ru_inblock - + previous->rusage.ru_inblock)); + table->field[8]->set_notnull(); + table->field[9]->store((uint32)(entry->rusage.ru_oublock - + previous->rusage.ru_oublock)); + table->field[9]->set_notnull(); +#else + /* TODO: Add block IO info for non-BSD systems */ +#endif + +#ifdef HAVE_GETRUSAGE + table->field[10]->store((uint32)(entry->rusage.ru_msgsnd - + previous->rusage.ru_msgsnd), true); + table->field[10]->set_notnull(); + table->field[11]->store((uint32)(entry->rusage.ru_msgrcv - + previous->rusage.ru_msgrcv), true); + table->field[11]->set_notnull(); +#else + /* TODO: Add message info for non-BSD systems */ +#endif + +#ifdef HAVE_GETRUSAGE + table->field[12]->store((uint32)(entry->rusage.ru_majflt - + previous->rusage.ru_majflt), true); + table->field[12]->set_notnull(); + table->field[13]->store((uint32)(entry->rusage.ru_minflt - + previous->rusage.ru_minflt), true); + table->field[13]->set_notnull(); +#else + /* TODO: Add page fault info for non-BSD systems */ +#endif + +#ifdef HAVE_GETRUSAGE + table->field[14]->store((uint32)(entry->rusage.ru_nswap - + previous->rusage.ru_nswap), true); + table->field[14]->set_notnull(); +#else + /* TODO: Add swap info for non-BSD systems */ +#endif + + /* Emit the location that started this step, not that ended it. */ + if ((previous->function != NULL) && (previous->file != NULL)) + { + table->field[15]->store(previous->function, strlen(previous->function), + system_charset_info); + table->field[15]->set_notnull(); + table->field[16]->store(previous->file, strlen(previous->file), system_charset_info); + table->field[16]->set_notnull(); + table->field[17]->store(previous->line, true); + table->field[17]->set_notnull(); + } + + if (schema_table_store_record(thd, table)) + DBUG_RETURN(1); + + } + } + + DBUG_RETURN(0); +} +#endif /* ENABLED_PROFILING */ diff --git a/sql/sql_profile.h b/sql/sql_profile.h new file mode 100644 index 00000000000..b5537487d26 --- /dev/null +++ b/sql/sql_profile.h @@ -0,0 +1,297 @@ +/* Copyright (C) 2007 MySQL AB + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifndef _SQL_PROFILE_H +#define _SQL_PROFILE_H + +#if __STDC_VERSION__ < 199901L +# if __GNUC__ >= 2 +# define __func__ __FUNCTION__ +# else +# define __func__ _unknown_func_ +extern const char * const _unknown_func_; +# endif +#elif defined(_MSC_VER) +# if _MSC_VER < 1300 +# define __func__ _unknown_func_ +extern const char * const _unknown_func_; +# else +# define __func__ __FUNCTION__ +# endif +#elif defined(__BORLANDC__) +# define __func__ __FUNC__ +#else +# define __func__ _unknown_func_ +extern const char * const _unknown_func_; +#endif + +extern ST_FIELD_INFO query_profile_statistics_info[]; +int fill_query_profile_statistics_info(THD *thd, TABLE_LIST *tables, Item *cond); +int make_profile_table_for_show(THD *thd, ST_SCHEMA_TABLE *schema_table); + + +#define PROFILE_NONE (uint)0 +#define PROFILE_CPU (uint)(1<<0) +#define PROFILE_MEMORY (uint)(1<<1) +#define PROFILE_BLOCK_IO (uint)(1<<2) +#define PROFILE_CONTEXT (uint)(1<<3) +#define PROFILE_PAGE_FAULTS (uint)(1<<4) +#define PROFILE_IPC (uint)(1<<5) +#define PROFILE_SWAPS (uint)(1<<6) +#define PROFILE_SOURCE (uint)(1<<16) +#define PROFILE_ALL (uint)(~0) + + +#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) +#include "mysql_priv.h" + +#ifdef HAVE_SYS_RESOURCE_H +#include <sys/resource.h> +#endif + + +class PROF_MEASUREMENT; +class QUERY_PROFILE; +class PROFILING; + + +/** + Implements a persistent FIFO using server List method names. Not + thread-safe. Intended to be used on thread-local data only. +*/ +template <class T> class Queue +{ +private: + + struct queue_item + { + T *payload; + struct queue_item *next, *previous; + }; + + struct queue_item *first, *last; + +public: + Queue() + { + elements= 0; + first= last= NULL; + } + + void empty() + { + struct queue_item *i, *after_i; + for (i= first; i != NULL; i= after_i) + { + after_i= i->next; + my_free((char *) i, MYF(0)); + } + elements= 0; + } + + ulong elements; /* The count of items in the Queue */ + + void push_back(T *payload) + { + struct queue_item *new_item; + + new_item= (struct queue_item *) my_malloc(sizeof(struct queue_item), MYF(0)); + + new_item->payload= payload; + + if (first == NULL) + first= new_item; + if (last != NULL) + { + DBUG_ASSERT(last->next == NULL); + last->next= new_item; + } + new_item->previous= last; + new_item->next= NULL; + last= new_item; + + elements++; + } + + T *pop() + { + struct queue_item *old_item= first; + T *ret= NULL; + + if (first == NULL) + { + DBUG_PRINT("warning", ("tried to pop nonexistent item from Queue")); + return NULL; + } + + ret= old_item->payload; + if (first->next != NULL) + first->next->previous= NULL; + else + last= NULL; + first= first->next; + + my_free((char *)old_item, MYF(0)); + elements--; + + return ret; + } + + bool is_empty() + { + DBUG_ASSERT(((elements > 0) && (first != NULL)) || ((elements == 0) || (first == NULL))); + return (elements == 0); + } + + void *new_iterator() + { + return first; + } + + void *iterator_next(void *current) + { + return ((struct queue_item *) current)->next; + } + + T *iterator_value(void *current) + { + return ((struct queue_item *) current)->payload; + } + +}; + + +/** + A single entry in a single profile. +*/ +class PROF_MEASUREMENT +{ +private: + friend class QUERY_PROFILE; + friend class PROFILING; + + QUERY_PROFILE *profile; + char *status; +#ifdef HAVE_GETRUSAGE + struct rusage rusage; +#endif + + char *function; + char *file; + unsigned int line; + + double time_usecs; + char *allocated_status_memory; + + void set_label(const char *status_arg, const char *function_arg, + const char *file_arg, unsigned int line_arg); + void clean_up(); + + PROF_MEASUREMENT(); + PROF_MEASUREMENT(QUERY_PROFILE *profile_arg, const char *status_arg); + PROF_MEASUREMENT(QUERY_PROFILE *profile_arg, const char *status_arg, + const char *function_arg, + const char *file_arg, unsigned int line_arg); + ~PROF_MEASUREMENT(); + void collect(); +}; + + +/** + The full profile for a single query, and includes multiple PROF_MEASUREMENT + objects. +*/ +class QUERY_PROFILE +{ +private: + friend class PROFILING; + + PROFILING *profiling; + + query_id_t profiling_query_id; /* Session-specific id. */ + char *query_source; + + PROF_MEASUREMENT *profile_start; + PROF_MEASUREMENT *profile_end; + Queue<PROF_MEASUREMENT> entries; + + + QUERY_PROFILE(PROFILING *profiling_arg, const char *status_arg); + ~QUERY_PROFILE(); + + void set_query_source(char *query_source_arg, uint query_length_arg); + + /* Add a profile status change to the current profile. */ + void new_status(const char *status_arg, + const char *function_arg, + const char *file_arg, unsigned int line_arg); + + /* Reset the contents of this profile entry. */ + void reset(); + + /* Show this profile. This is called by PROFILING. */ + bool show(uint options); +}; + + +/** + Profiling state for a single THD; contains multiple QUERY_PROFILE objects. +*/ +class PROFILING +{ +private: + friend class PROF_MEASUREMENT; + friend class QUERY_PROFILE; + + /* + Not the system query_id, but a counter unique to profiling. + */ + query_id_t profile_id_counter; + THD *thd; + bool keeping; + bool enabled; + + QUERY_PROFILE *current; + QUERY_PROFILE *last; + Queue<QUERY_PROFILE> history; + + query_id_t next_profile_id() { return(profile_id_counter++); } + +public: + PROFILING(); + ~PROFILING(); + void set_query_source(char *query_source_arg, uint query_length_arg); + + void start_new_query(const char *initial_state= "starting"); + + void discard_current_query(); + + void finish_current_query(); + + void status_change(const char *status_arg, + const char *function_arg, + const char *file_arg, unsigned int line_arg); + + inline void set_thd(THD *thd_arg) { thd= thd_arg; }; + + /* SHOW PROFILES */ + bool show_profiles(); + + /* ... from INFORMATION_SCHEMA.PROFILING ... */ + int fill_statistics_info(THD *thd, TABLE_LIST *tables, Item *cond); +}; + +# endif /* HAVE_PROFILING */ +#endif /* _SQL_PROFILE_H */ diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 88040e2933c..1e05e19c6f5 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -655,7 +655,7 @@ impossible position"; if (read_packet) { - thd->proc_info = "Sending binlog event to slave"; + thd_proc_info(thd, "Sending binlog event to slave"); if (my_net_write(net, (uchar*) packet->ptr(), packet->length()) ) { errmsg = "Failed on my_net_write()"; @@ -693,7 +693,7 @@ impossible position"; bool loop_breaker = 0; /* need this to break out of the for loop from switch */ - thd->proc_info = "Finished reading one binlog; switching to next binlog"; + thd_proc_info(thd, "Finished reading one binlog; switching to next binlog"); switch (mysql_bin_log.find_next_log(&linfo, 1)) { case LOG_INFO_EOF: loop_breaker = (flags & BINLOG_DUMP_NON_BLOCK); @@ -739,14 +739,14 @@ end: (void)my_close(file, MYF(MY_WME)); send_eof(thd); - thd->proc_info = "Waiting to finalize termination"; + thd_proc_info(thd, "Waiting to finalize termination"); pthread_mutex_lock(&LOCK_thread_count); thd->current_linfo = 0; pthread_mutex_unlock(&LOCK_thread_count); DBUG_VOID_RETURN; err: - thd->proc_info = "Waiting to finalize termination"; + thd_proc_info(thd, "Waiting to finalize termination"); end_io_cache(&log); /* Exclude iteration through thread list @@ -900,7 +900,7 @@ int stop_slave(THD* thd, Master_info* mi, bool net_report ) if (check_access(thd, SUPER_ACL, any_db,0,0,0,0)) DBUG_RETURN(1); - thd->proc_info = "Killing slave"; + thd_proc_info(thd, "Killing slave"); int thread_mask; lock_slave_threads(mi); // Get a mask of _running_ threads @@ -927,7 +927,7 @@ int stop_slave(THD* thd, Master_info* mi, bool net_report ) ER(ER_SLAVE_WAS_NOT_RUNNING)); } unlock_slave_threads(mi); - thd->proc_info = 0; + thd_proc_info(thd, 0); if (slave_errno) { @@ -1086,7 +1086,7 @@ bool change_master(THD* thd, Master_info* mi) DBUG_RETURN(TRUE); } - thd->proc_info = "Changing master"; + thd_proc_info(thd, "Changing master"); LEX_MASTER_INFO* lex_mi= &thd->lex->mi; // TODO: see if needs re-write if (init_master_info(mi, master_info_file, relay_log_info_file, 0, @@ -1217,7 +1217,7 @@ bool change_master(THD* thd, Master_info* mi) if (need_relay_log_purge) { relay_log_purge= 1; - thd->proc_info="Purging old relay logs"; + thd_proc_info(thd, "Purging old relay logs"); if (purge_relay_logs(&mi->rli, thd, 0 /* not only reset, but also reinit */, &errmsg)) @@ -1280,7 +1280,7 @@ bool change_master(THD* thd, Master_info* mi) pthread_mutex_unlock(&mi->rli.data_lock); unlock_slave_threads(mi); - thd->proc_info = 0; + thd_proc_info(thd, 0); send_ok(thd); DBUG_RETURN(FALSE); } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 8f9562eb5e2..d77fa6bbb04 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -14,12 +14,16 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /** + @file + + @brief + mysql_select and join optimization + + @defgroup Query_Optimizer Query Optimizer @{ */ -/* mysql_select and join optimization */ - #ifdef USE_PRAGMA_IMPLEMENTATION #pragma implementation // gcc: Class implementation #endif @@ -226,8 +230,8 @@ static void add_group_and_distinct_keys(JOIN *join, JOIN_TAB *join_tab); static bool test_if_ref(Item_field *left_item,Item *right_item); -/* - This handles SELECT with and without UNION +/** + This handles SELECT with and without UNION. */ bool handle_select(THD *thd, LEX *lex, select_result *result, @@ -383,8 +387,8 @@ fix_inner_refs(THD *thd, List<Item> &all_fields, SELECT_LEX *select, return res; } -/* - Function to setup clauses without sum functions +/** + Function to setup clauses without sum functions. */ inline int setup_without_group(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, @@ -417,10 +421,17 @@ inline int setup_without_group(THD *thd, Item **ref_pointer_array, mysql_select assumes that all tables are already opened *****************************************************************************/ -/* +/** Prepare of whole select (including sub queries in future). - return -1 on error - 0 on success + + @todo + Add check of calculation of GROUP functions and fields: + SELECT COUNT(*)+table.col1 from table1; + + @retval + -1 on error + @retval + 0 on success */ int JOIN::prepare(Item ***rref_pointer_array, @@ -750,11 +761,16 @@ static void save_index_subquery_explain_info(JOIN_TAB *join_tab, Item* where) } -/* +/** global select optimisation. - return 0 - success - 1 - error - error code saved in field 'error' + + @note + error code saved in field 'error' + + @retval + 0 success + @retval + 1 error */ int @@ -766,6 +782,7 @@ JOIN::optimize() DBUG_RETURN(0); optimized= 1; + thd_proc_info(thd, "optimizing"); row_limit= ((select_distinct || order || group_list) ? HA_POS_ERROR : unit->select_limit_cnt); /* select_limit is used to decide if we are likely to scan the whole table */ @@ -900,7 +917,14 @@ JOIN::optimize() { error= res; DBUG_PRINT("error",("Error from opt_sum_query")); - DBUG_RETURN(1); + DBUG_RETURN(1); + } + if (res < 0) + { + DBUG_PRINT("info",("No matching min/max row")); + zero_result_cause= "No matching min/max row"; + error=0; + DBUG_RETURN(0); } DBUG_PRINT("info",("Select tables optimized away")); zero_result_cause= "Select tables optimized away"; @@ -936,7 +960,7 @@ JOIN::optimize() sort_by_table= get_sort_by_table(order, group_list, select_lex->leaf_tables); /* Calculate how to do the join */ - thd->proc_info= "statistics"; + thd_proc_info(thd, "statistics"); if (make_join_statistics(this, select_lex->leaf_tables, conds, &keyuse) || thd->is_fatal_error) { @@ -946,7 +970,7 @@ JOIN::optimize() /* Remove distinct if only const tables */ select_distinct= select_distinct && (const_tables != tables); - thd->proc_info= "preparing"; + thd_proc_info(thd, "preparing"); if (result->initialize_tables(this)) { DBUG_PRINT("error",("Error: initialize_tables() failed")); @@ -1335,8 +1359,9 @@ JOIN::optimize() join_tab[const_tables].type != JT_REF_OR_NULL && (order && simple_order || group_list && simple_group)) { - if (add_ref_to_table_cond(thd,&join_tab[const_tables])) + if (add_ref_to_table_cond(thd,&join_tab[const_tables])) { DBUG_RETURN(1); + } } if (!(select_options & SELECT_BIG_RESULT) && @@ -1396,7 +1421,7 @@ JOIN::optimize() if (need_tmp) { DBUG_PRINT("info",("Creating tmp table")); - thd->proc_info="Creating tmp table"; + thd_proc_info(thd, "Creating tmp table"); init_items_ref_array(); @@ -1424,7 +1449,9 @@ JOIN::optimize() select_options, tmp_rows_limit, (char *) ""))) + { DBUG_RETURN(1); + } /* We don't have to store rows in temp table that doesn't match HAVING if: @@ -1444,28 +1471,34 @@ JOIN::optimize() if (group_list && simple_group) { DBUG_PRINT("info",("Sorting for group")); - thd->proc_info="Sorting for group"; + thd_proc_info(thd, "Sorting for group"); if (create_sort_index(thd, this, group_list, HA_POS_ERROR, HA_POS_ERROR, FALSE) || alloc_group_fields(this, group_list) || make_sum_func_list(all_fields, fields_list, 1) || setup_sum_funcs(thd, sum_funcs)) - DBUG_RETURN(1); + { + DBUG_RETURN(1); + } group_list=0; } else { if (make_sum_func_list(all_fields, fields_list, 0) || setup_sum_funcs(thd, sum_funcs)) - DBUG_RETURN(1); + { + DBUG_RETURN(1); + } + if (!group_list && ! exec_tmp_table1->distinct && order && simple_order) { - DBUG_PRINT("info",("Sorting for order")); - thd->proc_info="Sorting for order"; - if (create_sort_index(thd, this, order, + thd_proc_info(thd, "Sorting for order"); + if (create_sort_index(thd, this, order, HA_POS_ERROR, HA_POS_ERROR, TRUE)) - DBUG_RETURN(1); - order=0; + { + DBUG_RETURN(1); + } + order=0; } } @@ -1511,8 +1544,8 @@ JOIN::optimize() } -/* - Restore values in temporary join +/** + Restore values in temporary join. */ void JOIN::restore_tmp() { @@ -1600,8 +1633,16 @@ JOIN::save_join_tab() } -/* - Exec select +/** + Exec select. + + @todo + Note, that create_sort_index calls test_if_skip_sort_order and may + finally replace sorting with index scan if there is a LIMIT clause in + the query. It's never shown in EXPLAIN! + + @todo + When can we have here thd->net.report_error not zero? */ void JOIN::exec() @@ -1610,6 +1651,7 @@ JOIN::exec() int tmp_error; DBUG_ENTER("JOIN::exec"); + thd_proc_info(thd, "executing"); error= 0; if (procedure) { @@ -1748,7 +1790,7 @@ JOIN::exec() curr_tmp_table= exec_tmp_table1; /* Copy data to the temporary table */ - thd->proc_info= "Copying to tmp table"; + thd_proc_info(thd, "Copying to tmp table"); DBUG_PRINT("info", ("%s", thd->proc_info)); if (!curr_join->sort_and_group && curr_join->const_tables != curr_join->tables) @@ -1874,7 +1916,7 @@ JOIN::exec() } if (curr_join->group_list) { - thd->proc_info= "Creating sort index"; + thd_proc_info(thd, "Creating sort index"); if (curr_join->join_tab == join_tab && save_join_tab()) { DBUG_VOID_RETURN; @@ -1888,7 +1930,7 @@ JOIN::exec() sortorder= curr_join->sortorder; } - thd->proc_info="Copying to group table"; + thd_proc_info(thd, "Copying to group table"); DBUG_PRINT("info", ("%s", thd->proc_info)); tmp_error= -1; if (curr_join != this) @@ -1947,7 +1989,7 @@ JOIN::exec() curr_join->join_free(); /* Free quick selects */ if (curr_join->select_distinct && ! curr_join->group_list) { - thd->proc_info="Removing duplicates"; + thd_proc_info(thd, "Removing duplicates"); if (curr_join->tmp_having) curr_join->tmp_having->update_used_tables(); if (remove_duplicates(curr_join, curr_tmp_table, @@ -2010,7 +2052,7 @@ JOIN::exec() if (curr_join->group_list || curr_join->order) { DBUG_PRINT("info",("Sorting for send_fields")); - thd->proc_info="Sorting result"; + thd_proc_info(thd, "Sorting result"); /* If we have already done the group, add HAVING to sorted table */ if (curr_join->tmp_having && ! curr_join->group_list && ! curr_join->sort_and_group) @@ -2145,7 +2187,7 @@ JOIN::exec() } else { - thd->proc_info="Sending data"; + thd_proc_info(thd, "Sending data"); DBUG_PRINT("info", ("%s", thd->proc_info)); result->send_fields((procedure ? curr_join->procedure_fields_list : *curr_fields_list), @@ -2173,8 +2215,11 @@ JOIN::exec() } -/* - Clean up join. Return error that hold JOIN. +/** + Clean up join. + + @return + Return error that hold JOIN. */ int @@ -2208,49 +2253,48 @@ JOIN::destroy() DBUG_RETURN(error); } -/* +/** An entry point to single-unit select (a select without UNION). - SYNOPSIS - mysql_select() - - thd thread handler - rref_pointer_array a reference to ref_pointer_array of - the top-level select_lex for this query - tables list of all tables used in this query. - The tables have been pre-opened. - wild_num number of wildcards used in the top level - select of this query. - For example statement - SELECT *, t1.*, catalog.t2.* FROM t0, t1, t2; - has 3 wildcards. - fields list of items in SELECT list of the top-level - select - e.g. SELECT a, b, c FROM t1 will have Item_field - for a, b and c in this list. - conds top level item of an expression representing - WHERE clause of the top level select - og_num total number of ORDER BY and GROUP BY clauses - arguments - order linked list of ORDER BY agruments - group linked list of GROUP BY arguments - having top level item of HAVING expression - proc_param list of PROCEDUREs - select_options select options (BIG_RESULT, etc) - result an instance of result set handling class. - This object is responsible for send result - set rows to the client or inserting them - into a table. - select_lex the only SELECT_LEX of this query - unit top-level UNIT of this query - UNIT is an artificial object created by the parser - for every SELECT clause. - e.g. SELECT * FROM t1 WHERE a1 IN (SELECT * FROM t2) - has 2 unions. - - RETURN VALUE - FALSE success - TRUE an error + @param thd thread handler + @param rref_pointer_array a reference to ref_pointer_array of + the top-level select_lex for this query + @param tables list of all tables used in this query. + The tables have been pre-opened. + @param wild_num number of wildcards used in the top level + select of this query. + For example statement + SELECT *, t1.*, catalog.t2.* FROM t0, t1, t2; + has 3 wildcards. + @param fields list of items in SELECT list of the top-level + select + e.g. SELECT a, b, c FROM t1 will have Item_field + for a, b and c in this list. + @param conds top level item of an expression representing + WHERE clause of the top level select + @param og_num total number of ORDER BY and GROUP BY clauses + arguments + @param order linked list of ORDER BY agruments + @param group linked list of GROUP BY arguments + @param having top level item of HAVING expression + @param proc_param list of PROCEDUREs + @param select_options select options (BIG_RESULT, etc) + @param result an instance of result set handling class. + This object is responsible for send result + set rows to the client or inserting them + into a table. + @param select_lex the only SELECT_LEX of this query + @param unit top-level UNIT of this query + UNIT is an artificial object created by the + parser for every SELECT clause. + e.g. + SELECT * FROM t1 WHERE a1 IN (SELECT * FROM t2) + has 2 unions. + + @retval + FALSE success + @retval + TRUE an error */ bool @@ -2302,7 +2346,7 @@ mysql_select(THD *thd, Item ***rref_pointer_array, { if (!(join= new JOIN(thd, fields, select_options, result))) DBUG_RETURN(TRUE); - thd->proc_info="init"; + thd_proc_info(thd, "init"); thd->used_tables=0; // Updated by setup_fields if (err= join->prepare(rref_pointer_array, tables, wild_num, conds, og_num, order, group, having, proc_param, @@ -2347,7 +2391,7 @@ mysql_select(THD *thd, Item ***rref_pointer_array, err: if (free_join) { - thd->proc_info="end"; + thd_proc_info(thd, "end"); err|= select_lex->cleanup(); DBUG_RETURN(err || thd->is_error()); } @@ -2401,12 +2445,13 @@ typedef struct st_sargable_param uint num_values; /* number of values in the above array */ } SARGABLE_PARAM; -/* - Calculate the best possible join and initialize the join structure +/** + Calculate the best possible join and initialize the join structure. - RETURN VALUES - 0 ok - 1 Fatal error + @retval + 0 ok + @retval + 1 Fatal error */ static bool @@ -2847,13 +2892,14 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, keyuse Pointer to possible keys *****************************************************************************/ -typedef struct key_field_t { // Used when finding key fields +/// Used when finding key fields +typedef struct key_field_t { Field *field; - Item *val; // May be empty if diff constant + Item *val; ///< May be empty if diff constant uint level; uint optimize; bool eq_func; - /* + /** If true, the condition this struct represents will not be satisfied when val IS NULL. */ @@ -2865,22 +2911,28 @@ typedef struct key_field_t { // Used when finding key fields #define KEY_OPTIMIZE_EXISTS 1 #define KEY_OPTIMIZE_REF_OR_NULL 2 -/* - Merge new key definitions to old ones, remove those not used in both +/** + Merge new key definitions to old ones, remove those not used in both. - This is called for OR between different levels + This is called for OR between different levels. To be able to do 'ref_or_null' we merge a comparison of a column and 'column IS NULL' to one test. This is useful for sub select queries - that are internally transformed to something like: + that are internally transformed to something like:. + @code SELECT * FROM t1 WHERE t1.key=outer_ref_field or t1.key IS NULL + @endcode - KEY_FIELD::null_rejecting is processed as follows: + KEY_FIELD::null_rejecting is processed as follows: @n result has null_rejecting=true if it is set for both ORed references. for example: - (t2.key = t1.field OR t2.key = t1.field) -> null_rejecting=true - (t2.key = t1.field OR t2.key <=> t1.field) -> null_rejecting=false + - (t2.key = t1.field OR t2.key = t1.field) -> null_rejecting=true + - (t2.key = t1.field OR t2.key <=> t1.field) -> null_rejecting=false + + @todo + The result of this is that we're missing some 'ref' accesses. + OptimizerTeam: Fix this */ static KEY_FIELD * @@ -2989,25 +3041,23 @@ merge_key_fields(KEY_FIELD *start,KEY_FIELD *new_fields,KEY_FIELD *end, } -/* +/** Add a possible key to array of possible keys if it's usable as a key - SYNPOSIS - add_key_field() - key_fields Pointer to add key, if usable - and_level And level, to be stored in KEY_FIELD - cond Condition predicate - field Field used in comparision - eq_func True if we used =, <=> or IS NULL - value Value used for comparison with field - usable_tables Tables which can be used for key optimization - sargables IN/OUT Array of found sargable candidates + @param key_fields Pointer to add key, if usable + @param and_level And level, to be stored in KEY_FIELD + @param cond Condition predicate + @param field Field used in comparision + @param eq_func True if we used =, <=> or IS NULL + @param value Value used for comparison with field + @param usable_tables Tables which can be used for key optimization + @param sargables IN/OUT Array of found sargable candidates - NOTES + @note If we are doing a NOT NULL comparison on a NOT NULL field in a outer join table, we store this to be able to do not exists optimization later. - RETURN + @returns *key_fields is incremented if we stored a key in the array */ @@ -3158,26 +3208,25 @@ add_key_field(KEY_FIELD **key_fields,uint and_level, Item_func *cond, (*key_fields)++; } -/* - Add possible keys to array of possible keys originated from a simple predicate - - SYNPOSIS - add_key_equal_fields() - key_fields Pointer to add key, if usable - and_level And level, to be stored in KEY_FIELD - cond Condition predicate - field Field used in comparision - eq_func True if we used =, <=> or IS NULL - value Value used for comparison with field - Is NULL for BETWEEN and IN - usable_tables Tables which can be used for key optimization - sargables IN/OUT Array of found sargable candidates - - NOTES +/** + Add possible keys to array of possible keys originated from a simple + predicate. + + @param key_fields Pointer to add key, if usable + @param and_level And level, to be stored in KEY_FIELD + @param cond Condition predicate + @param field Field used in comparision + @param eq_func True if we used =, <=> or IS NULL + @param value Value used for comparison with field + Is NULL for BETWEEN and IN + @param usable_tables Tables which can be used for key optimization + @param sargables IN/OUT Array of found sargable candidates + + @note If field items f1 and f2 belong to the same multiple equality and a key is added for f1, the the same key is added for f2. - RETURN + @returns *key_fields is incremented if we stored a key in the array */ @@ -3408,9 +3457,13 @@ add_key_fields(JOIN *join, KEY_FIELD **key_fields, uint *and_level, } } -/* - Add all keys with uses 'field' for some keypart - If field->and_level != and_level then only mark key_part as const_part +/** + Add all keys with uses 'field' for some keypart. + + If field->and_level != and_level then only mark key_part as const_part. + + @todo + ft-keys in non-ft queries. SerG */ static uint @@ -3543,33 +3596,37 @@ sort_keyuse(KEYUSE *a,KEYUSE *b) /* - Add to KEY_FIELD array all 'ref' access candidates within nested join - - SYNPOSIS - add_key_fields_for_nj() - nested_join_table IN Nested join pseudo-table to process - end INOUT End of the key field array - and_level INOUT And-level - sargables IN/OUT Array of found sargable candidates + Add to KEY_FIELD array all 'ref' access candidates within nested join. - DESCRIPTION This function populates KEY_FIELD array with entries generated from the ON condition of the given nested join, and does the same for nested joins contained within this nested join. - NOTES + @param[in] nested_join_table Nested join pseudo-table to process + @param[in,out] end End of the key field array + @param[in,out] and_level And-level + @param[in,out] sargables Array of found sargable candidates + + + @note We can add accesses to the tables that are direct children of this nested join (1), and are not inner tables w.r.t their neighbours (2). Example for #1 (outer brackets pair denotes nested join this function is invoked for): + @code ... LEFT JOIN (t1 LEFT JOIN (t2 ... ) ) ON cond + @endcode Example for #2: + @code ... LEFT JOIN (t1 LEFT JOIN t2 ) ON cond + @endcode In examples 1-2 for condition cond, we can add 'ref' access candidates to t1 only. Example #3: + @code ... LEFT JOIN (t1, t2 LEFT JOIN t3 ON inner_cond) ON cond + @endcode Here we can add 'ref' access candidates for t1 and t2, but not for t3. */ @@ -3595,25 +3652,25 @@ static void add_key_fields_for_nj(JOIN *join, TABLE_LIST *nested_join_table, } -/* - Update keyuse array with all possible keys we can use to fetch rows +/** + Update keyuse array with all possible keys we can use to fetch rows. - SYNOPSIS - update_ref_and_keys() - thd - keyuse OUT Put here ordered array of KEYUSE structures - join_tab Array in tablenr_order - tables Number of tables in join - cond WHERE condition (note that the function analyzes - join_tab[i]->on_expr too) - normal_tables Tables not inner w.r.t some outer join (ones for which - we can make ref access based the WHERE clause) - select_lex current SELECT - sargables OUT Array of found sargable candidates + @param thd + @param[out] keyuse Put here ordered array of KEYUSE structures + @param join_tab Array in tablenr_order + @param tables Number of tables in join + @param cond WHERE condition (note that the function analyzes + join_tab[i]->on_expr too) + @param normal_tables Tables not inner w.r.t some outer join (ones + for which we can make ref access based the WHERE + clause) + @param select_lex current SELECT + @param[out] sargables Array of found sargable candidates - RETURN - 0 - OK - 1 - Out of memory. + @retval + 0 OK + @retval + 1 Out of memory. */ static bool @@ -3772,8 +3829,8 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab, return FALSE; } -/* - Update some values in keyuse for faster choose_plan() loop +/** + Update some values in keyuse for faster choose_plan() loop. */ static void optimize_keyuse(JOIN *join, DYNAMIC_ARRAY *keyuse_array) @@ -3814,23 +3871,21 @@ static void optimize_keyuse(JOIN *join, DYNAMIC_ARRAY *keyuse_array) } -/* +/** Discover the indexes that can be used for GROUP BY or DISTINCT queries. - SYNOPSIS - add_group_and_distinct_keys() - join - join_tab + If the query has a GROUP BY clause, find all indexes that contain all + GROUP BY fields, and add those indexes to join->const_keys. - DESCRIPTION - If the query has a GROUP BY clause, find all indexes that contain all - GROUP BY fields, and add those indexes to join->const_keys. - If the query has a DISTINCT clause, find all indexes that contain all - SELECT fields, and add those indexes to join->const_keys. - This allows later on such queries to be processed by a - QUICK_GROUP_MIN_MAX_SELECT. + If the query has a DISTINCT clause, find all indexes that contain all + SELECT fields, and add those indexes to join->const_keys. + This allows later on such queries to be processed by a + QUICK_GROUP_MIN_MAX_SELECT. - RETURN + @param join + @param join_tab + + @return None */ @@ -3882,7 +3937,7 @@ add_group_and_distinct_keys(JOIN *join, JOIN_TAB *join_tab) which uses least records *****************************************************************************/ -/* Save const tables first as used tables */ +/** Save const tables first as used tables. */ static void set_position(JOIN *join,uint idx,JOIN_TAB *table,KEYUSE *key) @@ -3905,31 +3960,28 @@ set_position(JOIN *join,uint idx,JOIN_TAB *table,KEYUSE *key) } -/* - Find the best access path for an extension of a partial execution plan and - add this path to the plan. - - SYNOPSIS - best_access_path() - join pointer to the structure providing all context info - for the query - s the table to be joined by the function - thd thread for the connection that submitted the query - remaining_tables set of tables not included into the partial plan yet - idx the length of the partial plan - record_count estimate for the number of records returned by the partial - plan - read_time the cost of the partial plan - - DESCRIPTION - The function finds the best access path to table 's' from the passed - partial plan where an access path is the general term for any means to - access the data in 's'. An access path may use either an index or a scan, - whichever is cheaper. The input partial plan is passed via the array - 'join->positions' of length 'idx'. The chosen access method for 's' and its - cost are stored in 'join->positions[idx]'. - - RETURN +/** + Find the best access path for an extension of a partial execution + plan and add this path to the plan. + + The function finds the best access path to table 's' from the passed + partial plan where an access path is the general term for any means to + access the data in 's'. An access path may use either an index or a scan, + whichever is cheaper. The input partial plan is passed via the array + 'join->positions' of length 'idx'. The chosen access method for 's' and its + cost are stored in 'join->positions[idx]'. + + @param join pointer to the structure providing all context info + for the query + @param s the table to be joined by the function + @param thd thread for the connection that submitted the query + @param remaining_tables set of tables not included into the partial plan yet + @param idx the length of the partial plan + @param record_count estimate for the number of records returned by the + partial plan + @param read_time the cost of the partial plan + + @return None */ @@ -4457,24 +4509,26 @@ best_access_path(JOIN *join, } -/* +/** Selects and invokes a search strategy for an optimal query plan. - SYNOPSIS - choose_plan() - join pointer to the structure providing all context info for - the query - join_tables set of the tables in the query + The function checks user-configurable parameters that control the search + strategy for an optimal plan, selects the search method and then invokes + it. Each specific optimization procedure stores the final optimal plan in + the array 'join->best_positions', and the cost of the plan in + 'join->best_read'. - DESCRIPTION - The function checks user-configurable parameters that control the search - strategy for an optimal plan, selects the search method and then invokes - it. Each specific optimization procedure stores the final optimal plan in - the array 'join->best_positions', and the cost of the plan in - 'join->best_read'. + @param join pointer to the structure providing all context info for + the query + @param join_tables set of the tables in the query - RETURN VALUES + @todo + 'MAX_TABLES+2' denotes the old implementation of find_best before + the greedy version. Will be removed when greedy_search is approved. + + @retval FALSE ok + @retval TRUE Fatal error */ @@ -4537,13 +4591,11 @@ choose_plan(JOIN *join, table_map join_tables) } -/* +/** Compare two JOIN_TAB objects based on the number of accessed records. - SYNOPSIS - join_tab_cmp() - ptr1 pointer to first JOIN_TAB object - ptr2 pointer to second JOIN_TAB object + @param ptr1 pointer to first JOIN_TAB object + @param ptr2 pointer to second JOIN_TAB object NOTES The order relation implemented by join_tab_cmp() is not transitive, @@ -4556,9 +4608,11 @@ choose_plan(JOIN *join, table_map join_tables) b: dependent = 0x0 table->map = 0x2 found_records = 3 ptr = 0x907e838 c: dependent = 0x6 table->map = 0x10 found_records = 2 ptr = 0x907ecd0 - RETURN + @retval 1 if first is bigger - -1 if second is bigger + @retval + -1 if second is bigger + @retval 0 if equal */ @@ -4580,7 +4634,7 @@ join_tab_cmp(const void* ptr1, const void* ptr2) } -/* +/** Same as join_tab_cmp, but for use with SELECT_STRAIGHT_JOIN. */ @@ -4597,27 +4651,33 @@ join_tab_cmp_straight(const void* ptr1, const void* ptr2) return jt1 > jt2 ? 1 : (jt1 < jt2 ? -1 : 0); } -/* +/** Heuristic procedure to automatically guess a reasonable degree of exhaustiveness for the greedy search procedure. - SYNOPSIS - determine_search_depth() - join pointer to the structure providing all context info for the query + The procedure estimates the optimization time and selects a search depth + big enough to result in a near-optimal QEP, that doesn't take too long to + find. If the number of tables in the query exceeds some constant, then + search_depth is set to this constant. - DESCRIPTION - The procedure estimates the optimization time and selects a search depth - big enough to result in a near-optimal QEP, that doesn't take too long to - find. If the number of tables in the query exceeds some constant, then - search_depth is set to this constant. + @param join pointer to the structure providing all context info for + the query - NOTES + @note This is an extremely simplistic implementation that serves as a stub for a more advanced analysis of the join. Ideally the search depth should be determined by learning from previous query optimizations, because it will depend on the CPU power (and other factors). - RETURN + @todo + this value should be determined dynamically, based on statistics: + uint max_tables_for_exhaustive_opt= 7; + + @todo + this value could be determined by some mapping of the form: + depth : table_count -> [max_tables_for_exhaustive_opt..MAX_EXHAUSTIVE] + + @return A positive integer that specifies the search depth (and thus the exhaustiveness) of the depth-first search algorithm used by 'greedy_search'. @@ -4644,16 +4704,9 @@ determine_search_depth(JOIN *join) } -/* +/** Select the best ways to access the tables in a query without reordering them. - SYNOPSIS - optimize_straight_join() - join pointer to the structure providing all context info for - the query - join_tables set of the tables in the query - - DESCRIPTION Find the best access paths for each query table and compute their costs according to their order in the array 'join->best_ref' (thus without reordering the join tables). The function calls sequentially @@ -4661,15 +4714,17 @@ determine_search_depth(JOIN *join) access method. The final optimal plan is stored in the array 'join->best_positions', and the corresponding cost in 'join->best_read'. - NOTES + @param join pointer to the structure providing all context info for + the query + @param join_tables set of the tables in the query + + @note This function can be applied to: - queries with STRAIGHT_JOIN - internally to compute the cost of an arbitrary QEP + @par Thus 'optimize_straight_join' can be used at any stage of the query optimization process to finalize a QEP as it is. - - RETURN - None */ static void @@ -4702,31 +4757,24 @@ optimize_straight_join(JOIN *join, table_map join_tables) } -/* +/** Find a good, possibly optimal, query execution plan (QEP) by a greedy search. - SYNOPSIS - join pointer to the structure providing all context info - for the query - remaining_tables set of tables not included into the partial plan yet - search_depth controlls the exhaustiveness of the search - prune_level the pruning heuristics that should be applied during - search - - DESCRIPTION The search procedure uses a hybrid greedy/exhaustive search with controlled exhaustiveness. The search is performed in N = card(remaining_tables) steps. Each step evaluates how promising is each of the unoptimized tables, selects the most promising table, and extends the current partial QEP with that table. Currenly the most 'promising' table is the one with least - expensive extension. + expensive extension.\ + There are two extreme cases: - 1. When (card(remaining_tables) < search_depth), the estimate finds the best - complete continuation of the partial QEP. This continuation can be - used directly as a result of the search. - 2. When (search_depth == 1) the 'best_extension_by_limited_search' - consideres the extension of the current QEP with each of the remaining - unoptimized tables. + -# When (card(remaining_tables) < search_depth), the estimate finds the + best complete continuation of the partial QEP. This continuation can be + used directly as a result of the search. + -# When (search_depth == 1) the 'best_extension_by_limited_search' + consideres the extension of the current QEP with each of the remaining + unoptimized tables. + All other cases are in-between these two extremes. Thus the parameter 'search_depth' controlls the exhaustiveness of the search. The higher the value, the longer the optimizaton time and possibly the better the @@ -4734,16 +4782,18 @@ optimize_straight_join(JOIN *join, table_map join_tables) estimated, but the more likely to get a bad QEP. All intermediate and final results of the procedure are stored in 'join': - join->positions modified for every partial QEP that is explored - join->best_positions modified for the current best complete QEP - join->best_read modified for the current best complete QEP - join->best_ref might be partially reordered + - join->positions : modified for every partial QEP that is explored + - join->best_positions: modified for the current best complete QEP + - join->best_read : modified for the current best complete QEP + - join->best_ref : might be partially reordered + The final optimal plan is stored in 'join->best_positions', and its corresponding cost in 'join->best_read'. - NOTES + @note The following pseudocode describes the algorithm of 'greedy_search': + @code procedure greedy_search input: remaining_tables output: pplan; @@ -4757,6 +4807,7 @@ optimize_straight_join(JOIN *join, table_map join_tables) return pplan; } + @endcode where 'best_extension' is a placeholder for a procedure that selects the most "promising" of all tables in 'remaining_tables'. Currently this estimate is performed by calling @@ -4764,16 +4815,26 @@ optimize_straight_join(JOIN *join, table_map join_tables) current QEP of size 'search_depth', thus the complexity of 'greedy_search' mainly depends on that of 'best_extension_by_limited_search'. + @par If 'best_extension()' == 'best_extension_by_limited_search()', then the worst-case complexity of this algorithm is <= O(N*N^search_depth/search_depth). When serch_depth >= N, then the complexity of greedy_search is O(N!). + @par In the future, 'greedy_search' might be extended to support other implementations of 'best_extension', e.g. some simpler quadratic procedure. - RETURN VALUES + @param join pointer to the structure providing all context info + for the query + @param remaining_tables set of tables not included into the partial plan yet + @param search_depth controlls the exhaustiveness of the search + @param prune_level the pruning heuristics that should be applied during + search + + @retval FALSE ok + @retval TRUE Fatal error */ @@ -4849,29 +4910,10 @@ greedy_search(JOIN *join, } -/* +/** Find a good, possibly optimal, query execution plan (QEP) by a possibly exhaustive search. - SYNOPSIS - best_extension_by_limited_search() - join pointer to the structure providing all context info for - the query - remaining_tables set of tables not included into the partial plan yet - idx length of the partial QEP in 'join->positions'; - since a depth-first search is used, also corresponds to - the current depth of the search tree; - also an index in the array 'join->best_ref'; - record_count estimate for the number of records returned by the best - partial plan - read_time the cost of the best partial plan - search_depth maximum depth of the recursion and thus size of the found - optimal plan (0 < search_depth <= join->tables+1). - prune_level pruning heuristics that should be applied during - optimization - (values: 0 = EXHAUSTIVE, 1 = PRUNE_BY_TIME_OR_ROWS) - - DESCRIPTION The procedure searches for the optimal ordering of the query tables in set 'remaining_tables' of size N, and the corresponding optimal access paths to each table. The choice of a table order and an access path for each table @@ -4898,16 +4940,18 @@ greedy_search(JOIN *join, The final optimal plan is stored in 'join->best_positions'. The corresponding cost of the optimal plan is in 'join->best_read'. - NOTES + @note The procedure uses a recursive depth-first search where the depth of the recursion (and thus the exhaustiveness of the search) is controlled by the parameter 'search_depth'. + @note The pseudocode below describes the algorithm of 'best_extension_by_limited_search'. The worst-case complexity of this algorithm is O(N*N^search_depth/search_depth). When serch_depth >= N, then the complexity of greedy_search is O(N!). + @code procedure best_extension_by_limited_search( pplan in, // in, partial plan of tables-joined-so-far pplan_cost, // in, cost of pplan @@ -4947,18 +4991,39 @@ greedy_search(JOIN *join, } } } + @endcode - IMPLEMENTATION + @note When 'best_extension_by_limited_search' is called for the first time, 'join->best_read' must be set to the largest possible value (e.g. DBL_MAX). The actual implementation provides a way to optionally use pruning heuristic (controlled by the parameter 'prune_level') to reduce the search space by skipping some partial plans. + + @note The parameter 'search_depth' provides control over the recursion depth, and thus the size of the resulting optimal plan. - RETURN VALUES + @param join pointer to the structure providing all context info + for the query + @param remaining_tables set of tables not included into the partial plan yet + @param idx length of the partial QEP in 'join->positions'; + since a depth-first search is used, also corresponds + to the current depth of the search tree; + also an index in the array 'join->best_ref'; + @param record_count estimate for the number of records returned by the + best partial plan + @param read_time the cost of the best partial plan + @param search_depth maximum depth of the recursion and thus size of the + found optimal plan + (0 < search_depth <= join->tables+1). + @param prune_level pruning heuristics that should be applied during + optimization + (values: 0 = EXHAUSTIVE, 1 = PRUNE_BY_TIME_OR_ROWS) + + @retval FALSE ok + @retval TRUE Fatal error */ @@ -5098,8 +5163,9 @@ best_extension_by_limited_search(JOIN *join, } -/* - TODO: this function is here only temporarily until 'greedy_search' is +/** + @todo + - TODO: this function is here only temporarily until 'greedy_search' is tested and accepted. RETURN VALUES @@ -5180,8 +5246,8 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, } -/* - Find how much space the prevous read not const tables takes in cache +/** + Find how much space the prevous read not const tables takes in cache. */ static void calc_used_field_length(THD *thd, JOIN_TAB *join_tab) @@ -5325,9 +5391,9 @@ prev_record_reads(JOIN *join, uint idx, table_map found_ref) } -/***************************************************************************** +/** Set up join struct according to best position. -*****************************************************************************/ +*/ static bool get_best_combination(JOIN *join) @@ -5568,9 +5634,11 @@ get_store_key(THD *thd, KEYUSE *keyuse, table_map used_tables, keyuse->val); } -/* - This function is only called for const items on fields which are keys - returns 1 if there was some conversion made when the field was stored. +/** + This function is only called for const items on fields which are keys. + + @return + returns 1 if there was some conversion made when the field was stored. */ bool @@ -5680,22 +5748,18 @@ inline void add_cond_and_fix(Item **e1, Item *e2) } -/* - Add to join_tab->select_cond[i] "table.field IS NOT NULL" conditions we've - inferred from ref/eq_ref access performed. - - SYNOPSIS - add_not_null_conds() - join Join to process +/** + Add to join_tab->select_cond[i] "table.field IS NOT NULL" conditions + we've inferred from ref/eq_ref access performed. - NOTES This function is a part of "Early NULL-values filtering for ref access" optimization. Example of this optimization: - For query SELECT * FROM t1,t2 WHERE t2.key=t1.field - and plan " any-access(t1), ref(t2.key=t1.field) " - add "t1.field IS NOT NULL" to t1's table condition. + For query SELECT * FROM t1,t2 WHERE t2.key=t1.field @n + and plan " any-access(t1), ref(t2.key=t1.field) " @n + add "t1.field IS NOT NULL" to t1's table condition. @n + Description of the optimization: We look through equalities choosen to perform ref/eq_ref access, @@ -5707,8 +5771,10 @@ inline void add_cond_and_fix(Item **e1, Item *e2) Exception from that is the case when referred_tab->join != join. I.e. don't add NOT NULL constraints from any embedded subquery. Consider this query: + @code SELECT A.f2 FROM t1 LEFT JOIN t2 A ON A.f2 = f1 WHERE A.f3=(SELECT MIN(f3) FROM t2 C WHERE A.f4 = C.f4) OR A.f3 IS NULL; + @endocde Here condition A.f3 IS NOT NULL is going to be added to the WHERE condition of the embedding query. Another example: @@ -5779,25 +5845,21 @@ static void add_not_null_conds(JOIN *join) DBUG_VOID_RETURN; } -/* - Build a predicate guarded by match variables for embedding outer joins - - SYNOPSIS - add_found_match_trig_cond() - tab the first inner table for most nested outer join - cond the predicate to be guarded (must be set) - root_tab the first inner table to stop - - DESCRIPTION - The function recursively adds guards for predicate cond - assending from tab to the first inner table next embedding - nested outer join and so on until it reaches root_tab - (root_tab can be 0). - - RETURN VALUE - pointer to the guarded predicate, if success - 0, otherwise -*/ +/** + Build a predicate guarded by match variables for embedding outer joins. + The function recursively adds guards for predicate cond + assending from tab to the first inner table next embedding + nested outer join and so on until it reaches root_tab + (root_tab can be 0). + + @param tab the first inner table for most nested outer join + @param cond the predicate to be guarded (must be set) + @param root_tab the first inner table to stop + + @return + - pointer to the guarded predicate, if success + - 0, otherwise +*/ static COND* add_found_match_trig_cond(JOIN_TAB *tab, COND *cond, JOIN_TAB *root_tab) @@ -5817,14 +5879,9 @@ add_found_match_trig_cond(JOIN_TAB *tab, COND *cond, JOIN_TAB *root_tab) } -/* - Fill in outer join related info for the execution plan structure - - SYNOPSIS - make_outerjoin_info() - join - reference to the info fully describing the query +/** + Fill in outer join related info for the execution plan structure. - DESCRIPTION For each outer join operation left after simplification of the original query the function set up the following pointers in the linear structure join->join_tab representing the selected execution plan. @@ -5839,21 +5896,25 @@ add_found_match_trig_cond(JOIN_TAB *tab, COND *cond, JOIN_TAB *root_tab) corresponding first inner table through the field t0->on_expr_ref. Here ti are structures of the JOIN_TAB type. - EXAMPLE - For the query: - SELECT * FROM t1 - LEFT JOIN - (t2, t3 LEFT JOIN t4 ON t3.a=t4.a) - ON (t1.a=t2.a AND t1.b=t3.b) - WHERE t1.c > 5, + EXAMPLE. For the query: + @code + SELECT * FROM t1 + LEFT JOIN + (t2, t3 LEFT JOIN t4 ON t3.a=t4.a) + ON (t1.a=t2.a AND t1.b=t3.b) + WHERE t1.c > 5, + @endcode + given the execution plan with the table order t1,t2,t3,t4 is selected, the following references will be set; t4->last_inner=[t4], t4->first_inner=[t4], t4->first_upper=[t2] t2->last_inner=[t4], t2->first_inner=t3->first_inner=[t2], on expression (t1.a=t2.a AND t1.b=t3.b) will be attached to *t2->on_expr_ref, while t3.a=t4.a will be attached to *t4->on_expr_ref. - - NOTES + + @param join reference to the info fully describing the query + + @note The function assumes that the simplification procedure has been already applied to the join query (see simplify_joins). This function can be called only after the execution plan @@ -6484,20 +6545,18 @@ make_join_readinfo(JOIN *join, ulonglong options) } -/* - Give error if we some tables are done with a full join +/** + Give error if we some tables are done with a full join. - SYNOPSIS - error_if_full_join() - join Join condition + This is used by multi_table_update and multi_table_delete when running + in safe mode. - USAGE - This is used by multi_table_update and multi_table_delete when running - in safe mode + @param join Join condition - RETURN VALUES - 0 ok - 1 Error (full join used) + @retval + 0 ok + @retval + 1 Error (full join used) */ bool error_if_full_join(JOIN *join) @@ -6517,11 +6576,8 @@ bool error_if_full_join(JOIN *join) } -/* - cleanup JOIN_TAB - - SYNOPSIS - JOIN_TAB::cleanup() +/** + cleanup JOIN_TAB. */ void JOIN_TAB::cleanup() @@ -6551,11 +6607,10 @@ void JOIN_TAB::cleanup() } -/* +/** Partially cleanup JOIN after it has executed: close index or rnd read (table cursors), free quick selects. - DESCRIPTION This function is called in the end of execution of a JOIN, before the used tables are unlocked and closed. @@ -6575,23 +6630,24 @@ void JOIN_TAB::cleanup() If a JOIN is executed for a subquery or if it has a subquery, we can't do the full cleanup and need to do a partial cleanup only. - o If a JOIN is not the top level join, we must not unlock the tables - because the outer select may not have been evaluated yet, and we - can't unlock only selected tables of a query. - - o Additionally, if this JOIN corresponds to a correlated subquery, we - should not free quick selects and join buffers because they will be - needed for the next execution of the correlated subquery. - - o However, if this is a JOIN for a [sub]select, which is not - a correlated subquery itself, but has subqueries, we can free it - fully and also free JOINs of all its subqueries. The exception - is a subquery in SELECT list, e.g: - SELECT a, (select max(b) from t1) group by c - This subquery will not be evaluated at first sweep and its value will - not be inserted into the temporary table. Instead, it's evaluated - when selecting from the temporary table. Therefore, it can't be freed - here even though it's not correlated. + - If a JOIN is not the top level join, we must not unlock the tables + because the outer select may not have been evaluated yet, and we + can't unlock only selected tables of a query. + - Additionally, if this JOIN corresponds to a correlated subquery, we + should not free quick selects and join buffers because they will be + needed for the next execution of the correlated subquery. + - However, if this is a JOIN for a [sub]select, which is not + a correlated subquery itself, but has subqueries, we can free it + fully and also free JOINs of all its subqueries. The exception + is a subquery in SELECT list, e.g: @n + SELECT a, (select max(b) from t1) group by c @n + This subquery will not be evaluated at first sweep and its value will + not be inserted into the temporary table. Instead, it's evaluated + when selecting from the temporary table. Therefore, it can't be freed + here even though it's not correlated. + + @todo + Unlock tables even if the join isn't top level select in the tree */ void JOIN::join_free() @@ -6651,15 +6707,15 @@ void JOIN::join_free() } -/* - Free resources of given join +/** + Free resources of given join. - SYNOPSIS - JOIN::cleanup() - fill - true if we should free all resources, call with full==1 should be - last, before it this function can be called with full==0 + @param fill true if we should free all resources, call with full==1 + should be last, before it this function can be called with + full==0 - NOTE: with subquery this function definitely will be called several times, + @note + With subquery this function definitely will be called several times, but even for simple query it can be called several times. */ @@ -6729,21 +6785,25 @@ void JOIN::cleanup(bool full) } -/***************************************************************************** +/** Remove the following expressions from ORDER BY and GROUP BY: - Constant expressions + Constant expressions @n Expression that only uses tables that are of type EQ_REF and the reference is in the ORDER list or if all refereed tables are of the above type. In the following, the X field can be removed: + @code SELECT * FROM t1,t2 WHERE t1.a=t2.a ORDER BY t1.a,t2.X SELECT * FROM t1,t2,t3 WHERE t1.a=t2.a AND t2.b=t3.b ORDER BY t1.a,t3.X + @endcode These can't be optimized: + @code SELECT * FROM t1,t2 WHERE t1.a=t2.a ORDER BY t2.X,t1.a SELECT * FROM t1,t2 WHERE t1.a=t2.a AND t1.b=t2.b ORDER BY t1.a,t2.c SELECT * FROM t1,t2 WHERE t1.a=t2.a ORDER BY t2.b,t1.a -*****************************************************************************/ + @endcode +*/ static bool eq_ref_table(JOIN *join, ORDER *start_order, JOIN_TAB *tab) @@ -6811,7 +6871,7 @@ only_eq_ref_tables(JOIN *join,ORDER *order,table_map tables) } -/* Update the dependency map for the tables */ +/** Update the dependency map for the tables. */ static void update_depend_map(JOIN *join) { @@ -6838,7 +6898,7 @@ static void update_depend_map(JOIN *join) } -/* Update the dependency map for the sort order */ +/** Update the dependency map for the sort order. */ static void update_depend_map(JOIN *join, ORDER *order) { @@ -6863,25 +6923,23 @@ static void update_depend_map(JOIN *join, ORDER *order) } -/* - Remove all constants and check if ORDER only contains simple expressions - - SYNOPSIS - remove_const() - join Join handler - first_order List of SORT or GROUP order - cond WHERE statement - change_list Set to 1 if we should remove things from list - If this is not set, then only simple_order is - calculated - simple_order Set to 1 if we are only using simple expressions +/** + Remove all constants and check if ORDER only contains simple + expressions. - RETURN - Returns new sort order + simple_order is set to 1 if sort_order only uses fields from head table + and the head table is not a LEFT JOIN table. - simple_order is set to 1 if sort_order only uses fields from head table - and the head table is not a LEFT JOIN table + @param join Join handler + @param first_order List of SORT or GROUP order + @param cond WHERE statement + @param change_list Set to 1 if we should remove things from list. + If this is not set, then only simple_order is + calculated. + @param simple_order Set to 1 if we are only using simple expressions + @return + Returns new sort order */ static ORDER * @@ -7037,25 +7095,23 @@ template class List_iterator<Item_func_match>; #endif -/* - Find the multiple equality predicate containing a field - - SYNOPSIS - find_item_equal() - cond_equal multiple equalities to search in - field field to look for - inherited_fl :out set up to TRUE if multiple equality is found - on upper levels (not on current level of cond_equal) - - DESCRIPTION - The function retrieves the multiple equalities accessed through - the con_equal structure from current level and up looking for - an equality containing field. It stops retrieval as soon as the equality - is found and set up inherited_fl to TRUE if it's found on upper levels. - - RETURN - Item_equal for the found multiple equality predicate if a success; - NULL - otherwise. +/** + Find the multiple equality predicate containing a field. + + The function retrieves the multiple equalities accessed through + the con_equal structure from current level and up looking for + an equality containing field. It stops retrieval as soon as the equality + is found and set up inherited_fl to TRUE if it's found on upper levels. + + @param cond_equal multiple equalities to search in + @param field field to look for + @param[out] inherited_fl set up to TRUE if multiple equality is found + on upper levels (not on current level of + cond_equal) + + @return + - Item_equal for the found multiple equality predicate if a success; + - NULL otherwise. */ Item_equal *find_item_equal(COND_EQUAL *cond_equal, Field *field, @@ -7081,18 +7137,9 @@ finish: } -/* - Check whether an equality can be used to build multiple equalities - - SYNOPSIS - check_simple_equality() - left_item left term of the quality to be checked - right_item right term of the equality to be checked - item equality item if the equality originates from a condition - predicate, 0 if the equality is the result of row elimination - cond_equal multiple equalities that must hold together with the equality +/** + Check whether an equality can be used to build multiple equalities. - DESCRIPTION This function first checks whether the equality (left_item=right_item) is a simple equality i.e. the one that equates a field with another field or a constant (field=field_item or field=const_item). @@ -7107,22 +7154,24 @@ finish: This guarantees that the set of multiple equalities covering equality predicates will be minimal. - EXAMPLE + EXAMPLE: For the where condition - WHERE a=b AND b=c AND - (b=2 OR f=e) + @code + WHERE a=b AND b=c AND + (b=2 OR f=e) + @endcode the check_equality will be called for the following equality predicates a=b, b=c, b=2 and f=e. - For a=b it will be called with *cond_equal=(0,[]) and will transform - *cond_equal into (0,[Item_equal(a,b)]). - For b=c it will be called with *cond_equal=(0,[Item_equal(a,b)]) - and will transform *cond_equal into CE=(0,[Item_equal(a,b,c)]). - For b=2 it will be called with *cond_equal=(ptr(CE),[]) - and will transform *cond_equal into (ptr(CE),[Item_equal(2,a,b,c)]). - For f=e it will be called with *cond_equal=(ptr(CE), []) - and will transform *cond_equal into (ptr(CE),[Item_equal(f,e)]). - - NOTES + - For a=b it will be called with *cond_equal=(0,[]) and will transform + *cond_equal into (0,[Item_equal(a,b)]). + - For b=c it will be called with *cond_equal=(0,[Item_equal(a,b)]) + and will transform *cond_equal into CE=(0,[Item_equal(a,b,c)]). + - For b=2 it will be called with *cond_equal=(ptr(CE),[]) + and will transform *cond_equal into (ptr(CE),[Item_equal(2,a,b,c)]). + - For f=e it will be called with *cond_equal=(ptr(CE), []) + and will transform *cond_equal into (ptr(CE),[Item_equal(f,e)]). + + @note Now only fields that have the same type definitions (verified by the Field::eq_def method) are placed to the same multiple equalities. Because of this some equality predicates are not eliminated and @@ -7134,8 +7183,8 @@ finish: equality. But at the same time it would allow us to get rid of constant propagation completely: it would be done by the call to build_equal_items_for_cond. - - IMPLEMENTATION + + The implementation does not follow exactly the above rules to build a new multiple equality for the equality predicate. If it processes the equality of the form field1=field2, it @@ -7155,9 +7204,18 @@ finish: acceptable, as this happens rarely. The implementation without copying would be much more complicated. - RETURN + @param left_item left term of the quality to be checked + @param right_item right term of the equality to be checked + @param item equality item if the equality originates from a condition + predicate, 0 if the equality is the result of row + elimination + @param cond_equal multiple equalities that must hold together with the + equality + + @retval TRUE if the predicate is a simple equality predicate to be used - for building multiple equalities + for building multiple equalities + @retval FALSE otherwise */ @@ -7326,30 +7384,30 @@ static bool check_simple_equality(Item *left_item, Item *right_item, } -/* - Convert row equalities into a conjunction of regular equalities - - SYNOPSIS - check_row_equality() - thd thread handle - left_row left term of the row equality to be processed - right_row right term of the row equality to be processed - cond_equal multiple equalities that must hold together with the predicate - eq_list results of conversions of row equalities that are not simple - enough to form multiple equalities +/** + Convert row equalities into a conjunction of regular equalities. - DESCRIPTION The function converts a row equality of the form (E1,...,En)=(E'1,...,E'n) into a list of equalities E1=E'1,...,En=E'n. For each of these equalities - Ei=E'i the function checks whether it is a simple equality or a row equality. - If it is a simple equality it is used to expand multiple equalities of - cond_equal. If it is a row equality it converted to a sequence of equalities - between row elements. If Ei=E'i is neither a simple equality nor a row - equality the item for this predicate is added to eq_list. - - RETURN - TRUE if conversion has succeeded (no fatal error) - FALSE otherwise + Ei=E'i the function checks whether it is a simple equality or a row + equality. If it is a simple equality it is used to expand multiple + equalities of cond_equal. If it is a row equality it converted to a + sequence of equalities between row elements. If Ei=E'i is neither a + simple equality nor a row equality the item for this predicate is added + to eq_list. + + @param thd thread handle + @param left_row left term of the row equality to be processed + @param right_row right term of the row equality to be processed + @param cond_equal multiple equalities that must hold together with the + predicate + @param eq_list results of conversions of row equalities that are not + simple enough to form multiple equalities + + @retval + TRUE if conversion has succeeded (no fatal error) + @retval + FALSE otherwise */ static bool check_row_equality(THD *thd, Item *left_row, Item_row *right_row, @@ -7391,18 +7449,9 @@ static bool check_row_equality(THD *thd, Item *left_row, Item_row *right_row, } -/* - Eliminate row equalities and form multiple equalities predicates - - SYNOPSIS - check_equality() - thd thread handle - item predicate to process - cond_equal multiple equalities that must hold together with the predicate - eq_list results of conversions of row equalities that are not simple - enough to form multiple equalities +/** + Eliminate row equalities and form multiple equalities predicates. - DESCRIPTION This function checks whether the item is a simple equality i.e. the one that equates a field with another field or a constant (field=field_item or field=constant_item), or, a row equality. @@ -7410,11 +7459,20 @@ static bool check_row_equality(THD *thd, Item *left_row, Item_row *right_row, in the lists referenced directly or indirectly by cond_equal inferring the given simple equality. If it doesn't find any, it builds/expands multiple equality that covers the predicate. - Row equalities are eliminated substituted for conjunctive regular equalities - which are treated in the same way as original equality predicates. - - RETURN + Row equalities are eliminated substituted for conjunctive regular + equalities which are treated in the same way as original equality + predicates. + + @param thd thread handle + @param item predicate to process + @param cond_equal multiple equalities that must hold together with the + predicate + @param eq_list results of conversions of row equalities that are not + simple enough to form multiple equalities + + @retval TRUE if re-writing rules have been applied + @retval FALSE otherwise, i.e. if the predicate is not an equality, or, if the equality is neither a simple one nor a row equality, @@ -7446,16 +7504,9 @@ static bool check_equality(THD *thd, Item *item, COND_EQUAL *cond_equal, } -/* - Replace all equality predicates in a condition by multiple equality items - - SYNOPSIS - build_equal_items_for_cond() - thd thread handle - cond condition(expression) where to make replacement - inherited path to all inherited multiple equality items +/** + Replace all equality predicates in a condition by multiple equality items. - DESCRIPTION At each 'and' level the function detects items for equality predicates and replaced them by a set of multiple equality items of class Item_equal, taking into account inherited equalities from upper levels. @@ -7474,7 +7525,7 @@ static bool check_equality(THD *thd, Item *item, COND_EQUAL *cond_equal, equality lists of each Item_cond_and object assigning it to thd->lex->current_select->max_equal_elems. - NOTES + @note Multiple equality predicate =(f1,..fn) is equivalent to the conjuction of f1=f2, .., fn-1=fn. It substitutes any inference from these equality predicates that is equivalent to the conjunction. @@ -7492,7 +7543,6 @@ static bool check_equality(THD *thd, Item *item, COND_EQUAL *cond_equal, but if additionally =(t4.d,t2.b) is inherited, it will be replaced by (=(t1.a,t2.b,t3.c,t4.d) AND t2.b>5) - IMPLEMENTATION The function performs the substitution in a recursive descent by the condtion tree, passing to the next AND level a chain of multiple equality predicates which have been built at the upper levels. @@ -7506,10 +7556,15 @@ static bool check_equality(THD *thd, Item *item, COND_EQUAL *cond_equal, - join them into disjoint Item_equal() groups - process the included OR conditions recursively to do the same for lower AND levels. + We need to do things in this order as lower AND levels need to know about all possible Item_equal objects in upper levels. - RETURN + @param thd thread handle + @param cond condition(expression) where to make replacement + @param inherited path to all inherited multiple equality items + + @return pointer to the transformed condition */ @@ -7657,19 +7712,10 @@ static COND *build_equal_items_for_cond(THD *thd, COND *cond, } -/* +/** Build multiple equalities for a condition and all on expressions that - inherit these multiple equalities + inherit these multiple equalities. - SYNOPSIS - build_equal_items() - thd thread handle - cond condition to build the multiple equalities for - inherited path to all inherited multiple equality items - join_list list of join tables to which the condition refers to - cond_equal_ref :out pointer to the structure to place built equalities in - - DESCRIPTION The function first applies the build_equal_items_for_cond function to build all multiple equalities for condition cond utilizing equalities referred through the parameter inherited. The extended set of @@ -7678,14 +7724,16 @@ static COND *build_equal_items_for_cond(THD *thd, COND *cond, all on expressions whose direct references can be found in join_list and who inherit directly the multiple equalities just having built. - NOTES + @note The on expression used in an outer join operation inherits all equalities - from the on expression of the embedding join, if there is any, or + from the on expression of the embedding join, if there is any, or otherwise - from the where condition. This fact is not obvious, but presumably can be proved. Consider the following query: + @code SELECT * FROM (t1,t2) LEFT JOIN (t3,t4) ON t1.a=t3.a AND t2.a=t4.a WHERE t1.a=t2.a; + @endcode If the on expression in the query inherits =(t1.a,t2.a), then we can build the multiple equality =(t1.a,t2.a,t3.a,t4.a) that infers the equality t3.a=t4.a. Although the on expression @@ -7695,23 +7743,38 @@ static COND *build_equal_items_for_cond(THD *thd, COND *cond, Interesting that multiple equality =(t1.a,t2.a,t3.a,t4.a) allows us to use t1.a=t3.a AND t3.a=t4.a under the on condition: + @code SELECT * FROM (t1,t2) LEFT JOIN (t3,t4) ON t1.a=t3.a AND t3.a=t4.a WHERE t1.a=t2.a + @endcode This query equivalent to: + @code SELECT * FROM (t1 LEFT JOIN (t3,t4) ON t1.a=t3.a AND t3.a=t4.a),t2 WHERE t1.a=t2.a + @endcode Similarly the original query can be rewritten to the query: + @code SELECT * FROM (t1,t2) LEFT JOIN (t3,t4) ON t2.a=t4.a AND t3.a=t4.a WHERE t1.a=t2.a + @endcode that is equivalent to: + @code SELECT * FROM (t2 LEFT JOIN (t3,t4)ON t2.a=t4.a AND t3.a=t4.a), t1 WHERE t1.a=t2.a + @endcode Thus, applying equalities from the where condition we basically can get more freedom in performing join operations. Althogh we don't use this property now, it probably makes sense to use it in the future. - - RETURN + @param thd Thread handler + @param cond condition to build the multiple equalities for + @param inherited path to all inherited multiple equality items + @param join_list list of join tables to which the condition + refers to + @param[out] cond_equal_ref pointer to the structure to place built + equalities in + + @return pointer to the transformed condition containing multiple equalities */ @@ -7769,25 +7832,24 @@ static COND *build_equal_items(THD *thd, COND *cond, } -/* - Compare field items by table order in the execution plan - - SYNOPSIS - compare_fields_by_table_order() - field1 first field item to compare - field2 second field item to compare - table_join_idx index to tables determining table order +/** + Compare field items by table order in the execution plan. - DESCRIPTION field1 considered as better than field2 if the table containing field1 is accessed earlier than the table containing field2. The function finds out what of two fields is better according this criteria. - RETURN - 1, if field1 is better than field2 - -1, if field2 is better than field1 - 0, otherwise + @param field1 first field item to compare + @param field2 second field item to compare + @param table_join_idx index to tables determining table order + + @retval + 1 if field1 is better than field2 + @retval + -1 if field2 is better than field1 + @retval + 0 otherwise */ static int compare_fields_by_table_order(Item_field *field1, @@ -7814,16 +7876,9 @@ static int compare_fields_by_table_order(Item_field *field1, } -/* - Generate minimal set of simple equalities equivalent to a multiple equality - - SYNOPSIS - eliminate_item_equal() - cond condition to add the generated equality to - upper_levels structure to access multiple equality of upper levels - item_equal multiple equality to generate simple equality from +/** + Generate minimal set of simple equalities equivalent to a multiple equality. - DESCRIPTION The function retrieves the fields of the multiple equality item item_equal and for each field f: - if item_equal contains const it generates the equality f=const_item; @@ -7831,7 +7886,11 @@ static int compare_fields_by_table_order(Item_field *field1, f=item_equal->get_first(). All generated equality are added to the cond conjunction. - NOTES + @param cond condition to add the generated equality to + @param upper_levels structure to access multiple equality of upper levels + @param item_equal multiple equality to generate simple equality from + + @note Before generating an equality function checks that it has not been generated for multiple equalities of the upper levels. E.g. for the following where condition @@ -7851,10 +7910,10 @@ static int compare_fields_by_table_order(Item_field *field1, If cond is equal to 0, then not more then one equality is generated and a pointer to it is returned as the result of the function. - RETURN - The condition with generated simple equalities or + @return + - The condition with generated simple equalities or a pointer to the simple generated equality, if success. - 0, otherwise. + - 0, otherwise. */ static Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels, @@ -7929,17 +7988,10 @@ static Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels, } -/* - Substitute every field reference in a condition by the best equal field - and eliminate all multiple equality predicates - - SYNOPSIS - substitute_for_best_equal_field() - cond condition to process - cond_equal multiple equalities to take into consideration - table_join_idx index to tables determining field preference +/** + Substitute every field reference in a condition by the best equal field + and eliminate all multiple equality predicates. - DESCRIPTION The function retrieves the cond condition and for each encountered multiple equality predicate it sorts the field references in it according to the order of tables specified by the table_join_idx @@ -7950,14 +8002,17 @@ static Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels, After this the function retrieves all other conjuncted predicates substitute every field reference by the field reference to the first equal field or equal constant if there are any. - - NOTES + @param cond condition to process + @param cond_equal multiple equalities to take into consideration + @param table_join_idx index to tables determining field preference + + @note At the first glance full sort of fields in multiple equality seems to be an overkill. Yet it's not the case due to possible new fields in multiple equality item of lower levels. We want the order in them to comply with the order of upper levels. - RETURN + @return The transformed condition */ @@ -8032,20 +8087,17 @@ static COND* substitute_for_best_equal_field(COND *cond, } -/* +/** Check appearance of new constant items in multiple equalities - of a condition after reading a constant table - - SYNOPSIS - update_const_equal_items() - cond condition whose multiple equalities are to be checked - table constant table that has been read + of a condition after reading a constant table. - DESCRIPTION The function retrieves the cond condition and for each encountered multiple equality checks whether new constants have appeared after reading the constant (single row) table tab. If so it adjusts the multiple equality appropriately. + + @param cond condition whose multiple equalities are to be checked + @param table constant table that has been read */ static void update_const_equal_items(COND *cond, JOIN_TAB *tab) @@ -8184,14 +8236,12 @@ change_cond_ref_to_const(THD *thd, I_List<COND_CMP> *save_list, } } -/* - Remove additional condition inserted by IN/ALL/ANY transformation +/** + Remove additional condition inserted by IN/ALL/ANY transformation. - SYNOPSIS - remove_additional_cond() - conds Condition for processing + @param conds condition for processing - RETURN VALUES + @return new conditions */ @@ -8279,17 +8329,10 @@ propagate_cond_constants(THD *thd, I_List<COND_CMP> *save_list, } -/* - Simplify joins replacing outer joins by inner joins whenever it's possible - - SYNOPSIS - simplify_joins() - join reference to the query info - join_list list representation of the join to be converted - conds conditions to add on expressions for converted joins - top true <=> conds is the where condition +/** + Simplify joins replacing outer joins by inner joins whenever it's + possible. - DESCRIPTION The function, during a retrieval of join_list, eliminates those outer joins that can be converted into inner join, possibly nested. It also moves the on expressions for the converted outer joins @@ -8313,26 +8356,39 @@ propagate_cond_constants(THD *thd, I_List<COND_CMP> *save_list, The function also removes all braces that can be removed from the join expression without changing its meaning. - NOTES + @note An outer join can be replaced by an inner join if the where condition or the on expression for an embedding nested join contains a conjunctive predicate rejecting null values for some attribute of the inner tables. E.g. in the query: + @code SELECT * FROM t1 LEFT JOIN t2 ON t2.a=t1.a WHERE t2.b < 5 + @endcode the predicate t2.b < 5 rejects nulls. The query is converted first to: + @code SELECT * FROM t1 INNER JOIN t2 ON t2.a=t1.a WHERE t2.b < 5 + @endcode then to the equivalent form: - SELECT * FROM t1, t2 ON t2.a=t1.a WHERE t2.b < 5 AND t2.a=t1.a. + @code + SELECT * FROM t1, t2 ON t2.a=t1.a WHERE t2.b < 5 AND t2.a=t1.a + @endcode + Similarly the following query: + @code SELECT * from t1 LEFT JOIN (t2, t3) ON t2.a=t1.a t3.b=t1.b WHERE t2.c < 5 + @endcode is converted to: + @code SELECT * FROM t1, (t2, t3) WHERE t2.c < 5 AND t2.a=t1.a t3.b=t1.b + @endcode + One conversion might trigger another: + @code SELECT * FROM t1 LEFT JOIN t2 ON t2.a=t1.a LEFT JOIN t3 ON t3.b=t2.b WHERE t3 IS NOT NULL => @@ -8340,16 +8396,26 @@ propagate_cond_constants(THD *thd, I_List<COND_CMP> *save_list, WHERE t3 IS NOT NULL AND t3.b=t2.b => SELECT * FROM t1, t2, t3 WHERE t3 IS NOT NULL AND t3.b=t2.b AND t2.a=t1.a - + @endcode + The function removes all unnecessary braces from the expression produced by the conversions. - E.g. SELECT * FROM t1, (t2, t3) WHERE t2.c < 5 AND t2.a=t1.a AND t3.b=t1.b + E.g. + @code + SELECT * FROM t1, (t2, t3) WHERE t2.c < 5 AND t2.a=t1.a AND t3.b=t1.b + @endcode finally is converted to: + @code SELECT * FROM t1, t2, t3 WHERE t2.c < 5 AND t2.a=t1.a AND t3.b=t1.b + @endcode + + It also will remove braces from the following queries: + @code SELECT * from (t1 LEFT JOIN t2 ON t2.a=t1.a) LEFT JOIN t3 ON t3.b=t2.b SELECT * from (t1, (t2,t3)) WHERE t1.a=t2.a AND t2.b=t3.b. + @endcode The benefit of this simplification procedure is that it might return a query for which the optimizer can evaluate execution plan with more @@ -8357,20 +8423,26 @@ propagate_cond_constants(THD *thd, I_List<COND_CMP> *save_list, consider any plan where one of the inner tables is before some of outer tables. - IMPLEMENTATION. + The function is implemented by a recursive procedure. On the recursive ascent all attributes are calculated, all outer joins that can be converted are replaced and then all unnecessary braces are removed. As join list contains join tables in the reverse order sequential elimination of outer joins does not require extra recursive calls. - EXAMPLES Here is an example of a join query with invalid cross references: + @code SELECT * FROM t1 LEFT JOIN t2 ON t2.a=t3.a LEFT JOIN t3 ON t3.b=t1.b - - RETURN VALUE - The new condition, if success - 0, otherwise + @endcode + + @param join reference to the query info + @param join_list list representation of the join to be converted + @param conds conditions to add on expressions for converted joins + @param top true <=> conds is the where condition + + @return + - The new condition, if success + - 0, otherwise */ static COND * @@ -8532,26 +8604,23 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top) } -/* - Assign each nested join structure a bit in nested_join_map - - SYNOPSIS - build_bitmap_for_nested_joins() - join Join being processed - join_list List of tables - first_unused Number of first unused bit in nested_join_map before the - call +/** + Assign each nested join structure a bit in nested_join_map. - DESCRIPTION Assign each nested join structure (except "confluent" ones - those that embed only one element) a bit in nested_join_map. - NOTE + @param join Join being processed + @param join_list List of tables + @param first_unused Number of first unused bit in nested_join_map before the + call + + @note This function is called after simplify_joins(), when there are no redundant nested joins, #non_confluent_nested_joins <= #tables_in_join so we will not run out of bits in nested_join_map. - RETURN + @return First unused bit in nested_join_map after the call. */ @@ -8587,17 +8656,14 @@ static uint build_bitmap_for_nested_joins(List<TABLE_LIST> *join_list, } -/* - Set NESTED_JOIN::counter=0 in all nested joins in passed list - - SYNOPSIS - reset_nj_counters() - join_list List of nested joins to process. It may also contain base - tables which will be ignored. +/** + Set NESTED_JOIN::counter=0 in all nested joins in passed list. - DESCRIPTION Recursively set NESTED_JOIN::counter=0 for all nested joins contained in the passed join_list. + + @param join_list List of nested joins to process. It may also contain base + tables which will be ignored. */ static void reset_nj_counters(List<TABLE_LIST> *join_list) @@ -8618,95 +8684,96 @@ static void reset_nj_counters(List<TABLE_LIST> *join_list) } -/* - Check interleaving with an inner tables of an outer join for extension table - - SYNOPSIS - check_interleaving_with_nj() - join Join being processed - last_tab Last table in current partial join order (this function is - not called for empty partial join orders) - next_tab Table we're going to extend the current partial join with +/** + Check interleaving with an inner tables of an outer join for + extension table. - DESCRIPTION Check if table next_tab can be added to current partial join order, and if yes, record that it has been added. The function assumes that both current partial join order and its extension with next_tab are valid wrt table dependencies. - IMPLEMENTATION - LIMITATIONS ON JOIN ORDER - The nested [outer] joins executioner algorithm imposes these limitations - on join order: - 1. "Outer tables first" - any "outer" table must be before any - corresponding "inner" table. - 2. "No interleaving" - tables inside a nested join must form a continuous - sequence in join order (i.e. the sequence must not be interrupted by - tables that are outside of this nested join). - - #1 is checked elsewhere, this function checks #2 provided that #1 has - been already checked. - - WHY NEED NON-INTERLEAVING - Consider an example: - - select * from t0 join t1 left join (t2 join t3) on cond1 - - The join order "t1 t2 t0 t3" is invalid: - - table t0 is outside of the nested join, so WHERE condition for t0 is - attached directly to t0 (without triggers, and it may be used to access - t0). Applying WHERE(t0) to (t2,t0,t3) record is invalid as we may miss - combinations of (t1, t2, t3) that satisfy condition cond1, and produce a - null-complemented (t1, t2.NULLs, t3.NULLs) row, which should not have - been produced. - - If table t0 is not between t2 and t3, the problem doesn't exist: - * If t0 is located after (t2,t3), WHERE(t0) is applied after nested join - processing has finished. - * If t0 is located before (t2,t3), predicates like WHERE_cond(t0, t2) are - wrapped into condition triggers, which takes care of correct nested - join processing. - - HOW IT IS IMPLEMENTED - The limitations on join order can be rephrased as follows: for valid - join order one must be able to: - 1. write down the used tables in the join order on one line. - 2. for each nested join, put one '(' and one ')' on the said line - 3. write "LEFT JOIN" and "ON (...)" where appropriate - 4. get a query equivalent to the query we're trying to execute. - - Calls to check_interleaving_with_nj() are equivalent to writing the - above described line from left to right. - A single check_interleaving_with_nj(A,B) call is equivalent to writing - table B and appropriate brackets on condition that table A and - appropriate brackets is the last what was written. Graphically the - transition is as follows: - - +---- current position - | - ... last_tab ))) | ( next_tab ) )..) | ... - X Y Z | - +- need to move to this - position. - - Notes about the position: - The caller guarantees that there is no more then one X-bracket by - checking "!(remaining_tables & s->dependent)" before calling this - function. X-bracket may have a pair in Y-bracket. - - When "writing" we store/update this auxilary info about the current - position: - 1. join->cur_embedding_map - bitmap of pairs of brackets (aka nested - joins) we've opened but didn't close. - 2. {each NESTED_JOIN structure not simplified away}->counter - number - of this nested join's children that have already been added to to - the partial join order. - - RETURN - FALSE Join order extended, nested joins info about current join order - (see NOTE section) updated. + @verbatim + IMPLEMENTATION + LIMITATIONS ON JOIN ORDER + The nested [outer] joins executioner algorithm imposes these limitations + on join order: + 1. "Outer tables first" - any "outer" table must be before any + corresponding "inner" table. + 2. "No interleaving" - tables inside a nested join must form a continuous + sequence in join order (i.e. the sequence must not be interrupted by + tables that are outside of this nested join). + + #1 is checked elsewhere, this function checks #2 provided that #1 has + been already checked. + + WHY NEED NON-INTERLEAVING + Consider an example: + + select * from t0 join t1 left join (t2 join t3) on cond1 + + The join order "t1 t2 t0 t3" is invalid: + + table t0 is outside of the nested join, so WHERE condition for t0 is + attached directly to t0 (without triggers, and it may be used to access + t0). Applying WHERE(t0) to (t2,t0,t3) record is invalid as we may miss + combinations of (t1, t2, t3) that satisfy condition cond1, and produce a + null-complemented (t1, t2.NULLs, t3.NULLs) row, which should not have + been produced. + + If table t0 is not between t2 and t3, the problem doesn't exist: + If t0 is located after (t2,t3), WHERE(t0) is applied after nested join + processing has finished. + If t0 is located before (t2,t3), predicates like WHERE_cond(t0, t2) are + wrapped into condition triggers, which takes care of correct nested + join processing. + + HOW IT IS IMPLEMENTED + The limitations on join order can be rephrased as follows: for valid + join order one must be able to: + 1. write down the used tables in the join order on one line. + 2. for each nested join, put one '(' and one ')' on the said line + 3. write "LEFT JOIN" and "ON (...)" where appropriate + 4. get a query equivalent to the query we're trying to execute. + + Calls to check_interleaving_with_nj() are equivalent to writing the + above described line from left to right. + A single check_interleaving_with_nj(A,B) call is equivalent to writing + table B and appropriate brackets on condition that table A and + appropriate brackets is the last what was written. Graphically the + transition is as follows: + + +---- current position + | + ... last_tab ))) | ( next_tab ) )..) | ... + X Y Z | + +- need to move to this + position. + + Notes about the position: + The caller guarantees that there is no more then one X-bracket by + checking "!(remaining_tables & s->dependent)" before calling this + function. X-bracket may have a pair in Y-bracket. + + When "writing" we store/update this auxilary info about the current + position: + 1. join->cur_embedding_map - bitmap of pairs of brackets (aka nested + joins) we've opened but didn't close. + 2. {each NESTED_JOIN structure not simplified away}->counter - number + of this nested join's children that have already been added to to + the partial join order. + @endverbatim + + @param join Join being processed + @param last_tab Last table in current partial join order (this function is + not called for empty partial join orders) + @param next_tab Table we're going to extend the current partial join with + + @retval + FALSE Join order extended, nested joins info about current join + order (see NOTE section) updated. + @retval TRUE Requested join order extension not allowed. */ @@ -8755,19 +8822,16 @@ static bool check_interleaving_with_nj(JOIN_TAB *last_tab, JOIN_TAB *next_tab) } -/* - Nested joins perspective: Remove the last table from the join order +/** + Nested joins perspective: Remove the last table from the join order. - SYNOPSIS - restore_prev_nj_state() - last join table to remove, it is assumed to be the last in current - partial join order. - - DESCRIPTION Remove the last table from the partial join order and update the nested joins counters and join->cur_embedding_map. It is ok to call this function for the first table in join order (for which check_interleaving_with_nj has not been called) + + @param last join table to remove, it is assumed to be the last in current + partial join order. */ static void restore_prev_nj_state(JOIN_TAB *last) @@ -8826,12 +8890,15 @@ optimize_cond(JOIN *join, COND *conds, List<TABLE_LIST> *join_list, } -/* - Remove const and eq items. Return new item, or NULL if no condition - cond_value is set to according: - COND_OK query is possible (field = constant) - COND_TRUE always true ( 1 = 1 ) - COND_FALSE always false ( 1 = 2 ) +/** + Remove const and eq items. + + @return + Return new item, or NULL if no condition @n + cond_value is set to according: + - COND_OK : query is possible (field = constant) + - COND_TRUE : always true ( 1 = 1 ) + - COND_FALSE : always false ( 1 = 2 ) */ COND * @@ -9022,8 +9089,8 @@ test_if_equality_guarantees_uniqueness(Item *l, Item *r) l->collation.collation == r->collation.collation))); } -/* - Return 1 if the item is a const value in all the WHERE clause +/** + Return TRUE if the item is a const value in all the WHERE clause. */ static bool @@ -9084,26 +9151,25 @@ const_expression_in_where(COND *cond, Item *comp_item, Item **const_item) Create internal temporary table ****************************************************************************/ -/* - Create field for temporary table from given field - - SYNOPSIS - create_tmp_field_from_field() - thd Thread handler - org_field field from which new field will be created - name New field name - table Temporary table - item !=NULL if item->result_field should point to new field. - This is relevant for how fill_record() is going to work: - If item != NULL then fill_record() will update - the record in the original table. - If item == NULL then fill_record() will update - the temporary table - convert_blob_length If >0 create a varstring(convert_blob_length) field - instead of blob. - - RETURN - 0 on error +/** + Create field for temporary table from given field. + + @param thd Thread handler + @param org_field field from which new field will be created + @param name New field name + @param table Temporary table + @param item !=NULL if item->result_field should point to new field. + This is relevant for how fill_record() is going to work: + If item != NULL then fill_record() will update + the record in the original table. + If item == NULL then fill_record() will update + the temporary table + @param convert_blob_length If >0 create a varstring(convert_blob_length) + field instead of blob. + + @retval + NULL on error + @retval new_created field */ @@ -9146,28 +9212,27 @@ Field *create_tmp_field_from_field(THD *thd, Field *org_field, return new_field; } -/* - Create field for temporary table using type of given item - - SYNOPSIS - create_tmp_field_from_item() - thd Thread handler - item Item to create a field for - table Temporary table - copy_func If set and item is a function, store copy of item - in this array - modify_item 1 if item->result_field should point to new item. - This is relevent for how fill_record() is going to - work: - If modify_item is 1 then fill_record() will update - the record in the original table. - If modify_item is 0 then fill_record() will update - the temporary table - convert_blob_length If >0 create a varstring(convert_blob_length) field - instead of blob. - - RETURN - 0 on error +/** + Create field for temporary table using type of given item. + + @param thd Thread handler + @param item Item to create a field for + @param table Temporary table + @param copy_func If set and item is a function, store copy of + item in this array + @param modify_item 1 if item->result_field should point to new + item. This is relevent for how fill_record() + is going to work: + If modify_item is 1 then fill_record() will + update the record in the original table. + If modify_item is 0 then fill_record() will + update the temporary table + @param convert_blob_length If >0 create a varstring(convert_blob_length) + field instead of blob. + + @retval + 0 on error + @retval new_created field */ @@ -9282,17 +9347,16 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table, } -/* - Create field for information schema table +/** + Create field for information schema table. - SYNOPSIS - create_tmp_field_for_schema() - thd Thread handler - table Temporary table - item Item to create a field for + @param thd Thread handler + @param table Temporary table + @param item Item to create a field for - RETURN + @retval 0 on error + @retval new_created field */ @@ -9316,33 +9380,32 @@ Field *create_tmp_field_for_schema(THD *thd, Item *item, TABLE *table) } -/* - Create field for temporary table - - SYNOPSIS - create_tmp_field() - thd Thread handler - table Temporary table - item Item to create a field for - type Type of item (normally item->type) - copy_func If set and item is a function, store copy of item - in this array - from_field if field will be created using other field as example, - pointer example field will be written here - default_field If field has a default value field, store it here - group 1 if we are going to do a relative group by on result - modify_item 1 if item->result_field should point to new item. - This is relevent for how fill_record() is going to - work: - If modify_item is 1 then fill_record() will update - the record in the original table. - If modify_item is 0 then fill_record() will update - the temporary table - convert_blob_length If >0 create a varstring(convert_blob_length) field - instead of blob. - - RETURN +/** + Create field for temporary table. + + @param thd Thread handler + @param table Temporary table + @param item Item to create a field for + @param type Type of item (normally item->type) + @param copy_func If set and item is a function, store copy of item + in this array + @param from_field if field will be created using other field as example, + pointer example field will be written here + @param default_field If field has a default value field, store it here + @param group 1 if we are going to do a relative group by on result + @param modify_item 1 if item->result_field should point to new item. + This is relevent for how fill_record() is going to + work: + If modify_item is 1 then fill_record() will update + the record in the original table. + If modify_item is 0 then fill_record() will update + the temporary table + @param convert_blob_length If >0 create a varstring(convert_blob_length) + field instead of blob. + + @retval 0 on error + @retval new_created field */ @@ -9503,33 +9566,30 @@ void setup_tmp_table_column_bitmaps(TABLE *table, uchar *bitmaps) } -/* +/** Create a temp table according to a field list. - SYNOPSIS - create_tmp_table() - thd thread handle - param a description used as input to create the table - fields list of items that will be used to define - column types of the table (also see NOTES) - group TODO document - distinct should table rows be distinct - save_sum_fields see NOTES - select_options - rows_limit - table_alias possible name of the temporary table that can be used - for name resolving; can be "". - - DESCRIPTION - Given field pointers are changed to point at tmp_table for - send_fields. The table object is self contained: it's - allocated in its own memory root, as well as Field objects - created for table columns. - This function will replace Item_sum items in 'fields' list with - corresponding Item_field items, pointing at the fields in the - temporary table, unless this was prohibited by TRUE - value of argument save_sum_fields. The Item_field objects - are created in THD memory root. + Given field pointers are changed to point at tmp_table for + send_fields. The table object is self contained: it's + allocated in its own memory root, as well as Field objects + created for table columns. + This function will replace Item_sum items in 'fields' list with + corresponding Item_field items, pointing at the fields in the + temporary table, unless this was prohibited by TRUE + value of argument save_sum_fields. The Item_field objects + are created in THD memory root. + + @param thd thread handle + @param param a description used as input to create the table + @param fields list of items that will be used to define + column types of the table (also see NOTES) + @param group TODO document + @param distinct should table rows be distinct + @param save_sum_fields see NOTES + @param select_options + @param rows_limit + @param table_alias possible name of the temporary table that can + be used for name resolving; can be "". */ #define STRING_TOTAL_LENGTH_TO_PACK_ROWS 128 @@ -10200,16 +10260,10 @@ err: /****************************************************************************/ -/* +/** Create a reduced TABLE object with properly set up Field list from a list of field definitions. - SYNOPSIS - create_virtual_tmp_table() - thd connection handle - field_list list of column definitions - - DESCRIPTION The created table doesn't have a table handler associated with it, has no keys, no group/distinct, no copy_funcs array. The sole purpose of this TABLE object is to use the power of Field @@ -10218,7 +10272,10 @@ err: The table is created in THD mem_root, so are the table's fields. Consequently, if you don't BLOB fields, you don't need to free it. - RETURN + @param thd connection handle + @param field_list list of column definitions + + @return 0 if out of memory, TABLE object in case of success */ @@ -10464,7 +10521,7 @@ free_tmp_table(THD *thd, TABLE *entry) DBUG_PRINT("enter",("table: %s",entry->alias)); save_proc_info=thd->proc_info; - thd->proc_info="removing tmp table"; + thd_proc_info(thd, "removing tmp table"); if (entry->file) { @@ -10486,13 +10543,14 @@ free_tmp_table(THD *thd, TABLE *entry) plugin_unlock(0, entry->s->db_plugin); free_root(&own_root, MYF(0)); /* the table is allocated in its own root */ - thd->proc_info=save_proc_info; + thd_proc_info(thd, save_proc_info); DBUG_VOID_RETURN; } -/* -* If a HEAP table gets full, create a MyISAM table and copy all rows to this +/** + If a HEAP table gets full, create a MyISAM table and copy all rows + to this. */ bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param, @@ -10519,7 +10577,7 @@ bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param, DBUG_RETURN(1); // End of memory save_proc_info=thd->proc_info; - thd->proc_info="converting HEAP to MyISAM"; + thd_proc_info(thd, "converting HEAP to MyISAM"); if (create_myisam_tmp_table(&new_table, param, thd->lex->select_lex.options | thd->options)) @@ -10583,8 +10641,8 @@ bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param, table->file->change_table_ptr(table, table->s); table->use_all_columns(); if (save_proc_info) - thd->proc_info= (!strcmp(save_proc_info,"Copying to tmp table") ? - "Copying to tmp table on disk" : save_proc_info); + thd_proc_info(thd, (!strcmp(save_proc_info,"Copying to tmp table") ? + "Copying to tmp table on disk" : save_proc_info)); DBUG_RETURN(0); err: @@ -10596,23 +10654,21 @@ bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param, new_table.file->delete_table(new_table.s->table_name.str); err2: delete new_table.file; - thd->proc_info=save_proc_info; + thd_proc_info(thd, save_proc_info); table->mem_root= new_table.mem_root; DBUG_RETURN(1); } -/* - SYNOPSIS - setup_end_select_func() - join join to setup the function for. +/** + @details + Rows produced by a join sweep may end up in a temporary table or be sent + to a client. Setup the function of the nested loop join algorithm which + handles final fully constructed and matched records. - DESCRIPTION - Rows produced by a join sweep may end up in a temporary table or be sent - to a client. Setup the function of the nested loop join algorithm which - handles final fully constructed and matched records. + @param join join to setup the function for. - RETURN + @return end_select function to use. This function can't fail. */ @@ -10677,12 +10733,16 @@ Next_select_func setup_end_select_func(JOIN *join) } -/**************************************************************************** - Make a join of all tables and write it on socket or to table - Return: 0 if ok - 1 if error is sent - -1 if error should be sent -****************************************************************************/ +/** + Make a join of all tables and write it on socket or to table. + + @retval + 0 if ok + @retval + 1 if error is sent + @retval + -1 if error should be sent +*/ static int do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure) @@ -10829,30 +10889,25 @@ sub_select_cache(JOIN *join,JOIN_TAB *join_tab,bool end_of_records) return rc; } -/* - Retrieve records ends with a given beginning from the result of a join - - SYNPOSIS - sub_select() - join pointer to the structure providing all context info for the query - join_tab the first next table of the execution plan to be retrieved - end_records true when we need to perform final steps of retrival +/** + Retrieve records ends with a given beginning from the result of a join. - DESCRIPTION For a given partial join record consisting of records from the tables preceding the table join_tab in the execution plan, the function retrieves all matching full records from the result set and send them to the result set stream. - NOTES + @note The function effectively implements the final (n-k) nested loops of nested loops join algorithm, where k is the ordinal number of the join_tab table and n is the total number of tables in the join query. It performs nested loops joins with all conjunctive predicates from the where condition pushed as low to the tables as possible. E.g. for the query - SELECT * FROM t1,t2,t3 - WHERE t1.a=t2.a AND t2.b=t3.b AND t1.a BETWEEN 5 AND 9 + @code + SELECT * FROM t1,t2,t3 + WHERE t1.a=t2.a AND t2.b=t3.b AND t1.a BETWEEN 5 AND 9 + @endcode the predicate (t1.a BETWEEN 5 AND 9) will be pushed to table t1, given the selected plan prescribes to nest retrievals of the joined tables in the following order: t1,t2,t3. @@ -10868,9 +10923,11 @@ sub_select_cache(JOIN *join,JOIN_TAB *join_tab,bool end_of_records) the execution plan. In this case the pushed down predicates can be checked only at certain conditions. Suppose for the query - SELECT * FROM t1 LEFT JOIN (t2,t3) ON t3.a=t1.a - WHERE t1>2 AND (t2.b>5 OR t2.b IS NULL) - the optimizer has chosen a plan with the table order t1,t2,t3. + @code + SELECT * FROM t1 LEFT JOIN (t2,t3) ON t3.a=t1.a + WHERE t1>2 AND (t2.b>5 OR t2.b IS NULL) + @endcode + the optimizer has chosen a plan with the table order t1,t2,t3. The predicate P1=t1>2 will be pushed down to the table t1, while the predicate P2=(t2.b>5 OR t2.b IS NULL) will be attached to the table t2. But the second predicate can not be unconditionally tested right @@ -10898,7 +10955,9 @@ sub_select_cache(JOIN *join,JOIN_TAB *join_tab,bool end_of_records) been done for the first row with a match. The only difference is the predicates from on expressions are not checked. - IMPLEMENTATION + @par + @b IMPLEMENTATION + @par The function forms output rows for a current partial join of k tables tables recursively. For each partial join record ending with a certain row from @@ -10914,11 +10973,13 @@ sub_select_cache(JOIN *join,JOIN_TAB *join_tab,bool end_of_records) To carry out a return to a nested loop level of join table t the pointer to t is remembered in the field 'return_tab' of the join structure. Consider the following query: - SELECT * FROM t1, - LEFT JOIN - (t2, t3 LEFT JOIN (t4,t5) ON t5.a=t3.a) - ON t4.a=t2.a - WHERE (t2.b=5 OR t2.b IS NULL) AND (t4.b=2 OR t4.b IS NULL) + @code + SELECT * FROM t1, + LEFT JOIN + (t2, t3 LEFT JOIN (t4,t5) ON t5.a=t3.a) + ON t4.a=t2.a + WHERE (t2.b=5 OR t2.b IS NULL) AND (t4.b=2 OR t4.b IS NULL) + @endcode Suppose the chosen execution plan dictates the order t1,t2,t3,t4,t5 and suppose for a given joined rows from tables t1,t2,t3 there are no rows in the result set yet. @@ -10933,11 +10994,18 @@ sub_select_cache(JOIN *join,JOIN_TAB *join_tab,bool end_of_records) Thus, when the first row from t5 with t5.a=t3.a is found this pointer for t5 is changed from t4 to t2. - STRUCTURE NOTES + @par + @b STRUCTURE @b NOTES + @par join_tab->first_unmatched points always backwards to the first inner table of the embedding nested join, if any. - RETURN + @param join pointer to the structure providing all context info for + the query + @param join_tab the first next table of the execution plan to be retrieved + @param end_records true when we need to perform final steps of retrival + + @return return one of enum_nested_loop_state, except NESTED_LOOP_NO_MORE_ROWS. */ @@ -11000,10 +11068,9 @@ sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records) } -/* +/** Process one record of the nested loop join. - DESCRIPTION This function will evaluate parts of WHERE/ON clauses that are applicable to the partial record on hand and in case of success submit this record to the next level of the nested loop. @@ -11127,8 +11194,9 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab, } -/* - DESCRIPTION +/** + + @details Construct a NULL complimented partial join record and feed it to the next level of the nested loop. This function is used in case we have an OUTER join and no matching record was found. @@ -11272,7 +11340,7 @@ flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skip_last) Returns -1 if row was not found, 0 if row was found and 1 on errors *****************************************************************************/ -/* Help function when we get some an error from the table handler */ +/** Help function when we get some an error from the table handler. */ int report_error(TABLE *table, int error) { @@ -11411,17 +11479,17 @@ join_read_system(JOIN_TAB *tab) } -/* - Read a table when there is at most one matching row +/** + Read a table when there is at most one matching row. - SYNOPSIS - join_read_const() - tab Table to read + @param tab Table to read - RETURN + @retval 0 Row was found - -1 Row was not found - 1 Got an error (other than row not found) during read + @retval + -1 Row was not found + @retval + 1 Got an error (other than row not found) during read */ static int @@ -11522,9 +11590,9 @@ join_read_always_key(JOIN_TAB *tab) } -/* +/** This function is used when optimizing away ORDER BY in - SELECT * FROM t1 WHERE a=1 ORDER BY a DESC,b DESC + SELECT * FROM t1 WHERE a=1 ORDER BY a DESC,b DESC. */ static int @@ -11739,8 +11807,8 @@ join_ft_read_next(READ_RECORD *info) } -/* - Reading of key with key reference and one part that may be NULL +/** + Reading of key with key reference and one part that may be NULL. */ int @@ -12049,8 +12117,8 @@ end: DBUG_RETURN(NESTED_LOOP_OK); } -/* Group by searching after group record and updating it if possible */ /* ARGSUSED */ +/** Group by searching after group record and updating it if possible. */ static enum_nested_loop_state end_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), @@ -12125,7 +12193,7 @@ end_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), } -/* Like end_update, but this is done with unique constraints instead of keys */ +/** Like end_update, but this is done with unique constraints instead of keys. */ static enum_nested_loop_state end_unique_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), @@ -12256,7 +12324,10 @@ end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), in sorted order. *****************************************************************************/ -/* Return 1 if right_item is used removable reference key on left_item */ +/** + @return + 1 if right_item is used removable reference key on left_item +*/ static bool test_if_ref(Item_field *left_item,Item *right_item) { @@ -12410,26 +12481,26 @@ part_of_refkey(TABLE *table,Field *field) } -/***************************************************************************** - Test if one can use the key to resolve ORDER BY +/** + Test if one can use the key to resolve ORDER BY. - SYNOPSIS - test_if_order_by_key() - order Sort order - table Table to sort - idx Index to check - used_key_parts Return value for used key parts. + @param order Sort order + @param table Table to sort + @param idx Index to check + @param used_key_parts Return value for used key parts. - NOTES + @note used_key_parts is set to correct key parts used if return value != 0 (On other cases, used_key_part may be changed) - RETURN + @retval 1 key is ok. + @retval 0 Key can't be used - -1 Reverse key can be used -*****************************************************************************/ + @retval + -1 Reverse key can be used +*/ static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx, uint *used_key_parts) @@ -12524,20 +12595,19 @@ uint find_shortest_key(TABLE *table, const key_map *usable_keys) return best; } -/* +/** Test if a second key is the subkey of the first one. - SYNOPSIS - is_subkey() - key_part First key parts - ref_key_part Second key parts - ref_key_part_end Last+1 part of the second key + @param key_part First key parts + @param ref_key_part Second key parts + @param ref_key_part_end Last+1 part of the second key - NOTE + @note Second key MUST be shorter than the first one. - RETURN + @retval 1 is a subkey + @retval 0 no sub key */ @@ -12551,17 +12621,16 @@ is_subkey(KEY_PART_INFO *key_part, KEY_PART_INFO *ref_key_part, return 1; } -/* - Test if we can use one of the 'usable_keys' instead of 'ref' key for sorting +/** + Test if we can use one of the 'usable_keys' instead of 'ref' key + for sorting. - SYNOPSIS - test_if_subkey() - ref Number of key, used for WHERE clause - usable_keys Keys for testing + @param ref Number of key, used for WHERE clause + @param usable_keys Keys for testing - RETURN - MAX_KEY If we can't use other key - the number of found key Otherwise + @return + - MAX_KEY If we can't use other key + - the number of found key Otherwise */ static uint @@ -12592,24 +12661,19 @@ test_if_subkey(ORDER *order, TABLE *table, uint ref, uint ref_key_parts, } -/* +/** Check if GROUP BY/DISTINCT can be optimized away because the set is already known to be distinct. - - SYNOPSIS - list_contains_unique_index () - table The table to operate on. - find_func function to iterate over the list and search - for a field - DESCRIPTION - Used in removing the GROUP BY/DISTINCT of the following types of - statements: - SELECT [DISTINCT] <unique_key_cols>... FROM <single_table_ref> - [GROUP BY <unique_key_cols>,...] + Used in removing the GROUP BY/DISTINCT of the following types of + statements: + @code + SELECT [DISTINCT] <unique_key_cols>... FROM <single_table_ref> + [GROUP BY <unique_key_cols>,...] + @endcode If (a,b,c is distinct) - then <any combination of a,b,c>,{whatever} is also distinct + then <any combination of a,b,c>,{whatever} is also distinct This function checks if all the key parts of any of the unique keys of the table are referenced by a list : either the select list @@ -12618,9 +12682,14 @@ test_if_subkey(ORDER *order, TABLE *table, uint ref, uint ref_key_parts, If the above holds and the key parts cannot contain NULLs then we can safely remove the GROUP BY/DISTINCT, as no result set can be more distinct than an unique key. - - RETURN VALUE + + @param table The table to operate on. + @param find_func function to iterate over the list and search + for a field + + @retval 1 found + @retval 0 not found. */ @@ -12653,20 +12722,17 @@ list_contains_unique_index(TABLE *table, } -/* +/** Helper function for list_contains_unique_index. Find a field reference in a list of ORDER structures. - - SYNOPSIS - find_field_in_order_list () - field The field to search for. - data ORDER *.The list to search in - - DESCRIPTION - Finds a direct reference of the Field in the list. - - RETURN VALUE + Finds a direct reference of the Field in the list. + + @param field The field to search for. + @param data ORDER *.The list to search in + + @retval 1 found + @retval 0 not found. */ @@ -12689,20 +12755,17 @@ find_field_in_order_list (Field *field, void *data) } -/* +/** Helper function for list_contains_unique_index. Find a field reference in a dynamic list of Items. - - SYNOPSIS - find_field_in_item_list () - field in The field to search for. - data in List<Item> *.The list to search in - - DESCRIPTION - Finds a direct reference of the Field in the list. - - RETURN VALUE + Finds a direct reference of the Field in the list. + + @param[in] field The field to search for. + @param[in] data List<Item> *.The list to search in + + @retval 1 found + @retval 0 not found. */ @@ -12727,7 +12790,7 @@ find_field_in_item_list (Field *field, void *data) } -/* +/** Test if we can skip the ORDER BY by using an index. If we can use an index, the JOIN_TAB / tab->select struct @@ -12735,9 +12798,14 @@ find_field_in_item_list (Field *field, void *data) The index must cover all fields in <order>, or it will not be considered. - Return: - 0 We have to use filesort to do the sorting - 1 We can use an index. + @todo + - sergeyp: Results of all index merge selects actually are ordered + by clustered PK values. + + @retval + 0 We have to use filesort to do the sorting + @retval + 1 We can use an index. */ static bool @@ -13276,11 +13344,11 @@ err: DBUG_RETURN(-1); } -/* - Add the HAVING criteria to table->select +#ifdef NOT_YET +/** + Add the HAVING criteria to table->select. */ -#ifdef NOT_YET static bool fix_having(JOIN *join, Item **having) { (*having)->update_used_tables(); // Some tables may have been const @@ -13487,9 +13555,11 @@ err: } -/* - Generate a hash index for each row to quickly find duplicate rows - Note that this will not work on tables with blobs! +/** + Generate a hash index for each row to quickly find duplicate rows. + + @note + Note that this will not work on tables with blobs! */ static int remove_dup_with_hash_index(THD *thd, TABLE *table, @@ -13926,37 +13996,37 @@ cp_buffer_from_ref(THD *thd, TABLE *table, TABLE_REF *ref) Group and order functions *****************************************************************************/ -/* +/** Resolve an ORDER BY or GROUP BY column reference. - SYNOPSIS - find_order_in_list() - thd [in] Pointer to current thread structure - ref_pointer_array [in/out] All select, group and order by fields - tables [in] List of tables to search in (usually FROM clause) - order [in] Column reference to be resolved - fields [in] List of fields to search in (usually SELECT list) - all_fields [in/out] All select, group and order by fields - is_group_field [in] True if order is a GROUP field, false if - ORDER by field - - DESCRIPTION - Given a column reference (represented by 'order') from a GROUP BY or ORDER - BY clause, find the actual column it represents. If the column being - resolved is from the GROUP BY clause, the procedure searches the SELECT - list 'fields' and the columns in the FROM list 'tables'. If 'order' is from - the ORDER BY clause, only the SELECT list is being searched. - - If 'order' is resolved to an Item, then order->item is set to the found - Item. If there is no item for the found column (that is, it was resolved - into a table field), order->item is 'fixed' and is added to all_fields and - ref_pointer_array. - - RETURN + Given a column reference (represented by 'order') from a GROUP BY or ORDER + BY clause, find the actual column it represents. If the column being + resolved is from the GROUP BY clause, the procedure searches the SELECT + list 'fields' and the columns in the FROM list 'tables'. If 'order' is from + the ORDER BY clause, only the SELECT list is being searched. + + If 'order' is resolved to an Item, then order->item is set to the found + Item. If there is no item for the found column (that is, it was resolved + into a table field), order->item is 'fixed' and is added to all_fields and + ref_pointer_array. + + ref_pointer_array and all_fields are updated. + + @param[in] thd Pointer to current thread structure + @param[in,out] ref_pointer_array All select, group and order by fields + @param[in] tables List of tables to search in (usually + FROM clause) + @param[in] order Column reference to be resolved + @param[in] fields List of fields to search in (usually + SELECT list) + @param[in,out] all_fields All select, group and order by fields + @param[in] is_group_field True if order is a GROUP field, false if + ORDER by field + + @retval FALSE if OK + @retval TRUE if error occurred - - ref_pointer_array and all_fields are updated */ static bool @@ -14090,9 +14160,11 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, } -/* - Change order to point at item in select list. If item isn't a number - and doesn't exits in the select list, add it the the field list. +/** + Change order to point at item in select list. + + If item isn't a number and doesn't exits in the select list, add it the + the field list. */ int setup_order(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, @@ -14109,27 +14181,30 @@ int setup_order(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, } -/* +/** Intitialize the GROUP BY list. - SYNOPSIS - setup_group() - thd Thread handler - ref_pointer_array We store references to all fields that was not in - 'fields' here. - fields All fields in the select part. Any item in 'order' - that is part of these list is replaced by a pointer - to this fields. - all_fields Total list of all unique fields used by the select. - All items in 'order' that was not part of fields will - be added first to this list. - order The fields we should do GROUP BY on. - hidden_group_fields Pointer to flag that is set to 1 if we added any fields - to all_fields. - - RETURN - 0 ok - 1 error (probably out of memory) + @param thd Thread handler + @param ref_pointer_array We store references to all fields that was + not in 'fields' here. + @param fields All fields in the select part. Any item in + 'order' that is part of these list is replaced + by a pointer to this fields. + @param all_fields Total list of all unique fields used by the + select. All items in 'order' that was not part + of fields will be added first to this list. + @param order The fields we should do GROUP BY on. + @param hidden_group_fields Pointer to flag that is set to 1 if we added + any fields to all_fields. + + @todo + change ER_WRONG_FIELD_WITH_GROUP to more detailed + ER_NON_GROUPING_FIELD_USED + + @retval + 0 ok + @retval + 1 error (probably out of memory) */ int @@ -14222,8 +14297,11 @@ next_field: return 0; } -/* - Add fields with aren't used at start of field list. Return FALSE if ok +/** + Add fields with aren't used at start of field list. + + @return + FALSE if ok */ static bool @@ -14253,10 +14331,11 @@ setup_new_fields(THD *thd, List<Item> &fields, DBUG_RETURN(0); } -/* - Create a group by that consist of all non const fields. Try to use - the fields in the order given by 'order' to allow one to optimize - away 'order by'. +/** + Create a group by that consist of all non const fields. + + Try to use the fields in the order given by 'order' to allow one to + optimize away 'order by'. */ static ORDER * @@ -14343,9 +14422,9 @@ next_item: } -/***************************************************************************** - Update join with count of the different type of fields -*****************************************************************************/ +/** + Update join with count of the different type of fields. +*/ void count_field_types(SELECT_LEX *select_lex, TMP_TABLE_PARAM *param, @@ -14395,8 +14474,9 @@ count_field_types(SELECT_LEX *select_lex, TMP_TABLE_PARAM *param, } -/* - Return 1 if second is a subpart of first argument +/** + Return 1 if second is a subpart of first argument. + If first parts has different direction, change it to second part (group is sorted like order) */ @@ -14414,10 +14494,9 @@ test_if_subpart(ORDER *a,ORDER *b) return test(!b); } -/* +/** Return table number if there is only one table in sort order - and group and order is compatible - else return 0; + and group and order is compatible, else return 0. */ static TABLE * @@ -14448,7 +14527,9 @@ get_sort_by_table(ORDER *a,ORDER *b,TABLE_LIST *tables) } - /* calc how big buffer we need for comparing group entries */ +/** + calc how big buffer we need for comparing group entries. +*/ static void calc_group_buffer(JOIN *join,ORDER *group) @@ -14533,17 +14614,17 @@ calc_group_buffer(JOIN *join,ORDER *group) } -/* - allocate group fields or take prepared (cached) +/** + allocate group fields or take prepared (cached). - SYNOPSIS - make_group_fields() - main_join - join of current select - curr_join - current join (join of current select or temporary copy of it) + @param main_join join of current select + @param curr_join current join (join of current select or temporary copy + of it) - RETURN - 0 - ok - 1 - failed + @retval + 0 ok + @retval + 1 failed */ static bool @@ -14564,9 +14645,10 @@ make_group_fields(JOIN *main_join, JOIN *curr_join) } -/* - Get a list of buffers for saveing last group - Groups are saved in reverse order for easyer check loop +/** + Get a list of buffers for saveing last group. + + Groups are saved in reverse order for easyer check loop. */ static bool @@ -14604,27 +14686,33 @@ test_if_group_changed(List<Cached_item> &list) } -/* - Setup copy_fields to save fields at start of new group +/** + Setup copy_fields to save fields at start of new group. - setup_copy_fields() - thd - THD pointer - param - temporary table parameters - ref_pointer_array - array of pointers to top elements of filed list - res_selected_fields - new list of items of select item list - res_all_fields - new list of all items - elements - number of elements in select item list - all_fields - all fields list + Setup copy_fields to save fields at start of new group - DESCRIPTION - Setup copy_fields to save fields at start of new group - Only FIELD_ITEM:s and FUNC_ITEM:s needs to be saved between groups. - Change old item_field to use a new field with points at saved fieldvalue - This function is only called before use of send_fields - - RETURN - 0 - ok - !=0 - error + Only FIELD_ITEM:s and FUNC_ITEM:s needs to be saved between groups. + Change old item_field to use a new field with points at saved fieldvalue + This function is only called before use of send_fields. + + @param thd THD pointer + @param param temporary table parameters + @param ref_pointer_array array of pointers to top elements of filed list + @param res_selected_fields new list of items of select item list + @param res_all_fields new list of all items + @param elements number of elements in select item list + @param all_fields all fields list + + @todo + In most cases this result will be sent to the user. + This should be changed to use copy_int or copy_real depending + on how the value is to be used: In some cases this may be an + argument in a group function, like: IF(ISNULL(col),0,COUNT(*)) + + @retval + 0 ok + @retval + !=0 error */ bool @@ -14758,8 +14846,8 @@ err2: } -/* - Make a copy of all simple SELECT'ed items +/** + Make a copy of all simple SELECT'ed items. This is done at the start of a new group so that we can retrieve these later when the group changes. @@ -14781,14 +14869,13 @@ copy_fields(TMP_TABLE_PARAM *param) } -/* - Make an array of pointers to sum_functions to speed up sum_func calculation - - SYNOPSIS - alloc_func_list() +/** + Make an array of pointers to sum_functions to speed up + sum_func calculation. - RETURN + @retval 0 ok + @retval 1 Error */ @@ -14833,18 +14920,17 @@ bool JOIN::alloc_func_list() } -/* - Initialize 'sum_funcs' array with all Item_sum objects +/** + Initialize 'sum_funcs' array with all Item_sum objects. - SYNOPSIS - make_sum_func_list() - field_list All items - send_fields Items in select list - before_group_by Set to 1 if this is called before GROUP BY handling - recompute Set to TRUE if sum_funcs must be recomputed + @param field_list All items + @param send_fields Items in select list + @param before_group_by Set to 1 if this is called before GROUP BY handling + @param recompute Set to TRUE if sum_funcs must be recomputed - RETURN + @retval 0 ok + @retval 1 error */ @@ -14885,21 +14971,21 @@ bool JOIN::make_sum_func_list(List<Item> &field_list, List<Item> &send_fields, } -/* +/** Change all funcs and sum_funcs to fields in tmp table, and create new list of all items. - change_to_use_tmp_fields() - thd - THD pointer - ref_pointer_array - array of pointers to top elements of filed list - res_selected_fields - new list of items of select item list - res_all_fields - new list of all items - elements - number of elements in select item list - all_fields - all fields list - - RETURN - 0 - ok - !=0 - error + @param thd THD pointer + @param ref_pointer_array array of pointers to top elements of filed list + @param res_selected_fields new list of items of select item list + @param res_all_fields new list of all items + @param elements number of elements in select item list + @param all_fields all fields list + + @retval + 0 ok + @retval + !=0 error */ static bool @@ -14976,20 +15062,20 @@ change_to_use_tmp_fields(THD *thd, Item **ref_pointer_array, } -/* - Change all sum_func refs to fields to point at fields in tmp table - Change all funcs to be fields in tmp table - - change_refs_to_tmp_fields() - thd - THD pointer - ref_pointer_array - array of pointers to top elements of filed list - res_selected_fields - new list of items of select item list - res_all_fields - new list of all items - elements - number of elements in select item list - all_fields - all fields list - - RETURN +/** + Change all sum_func refs to fields to point at fields in tmp table. + Change all funcs to be fields in tmp table. + + @param thd THD pointer + @param ref_pointer_array array of pointers to top elements of filed list + @param res_selected_fields new list of items of select item list + @param res_all_fields new list of all items + @param elements number of elements in select item list + @param all_fields all fields list + + @retval 0 ok + @retval 1 error */ @@ -15027,16 +15113,15 @@ change_refs_to_tmp_fields(THD *thd, Item **ref_pointer_array, ******************************************************************************/ -/* - Call ::setup for all sum functions +/** + Call ::setup for all sum functions. - SYNOPSIS - setup_sum_funcs() - thd thread handler - func_ptr sum function list + @param thd thread handler + @param func_ptr sum function list - RETURN + @retval FALSE ok + @retval TRUE error */ @@ -15062,7 +15147,7 @@ init_tmptable_sum_functions(Item_sum **func_ptr) } - /* Update record 0 in tmp_table from record 1 */ +/** Update record 0 in tmp_table from record 1. */ static void update_tmptable_sum_func(Item_sum **func_ptr, @@ -15074,7 +15159,7 @@ update_tmptable_sum_func(Item_sum **func_ptr, } - /* Copy result of sum functions to record in tmp_table */ +/** Copy result of sum functions to record in tmp_table. */ static void copy_sum_funcs(Item_sum **func_ptr, Item_sum **end_ptr) @@ -15113,7 +15198,7 @@ update_sum_func(Item_sum **func_ptr) return 0; } - /* Copy result of functions to record in tmp_table */ +/** Copy result of functions to record in tmp_table. */ void copy_funcs(Item **func_ptr) @@ -15124,9 +15209,9 @@ copy_funcs(Item **func_ptr) } -/* +/** Create a condition for a const reference and add this to the - currenct select for the table + currenct select for the table. */ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab) @@ -15166,12 +15251,11 @@ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab) } -/* +/** Free joins of subselect of this select. - free_underlaid_joins() - thd - THD pointer - select - pointer to st_select_lex which subselects joins we will free + @param thd THD pointer + @param select pointer to st_select_lex which subselects joins we will free */ void free_underlaid_joins(THD *thd, SELECT_LEX *select) @@ -15186,41 +15270,43 @@ void free_underlaid_joins(THD *thd, SELECT_LEX *select) ROLLUP handling ****************************************************************************/ -/* - Replace occurences of group by fields in an expression by ref items +/** + Replace occurences of group by fields in an expression by ref items. - SYNOPSIS - change_group_ref() - thd reference to the context - expr expression to make replacement - group_list list of references to group by items - changed out: returns 1 if item contains a replaced field item + The function replaces occurrences of group by fields in expr + by ref objects for these fields unless they are under aggregate + functions. + The function also corrects value of the the maybe_null attribute + for the items of all subexpressions containing group by fields. - DESCRIPTION - The function replaces occurrences of group by fields in expr - by ref objects for these fields unless they are under aggregate - functions. - The function also corrects value of the the maybe_null attribute - for the items of all subexpressions containing group by fields. + @b EXAMPLES + @code + SELECT a+1 FROM t1 GROUP BY a WITH ROLLUP + SELECT SUM(a)+a FROM t1 GROUP BY a WITH ROLLUP + @endcode + + @b IMPLEMENTATION - IMPLEMENTATION The function recursively traverses the tree of the expr expression, looks for occurrences of the group by fields that are not under aggregate functions and replaces them for the corresponding ref items. - NOTES + @note This substitution is needed GROUP BY queries with ROLLUP if SELECT list contains expressions over group by attributes. - TODO: Some functions are not null-preserving. For those functions + @param thd reference to the context + @param expr expression to make replacement + @param group_list list of references to group by items + @param changed out: returns 1 if item contains a replaced field item + + @todo + - TODO: Some functions are not null-preserving. For those functions updating of the maybe_null attribute is an overkill. - EXAMPLES - SELECT a+1 FROM t1 GROUP BY a WITH ROLLUP - SELECT SUM(a)+a FROM t1 GROUP BY a WITH ROLLUP - - RETURN + @retval 0 if ok + @retval 1 on error */ @@ -15269,7 +15355,7 @@ static bool change_group_ref(THD *thd, Item_func *expr, ORDER *group_list, } -/* Allocate memory needed for other rollup functions */ +/** Allocate memory needed for other rollup functions. */ bool JOIN::rollup_init() { @@ -15372,22 +15458,20 @@ bool JOIN::rollup_init() } -/* - Fill up rollup structures with pointers to fields to use +/** + Fill up rollup structures with pointers to fields to use. - SYNOPSIS - rollup_make_fields() - fields_arg List of all fields (hidden and real ones) - sel_fields Pointer to selected fields - func Store here a pointer to all fields + Creates copies of item_sum items for each sum level. - IMPLEMENTATION: - Creates copies of item_sum items for each sum level + @param fields_arg List of all fields (hidden and real ones) + @param sel_fields Pointer to selected fields + @param func Store here a pointer to all fields - RETURN - 0 if ok - In this case func is pointing to next not used element. - 1 on error + @retval + 0 if ok; + In this case func is pointing to next not used element. + @retval + 1 on error */ bool JOIN::rollup_make_fields(List<Item> &fields_arg, List<Item> &sel_fields, @@ -15505,21 +15589,22 @@ bool JOIN::rollup_make_fields(List<Item> &fields_arg, List<Item> &sel_fields, return 0; } -/* - Send all rollup levels higher than the current one to the client +/** + Send all rollup levels higher than the current one to the client. - SYNOPSIS: - rollup_send_data() - idx Level we are on: - 0 = Total sum level - 1 = First group changed (a) - 2 = Second group changed (a,b) + @b SAMPLE + @code + SELECT a, b, c SUM(b) FROM t1 GROUP BY a,b WITH ROLLUP + @endcode - SAMPLE - SELECT a, b, c SUM(b) FROM t1 GROUP BY a,b WITH ROLLUP + @param idx Level we are on: + - 0 = Total sum level + - 1 = First group changed (a) + - 2 = Second group changed (a,b) - RETURN - 0 ok + @retval + 0 ok + @retval 1 If send_data_failed() */ @@ -15545,22 +15630,23 @@ int JOIN::rollup_send_data(uint idx) return 0; } -/* - Write all rollup levels higher than the current one to a temp table - - SYNOPSIS: - rollup_write_data() - idx Level we are on: - 0 = Total sum level - 1 = First group changed (a) - 2 = Second group changed (a,b) - table reference to temp table - - SAMPLE - SELECT a, b, SUM(c) FROM t1 GROUP BY a,b WITH ROLLUP - - RETURN - 0 ok +/** + Write all rollup levels higher than the current one to a temp table. + + @b SAMPLE + @code + SELECT a, b, SUM(c) FROM t1 GROUP BY a,b WITH ROLLUP + @endcode + + @param idx Level we are on: + - 0 = Total sum level + - 1 = First group changed (a) + - 2 = Second group changed (a,b) + @param table reference to temp table + + @retval + 0 ok + @retval 1 if write_data_failed() */ @@ -15597,12 +15683,9 @@ int JOIN::rollup_write_data(uint idx, TABLE *table_arg) return 0; } -/* +/** clear results if there are not rows found for group (end_send_group/end_write_group) - - SYNOPSYS - JOIN::clear() */ void JOIN::clear() @@ -15618,11 +15701,11 @@ void JOIN::clear() } } -/**************************************************************************** - EXPLAIN handling +/** + EXPLAIN handling. - Send a description about what how the select will be done to stdout -****************************************************************************/ + Send a description about what how the select will be done to stdout. +*/ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, bool distinct,const char *message) @@ -16142,14 +16225,12 @@ bool mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result) } -/* - Print joins from the FROM clause +/** + Print joins from the FROM clause. - SYNOPSIS - print_join() - thd thread handler - str string where table should be printed - tables list of tables in join + @param thd thread handler + @param str string where table should be printed + @param tables list of tables in join */ static void print_join(THD *thd, String *str, List<TABLE_LIST> *tables) @@ -16228,12 +16309,10 @@ Index_hint::print(THD *thd, String *str) } -/* - Print table as it should be in join list +/** + Print table as it should be in join list. - SYNOPSIS - TABLE_LIST::print(); - str string where table should bbe printed + @param str string where table should bbe printed */ void TABLE_LIST::print(THD *thd, String *str) @@ -16444,16 +16523,15 @@ void st_select_lex::print(THD *thd, String *str) } -/* - change select_result object of JOIN +/** + change select_result object of JOIN. - SYNOPSIS - JOIN::change_result() - res new select_result object + @param res new select_result object - RETURN - FALSE - OK - TRUE - error + @retval + FALSE OK + @retval + TRUE error */ bool JOIN::change_result(select_result *res) diff --git a/sql/sql_select.h b/sql/sql_select.h index cb59032315a..dbeace2ffa4 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -14,7 +14,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* classes to use when handling where clause */ +/** + @file + + @brief + classes to use when handling where clause +*/ #ifdef USE_PRAGMA_INTERFACE #pragma interface /* gcc class implementation */ @@ -25,12 +30,12 @@ typedef struct keyuse_t { TABLE *table; - Item *val; /* or value if no field */ + Item *val; /**< or value if no field */ table_map used_tables; uint key, keypart, optimize; key_part_map keypart_map; ha_rows ref_table_rows; - /* + /** If true, the comparison this value was created from will not be satisfied if val has NULL 'value'. */ @@ -53,13 +58,13 @@ class store_key; typedef struct st_table_ref { bool key_err; - uint key_parts; // num of ... - uint key_length; // length of key_buff - int key; // key no - uchar *key_buff; // value to look for with key - uchar *key_buff2; // key_buff+key_length + uint key_parts; ///< num of ... + uint key_length; ///< length of key_buff + int key; ///< key no + uchar *key_buff; ///< value to look for with key + uchar *key_buff2; ///< key_buff+key_length store_key **key_copy; // - Item **items; // val()'s for each keypart + Item **items; ///< val()'s for each keypart /* Array of pointers to trigger variables. Some/all of the pointers may be NULL. The ref access can be used iff @@ -72,18 +77,18 @@ typedef struct st_table_ref underlying conditions is switched off (see subquery code for more details) */ bool **cond_guards; - /* + /** (null_rejecting & (1<<i)) means the condition is '=' and no matching rows will be produced if items[i] IS NULL (see add_not_null_conds()) */ key_part_map null_rejecting; - table_map depend_map; // Table depends on these tables. + table_map depend_map; ///< Table depends on these tables. /* null byte position in the key_buf. Used for REF_OR_NULL optimization */ uchar *null_ref_key; } TABLE_REF; -/* +/** CACHE_FIELD and JOIN_CACHE is used on full join to cache records in outer table */ @@ -136,18 +141,18 @@ Next_select_func setup_end_select_func(JOIN *join); typedef struct st_join_table { st_join_table() {} /* Remove gcc warning */ TABLE *table; - KEYUSE *keyuse; /* pointer to first used key */ + KEYUSE *keyuse; /**< pointer to first used key */ SQL_SELECT *select; COND *select_cond; QUICK_SELECT_I *quick; - Item **on_expr_ref; /* pointer to the associated on expression */ - COND_EQUAL *cond_equal; /* multiple equalities for the on expression */ - st_join_table *first_inner; /* first inner table for including outerjoin */ - bool found; /* true after all matches or null complement */ - bool not_null_compl;/* true before null complement is added */ - st_join_table *last_inner; /* last table table for embedding outer join */ - st_join_table *first_upper; /* first inner table for embedding outer join */ - st_join_table *first_unmatched; /* used for optimization purposes only */ + Item **on_expr_ref; /**< pointer to the associated on expression */ + COND_EQUAL *cond_equal; /**< multiple equalities for the on expression */ + st_join_table *first_inner; /**< first inner table for including outerjoin */ + bool found; /**< true after all matches or null complement */ + bool not_null_compl;/**< true before null complement is added */ + st_join_table *last_inner; /**< last table table for embedding outer join */ + st_join_table *first_upper; /**< first inner table for embedding outer join */ + st_join_table *first_unmatched; /**< used for optimization purposes only */ /* Special content for EXPLAIN 'Extra' column or NULL if none */ const char *info; @@ -168,10 +173,10 @@ typedef struct st_join_table { Read_record_func save_read_first_record;/* to save read_first_record */ int (*save_read_record) (READ_RECORD *);/* to save read_record.read_record */ double worst_seeks; - key_map const_keys; /* Keys with constant part */ - key_map checked_keys; /* Keys checked in find_best */ + key_map const_keys; /**< Keys with constant part */ + key_map checked_keys; /**< Keys checked in find_best */ key_map needed_reg; - key_map keys; /* all keys with can be used */ + key_map keys; /**< all keys with can be used */ /* Either #rows in the table or 1 for const table. */ ha_rows records; @@ -189,7 +194,7 @@ typedef struct st_join_table { table_map dependent,key_dependent; uint use_quick,index; - uint status; // Save status for cache + uint status; ///< Save status for cache uint used_fields,used_fieldlength,used_blobs; enum join_type type; bool cached_eq_ref_table,eq_ref_table,not_used_in_distinct; @@ -203,7 +208,7 @@ typedef struct st_join_table { TABLE_REF ref; JOIN_CACHE cache; JOIN *join; - /* Bitmap of nested joins this table is part of */ + /** Bitmap of nested joins this table is part of */ nested_join_map embedding_map; void cleanup(); @@ -220,7 +225,7 @@ enum_nested_loop_state sub_select_cache(JOIN *join, JOIN_TAB *join_tab, bool enum_nested_loop_state sub_select(JOIN *join,JOIN_TAB *join_tab, bool end_of_records); -/* +/** Information about a position of table within a join order. Used in join optimization. */ @@ -264,25 +269,25 @@ typedef struct st_rollup class JOIN :public Sql_alloc { - JOIN(const JOIN &rhs); /* not implemented */ - JOIN& operator=(const JOIN &rhs); /* not implemented */ + JOIN(const JOIN &rhs); /**< not implemented */ + JOIN& operator=(const JOIN &rhs); /**< not implemented */ public: JOIN_TAB *join_tab,**best_ref; - JOIN_TAB **map2table; // mapping between table indexes and JOIN_TABs - JOIN_TAB *join_tab_save; // saved join_tab for subquery reexecution + JOIN_TAB **map2table; ///< mapping between table indexes and JOIN_TABs + JOIN_TAB *join_tab_save; ///< saved join_tab for subquery reexecution TABLE **table,**all_tables,*sort_by_table; uint tables,const_tables; uint send_group_parts; bool sort_and_group,first_record,full_join,group, no_field_update; bool do_send_rows; - /* + /** TRUE when we want to resume nested loop iterations when fetching data from a cursor */ bool resume_nested_loop; table_map const_table_map,found_const_table_map,outer_join; ha_rows send_records,found_records,examined_rows,row_limit, select_limit; - /* + /** Used to fetch no more than given amount of rows per one fetch operation of server side cursor. The value is checked in end_send and end_send_group in fashion, similar @@ -294,7 +299,7 @@ public: ha_rows fetch_limit; POSITION positions[MAX_TABLES+1],best_positions[MAX_TABLES+1]; - /* + /* * Bitmap of nested joins embedding the position at the end of the current partial join (valid only during join optimizer run). */ @@ -304,25 +309,25 @@ public: List<Item> *fields; List<Cached_item> group_fields, group_fields_cache; TABLE *tmp_table; - // used to store 2 possible tmp table of SELECT + /// used to store 2 possible tmp table of SELECT TABLE *exec_tmp_table1, *exec_tmp_table2; THD *thd; Item_sum **sum_funcs, ***sum_funcs_end; - /* second copy of sumfuncs (for queries with 2 temporary tables */ + /** second copy of sumfuncs (for queries with 2 temporary tables */ Item_sum **sum_funcs2, ***sum_funcs_end2; Procedure *procedure; Item *having; - Item *tmp_having; // To store having when processed temporary table - Item *having_history; // Store having for explain + Item *tmp_having; ///< To store having when processed temporary table + Item *having_history; ///< Store having for explain ulonglong select_options; select_result *result; TMP_TABLE_PARAM tmp_table_param; MYSQL_LOCK *lock; - // unit structure (with global parameters) for this select + /// unit structure (with global parameters) for this select SELECT_LEX_UNIT *unit; - // select that processed + /// select that processed SELECT_LEX *select_lex; - /* + /** TRUE <=> optimizer must not mark any table as a constant table. This is needed for subqueries in form "a IN (SELECT .. UNION SELECT ..): when we optimize the select that reads the results of the union from a @@ -331,11 +336,11 @@ public: */ bool no_const_tables; - JOIN *tmp_join; // copy of this JOIN to be used with temporary tables - ROLLUP rollup; // Used with rollup + JOIN *tmp_join; ///< copy of this JOIN to be used with temporary tables + ROLLUP rollup; ///< Used with rollup - bool select_distinct; // Set if SELECT DISTINCT - /* + bool select_distinct; ///< Set if SELECT DISTINCT + /** If we have the GROUP BY statement in the query, but the group_list was emptied by optimizer, this flag is TRUE. @@ -350,42 +355,42 @@ public: It's also set if ORDER/GROUP BY is empty. */ bool simple_order, simple_group; - /* + /** Is set only in case if we have a GROUP BY clause and no ORDER BY after constant elimination of 'order'. */ bool no_order; - /* Is set if we have a GROUP BY and we have ORDER BY on a constant. */ + /** Is set if we have a GROUP BY and we have ORDER BY on a constant. */ bool skip_sort_order; bool need_tmp, hidden_group_fields; DYNAMIC_ARRAY keyuse; Item::cond_result cond_value, having_value; - List<Item> all_fields; // to store all fields that used in query - //Above list changed to use temporary table + List<Item> all_fields; ///< to store all fields that used in query + ///Above list changed to use temporary table List<Item> tmp_all_fields1, tmp_all_fields2, tmp_all_fields3; - //Part, shared with list above, emulate following list + ///Part, shared with list above, emulate following list List<Item> tmp_fields_list1, tmp_fields_list2, tmp_fields_list3; - List<Item> &fields_list; // hold field list passed to mysql_select + List<Item> &fields_list; ///< hold field list passed to mysql_select List<Item> procedure_fields_list; int error; ORDER *order, *group_list, *proc_param; //hold parameters of mysql_select COND *conds; // ---"--- Item *conds_history; // store WHERE for explain - TABLE_LIST *tables_list; //hold 'tables' parameter of mysql_select - List<TABLE_LIST> *join_list; // list of joined tables in reverse order + TABLE_LIST *tables_list; ///<hold 'tables' parameter of mysql_select + List<TABLE_LIST> *join_list; ///< list of joined tables in reverse order COND_EQUAL *cond_equal; - SQL_SELECT *select; //created in optimisation phase - JOIN_TAB *return_tab; //used only for outer joins - Item **ref_pointer_array; //used pointer reference for this select + SQL_SELECT *select; ///<created in optimisation phase + JOIN_TAB *return_tab; ///<used only for outer joins + Item **ref_pointer_array; ///<used pointer reference for this select // Copy of above to be used with different lists Item **items0, **items1, **items2, **items3, **current_ref_pointer_array; - uint ref_pointer_array_size; // size of above in bytes - const char *zero_result_cause; // not 0 if exec must return zero result + uint ref_pointer_array_size; ///< size of above in bytes + const char *zero_result_cause; ///< not 0 if exec must return zero result - bool union_part; // this subselect is part of union - bool optimized; // flag to avoid double optimization in EXPLAIN + bool union_part; ///< this subselect is part of union + bool optimized; ///< flag to avoid double optimization in EXPLAIN /* storage for caching buffers allocated during query execution. @@ -494,14 +499,14 @@ public: int rollup_send_data(uint idx); int rollup_write_data(uint idx, TABLE *table); void remove_subq_pushed_predicates(Item **where); - /* + /** Release memory and, if possible, the open tables held by this execution plan (and nested plans). It's used to release some tables before the end of execution in order to increase concurrency and reduce memory consumption. */ void join_free(); - /* Cleanup this JOIN, possibly for reuse */ + /** Cleanup this JOIN, possibly for reuse */ void cleanup(bool full); void clear(); bool save_join_tab(); @@ -556,7 +561,7 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds); /* from sql_delete.cc, used by opt_range.cc */ extern "C" int refpos_order_cmp(void* arg, const void *a,const void *b); -/* class to copying an field/item to a key struct */ +/** class to copying an field/item to a key struct */ class store_key :public Sql_alloc { @@ -582,7 +587,7 @@ public: to_field=field_arg->new_key_field(thd->mem_root, field_arg->table, ptr, null, 1); } - virtual ~store_key() {} /* Not actually needed */ + virtual ~store_key() {} /** Not actually needed */ virtual const char *name() const=0; /** diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 36f9cc780bd..177e84ab0a7 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -5375,17 +5375,24 @@ ST_SCHEMA_TABLE *get_schema_table(enum enum_schema_tables schema_table_idx) } -/* - Create information_schema table using schema_table data +/** + Create information_schema table using schema_table data. - SYNOPSIS - create_schema_table() + @note + For MYSQL_TYPE_DECIMAL fields only, the field_length member has encoded + into it two numbers, based on modulus of base-10 numbers. In the ones + position is the number of decimals. Tens position is unused. In the + hundreds and thousands position is a two-digit decimal number representing + length. Encode this value with (decimals*100)+length , where + 0<decimals<10 and 0<=length<100 . + + @param thd thread handler + @param schema_table pointer to 'shema_tables' element - RETURN - # Pointer to created table - 0 Can't create table + @retval \# Pointer to created table + @retval NULL Can't create table */ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list) @@ -6528,6 +6535,9 @@ ST_SCHEMA_TABLE schema_tables[]= fill_plugins, make_old_format, 0, -1, -1, 0, 0}, {"PROCESSLIST", processlist_fields_info, create_schema_table, fill_schema_processlist, make_old_format, 0, -1, -1, 0, 0}, + {"PROFILING", query_profile_statistics_info, create_schema_table, + fill_query_profile_statistics_info, make_profile_table_for_show, + NULL, -1, -1, false, 0}, {"REFERENTIAL_CONSTRAINTS", referential_constraints_fields_info, create_schema_table, get_all_tables, 0, get_referential_constraints_record, 1, 9, 0, OPEN_TABLE_ONLY}, diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 6bd31544e11..5bd7d446cbd 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -3477,7 +3477,7 @@ bool mysql_create_table_no_lock(THD *thd, } } - thd->proc_info="creating table"; + thd_proc_info(thd, "creating table"); create_info->table_existed= 0; // Mark that table is created if (thd->variables.sql_mode & MODE_NO_DIR_IN_CREATE) @@ -3518,7 +3518,7 @@ unlock_and_end: VOID(pthread_mutex_unlock(&LOCK_open)); err: - thd->proc_info="After create"; + thd_proc_info(thd, "After create"); delete file; DBUG_RETURN(error); @@ -4965,7 +4965,7 @@ mysql_discard_or_import_tablespace(THD *thd, ALTER TABLE */ - thd->proc_info="discard_or_import_tablespace"; + thd_proc_info(thd, "discard_or_import_tablespace"); discard= test(tablespace_op == DISCARD_TABLESPACE); @@ -4982,7 +4982,7 @@ mysql_discard_or_import_tablespace(THD *thd, error=table->file->discard_or_import_tablespace(discard); - thd->proc_info="end"; + thd_proc_info(thd, "end"); if (error) goto err; @@ -5906,7 +5906,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, to simplify further comparisions: we want to see if it's a RENAME later just by comparing the pointers, avoiding the need for strcmp. */ - thd->proc_info="init"; + thd_proc_info(thd, "init"); table_name=table_list->table_name; alias= (lower_case_table_names == 2) ? table_list->alias : table_name; db=table_list->db; @@ -6109,7 +6109,7 @@ view_err: goto err; } - thd->proc_info="setup"; + thd_proc_info(thd, "setup"); if (!(alter_info->flags & ~(ALTER_RENAME | ALTER_KEYS_ONOFF)) && !table->s->tmp_table) // no need to touch frm { @@ -6165,7 +6165,7 @@ view_err: if (!error && (new_name != table_name || new_db != db)) { - thd->proc_info="rename"; + thd_proc_info(thd, "rename"); /* Then do a 'simple' rename of the table. First we need to close all instances of 'source' table. @@ -6502,7 +6502,7 @@ view_err: /* Copy the data if necessary. */ thd->count_cuted_fields= CHECK_FIELD_WARN; // calc cuted fields thd->cuted_fields=0L; - thd->proc_info="copy to tmp table"; + thd_proc_info(thd, "copy to tmp table"); copied=deleted=0; /* We do not copy data for MERGE tables. Only the children have data. @@ -6676,7 +6676,7 @@ view_err: call to remove name-locks from table cache and list of open table. */ - thd->proc_info="rename result table"; + thd_proc_info(thd, "rename result table"); my_snprintf(old_name, sizeof(old_name), "%s2-%lx-%lx", tmp_file_prefix, current_pid, thd->thread_id); if (lower_case_table_names) @@ -6791,7 +6791,7 @@ view_err: } VOID(pthread_mutex_unlock(&LOCK_open)); - thd->proc_info="end"; + thd_proc_info(thd, "end"); DBUG_EXECUTE_IF("sleep_alter_before_main_binlog", my_sleep(6000000);); diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index b421f57b7ab..4bf23dc52f9 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -168,7 +168,7 @@ static const LEX_STRING triggers_file_type= const char * const TRG_EXT= ".TRG"; -/* +/** Table of .TRG file field descriptors. We have here only one field now because in nearest future .TRG files will be merged into .FRM files (so we don't need something @@ -216,7 +216,7 @@ File_option sql_modes_parameters= FILE_OPTIONS_ULLLIST }; -/* +/** This must be kept up to date whenever a new option is added to the list above, as it specifies the number of required parameters of the trigger in .trg file. @@ -292,23 +292,27 @@ private: }; -/* +/** Create or drop trigger for table. - SYNOPSIS - mysql_create_or_drop_trigger() - thd - current thread context (including trigger definition in LEX) - tables - table list containing one table for which trigger is created. - create - whenever we create (TRUE) or drop (FALSE) trigger + @param thd current thread context (including trigger definition in LEX) + @param tables table list containing one table for which trigger is created. + @param create whenever we create (TRUE) or drop (FALSE) trigger - NOTE + @note This function is mainly responsible for opening and locking of table and invalidation of all its instances in table cache after trigger creation. Real work on trigger creation/dropping is done inside Table_triggers_list methods. - RETURN VALUE + @todo + TODO: We should check if user has TRIGGER privilege for table here. + Now we just require SUPER privilege for creating/dropping because + we don't have proper privilege checking for triggers in place yet. + + @retval FALSE Success + @retval TRUE error */ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) @@ -518,29 +522,28 @@ end: } -/* +/** Create trigger for table. - SYNOPSIS - create_trigger() - thd - current thread context (including trigger definition in - LEX) - tables - table list containing one open table for which the - trigger is created. - stmt_query - [OUT] after successful return, this string contains - well-formed statement for creating this trigger. + @param thd current thread context (including trigger definition in + LEX) + @param tables table list containing one open table for which the + trigger is created. + @param[out] stmt_query after successful return, this string contains + well-formed statement for creation this trigger. - NOTE + @note - Assumes that trigger name is fully qualified. - NULL-string means the following LEX_STRING instance: - { str = 0; length = 0 }. + { str = 0; length = 0 }. - In other words, definer_user and definer_host should contain - simultaneously NULL-strings (non-SUID/old trigger) or valid strings - (SUID/new trigger). + simultaneously NULL-strings (non-SUID/old trigger) or valid strings + (SUID/new trigger). - RETURN VALUE - False - success - True - error + @retval + False success + @retval + True error */ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables, String *stmt_query) @@ -806,19 +809,18 @@ err_with_cleanup: } -/* - Deletes the .TRG file for a table - - SYNOPSIS - rm_trigger_file() - path - char buffer of size FN_REFLEN to be used - for constructing path to .TRG file. - db - table's database name - table_name - table's name - - RETURN VALUE - False - success - True - error +/** + Deletes the .TRG file for a table. + + @param path char buffer of size FN_REFLEN to be used + for constructing path to .TRG file. + @param db table's database name + @param table_name table's name + + @retval + False success + @retval + True error */ static bool rm_trigger_file(char *path, const char *db, @@ -829,19 +831,18 @@ static bool rm_trigger_file(char *path, const char *db, } -/* - Deletes the .TRN file for a trigger - - SYNOPSIS - rm_trigname_file() - path - char buffer of size FN_REFLEN to be used - for constructing path to .TRN file. - db - trigger's database name - table_name - trigger's name - - RETURN VALUE - False - success - True - error +/** + Deletes the .TRN file for a trigger. + + @param path char buffer of size FN_REFLEN to be used + for constructing path to .TRN file. + @param db trigger's database name + @param table_name trigger's name + + @retval + False success + @retval + True error */ static bool rm_trigname_file(char *path, const char *db, @@ -852,17 +853,16 @@ static bool rm_trigname_file(char *path, const char *db, } -/* +/** Helper function that saves .TRG file for Table_triggers_list object. - SYNOPSIS - save_trigger_file() - triggers Table_triggers_list object for which file should be saved - db Name of database for subject table - table_name Name of subject table + @param triggers Table_triggers_list object for which file should be saved + @param db Name of database for subject table + @param table_name Name of subject table - RETURN VALUE + @retval FALSE Success + @retval TRUE Error */ @@ -881,21 +881,26 @@ static bool save_trigger_file(Table_triggers_list *triggers, const char *db, } -/* +/** Drop trigger for table. - SYNOPSIS - drop_trigger() - thd - current thread context - (including trigger definition in LEX) - tables - table list containing one open table for which trigger - is dropped. - stmt_query - [OUT] after successful return, this string contains - well-formed statement for deleting this trigger. - - RETURN VALUE - False - success - True - error + @param thd current thread context + (including trigger definition in LEX) + @param tables table list containing one open table for which trigger + is dropped. + @param[out] stmt_query after successful return, this string contains + well-formed statement for creation this trigger. + + @todo + Probably instead of removing .TRG file we should move + to archive directory but this should be done as part of + parse_file.cc functionality (because we will need it + elsewhere). + + @retval + False success + @retval + True error */ bool Table_triggers_list::drop_trigger(THD *thd, TABLE_LIST *tables, String *stmt_query) @@ -978,18 +983,17 @@ Table_triggers_list::~Table_triggers_list() } -/* +/** Prepare array of Field objects referencing to TABLE::record[1] instead of record[0] (they will represent OLD.* row values in ON UPDATE trigger and in ON DELETE trigger which will be called during REPLACE execution). - SYNOPSIS - prepare_record1_accessors() - table - pointer to TABLE object for which we are creating fields. + @param table pointer to TABLE object for which we are creating fields. - RETURN VALUE - False - success - True - error + @retval + False success + @retval + True error */ bool Table_triggers_list::prepare_record1_accessors(TABLE *table) { @@ -1018,12 +1022,10 @@ bool Table_triggers_list::prepare_record1_accessors(TABLE *table) } -/* +/** Adjust Table_triggers_list with new TABLE pointer. - SYNOPSIS - set_table() - new_table - new pointer to TABLE instance + @param new_table new pointer to TABLE instance */ void Table_triggers_list::set_table(TABLE *new_table) @@ -1037,20 +1039,26 @@ void Table_triggers_list::set_table(TABLE *new_table) } -/* +/** Check whenever .TRG file for table exist and load all triggers it contains. - SYNOPSIS - check_n_load() - thd - current thread context - db - table's database name - table_name - table's name - table - pointer to table object - names_only - stop after loading trigger names - - RETURN VALUE - False - success - True - error + @param thd current thread context + @param db table's database name + @param table_name table's name + @param table pointer to table object + @param names_only stop after loading trigger names + + @todo + A lot of things to do here e.g. how about other funcs and being + more paranoical ? + + @todo + This could be avoided if there is no triggers for UPDATE and DELETE. + + @retval + False success + @retval + True error */ bool Table_triggers_list::check_n_load(THD *thd, const char *db, @@ -1433,24 +1441,23 @@ err_with_lex_cleanup: } -/* - Obtains and returns trigger metadata - - SYNOPSIS - get_trigger_info() - thd - current thread context - event - trigger event type - time_type - trigger action time - name - returns name of trigger - stmt - returns statement of trigger - sql_mode - returns sql_mode of trigger - definer_user - returns definer/creator of trigger. The caller is - responsible to allocate enough space for storing definer - information. - - RETURN VALUE - False - success - True - error +/** + Obtains and returns trigger metadata. + + @param thd current thread context + @param event trigger event type + @param time_type trigger action time + @param trigger_name returns name of trigger + @param trigger_stmt returns statement of trigger + @param sql_mode returns sql_mode of trigger + @param definer returns definer/creator of trigger. The caller is + responsible to allocate enough space for storing + definer information. + + @retval + False success + @retval + True error */ bool Table_triggers_list::get_trigger_info(THD *thd, trg_event_type event, @@ -1616,21 +1623,20 @@ bool add_table_for_trigger(THD *thd, } -/* +/** Drop all triggers for table. - SYNOPSIS - drop_all_triggers() - thd - current thread context - db - schema for table - name - name for table + @param thd current thread context + @param db schema for table + @param name name for table - NOTE + @note The calling thread should hold the LOCK_open mutex; - RETURN VALUE - False - success - True - error + @retval + False success + @retval + True error */ bool Table_triggers_list::drop_all_triggers(THD *thd, char *db, char *name) @@ -1680,19 +1686,18 @@ end: } -/* +/** Update .TRG file after renaming triggers' subject table (change name of table in triggers' definitions). - SYNOPSIS - change_table_name_in_triggers() - thd Thread context - db_name Database of subject table - old_table_name Old subject table's name - new_table_name New subject table's name + @param thd Thread context + @param db_name Database of subject table + @param old_table_name Old subject table's name + @param new_table_name New subject table's name - RETURN VALUE + @retval FALSE Success + @retval TRUE Failure */ @@ -1762,21 +1767,20 @@ Table_triggers_list::change_table_name_in_triggers(THD *thd, } -/* - Iterate though Table_triggers_list::names_list list and update .TRN files - after renaming triggers' subject table. +/** + Iterate though Table_triggers_list::names_list list and update + .TRN files after renaming triggers' subject table. - SYNOPSIS - change_table_name_in_trignames() - db_name Database of subject table - new_table_name New subject table's name - stopper Pointer to Table_triggers_list::names_list at - which we should stop updating. + @param db_name Database of subject table + @param new_table_name New subject table's name + @param stopper Pointer to Table_triggers_list::names_list at + which we should stop updating. - RETURN VALUE + @retval 0 Success + @retval non-0 Failure, pointer to Table_triggers_list::names_list element - for which update failed. + for which update failed. */ LEX_STRING* @@ -1810,7 +1814,7 @@ Table_triggers_list::change_table_name_in_trignames(const char *db_name, /** - @brief Update .TRG and .TRN files after renaming triggers' subject table. + Update .TRG and .TRN files after renaming triggers' subject table. @param[in,out] thd Thread context @param[in] db Old database of subject table @@ -1972,19 +1976,17 @@ bool Table_triggers_list::process_triggers(THD *thd, } -/* - Mark fields of subject table which we read/set in its triggers as such. - - SYNOPSIS - mark_fields_used() - thd Current thread context - event Type of event triggers for which we are going to ins - - DESCRIPTION - This method marks fields of subject table which are read/set in its - triggers as such (by properly updating TABLE::read_set/write_set) - and thus informs handler that values for these fields should be - retrieved/stored during execution of statement. +/** + Mark fields of subject table which we read/set in its triggers + as such. + + This method marks fields of subject table which are read/set in its + triggers as such (by properly updating TABLE::read_set/write_set) + and thus informs handler that values for these fields should be + retrieved/stored during execution of statement. + + @param thd Current thread context + @param event Type of event triggers for which we are going to inspect */ void Table_triggers_list::mark_fields_used(trg_event_type event) @@ -2010,23 +2012,23 @@ void Table_triggers_list::mark_fields_used(trg_event_type event) } -/* - Trigger BUG#14090 compatibility hook +/** + Trigger BUG#14090 compatibility hook. - SYNOPSIS - Handle_old_incorrect_sql_modes_hook::process_unknown_string() - unknown_key [in/out] reference on the line with unknown - parameter and the parsing point - base [in] base address for parameter writing (structure - like TABLE) - mem_root [in] MEM_ROOT for parameters allocation - end [in] the end of the configuration + @param[in,out] unknown_key reference on the line with unknown + parameter and the parsing point + @param[in] base base address for parameter writing + (structure like TABLE) + @param[in] mem_root MEM_ROOT for parameters allocation + @param[in] end the end of the configuration - NOTE: this hook process back compatibility for incorrectly written - sql_modes parameter (see BUG#14090). + @note + NOTE: this hook process back compatibility for incorrectly written + sql_modes parameter (see BUG#14090). - RETURN + @retval FALSE OK + @retval TRUE Error */ @@ -2068,13 +2070,12 @@ Handle_old_incorrect_sql_modes_hook::process_unknown_string(char *&unknown_key, DBUG_RETURN(FALSE); } -/* +#define INVALID_TRIGGER_TABLE_LENGTH 15 + +/** Trigger BUG#15921 compatibility hook. For details see Handle_old_incorrect_sql_modes_hook::process_unknown_string(). */ - -#define INVALID_TRIGGER_TABLE_LENGTH 15 - bool Handle_old_incorrect_trigger_table_hook:: process_unknown_string(char *&unknown_key, uchar* base, MEM_ROOT *mem_root, @@ -2113,9 +2114,9 @@ process_unknown_string(char *&unknown_key, uchar* base, MEM_ROOT *mem_root, /** Contruct path to TRN-file. - @param[in] thd Thread context. - @param[in] trg_name Trigger name. - @param[out] trn_path Variable to store constructed path + @param thd[in] Thread context. + @param trg_name[in] Trigger name. + @param trn_path[out] Variable to store constructed path */ void build_trn_path(THD *thd, const sp_name *trg_name, LEX_STRING *trn_path) @@ -2148,10 +2149,10 @@ bool check_trn_exists(const LEX_STRING *trn_path) /** Retrieve table name for given trigger. - @param[in] thd Thread context. - @param[in] trg_name Trigger name. - @param[in] trn_path Path to the corresponding TRN-file. - @param[out] tbl_name Variable to store retrieved table name. + @param thd[in] Thread context. + @param trg_name[in] Trigger name. + @param trn_path[in] Path to the corresponding TRN-file. + @param tbl_name[out] Variable to store retrieved table name. @return Error status. @retval FALSE on success. diff --git a/sql/sql_trigger.h b/sql/sql_trigger.h index 8f6b08c927f..1b0edf6bea8 100644 --- a/sql/sql_trigger.h +++ b/sql/sql_trigger.h @@ -14,7 +14,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* +/** This class holds all information about triggers of table. QQ: Will it be merged into TABLE in the future ? @@ -22,20 +22,20 @@ class Table_triggers_list: public Sql_alloc { - /* Triggers as SPs grouped by event, action_time */ + /** Triggers as SPs grouped by event, action_time */ sp_head *bodies[TRG_EVENT_MAX][TRG_ACTION_MAX]; - /* + /** Heads of the lists linking items for all fields used in triggers grouped by event and action_time. */ Item_trigger_field *trigger_fields[TRG_EVENT_MAX][TRG_ACTION_MAX]; - /* + /** Copy of TABLE::Field array with field pointers set to TABLE::record[1] buffer instead of TABLE::record[0] (used for OLD values in on UPDATE trigger and DELETE trigger when it is called for REPLACE). */ Field **record1_field; - /* + /** During execution of trigger new_field and old_field should point to the array of fields representing new or old version of row correspondingly (so it can point to TABLE::field or to Tale_triggers_list::record1_field) @@ -45,30 +45,30 @@ class Table_triggers_list: public Sql_alloc /* TABLE instance for which this triggers list object was created */ TABLE *trigger_table; - /* + /** Names of triggers. Should correspond to order of triggers on definitions_list, used in CREATE/DROP TRIGGER for looking up trigger by name. */ List<LEX_STRING> names_list; - /* + /** List of "ON table_name" parts in trigger definitions, used for updating trigger definitions during RENAME TABLE. */ List<LEX_STRING> on_table_names_list; - /* + /** Grant information for each trigger (pair: subject table, trigger definer). */ GRANT_INFO subject_table_grants[TRG_EVENT_MAX][TRG_ACTION_MAX]; public: - /* + /** Field responsible for storing triggers definitions in file. It have to be public because we are using it directly from parser. */ List<LEX_STRING> definitions_list; - /* + /** List of sql modes for triggers */ List<ulonglong> definition_modes_list; diff --git a/sql/sql_update.cc b/sql/sql_update.cc index e2dfd89aa32..78dea6b7cdb 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -84,7 +84,7 @@ static bool check_fields(THD *thd, List<Item> &items) /** - @brief Re-read record if more columns are needed for error message. + Re-read record if more columns are needed for error message. If we got a duplicate key error, we want to write an error message containing the value of the duplicate key. If we do not have @@ -232,7 +232,7 @@ int mysql_update(THD *thd, mysql_handle_derived(thd->lex, &mysql_derived_filling))) DBUG_RETURN(1); - thd->proc_info="init"; + thd_proc_info(thd, "init"); table= table_list->table; /* Calculate "table->covering_keys" based on the WHERE */ @@ -461,7 +461,7 @@ int mysql_update(THD *thd, else init_read_record_idx(&info, thd, table, 1, used_index); - thd->proc_info="Searching rows for update"; + thd_proc_info(thd, "Searching rows for update"); ha_rows tmp_limit= limit; while (!(error=info.read_record(&info)) && !thd->killed) @@ -528,7 +528,7 @@ int mysql_update(THD *thd, updated= found= 0; thd->count_cuted_fields= CHECK_FIELD_WARN; /* calc cuted fields */ thd->cuted_fields=0L; - thd->proc_info="Updating"; + thd_proc_info(thd, "Updating"); transactional_table= table->file->has_transactions(); thd->abort_on_warning= test(!ignore && @@ -761,7 +761,7 @@ int mysql_update(THD *thd, end_read_record(&info); delete select; - thd->proc_info= "end"; + thd_proc_info(thd, "end"); VOID(table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY)); /* @@ -1224,7 +1224,7 @@ int multi_update::prepare(List<Item> ¬_used_values, thd->count_cuted_fields= CHECK_FIELD_WARN; thd->cuted_fields=0L; - thd->proc_info="updating main table"; + thd_proc_info(thd, "updating main table"); tables_to_update= get_table_map(fields); @@ -1942,7 +1942,7 @@ bool multi_update::send_eof() ulonglong id; THD::killed_state killed_status= THD::NOT_KILLED; DBUG_ENTER("multi_update::send_eof"); - thd->proc_info="updating reference tables"; + thd_proc_info(thd, "updating reference tables"); /* Does updates for the last n - 1 tables, returns 0 if ok; @@ -1954,7 +1954,7 @@ bool multi_update::send_eof() later carried out killing should not affect binlogging. */ killed_status= (local_error == 0)? THD::NOT_KILLED : thd->killed; - thd->proc_info= "end"; + thd_proc_info(thd, "end"); /* We must invalidate the query cache before binlog writing and ha_autocommit_... */ diff --git a/sql/sql_view.cc b/sql/sql_view.cc index f7223cafb5e..79973b85181 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -206,7 +206,7 @@ fill_defined_view_parts (THD *thd, TABLE_LIST *view) /** - @brief Creating/altering VIEW procedure + Creating/altering VIEW procedure @param thd thread handler @param views views to create @@ -604,7 +604,7 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, DBUG_RETURN(0); err: - thd->proc_info= "end"; + thd_proc_info(thd, "end"); lex->link_first_table_back(view, link_to_local); unit->cleanup(); DBUG_RETURN(res || thd->is_error()); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 6d2e4ea9a59..9cccc7c724e 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -568,6 +568,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token BIT_SYM /* MYSQL-FUNC */ %token BIT_XOR /* MYSQL-FUNC */ %token BLOB_SYM /* SQL-2003-R */ +%token BLOCK_SYM %token BOOLEAN_SYM /* SQL-2003-R */ %token BOOL_SYM %token BOTH /* SQL-2003-R */ @@ -608,10 +609,12 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token CONSISTENT_SYM %token CONSTRAINT /* SQL-2003-R */ %token CONTAINS_SYM /* SQL-2003-N */ +%token CONTEXT_SYM %token CONTINUE_SYM /* SQL-2003-R */ %token CONTRIBUTORS_SYM %token CONVERT_SYM /* SQL-2003-N */ %token COUNT_SYM /* SQL-2003-N */ +%token CPU_SYM %token CREATE /* SQL-2003-R */ %token CROSS /* SQL-2003-R */ %token CUBE_SYM /* SQL-2003-R */ @@ -686,6 +689,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token EXTRACT_SYM /* SQL-2003-N */ %token FALSE_SYM /* SQL-2003-R */ %token FAST_SYM +%token FAULTS_SYM %token FETCH_SYM /* SQL-2003-R */ %token FILE_SYM %token FIRST_SYM /* SQL-2003-N */ @@ -746,6 +750,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token INT_SYM /* SQL-2003-R */ %token INVOKER_SYM %token IN_SYM /* SQL-2003-R */ +%token IO_SYM +%token IPC_SYM %token IS /* SQL-2003-R */ %token ISOLATION /* SQL-2003-R */ %token ISSUER_SYM @@ -898,6 +904,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token PROCEDURE /* SQL-2003-R */ %token PROCESS %token PROCESSLIST_SYM +%token PROFILE_SYM +%token PROFILES_SYM %token PURGE %token QUARTER_SYM %token QUERY_SYM @@ -973,6 +981,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token SOCKET_SYM %token SONAME_SYM %token SOUNDS_SYM +%token SOURCE_SYM %token SPATIAL_SYM %token SPECIFIC_SYM /* SQL-2003-R */ %token SQLEXCEPTION_SYM /* SQL-2003-R */ @@ -1005,6 +1014,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token SUM_SYM /* SQL-2003-N */ %token SUPER_SYM %token SUSPEND_SYM +%token SWAPS_SYM +%token SWITCHES_SYM %token SYSDATE %token TABLES %token TABLESPACE @@ -8869,6 +8880,64 @@ opt_table_sym: | TABLE_SYM ; +opt_profile_defs: + /* empty */ + | profile_defs; + +profile_defs: + profile_def + | profile_defs ',' profile_def; + +profile_def: + CPU_SYM + { + Lex->profile_options|= PROFILE_CPU; + } + | MEMORY_SYM + { + Lex->profile_options|= PROFILE_MEMORY; + } + | BLOCK_SYM IO_SYM + { + Lex->profile_options|= PROFILE_BLOCK_IO; + } + | CONTEXT_SYM SWITCHES_SYM + { + Lex->profile_options|= PROFILE_CONTEXT; + } + | PAGE_SYM FAULTS_SYM + { + Lex->profile_options|= PROFILE_PAGE_FAULTS; + } + | IPC_SYM + { + Lex->profile_options|= PROFILE_IPC; + } + | SWAPS_SYM + { + Lex->profile_options|= PROFILE_SWAPS; + } + | SOURCE_SYM + { + Lex->profile_options|= PROFILE_SOURCE; + } + | ALL + { + Lex->profile_options|= PROFILE_ALL; + } + ; + +opt_profile_args: + /* empty */ + { + Lex->profile_query_id= 0; + } + | FOR_SYM QUERY_SYM NUM + { + Lex->profile_query_id= atoi($3.str); + } + ; + /* Show things */ show: @@ -9039,6 +9108,15 @@ show_param: { Lex->sql_command = SQLCOM_SHOW_WARNS;} | ERRORS opt_limit_clause_init { Lex->sql_command = SQLCOM_SHOW_ERRORS;} + | PROFILES_SYM + { Lex->sql_command = SQLCOM_SHOW_PROFILES; } + | PROFILE_SYM opt_profile_defs opt_profile_args opt_limit_clause_init + { + LEX *lex= Lex; + lex->sql_command= SQLCOM_SHOW_PROFILE; + if (prepare_schema_table(YYTHD, lex, NULL, SCH_PROFILES) != 0) + YYABORT; + } | opt_var_type STATUS_SYM wild_and_where { LEX *lex= Lex; @@ -10290,6 +10368,7 @@ keyword_sp: | AVG_SYM {} | BINLOG_SYM {} | BIT_SYM {} + | BLOCK_SYM {} | BOOL_SYM {} | BOOLEAN_SYM {} | BTREE_SYM {} @@ -10309,7 +10388,9 @@ keyword_sp: | CONCURRENT {} | CONNECTION_SYM {} | CONSISTENT_SYM {} + | CONTEXT_SYM {} | CONTRIBUTORS_SYM {} + | CPU_SYM {} | CUBE_SYM {} | DATA_SYM {} | DATAFILE_SYM {} @@ -10338,6 +10419,7 @@ keyword_sp: | EXPANSION_SYM {} | EXTENDED_SYM {} | EXTENT_SIZE_SYM {} + | FAULTS_SYM {} | FAST_SYM {} | FOUND_SYM {} | ENABLE_SYM {} @@ -10359,6 +10441,8 @@ keyword_sp: | IMPORT {} | INDEXES {} | INITIAL_SIZE_SYM {} + | IO_SYM {} + | IPC_SYM {} | ISOLATION {} | ISSUER_SYM {} | INNOBASE_SYM {} @@ -10441,6 +10525,8 @@ keyword_sp: | PRIVILEGES {} | PROCESS {} | PROCESSLIST_SYM {} + | PROFILE_SYM {} + | PROFILES_SYM {} | QUARTER_SYM {} | QUERY_SYM {} | QUICK {} @@ -10475,6 +10561,7 @@ keyword_sp: | SHUTDOWN {} | SNAPSHOT_SYM {} | SOUNDS_SYM {} + | SOURCE_SYM {} | SQL_CACHE_SYM {} | SQL_BUFFER_RESULT {} | SQL_NO_CACHE_SYM {} @@ -10489,6 +10576,8 @@ keyword_sp: | SUBPARTITIONS_SYM {} | SUPER_SYM {} | SUSPEND_SYM {} + | SWAPS_SYM {} + | SWITCHES_SYM {} | TABLES {} | TABLESPACE {} | TEMPORARY {} diff --git a/sql/structs.h b/sql/structs.h index 662d0a680b8..f14cca3c5db 100644 --- a/sql/structs.h +++ b/sql/structs.h @@ -209,7 +209,7 @@ typedef struct user_conn { char *user; /* Pointer to host part of the key. */ char *host; - /* + /** The moment of time when per hour counters were reset last time (i.e. start of "hour" for conn_per_hour, updates, questions counters). */ diff --git a/sql/table.h b/sql/table.h index 1e80afdf421..284885658e0 100644 --- a/sql/table.h +++ b/sql/table.h @@ -729,6 +729,7 @@ enum enum_schema_tables SCH_PARTITIONS, SCH_PLUGINS, SCH_PROCESSLIST, + SCH_PROFILES, SCH_REFERENTIAL_CONSTRAINTS, SCH_PROCEDURES, SCH_SCHEMATA, diff --git a/sql/tztime.h b/sql/tztime.h index ddd80b88bf2..3d77a3eefa3 100644 --- a/sql/tztime.h +++ b/sql/tztime.h @@ -20,7 +20,7 @@ #if !defined(TESTTIME) && !defined(TZINFO2SQL) -/* +/** This class represents abstract time zone and provides basic interface for MYSQL_TIME <-> my_time_t conversion. Actual time zones which are specified by DB, or via offset @@ -30,7 +30,7 @@ class Time_zone: public Sql_alloc { public: Time_zone() {} /* Remove gcc warning */ - /* + /** Converts local time in broken down MYSQL_TIME representation to my_time_t (UTC seconds since Epoch) represenation. Returns 0 in case of error. Sets in_dst_time_gap to true if date provided @@ -38,19 +38,19 @@ public: */ virtual my_time_t TIME_to_gmt_sec(const MYSQL_TIME *t, my_bool *in_dst_time_gap) const = 0; - /* + /** Converts time in my_time_t representation to local time in broken down MYSQL_TIME representation. */ virtual void gmt_sec_to_TIME(MYSQL_TIME *tmp, my_time_t t) const = 0; - /* + /** Because of constness of String returned by get_name() time zone name have to be already zeroended to be able to use String::ptr() instead of c_ptr(). */ virtual const String * get_name() const = 0; - /* + /** We need this only for surpressing warnings, objects of this type are allocated on MEM_ROOT and should not require destruction. */ @@ -65,7 +65,7 @@ extern my_bool my_tz_init(THD *org_thd, const char *default_tzname, my_bool extern void my_tz_free(); extern my_time_t sec_since_epoch_TIME(MYSQL_TIME *t); -/* +/** Number of elements in table list produced by my_tz_get_table_list() (this table list contains tables which are needed for dynamical loading of time zone descriptions). Actually it is imlementation detail that diff --git a/sql/unireg.h b/sql/unireg.h index f0b4a88c7f8..2e0172ce31d 100644 --- a/sql/unireg.h +++ b/sql/unireg.h @@ -155,34 +155,34 @@ #define OPEN_VIEW 8192 /* Allow open on view */ #define OPEN_VIEW_NO_PARSE 16384 /* Open frm only if it's a view, but do not parse view itself */ -/* +/** This flag is used in function get_all_tables() which fills I_S tables with data which are retrieved from frm files and storage engine The flag means that we need to open FRM file only to get necessary data. */ #define OPEN_FRM_FILE_ONLY 32768 -/* +/** This flag is used in function get_all_tables() which fills I_S tables with data which are retrieved from frm files and storage engine The flag means that we need to process tables only to get necessary data. Views are not processed. */ #define OPEN_TABLE_ONLY OPEN_FRM_FILE_ONLY*2 -/* +/** This flag is used in function get_all_tables() which fills I_S tables with data which are retrieved from frm files and storage engine The flag means that we need to process views only to get necessary data. Tables are not processed. */ #define OPEN_VIEW_ONLY OPEN_TABLE_ONLY*2 -/* +/** This flag is used in function get_all_tables() which fills I_S tables with data which are retrieved from frm files and storage engine. The flag means that we need to open a view using open_normal_and_derived_tables() function. */ #define OPEN_VIEW_FULL OPEN_VIEW_ONLY*2 -/* +/** This flag is used in function get_all_tables() which fills I_S tables with data which are retrieved from frm files and storage engine. The flag means that I_S table uses optimization algorithm. |