1 /* Copyright (c) 2015, 2021, Oracle and/or its affiliates.
2 
3   This program is free software; you can redistribute it and/or modify
4   it under the terms of the GNU General Public License, version 2.0,
5   as published by the Free Software Foundation.
6 
7   This program is also distributed with certain software (including
8   but not limited to OpenSSL) that is licensed under separate terms,
9   as designated in a particular file or component or in included license
10   documentation.  The authors of MySQL hereby grant you an additional
11   permission to link the program and your derivative works with the
12   separately licensed software that they have included with MySQL.
13 
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License, version 2.0, for more details.
18 
19   You should have received a copy of the GNU General Public License
20   along with this program; if not, write to the Free Software
21   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
22 
23 /**
24   @file storage/perfschema/table_global_variables.cc
25   Table GLOBAL_VARIABLES (implementation).
26 */
27 
28 #include "my_global.h"
29 #include "table_global_variables.h"
30 #include "my_thread.h"
31 #include "pfs_instr_class.h"
32 #include "pfs_column_types.h"
33 #include "pfs_column_values.h"
34 #include "pfs_global.h"
35 
36 THR_LOCK table_global_variables::m_table_lock;
37 
38 PFS_engine_table_share
39 table_global_variables::m_share=
40 {
41   { C_STRING_WITH_LEN("global_variables") },
42   &pfs_readonly_world_acl,
43   table_global_variables::create,
44   NULL, /* write_row */
45   NULL, /* delete_all_rows */
46   table_global_variables::get_row_count,
47   sizeof(pos_t),
48   &m_table_lock,
49   { C_STRING_WITH_LEN("CREATE TABLE global_variables("
50   "VARIABLE_NAME VARCHAR(64) not null,"
51   "VARIABLE_VALUE VARCHAR(1024))") },
52   true   /* perpetual */
53 };
54 
55 PFS_engine_table*
create(void)56 table_global_variables::create(void)
57 {
58   return new table_global_variables();
59 }
60 
get_row_count(void)61 ha_rows table_global_variables::get_row_count(void)
62 {
63   mysql_mutex_lock(&LOCK_plugin_delete);
64   mysql_prlock_rdlock(&LOCK_system_variables_hash);
65   ha_rows system_var_count= get_system_variable_hash_records();
66   mysql_prlock_unlock(&LOCK_system_variables_hash);
67   mysql_mutex_unlock(&LOCK_plugin_delete);
68   return system_var_count;
69 }
70 
table_global_variables()71 table_global_variables::table_global_variables()
72   : PFS_engine_table(&m_share, &m_pos),
73     m_sysvar_cache(false), m_row_exists(false), m_pos(0), m_next_pos(0)
74 {}
75 
reset_position(void)76 void table_global_variables::reset_position(void)
77 {
78   m_pos.m_index= 0;
79   m_next_pos.m_index= 0;
80 }
81 
rnd_init(bool scan)82 int table_global_variables::rnd_init(bool scan)
83 {
84   /*
85     Build a list of system variables from the global system variable hash.
86     Filter by scope.
87   */
88   m_sysvar_cache.materialize_global();
89 
90   /* Record the version of the system variable hash. */
91   ulonglong hash_version= m_sysvar_cache.get_sysvar_hash_version();
92 
93   /*
94     The table context holds the current version of the system variable hash.
95     If scan == true, then allocate a new context from mem_root and store in TLS.
96     If scan == false, then restore from TLS.
97   */
98   m_context= (table_global_variables_context *)current_thd->alloc(sizeof(table_global_variables_context));
99   new(m_context) table_global_variables_context(hash_version, !scan);
100   return 0;
101 }
102 
rnd_next(void)103 int table_global_variables::rnd_next(void)
104 {
105   for (m_pos.set_at(&m_next_pos);
106        m_pos.m_index < m_sysvar_cache.size();
107        m_pos.next())
108   {
109     const System_variable *system_var= m_sysvar_cache.get(m_pos.m_index);
110     if (system_var != NULL)
111     {
112       make_row(system_var);
113       m_next_pos.set_after(&m_pos);
114       return 0;
115     }
116   }
117   return HA_ERR_END_OF_FILE;
118 }
119 
rnd_pos(const void * pos)120 int table_global_variables::rnd_pos(const void *pos)
121 {
122   /* If system variable hash changes, do nothing. */ // TODO: Issue warning
123   if (!m_context->versions_match())
124     return HA_ERR_RECORD_DELETED;
125 
126   set_position(pos);
127   assert(m_pos.m_index < m_sysvar_cache.size());
128 
129   const System_variable *system_var= m_sysvar_cache.get(m_pos.m_index);
130   if (system_var != NULL)
131   {
132     make_row(system_var);
133     return 0;
134   }
135   return HA_ERR_RECORD_DELETED;
136 }
137 
138 void table_global_variables
make_row(const System_variable * system_var)139 ::make_row(const System_variable *system_var)
140 {
141   m_row_exists= false;
142   if (system_var->is_null() || system_var->is_ignored())
143     return;
144   m_row.m_variable_name.make_row(system_var->m_name, system_var->m_name_length);
145   m_row.m_variable_value.make_row(system_var);
146   m_row_exists= true;
147 }
148 
149 int table_global_variables
read_row_values(TABLE * table,unsigned char * buf,Field ** fields,bool read_all)150 ::read_row_values(TABLE *table,
151                   unsigned char *buf,
152                   Field **fields,
153                   bool read_all)
154 {
155   Field *f;
156 
157   if (unlikely(! m_row_exists))
158     return HA_ERR_RECORD_DELETED;
159 
160   /* Set the null bits */
161   assert(table->s->null_bytes == 1);
162   buf[0]= 0;
163 
164   for (; (f= *fields) ; fields++)
165   {
166     if (read_all || bitmap_is_set(table->read_set, f->field_index))
167     {
168       switch(f->field_index)
169       {
170       case 0: /* VARIABLE_NAME */
171         set_field_varchar_utf8(f, m_row.m_variable_name.m_str, m_row.m_variable_name.m_length);
172         break;
173       case 1: /* VARIABLE_VALUE */
174         m_row.m_variable_value.set_field(f);
175         break;
176       default:
177         assert(false);
178       }
179     }
180   }
181 
182   return 0;
183 }
184 
185