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 static const TABLE_FIELD_TYPE field_types[]=
39 {
40   {
41     { C_STRING_WITH_LEN("VARIABLE_NAME") },
42     { C_STRING_WITH_LEN("varchar(64)") },
43     { NULL, 0}
44   },
45   {
46     { C_STRING_WITH_LEN("VARIABLE_VALUE") },
47     { C_STRING_WITH_LEN("varchar(1024)") },
48     { NULL, 0}
49   }
50 };
51 
52 TABLE_FIELD_DEF
53 table_global_variables::m_field_def=
54 { 2, field_types };
55 
56 PFS_engine_table_share
57 table_global_variables::m_share=
58 {
59   { C_STRING_WITH_LEN("global_variables") },
60   &pfs_readonly_world_acl,
61   table_global_variables::create,
62   NULL, /* write_row */
63   NULL, /* delete_all_rows */
64   table_global_variables::get_row_count,
65   sizeof(pos_t),
66   &m_table_lock,
67   &m_field_def,
68   false, /* checked */
69   true   /* perpetual */
70 };
71 
72 PFS_engine_table*
create(void)73 table_global_variables::create(void)
74 {
75   return new table_global_variables();
76 }
77 
get_row_count(void)78 ha_rows table_global_variables::get_row_count(void)
79 {
80   mysql_mutex_lock(&LOCK_plugin_delete);
81   mysql_rwlock_rdlock(&LOCK_system_variables_hash);
82   ha_rows system_var_count= get_system_variable_hash_records();
83   mysql_rwlock_unlock(&LOCK_system_variables_hash);
84   mysql_mutex_unlock(&LOCK_plugin_delete);
85   return system_var_count;
86 }
87 
table_global_variables()88 table_global_variables::table_global_variables()
89   : PFS_engine_table(&m_share, &m_pos),
90     m_sysvar_cache(false), m_row_exists(false), m_pos(0), m_next_pos(0)
91 {}
92 
reset_position(void)93 void table_global_variables::reset_position(void)
94 {
95   m_pos.m_index= 0;
96   m_next_pos.m_index= 0;
97 }
98 
rnd_init(bool scan)99 int table_global_variables::rnd_init(bool scan)
100 {
101   /*
102     Build a list of system variables from the global system variable hash.
103     Filter by scope.
104   */
105   m_sysvar_cache.materialize_global();
106 
107   /* Record the version of the system variable hash. */
108   ulonglong hash_version= m_sysvar_cache.get_sysvar_hash_version();
109 
110   /*
111     The table context holds the current version of the system variable hash.
112     If scan == true, then allocate a new context from mem_root and store in TLS.
113     If scan == false, then restore from TLS.
114   */
115   m_context= (table_global_variables_context *)current_thd->alloc(sizeof(table_global_variables_context));
116   new(m_context) table_global_variables_context(hash_version, !scan);
117   return 0;
118 }
119 
rnd_next(void)120 int table_global_variables::rnd_next(void)
121 {
122   for (m_pos.set_at(&m_next_pos);
123        m_pos.m_index < m_sysvar_cache.size();
124        m_pos.next())
125   {
126     const System_variable *system_var= m_sysvar_cache.get(m_pos.m_index);
127     if (system_var != NULL)
128     {
129       make_row(system_var);
130       m_next_pos.set_after(&m_pos);
131       return 0;
132     }
133   }
134   return HA_ERR_END_OF_FILE;
135 }
136 
rnd_pos(const void * pos)137 int table_global_variables::rnd_pos(const void *pos)
138 {
139   /* If system variable hash changes, do nothing. */ // TODO: Issue warning
140   if (!m_context->versions_match())
141     return HA_ERR_RECORD_DELETED;
142 
143   set_position(pos);
144   assert(m_pos.m_index < m_sysvar_cache.size());
145 
146   const System_variable *system_var= m_sysvar_cache.get(m_pos.m_index);
147   if (system_var != NULL)
148   {
149     make_row(system_var);
150     return 0;
151   }
152   return HA_ERR_RECORD_DELETED;
153 }
154 
155 void table_global_variables
make_row(const System_variable * system_var)156 ::make_row(const System_variable *system_var)
157 {
158   m_row_exists= false;
159   if (system_var->is_null() || system_var->is_ignored())
160     return;
161   m_row.m_variable_name.make_row(system_var->m_name, system_var->m_name_length);
162   m_row.m_variable_value.make_row(system_var);
163   m_row_exists= true;
164 }
165 
166 int table_global_variables
read_row_values(TABLE * table,unsigned char * buf,Field ** fields,bool read_all)167 ::read_row_values(TABLE *table,
168                   unsigned char *buf,
169                   Field **fields,
170                   bool read_all)
171 {
172   Field *f;
173 
174   if (unlikely(! m_row_exists))
175     return HA_ERR_RECORD_DELETED;
176 
177   /* Set the null bits */
178   assert(table->s->null_bytes == 1);
179   buf[0]= 0;
180 
181   for (; (f= *fields) ; fields++)
182   {
183     if (read_all || bitmap_is_set(table->read_set, f->field_index))
184     {
185       switch(f->field_index)
186       {
187       case 0: /* VARIABLE_NAME */
188         set_field_varchar_utf8(f, m_row.m_variable_name.m_str, m_row.m_variable_name.m_length);
189         break;
190       case 1: /* VARIABLE_VALUE */
191         m_row.m_variable_value.set_field(f);
192         break;
193       default:
194         assert(false);
195       }
196     }
197   }
198 
199   return 0;
200 }
201 
202