diff options
Diffstat (limited to 'sql/sql_class.cc')
-rw-r--r-- | sql/sql_class.cc | 234 |
1 files changed, 172 insertions, 62 deletions
diff --git a/sql/sql_class.cc b/sql/sql_class.cc index d8d4b9a8d64..a0d2924009f 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2000, 2015, Oracle and/or its affiliates. - Copyright (c) 2008, 2019, MariaDB Corporation. + Copyright (c) 2008, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -129,6 +129,39 @@ bool Key_part_spec::operator==(const Key_part_spec& other) const &other.field_name); } + +bool Key_part_spec::check_key_for_blob(const handler *file) const +{ + if (!(file->ha_table_flags() & HA_CAN_INDEX_BLOBS)) + { + my_error(ER_BLOB_USED_AS_KEY, MYF(0), field_name.str, file->table_type()); + return true; + } + return false; +} + + +bool Key_part_spec::check_key_length_for_blob() const +{ + if (!length) + { + my_error(ER_BLOB_KEY_WITHOUT_LENGTH, MYF(0), field_name.str); + return true; + } + return false; +} + + +bool Key_part_spec::init_multiple_key_for_blob(const handler *file) +{ + if (check_key_for_blob(file)) + return true; + if (!length) + length= file->max_key_length() + 1; + return false; +} + + /** Construct an (almost) deep copy of this key. Only those elements that are known to never change are not copied. @@ -156,6 +189,7 @@ Key::Key(const Key &rhs, MEM_ROOT *mem_root) Foreign_key::Foreign_key(const Foreign_key &rhs, MEM_ROOT *mem_root) :Key(rhs,mem_root), + constraint_name(rhs.constraint_name), ref_db(rhs.ref_db), ref_table(rhs.ref_table), ref_columns(rhs.ref_columns,mem_root), @@ -420,12 +454,6 @@ void thd_exit_cond(MYSQL_THD thd, const PSI_stage_info *stage, } extern "C" -void **thd_ha_data(const THD *thd, const struct handlerton *hton) -{ - return (void **) &thd->ha_data[hton->slot].ha_ptr; -} - -extern "C" void thd_storage_lock_wait(THD *thd, long long value) { thd->utime_after_lock+= value; @@ -437,7 +465,7 @@ void thd_storage_lock_wait(THD *thd, long long value) extern "C" void *thd_get_ha_data(const THD *thd, const struct handlerton *hton) { - return *thd_ha_data(thd, hton); + return thd->ha_data[hton->slot].ha_ptr; } @@ -450,6 +478,7 @@ void thd_set_ha_data(THD *thd, const struct handlerton *hton, const void *ha_data) { plugin_ref *lock= &thd->ha_data[hton->slot].lock; + thd->ha_data[hton->slot].ha_ptr= const_cast<void*>(ha_data); if (ha_data && !*lock) *lock= ha_lock_engine(NULL, (handlerton*) hton); else if (!ha_data && *lock) @@ -457,7 +486,6 @@ void thd_set_ha_data(THD *thd, const struct handlerton *hton, plugin_unlock(NULL, *lock); *lock= NULL; } - *thd_ha_data(thd, hton)= (void*) ha_data; } @@ -669,9 +697,10 @@ THD::THD(my_thread_id id, bool is_wsrep_applier) wsrep_apply_format(0), wsrep_rbr_buf(NULL), wsrep_sync_wait_gtid(WSREP_GTID_UNDEFINED), + wsrep_last_written_gtid_seqno(0), + wsrep_current_gtid_seqno(0), wsrep_affected_rows(0), wsrep_has_ignored_error(false), - wsrep_replicate_GTID(false), wsrep_ignore_table(false), /* wsrep-lib */ @@ -728,7 +757,6 @@ THD::THD(my_thread_id id, bool is_wsrep_applier) event_scheduler.data= 0; event_scheduler.m_psi= 0; skip_wait_timeout= false; - extra_port= 0; catalog= (char*)"std"; // the only catalog we have for now main_security_ctx.init(); security_ctx= &main_security_ctx; @@ -1286,7 +1314,6 @@ void THD::init() wsrep_rbr_buf = NULL; wsrep_affected_rows = 0; m_wsrep_next_trx_id = WSREP_UNDEFINED_TRX_ID; - wsrep_replicate_GTID = false; #endif /* WITH_WSREP */ if (variables.sql_log_bin) @@ -1310,6 +1337,7 @@ void THD::init() #endif //EMBEDDED_LIBRARY apc_target.init(&LOCK_thd_kill); + gap_tracker_data.init(); DBUG_VOID_RETURN; } @@ -1723,6 +1751,7 @@ THD::~THD() /* trick to make happy memory accounting system */ #ifndef EMBEDDED_LIBRARY session_tracker.sysvars.deinit(); + session_tracker.user_variables.deinit(); #endif //EMBEDDED_LIBRARY if (status_var.local_memory_used != 0) @@ -2523,8 +2552,7 @@ THD::make_string_literal_charset(const Lex_string_with_metadata_st &str, { if (!str.length && (variables.sql_mode & MODE_EMPTY_STRING_IS_NULL)) return new (mem_root) Item_null(this, 0, cs); - return new (mem_root) Item_string_with_introducer(this, - str.str, (uint)str.length, cs); + return new (mem_root) Item_string_with_introducer(this, str, cs); } @@ -2989,15 +3017,6 @@ int select_send::send_data(List<Item> &items) Protocol *protocol= thd->protocol; DBUG_ENTER("select_send::send_data"); - /* unit is not set when using 'delete ... returning' */ - if (unit && unit->offset_limit_cnt) - { // using limit offset,count - unit->offset_limit_cnt--; - DBUG_RETURN(FALSE); - } - if (thd->killed == ABORT_QUERY) - DBUG_RETURN(FALSE); - protocol->prepare_for_resend(); if (protocol->send_result_set_row(&items)) { @@ -3259,13 +3278,6 @@ int select_export::send_data(List<Item> &items) String tmp(buff,sizeof(buff),&my_charset_bin),*res; tmp.length(0); - if (unit->offset_limit_cnt) - { // using limit offset,count - unit->offset_limit_cnt--; - DBUG_RETURN(0); - } - if (thd->killed == ABORT_QUERY) - DBUG_RETURN(0); row_count++; Item *item; uint used_length=0,items_left=items.elements; @@ -3383,7 +3395,7 @@ int select_export::send_data(List<Item> &items) pos++) { #ifdef USE_MB - if (use_mb(res_charset)) + if (res_charset->use_mb()) { int l; if ((l=my_ismbchar(res_charset, pos, end))) @@ -3519,14 +3531,6 @@ int select_dump::send_data(List<Item> &items) Item *item; DBUG_ENTER("select_dump::send_data"); - if (unit->offset_limit_cnt) - { // using limit offset,count - unit->offset_limit_cnt--; - DBUG_RETURN(0); - } - if (thd->killed == ABORT_QUERY) - DBUG_RETURN(0); - if (row_count++ > 1) { my_message(ER_TOO_MANY_ROWS, ER_THD(thd, ER_TOO_MANY_ROWS), MYF(0)); @@ -3562,13 +3566,6 @@ int select_singlerow_subselect::send_data(List<Item> &items) MYF(current_thd->lex->ignore ? ME_WARNING : 0)); DBUG_RETURN(1); } - if (unit->offset_limit_cnt) - { // Using limit offset,count - unit->offset_limit_cnt--; - DBUG_RETURN(0); - } - if (thd->killed == ABORT_QUERY) - DBUG_RETURN(0); List_iterator_fast<Item> li(items); Item *val_item; for (uint i= 0; (val_item= li++); i++) @@ -3703,13 +3700,6 @@ int select_exists_subselect::send_data(List<Item> &items) { DBUG_ENTER("select_exists_subselect::send_data"); Item_exists_subselect *it= (Item_exists_subselect *)item; - if (unit->offset_limit_cnt) - { // Using limit offset,count - unit->offset_limit_cnt--; - DBUG_RETURN(0); - } - if (thd->killed == ABORT_QUERY) - DBUG_RETURN(0); it->value= 1; it->assigned(1); DBUG_RETURN(0); @@ -4112,12 +4102,7 @@ int select_dumpvar::send_data(List<Item> &items) { DBUG_ENTER("select_dumpvar::send_data"); - if (unit->offset_limit_cnt) - { // using limit offset,count - unit->offset_limit_cnt--; - DBUG_RETURN(0); - } - if (row_count++) + if (row_count++) { my_message(ER_TOO_MANY_ROWS, ER_THD(thd, ER_TOO_MANY_ROWS), MYF(0)); DBUG_RETURN(1); @@ -4767,6 +4752,12 @@ TABLE *open_purge_table(THD *thd, const char *db, size_t dblen, DBUG_RETURN(error ? NULL : tl->table); } +TABLE *get_purge_table(THD *thd) +{ + /* see above, at most one table can be opened */ + DBUG_ASSERT(thd->open_tables == NULL || thd->open_tables->next == NULL); + return thd->open_tables; +} /** Find an open table in the list of prelocked tabled @@ -4810,6 +4801,114 @@ void destroy_thd(MYSQL_THD thd) delete thd; } +/** + Create a THD that only has auxilliary functions + It will never be added to the global connection list + server_threads. It does not represent any client connection. + + It should never be counted, because it will stall the + shutdown. It is solely for engine's internal use, + like for example, evaluation of virtual function in innodb + purge. +*/ +extern "C" pthread_key(struct st_my_thread_var *, THR_KEY_mysys); +MYSQL_THD create_background_thd() +{ + DBUG_ASSERT(!current_thd); + auto save_mysysvar= pthread_getspecific(THR_KEY_mysys); + + /* + Allocate new mysys_var specifically this THD, + so that e.g safemalloc, DBUG etc are happy. + */ + pthread_setspecific(THR_KEY_mysys, 0); + my_thread_init(); + auto thd_mysysvar= pthread_getspecific(THR_KEY_mysys); + auto thd= new THD(0); + pthread_setspecific(THR_KEY_mysys, save_mysysvar); + + /* + Workaround the adverse effect of incrementing thread_count + in THD constructor. We do not want these THDs to be counted, + or waited for on shutdown. + */ + thread_count--; + + thd->mysys_var= (st_my_thread_var *) thd_mysysvar; + thd->set_command(COM_DAEMON); + thd->system_thread= SYSTEM_THREAD_GENERIC; + thd->security_ctx->host_or_ip= ""; + return thd; +} + + +/* + Attach a background THD. + + Changes current value THR_KEY_mysys TLS variable, + and returns the original value. +*/ +void *thd_attach_thd(MYSQL_THD thd) +{ + DBUG_ASSERT(!current_thd); + DBUG_ASSERT(thd && thd->mysys_var); + + auto save_mysysvar= pthread_getspecific(THR_KEY_mysys); + pthread_setspecific(THR_KEY_mysys, thd->mysys_var); + thd->thread_stack= (char *) &thd; + thd->store_globals(); + return save_mysysvar; +} + +/* + Restore THR_KEY_mysys TLS variable, + which was changed thd_attach_thd(). +*/ +void thd_detach_thd(void *mysysvar) +{ + /* Restore mysys_var that is changed when THD was attached.*/ + pthread_setspecific(THR_KEY_mysys, mysysvar); + /* Restore the THD (we assume it was NULL during attach).*/ + set_current_thd(0); +} + +/* + Destroy a THD that was previously created by + create_background_thd() +*/ +void destroy_background_thd(MYSQL_THD thd) +{ + DBUG_ASSERT(!current_thd); + auto thd_mysys_var= thd->mysys_var; + auto save_mysys_var= thd_attach_thd(thd); + DBUG_ASSERT(thd_mysys_var != save_mysys_var); + /* + Workaround the adverse effect decrementing thread_count on THD() + destructor. + As we decremented it in create_background_thd(), in order for it + not to go negative, we have to increment it before destructor. + */ + thread_count++; + delete thd; + + thd_detach_thd(save_mysys_var); + /* + Delete THD-specific my_thread_var, that was + allocated in create_background_thd(). + Also preserve current PSI context, since my_thread_end() + would kill it, if we're not careful. + */ +#ifdef HAVE_PSI_THREAD_INTERFACE + auto save_psi_thread= PSI_CALL_get_thread(); +#endif + PSI_CALL_set_thread(0); + pthread_setspecific(THR_KEY_mysys, thd_mysys_var); + my_thread_end(); + pthread_setspecific(THR_KEY_mysys, save_mysys_var); + PSI_CALL_set_thread(save_psi_thread); +} + + void reset_thd(MYSQL_THD thd) { close_thread_tables(thd); @@ -5210,6 +5309,18 @@ extern "C" void thd_wait_end(MYSQL_THD thd) #endif // INNODB_COMPATIBILITY_HOOKS */ + +/** + MDL_context accessor + @param thd the current session + @return pointer to thd->mdl_context +*/ +extern "C" void *thd_mdl_context(MYSQL_THD thd) +{ + return &thd->mdl_context; +} + + /**************************************************************************** Handling of statement states in functions and triggers. @@ -7214,11 +7325,10 @@ void THD::set_last_commit_gtid(rpl_gtid >id) #endif m_last_commit_gtid= gtid; #ifndef EMBEDDED_LIBRARY - if (changed_gtid && session_tracker.sysvars.is_enabled()) + if (changed_gtid) { DBUG_ASSERT(current_thd == this); - session_tracker.sysvars. - mark_as_changed(this, (LEX_CSTRING*)Sys_last_gtid_ptr); + session_tracker.sysvars.mark_as_changed(this, Sys_last_gtid_ptr); } #endif } |