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_session_variables.cc
25 Table SESSION_VARIABLES (implementation).
26 */
27
28 #include "my_global.h"
29 #include "my_thread.h"
30 #include "table_session_variables.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_session_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_session_variables::m_field_def=
54 { 2, field_types };
55
56 PFS_engine_table_share
57 table_session_variables::m_share=
58 {
59 { C_STRING_WITH_LEN("session_variables") },
60 &pfs_readonly_world_acl,
61 table_session_variables::create,
62 NULL, /* write_row */
63 NULL, /* delete_all_rows */
64 table_session_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_session_variables::create(void)
74 {
75 return new table_session_variables();
76 }
77
get_row_count(void)78 ha_rows table_session_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_session_variables()88 table_session_variables::table_session_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_session_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_session_variables::rnd_init(bool scan)
100 {
101 /* Build a cache of system variables for this thread. */
102 m_sysvar_cache.materialize_all(current_thd);
103
104 /* Record the version of the system variable hash. */
105 ulonglong hash_version= m_sysvar_cache.get_sysvar_hash_version();
106
107 /*
108 The table context holds the current version of the system variable hash.
109 If scan == true, then allocate a new context from mem_root and store in TLS.
110 If scan == false, then restore from TLS.
111 */
112 m_context= (table_session_variables_context *)current_thd->alloc(sizeof(table_session_variables_context));
113 new(m_context) table_session_variables_context(hash_version, !scan);
114 return 0;
115 }
116
rnd_next(void)117 int table_session_variables::rnd_next(void)
118 {
119 for (m_pos.set_at(&m_next_pos);
120 m_pos.m_index < m_sysvar_cache.size();
121 m_pos.next())
122 {
123 if (m_sysvar_cache.is_materialized())
124 {
125 const System_variable *system_var= m_sysvar_cache.get(m_pos.m_index);
126 if (system_var != NULL)
127 {
128 make_row(system_var);
129 m_next_pos.set_after(&m_pos);
130 return 0;
131 }
132 }
133 }
134 return HA_ERR_END_OF_FILE;
135 }
136
rnd_pos(const void * pos)137 int table_session_variables::rnd_pos(const void *pos)
138 {
139 /* If system variable hash changes, do nothing. */
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 if (m_sysvar_cache.is_materialized())
147 {
148 const System_variable *system_var= m_sysvar_cache.get(m_pos.m_index);
149 if (system_var != NULL)
150 {
151 make_row(system_var);
152 return 0;
153 }
154 }
155 return HA_ERR_RECORD_DELETED;
156 }
157
158 void table_session_variables
make_row(const System_variable * system_var)159 ::make_row(const System_variable *system_var)
160 {
161 m_row_exists= false;
162 if (system_var->is_null() || system_var->is_ignored())
163 return;
164 m_row.m_variable_name.make_row(system_var->m_name, system_var->m_name_length);
165 m_row.m_variable_value.make_row(system_var);
166 m_row_exists= true;
167 }
168
169 int table_session_variables
read_row_values(TABLE * table,unsigned char * buf,Field ** fields,bool read_all)170 ::read_row_values(TABLE *table,
171 unsigned char *buf,
172 Field **fields,
173 bool read_all)
174 {
175 Field *f;
176
177 if (unlikely(!m_row_exists))
178 return HA_ERR_RECORD_DELETED;
179
180 /* Set the null bits */
181 assert(table->s->null_bytes == 1);
182 buf[0]= 0;
183
184 for (; (f= *fields) ; fields++)
185 {
186 if (read_all || bitmap_is_set(table->read_set, f->field_index))
187 {
188 switch(f->field_index)
189 {
190 case 0: /* VARIABLE_NAME */
191 set_field_varchar_utf8(f, m_row.m_variable_name.m_str, m_row.m_variable_name.m_length);
192 break;
193 case 1: /* VARIABLE_VALUE */
194 m_row.m_variable_value.set_field(f);
195 break;
196 default:
197 assert(false);
198 }
199 }
200 }
201
202 return 0;
203 }
204
205