1 | /* Copyright (c) 2008, 2014, 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 | #ifndef HA_PERFSCHEMA_H |
17 | #define HA_PERFSCHEMA_H |
18 | |
19 | #include "handler.h" /* class handler */ |
20 | #include "table.h" |
21 | #include "sql_class.h" |
22 | |
23 | /** |
24 | @file storage/perfschema/ha_perfschema.h |
25 | Performance schema storage engine (declarations). |
26 | |
27 | @defgroup Performance_schema_engine Performance Schema Engine |
28 | @ingroup Performance_schema_implementation |
29 | @{ |
30 | */ |
31 | struct PFS_engine_table_share; |
32 | class PFS_engine_table; |
33 | /** Name of the performance schema engine. */ |
34 | extern const char *pfs_engine_name; |
35 | |
36 | /** A handler for a PERFORMANCE_SCHEMA table. */ |
37 | class ha_perfschema : public handler |
38 | { |
39 | public: |
40 | /** |
41 | Create a new performance schema table handle on a table. |
42 | @param hton storage engine handler singleton |
43 | @param share table share |
44 | */ |
45 | ha_perfschema(handlerton *hton, TABLE_SHARE *share); |
46 | |
47 | ~ha_perfschema(); |
48 | |
49 | const char *index_type(uint) { return "" ; } |
50 | |
51 | /** Capabilities of the performance schema tables. */ |
52 | ulonglong table_flags(void) const |
53 | { |
54 | /* |
55 | About HA_FAST_KEY_READ: |
56 | |
57 | The storage engine ::rnd_pos() method is fast to locate records by key, |
58 | so HA_FAST_KEY_READ is technically true, but the record content can be |
59 | overwritten between ::rnd_next() and ::rnd_pos(), because all the P_S |
60 | data is volatile. |
61 | The HA_FAST_KEY_READ flag is not advertised, to force the optimizer |
62 | to cache records instead, to provide more consistent records. |
63 | For example, consider the following statement: |
64 | - select * from P_S.EVENTS_WAITS_HISTORY_LONG where THREAD_ID=<n> |
65 | order by ... |
66 | With HA_FAST_KEY_READ, it can return records where "THREAD_ID=<n>" |
67 | is false, because the where clause was evaluated to true after |
68 | ::rnd_pos(), then the content changed, then the record was fetched by |
69 | key using ::rnd_pos(). |
70 | Without HA_FAST_KEY_READ, the optimizer reads all columns and never |
71 | calls ::rnd_pos(), so it is guaranteed to return only thread <n> |
72 | records. |
73 | */ |
74 | return HA_NO_TRANSACTIONS | HA_REC_NOT_IN_SEQ | HA_NO_AUTO_INCREMENT | |
75 | HA_PRIMARY_KEY_REQUIRED_FOR_DELETE; |
76 | } |
77 | |
78 | /** |
79 | Operations supported by indexes. |
80 | None, there are no indexes. |
81 | */ |
82 | ulong index_flags(uint , uint , bool ) const |
83 | { return 0; } |
84 | |
85 | uint max_supported_record_length(void) const |
86 | { return HA_MAX_REC_LENGTH; } |
87 | |
88 | uint max_supported_keys(void) const |
89 | { return 0; } |
90 | |
91 | uint max_supported_key_parts(void) const |
92 | { return 0; } |
93 | |
94 | uint max_supported_key_length(void) const |
95 | { return 0; } |
96 | |
97 | ha_rows estimate_rows_upper_bound(void) |
98 | { return HA_POS_ERROR; } |
99 | |
100 | double scan_time(void) |
101 | { return 1.0; } |
102 | |
103 | /** |
104 | Open a performance schema table. |
105 | @param name the table to open |
106 | @param mode unused |
107 | @param test_if_locked unused |
108 | @return 0 on success |
109 | */ |
110 | int open(const char *name, int mode, uint test_if_locked); |
111 | |
112 | /** |
113 | Close a table handle. |
114 | @sa open. |
115 | */ |
116 | int close(void); |
117 | |
118 | /** |
119 | Write a row. |
120 | @param buf the row to write |
121 | @return 0 on success |
122 | */ |
123 | int write_row(uchar *buf); |
124 | |
125 | void use_hidden_primary_key(); |
126 | |
127 | /** |
128 | Update a row. |
129 | @param old_data the row old values |
130 | @param new_data the row new values |
131 | @return 0 on success |
132 | */ |
133 | int update_row(const uchar *old_data, const uchar *new_data); |
134 | |
135 | /** |
136 | Delete a row. |
137 | @param buf the row to delete |
138 | @return 0 on success |
139 | */ |
140 | int delete_row(const uchar *buf); |
141 | |
142 | int rnd_init(bool scan); |
143 | |
144 | /** |
145 | Scan end. |
146 | @sa rnd_init. |
147 | */ |
148 | int rnd_end(void); |
149 | |
150 | /** |
151 | Iterator, fetch the next row. |
152 | @param[out] buf the row fetched. |
153 | @return 0 on success |
154 | */ |
155 | int rnd_next(uchar *buf); |
156 | |
157 | /** |
158 | Iterator, fetch the row at a given position. |
159 | @param[out] buf the row fetched. |
160 | @param pos the row position |
161 | @return 0 on success |
162 | */ |
163 | int rnd_pos(uchar *buf, uchar *pos); |
164 | |
165 | /** |
166 | Read the row current position. |
167 | @param record the current row |
168 | */ |
169 | void position(const uchar *record); |
170 | |
171 | int info(uint); |
172 | |
173 | int delete_all_rows(void); |
174 | |
175 | int truncate(); |
176 | |
177 | int delete_table(const char *from); |
178 | |
179 | int rename_table(const char * from, const char * to); |
180 | |
181 | int create(const char *name, TABLE *form, |
182 | HA_CREATE_INFO *create_info); |
183 | |
184 | THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to, |
185 | enum thr_lock_type lock_type); |
186 | |
187 | virtual uint8 table_cache_type(void) |
188 | { return HA_CACHE_TBL_NOCACHE; } |
189 | |
190 | virtual my_bool register_query_cache_table |
191 | (THD *, const char *, uint , qc_engine_callback *engine_callback, |
192 | ulonglong *) |
193 | { |
194 | *engine_callback= 0; |
195 | return FALSE; |
196 | } |
197 | |
198 | virtual void print_error(int error, myf errflags); |
199 | |
200 | private: |
201 | /** |
202 | Check if the caller is a replication thread or the caller is called |
203 | by a client thread executing base64 encoded BINLOG'... statement. |
204 | |
205 | In theory, performance schema tables are not supposed to be replicated. |
206 | This is true and enforced starting with MySQL 5.6.10. |
207 | In practice, in previous versions such as MySQL 5.5 (GA) or earlier 5.6 |
208 | (non GA) DML on performance schema tables could end up written in the binlog, |
209 | both in STATEMENT and ROW format. |
210 | While these records are not supposed to be there, they are found when: |
211 | - performing replication from a 5.5 master to a 5.6 slave during |
212 | upgrades |
213 | - performing replication from 5.5 (performance_schema enabled) |
214 | to a 5.6 slave |
215 | - performing point in time recovery in 5.6 with old archived logs. |
216 | |
217 | This API detects when the code calling the performance schema storage |
218 | engine is a slave thread or whether the code calling isthe client thread |
219 | executing a BINLOG'.. statement. |
220 | |
221 | This API acts as a late filter for the above mentioned cases. |
222 | |
223 | For ROW format, @see Rows_log_event::do_apply_event() |
224 | |
225 | */ |
226 | bool is_executed_by_slave() const |
227 | { |
228 | DBUG_ASSERT(table != NULL); |
229 | DBUG_ASSERT(table->in_use != NULL); |
230 | return table->in_use->slave_thread; |
231 | |
232 | } |
233 | |
234 | /** MySQL lock */ |
235 | THR_LOCK_DATA m_thr_lock; |
236 | /** Performance schema table share for this table handler. */ |
237 | const PFS_engine_table_share *m_table_share; |
238 | /** Performance schema table cursor. */ |
239 | PFS_engine_table *m_table; |
240 | }; |
241 | |
242 | /** @} */ |
243 | #endif |
244 | |
245 | |