1 /* Copyright (c) 2008, 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_objects.cc
25 Table SETUP_OBJECTS (implementation).
26 */
27
28 #include "my_global.h"
29 #include "my_thread.h"
30 #include "pfs_instr.h"
31 #include "pfs_column_types.h"
32 #include "pfs_column_values.h"
33 #include "pfs_setup_object.h"
34 #include "table_setup_objects.h"
35 #include "table_helper.h"
36 #include "pfs_global.h"
37 #include "pfs_buffer_container.h"
38 #include "field.h"
39
40 THR_LOCK table_setup_objects::m_table_lock;
41
42 static const TABLE_FIELD_TYPE field_types[]=
43 {
44 {
45 { C_STRING_WITH_LEN("OBJECT_TYPE") },
46 { C_STRING_WITH_LEN("enum(\'EVENT\',\'FUNCTION\',\'PROCEDURE\',\'TABLE\',\'TRIGGER\'") },
47 { NULL, 0}
48 },
49 {
50 { C_STRING_WITH_LEN("OBJECT_SCHEMA") },
51 { C_STRING_WITH_LEN("varchar(64)") },
52 { NULL, 0}
53 },
54 {
55 { C_STRING_WITH_LEN("OBJECT_NAME") },
56 { C_STRING_WITH_LEN("varchar(64)") },
57 { NULL, 0}
58 },
59 {
60 { C_STRING_WITH_LEN("ENABLED") },
61 { C_STRING_WITH_LEN("enum(\'YES\',\'NO\')") },
62 { NULL, 0}
63 },
64 {
65 { C_STRING_WITH_LEN("TIMED") },
66 { C_STRING_WITH_LEN("enum(\'YES\',\'NO\')") },
67 { NULL, 0}
68 }
69 };
70
71 TABLE_FIELD_DEF
72 table_setup_objects::m_field_def=
73 { 5, field_types };
74
75 PFS_engine_table_share
76 table_setup_objects::m_share=
77 {
78 { C_STRING_WITH_LEN("setup_objects") },
79 &pfs_editable_acl,
80 table_setup_objects::create,
81 table_setup_objects::write_row,
82 table_setup_objects::delete_all_rows,
83 table_setup_objects::get_row_count,
84 sizeof(PFS_simple_index),
85 &m_table_lock,
86 &m_field_def,
87 false, /* checked */
88 false /* perpetual */
89 };
90
update_derived_flags()91 int update_derived_flags()
92 {
93 PFS_thread *thread= PFS_thread::get_current_thread();
94 if (unlikely(thread == NULL))
95 return HA_ERR_OUT_OF_MEM;
96
97 update_table_share_derived_flags(thread);
98 update_program_share_derived_flags(thread);
99 update_table_derived_flags();
100 return 0;
101 }
102
create(void)103 PFS_engine_table* table_setup_objects::create(void)
104 {
105 return new table_setup_objects();
106 }
107
write_row(TABLE * table,unsigned char * buf,Field ** fields)108 int table_setup_objects::write_row(TABLE *table, unsigned char *buf,
109 Field **fields)
110 {
111 int result;
112 Field *f;
113 enum_object_type object_type= OBJECT_TYPE_TABLE;
114 String object_schema_data("%", 1, &my_charset_utf8_bin);
115 String object_name_data("%", 1, &my_charset_utf8_bin);
116 String *object_schema= &object_schema_data;
117 String *object_name= &object_name_data;
118 enum_yes_no enabled_value= ENUM_YES;
119 enum_yes_no timed_value= ENUM_YES;
120 bool enabled= true;
121 bool timed= true;
122
123 for (; (f= *fields) ; fields++)
124 {
125 if (bitmap_is_set(table->write_set, f->field_index))
126 {
127 switch(f->field_index)
128 {
129 case 0: /* OBJECT_TYPE */
130 object_type= (enum_object_type) get_field_enum(f);
131 break;
132 case 1: /* OBJECT_SCHEMA */
133 object_schema= get_field_varchar_utf8(f, &object_schema_data);
134 break;
135 case 2: /* OBJECT_NAME */
136 object_name= get_field_varchar_utf8(f, &object_name_data);
137 break;
138 case 3: /* ENABLED */
139 enabled_value= (enum_yes_no) get_field_enum(f);
140 break;
141 case 4: /* TIMED */
142 timed_value= (enum_yes_no) get_field_enum(f);
143 break;
144 default:
145 assert(false);
146 }
147 }
148 }
149
150 /* Reject illegal enum values in OBJECT_TYPE */
151 if (object_type < FIRST_OBJECT_TYPE ||
152 object_type > LAST_OBJECT_TYPE ||
153 object_type == OBJECT_TYPE_TEMPORARY_TABLE)
154 return HA_ERR_NO_REFERENCED_ROW;
155
156 /* Reject illegal enum values in ENABLED */
157 if ((enabled_value != ENUM_YES) && (enabled_value != ENUM_NO))
158 return HA_ERR_NO_REFERENCED_ROW;
159
160 /* Reject illegal enum values in TIMED */
161 if ((timed_value != ENUM_YES) && (timed_value != ENUM_NO))
162 return HA_ERR_NO_REFERENCED_ROW;
163
164 enabled= (enabled_value == ENUM_YES) ? true : false;
165 timed= (timed_value == ENUM_YES) ? true : false;
166
167 result= insert_setup_object(object_type, object_schema, object_name,
168 enabled, timed);
169 if (result == 0)
170 result= update_derived_flags();
171 return result;
172 }
173
delete_all_rows(void)174 int table_setup_objects::delete_all_rows(void)
175 {
176 int result= reset_setup_object();
177 if (result == 0)
178 result= update_derived_flags();
179 return result;
180 }
181
get_row_count(void)182 ha_rows table_setup_objects::get_row_count(void)
183 {
184 return global_setup_object_container.get_row_count();
185 }
186
table_setup_objects()187 table_setup_objects::table_setup_objects()
188 : PFS_engine_table(&m_share, &m_pos),
189 m_row_exists(false), m_pos(0), m_next_pos(0)
190 {}
191
reset_position(void)192 void table_setup_objects::reset_position(void)
193 {
194 m_pos.m_index= 0;
195 m_next_pos.m_index= 0;
196 }
197
rnd_next(void)198 int table_setup_objects::rnd_next(void)
199 {
200 PFS_setup_object *pfs;
201
202 m_pos.set_at(&m_next_pos);
203 PFS_setup_object_iterator it= global_setup_object_container.iterate(m_pos.m_index);
204 pfs= it.scan_next(& m_pos.m_index);
205 if (pfs != NULL)
206 {
207 make_row(pfs);
208 m_next_pos.set_after(&m_pos);
209 return 0;
210 }
211
212 return HA_ERR_END_OF_FILE;
213 }
214
rnd_pos(const void * pos)215 int table_setup_objects::rnd_pos(const void *pos)
216 {
217 PFS_setup_object *pfs;
218
219 set_position(pos);
220
221 pfs= global_setup_object_container.get(m_pos.m_index);
222 if (pfs != NULL)
223 {
224 make_row(pfs);
225 return 0;
226 }
227
228 return HA_ERR_RECORD_DELETED;
229 }
230
make_row(PFS_setup_object * pfs)231 void table_setup_objects::make_row(PFS_setup_object *pfs)
232 {
233 pfs_optimistic_state lock;
234
235 m_row_exists= false;
236
237 pfs->m_lock.begin_optimistic_lock(&lock);
238
239 m_row.m_object_type= pfs->get_object_type();
240 memcpy(m_row.m_schema_name, pfs->m_schema_name, pfs->m_schema_name_length);
241 m_row.m_schema_name_length= pfs->m_schema_name_length;
242 memcpy(m_row.m_object_name, pfs->m_object_name, pfs->m_object_name_length);
243 m_row.m_object_name_length= pfs->m_object_name_length;
244 m_row.m_enabled_ptr= &pfs->m_enabled;
245 m_row.m_timed_ptr= &pfs->m_timed;
246
247 if (pfs->m_lock.end_optimistic_lock(&lock))
248 m_row_exists= true;
249 }
250
read_row_values(TABLE * table,unsigned char * buf,Field ** fields,bool read_all)251 int table_setup_objects::read_row_values(TABLE *table,
252 unsigned char *buf,
253 Field **fields,
254 bool read_all)
255 {
256 Field *f;
257
258 if (unlikely(! m_row_exists))
259 return HA_ERR_RECORD_DELETED;
260
261 /* Set the null bits */
262 assert(table->s->null_bytes == 1);
263 buf[0]= 0;
264
265 for (; (f= *fields) ; fields++)
266 {
267 if (read_all || bitmap_is_set(table->read_set, f->field_index))
268 {
269 switch(f->field_index)
270 {
271 case 0: /* OBJECT_TYPE */
272 set_field_enum(f, m_row.m_object_type);
273 break;
274 case 1: /* OBJECT_SCHEMA */
275 if (m_row.m_schema_name_length)
276 set_field_varchar_utf8(f, m_row.m_schema_name,
277 m_row.m_schema_name_length);
278 else
279 f->set_null();
280 break;
281 case 2: /* OBJECT_NAME */
282 if (m_row.m_object_name_length)
283 set_field_varchar_utf8(f, m_row.m_object_name,
284 m_row.m_object_name_length);
285 else
286 f->set_null();
287 break;
288 case 3: /* ENABLED */
289 set_field_enum(f, (*m_row.m_enabled_ptr) ? ENUM_YES : ENUM_NO);
290 break;
291 case 4: /* TIMED */
292 set_field_enum(f, (*m_row.m_timed_ptr) ? ENUM_YES : ENUM_NO);
293 break;
294 default:
295 assert(false);
296 }
297 }
298 }
299
300 return 0;
301 }
302
update_row_values(TABLE * table,const unsigned char *,unsigned char *,Field ** fields)303 int table_setup_objects::update_row_values(TABLE *table,
304 const unsigned char *,
305 unsigned char *,
306 Field **fields)
307 {
308 int result;
309 Field *f;
310 enum_yes_no value;
311
312 for (; (f= *fields) ; fields++)
313 {
314 if (bitmap_is_set(table->write_set, f->field_index))
315 {
316 switch(f->field_index)
317 {
318 case 0: /* OBJECT_TYPE */
319 case 1: /* OBJECT_SCHEMA */
320 case 2: /* OBJECT_NAME */
321 return HA_ERR_WRONG_COMMAND;
322 case 3: /* ENABLED */
323 value= (enum_yes_no) get_field_enum(f);
324 /* Reject illegal enum values in ENABLED */
325 if ((value != ENUM_YES) && (value != ENUM_NO))
326 return HA_ERR_NO_REFERENCED_ROW;
327 *m_row.m_enabled_ptr= (value == ENUM_YES) ? true : false;
328 break;
329 case 4: /* TIMED */
330 value= (enum_yes_no) get_field_enum(f);
331 /* Reject illegal enum values in TIMED */
332 if ((value != ENUM_YES) && (value != ENUM_NO))
333 return HA_ERR_NO_REFERENCED_ROW;
334 *m_row.m_timed_ptr= (value == ENUM_YES) ? true : false;
335 break;
336 default:
337 assert(false);
338 }
339 }
340 }
341
342 result= update_derived_flags();
343 return result;
344 }
345
delete_row_values(TABLE * table,const unsigned char * buf,Field ** fields)346 int table_setup_objects::delete_row_values(TABLE *table,
347 const unsigned char *buf,
348 Field **fields)
349 {
350 assert(m_row_exists);
351
352 CHARSET_INFO *cs= &my_charset_utf8_bin;
353 enum_object_type object_type= OBJECT_TYPE_TABLE;
354 String object_schema(m_row.m_schema_name, m_row.m_schema_name_length, cs);
355 String object_name(m_row.m_object_name, m_row.m_object_name_length, cs);
356
357 int result= delete_setup_object(object_type, &object_schema, &object_name);
358
359 if (result == 0)
360 result= update_derived_flags();
361 return result;
362 }
363
364