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