

Public Member Functions | |
| Sensitive_cursor (THD *thd, select_result *result_arg) | |
| THR_LOCK_OWNER * | get_lock_id () |
| void | post_open (THD *thd) |
| virtual bool | is_open () const |
| virtual int | open (JOIN *join) |
| virtual void | fetch (ulong num_rows) |
| virtual void | close () |
| virtual | ~Sensitive_cursor () |
Private Member Functions | |
| void | reset_thd (THD *thd) |
Private Attributes | |
| MEM_ROOT | main_mem_root |
| Query_arena * | stmt_arena |
| JOIN * | join |
| TABLE * | open_tables |
| MYSQL_LOCK * | lock |
| TABLE * | derived_tables |
| query_id_t | query_id |
| Engine_info | ht_info [MAX_HA] |
| Item_change_list | change_list |
| my_bool | close_at_commit |
| THR_LOCK_OWNER | lock_id |
Classes | |
| struct | Engine_info |
Definition at line 36 of file sql_cursor.cc.
| Sensitive_cursor::Sensitive_cursor | ( | THD * | thd, | |
| select_result * | result_arg | |||
| ) |
Definition at line 270 of file sql_cursor.cc.
References ALLOC_ROOT_MIN_BLOCK_SIZE, bzero, ht_info, init_sql_alloc(), lock_id, main_mem_root, and thr_lock_owner_init.
00271 :Server_side_cursor(&main_mem_root, result_arg), 00272 stmt_arena(0), 00273 join(0), 00274 close_at_commit(FALSE) 00275 { 00276 /* We will overwrite it at open anyway. */ 00277 init_sql_alloc(&main_mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0); 00278 thr_lock_owner_init(&lock_id, &thd->lock_info); 00279 bzero((void*) ht_info, sizeof(ht_info)); 00280 }
Here is the call graph for this function:

| Sensitive_cursor::~Sensitive_cursor | ( | ) | [virtual] |
| void Sensitive_cursor::close | ( | ) | [virtual] |
Implements Server_side_cursor.
Definition at line 483 of file sql_cursor.cc.
References change_list, DBUG_ASSERT, DBUG_ENTER, DBUG_VOID_RETURN, derived_tables, free_items(), ht_info, info, join, lock, open_tables, stmt_arena, and JOIN::thd.
Referenced by fetch(), and ~Sensitive_cursor().
00484 { 00485 THD *thd= join->thd; 00486 DBUG_ENTER("Sensitive_cursor::close"); 00487 00488 for (Engine_info *info= ht_info; info->read_view; info++) 00489 { 00490 (info->ht->close_cursor_read_view)(info->read_view); 00491 info->read_view= 0; 00492 info->ht= 0; 00493 } 00494 00495 thd->change_list= change_list; 00496 { 00497 /* 00498 XXX: Another hack: we need to set THD state as if in a fetch to be 00499 able to call stmt close. 00500 */ 00501 DBUG_ASSERT(lock || open_tables || derived_tables); 00502 00503 TABLE *tmp_derived_tables= thd->derived_tables; 00504 MYSQL_LOCK *tmp_lock= thd->lock; 00505 00506 thd->open_tables= open_tables; 00507 thd->derived_tables= derived_tables; 00508 thd->lock= lock; 00509 00510 /* Is expected to at least close tables and empty thd->change_list */ 00511 stmt_arena->cleanup_stmt(); 00512 00513 thd->open_tables= tmp_derived_tables; 00514 thd->derived_tables= tmp_derived_tables; 00515 thd->lock= tmp_lock; 00516 } 00517 thd->lock_info.n_cursors--; /* Decrease the number of active cursors */ 00518 join= 0; 00519 stmt_arena= 0; 00520 free_items(); 00521 change_list.empty(); 00522 DBUG_VOID_RETURN; 00523 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void Sensitive_cursor::fetch | ( | ulong | num_rows | ) | [virtual] |
Implements Server_side_cursor.
Definition at line 414 of file sql_cursor.cc.
References change_list, close(), JOIN::const_tables, DBUG_ASSERT, DBUG_ENTER, DBUG_PRINT, DBUG_VOID_RETURN, derived_tables, ER, ER_OUT_OF_RESOURCES, error, JOIN::fetch_limit, ha_release_temporary_latches(), Sensitive_cursor::Engine_info::ht, ht_info, info, join, JOIN::join_tab, lock, my_message(), MYF, NESTED_LOOP_CURSOR_LIMIT, NESTED_LOOP_KILLED, NESTED_LOOP_NO_MORE_ROWS, NESTED_LOOP_OK, NESTED_LOOP_QUERY_LIMIT, open_tables, query_id, Sensitive_cursor::Engine_info::read_view, reset_thd(), Server_side_cursor::result, JOIN::resume_nested_loop, SERVER_STATUS_CURSOR_EXISTS, SERVER_STATUS_LAST_ROW_SENT, handlerton::set_cursor_read_view, sub_select(), JOIN::thd, and TRUE.
00415 { 00416 THD *thd= join->thd; 00417 JOIN_TAB *join_tab= join->join_tab + join->const_tables; 00418 enum_nested_loop_state error= NESTED_LOOP_OK; 00419 Query_arena backup_arena; 00420 Engine_info *info; 00421 DBUG_ENTER("Sensitive_cursor::fetch"); 00422 DBUG_PRINT("enter",("rows: %lu", num_rows)); 00423 00424 DBUG_ASSERT(thd->derived_tables == 0 && thd->open_tables == 0 && 00425 thd->lock == 0); 00426 00427 thd->derived_tables= derived_tables; 00428 thd->open_tables= open_tables; 00429 thd->lock= lock; 00430 thd->query_id= query_id; 00431 thd->change_list= change_list; 00432 /* save references to memory allocated during fetch */ 00433 thd->set_n_backup_active_arena(this, &backup_arena); 00434 00435 for (info= ht_info; info->read_view ; info++) 00436 (info->ht->set_cursor_read_view)(info->read_view); 00437 00438 join->fetch_limit+= num_rows; 00439 00440 error= sub_select(join, join_tab, 0); 00441 if (error == NESTED_LOOP_OK || error == NESTED_LOOP_NO_MORE_ROWS) 00442 error= sub_select(join,join_tab,1); 00443 if (error == NESTED_LOOP_QUERY_LIMIT) 00444 error= NESTED_LOOP_OK; /* select_limit used */ 00445 if (error == NESTED_LOOP_CURSOR_LIMIT) 00446 join->resume_nested_loop= TRUE; 00447 00448 ha_release_temporary_latches(thd); 00449 00450 /* Grab free_list here to correctly free it in close */ 00451 thd->restore_active_arena(this, &backup_arena); 00452 00453 change_list= thd->change_list; 00454 reset_thd(thd); 00455 00456 for (info= ht_info; info->read_view; info++) 00457 (info->ht->set_cursor_read_view)(0); 00458 00459 if (error == NESTED_LOOP_CURSOR_LIMIT) 00460 { 00461 /* Fetch limit worked, possibly more rows are there */ 00462 thd->server_status|= SERVER_STATUS_CURSOR_EXISTS; 00463 result->send_eof(); 00464 thd->server_status&= ~SERVER_STATUS_CURSOR_EXISTS; 00465 } 00466 else 00467 { 00468 close(); 00469 if (error == NESTED_LOOP_OK) 00470 { 00471 thd->server_status|= SERVER_STATUS_LAST_ROW_SENT; 00472 result->send_eof(); 00473 thd->server_status&= ~SERVER_STATUS_LAST_ROW_SENT; 00474 } 00475 else if (error != NESTED_LOOP_KILLED) 00476 my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0)); 00477 } 00478 DBUG_VOID_RETURN; 00479 }
Here is the call graph for this function:

| THR_LOCK_OWNER* Sensitive_cursor::get_lock_id | ( | ) | [inline] |
Definition at line 61 of file sql_cursor.cc.
References lock_id.
Referenced by mysql_open_cursor().
00061 { return &lock_id; }
Here is the caller graph for this function:

| virtual bool Sensitive_cursor::is_open | ( | ) | const [inline, virtual] |
Implements Server_side_cursor.
Definition at line 65 of file sql_cursor.cc.
References join.
Referenced by mysql_open_cursor(), and ~Sensitive_cursor().
00065 { return join != 0; }
Here is the caller graph for this function:

| int Sensitive_cursor::open | ( | JOIN * | join | ) | [virtual] |
Implements Server_side_cursor.
Definition at line 350 of file sql_cursor.cc.
References JOIN::change_result(), JOIN::const_tables, DBUG_ASSERT, DBUG_ENTER, DBUG_RETURN, JOIN::fetch_limit, JOIN::fields, join, JOIN::join_tab, st_join_table::next_select, st_reginfo::not_exists_optimize, st_join_table::not_used_in_distinct, st_table::null_row, st_table::reginfo, Server_side_cursor::result, Protocol::SEND_NUM_ROWS, JOIN::send_records, SERVER_STATUS_CURSOR_EXISTS, setup_end_select_func(), sub_select(), sub_select_cache(), st_join_table::table, JOIN::tables, JOIN::thd, JOIN::tmp_table, and JOIN::unit.
00351 { 00352 join= join_arg; 00353 THD *thd= join->thd; 00354 /* First non-constant table */ 00355 JOIN_TAB *join_tab= join->join_tab + join->const_tables; 00356 DBUG_ENTER("Sensitive_cursor::open"); 00357 00358 join->change_result(result); 00359 /* 00360 Send fields description to the client; server_status is sent 00361 in 'EOF' packet, which follows send_fields(). 00362 We don't simply use SEND_EOF flag of send_fields because we also 00363 want to flush the network buffer, which is done only in a standalone 00364 send_eof(). 00365 */ 00366 result->send_fields(*join->fields, Protocol::SEND_NUM_ROWS); 00367 thd->server_status|= SERVER_STATUS_CURSOR_EXISTS; 00368 result->send_eof(); 00369 thd->server_status&= ~SERVER_STATUS_CURSOR_EXISTS; 00370 00371 /* Prepare JOIN for reading rows. */ 00372 join->tmp_table= 0; 00373 join->join_tab[join->tables-1].next_select= setup_end_select_func(join); 00374 join->send_records= 0; 00375 join->fetch_limit= join->unit->offset_limit_cnt; 00376 00377 /* Disable JOIN CACHE as it is not working with cursors yet */ 00378 for (JOIN_TAB *tab= join_tab; 00379 tab != join->join_tab + join->tables - 1; 00380 tab++) 00381 { 00382 if (tab->next_select == sub_select_cache) 00383 tab->next_select= sub_select; 00384 } 00385 00386 DBUG_ASSERT(join_tab->table->reginfo.not_exists_optimize == 0); 00387 DBUG_ASSERT(join_tab->not_used_in_distinct == 0); 00388 /* 00389 null_row is set only if row not found and it's outer join: should never 00390 happen for the first table in join_tab list 00391 */ 00392 DBUG_ASSERT(join_tab->table->null_row == 0); 00393 DBUG_RETURN(0); 00394 }
Here is the call graph for this function:

| void Sensitive_cursor::post_open | ( | THD * | thd | ) |
Definition at line 284 of file sql_cursor.cc.
References change_list, close_at_commit, derived_tables, FALSE, free_list(), Sensitive_cursor::Engine_info::ht, ht, ht_info, HTON_CLOSE_CURSORS_AT_COMMIT, info, init_sql_alloc(), lock, open_tables, query_id, Sensitive_cursor::Engine_info::read_view, reset_thd(), stmt_arena, and test.
Referenced by mysql_open_cursor().
00285 { 00286 Engine_info *info; 00287 /* 00288 We need to save and reset thd->mem_root, otherwise it'll be 00289 freed later in mysql_parse. 00290 00291 We can't just change thd->mem_root here as we want to keep the 00292 things that are already allocated in thd->mem_root for 00293 Sensitive_cursor::fetch() 00294 */ 00295 *mem_root= *thd->mem_root; 00296 stmt_arena= thd->stmt_arena; 00297 state= stmt_arena->state; 00298 /* Allocate a new memory root for thd */ 00299 init_sql_alloc(thd->mem_root, 00300 thd->variables.query_alloc_block_size, 00301 thd->variables.query_prealloc_size); 00302 00303 /* 00304 Save tables and zero THD pointers to prevent table close in 00305 close_thread_tables. 00306 */ 00307 derived_tables= thd->derived_tables; 00308 open_tables= thd->open_tables; 00309 lock= thd->lock; 00310 query_id= thd->query_id; 00311 free_list= thd->free_list; 00312 change_list= thd->change_list; 00313 reset_thd(thd); 00314 /* Now we have an active cursor and can cause a deadlock */ 00315 thd->lock_info.n_cursors++; 00316 00317 close_at_commit= FALSE; /* reset in case we're reusing the cursor */ 00318 info= &ht_info[0]; 00319 for (handlerton **pht= thd->transaction.stmt.ht; *pht; pht++) 00320 { 00321 const handlerton *ht= *pht; 00322 close_at_commit|= test(ht->flags & HTON_CLOSE_CURSORS_AT_COMMIT); 00323 if (ht->create_cursor_read_view) 00324 { 00325 info->ht= ht; 00326 info->read_view= (ht->create_cursor_read_view)(); 00327 ++info; 00328 } 00329 } 00330 /* 00331 XXX: thd->locked_tables is not changed. 00332 What problems can we have with it if cursor is open? 00333 TODO: must be fixed because of the prelocked mode. 00334 */ 00335 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void Sensitive_cursor::reset_thd | ( | THD * | thd | ) | [private] |
Definition at line 339 of file sql_cursor.cc.
Referenced by fetch(), and post_open().
00340 { 00341 thd->derived_tables= 0; 00342 thd->open_tables= 0; 00343 thd->lock= 0; 00344 thd->free_list= 0; 00345 thd->change_list.empty(); 00346 }
Here is the caller graph for this function:

Item_change_list Sensitive_cursor::change_list [private] |
my_bool Sensitive_cursor::close_at_commit [private] |
TABLE* Sensitive_cursor::derived_tables [private] |
Engine_info Sensitive_cursor::ht_info[MAX_HA] [private] |
Definition at line 51 of file sql_cursor.cc.
Referenced by close(), fetch(), post_open(), and Sensitive_cursor().
JOIN* Sensitive_cursor::join [private] |
MYSQL_LOCK* Sensitive_cursor::lock [private] |
THR_LOCK_OWNER Sensitive_cursor::lock_id [private] |
MEM_ROOT Sensitive_cursor::main_mem_root [private] |
TABLE* Sensitive_cursor::open_tables [private] |
query_id_t Sensitive_cursor::query_id [private] |
Query_arena* Sensitive_cursor::stmt_arena [private] |
1.4.7

