1 /* Copyright (c) 2011, 2020, 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, 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_users.cc
25   TABLE USERS.
26 */
27 
28 #include "storage/perfschema/table_users.h"
29 
30 #include <stddef.h>
31 
32 #include "my_dbug.h"
33 #include "my_thread.h"
34 #include "sql/field.h"
35 #include "sql/plugin_table.h"
36 #include "sql/table.h"
37 #include "storage/perfschema/pfs_account.h"
38 #include "storage/perfschema/pfs_events_transactions.h"
39 #include "storage/perfschema/pfs_instr.h"
40 #include "storage/perfschema/pfs_instr_class.h"
41 #include "storage/perfschema/pfs_memory.h"
42 #include "storage/perfschema/pfs_status.h"
43 #include "storage/perfschema/pfs_user.h"
44 #include "storage/perfschema/pfs_visitor.h"
45 
46 THR_LOCK table_users::m_table_lock;
47 
48 Plugin_table table_users::m_table_def(
49     /* Schema name */
50     "performance_schema",
51     /* Name */
52     "users",
53     /* Definition */
54     "  USER CHAR(32) collate utf8mb4_bin default null,\n"
55     "  CURRENT_CONNECTIONS bigint not null,\n"
56     "  TOTAL_CONNECTIONS bigint not null,\n"
57     "  UNIQUE KEY (USER) USING HASH\n",
58     /* Options */
59     " ENGINE=PERFORMANCE_SCHEMA",
60     /* Tablespace */
61     nullptr);
62 
63 PFS_engine_table_share table_users::m_share = {
64     &pfs_truncatable_acl,
65     table_users::create,
66     nullptr, /* write_row */
67     table_users::delete_all_rows,
68     cursor_by_user::get_row_count,
69     sizeof(PFS_simple_index), /* ref length */
70     &m_table_lock,
71     &m_table_def,
72     false, /* perpetual */
73     PFS_engine_table_proxy(),
74     {0},
75     false /* m_in_purgatory */
76 };
77 
match(PFS_user * pfs)78 bool PFS_index_users_by_user::match(PFS_user *pfs) {
79   if (m_fields >= 1) {
80     if (!m_key.match(pfs)) {
81       return false;
82     }
83   }
84 
85   return true;
86 }
87 
create(PFS_engine_table_share *)88 PFS_engine_table *table_users::create(PFS_engine_table_share *) {
89   return new table_users();
90 }
91 
delete_all_rows(void)92 int table_users::delete_all_rows(void) {
93   reset_events_waits_by_thread();
94   reset_events_waits_by_account();
95   reset_events_waits_by_user();
96   reset_events_stages_by_thread();
97   reset_events_stages_by_account();
98   reset_events_stages_by_user();
99   reset_events_statements_by_thread();
100   reset_events_statements_by_account();
101   reset_events_statements_by_user();
102   reset_events_transactions_by_thread();
103   reset_events_transactions_by_account();
104   reset_events_transactions_by_user();
105   reset_memory_by_thread();
106   reset_memory_by_account();
107   reset_memory_by_user();
108   reset_status_by_thread();
109   reset_status_by_account();
110   reset_status_by_user();
111   purge_all_account();
112   purge_all_user();
113   return 0;
114 }
115 
table_users()116 table_users::table_users() : cursor_by_user(&m_share) {}
117 
index_init(uint,bool)118 int table_users::index_init(uint, bool) {
119   PFS_index_users *result = nullptr;
120   result = PFS_NEW(PFS_index_users_by_user);
121   m_opened_index = result;
122   m_index = result;
123   return 0;
124 }
125 
make_row(PFS_user * pfs)126 int table_users::make_row(PFS_user *pfs) {
127   pfs_optimistic_state lock;
128 
129   pfs->m_lock.begin_optimistic_lock(&lock);
130 
131   if (m_row.m_user.make_row(pfs)) {
132     return HA_ERR_RECORD_DELETED;
133   }
134 
135   PFS_connection_stat_visitor visitor;
136   PFS_connection_iterator::visit_user(pfs, true, /* accounts */
137                                       true,      /* threads */
138                                       false,     /* THDs */
139                                       &visitor);
140 
141   if (!pfs->m_lock.end_optimistic_lock(&lock)) {
142     return HA_ERR_RECORD_DELETED;
143   }
144 
145   m_row.m_connection_stat.set(&visitor.m_stat);
146   return 0;
147 }
148 
read_row_values(TABLE * table,unsigned char * buf,Field ** fields,bool read_all)149 int table_users::read_row_values(TABLE *table, unsigned char *buf,
150                                  Field **fields, bool read_all) {
151   Field *f;
152 
153   /* Set the null bits */
154   DBUG_ASSERT(table->s->null_bytes == 1);
155   buf[0] = 0;
156 
157   for (; (f = *fields); fields++) {
158     if (read_all || bitmap_is_set(table->read_set, f->field_index())) {
159       switch (f->field_index()) {
160         case 0: /* USER */
161           m_row.m_user.set_field(f);
162           break;
163         case 1: /* CURRENT_CONNECTIONS */
164         case 2: /* TOTAL_CONNECTIONS */
165           m_row.m_connection_stat.set_field(f->field_index() - 1, f);
166           break;
167         default:
168           DBUG_ASSERT(false);
169       }
170     }
171   }
172   return 0;
173 }
174