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