diff options
author | Alexey Kopytov <Alexey.Kopytov@Sun.com> | 2010-03-07 19:40:59 +0300 |
---|---|---|
committer | Alexey Kopytov <Alexey.Kopytov@Sun.com> | 2010-03-07 19:40:59 +0300 |
commit | 6e7b8b6a7ab2b58016403304b1c49cf908a6479d (patch) | |
tree | 395144ff597d9d1ea027cb0f57f50c5a6e6ab90c /storage/federated | |
parent | 61bd9ef6487829ae8106387dd4a1f5b32b67b4bb (diff) | |
parent | 63a88e137365c4158e22c1c8aba7847b5a0ffe86 (diff) | |
download | mariadb-git-6e7b8b6a7ab2b58016403304b1c49cf908a6479d.tar.gz |
Manual merge of mysql-5.1-bugteam into mysql-trunk-merge.
Conflicts:
Text conflict in .bzr-mysql/default.conf
Text conflict in mysql-test/r/explain.result
Text conflict in mysql-test/r/having.result
Text conflict in mysql-test/suite/rpl/t/disabled.def
Text conflict in mysql-test/suite/rpl/t/rpl_slave_skip.test
Text conflict in storage/federated/ha_federated.cc
Diffstat (limited to 'storage/federated')
-rw-r--r-- | storage/federated/ha_federated.cc | 197 | ||||
-rw-r--r-- | storage/federated/ha_federated.h | 9 |
2 files changed, 127 insertions, 79 deletions
diff --git a/storage/federated/ha_federated.cc b/storage/federated/ha_federated.cc index 05be8b27a8b..80b620db639 100644 --- a/storage/federated/ha_federated.cc +++ b/storage/federated/ha_federated.cc @@ -1622,11 +1622,10 @@ int ha_federated::open(const char *name, int mode, uint test_if_locked) DBUG_ASSERT(mysql == NULL); - ref_length= (table->s->primary_key != MAX_KEY ? - table->key_info[table->s->primary_key].key_length : - table->s->reclength); + ref_length= sizeof(MYSQL_RES *) + sizeof(MYSQL_ROW_OFFSET); DBUG_PRINT("info", ("ref_length: %u", ref_length)); + my_init_dynamic_array(&results, sizeof(MYSQL_RES *), 4, 4); reset(); DBUG_RETURN(0); @@ -1646,21 +1645,17 @@ int ha_federated::open(const char *name, int mode, uint test_if_locked) int ha_federated::close(void) { - int retval; DBUG_ENTER("ha_federated::close"); - /* free the result set */ - if (stored_result) - { - mysql_free_result(stored_result); - stored_result= 0; - } + free_result(); + + delete_dynamic(&results); + /* Disconnect from mysql */ mysql_close(mysql); mysql= NULL; - retval= free_share(share); - DBUG_RETURN(retval); + DBUG_RETURN(free_share(share)); } /* @@ -2329,8 +2324,7 @@ int ha_federated::index_read(uchar *buf, const uchar *key, DBUG_ENTER("ha_federated::index_read"); MYSQL_INDEX_READ_ROW_START(table_share->db.str, table_share->table_name.str); - if (stored_result) - mysql_free_result(stored_result); + free_result(); rc= index_read_idx_with_result_set(buf, active_index, key, key_len, find_flag, &stored_result); @@ -2364,7 +2358,8 @@ int ha_federated::index_read_idx(uchar *buf, uint index, const uchar *key, &mysql_result))) DBUG_RETURN(retval); mysql_free_result(mysql_result); - DBUG_RETURN(retval); + results.elements--; + DBUG_RETURN(0); } @@ -2420,18 +2415,20 @@ int ha_federated::index_read_idx_with_result_set(uchar *buf, uint index, retval= ER_QUERY_ON_FOREIGN_DATA_SOURCE; goto error; } - if (!(*result= mysql_store_result(mysql))) + if (!(*result= store_result(mysql))) { retval= HA_ERR_END_OF_FILE; goto error; } - if (!(retval= read_next(buf, *result))) + if ((retval= read_next(buf, *result))) + { + mysql_free_result(*result); + results.elements--; + *result= 0; + table->status= STATUS_NOT_FOUND; DBUG_RETURN(retval); - - mysql_free_result(*result); - *result= 0; - table->status= STATUS_NOT_FOUND; - DBUG_RETURN(retval); + } + DBUG_RETURN(0); error: table->status= STATUS_NOT_FOUND; @@ -2492,12 +2489,6 @@ int ha_federated::read_range_first(const key_range *start_key, create_where_from_key(&sql_query, &table->key_info[active_index], start_key, end_key, 0, eq_range_arg); - - if (stored_result) - { - mysql_free_result(stored_result); - stored_result= 0; - } if (real_query(sql_query.ptr(), sql_query.length())) { retval= ER_QUERY_ON_FOREIGN_DATA_SOURCE; @@ -2505,7 +2496,7 @@ int ha_federated::read_range_first(const key_range *start_key, } sql_query.length(0); - if (!(stored_result= mysql_store_result(mysql))) + if (!(stored_result= store_result(mysql))) { retval= HA_ERR_END_OF_FILE; goto error; @@ -2599,23 +2590,11 @@ int ha_federated::rnd_init(bool scan) if (scan) { - if (stored_result) - { - mysql_free_result(stored_result); - stored_result= 0; - } - - if (real_query(share->select_query, strlen(share->select_query))) - goto error; - - stored_result= mysql_store_result(mysql); - if (!stored_result) - goto error; + if (real_query(share->select_query, strlen(share->select_query)) || + !(stored_result= store_result(mysql))) + DBUG_RETURN(stash_remote_error()); } DBUG_RETURN(0); - -error: - DBUG_RETURN(stash_remote_error()); } @@ -2629,11 +2608,7 @@ int ha_federated::rnd_end() int ha_federated::index_end(void) { DBUG_ENTER("ha_federated::index_end"); - if (stored_result) - { - mysql_free_result(stored_result); - stored_result= 0; - } + free_result(); active_index= MAX_KEY; DBUG_RETURN(0); } @@ -2704,6 +2679,9 @@ int ha_federated::read_next(uchar *buf, MYSQL_RES *result) DBUG_ENTER("ha_federated::read_next"); table->status= STATUS_NOT_FOUND; // For easier return + + /* Save current data cursor position. */ + current_position= result->data_cursor; /* Fetch a row, insert it back in a row format. */ if (!(row= mysql_fetch_row(result))) @@ -2716,24 +2694,38 @@ int ha_federated::read_next(uchar *buf, MYSQL_RES *result) } -/* - store reference to current row so that we can later find it for - a re-read, update or delete. - - In case of federated, a reference is either a primary key or - the whole record. - - Called from filesort.cc, sql_select.cc, sql_delete.cc and sql_update.cc. +/** + @brief Store a reference to current row. + + @details During a query execution we may have different result sets (RS), + e.g. for different ranges. All the RS's used are stored in + memory and placed in @c results dynamic array. At the end of + execution all stored RS's are freed at once in the + @c ha_federated::reset(). + So, in case of federated, a reference to current row is a + stored result address and current data cursor position. + As we keep all RS in memory during a query execution, + we can get any record using the reference any time until + @c ha_federated::reset() is called. + TODO: we don't have to store all RS's rows but only those + we call @c ha_federated::position() for, so we can free memory + where we store other rows in the @c ha_federated::index_end(). + + @param[in] record record data (unused) */ -void ha_federated::position(const uchar *record) +void ha_federated::position(const uchar *record __attribute__ ((unused))) { DBUG_ENTER("ha_federated::position"); - if (table->s->primary_key != MAX_KEY) - key_copy(ref, (uchar *)record, table->key_info + table->s->primary_key, - ref_length); - else - memcpy(ref, record, ref_length); + + DBUG_ASSERT(stored_result); + + position_called= TRUE; + /* Store result set address. */ + memcpy_fixed(ref, &stored_result, sizeof(MYSQL_RES *)); + /* Store data cursor position. */ + memcpy_fixed(ref + sizeof(MYSQL_RES *), ¤t_position, + sizeof(MYSQL_ROW_OFFSET)); DBUG_VOID_RETURN; } @@ -2749,26 +2741,24 @@ void ha_federated::position(const uchar *record) int ha_federated::rnd_pos(uchar *buf, uchar *pos) { - int result; + MYSQL_RES *result; + int ret_val; DBUG_ENTER("ha_federated::rnd_pos"); + MYSQL_READ_ROW_START(table_share->db.str, table_share->table_name.str, FALSE); ha_statistic_increment(&SSV::ha_read_rnd_count); - if (table->s->primary_key != MAX_KEY) - { - /* We have a primary key, so use index_read_idx to find row */ - result= index_read_idx(buf, table->s->primary_key, pos, - ref_length, HA_READ_KEY_EXACT); - } - else - { - /* otherwise, get the old record ref as obtained in ::position */ - memcpy(buf, pos, ref_length); - result= 0; - } - table->status= result ? STATUS_NOT_FOUND : 0; - MYSQL_READ_ROW_DONE(result); - DBUG_RETURN(result); + + /* Get stored result set. */ + memcpy_fixed(&result, pos, sizeof(MYSQL_RES *)); + DBUG_ASSERT(result); + /* Set data cursor position. */ + memcpy_fixed(&result->data_cursor, pos + sizeof(MYSQL_RES *), + sizeof(MYSQL_ROW_OFFSET)); + /* Read a row. */ + ret_val= read_next(buf, result); + MYSQL_READ_ROW_DONE(ret_val); + DBUG_RETURN(ret_val); } @@ -2971,6 +2961,16 @@ int ha_federated::reset(void) insert_dup_update= FALSE; ignore_duplicates= FALSE; replace_duplicates= FALSE; + + /* Free stored result sets. */ + for (uint i= 0; i < results.elements; i++) + { + MYSQL_RES *result; + get_dynamic(&results, (uchar *) &result, i); + mysql_free_result(result); + } + reset_dynamic(&results); + return 0; } @@ -3234,6 +3234,45 @@ bool ha_federated::get_error_message(int error, String* buf) DBUG_RETURN(FALSE); } + +/** + @brief Store a result set. + + @details Call @c mysql_store_result() to save a result set then + append it to the stored results array. + + @param[in] mysql MySLQ connection structure. + + @return Stored result set (MYSQL_RES object). +*/ + +MYSQL_RES *ha_federated::store_result(MYSQL *mysql) +{ + MYSQL_RES *result= mysql_store_result(mysql); + DBUG_ENTER("ha_federated::store_result"); + if (result) + { + (void) insert_dynamic(&results, (uchar*) &result); + } + position_called= FALSE; + DBUG_RETURN(result); +} + + +void ha_federated::free_result() +{ + DBUG_ENTER("ha_federated::free_result"); + if (stored_result && !position_called) + { + mysql_free_result(stored_result); + stored_result= 0; + if (results.elements > 0) + results.elements--; + } + DBUG_VOID_RETURN; +} + + int ha_federated::external_lock(THD *thd, int lock_type) { int error= 0; diff --git a/storage/federated/ha_federated.h b/storage/federated/ha_federated.h index ea0a3d2f591..9740485854f 100644 --- a/storage/federated/ha_federated.h +++ b/storage/federated/ha_federated.h @@ -84,6 +84,11 @@ class ha_federated: public handler FEDERATED_SHARE *share; /* Shared lock info */ MYSQL *mysql; /* MySQL connection */ MYSQL_RES *stored_result; + /** + Array of all stored results we get during a query execution. + */ + DYNAMIC_ARRAY results; + bool position_called; uint fetch_num; // stores the fetch num MYSQL_ROW_OFFSET current_position; // Current position used by ::position() int remote_error_number; @@ -252,6 +257,10 @@ public: THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to, enum thr_lock_type lock_type); //required bool get_error_message(int error, String *buf); + + MYSQL_RES *store_result(MYSQL *mysql); + void free_result(); + int external_lock(THD *thd, int lock_type); int connection_commit(); int connection_rollback(); |