55 #include "sql_handler.h"
62 #include "transaction.h"
63 #include "sql_parse.h"
65 #define HANDLER_TABLES_HASH_SIZE 120
67 static enum enum_ha_read_modes rkey_to_rnext[]=
68 { RNEXT_SAME, RNEXT, RPREV, RNEXT, RPREV, RNEXT, RPREV, RPREV };
91 static char *mysql_ha_hash_get_key(
TABLE_LIST *tables,
size_t *key_len_p,
92 my_bool first __attribute__((unused)))
94 *key_len_p= strlen(tables->alias) + 1 ;
113 static void mysql_ha_hash_free(
TABLE_LIST *tables)
129 static void mysql_ha_close_table(THD *thd,
TABLE_LIST *tables)
132 if (tables->table && !tables->table->s->tmp_table)
135 tables->table->file->ha_index_or_rnd_end();
136 tables->table->open_by_handler= 0;
137 close_thread_table(thd, &tables->table);
138 thd->mdl_context.release_lock(tables->mdl_request.
ticket);
140 else if (tables->table)
144 table->file->ha_index_or_rnd_end();
145 table->query_id= thd->query_id;
146 table->open_by_handler= 0;
153 tables->mdl_request.
ticket= NULL;
169 char *db, *
name, *alias;
170 uint dblen, namelen, aliaslen;
172 DBUG_ENTER(
"Sql_cmd_handler_open::execute");
173 DBUG_PRINT(
"enter",(
"'%s'.'%s' as '%s'",
174 tables->db, tables->table_name, tables->alias));
176 if (thd->locked_tables_mode)
178 my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0));
181 if (tables->schema_table)
183 my_error(ER_WRONG_USAGE, MYF(0),
"HANDLER OPEN",
184 INFORMATION_SCHEMA_NAME.str);
185 DBUG_PRINT(
"exit",(
"ERROR"));
189 if (! my_hash_inited(&thd->handler_tables_hash))
194 if (my_hash_init(&thd->handler_tables_hash, &my_charset_latin1,
195 HANDLER_TABLES_HASH_SIZE, 0, 0,
196 (my_hash_get_key) mysql_ha_hash_get_key,
197 (my_hash_free_key) mysql_ha_hash_free, 0))
199 DBUG_PRINT(
"exit",(
"ERROR"));
212 if (my_hash_search(&thd->handler_tables_hash, (uchar*) tables->alias,
213 strlen(tables->alias) + 1))
215 DBUG_PRINT(
"info",(
"duplicate '%s'", tables->alias));
216 DBUG_PRINT(
"exit",(
"ERROR"));
217 my_error(ER_NONUNIQ_TABLE, MYF(0), tables->alias);
223 dblen= strlen(tables->db) + 1;
224 namelen= strlen(tables->table_name) + 1;
225 aliaslen= strlen(tables->alias) + 1;
226 if (!(my_multi_malloc(MYF(MY_WME),
227 &hash_tables, (uint)
sizeof(*hash_tables),
229 &name, (uint) namelen,
230 &alias, (uint) aliaslen,
233 DBUG_PRINT(
"exit",(
"ERROR"));
237 *hash_tables= *tables;
239 hash_tables->table_name=
name;
240 hash_tables->alias= alias;
241 memcpy(hash_tables->db, tables->db, dblen);
242 memcpy(hash_tables->table_name, tables->table_name, namelen);
243 memcpy(hash_tables->alias, tables->alias, aliaslen);
249 hash_tables->mdl_request.
init(MDL_key::TABLE, db, name, MDL_SHARED,
252 hash_tables->required_type= FRMTYPE_TABLE;
255 if (my_hash_insert(&thd->handler_tables_hash, (uchar*) hash_tables))
257 my_free(hash_tables);
258 DBUG_PRINT(
"exit",(
"ERROR"));
265 mysql_ha_open_table(thd, hash_tables))
268 my_hash_delete(&thd->handler_tables_hash, (uchar*) hash_tables);
269 DBUG_PRINT(
"exit",(
"ERROR"));
275 DBUG_PRINT(
"exit",(
"OK"));
290 static bool mysql_ha_open_table(THD *thd,
TABLE_LIST *hash_tables)
292 TABLE *backup_open_tables;
297 DBUG_ENTER(
"mysql_ha_open_table");
299 DBUG_ASSERT(!thd->locked_tables_mode);
309 backup_open_tables= thd->open_tables;
310 thd->set_open_tables(NULL);
311 mdl_savepoint= thd->mdl_context.mdl_savepoint();
317 DBUG_ASSERT(! hash_tables->table || is_temporary_table(hash_tables));
319 error=
open_tables(thd, &hash_tables, &counter, 0);
322 ! (hash_tables->table->file->
ha_table_flags() & HA_CAN_SQL_HANDLER))
324 my_error(ER_ILLEGAL_HA, MYF(0), hash_tables->alias);
328 hash_tables->mdl_request.
ticket &&
329 thd->mdl_context.has_lock(mdl_savepoint,
330 hash_tables->mdl_request.
ticket))
333 error= thd->mdl_context.clone_ticket(&hash_tables->mdl_request);
334 hash_tables->table->mdl_ticket= hash_tables->mdl_request.
ticket;
343 DBUG_ASSERT(thd->transaction.stmt.is_empty());
344 close_thread_tables(thd);
345 thd->mdl_context.rollback_to_savepoint(mdl_savepoint);
346 thd->set_open_tables(backup_open_tables);
347 hash_tables->table= NULL;
349 hash_tables->mdl_request.
ticket= NULL;
350 DBUG_PRINT(
"exit",(
"ERROR"));
353 thd->set_open_tables(backup_open_tables);
354 if (hash_tables->mdl_request.
ticket)
356 thd->mdl_context.set_lock_duration(hash_tables->mdl_request.
ticket,
358 thd->mdl_context.set_needs_thr_lock_abort(TRUE);
367 DBUG_ASSERT(hash_tables->table->next == NULL ||
368 hash_tables->table->s->tmp_table);
374 hash_tables->table->open_by_handler= 1;
376 DBUG_PRINT(
"exit",(
"OK"));
397 DBUG_ENTER(
"Sql_cmd_handler_close::execute");
398 DBUG_PRINT(
"enter",(
"'%s'.'%s' as '%s'",
399 tables->db, tables->table_name, tables->alias));
401 if (thd->locked_tables_mode)
403 my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0));
406 if ((hash_tables= (
TABLE_LIST*) my_hash_search(&thd->handler_tables_hash,
407 (uchar*) tables->alias,
408 strlen(tables->alias) + 1)))
410 mysql_ha_close_table(thd, hash_tables);
411 my_hash_delete(&thd->handler_tables_hash, (uchar*) hash_tables);
415 my_error(ER_UNKNOWN_TABLE, MYF(0), tables->alias,
"HANDLER");
416 DBUG_PRINT(
"exit",(
"ERROR"));
424 if (! thd->handler_tables_hash.records)
425 thd->mdl_context.set_needs_thr_lock_abort(FALSE);
428 DBUG_PRINT(
"exit", (
"OK"));
449 const char *sqlstate,
450 Sql_condition::enum_warning_level
level,
454 bool need_reopen()
const {
return m_need_reopen; };
455 void init() { m_need_reopen= FALSE; };
470 const char *sqlstate,
471 Sql_condition::enum_warning_level
level,
476 if (sql_errno == ER_LOCK_ABORTED)
479 return m_need_reopen;
502 char buff[MAX_FIELD_WIDTH];
503 String buffer(buff,
sizeof(buff), system_charset_info);
504 int error, keyno= -1;
506 uchar *UNINIT_VAR(key);
507 uint UNINIT_VAR(key_len);
510 SELECT_LEX *select_lex= &lex->select_lex;
511 SELECT_LEX_UNIT *unit= &lex->unit;
512 TABLE_LIST *tables= select_lex->table_list.first;
513 enum enum_ha_read_modes
mode= m_read_mode;
514 Item *cond= select_lex->where;
515 ha_rows select_limit_cnt, offset_limit_cnt;
516 DBUG_ENTER(
"Sql_cmd_handler_read::execute");
517 DBUG_PRINT(
"enter",(
"'%s'.'%s' as '%s'",
518 tables->db, tables->table_name, tables->alias));
520 if (thd->locked_tables_mode)
522 my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0));
527 enum xa_states xa_state= thd->transaction.xid_state.xa_state;
528 if (tables && (xa_state == XA_IDLE || xa_state == XA_PREPARED))
530 my_error(ER_XAER_RMFAIL, MYF(0), xa_state_names[xa_state]);
541 unit->set_limit(select_lex);
542 select_limit_cnt= unit->select_limit_cnt;
543 offset_limit_cnt= unit->offset_limit_cnt;
545 select_lex->context.resolve_in_table_list_only(tables);
546 list.push_front(
new Item_field(&select_lex->context,
552 if ((hash_tables= (
TABLE_LIST*) my_hash_search(&thd->handler_tables_hash,
553 (uchar*) tables->alias,
554 strlen(tables->alias) + 1)))
556 table= hash_tables->table;
557 DBUG_PRINT(
"info-in-hash",(
"'%s'.'%s' as '%s' table: 0x%lx",
558 hash_tables->db, hash_tables->table_name,
559 hash_tables->alias, (
long) table));
565 if (mysql_ha_open_table(thd, hash_tables))
567 DBUG_PRINT(
"exit",(
"reopen failed"));
571 table= hash_tables->table;
572 DBUG_PRINT(
"info",(
"re-opened '%s'.'%s' as '%s' tab %p",
573 hash_tables->db, hash_tables->table_name,
574 hash_tables->alias, table));
582 my_error(ER_UNKNOWN_TABLE, MYF(0), tables->alias,
"HANDLER");
587 backup_open_tables= thd->open_tables;
589 DBUG_ASSERT(hash_tables->table->next == NULL ||
590 hash_tables->table->s->tmp_table);
595 thd->set_open_tables(hash_tables->table);
598 sql_handler_lock_error.init();
599 thd->push_internal_handler(&sql_handler_lock_error);
603 thd->pop_internal_handler();
609 DBUG_ASSERT(hash_tables->table == thd->open_tables);
611 thd->set_open_tables(backup_open_tables);
613 if (sql_handler_lock_error.need_reopen())
615 DBUG_ASSERT(!lock && !thd->is_error());
622 DBUG_ASSERT(! thd->transaction_rollback_request);
623 trans_rollback_stmt(thd);
624 mysql_ha_close_table(thd, hash_tables);
632 hash_tables->table->read_set= &hash_tables->table->s->all_set;
633 tables->table= hash_tables->table;
637 if (table->query_id != thd->query_id)
640 cond->fix_fields(thd, &cond)) || cond->check_cols(1))
646 keyno= find_type((
char*) m_key_name,
648 FIND_TYPE_NO_PREFIX) - 1;
651 my_error(ER_KEY_DOES_NOT_EXITS, MYF(0), m_key_name, tables->alias);
655 if ((uint) keyno != table->file->get_index())
659 else if (mode == RPREV)
664 if (insert_fields(thd, &select_lex->context,
665 tables->db, tables->alias, &it, 0))
676 table->file->init_table_handle_for_HANDLER();
678 for (num_rows=0; num_rows < select_limit_cnt; )
684 if (table->file->inited == handler::INDEX)
687 DBUG_ASSERT((uint) keyno == table->file->get_index());
692 else if (table->file->inited == handler::RND)
706 if (!(error= table->file->ha_index_or_rnd_end()) &&
712 if (!(error= table->file->ha_index_or_rnd_end()) &&
719 DBUG_ASSERT(m_key_name != 0);
721 DBUG_ASSERT((uint) keyno == table->file->get_index());
722 if (table->file->inited == handler::INDEX)
729 DBUG_ASSERT(m_key_name != 0);
730 if (!(error= table->file->ha_index_or_rnd_end()) &&
737 DBUG_ASSERT(table->file->inited == handler::INDEX);
742 DBUG_ASSERT(m_key_name != 0);
743 KEY *keyinfo=table->key_info+keyno;
752 key_part_map keypart_map;
753 for (keypart_map= key_len=0 ; (item=it_ke++) ; key_part++)
755 my_bitmap_map *old_map;
758 item->fix_fields(thd, it_ke.ref())) ||
759 (item= *it_ke.ref())->check_cols(1))
761 if (item->used_tables() & ~RAND_TABLE_BIT)
763 my_error(ER_WRONG_ARGUMENTS,MYF(0),
"HANDLER ... READ");
766 old_map= dbug_tmp_use_all_columns(table, table->write_set);
768 dbug_tmp_restore_column_map(table->write_set, old_map);
769 key_len+=key_part->store_length;
770 keypart_map= (keypart_map << 1) | 1;
773 if (!(key= (uchar*) thd->calloc(ALIGN_SIZE(key_len))))
775 if ((error= table->file->ha_index_or_rnd_end()))
777 key_copy(key, table->record[0], table->key_info + keyno, key_len);
780 key, keypart_map, m_rkey_mode);
781 mode=rkey_to_rnext[(int)m_rkey_mode];
785 my_message(ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA), MYF(0));
791 if (error == HA_ERR_RECORD_DELETED)
793 if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
795 sql_print_error(
"mysql_ha_read: Got error %d when reading table '%s'",
796 error, tables->table_name);
802 if (cond && !cond->val_int())
808 if (num_rows >= offset_limit_cnt)
810 protocol->prepare_for_resend();
824 trans_commit_stmt(thd);
825 mysql_unlock_tables(thd,lock);
827 DBUG_PRINT(
"exit",(
"OK"));
831 trans_rollback_stmt(thd);
832 mysql_unlock_tables(thd,lock);
834 DBUG_PRINT(
"exit",(
"ERROR"));
852 TABLE_LIST *hash_tables, *head= NULL, *first= tables;
853 DBUG_ENTER(
"mysql_ha_find");
856 for (uint
i= 0;
i < thd->handler_tables_hash.records;
i++)
858 hash_tables= (
TABLE_LIST*) my_hash_element(&thd->handler_tables_hash,
i);
859 for (tables= first; tables; tables= tables->next_local)
864 ! my_strcasecmp(&my_charset_latin1,
867 ! my_strcasecmp(&my_charset_latin1,
874 hash_tables->next_local= head;
892 void mysql_ha_rm_tables(THD *thd,
TABLE_LIST *tables)
895 DBUG_ENTER(
"mysql_ha_rm_tables");
899 hash_tables= mysql_ha_find(thd, tables);
903 next= hash_tables->next_local;
904 if (hash_tables->table)
905 mysql_ha_close_table(thd, hash_tables);
906 my_hash_delete(&thd->handler_tables_hash, (uchar*) hash_tables);
914 if (! thd->handler_tables_hash.records)
915 thd->mdl_context.set_needs_thr_lock_abort(FALSE);
928 void mysql_ha_flush_tables(THD *thd,
TABLE_LIST *all_tables)
930 DBUG_ENTER(
"mysql_ha_flush_tables");
932 for (
TABLE_LIST *table_list= all_tables; table_list;
933 table_list= table_list->next_global)
935 TABLE_LIST *hash_tables= mysql_ha_find(thd, table_list);
939 TABLE_LIST *next_local= hash_tables->next_local;
940 if (hash_tables->table)
941 mysql_ha_close_table(thd, hash_tables);
942 hash_tables= next_local;
959 void mysql_ha_flush(THD *thd)
962 DBUG_ENTER(
"mysql_ha_flush");
971 if (thd->state_flags & Open_tables_state::BACKUPS_AVAIL)
974 for (uint
i= 0;
i < thd->handler_tables_hash.records;
i++)
976 hash_tables= (
TABLE_LIST*) my_hash_element(&thd->handler_tables_hash,
i);
980 if (hash_tables->table &&
981 ((hash_tables->table->mdl_ticket &&
983 (!hash_tables->table->s->tmp_table &&
985 mysql_ha_close_table(thd, hash_tables);
1000 void mysql_ha_cleanup(THD *thd)
1003 DBUG_ENTER(
"mysql_ha_cleanup");
1005 for (uint
i= 0;
i < thd->handler_tables_hash.records;
i++)
1007 hash_tables= (
TABLE_LIST*) my_hash_element(&thd->handler_tables_hash,
i);
1008 if (hash_tables->table)
1009 mysql_ha_close_table(thd, hash_tables);
1012 my_hash_free(&thd->handler_tables_hash);
1025 void mysql_ha_set_explicit_lock_duration(THD *thd)
1028 DBUG_ENTER(
"mysql_ha_set_explicit_lock_duration");
1030 for (uint
i= 0;
i < thd->handler_tables_hash.records;
i++)
1032 hash_tables= (
TABLE_LIST*) my_hash_element(&thd->handler_tables_hash,
i);
1033 if (hash_tables->table && hash_tables->table->mdl_ticket)
1034 thd->mdl_context.set_lock_duration(hash_tables->table->mdl_ticket,