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