1 /* Copyright (c) 2010, 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 Foundation,
21 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
22
23 /**
24 @file storage/perfschema/table_setup_actors.cc
25 Table SETUP_ACTORS (implementation).
26 */
27
28 #include "my_global.h"
29 #include "my_thread.h"
30 #include "pfs_instr_class.h"
31 #include "pfs_column_types.h"
32 #include "pfs_column_values.h"
33 #include "pfs_setup_actor.h"
34 #include "table_setup_actors.h"
35 #include "pfs_global.h"
36 #include "pfs_buffer_container.h"
37 #include "field.h"
38
39 THR_LOCK table_setup_actors::m_table_lock;
40
41 static const TABLE_FIELD_TYPE field_types[]=
42 {
43 {
44 { C_STRING_WITH_LEN("HOST") },
45 { C_STRING_WITH_LEN("char(60)") },
46 { NULL, 0}
47 },
48 {
49 { C_STRING_WITH_LEN("USER") },
50 { C_STRING_WITH_LEN("char(" USERNAME_CHAR_LENGTH_STR ")") },
51 { NULL, 0}
52 },
53 {
54 { C_STRING_WITH_LEN("ROLE") },
55 { C_STRING_WITH_LEN("char(16)") },
56 { NULL, 0}
57 },
58 {
59 { C_STRING_WITH_LEN("ENABLED") },
60 { C_STRING_WITH_LEN("enum(\'YES\',\'NO\')") },
61 { NULL, 0}
62 },
63 {
64 { C_STRING_WITH_LEN("HISTORY") },
65 { C_STRING_WITH_LEN("enum(\'YES\',\'NO\')") },
66 { NULL, 0}
67 }
68 };
69
70 TABLE_FIELD_DEF
71 table_setup_actors::m_field_def=
72 { 5, field_types };
73
74 PFS_engine_table_share
75 table_setup_actors::m_share=
76 {
77 { C_STRING_WITH_LEN("setup_actors") },
78 &pfs_editable_acl,
79 table_setup_actors::create,
80 table_setup_actors::write_row,
81 table_setup_actors::delete_all_rows,
82 table_setup_actors::get_row_count,
83 sizeof(PFS_simple_index),
84 &m_table_lock,
85 &m_field_def,
86 false, /* checked */
87 false /* perpetual */
88 };
89
create()90 PFS_engine_table* table_setup_actors::create()
91 {
92 return new table_setup_actors();
93 }
94
write_row(TABLE * table,unsigned char * buf,Field ** fields)95 int table_setup_actors::write_row(TABLE *table, unsigned char *buf,
96 Field **fields)
97 {
98 Field *f;
99 String user_data("%", 1, &my_charset_utf8_bin);
100 String host_data("%", 1, &my_charset_utf8_bin);
101 String role_data("%", 1, &my_charset_utf8_bin);
102 String *user= &user_data;
103 String *host= &host_data;
104 String *role= &role_data;
105 enum_yes_no enabled_value= ENUM_YES;
106 enum_yes_no history_value= ENUM_YES;
107 bool enabled;
108 bool history;
109
110 for (; (f= *fields) ; fields++)
111 {
112 if (bitmap_is_set(table->write_set, f->field_index))
113 {
114 switch(f->field_index)
115 {
116 case 0: /* HOST */
117 host= get_field_char_utf8(f, &host_data);
118 break;
119 case 1: /* USER */
120 user= get_field_char_utf8(f, &user_data);
121 break;
122 case 2: /* ROLE */
123 role= get_field_char_utf8(f, &role_data);
124 break;
125 case 3: /* ENABLED */
126 enabled_value= (enum_yes_no) get_field_enum(f);
127 break;
128 case 4: /* HISTORY */
129 history_value= (enum_yes_no) get_field_enum(f);
130 break;
131 default:
132 assert(false);
133 }
134 }
135 }
136
137 /* Reject illegal enum values in ENABLED */
138 if ((enabled_value != ENUM_YES) && (enabled_value != ENUM_NO))
139 return HA_ERR_NO_REFERENCED_ROW;
140
141 /* Reject illegal enum values in HISTORY */
142 if ((history_value != ENUM_YES) && (history_value != ENUM_NO))
143 return HA_ERR_NO_REFERENCED_ROW;
144
145 /* Reject if any of user/host/role is not provided */
146 if (user->length() == 0 || host->length() == 0 || role->length() == 0)
147 return HA_ERR_WRONG_COMMAND;
148
149 enabled= (enabled_value == ENUM_YES) ? true : false;
150 history= (history_value == ENUM_YES) ? true : false;
151
152 return insert_setup_actor(user, host, role, enabled, history);
153 }
154
delete_all_rows(void)155 int table_setup_actors::delete_all_rows(void)
156 {
157 return reset_setup_actor();
158 }
159
get_row_count(void)160 ha_rows table_setup_actors::get_row_count(void)
161 {
162 return global_setup_actor_container.get_row_count();
163 }
164
table_setup_actors()165 table_setup_actors::table_setup_actors()
166 : PFS_engine_table(&m_share, &m_pos),
167 m_row_exists(false), m_pos(0), m_next_pos(0)
168 {}
169
reset_position(void)170 void table_setup_actors::reset_position(void)
171 {
172 m_pos.m_index= 0;
173 m_next_pos.m_index= 0;
174 }
175
rnd_next()176 int table_setup_actors::rnd_next()
177 {
178 PFS_setup_actor *pfs;
179
180 m_pos.set_at(&m_next_pos);
181 PFS_setup_actor_iterator it= global_setup_actor_container.iterate(m_pos.m_index);
182 pfs= it.scan_next(& m_pos.m_index);
183 if (pfs != NULL)
184 {
185 make_row(pfs);
186 m_next_pos.set_after(&m_pos);
187 return 0;
188 }
189
190 return HA_ERR_END_OF_FILE;
191 }
192
rnd_pos(const void * pos)193 int table_setup_actors::rnd_pos(const void *pos)
194 {
195 PFS_setup_actor *pfs;
196
197 set_position(pos);
198
199 pfs= global_setup_actor_container.get(m_pos.m_index);
200 if (pfs != NULL)
201 {
202 make_row(pfs);
203 return 0;
204 }
205
206 return HA_ERR_RECORD_DELETED;
207 }
208
make_row(PFS_setup_actor * pfs)209 void table_setup_actors::make_row(PFS_setup_actor *pfs)
210 {
211 pfs_optimistic_state lock;
212
213 m_row_exists= false;
214
215 pfs->m_lock.begin_optimistic_lock(&lock);
216
217 m_row.m_hostname_length= pfs->m_hostname_length;
218 if (unlikely((m_row.m_hostname_length == 0) ||
219 (m_row.m_hostname_length > sizeof(m_row.m_hostname))))
220 return;
221 memcpy(m_row.m_hostname, pfs->m_hostname, m_row.m_hostname_length);
222
223 m_row.m_username_length= pfs->m_username_length;
224 if (unlikely((m_row.m_username_length == 0) ||
225 (m_row.m_username_length > sizeof(m_row.m_username))))
226 return;
227 memcpy(m_row.m_username, pfs->m_username, m_row.m_username_length);
228
229 m_row.m_rolename_length= pfs->m_rolename_length;
230 if (unlikely((m_row.m_rolename_length == 0) ||
231 (m_row.m_rolename_length > sizeof(m_row.m_rolename))))
232 return;
233 memcpy(m_row.m_rolename, pfs->m_rolename, m_row.m_rolename_length);
234
235 m_row.m_enabled_ptr= &pfs->m_enabled;
236 m_row.m_history_ptr= &pfs->m_history;
237
238 if (pfs->m_lock.end_optimistic_lock(&lock))
239 m_row_exists= true;
240 }
241
read_row_values(TABLE * table,unsigned char * buf,Field ** fields,bool read_all)242 int table_setup_actors::read_row_values(TABLE *table,
243 unsigned char *buf,
244 Field **fields,
245 bool read_all)
246 {
247 Field *f;
248
249 if (unlikely(! m_row_exists))
250 return HA_ERR_RECORD_DELETED;
251
252 /* Set the null bits */
253 assert(table->s->null_bytes == 1);
254
255 for (; (f= *fields) ; fields++)
256 {
257 if (read_all || bitmap_is_set(table->read_set, f->field_index))
258 {
259 switch(f->field_index)
260 {
261 case 0: /* HOST */
262 set_field_char_utf8(f, m_row.m_hostname, m_row.m_hostname_length);
263 break;
264 case 1: /* USER */
265 set_field_char_utf8(f, m_row.m_username, m_row.m_username_length);
266 break;
267 case 2: /* ROLE */
268 set_field_char_utf8(f, m_row.m_rolename, m_row.m_rolename_length);
269 break;
270 case 3: /* ENABLED */
271 set_field_enum(f, (*m_row.m_enabled_ptr) ? ENUM_YES : ENUM_NO);
272 break;
273 case 4: /* HISTORY */
274 set_field_enum(f, (*m_row.m_history_ptr) ? ENUM_YES : ENUM_NO);
275 break;
276 default:
277 assert(false);
278 }
279 }
280 }
281
282 return 0;
283 }
284
update_row_values(TABLE * table,const unsigned char * old_buf,unsigned char * new_buf,Field ** fields)285 int table_setup_actors::update_row_values(TABLE *table,
286 const unsigned char *old_buf,
287 unsigned char *new_buf,
288 Field **fields)
289 {
290 int result;
291 Field *f;
292 enum_yes_no value;
293
294 for (; (f= *fields) ; fields++)
295 {
296 if (bitmap_is_set(table->write_set, f->field_index))
297 {
298 switch(f->field_index)
299 {
300 case 0: /* HOST */
301 case 1: /* USER */
302 case 2: /* ROLE */
303 return HA_ERR_WRONG_COMMAND;
304 case 3: /* ENABLED */
305 value= (enum_yes_no) get_field_enum(f);
306 /* Reject illegal enum values in ENABLED */
307 if ((value != ENUM_YES) && (value != ENUM_NO))
308 return HA_ERR_NO_REFERENCED_ROW;
309 *m_row.m_enabled_ptr= (value == ENUM_YES) ? true : false;
310 break;
311 case 4: /* HISTORY */
312 value= (enum_yes_no) get_field_enum(f);
313 /* Reject illegal enum values in HISTORY */
314 if ((value != ENUM_YES) && (value != ENUM_NO))
315 return HA_ERR_NO_REFERENCED_ROW;
316 *m_row.m_history_ptr= (value == ENUM_YES) ? true : false;
317 break;
318 default:
319 assert(false);
320 }
321 }
322 }
323
324 result= update_setup_actors_derived_flags();
325 return result;
326 }
327
delete_row_values(TABLE * table,const unsigned char * buf,Field ** fields)328 int table_setup_actors::delete_row_values(TABLE *table,
329 const unsigned char *buf,
330 Field **fields)
331 {
332 assert(m_row_exists);
333
334 CHARSET_INFO *cs= &my_charset_utf8_bin;
335 String user(m_row.m_username, m_row.m_username_length, cs);
336 String role(m_row.m_rolename, m_row.m_rolename_length, cs);
337 String host(m_row.m_hostname, m_row.m_hostname_length, cs);
338
339 return delete_setup_actor(&user, &host, &role);
340 }
341
342