diff options
Diffstat (limited to 'sql')
-rw-r--r-- | sql/field.cc | 38 | ||||
-rw-r--r-- | sql/field.h | 2 | ||||
-rw-r--r-- | sql/ha_federated.cc | 110 | ||||
-rw-r--r-- | sql/handler.cc | 2 | ||||
-rw-r--r-- | sql/item_func.cc | 8 | ||||
-rw-r--r-- | sql/item_sum.cc | 4 | ||||
-rw-r--r-- | sql/lock.cc | 2 | ||||
-rw-r--r-- | sql/log_event.cc | 2 | ||||
-rw-r--r-- | sql/mysql_priv.h | 35 | ||||
-rw-r--r-- | sql/opt_range.cc | 6 | ||||
-rw-r--r-- | sql/sp_head.cc | 36 | ||||
-rw-r--r-- | sql/sql_acl.cc | 29 | ||||
-rw-r--r-- | sql/sql_acl.h | 2 | ||||
-rw-r--r-- | sql/sql_base.cc | 6 | ||||
-rw-r--r-- | sql/sql_delete.cc | 2 | ||||
-rw-r--r-- | sql/sql_error.cc | 5 | ||||
-rw-r--r-- | sql/sql_help.cc | 2 | ||||
-rw-r--r-- | sql/sql_parse.cc | 54 | ||||
-rw-r--r-- | sql/sql_prepare.cc | 2 | ||||
-rw-r--r-- | sql/sql_rename.cc | 2 | ||||
-rw-r--r-- | sql/sql_select.cc | 36 | ||||
-rw-r--r-- | sql/sql_show.cc | 34 | ||||
-rw-r--r-- | sql/sql_string.cc | 12 | ||||
-rw-r--r-- | sql/sql_table.cc | 282 | ||||
-rw-r--r-- | sql/sql_udf.cc | 13 | ||||
-rw-r--r-- | sql/sql_update.cc | 4 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 246 | ||||
-rw-r--r-- | sql/table.cc | 6 |
28 files changed, 565 insertions, 417 deletions
diff --git a/sql/field.cc b/sql/field.cc index 26575d97f69..b6dd00d62a7 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -5328,11 +5328,11 @@ Field *Field_string::new_field(MEM_ROOT *root, struct st_table *new_table) int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs) { - int error= 0; uint32 not_used, copy_length; char buff[STRING_BUFFER_USUAL_SIZE]; String tmpstr(buff,sizeof(buff), &my_charset_bin); - bool lost_only_spaces= FALSE; + int error_code= 0; + enum MYSQL_ERROR::enum_warning_level level= MYSQL_ERROR::WARN_LEVEL_WARN; /* Convert character set if necessary */ if (String::needs_conversion(length, cs, field_charset, ¬_used)) @@ -5342,7 +5342,7 @@ int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs) from= tmpstr.ptr(); length= tmpstr.length(); if (conv_errors) - error= 1; + error_code= WARN_DATA_TRUNCATED; } /* Make sure we don't break a multibyte sequence @@ -5359,30 +5359,26 @@ int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs) int2store(ptr, copy_length); // Check if we lost something other than just trailing spaces - if ((copy_length < length) && table->in_use->count_cuted_fields) + if ((copy_length < length) && table->in_use->count_cuted_fields && + !error_code) { const char *end= from + length; from+= copy_length; from+= field_charset->cset->scan(field_charset, from, end, MY_SEQ_SPACES); - /* - If we lost only spaces then produce a NOTE, not a WARNING. - But if we have already had errors (e.g with charset conversion), - then don't reset level to NOTE. - */ - if (from == end && !error) - lost_only_spaces= TRUE; - error= 1; + /* If we lost only spaces then produce a NOTE, not a WARNING */ + if (from == end) + level= MYSQL_ERROR::WARN_LEVEL_NOTE; + error_code= WARN_DATA_TRUNCATED; } - if (error) + if (error_code) { - if (lost_only_spaces) - set_warning(MYSQL_ERROR::WARN_LEVEL_NOTE, WARN_DATA_TRUNCATED, 1); - else if (table->in_use->abort_on_warning) - set_warning(MYSQL_ERROR::WARN_LEVEL_ERROR, ER_DATA_TOO_LONG, 1); - else - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1); + if (level == MYSQL_ERROR::WARN_LEVEL_WARN && + table->in_use->abort_on_warning) + error_code= ER_DATA_TOO_LONG; + set_warning(level, error_code, 1); + return 1; } - return error; + return 0; } @@ -7562,7 +7558,7 @@ create_field::create_field(Field *old_field,Field *orig_field) false - otherwise */ bool -Field::set_warning(const uint level, const uint code, int cuted_increment) +Field::set_warning(uint level, uint code, int cuted_increment) { THD *thd= table->in_use; if (thd->count_cuted_fields) diff --git a/sql/field.h b/sql/field.h index 083af27d6d9..5b13ba1042a 100644 --- a/sql/field.h +++ b/sql/field.h @@ -279,7 +279,7 @@ public: virtual CHARSET_INFO *sort_charset(void) const { return charset(); } virtual bool has_charset(void) const { return FALSE; } virtual void set_charset(CHARSET_INFO *charset) { } - bool set_warning(const unsigned int level, const unsigned int code, + bool set_warning(unsigned int level, unsigned int code, int cuted_increment); bool check_int(const char *str, int length, const char *int_end, CHARSET_INFO *cs); diff --git a/sql/ha_federated.cc b/sql/ha_federated.cc index 215a8daf200..cddd0fd5927 100644 --- a/sql/ha_federated.cc +++ b/sql/ha_federated.cc @@ -634,23 +634,12 @@ static int parse_url(FEDERATED_SHARE *share, TABLE *table, share->port= MYSQL_PORT; } - DBUG_PRINT("ha_federated::parse_url", + DBUG_PRINT("info", ("scheme %s username %s password %s \ hostname %s port %d database %s tablename %s\n", share->scheme, share->username, share->password, share->hostname, share->port, share->database, share->table_base_name)); - - /* If creation, check first if we can connect and that the table exists */ - /*if (table_create_flag) - { - if (check_foreign_data_source(share)) - goto error; - */ - /* free share->schema even if no error, since this is a create */ - /* - my_free((gptr) share->scheme, MYF(0)); - }*/ } else goto error; @@ -662,7 +651,7 @@ static int parse_url(FEDERATED_SHARE *share, TABLE *table, error: my_error(error_num, MYF(0), - "this connection string is not in the correct format!\n"); + "connection string is not in the correct format",0); DBUG_RETURN(1); } @@ -760,7 +749,7 @@ bool ha_federated::create_where_from_key(String *to, KEY *key_info, if (to->append("IS NULL", 7)) DBUG_RETURN(1); - DBUG_PRINT("ha_federated::create_where_from_key", + DBUG_PRINT("info", ("NULL type %s", to->c_ptr_quick())); key_length-= key_part->store_length; key+= key_part->store_length - 1; @@ -790,8 +779,6 @@ bool ha_federated::create_where_from_key(String *to, KEY *key_info, if (to->append(buff, (uint)(ptr - buff))) DBUG_RETURN(1); - DBUG_PRINT("ha_federated::create_where_from_key", - ("bit type %s", to->c_ptr_quick())); key_length-= length; continue; } @@ -805,8 +792,6 @@ bool ha_federated::create_where_from_key(String *to, KEY *key_info, if (append_escaped(to, &tmp)) DBUG_RETURN(1); - DBUG_PRINT("ha_federated::create_where_from_key", - ("blob type %s", to->c_ptr_quick())); length= key_part->length; } else if (key_part->key_part_flag & HA_VAR_LENGTH_PART) @@ -816,14 +801,9 @@ bool ha_federated::create_where_from_key(String *to, KEY *key_info, tmp.set_quick((char*) key, length, &my_charset_bin); if (append_escaped(to, &tmp)) DBUG_RETURN(1); - - DBUG_PRINT("ha_federated::create_where_from_key", - ("varchar type %s", to->c_ptr_quick())); } else { - DBUG_PRINT("ha_federated::create_where_from_key", - ("else block, unknown type so far")); char buff[MAX_FIELD_WIDTH]; String str(buff, sizeof(buff), field->charset()), *res; @@ -833,16 +813,13 @@ bool ha_federated::create_where_from_key(String *to, KEY *key_info, if (append_escaped(to, res)) DBUG_RETURN(1); res= field->val_str(&str, (char*) (key)); - - DBUG_PRINT("ha_federated::create_where_from_key", - ("else block, string type", to->c_ptr_quick())); } else if (to->append(res->ptr(), res->length())) DBUG_RETURN(1); } if (needs_quotes && to->append("'")) DBUG_RETURN(1); - DBUG_PRINT("ha_federated::create_where_from_key", + DBUG_PRINT("info", ("final value for 'to' %s", to->c_ptr_quick())); key+= length; key_length-= length; @@ -869,7 +846,7 @@ static FEDERATED_SHARE *get_share(const char *table_name, TABLE *table) /* share->table_name has the file location - we want the table's name! */ table_base_name= (char*) table->s->table_name; - DBUG_PRINT("ha_federated::get_share", ("table_name %s", table_base_name)); + DBUG_PRINT("info", ("table_name %s", table_base_name)); /* So why does this exist? There is no way currently to init a storage engine. Innodb and BDB both have modifications to the server to allow them to @@ -909,7 +886,7 @@ static FEDERATED_SHARE *get_share(const char *table_name, TABLE *table) share->select_query= select_query; strmov(share->table_name, table_name); strmov(share->select_query, query.ptr()); - DBUG_PRINT("ha_federated::get_share", + DBUG_PRINT("info", ("share->select_query %s", share->select_query)); if (my_hash_insert(&federated_open_tables, (byte*) share)) goto error; @@ -996,11 +973,11 @@ int ha_federated::open(const char *name, int mode, uint test_if_locked) /* Connect to foreign database mysql_real_connect() */ mysql= mysql_init(0); - DBUG_PRINT("ha_federated::open", ("hostname %s", share->hostname)); - DBUG_PRINT("ha_federated::open", ("username %s", share->username)); - DBUG_PRINT("ha_federated::open", ("password %s", share->password)); - DBUG_PRINT("ha_federated::open", ("database %s", share->database)); - DBUG_PRINT("ha_federated::open", ("port %d", share->port)); + DBUG_PRINT("info", ("hostname %s", share->hostname)); + DBUG_PRINT("info", ("username %s", share->username)); + DBUG_PRINT("info", ("password %s", share->password)); + DBUG_PRINT("info", ("database %s", share->database)); + DBUG_PRINT("info", ("port %d", share->port)); if (!mysql_real_connect(mysql, share->hostname, share->username, @@ -1034,7 +1011,7 @@ int ha_federated::close(void) /* free the result set */ if (result) { - DBUG_PRINT("ha_federated::close", + DBUG_PRINT("info", ("mysql_free_result result at address %lx", result)); mysql_free_result(result); result= 0; @@ -1120,7 +1097,7 @@ int ha_federated::write_row(byte *buf) insert_field_value_string.length(0); DBUG_ENTER("ha_federated::write_row"); - DBUG_PRINT("ha_federated::write_row", ("table charset name %s csname %s", + DBUG_PRINT("info", ("table charset name %s csname %s", table->s->table_charset->name, table->s->table_charset->csname)); statistic_increment(table->in_use->status_var.ha_write_count, &LOCK_status); @@ -1133,8 +1110,7 @@ int ha_federated::write_row(byte *buf) this query id */ current_query_id= table->in_use->query_id; - DBUG_PRINT("ha_federated::write_row", ("current query id %d", - current_query_id)); + DBUG_PRINT("info", ("current query id %d", current_query_id)); /* start off our string */ insert_string.append("INSERT INTO `"); @@ -1160,9 +1136,9 @@ int ha_federated::write_row(byte *buf) loop through the field pointer array, add any fields to both the values list and the fields list that match the current query id */ + x=0; for (field= table->field; *field; field++, x++) { - DBUG_PRINT("ha_federated::write_row", ("field type %d", (*field)->type())); /* if there is a query id and if it's equal to the current query id */ if (((*field)->query_id && (*field)->query_id == current_query_id) || all_fields_have_same_query_id) @@ -1171,16 +1147,16 @@ int ha_federated::write_row(byte *buf) if ((*field)->is_null()) { - DBUG_PRINT("ha_federated::write_row", - ("current query id %d field is_null query id %d", - current_query_id, (*field)->query_id)); + DBUG_PRINT("info", + ("column %d current query id %d field is_null query id %d", + x, current_query_id, (*field)->query_id)); insert_field_value_string.append("NULL"); } else { - DBUG_PRINT("ha_federated::write_row", - ("current query id %d field is not null query ID %d", - current_query_id, (*field)->query_id)); + DBUG_PRINT("info", + ("column %d current query id %d field is not null query ID %d", + x, current_query_id, (*field)->query_id)); (*field)->val_str(&insert_field_value_string); /* quote these fields if they require it */ (*field)->quote_data(&insert_field_value_string); } @@ -1194,10 +1170,6 @@ int ha_federated::write_row(byte *buf) /* append commas between both fields and fieldnames */ insert_string.append(','); values_string.append(','); - DBUG_PRINT("ha_federated::write_row", - ("insert_string %s values_string %s insert_field_value_string %s", - insert_string.c_ptr_quick(), values_string.c_ptr_quick(), - insert_field_value_string.c_ptr_quick())); } } @@ -1215,7 +1187,7 @@ int ha_federated::write_row(byte *buf) AND, we don't want to chop off the last char '(' insert will be "INSERT INTO t1 VALUES ();" */ - DBUG_PRINT("ha_federated::write_row", ("x %d num fields %d", x, num_fields)); + DBUG_PRINT("info", ("x %d num fields %d", x, num_fields)); if (num_fields > 0) { /* chops off leading commas */ @@ -1228,8 +1200,7 @@ int ha_federated::write_row(byte *buf) /* add the values */ insert_string.append(values_string); - DBUG_PRINT("ha_federated::write_row", ("insert query %s", - insert_string.c_ptr_quick())); + DBUG_PRINT("info", ("insert query %s", insert_string.c_ptr_quick())); if (mysql_real_query(mysql, insert_string.ptr(), insert_string.length())) { @@ -1240,6 +1211,7 @@ int ha_federated::write_row(byte *buf) DBUG_RETURN(0); } + /* Yes, update_row() does what you expect, it updates a row. old_data will have the previous row record in it, while new_data will have the newest data in @@ -1286,7 +1258,7 @@ int ha_federated::update_row(const byte *old_data, byte *new_data) primary_key_field_num= has_a_primary_key ? table->key_info[table->s->primary_key].key_part->fieldnr - 1 : -1; if (has_a_primary_key) - DBUG_PRINT("ha_federated::update_row", ("has a primary key")); + DBUG_PRINT("info", ("has a primary key")); update_string.append("UPDATE `"); update_string.append(share->table_base_name); @@ -1324,7 +1296,10 @@ int ha_federated::update_row(const byte *old_data, byte *new_data) update_string.append('='); if ((*field)->is_null()) + { + DBUG_PRINT("info", ("column %d is NULL", x )); new_field_value.append("NULL"); + } else { /* otherwise = */ @@ -1356,12 +1331,18 @@ int ha_federated::update_row(const byte *old_data, byte *new_data) where_string.append(" IS NULL "); else { + uint o_len; (*field)->val_str(&old_field_value, (char*) (old_data + (*field)->offset())); + o_len= (*field)->pack_length(); + DBUG_PRINT("info", ("o_len %lu", o_len)); (*field)->quote_data(&old_field_value); where_string.append(old_field_value); } } + DBUG_PRINT("info", + ("column %d new value %s old value %s", + x, new_field_value.c_ptr_quick(), old_field_value.c_ptr_quick() )); update_string.append(new_field_value); new_field_value.length(0); @@ -1378,7 +1359,7 @@ int ha_federated::update_row(const byte *old_data, byte *new_data) if (! has_a_primary_key) update_string.append(" LIMIT 1"); - DBUG_PRINT("ha_federated::update_row", ("Final update query: %s", + DBUG_PRINT("info", ("Final update query: %s", update_string.c_ptr_quick())); if (mysql_real_query(mysql, update_string.ptr(), update_string.length())) { @@ -1447,7 +1428,7 @@ int ha_federated::delete_row(const byte *buf) } delete_string.append(" LIMIT 1"); - DBUG_PRINT("ha_federated::delete_row", + DBUG_PRINT("info", ("Delete sql: %s", delete_string.c_ptr_quick())); if (mysql_real_query(mysql, delete_string.ptr(), delete_string.length())) { @@ -1513,12 +1494,12 @@ int ha_federated::index_read_idx(byte *buf, uint index, const byte *key, create_where_from_key(&index_string, &table->key_info[index], key, keylen); sql_query.append(index_string); - DBUG_PRINT("ha_federated::index_read_idx", + DBUG_PRINT("info", ("current key %d key value %s index_string value %s length %d", index, (char*) key, index_string.c_ptr_quick(), index_string.length())); - DBUG_PRINT("ha_federated::index_read_idx", + DBUG_PRINT("info", ("current position %d sql_query %s", current_position, sql_query.c_ptr_quick())); @@ -1554,7 +1535,7 @@ int ha_federated::index_init(uint keynr) { int error; DBUG_ENTER("ha_federated::index_init"); - DBUG_PRINT("ha_federated::index_init", + DBUG_PRINT("info", ("table: '%s' key: %d", table->s->table_name, keynr)); active_index= keynr; DBUG_RETURN(0); @@ -1623,11 +1604,10 @@ int ha_federated::rnd_init(bool scan) scan_flag= scan; if (scan) { - DBUG_PRINT("ha_federated::rnd_init", - ("share->select_query %s", share->select_query)); + DBUG_PRINT("info", ("share->select_query %s", share->select_query)); if (result) { - DBUG_PRINT("ha_federated::rnd_init", + DBUG_PRINT("info", ("mysql_free_result address %lx", result)); mysql_free_result(result); result= 0; @@ -1652,8 +1632,7 @@ int ha_federated::rnd_end() DBUG_ENTER("ha_federated::rnd_end"); if (result) { - DBUG_PRINT("ha_federated::index_end", - ("mysql_free_result address %lx", result)); + DBUG_PRINT("info", ("mysql_free_result address %lx", result)); mysql_free_result(result); result= 0; } @@ -1696,8 +1675,7 @@ int ha_federated::rnd_next(byte *buf) /* Fetch a row, insert it back in a row format. */ current_position= result->data_cursor; - DBUG_PRINT("ha_federated::rnd_next", - ("current position %d", current_position)); + DBUG_PRINT("info", ("current position %d", current_position)); if (!(row= mysql_fetch_row(result))) DBUG_RETURN(HA_ERR_END_OF_FILE); @@ -1941,7 +1919,7 @@ int ha_federated::create(const char *name, TABLE *table_arg, DBUG_RETURN(0); error: - DBUG_PRINT("ha_federated::create", ("errors, returning %d", ER_CANT_CREATE_TABLE)); + DBUG_PRINT("info", ("errors, returning %d", ER_CANT_CREATE_TABLE)); my_free((gptr) tmp.scheme, MYF(0)); DBUG_RETURN(ER_CANT_CREATE_TABLE); diff --git a/sql/handler.cc b/sql/handler.cc index c7bd65bf24c..1ef73a9136f 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -841,7 +841,7 @@ int ha_recover(HASH *commit_list) for now, only InnoDB supports 2pc. It means we can always safely rollback all pending transactions, without risking inconsistent data */ - DBUG_ASSERT(total_ha_2pc == opt_bin_log+1); // only InnoDB and binlog + DBUG_ASSERT(total_ha_2pc == (ulong) opt_bin_log+1); // only InnoDB and binlog tc_heuristic_recover= TC_HEURISTIC_RECOVER_ROLLBACK; // forcing ROLLBACK dry_run=FALSE; #endif diff --git a/sql/item_func.cc b/sql/item_func.cc index 0a993b6f3d8..684ba814cd4 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -4467,19 +4467,19 @@ Item_func_sp::Item_func_sp(sp_name *name) { maybe_null= 1; m_name->init_qname(current_thd); - dummy_table= (TABLE *)sql_alloc(sizeof(TABLE)); - bzero(dummy_table, sizeof(TABLE)); + dummy_table= (TABLE*) sql_calloc(sizeof(TABLE)); } + Item_func_sp::Item_func_sp(sp_name *name, List<Item> &list) :Item_func(list), m_name(name), m_sp(NULL) { maybe_null= 1; m_name->init_qname(current_thd); - dummy_table= (TABLE *)sql_alloc(sizeof(TABLE)); - bzero(dummy_table, sizeof(TABLE)); + dummy_table= (TABLE*) sql_calloc(sizeof(TABLE)); } + const char * Item_func_sp::func_name() const { diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 174e2ba4b85..b18653ed5a4 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -727,7 +727,7 @@ Item_sum_avg_distinct::fix_length_and_dec() AVG() will divide val by count. We need to reserve digits after decimal point as the result can be fractional. */ - decimals+= 4; + decimals= min(decimals + 4, NOT_FIXED_DEC); } @@ -927,7 +927,7 @@ void Item_sum_variance::fix_length_and_dec() { DBUG_ENTER("Item_sum_variance::fix_length_and_dec"); maybe_null= null_value= 1; - decimals= args[0]->decimals + 4; + decimals= min(args[0]->decimals + 4, NOT_FIXED_DEC); switch (args[0]->result_type()) { case REAL_RESULT: case STRING_RESULT: diff --git a/sql/lock.cc b/sql/lock.cc index b4a51abba70..266e8dc4d4d 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -562,7 +562,7 @@ int lock_table_name(THD *thd, TABLE_LIST *table_list) my_free((gptr) table,MYF(0)); DBUG_RETURN(-1); } - if (remove_table_from_cache(thd, db, table_list->table_name)) + if (remove_table_from_cache(thd, db, table_list->table_name, 0)) DBUG_RETURN(1); // Table is in use DBUG_RETURN(0); } diff --git a/sql/log_event.cc b/sql/log_event.cc index 3176cdfd5cb..ba018e859c1 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -2610,7 +2610,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli, "data truncated" warning but which is absorbed and never gets to the error log); still we init it to avoid a Valgrind message. */ - mysql_reset_errors(thd); + mysql_reset_errors(thd, 0); TABLE_LIST tables; bzero((char*) &tables,sizeof(tables)); diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 43bb28a5f36..ba9f382fc33 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -457,7 +457,7 @@ bool check_procedure_access(THD *thd,ulong want_access,char *db,char *name, bool check_some_access(THD *thd, ulong want_access, TABLE_LIST *table); bool check_merge_table_access(THD *thd, char *db, TABLE_LIST *table_list); -bool check_some_routine_access(THD *thd, char *db, char *name); +bool check_some_routine_access(THD *thd, const char *db, const char *name); bool multi_update_precheck(THD *thd, TABLE_LIST *tables); bool multi_delete_precheck(THD *thd, TABLE_LIST *tables, uint *table_count); bool mysql_multi_update_prepare(THD *thd); @@ -632,10 +632,11 @@ int mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *t); int mysql_derived_filling(THD *thd, LEX *lex, TABLE_LIST *t); Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, Item ***copy_func, Field **from_field, - bool group, bool modify_item, uint convert_blob_length); + bool group, bool modify_item, + uint convert_blob_length); int prepare_create_field(create_field *sql_field, - uint &blob_columns, - int ×tamps, int ×tamps_with_niladic, + uint *blob_columns, + int *timestamps, int *timestamps_with_niladic, uint table_flags); int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, List<create_field> &fields, @@ -661,7 +662,7 @@ bool mysql_alter_table(THD *thd, char *new_db, char *new_name, uint order_num, ORDER *order, enum enum_duplicates handle_duplicates, bool ignore, - ALTER_INFO *alter_info, bool do_send_ok=1); + ALTER_INFO *alter_info, bool do_send_ok); bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list, bool do_send_ok); bool mysql_create_like_table(THD *thd, TABLE_LIST *table, HA_CREATE_INFO *create_info, @@ -705,7 +706,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT* mem, bool *refresh); TABLE *reopen_name_locked_table(THD* thd, TABLE_LIST* table); TABLE *find_locked_table(THD *thd, const char *db,const char *table_name); -bool reopen_table(TABLE *table,bool locked=0); +bool reopen_table(TABLE *table,bool locked); bool reopen_tables(THD *thd,bool get_locks,bool in_refresh); void close_old_data_files(THD *thd, TABLE *table, bool abort_locks, bool send_refresh); @@ -769,7 +770,7 @@ void append_identifier(THD *thd, String *packet, const char *name, uint length); int get_quote_char_for_identifier(THD *thd, const char *name, uint length); void mysqld_list_fields(THD *thd,TABLE_LIST *table, const char *wild); -int mysqld_dump_create_info(THD *thd, TABLE_LIST *table_list, int fd = -1); +int mysqld_dump_create_info(THD *thd, TABLE_LIST *table_list, int fd); bool mysqld_show_create(THD *thd, TABLE_LIST *table_list); bool mysqld_show_create_db(THD *thd, char *dbname, HA_CREATE_INFO *create); @@ -790,7 +791,7 @@ void calc_sum_of_all_status(STATUS_VAR *to); extern LEX_STRING information_schema_name; LEX_STRING *make_lex_string(THD *thd, LEX_STRING *lex_str, const char* str, uint length, - bool allocate_lex_string= 0); + bool allocate_lex_string); ST_SCHEMA_TABLE *find_schema_table(THD *thd, const char* table_name); ST_SCHEMA_TABLE *get_schema_table(enum enum_schema_tables schema_table_idx); int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident, @@ -806,7 +807,7 @@ bool get_schema_tables_result(JOIN *join); /* sql_prepare.cc */ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length, - LEX_STRING *name=NULL); + LEX_STRING *name); void mysql_stmt_execute(THD *thd, char *packet, uint packet_length); void mysql_sql_stmt_execute(THD *thd, LEX_STRING *stmt_name); void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length); @@ -821,11 +822,11 @@ MYSQL_ERROR *push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level, uint const char *msg); void push_warning_printf(THD *thd, MYSQL_ERROR::enum_warning_level level, uint code, const char *format, ...); -void mysql_reset_errors(THD *thd, bool force= false); +void mysql_reset_errors(THD *thd, bool force); bool mysqld_show_warnings(THD *thd, ulong levels_to_show); /* sql_handler.cc */ -bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen= 0); +bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen); bool mysql_ha_close(THD *thd, TABLE_LIST *tables); bool mysql_ha_read(THD *, TABLE_LIST *,enum enum_ha_read_modes,char *, List<Item> *,enum ha_rkey_function,Item *,ha_rows,ha_rows); @@ -854,15 +855,15 @@ create_field * new_create_field(THD *thd, char *field_name, enum_field_types typ List<String> *interval_list, CHARSET_INFO *cs, uint uint_geom_type); void store_position_for_column(const char *name); -bool add_to_list(THD *thd, SQL_LIST &list,Item *group,bool asc=0); +bool add_to_list(THD *thd, SQL_LIST &list,Item *group,bool asc); void add_join_on(TABLE_LIST *b,Item *expr); void add_join_natural(TABLE_LIST *a,TABLE_LIST *b); bool add_proc_to_list(THD *thd, Item *item); TABLE *unlink_open_table(THD *thd,TABLE *list,TABLE *find); SQL_SELECT *make_select(TABLE *head, table_map const_tables, - table_map read_tables, COND *conds, int *error, - bool allow_null_cond= false); + table_map read_tables, COND *conds, + bool allow_null_cond, int *error); extern Item **not_found_item; Item ** find_item_in_list(Item *item, List<Item> &items, uint *counter, find_item_error_report_type report_error, @@ -905,13 +906,13 @@ TABLE_LIST *find_table_in_list(TABLE_LIST *table, TABLE_LIST *unique_table(TABLE_LIST *table, TABLE_LIST *table_list); TABLE **find_temporary_table(THD *thd, const char *db, const char *table_name); bool close_temporary_table(THD *thd, const char *db, const char *table_name); -void close_temporary(TABLE *table, bool delete_table=1); +void close_temporary(TABLE *table, bool delete_table); bool rename_temporary_table(THD* thd, TABLE *table, const char *new_db, const char *table_name); void remove_db_from_cache(const char *db); void flush_tables(); bool remove_table_from_cache(THD *thd, const char *db, const char *table, - bool return_if_owned_by_thd=0); + bool return_if_owned_by_thd); bool close_cached_tables(THD *thd, bool wait_for_refresh, TABLE_LIST *tables); void copy_field_from_tmp_record(Field *field,int offset); bool fill_record(THD *thd, List<Item> &fields, List<Item> &values, @@ -1172,7 +1173,7 @@ void unlock_table_name(THD *thd, TABLE_LIST *table_list); bool wait_for_locked_table_names(THD *thd, TABLE_LIST *table_list); bool lock_table_names(THD *thd, TABLE_LIST *table_list); void unlock_table_names(THD *thd, TABLE_LIST *table_list, - TABLE_LIST *last_table= 0); + TABLE_LIST *last_table); /* old unireg functions */ diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 812d5a41cbc..fe1780b92a7 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -650,8 +650,10 @@ int imerge_list_or_tree(PARAM *param, */ SQL_SELECT *make_select(TABLE *head, table_map const_tables, - table_map read_tables, COND *conds, int *error, - bool allow_null_cond) + table_map read_tables, COND *conds, + bool allow_null_cond, + int *error) + { SQL_SELECT *select; DBUG_ENTER("make_select"); diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 2097e55d4e3..89c4b2dbaac 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -1016,23 +1016,31 @@ sp_head::restore_thd_mem_root(THD *thd) } -bool check_show_routine_acceess(THD *thd, sp_head *sp, bool *full_access) +/* + 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 +*/ + +bool check_show_routine_access(THD *thd, sp_head *sp, bool *full_access) { TABLE_LIST tables; bzero((char*) &tables,sizeof(tables)); tables.db= (char*) "mysql"; tables.table_name= tables.alias= (char*) "proc"; - *full_access= !check_table_access(thd, SELECT_ACL, &tables, 1); - if (!(*full_access)) - *full_access= (!strcmp(sp->m_definer_user.str, thd->priv_user) && - !strcmp(sp->m_definer_host.str, thd->priv_host)); - if (!(*full_access)) - { -#ifndef NO_EMBEDDED_ACCESS_CHECKS - return check_some_routine_access(thd, (char * )sp->m_db.str, - (char * ) sp->m_name.str); -#endif - } + *full_access= (!check_table_access(thd, SELECT_ACL, &tables, 1) || + (!strcmp(sp->m_definer_user.str, thd->priv_user) && + !strcmp(sp->m_definer_host.str, thd->priv_host))); + if (!*full_access) + return check_some_routine_access(thd, sp->m_db.str, sp->m_name.str); return 0; } @@ -1056,7 +1064,7 @@ sp_head::show_create_procedure(THD *thd) LINT_INIT(sql_mode_str); LINT_INIT(sql_mode_len); - if (check_show_routine_acceess(thd, this, &full_access)) + if (check_show_routine_access(thd, this, &full_access)) return 1; old_sql_mode= thd->variables.sql_mode; @@ -1129,7 +1137,7 @@ sp_head::show_create_function(THD *thd) LINT_INIT(sql_mode_str); LINT_INIT(sql_mode_len); - if (check_show_routine_acceess(thd, this, &full_access)) + if (check_show_routine_access(thd, this, &full_access)) return 1; old_sql_mode= thd->variables.sql_mode; diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 3db219b5fdc..c51e5e00aa1 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -1642,17 +1642,6 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo, } else { - /* - Check that the user isn't trying to change a password for another - user if he doesn't have UPDATE privilege to the MySQL database - */ - DBUG_ASSERT(combo.host.str != 0); - if (thd->user && combo.password.str && - (strcmp(thd->user,combo.user.str) || - my_strcasecmp(system_charset_info, - combo.host.str, thd->host_or_ip)) && - check_access(thd, UPDATE_ACL, "mysql",0,1,0)) - goto end; old_row_exists = 1; store_record(table,record[1]); // Save copy for update if (combo.password.str) // If password given @@ -2125,7 +2114,7 @@ static GRANT_NAME *name_hash_search(HASH *name_hash, inline GRANT_NAME * proc_hash_search(const char *host, const char *ip, const char *db, - const char *user, const char *tname, bool exact) + const char *user, const char *tname, bool exact) { return (GRANT_TABLE*) name_hash_search(&proc_priv_hash, host, ip, db, user, tname, exact); @@ -3594,11 +3583,11 @@ err: name Routine name RETURN - 1 error 0 Ok + 1 error */ -bool check_routine_level_acl(THD *thd, char *db, char *name) +bool check_routine_level_acl(THD *thd, const char *db, const char *name) { bool no_routine_acl= 1; if (grant_option) @@ -5570,4 +5559,16 @@ void fill_effective_table_privileges(THD *thd, GRANT_INFO *grant, grant->privilege|= grant->grant_table->privs; } } + +#else /* NO_EMBEDDED_ACCESS_CHECKS */ + +/**************************************************************************** + Dummy wrappers when we don't have any access checks +****************************************************************************/ + +bool check_routine_level_acl(THD *thd, const char *db, const char *name) +{ + return FALSE; +} + #endif diff --git a/sql/sql_acl.h b/sql/sql_acl.h index 30e335c7afd..24916fd4385 100644 --- a/sql/sql_acl.h +++ b/sql/sql_acl.h @@ -219,7 +219,7 @@ void fill_effective_table_privileges(THD *thd, GRANT_INFO *grant, const char *db, const char *table); bool sp_revoke_privileges(THD *thd, const char *sp_db, const char *sp_name); bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name); -bool check_routine_level_acl(THD *thd, char *db, char *name); +bool check_routine_level_acl(THD *thd, const char *db, const char *name); #ifdef NO_EMBEDDED_ACCESS_CHECKS #define check_grant(A,B,C,D,E,F) 0 diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 09640eb3f57..4750fe1386f 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -633,7 +633,7 @@ void close_temporary_tables(THD *thd) table->s->table_name,"`,", NullS); } next=table->next; - close_temporary(table); + close_temporary(table, 1); } if (query && found_user_tables && mysql_bin_log.is_open()) { @@ -798,7 +798,7 @@ bool close_temporary_table(THD *thd, const char *db, const char *table_name) return 1; table= *prev; *prev= table->next; - close_temporary(table); + close_temporary(table, 1); if (thd->slave_thread) --slave_open_temp_tables; return 0; @@ -1606,7 +1606,7 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db, if (ha_create_table_from_engine(thd, db, name, TRUE) != 0) goto err; - mysql_reset_errors(thd, true); // Clear warnings + mysql_reset_errors(thd, 1); // Clear warnings thd->clear_error(); // Clear error message continue; } diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index d49d654cb87..642564f5d7a 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -96,7 +96,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, table->used_keys.clear_all(); table->quick_keys.clear_all(); // Can't use 'only index' - select=make_select(table,0,0,conds,&error); + select=make_select(table, 0, 0, conds, 0, &error); if (error) DBUG_RETURN(TRUE); if ((select && select->check_quick(thd, safe_update, limit)) || !limit) diff --git a/sql/sql_error.cc b/sql/sql_error.cc index 4420f2d16ad..281ac7169c0 100644 --- a/sql/sql_error.cc +++ b/sql/sql_error.cc @@ -80,7 +80,8 @@ void mysql_reset_errors(THD *thd, bool force) thd->warn_id= thd->query_id; free_root(&thd->warn_root,MYF(0)); bzero((char*) thd->warn_count, sizeof(thd->warn_count)); - if (force) thd->total_warn_count= 0; + if (force) + thd->total_warn_count= 0; thd->warn_list.empty(); thd->row_count= 1; // by default point to row 1 } @@ -113,7 +114,7 @@ MYSQL_ERROR *push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level, DBUG_RETURN(0); if (thd->query_id != thd->warn_id) - mysql_reset_errors(thd); + mysql_reset_errors(thd, 0); thd->got_warning= 1; if (thd->spcont && thd->spcont->find_handler(code, diff --git a/sql/sql_help.cc b/sql/sql_help.cc index f5490da7e85..fa3e2070a28 100644 --- a/sql/sql_help.cc +++ b/sql/sql_help.cc @@ -562,7 +562,7 @@ SQL_SELECT *prepare_simple_select(THD *thd, Item *cond, TABLE_LIST *tables, /* Assume that no indexes cover all required fields */ table->used_keys.clear_all(); - SQL_SELECT *res= make_select(table,0,0,cond,error); + SQL_SELECT *res= make_select(table, 0, 0, cond, 0, error); if (*error || (res && res->check_quick(thd, 0, HA_POS_ERROR)) || (res->quick && res->quick->reset())) { diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 66b0e69452f..a39ccacfe00 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1623,7 +1623,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, } case COM_PREPARE: { - mysql_stmt_prepare(thd, packet, packet_length); + mysql_stmt_prepare(thd, packet, packet_length, 0); break; } case COM_CLOSE_STMT: @@ -2261,7 +2261,7 @@ mysql_execute_command(THD *thd) */ if (all_tables || &lex->select_lex != lex->all_selects_list || lex->spfuns.records || lex->spprocs.records) - mysql_reset_errors(thd); + mysql_reset_errors(thd, 0); #ifdef HAVE_REPLICATION if (thd->slave_thread) @@ -2935,7 +2935,8 @@ unsent_create_error: lex->key_list, select_lex->order_list.elements, (ORDER *) select_lex->order_list.first, - lex->duplicates, lex->ignore, &lex->alter_info); + lex->duplicates, lex->ignore, &lex->alter_info, + 1); } break; } @@ -3625,6 +3626,24 @@ unsent_create_error: first_table ? 0 : 1, 0)) goto error; + if (thd->user) // If not replication + { + LEX_USER *user; + List_iterator <LEX_USER> user_list(lex->users_list); + while ((user=user_list++)) + { + if (user->password.str && + strcmp(thd->user, user->user.str) || + user->host.str && + my_strcasecmp(system_charset_info, + user->host.str, thd->host_or_ip)) + { + if (check_access(thd, UPDATE_ACL, "mysql", 0, 1, 0)) + goto error; + break; // We are allowed to do changes + } + } + } if (specialflag & SPECIAL_NO_RESOLVE) { LEX_USER *user; @@ -3762,7 +3781,7 @@ unsent_create_error: if (check_db_used(thd, all_tables) || check_table_access(thd, SELECT_ACL, all_tables, 0)) goto error; - res= mysql_ha_open(thd, first_table); + res= mysql_ha_open(thd, first_table, 0); break; case SQLCOM_HA_CLOSE: DBUG_ASSERT(first_table == all_tables && first_table != 0); @@ -4107,7 +4126,7 @@ unsent_create_error: sp= sp_find_procedure(thd, lex->spname); else sp= sp_find_function(thd, lex->spname); - mysql_reset_errors(thd); + mysql_reset_errors(thd, 0); if (! sp) result= SP_KEY_NOT_FOUND; else @@ -4148,7 +4167,7 @@ unsent_create_error: sp= sp_find_procedure(thd, lex->spname); else sp= sp_find_function(thd, lex->spname); - mysql_reset_errors(thd); + mysql_reset_errors(thd, 0); if (sp) { db= thd->strdup(sp->m_db.str); @@ -4758,7 +4777,7 @@ check_procedure_access(THD *thd, ulong want_access,char *db, char *name, 1 error */ -bool check_some_routine_access(THD *thd, char *db, char *name) +bool check_some_routine_access(THD *thd, const char *db, const char *name) { ulong save_priv; if (thd->master_access & SHOW_PROC_ACLS) @@ -4766,12 +4785,7 @@ bool check_some_routine_access(THD *thd, char *db, char *name) if (!check_access(thd, SHOW_PROC_ACLS, db, &save_priv, 0, 1) || (save_priv & SHOW_PROC_ACLS)) return FALSE; -#ifndef NO_EMBEDDED_ACCESS_CHECKS - if (grant_option) - return check_routine_level_acl(thd, db, name); -#endif - - return FALSE; + return check_routine_level_acl(thd, db, name); } @@ -5849,11 +5863,14 @@ bool st_select_lex::init_nested_join(THD *thd) TABLE_LIST *st_select_lex::end_nested_join(THD *thd) { TABLE_LIST *ptr; + NESTED_JOIN *nested_join; DBUG_ENTER("end_nested_join"); + + DBUG_ASSERT(embedding); ptr= embedding; join_list= ptr->join_list; embedding= ptr->embedding; - NESTED_JOIN *nested_join= ptr->nested_join; + nested_join= ptr->nested_join; if (nested_join->join_list.elements == 1) { TABLE_LIST *embedded= nested_join->join_list.head(); @@ -5863,6 +5880,11 @@ TABLE_LIST *st_select_lex::end_nested_join(THD *thd) join_list->push_front(embedded); ptr= embedded; } + else if (nested_join->join_list.elements == 0) + { + join_list->pop(); + ptr= 0; // return value + } DBUG_RETURN(ptr); } @@ -6494,7 +6516,7 @@ bool mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys) DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->table_name, &create_info, table_list, fields, keys, 0, (ORDER*)0, - DUP_ERROR, 0, &alter_info)); + DUP_ERROR, 0, &alter_info, 1)); } @@ -6512,7 +6534,7 @@ bool mysql_drop_index(THD *thd, TABLE_LIST *table_list, ALTER_INFO *alter_info) DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->table_name, &create_info, table_list, fields, keys, 0, (ORDER*)0, - DUP_ERROR, 0, alter_info)); + DUP_ERROR, 0, alter_info, 1)); } diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 5cd4753c229..7862717bb18 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1782,7 +1782,7 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length, thd->current_arena= stmt; mysql_init_query(thd, (uchar *) thd->query, thd->query_length); /* Reset warnings from previous command */ - mysql_reset_errors(thd); + mysql_reset_errors(thd, 0); lex= thd->lex; lex->safe_to_cache_query= 0; diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc index 8bc1891ef1b..8fe17198cf0 100644 --- a/sql/sql_rename.cc +++ b/sql/sql_rename.cc @@ -90,7 +90,7 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list) send_ok(thd); } - unlock_table_names(thd, table_list); + unlock_table_names(thd, table_list, (TABLE_LIST*) 0); err: pthread_mutex_unlock(&LOCK_open); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 277c9970595..b970c184489 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -675,8 +675,8 @@ JOIN::optimize() /* Handle the case where we have an OUTER JOIN without a WHERE */ conds=new Item_int((longlong) 1,1); // Always true } - select=make_select(*table, const_table_map, - const_table_map, conds, &error, true); + select= make_select(*table, const_table_map, + const_table_map, conds, 1, &error); if (error) { /* purecov: inspected */ error= -1; /* purecov: inspected */ @@ -2398,7 +2398,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, select= make_select(s->table, found_const_table_map, found_const_table_map, *s->on_expr_ref ? *s->on_expr_ref : conds, - &error, true); + 1, &error); if (!select) DBUG_RETURN(1); records= get_quick_record_count(join->thd, select, s->table, @@ -4987,7 +4987,7 @@ bool store_val_in_field(Field *field,Item *item) { bool error; - THD *thd=current_thd; + THD *thd= field->table->in_use; ha_rows cuted_fields=thd->cuted_fields; /* we should restore old value of count_cuted_fields because @@ -5182,6 +5182,7 @@ make_outerjoin_info(JOIN *join) static bool make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) { + THD *thd= join->thd; DBUG_ENTER("make_join_select"); if (select) { @@ -5191,8 +5192,8 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) if (join->tables > 1) cond->update_used_tables(); // Tablenr may have changed if (join->const_tables == join->tables && - join->thd->lex->current_select->master_unit() == - &join->thd->lex->unit) // not upper level SELECT + thd->lex->current_select->master_unit() == + &thd->lex->unit) // not upper level SELECT join->const_table_map|=RAND_TABLE_BIT; { // Check const tables COND *const_cond= @@ -5288,7 +5289,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) { DBUG_EXECUTE("where",print_where(tmp,tab->table->alias);); SQL_SELECT *sel=tab->select=(SQL_SELECT*) - join->thd->memdup((gptr) select, sizeof(SQL_SELECT)); + thd->memdup((gptr) select, sizeof(SQL_SELECT)); if (!sel) DBUG_RETURN(1); // End of memory /* @@ -5298,14 +5299,15 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) the first match for outer tables is encountered. */ if (cond) - {/* + { + /* Because of QUICK_GROUP_MIN_MAX_SELECT there may be a select without a cond, so neutralize the hack above. */ if (!(tmp= add_found_match_trig_cond(first_inner_tab, tmp, 0))) DBUG_RETURN(1); tab->select_cond=sel->cond=tmp; - if (join->thd->variables.engine_condition_pushdown) + if (thd->variables.engine_condition_pushdown) { tab->table->file->pushed_cond= NULL; /* Push condition to handler */ @@ -5375,7 +5377,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) if (sel->cond && !sel->cond->fixed) sel->cond->quick_fix_field(); - if (sel->test_quick_select(join->thd, tab->keys, + if (sel->test_quick_select(thd, tab->keys, used_tables & ~ current_map, (join->select_options & OPTION_FOUND_ROWS ? @@ -5388,7 +5390,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) */ sel->cond=orig_cond; if (!*tab->on_expr_ref || - sel->test_quick_select(join->thd, tab->keys, + sel->test_quick_select(thd, tab->keys, used_tables & ~ current_map, (join->select_options & OPTION_FOUND_ROWS ? @@ -5430,10 +5432,10 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) { DBUG_EXECUTE("where",print_where(tmp,"cache");); tab->cache.select=(SQL_SELECT*) - join->thd->memdup((gptr) sel, sizeof(SQL_SELECT)); + thd->memdup((gptr) sel, sizeof(SQL_SELECT)); tab->cache.select->cond=tmp; tab->cache.select->read_tables=join->const_table_map; - if (join->thd->variables.engine_condition_pushdown && + if (thd->variables.engine_condition_pushdown && (!tab->table->file->pushed_cond)) { /* Push condition to handler */ @@ -5443,7 +5445,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) } } } - } + } /* Push down all predicates from on expressions. @@ -11909,7 +11911,7 @@ calc_group_buffer(JOIN *join,ORDER *group) { /* This case should never be choosen */ DBUG_ASSERT(0); - current_thd->fatal_error(); + join->thd->fatal_error(); } parts++; if ((*group->item)->maybe_null) @@ -12493,7 +12495,8 @@ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab) error=(int) cond->add(join_tab->select->cond); join_tab->select_cond=join_tab->select->cond=cond; } - else if ((join_tab->select=make_select(join_tab->table, 0, 0, cond,&error))) + else if ((join_tab->select= make_select(join_tab->table, 0, 0, cond, 0, + &error))) join_tab->select_cond=cond; DBUG_RETURN(error ? TRUE : FALSE); @@ -13237,6 +13240,7 @@ void st_table_list::print(THD *thd, String *str) void st_select_lex::print(THD *thd, String *str) { + /* QQ: thd may not be set for sub queries, but this should be fixed */ if (!thd) thd= current_thd; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index e0fc570015d..124ce1805db 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -704,14 +704,17 @@ static void append_directory(THD *thd, String *packet, const char *dir_type, packet->append(dir_type); packet->append(" DIRECTORY='", 12); #ifdef __WIN__ - char *winfilename = thd->memdup(filename, length); - for (uint i=0; i < length; i++) - if (winfilename[i] == '\\') - winfilename[i] = '/'; - packet->append(winfilename, length); -#else - packet->append(filename, length); + /* Convert \ to / to be able to create table on unix */ + char *winfilename= (char*) thd->memdup(filename, length); + char *pos, *end; + for (pos= winfilename, end= pos+length ; pos < end ; pos++) + { + if (*pos == '\\') + *pos = '/'; + } + filename= winfilename; #endif + packet->append(filename, length); packet->append('\''); } } @@ -2489,13 +2492,8 @@ void store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table, definer= get_field(thd->mem_root, proc_table->field[11]); if (!full_access) full_access= !strcmp(sp_user, definer); - if (!full_access) - { -#ifndef NO_EMBEDDED_ACCESS_CHECKS - if (check_some_routine_access(thd, (char * )sp_db, (char * )sp_name)) - return; -#endif - } + if (!full_access && check_some_routine_access(thd, sp_db, sp_name)) + return; if (lex->orig_sql_command == SQLCOM_SHOW_STATUS_PROC && proc_table->field[2]->val_int() == TYPE_ENUM_PROCEDURE || @@ -2507,36 +2505,30 @@ void store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table, if (!wild || !wild[0] || !wild_compare(sp_name, wild, 0)) { table->field[3]->store(sp_name, strlen(sp_name), cs); - tmp_string.length(0); get_field(thd->mem_root, proc_table->field[3], &tmp_string); table->field[0]->store(tmp_string.ptr(), tmp_string.length(), cs); table->field[2]->store(sp_db, strlen(sp_db), cs); - tmp_string.length(0); get_field(thd->mem_root, proc_table->field[2], &tmp_string); table->field[4]->store(tmp_string.ptr(), tmp_string.length(), cs); if (proc_table->field[2]->val_int() == TYPE_ENUM_FUNCTION) { - tmp_string.length(0); get_field(thd->mem_root, proc_table->field[9], &tmp_string); table->field[5]->store(tmp_string.ptr(), tmp_string.length(), cs); table->field[5]->set_notnull(); } if (full_access) { - tmp_string.length(0); get_field(thd->mem_root, proc_table->field[10], &tmp_string); table->field[7]->store(tmp_string.ptr(), tmp_string.length(), cs); } table->field[6]->store("SQL", 3, cs); table->field[10]->store("SQL", 3, cs); - tmp_string.length(0); get_field(thd->mem_root, proc_table->field[6], &tmp_string); table->field[11]->store(tmp_string.ptr(), tmp_string.length(), cs); if (proc_table->field[5]->val_int() == SP_CONTAINS_SQL) { table->field[12]->store("CONTAINS SQL", 12 , cs); } - tmp_string.length(0); get_field(thd->mem_root, proc_table->field[7], &tmp_string); table->field[14]->store(tmp_string.ptr(), tmp_string.length(), cs); bzero((char *)&time, sizeof(time)); @@ -2545,10 +2537,8 @@ void store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table, bzero((char *)&time, sizeof(time)); ((Field_timestamp *) proc_table->field[13])->get_time(&time); table->field[16]->store_time(&time, MYSQL_TIMESTAMP_DATETIME); - tmp_string.length(0); get_field(thd->mem_root, proc_table->field[14], &tmp_string); table->field[17]->store(tmp_string.ptr(), tmp_string.length(), cs); - tmp_string.length(0); get_field(thd->mem_root, proc_table->field[15], &tmp_string); table->field[18]->store(tmp_string.ptr(), tmp_string.length(), cs); table->field[19]->store(definer, strlen(definer), cs); diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 226a80201a1..0424723d97f 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -686,16 +686,16 @@ void String::qs_append(double *d) void String::qs_append(int i) { - char *buff = Ptr + str_length; - sprintf(buff,"%d", i); - str_length += strlen(buff); + char *buff= Ptr + str_length; + char *end= int10_to_str(i, buff, -10); + str_length+= (int) (end-buff); } void String::qs_append(uint i) { - char *buff = Ptr + str_length; - sprintf(buff,"%u", i); - str_length += strlen(buff); + char *buff= Ptr + str_length; + char *end= int10_to_str(i, buff, 10); + str_length+= (int) (end-buff); } /* diff --git a/sql/sql_table.cc b/sql/sql_table.cc index c79f49afc64..8295e2f07ab 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -207,7 +207,8 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, if (!drop_temporary) { abort_locked_tables(thd,db,table->table_name); - while (remove_table_from_cache(thd,db,table->table_name) && !thd->killed) + while (remove_table_from_cache(thd, db, table->table_name, 0) && + !thd->killed) { dropping_tables++; (void) pthread_cond_wait(&COND_refresh,&LOCK_open); @@ -290,7 +291,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, } } - unlock_table_names(thd, tables); + unlock_table_names(thd, tables, (TABLE_LIST*) 0); thd->no_warnings_for_error= 0; DBUG_RETURN(error); } @@ -450,150 +451,151 @@ void calculate_interval_lengths(CHARSET_INFO *cs, TYPELIB *interval, */ int prepare_create_field(create_field *sql_field, - uint &blob_columns, - int ×tamps, int ×tamps_with_niladic, + uint *blob_columns, + int *timestamps, int *timestamps_with_niladic, uint table_flags) { DBUG_ENTER("prepare_field"); - { - /* This code came from mysql_prepare_table. - Indent preserved to make patching easier */ - DBUG_ASSERT(sql_field->charset); - - switch (sql_field->sql_type) { - case FIELD_TYPE_BLOB: - case FIELD_TYPE_MEDIUM_BLOB: - case FIELD_TYPE_TINY_BLOB: - case FIELD_TYPE_LONG_BLOB: - sql_field->pack_flag=FIELDFLAG_BLOB | - pack_length_to_packflag(sql_field->pack_length - - portable_sizeof_char_ptr); - if (sql_field->charset->state & MY_CS_BINSORT) - sql_field->pack_flag|=FIELDFLAG_BINARY; - sql_field->length=8; // Unireg field length - sql_field->unireg_check=Field::BLOB_FIELD; - blob_columns++; - break; - case FIELD_TYPE_GEOMETRY: + + /* + This code came from mysql_prepare_table. + Indent preserved to make patching easier + */ + DBUG_ASSERT(sql_field->charset); + + switch (sql_field->sql_type) { + case FIELD_TYPE_BLOB: + case FIELD_TYPE_MEDIUM_BLOB: + case FIELD_TYPE_TINY_BLOB: + case FIELD_TYPE_LONG_BLOB: + sql_field->pack_flag=FIELDFLAG_BLOB | + pack_length_to_packflag(sql_field->pack_length - + portable_sizeof_char_ptr); + if (sql_field->charset->state & MY_CS_BINSORT) + sql_field->pack_flag|=FIELDFLAG_BINARY; + sql_field->length=8; // Unireg field length + sql_field->unireg_check=Field::BLOB_FIELD; + (*blob_columns)++; + break; + case FIELD_TYPE_GEOMETRY: #ifdef HAVE_SPATIAL - if (!(table_flags & HA_CAN_GEOMETRY)) - { - my_printf_error(ER_CHECK_NOT_IMPLEMENTED, ER(ER_CHECK_NOT_IMPLEMENTED), - MYF(0), "GEOMETRY"); - DBUG_RETURN(1); - } - sql_field->pack_flag=FIELDFLAG_GEOM | - pack_length_to_packflag(sql_field->pack_length - - portable_sizeof_char_ptr); - if (sql_field->charset->state & MY_CS_BINSORT) - sql_field->pack_flag|=FIELDFLAG_BINARY; - sql_field->length=8; // Unireg field length - sql_field->unireg_check=Field::BLOB_FIELD; - blob_columns++; - break; -#else - my_printf_error(ER_FEATURE_DISABLED,ER(ER_FEATURE_DISABLED), MYF(0), - sym_group_geom.name, sym_group_geom.needed_define); + if (!(table_flags & HA_CAN_GEOMETRY)) + { + my_printf_error(ER_CHECK_NOT_IMPLEMENTED, ER(ER_CHECK_NOT_IMPLEMENTED), + MYF(0), "GEOMETRY"); DBUG_RETURN(1); + } + sql_field->pack_flag=FIELDFLAG_GEOM | + pack_length_to_packflag(sql_field->pack_length - + portable_sizeof_char_ptr); + if (sql_field->charset->state & MY_CS_BINSORT) + sql_field->pack_flag|=FIELDFLAG_BINARY; + sql_field->length=8; // Unireg field length + sql_field->unireg_check=Field::BLOB_FIELD; + (*blob_columns)++; + break; +#else + my_printf_error(ER_FEATURE_DISABLED,ER(ER_FEATURE_DISABLED), MYF(0), + sym_group_geom.name, sym_group_geom.needed_define); + DBUG_RETURN(1); #endif /*HAVE_SPATIAL*/ - case MYSQL_TYPE_VARCHAR: + case MYSQL_TYPE_VARCHAR: #ifndef QQ_ALL_HANDLERS_SUPPORT_VARCHAR - if (table_flags & HA_NO_VARCHAR) - { - /* convert VARCHAR to CHAR because handler is not yet up to date */ - sql_field->sql_type= MYSQL_TYPE_VAR_STRING; - sql_field->pack_length= calc_pack_length(sql_field->sql_type, - (uint) sql_field->length); - if ((sql_field->length / sql_field->charset->mbmaxlen) > - MAX_FIELD_CHARLENGTH) - { - my_printf_error(ER_TOO_BIG_FIELDLENGTH, ER(ER_TOO_BIG_FIELDLENGTH), - MYF(0), sql_field->field_name, MAX_FIELD_CHARLENGTH); - DBUG_RETURN(1); - } - } -#endif - /* fall through */ - case FIELD_TYPE_STRING: - sql_field->pack_flag=0; - if (sql_field->charset->state & MY_CS_BINSORT) - sql_field->pack_flag|=FIELDFLAG_BINARY; - break; - case FIELD_TYPE_ENUM: - sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) | - FIELDFLAG_INTERVAL; - if (sql_field->charset->state & MY_CS_BINSORT) - sql_field->pack_flag|=FIELDFLAG_BINARY; - sql_field->unireg_check=Field::INTERVAL_FIELD; - check_duplicates_in_interval("ENUM",sql_field->field_name, - sql_field->interval, - sql_field->charset); - break; - case FIELD_TYPE_SET: - sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) | - FIELDFLAG_BITFIELD; - if (sql_field->charset->state & MY_CS_BINSORT) - sql_field->pack_flag|=FIELDFLAG_BINARY; - sql_field->unireg_check=Field::BIT_FIELD; - check_duplicates_in_interval("SET",sql_field->field_name, - sql_field->interval, - sql_field->charset); - break; - case FIELD_TYPE_DATE: // Rest of string types - case FIELD_TYPE_NEWDATE: - case FIELD_TYPE_TIME: - case FIELD_TYPE_DATETIME: - case FIELD_TYPE_NULL: - sql_field->pack_flag=f_settype((uint) sql_field->sql_type); - break; - case FIELD_TYPE_BIT: - if (!(table_flags & HA_CAN_BIT_FIELD)) + if (table_flags & HA_NO_VARCHAR) + { + /* convert VARCHAR to CHAR because handler is not yet up to date */ + sql_field->sql_type= MYSQL_TYPE_VAR_STRING; + sql_field->pack_length= calc_pack_length(sql_field->sql_type, + (uint) sql_field->length); + if ((sql_field->length / sql_field->charset->mbmaxlen) > + MAX_FIELD_CHARLENGTH) { - my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "BIT FIELD"); + my_printf_error(ER_TOO_BIG_FIELDLENGTH, ER(ER_TOO_BIG_FIELDLENGTH), + MYF(0), sql_field->field_name, MAX_FIELD_CHARLENGTH); DBUG_RETURN(1); } - sql_field->pack_flag= FIELDFLAG_NUMBER; - break; - case FIELD_TYPE_NEWDECIMAL: - sql_field->pack_flag=(FIELDFLAG_NUMBER | - (sql_field->flags & UNSIGNED_FLAG ? 0 : - FIELDFLAG_DECIMAL) | - (sql_field->flags & ZEROFILL_FLAG ? - FIELDFLAG_ZEROFILL : 0) | - (sql_field->decimals << FIELDFLAG_DEC_SHIFT)); - break; - case FIELD_TYPE_TIMESTAMP: - /* We should replace old TIMESTAMP fields with their newer analogs */ - if (sql_field->unireg_check == Field::TIMESTAMP_OLD_FIELD) + } +#endif + /* fall through */ + case FIELD_TYPE_STRING: + sql_field->pack_flag=0; + if (sql_field->charset->state & MY_CS_BINSORT) + sql_field->pack_flag|=FIELDFLAG_BINARY; + break; + case FIELD_TYPE_ENUM: + sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) | + FIELDFLAG_INTERVAL; + if (sql_field->charset->state & MY_CS_BINSORT) + sql_field->pack_flag|=FIELDFLAG_BINARY; + sql_field->unireg_check=Field::INTERVAL_FIELD; + check_duplicates_in_interval("ENUM",sql_field->field_name, + sql_field->interval, + sql_field->charset); + break; + case FIELD_TYPE_SET: + sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) | + FIELDFLAG_BITFIELD; + if (sql_field->charset->state & MY_CS_BINSORT) + sql_field->pack_flag|=FIELDFLAG_BINARY; + sql_field->unireg_check=Field::BIT_FIELD; + check_duplicates_in_interval("SET",sql_field->field_name, + sql_field->interval, + sql_field->charset); + break; + case FIELD_TYPE_DATE: // Rest of string types + case FIELD_TYPE_NEWDATE: + case FIELD_TYPE_TIME: + case FIELD_TYPE_DATETIME: + case FIELD_TYPE_NULL: + sql_field->pack_flag=f_settype((uint) sql_field->sql_type); + break; + case FIELD_TYPE_BIT: + if (!(table_flags & HA_CAN_BIT_FIELD)) + { + my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "BIT FIELD"); + DBUG_RETURN(1); + } + sql_field->pack_flag= FIELDFLAG_NUMBER; + break; + case FIELD_TYPE_NEWDECIMAL: + sql_field->pack_flag=(FIELDFLAG_NUMBER | + (sql_field->flags & UNSIGNED_FLAG ? 0 : + FIELDFLAG_DECIMAL) | + (sql_field->flags & ZEROFILL_FLAG ? + FIELDFLAG_ZEROFILL : 0) | + (sql_field->decimals << FIELDFLAG_DEC_SHIFT)); + break; + case FIELD_TYPE_TIMESTAMP: + /* We should replace old TIMESTAMP fields with their newer analogs */ + if (sql_field->unireg_check == Field::TIMESTAMP_OLD_FIELD) + { + if (!*timestamps) { - if (!timestamps) - { - sql_field->unireg_check= Field::TIMESTAMP_DNUN_FIELD; - timestamps_with_niladic++; - } - else - sql_field->unireg_check= Field::NONE; + sql_field->unireg_check= Field::TIMESTAMP_DNUN_FIELD; + (*timestamps_with_niladic)++; } - else if (sql_field->unireg_check != Field::NONE) - timestamps_with_niladic++; - - timestamps++; - /* fall-through */ - default: - sql_field->pack_flag=(FIELDFLAG_NUMBER | - (sql_field->flags & UNSIGNED_FLAG ? 0 : - FIELDFLAG_DECIMAL) | - (sql_field->flags & ZEROFILL_FLAG ? - FIELDFLAG_ZEROFILL : 0) | - f_settype((uint) sql_field->sql_type) | - (sql_field->decimals << FIELDFLAG_DEC_SHIFT)); - break; - } - if (!(sql_field->flags & NOT_NULL_FLAG)) - sql_field->pack_flag|= FIELDFLAG_MAYBE_NULL; - if (sql_field->flags & NO_DEFAULT_VALUE_FLAG) - sql_field->pack_flag|= FIELDFLAG_NO_DEFAULT; - } + else + sql_field->unireg_check= Field::NONE; + } + else if (sql_field->unireg_check != Field::NONE) + (*timestamps_with_niladic)++; + + (*timestamps)++; + /* fall-through */ + default: + sql_field->pack_flag=(FIELDFLAG_NUMBER | + (sql_field->flags & UNSIGNED_FLAG ? 0 : + FIELDFLAG_DECIMAL) | + (sql_field->flags & ZEROFILL_FLAG ? + FIELDFLAG_ZEROFILL : 0) | + f_settype((uint) sql_field->sql_type) | + (sql_field->decimals << FIELDFLAG_DEC_SHIFT)); + break; + } + if (!(sql_field->flags & NOT_NULL_FLAG)) + sql_field->pack_flag|= FIELDFLAG_MAYBE_NULL; + if (sql_field->flags & NO_DEFAULT_VALUE_FLAG) + sql_field->pack_flag|= FIELDFLAG_NO_DEFAULT; DBUG_RETURN(0); } @@ -856,8 +858,8 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, { DBUG_ASSERT(sql_field->charset != 0); - if (prepare_create_field(sql_field, blob_columns, - timestamps, timestamps_with_niladic, + if (prepare_create_field(sql_field, &blob_columns, + ×tamps, ×tamps_with_niladic, file->table_flags())) DBUG_RETURN(-1); if (sql_field->sql_type == FIELD_TYPE_BLOB || @@ -1764,7 +1766,7 @@ static void wait_while_table_is_used(THD *thd,TABLE *table, mysql_lock_abort(thd, table); // end threads waiting on lock /* Wait until all there are no other threads that has this table open */ - while (remove_table_from_cache(thd, table->s->db, table->s->table_name)) + while (remove_table_from_cache(thd, table->s->db, table->s->table_name, 0)) { dropping_tables++; (void) pthread_cond_wait(&COND_refresh,&LOCK_open); @@ -2133,7 +2135,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, "Waiting to get writelock"); mysql_lock_abort(thd,table->table); while (remove_table_from_cache(thd, table->table->s->db, - table->table->s->table_name) && + table->table->s->table_name, 0) && ! thd->killed) { dropping_tables++; @@ -2248,7 +2250,7 @@ send_result_message: { pthread_mutex_lock(&LOCK_open); remove_table_from_cache(thd, table->table->s->db, - table->table->s->table_name); + table->table->s->table_name, 0); pthread_mutex_unlock(&LOCK_open); /* May be something modified consequently we have to invalidate cache */ query_cache_invalidate3(thd, table->table, 0); @@ -3557,7 +3559,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, if (table) { VOID(table->file->extra(HA_EXTRA_FORCE_REOPEN)); // Use new file - remove_table_from_cache(thd,db,table_name); // Mark all in-use copies old + remove_table_from_cache(thd,db,table_name, 0); // Mark in-use copies old mysql_lock_abort(thd,table); // end threads waiting on lock } VOID(quick_rm_table(old_db_type,db,old_name)); diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc index 1d14d037c47..3340c46bb6b 100644 --- a/sql/sql_udf.cc +++ b/sql/sql_udf.cc @@ -110,15 +110,15 @@ static char *init_syms(udf_func *tmp, char *nm) */ if (!tmp->func_init && !tmp->func_deinit && tmp->type != UDFTYPE_AGGREGATE) { - if (opt_allow_suspicious_udfs) - sql_print_error(ER(ER_CANT_FIND_DL_ENTRY), nm); - else + if (!opt_allow_suspicious_udfs) return nm; + if (current_thd->variables.log_warnings) + sql_print_warning(ER(ER_CANT_FIND_DL_ENTRY), nm); } - return 0; } + extern "C" byte* get_hash_key(const byte *buff,uint *length, my_bool not_used __attribute__((unused))) { @@ -127,9 +127,10 @@ extern "C" byte* get_hash_key(const byte *buff,uint *length, return (byte*) udf->name.str; } + /* -** Read all predeclared functions from mysql.func and accept all that -** can be used. + Read all predeclared functions from mysql.func and accept all that + can be used. */ void udf_init() diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 477a283448a..3ee656b00ce 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -219,7 +219,7 @@ int mysql_update(THD *thd, #ifndef NO_EMBEDDED_ACCESS_CHECKS /* Check values */ table_list->grant.want_privilege= table->grant.want_privilege= - (SELECT_ACL & ~~table->grant.privilege); + (SELECT_ACL & ~table->grant.privilege); #endif if (setup_fields(thd, 0, table_list, values, 1, 0, 0)) { @@ -229,7 +229,7 @@ int mysql_update(THD *thd, // Don't count on usage of 'only index' when calculating which key to use table->used_keys.clear_all(); - select=make_select(table,0,0,conds,&error); + select= make_select(table, 0, 0, conds, 0, &error); if (error || (select && select->check_quick(thd, safe_update, limit)) || !limit) { diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index ef5cbb3c79b..cc6eadf5fd5 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -52,6 +52,13 @@ const LEX_STRING null_lex_str={0,0}; ER_WARN_DEPRECATED_SYNTAX, \ ER(ER_WARN_DEPRECATED_SYNTAX), (A), (B)); +#define TEST_ASSERT(A) \ + if (!(A)) \ + { \ + yyerror(ER(ER_SYNTAX_ERROR)); \ + YYABORT; \ + } + /* Helper for parsing "IS [NOT] truth_value" */ inline Item *is_truth_value(Item *A, bool v1, bool v2) { @@ -692,6 +699,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); opt_var_ident_type delete_option opt_temporary all_or_any opt_distinct opt_ignore_leaves fulltext_options spatial_type union_option start_transaction_opts opt_chain opt_release + union_opt select_derived_init %type <ulong_num> ULONG_NUM raid_types merge_insert_types @@ -738,6 +746,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %type <table_list> join_table_list join_table table_factor table_ref + select_derived derived_table_list %type <date_time_type> date_time_type; %type <interval> interval @@ -772,6 +781,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %type <variable> internal_variable_name %type <select_lex> in_subselect in_subselect_init + get_select_lex %type <boolfunc2creator> comp_op @@ -1388,14 +1398,18 @@ create_function_tail: uint unused1= 0; int unused2= 0; - if (!(new_field= new_create_field(YYTHD, "", (enum enum_field_types)$8, - lex->length, lex->dec, lex->type, - (Item *)0, (Item *) 0, &cmt, 0, &lex->interval_list, - (lex->charset ? lex->charset : default_charset_info), - lex->uint_geom_type))) + if (!(new_field= new_create_field(YYTHD, "", + (enum enum_field_types)$8, + lex->length, lex->dec, lex->type, + (Item *)0, (Item *) 0, &cmt, 0, + &lex->interval_list, + (lex->charset ? lex->charset : + default_charset_info), + lex->uint_geom_type))) YYABORT; - if (prepare_create_field(new_field, unused1, unused2, unused2, 0)) + if (prepare_create_field(new_field, &unused1, &unused2, &unused2, + 0)) YYABORT; sp->m_returns= new_field->sql_type; @@ -4024,13 +4038,53 @@ optional_braces: /* all possible expressions */ expr: - expr or bool_term { $$= new Item_cond_or($1,$3); } - | expr XOR bool_term { $$= new Item_cond_xor($1,$3); } - | bool_term ; + bool_term { Select->expr_list.push_front(new List<Item>); } + bool_or_expr + { + List<Item> *list= Select->expr_list.pop(); + if (list->elements) + { + list->push_front($1); + $$= new Item_cond_or(*list); + /* optimize construction of logical OR to reduce + amount of objects for complex expressions */ + } + else + $$= $1; + delete list; + } + ; + +bool_or_expr: + /* empty */ + | bool_or_expr or bool_term + { Select->expr_list.head()->push_back($3); } + ; bool_term: - bool_term and bool_factor { $$= new Item_cond_and($1,$3); } - | bool_factor ; + bool_term XOR bool_term { $$= new Item_cond_xor($1,$3); } + | bool_factor { Select->expr_list.push_front(new List<Item>); } + bool_and_expr + { + List<Item> *list= Select->expr_list.pop(); + if (list->elements) + { + list->push_front($1); + $$= new Item_cond_and(*list); + /* optimize construction of logical AND to reduce + amount of objects for complex expressions */ + } + else + $$= $1; + delete list; + } + ; + +bool_and_expr: + /* empty */ + | bool_and_expr and bool_factor + { Select->expr_list.head()->push_back($3); } + ; bool_factor: NOT_SYM bool_factor { $$= negate_expression(YYTHD, $2); } @@ -4915,6 +4969,7 @@ when_list2: sel->when_list.head()->push_back($5); }; +/* Warning - may return NULL in case of incomplete SELECT */ table_ref: table_factor { $$=$1; } | join_table { $$=$1; } @@ -4926,36 +4981,47 @@ table_ref: ; join_table_list: + derived_table_list { TEST_ASSERT($$=$1); } + ; + +/* Warning - may return NULL in case of incomplete SELECT */ +derived_table_list: table_ref { $$=$1; } - | join_table_list ',' table_ref { $$=$3; } + | derived_table_list ',' table_ref + { + TEST_ASSERT($1 && ($$=$3)); + } ; join_table: - table_ref normal_join table_ref { $$=$3; } + table_ref normal_join table_ref { TEST_ASSERT($1 && ($$=$3)); } | table_ref STRAIGHT_JOIN table_factor - { $3->straight=1; $$=$3 ; } + { TEST_ASSERT($1 && ($$=$3)); $3->straight=1; } | table_ref normal_join table_ref ON expr - { add_join_on($3,$5); $$=$3; } + { TEST_ASSERT($1 && ($$=$3)); add_join_on($3,$5); } | table_ref normal_join table_ref USING { SELECT_LEX *sel= Select; + TEST_ASSERT($1 && $3); sel->save_names_for_using_list($1, $3); } '(' using_list ')' { add_join_on($3,$7); $$=$3; } | table_ref LEFT opt_outer JOIN_SYM table_ref ON expr - { add_join_on($5,$7); $5->outer_join|=JOIN_TYPE_LEFT; $$=$5; } + { TEST_ASSERT($1 && $5); add_join_on($5,$7); $5->outer_join|=JOIN_TYPE_LEFT; $$=$5; } | table_ref LEFT opt_outer JOIN_SYM table_factor { SELECT_LEX *sel= Select; + TEST_ASSERT($1 && $5); sel->save_names_for_using_list($1, $5); } USING '(' using_list ')' { add_join_on($5,$9); $5->outer_join|=JOIN_TYPE_LEFT; $$=$5; } | table_ref NATURAL LEFT opt_outer JOIN_SYM table_factor { + TEST_ASSERT($1 && $6); add_join_natural($1,$6); $6->outer_join|=JOIN_TYPE_LEFT; $$=$6; @@ -4963,6 +5029,7 @@ join_table: | table_ref RIGHT opt_outer JOIN_SYM table_ref ON expr { LEX *lex= Lex; + TEST_ASSERT($1 && $5); if (!($$= lex->current_select->convert_right_join())) YYABORT; add_join_on($$, $7); @@ -4970,6 +5037,7 @@ join_table: | table_ref RIGHT opt_outer JOIN_SYM table_factor { SELECT_LEX *sel= Select; + TEST_ASSERT($1 && $5); sel->save_names_for_using_list($1, $5); } USING '(' using_list ')' @@ -4981,13 +5049,14 @@ join_table: } | table_ref NATURAL RIGHT opt_outer JOIN_SYM table_factor { + TEST_ASSERT($1 && $6); add_join_natural($6,$1); LEX *lex= Lex; if (!($$= lex->current_select->convert_right_join())) YYABORT; } | table_ref NATURAL JOIN_SYM table_factor - { add_join_natural($1,$4); $$=$4; }; + { TEST_ASSERT($1 && ($$=$4)); add_join_natural($1,$4); }; normal_join: @@ -4996,6 +5065,7 @@ normal_join: | CROSS JOIN_SYM {} ; +/* Warning - may return NULL in case of incomplete SELECT */ table_factor: { SELECT_LEX *sel= Select; @@ -5014,50 +5084,96 @@ table_factor: YYABORT; sel->add_joined_table($$); } - | '(' + | '{' ident table_ref LEFT OUTER JOIN_SYM table_ref ON expr '}' + { TEST_ASSERT($3 && $7); add_join_on($7,$9); $7->outer_join|=JOIN_TYPE_LEFT; $$=$7; } + | select_derived_init get_select_lex select_derived2 { LEX *lex= Lex; - if (lex->current_select->init_nested_join(lex->thd)) - YYABORT; + SELECT_LEX *sel= lex->current_select; + if ($1) + { + if (sel->set_braces(1)) + { + yyerror(ER(ER_SYNTAX_ERROR)); + YYABORT; + } + /* select in braces, can't contain global parameters */ + if (sel->master_unit()->fake_select_lex) + sel->master_unit()->global_parameters= + sel->master_unit()->fake_select_lex; + } + if ($2->init_nested_join(lex->thd)) + YYABORT; + $$= 0; + /* incomplete derived tables return NULL, we must be + nested in select_derived rule to be here. */ } - join_table_list ')' + | '(' get_select_lex select_derived union_opt ')' opt_table_alias + { + /* Use $2 instead of Lex->current_select as derived table will + alter value of Lex->current_select. */ + + if (!($3 || $6) && $2->embedding && + !$2->embedding->nested_join->join_list.elements) { - LEX *lex= Lex; - if (!($$= lex->current_select->end_nested_join(lex->thd))) - YYABORT; + /* we have a derived table ($3 == NULL) but no alias, + Since we are nested in further parentheses so we + can pass NULL to the outer level parentheses + Permits parsing of "((((select ...))) as xyz)" */ + $$= 0; } - | '{' ident table_ref LEFT OUTER JOIN_SYM table_ref ON expr '}' - { add_join_on($7,$9); $7->outer_join|=JOIN_TYPE_LEFT; $$=$7; } - | '(' select_derived union_opt ')' opt_table_alias - { - LEX *lex=Lex; - SELECT_LEX_UNIT *unit= lex->current_select->master_unit(); - lex->current_select= unit->outer_select(); - if (!($$= lex->current_select-> - add_table_to_list(lex->thd, new Table_ident(unit), $5, 0, - TL_READ,(List<String> *)0, - (List<String> *)0))) + else + if (!$3) + { + /* Handle case of derived table, alias may be NULL if there + are no outer parentheses, add_table_to_list() will throw + error in this case */ + LEX *lex=Lex; + SELECT_LEX *sel= lex->current_select; + SELECT_LEX_UNIT *unit= sel->master_unit(); + lex->current_select= sel= unit->outer_select(); + if (!($$= sel-> + add_table_to_list(lex->thd, new Table_ident(unit), $6, 0, + TL_READ,(List<String> *)0, + (List<String> *)0))) + YYABORT; + sel->add_joined_table($$); + } + else + if ($4 || $6) + { + /* simple nested joins cannot have aliases or unions */ + yyerror(ER(ER_SYNTAX_ERROR)); YYABORT; - lex->current_select->add_joined_table($$); - }; - + } + else + $$= $3; + } + ; +/* handle contents of parentheses in join expression */ select_derived: - SELECT_SYM select_derived2 - | '(' select_derived ')' + get_select_lex { - SELECT_LEX *sel= Select; - if (sel->set_braces(1)) - { + LEX *lex= Lex; + if ($1->init_nested_join(lex->thd)) + YYABORT; + } + derived_table_list + { + LEX *lex= Lex; + /* for normal joins, $3 != NULL and end_nested_join() != NULL, + for derived tables, both must equal NULL */ + + if (!($$= $1->end_nested_join(lex->thd)) && $3) + YYABORT; + if (!$3 && $$) + { yyerror(ER(ER_SYNTAX_ERROR)); YYABORT; - } - /* select in braces, can't contain global parameters */ - if (sel->master_unit()->fake_select_lex) - sel->master_unit()->global_parameters= - sel->master_unit()->fake_select_lex; - } + } + } ; select_derived2: @@ -5085,6 +5201,29 @@ select_derived2: opt_select_from ; +get_select_lex: + /* Empty */ { $$= Select; } + ; + +select_derived_init: + SELECT_SYM + { + LEX *lex= Lex; + SELECT_LEX *sel= lex->current_select; + TABLE_LIST *embedding; + if (!sel->embedding || sel->end_nested_join(lex->thd)) + { + /* we are not in parentheses */ + yyerror(ER(ER_SYNTAX_ERROR)); + YYABORT; + } + embedding= Select->embedding; + $$= embedding && + !embedding->nested_join->join_list.elements; + /* return true if we are deeply nested */ + } + ; + opt_outer: /* empty */ {} | OUTER {}; @@ -8118,13 +8257,12 @@ union_list: ; union_opt: - union_list {} - | optional_order_or_limit {} + /* Empty */ { $$= 0; } + | union_list { $$= 1; } + | union_order_or_limit { $$= 1; } ; -optional_order_or_limit: - /* Empty */ {} - | +union_order_or_limit: { THD *thd= YYTHD; LEX *lex= thd->lex; diff --git a/sql/table.cc b/sql/table.cc index 63da10c687a..939690395d4 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1390,8 +1390,12 @@ bool get_field(MEM_ROOT *mem, Field *field, String *res) field->val_str(&str); if (!(length= str.length())) + { + res->length(0); return 1; - to= strmake_root(mem, str.ptr(), length); + } + if (!(to= strmake_root(mem, str.ptr(), length))) + length= 0; // Safety fix res->set(to, length, ((Field_str*)field)->charset()); return 0; } |