1 /*
2    Copyright (c) 2013, 2021, Oracle and/or its affiliates.
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License, version 2.0,
6    as published by the Free Software Foundation.
7 
8    This program is also distributed with certain software (including
9    but not limited to OpenSSL) that is licensed under separate terms,
10    as designated in a particular file or component or in included license
11    documentation.  The authors of MySQL hereby grant you an additional
12    permission to link the program and your derivative works with the
13    separately licensed software that they have included with MySQL.
14 
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License, version 2.0, for more details.
19 
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software Foundation,
22    51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
23 
24 #include "transaction_info.h"
25 #include "mysys_err.h"
26 #include "sql_class.h"
27 
Transaction_ctx()28 Transaction_ctx::Transaction_ctx()
29   : m_savepoints(NULL), m_xid_state(), m_changed_tables(NULL),
30     last_committed(0), sequence_number(0),
31     m_rpl_transaction_ctx(), m_transaction_write_set_ctx()
32 {
33   memset(&m_scope_info, 0, sizeof(m_scope_info));
34   memset(&m_flags, 0, sizeof(m_flags));
35   init_sql_alloc(key_memory_thd_transactions, &m_mem_root,
36                  global_system_variables.trans_alloc_block_size,
37                  global_system_variables.trans_prealloc_size);
38 }
39 
40 
push_unsafe_rollback_warnings(THD * thd)41 void Transaction_ctx::push_unsafe_rollback_warnings(THD *thd)
42 {
43   if (m_scope_info[SESSION].has_modified_non_trans_table())
44     push_warning(thd, Sql_condition::SL_WARNING,
45                  ER_WARNING_NOT_COMPLETE_ROLLBACK,
46                  ER(ER_WARNING_NOT_COMPLETE_ROLLBACK));
47 
48   if (m_scope_info[SESSION].has_created_temp_table())
49     push_warning(thd, Sql_condition::SL_WARNING,
50                  ER_WARNING_NOT_COMPLETE_ROLLBACK_WITH_CREATED_TEMP_TABLE,
51                  ER(ER_WARNING_NOT_COMPLETE_ROLLBACK_WITH_CREATED_TEMP_TABLE));
52 
53   if (m_scope_info[SESSION].has_dropped_temp_table())
54     push_warning(thd, Sql_condition::SL_WARNING,
55                  ER_WARNING_NOT_COMPLETE_ROLLBACK_WITH_DROPPED_TEMP_TABLE,
56                  ER(ER_WARNING_NOT_COMPLETE_ROLLBACK_WITH_DROPPED_TEMP_TABLE));
57 }
58 
59 
add_changed_table(const char * key,long key_length)60 bool Transaction_ctx::add_changed_table(const char *key, long key_length)
61 {
62   DBUG_ENTER("Transaction_ctx::add_changed_table");
63   CHANGED_TABLE_LIST **prev_changed = &m_changed_tables;
64   CHANGED_TABLE_LIST *curr = m_changed_tables;
65 
66   for (; curr; prev_changed = &(curr->next), curr = curr->next)
67   {
68     int cmp =  (long)curr->key_length - key_length;
69     if (cmp < 0)
70     {
71       if (list_include(prev_changed, curr,
72                        changed_table_dup(key, key_length)))
73         DBUG_RETURN(true);
74 
75       DBUG_PRINT("info",
76                  ("key_length: %ld  %u", key_length,
77                      (*prev_changed)->key_length));
78       DBUG_RETURN(false);
79     }
80     else if (cmp == 0)
81     {
82       cmp = memcmp(curr->key, key, curr->key_length);
83       if (cmp < 0)
84       {
85         if (list_include(prev_changed, curr, changed_table_dup(key, key_length)))
86           DBUG_RETURN(true);
87 
88         DBUG_PRINT("info",
89                    ("key_length:  %ld  %u", key_length,
90                        (*prev_changed)->key_length));
91         DBUG_RETURN(false);
92       }
93       else if (cmp == 0)
94       {
95         DBUG_PRINT("info", ("already in list"));
96         DBUG_RETURN(false);
97         DBUG_RETURN(false);
98       }
99     }
100   }
101   *prev_changed = changed_table_dup(key, key_length);
102   if (!(*prev_changed))
103     DBUG_RETURN(true);
104   DBUG_PRINT("info", ("key_length: %ld  %u", key_length,
105       (*prev_changed)->key_length));
106   DBUG_RETURN(false);
107 }
108 
109 
changed_table_dup(const char * key,long key_length)110 CHANGED_TABLE_LIST* Transaction_ctx::changed_table_dup(const char *key,
111                                                        long key_length)
112 {
113   CHANGED_TABLE_LIST* new_table =
114       (CHANGED_TABLE_LIST*) allocate_memory(
115           ALIGN_SIZE(sizeof(CHANGED_TABLE_LIST)) + key_length + 1);
116   if (!new_table)
117   {
118     my_error(EE_OUTOFMEMORY, MYF(ME_FATALERROR),
119              ALIGN_SIZE(sizeof(TABLE_LIST)) + key_length + 1);
120     return 0;
121   }
122 
123   new_table->key= ((char*)new_table)+ ALIGN_SIZE(sizeof(CHANGED_TABLE_LIST));
124   new_table->next = 0;
125   new_table->key_length = key_length;
126   ::memcpy(new_table->key, key, key_length);
127   return new_table;
128 }
129