1/* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
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 as published by
5 the Free Software Foundation; version 2 of the License.
6
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
11
12 You should have received a copy of the GNU General Public License
13 along with this program; if not, write to the Free Software Foundation,
14 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
15
16/**
17 @file storage/perfschema/table_setup_objects.cc
18 Table SETUP_OBJECTS (implementation).
19*/
20
21#include "my_global.h"
22#include "my_pthread.h"
23#include "pfs_instr.h"
24#include "pfs_column_types.h"
25#include "pfs_column_values.h"
26#include "pfs_setup_object.h"
27#include "table_setup_objects.h"
28#include "table_helper.h"
29#include "pfs_global.h"
30
31THR_LOCK table_setup_objects::m_table_lock;
32
33PFS_engine_table_share
34table_setup_objects::m_share=
35{
36 { C_STRING_WITH_LEN("setup_objects") },
37 &pfs_editable_acl,
38 table_setup_objects::create,
39 table_setup_objects::write_row,
40 table_setup_objects::delete_all_rows,
41 table_setup_objects::get_row_count,
42 1000, /* records */
43 sizeof(PFS_simple_index),
44 &m_table_lock,
45 { C_STRING_WITH_LEN("CREATE TABLE setup_objects("
46 "OBJECT_TYPE ENUM ('TABLE') not null default 'TABLE',"
47 "OBJECT_SCHEMA VARCHAR(64) default '%',"
48 "OBJECT_NAME VARCHAR(64) not null default '%',"
49 "ENABLED ENUM ('YES', 'NO') not null default 'YES',"
50 "TIMED ENUM ('YES', 'NO') not null default 'YES')") }
51};
52
53int update_derived_flags()
54{
55 PFS_thread *thread= PFS_thread::get_current_thread();
56 if (unlikely(thread == NULL))
57 return HA_ERR_OUT_OF_MEM;
58
59 update_table_share_derived_flags(thread);
60 update_table_derived_flags();
61 return 0;
62}
63
64PFS_engine_table* table_setup_objects::create(void)
65{
66 return new table_setup_objects();
67}
68
69int table_setup_objects::write_row(TABLE *table, unsigned char *buf,
70 Field **fields)
71{
72 int result;
73 Field *f;
74 enum_object_type object_type= OBJECT_TYPE_TABLE;
75 String object_schema_data("%", 1, &my_charset_utf8_bin);
76 String object_name_data("%", 1, &my_charset_utf8_bin);
77 String *object_schema= &object_schema_data;
78 String *object_name= &object_name_data;
79 enum_yes_no enabled_value= ENUM_YES;
80 enum_yes_no timed_value= ENUM_YES;
81 bool enabled= true;
82 bool timed= true;
83
84 for (; (f= *fields) ; fields++)
85 {
86 if (bitmap_is_set(table->write_set, f->field_index))
87 {
88 switch(f->field_index)
89 {
90 case 0: /* OBJECT_TYPE */
91 object_type= (enum_object_type) get_field_enum(f);
92 break;
93 case 1: /* OBJECT_SCHEMA */
94 object_schema= get_field_varchar_utf8(f, &object_schema_data);
95 break;
96 case 2: /* OBJECT_NAME */
97 object_name= get_field_varchar_utf8(f, &object_name_data);
98 break;
99 case 3: /* ENABLED */
100 enabled_value= (enum_yes_no) get_field_enum(f);
101 break;
102 case 4: /* TIMED */
103 timed_value= (enum_yes_no) get_field_enum(f);
104 break;
105 default:
106 DBUG_ASSERT(false);
107 }
108 }
109 }
110
111 /* Reject illegal enum values in OBJECT_TYPE */
112 if (object_type != OBJECT_TYPE_TABLE)
113 return HA_ERR_NO_REFERENCED_ROW;
114
115 /* Reject illegal enum values in ENABLED */
116 if ((enabled_value != ENUM_YES) && (enabled_value != ENUM_NO))
117 return HA_ERR_NO_REFERENCED_ROW;
118
119 /* Reject illegal enum values in TIMED */
120 if ((timed_value != ENUM_YES) && (timed_value != ENUM_NO))
121 return HA_ERR_NO_REFERENCED_ROW;
122
123 enabled= (enabled_value == ENUM_YES) ? true : false;
124 timed= (timed_value == ENUM_YES) ? true : false;
125
126 result= insert_setup_object(object_type, object_schema, object_name,
127 enabled, timed);
128 if (result == 0)
129 result= update_derived_flags();
130 return result;
131}
132
133int table_setup_objects::delete_all_rows(void)
134{
135 int result= reset_setup_object();
136 if (result == 0)
137 result= update_derived_flags();
138 return result;
139}
140
141ha_rows table_setup_objects::get_row_count(void)
142{
143 return setup_object_count();
144}
145
146table_setup_objects::table_setup_objects()
147 : PFS_engine_table(&m_share, &m_pos),
148 m_row_exists(false), m_pos(0), m_next_pos(0)
149{}
150
151void table_setup_objects::reset_position(void)
152{
153 m_pos.m_index= 0;
154 m_next_pos.m_index= 0;
155}
156
157int table_setup_objects::rnd_next(void)
158{
159 PFS_setup_object *pfs;
160
161 for (m_pos.set_at(&m_next_pos);
162 m_pos.m_index < setup_object_max;
163 m_pos.next())
164 {
165 pfs= &setup_object_array[m_pos.m_index];
166 if (pfs->m_lock.is_populated())
167 {
168 make_row(pfs);
169 m_next_pos.set_after(&m_pos);
170 return 0;
171 }
172 }
173
174 return HA_ERR_END_OF_FILE;
175}
176
177int table_setup_objects::rnd_pos(const void *pos)
178{
179 PFS_setup_object *pfs;
180
181 set_position(pos);
182
183 DBUG_ASSERT(m_pos.m_index < setup_object_max);
184 pfs= &setup_object_array[m_pos.m_index];
185 if (pfs->m_lock.is_populated())
186 {
187 make_row(pfs);
188 return 0;
189 }
190
191 return HA_ERR_RECORD_DELETED;
192}
193
194void table_setup_objects::make_row(PFS_setup_object *pfs)
195{
196 pfs_lock lock;
197
198 m_row_exists= false;
199
200 pfs->m_lock.begin_optimistic_lock(&lock);
201
202 m_row.m_object_type= pfs->get_object_type();
203 memcpy(m_row.m_schema_name, pfs->m_schema_name, pfs->m_schema_name_length);
204 m_row.m_schema_name_length= pfs->m_schema_name_length;
205 memcpy(m_row.m_object_name, pfs->m_object_name, pfs->m_object_name_length);
206 m_row.m_object_name_length= pfs->m_object_name_length;
207 m_row.m_enabled_ptr= &pfs->m_enabled;
208 m_row.m_timed_ptr= &pfs->m_timed;
209
210 if (pfs->m_lock.end_optimistic_lock(&lock))
211 m_row_exists= true;
212}
213
214int table_setup_objects::read_row_values(TABLE *table,
215 unsigned char *buf,
216 Field **fields,
217 bool read_all)
218{
219 Field *f;
220
221 if (unlikely(! m_row_exists))
222 return HA_ERR_RECORD_DELETED;
223
224 /* Set the null bits */
225 DBUG_ASSERT(table->s->null_bytes == 1);
226 buf[0]= 0;
227
228 for (; (f= *fields) ; fields++)
229 {
230 if (read_all || bitmap_is_set(table->read_set, f->field_index))
231 {
232 switch(f->field_index)
233 {
234 case 0: /* OBJECT_TYPE */
235 set_field_enum(f, m_row.m_object_type);
236 break;
237 case 1: /* OBJECT_SCHEMA */
238 if (m_row.m_schema_name_length)
239 set_field_varchar_utf8(f, m_row.m_schema_name,
240 m_row.m_schema_name_length);
241 else
242 f->set_null();
243 break;
244 case 2: /* OBJECT_NAME */
245 if (m_row.m_object_name_length)
246 set_field_varchar_utf8(f, m_row.m_object_name,
247 m_row.m_object_name_length);
248 else
249 f->set_null();
250 break;
251 case 3: /* ENABLED */
252 set_field_enum(f, (*m_row.m_enabled_ptr) ? ENUM_YES : ENUM_NO);
253 break;
254 case 4: /* TIMED */
255 set_field_enum(f, (*m_row.m_timed_ptr) ? ENUM_YES : ENUM_NO);
256 break;
257 default:
258 DBUG_ASSERT(false);
259 }
260 }
261 }
262
263 return 0;
264}
265
266int table_setup_objects::update_row_values(TABLE *table,
267 const unsigned char *,
268 const unsigned char *,
269 Field **fields)
270{
271 int result;
272 Field *f;
273 enum_yes_no value;
274
275 for (; (f= *fields) ; fields++)
276 {
277 if (bitmap_is_set(table->write_set, f->field_index))
278 {
279 switch(f->field_index)
280 {
281 case 0: /* OBJECT_TYPE */
282 case 1: /* OBJECT_SCHEMA */
283 case 2: /* OBJECT_NAME */
284 return HA_ERR_WRONG_COMMAND;
285 case 3: /* ENABLED */
286 value= (enum_yes_no) get_field_enum(f);
287 /* Reject illegal enum values in ENABLED */
288 if ((value != ENUM_YES) && (value != ENUM_NO))
289 return HA_ERR_NO_REFERENCED_ROW;
290 *m_row.m_enabled_ptr= (value == ENUM_YES) ? true : false;
291 break;
292 case 4: /* TIMED */
293 value= (enum_yes_no) get_field_enum(f);
294 /* Reject illegal enum values in TIMED */
295 if ((value != ENUM_YES) && (value != ENUM_NO))
296 return HA_ERR_NO_REFERENCED_ROW;
297 *m_row.m_timed_ptr= (value == ENUM_YES) ? true : false;
298 break;
299 default:
300 DBUG_ASSERT(false);
301 }
302 }
303 }
304
305 result= update_derived_flags();
306 return result;
307}
308
309int table_setup_objects::delete_row_values(TABLE *table,
310 const unsigned char *buf,
311 Field **fields)
312{
313 DBUG_ASSERT(m_row_exists);
314
315 CHARSET_INFO *cs= &my_charset_utf8_bin;
316 enum_object_type object_type= OBJECT_TYPE_TABLE;
317 String object_schema(m_row.m_schema_name, m_row.m_schema_name_length, cs);
318 String object_name(m_row.m_object_name, m_row.m_object_name_length, cs);
319
320 int result= delete_setup_object(object_type, &object_schema, &object_name);
321
322 if (result == 0)
323 result= update_derived_flags();
324 return result;
325}
326
327