1 // Copyright (c) 2017, 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, as
5 // 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
11 // additional permission to link the program and your derivative works
12 // with the separately licensed software that they have included with
13 // MySQL.
14 //
15 // Without limiting anything contained in the foregoing, this file,
16 // which is part of MySQL Server, is also subject to the
17 // Universal FOSS Exception, version 1.0, a copy of which can be found at
18 // http://oss.oracle.com/licenses/universal-foss-exception.
19 //
20 // This program is distributed in the hope that it will be useful, but
21 // WITHOUT ANY WARRANTY; without even the implied warranty of
22 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
23 // See the GNU General Public License, version 2.0, for more details.
24 //
25 // You should have received a copy of the GNU General Public License
26 // along with this program; if not, write to the Free Software Foundation, Inc.,
27 // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
28 
29 #ifndef PFS_PLUGIN_TABLE_SERVICE_H
30 #define PFS_PLUGIN_TABLE_SERVICE_H
31 
32 #include <mysql/components/service.h>
33 #include <mysql/components/service_implementation.h>
34 
35 /**
36   @page EXAMPLE_PLUGIN_COMPONENT Example plugin/component to use this service.
37 
38   Any plugin/component, which exposes tables in performance schema, has to
39   - provide implementation of interface PFS_engine_table_proxy.
40 
41   As there is no storage engine here to handle table data, plugin/component has
42   to:
43   - maintain storage for table being exposed.
44   - take care of handling any duplicate check (Primary/Unique Key, etc.)
45 
46   Following table explains datatypes exposed to plugin/component which should be
47   used for respective columns type in table.
48 
49   COLUMN TYPE | TO BE USED   | NULL VALUE INDICATION
50   ----------- | ------------ | :---------------------:
51    INTEGER    | PSI_int      |     is_null=true
52    TINYINT    | PSI_tinyint  |        -do-
53    SMALLINT   | PSI_smallint |        -do-
54    BIGINT     | PSI_bigint   |        -do-
55    MEDIUMINT  | PSI_mediumint|        -do-
56    DECIMAL    | PSI_decimal  |        -do-
57    FLOAT      | PSI_float    |        -do-
58    DOUBLE     | PSI_double   |        -do-
59    ENUM       | PSI_enum     |        -do-
60    YEAR       | PSI_year     |        -do-
61    DATE       | char array   |      length=0
62    TIME       | char array   |        -do-
63    DATETIME   | char array   |        -do-
64    TIMESTAMP  | char array   |        -do-
65    CHAR       | char array   |        -do-
66    VARCHAR    | char array   |        -do-
67    BLOB       | char array   |        -do-
68 
69    @section STEPS Steps to write a plugin/component exposing tables in
70   Performance Schema
71    - TBD
72 
73    Following are the example implementations of a plugin and a component which
74    uses this pfs_plugin_table service.
75 
76    @subpage EXAMPLE_PLUGIN
77 
78    @subpage EXAMPLE_COMPONENT
79 */
80 
81 /* Define ERRORS */
82 #define PFS_HA_ERR_WRONG_COMMAND 131
83 #define PFS_HA_ERR_RECORD_DELETED 134
84 #define PFS_HA_ERR_END_OF_FILE 137
85 #define PFS_HA_ERR_NO_REFERENCED_ROW 151
86 #define PFS_HA_ERR_FOUND_DUPP_KEY 121
87 #define PFS_HA_ERR_RECORD_FILE_FULL 135
88 
89 /* Helper macro */
90 struct PFS_string {
91   char *str;
92   unsigned int length;
93 };
94 typedef struct PFS_string PFS_string;
95 
96 /**
97   This is an opaque structure to denote filed in plugin/component code.
98 */
99 typedef struct PSI_field PSI_field;
100 /**
101   This is an opaque structure to denote table handle in plugin/component code.
102 */
103 typedef struct PSI_table_handle PSI_table_handle;
104 /**
105   This is an opaque structure to denote cursor position in plugin/component
106   code.
107 */
108 typedef struct PSI_pos PSI_pos;
109 /**
110   This is an opaque structure to denote Key Reader in plugin/component code.
111 */
112 typedef struct PSI_key_reader PSI_key_reader;
113 /**
114   This is an opaque structure to denote Index Handle in plugin/component code.
115 */
116 typedef struct PSI_index_handle PSI_index_handle;
117 
118 struct PSI_long {
119   long val;     /* Column value */
120   bool is_null; /* If Column value is NULL */
121 };
122 typedef struct PSI_long PSI_long;
123 
124 struct PSI_ulong {
125   unsigned long val; /* Column value */
126   bool is_null;      /* If Column value is NULL */
127 };
128 typedef struct PSI_ulong PSI_ulong;
129 
130 struct PSI_longlong {
131   long long val; /* Column value */
132   bool is_null /* If Column value is NULL */;
133 };
134 typedef struct PSI_longlong PSI_longlong;
135 
136 struct PSI_ulonglong {
137   unsigned long long val; /* Column value */
138   bool is_null /* If Column value is NULL */;
139 };
140 typedef struct PSI_ulonglong PSI_ulonglong;
141 
142 struct PSI_double {
143   double val; /* Column value */
144   bool is_null /* If Column value is NULL */;
145 };
146 typedef struct PSI_double PSI_double;
147 
148 #define PSI_tinyint PSI_long
149 #define PSI_utinyint PSI_ulong
150 #define PSI_smallint PSI_long
151 #define PSI_usmallint PSI_ulong
152 #define PSI_mediumint PSI_long
153 #define PSI_umediumint PSI_ulong
154 #define PSI_int PSI_long
155 #define PSI_uint PSI_ulong
156 #define PSI_bigint PSI_longlong
157 #define PSI_ubigint PSI_ulonglong
158 #define PSI_year PSI_ulong
159 #define PSI_enum PSI_ulonglong
160 #define PSI_decimal PSI_double
161 #define PSI_float PSI_double
162 
163 /**
164   A structure to denote a key of type long in an index.
165 */
166 struct PSI_plugin_key_integer {
167   /* name of the key column */
168   const char *m_name;
169   /* find flags */
170   int m_find_flags;
171   /* is column NULL */
172   bool m_is_null;
173   /* value of the key column */
174   long m_value;
175 };
176 typedef struct PSI_plugin_key_integer PSI_plugin_key_integer;
177 
178 /**
179   A structure to denote a key of type string in an index.
180 */
181 struct PSI_plugin_key_string {
182   /* name of the key column */
183   const char *m_name;
184   /* find flags */
185   int m_find_flags;
186   /* is column null */
187   bool m_is_null;
188   /* buffer to store key column value */
189   char *m_value_buffer;
190   // FIXME: size_t
191   /* length of the key value in buffer */
192   unsigned int m_value_buffer_length;
193   /* Maximum size of buffer */
194   unsigned int m_value_buffer_capacity;
195 };
196 typedef struct PSI_plugin_key_string PSI_plugin_key_string;
197 
198 /**
199   Api to read the next record.
200   @param handle Table handle.
201 
202   @return Operation status
203   @retval 0    Success
204   @retval !=0  Error
205 */
206 typedef int (*rnd_next_t)(PSI_table_handle *handle);
207 
208 /**
209   API to initialize for random scan or read.
210   @param handle Table handle.
211   @param scan True, if its a random scan.
212               False, if its a random read.
213 
214   @return Operation status
215   @retval 0    Success
216   @retval !=0  Error
217 */
218 typedef int (*rnd_init_t)(PSI_table_handle *handle, bool scan);
219 
220 /**
221   API to read row from a position which is set in table handle.
222   @param handle Table handle.
223 
224   @return Operation status
225   @retval 0    Success
226   @retval !=0  Error
227 */
228 typedef int (*rnd_pos_t)(PSI_table_handle *handle);
229 
230 /**
231   API to initialize index(es).
232   @param handle Table handle.
233   @param idx    Index of the index to be initialized (in case of multiple
234                 indexes on table)
235   @param sorted
236   @param index  Initialized index handle.
237 
238   @return Operation status
239   @retval 0    Success
240   @retval !=0  Error
241 */
242 typedef int (*index_init_t)(PSI_table_handle *table, unsigned int idx,
243                             bool sorted, PSI_index_handle **index);
244 /**
245   API to read keys in index.
246   @param index      Index handle.
247   @param reader     Key reader.
248   @param idx        Index of the index to be read.
249   @param find_flag  find flag.
250 
251   @return Operation status
252   @retval 0    Success
253   @retval !=0  Error
254 */
255 typedef int (*index_read_t)(PSI_index_handle *index, PSI_key_reader *reader,
256                             unsigned int idx, int find_flag);
257 
258 /**
259   API to read next record with matching index.
260   @param handle Table handle.
261 
262   @return Operation status
263   @retval 0    Success
264   @retval !=0  Error
265 */
266 typedef int (*index_next_t)(PSI_table_handle *table);
267 
268 /**
269   API to reset cursor position
270   @param handle Table handle.
271 */
272 typedef void (*reset_position_t)(PSI_table_handle *handle);
273 
274 /**
275   API to read a column value from table.
276   @param handle Table handle.
277   @param field  Field for which value is to be read.
278   @param index  Index of field in table column.
279 
280   @return Operation status
281   @retval 0    Success
282   @retval !=0  Error
283 */
284 typedef int (*read_column_value_t)(PSI_table_handle *handle, PSI_field *field,
285                                    unsigned int index);
286 
287 /**
288   API to write a column value in table.
289   @param handle Table handle.
290   @param field  Field for which value is to be written.
291   @param index  Index of field in table column.
292 
293   @return Operation status
294   @retval 0    Success
295   @retval !=0  Error
296 */
297 typedef int (*write_column_value_t)(PSI_table_handle *handle, PSI_field *fields,
298                                     unsigned int index);
299 /**
300   API to write a record in table.
301   @param handle Table handle having new record to be written.
302 */
303 typedef int (*write_row_values_t)(PSI_table_handle *handle);
304 
305 /**
306   API to update a column value in table.
307   @param handle Table handle.
308   @param field  Field for which value is to be updated.
309   @param index  Index of field in table column.
310 
311   @return Operation status
312   @retval 0    Success
313   @retval !=0  Error
314 */
315 typedef int (*update_column_value_t)(PSI_table_handle *handle,
316                                      PSI_field *fields, unsigned int index);
317 /**
318   API to write a record in table.
319   @param handle Table handle having updated record to be updated.
320 */
321 typedef int (*update_row_values_t)(PSI_table_handle *handle);
322 
323 /**
324   API to delete record from table.
325   @param handle Table handle having record to be deleted.
326 */
327 typedef int (*delete_row_values_t)(PSI_table_handle *handle);
328 
329 /**
330   API to Open a table handle in plugin/component code and reset position
331   pointer when a new table handle in opened in Performance Schema.
332   @param pos pos pointer to be updated.
333 
334   @return initialized table handle.
335 */
336 typedef PSI_table_handle *(*open_table_t)(PSI_pos **pos);
337 
338 /**
339   API to Close a table handle in plugin/component code and reset position
340   pointer when a table handle in closed in Performance Schema.
341   @param handle table handle
342 */
343 typedef void (*close_table_t)(PSI_table_handle *handle);
344 
345 /**
346  A structure to keep callback functions to be implemented by
347  plugin/component.
348 */
349 struct PFS_engine_table_proxy {
350   rnd_next_t rnd_next;
351   rnd_init_t rnd_init;
352   rnd_pos_t rnd_pos;
353   index_init_t index_init;
354   index_read_t index_read;
355   index_next_t index_next;
356   read_column_value_t read_column_value;
357   reset_position_t reset_position;
358   write_column_value_t write_column_value;
359   write_row_values_t write_row_values;
360   update_column_value_t update_column_value;
361   update_row_values_t update_row_values;
362   delete_row_values_t delete_row_values;
363   open_table_t open_table;
364   close_table_t close_table;
365   PFS_engine_table_proxy() = default;
366 };
367 typedef struct PFS_engine_table_proxy PFS_engine_table_proxy;
368 
369 /**
370   Types of access allowed to tables.
371 */
372 enum Access_control {
373   /* Only Read is allowed */
374   READONLY = 0,
375   /* Read/Truncate allowed but no Update/Insert/Delete. */
376   TRUNCATABLE,
377   /* Read/Truncate/Update allowed but no Insert/Delete. */
378   UPDATABLE,
379   /* Read/Truncate/Insert/UPDATE/Delete allowed. */
380   EDITABLE
381 };
382 
383 /**
384   API to delete/truncate all the rows in a table
385 */
386 typedef int (*delete_all_rows_t)(void);
387 
388 /**
389   API to give number of rows in a table
390 
391   @return number of rows.
392 */
393 typedef unsigned long long (*get_row_count_t)(void);
394 
395 /**
396   A share to be initialized by plugin/component code and to be provided
397   to add_table() service method of pfs_plugin_table service.
398  */
399 struct PFS_engine_table_share_proxy {
400  public:
401   /* Callback functions list of APIs */
402   PFS_engine_table_proxy m_proxy_engine_table;
403 
404   /* Name of the table to be added */
405   const char *m_table_name;
406   /* Length of the table name */
407   unsigned int m_table_name_length;
408 
409   /* Table Columns definition */
410   const char *m_table_definition;
411   unsigned int m_ref_length;
412 
413   /* Access allowed on the table */
414   enum Access_control m_acl;
415 
416   delete_all_rows_t delete_all_rows;
417   get_row_count_t get_row_count;
418 };
419 typedef struct PFS_engine_table_share_proxy PFS_engine_table_share_proxy;
420 
421 /**
422   Definition of pfs_plugin_table service and its methods.
423 */
424 BEGIN_SERVICE_DEFINITION(pfs_plugin_table)
425 /* Methods to add tables in Performance Schema */
426 DECLARE_METHOD(int, add_tables,
427                (PFS_engine_table_share_proxy * *st_share,
428                 unsigned int share_count));
429 
430 /* Methods to delete tables in Performance Schema */
431 DECLARE_METHOD(int, delete_tables,
432                (PFS_engine_table_share_proxy * *st_share,
433                 unsigned int share_count));
434 
435 /* TINYINT */
436 DECLARE_METHOD(void, set_field_tinyint, (PSI_field * f, PSI_tinyint value));
437 DECLARE_METHOD(void, set_field_utinyint, (PSI_field * f, PSI_utinyint value));
438 DECLARE_METHOD(void, get_field_tinyint, (PSI_field * f, PSI_tinyint *value));
439 
440 /* SMALLINT */
441 DECLARE_METHOD(void, set_field_smallint, (PSI_field * f, PSI_smallint value));
442 DECLARE_METHOD(void, set_field_usmallint, (PSI_field * f, PSI_usmallint value));
443 DECLARE_METHOD(void, get_field_smallint, (PSI_field * f, PSI_smallint *value));
444 
445 /* MIDIUMINT */
446 DECLARE_METHOD(void, set_field_mediumint, (PSI_field * f, PSI_mediumint value));
447 DECLARE_METHOD(void, set_field_umediumint,
448                (PSI_field * f, PSI_umediumint value));
449 DECLARE_METHOD(void, get_field_mediumint,
450                (PSI_field * f, PSI_mediumint *value));
451 
452 /* INTEGER(INT) */
453 DECLARE_METHOD(void, set_field_integer, (PSI_field * f, PSI_int value));
454 DECLARE_METHOD(void, set_field_uinteger, (PSI_field * f, PSI_uint value));
455 DECLARE_METHOD(void, get_field_integer, (PSI_field * f, PSI_int *value));
456 DECLARE_METHOD(void, read_key_integer,
457                (PSI_key_reader * reader, PSI_plugin_key_integer *key,
458                 int find_flag));
459 DECLARE_METHOD(bool, match_key_integer,
460                (bool record_null, long record_value,
461                 PSI_plugin_key_integer *key));
462 
463 /* BIGINT */
464 DECLARE_METHOD(void, set_field_bigint, (PSI_field * f, PSI_bigint value));
465 DECLARE_METHOD(void, set_field_ubigint, (PSI_field * f, PSI_ubigint value));
466 DECLARE_METHOD(void, get_field_bigint, (PSI_field * f, PSI_bigint *value));
467 
468 /* DECIMAL */
469 DECLARE_METHOD(void, set_field_decimal, (PSI_field * f, PSI_double value));
470 DECLARE_METHOD(void, get_field_decimal, (PSI_field * f, PSI_double *value));
471 
472 /* FLOAT */
473 DECLARE_METHOD(void, set_field_float, (PSI_field * f, PSI_double value));
474 DECLARE_METHOD(void, get_field_float, (PSI_field * f, PSI_double *value));
475 
476 /* DOUBLE */
477 DECLARE_METHOD(void, set_field_double, (PSI_field * f, PSI_double value));
478 DECLARE_METHOD(void, get_field_double, (PSI_field * f, PSI_double *value));
479 
480 /* CHAR */
481 DECLARE_METHOD(void, set_field_char_utf8,
482                (PSI_field * f, const char *value, unsigned int length));
483 DECLARE_METHOD(void, get_field_char_utf8,
484                (PSI_field * f, char *str, unsigned int *length));
485 DECLARE_METHOD(void, read_key_string,
486                (PSI_key_reader * reader, PSI_plugin_key_string *key,
487                 int find_flag));
488 DECLARE_METHOD(bool, match_key_string,
489                (bool record_null, const char *record_string_value,
490                 unsigned int record_string_length, PSI_plugin_key_string *key));
491 
492 /* VARCHAR */
493 DECLARE_METHOD(void, set_field_varchar_utf8, (PSI_field * f, const char *str));
494 DECLARE_METHOD(void, set_field_varchar_utf8_len,
495                (PSI_field * f, const char *str, unsigned int len));
496 DECLARE_METHOD(void, get_field_varchar_utf8,
497                (PSI_field * f, char *str, unsigned int *length));
498 
499 DECLARE_METHOD(void, set_field_varchar_utf8mb4,
500                (PSI_field * f, const char *str));
501 DECLARE_METHOD(void, set_field_varchar_utf8mb4_len,
502                (PSI_field * f, const char *str, unsigned int len));
503 
504 /* BLOB/TEXT */
505 DECLARE_METHOD(void, set_field_blob,
506                (PSI_field * f, const char *val, unsigned int len));
507 DECLARE_METHOD(void, get_field_blob,
508                (PSI_field * f, char *val, unsigned int *len));
509 
510 /* ENUM */
511 DECLARE_METHOD(void, set_field_enum, (PSI_field * f, PSI_enum value));
512 DECLARE_METHOD(void, get_field_enum, (PSI_field * f, PSI_enum *value));
513 
514 /* DATE */
515 DECLARE_METHOD(void, set_field_date,
516                (PSI_field * f, const char *str, unsigned int length));
517 DECLARE_METHOD(void, get_field_date,
518                (PSI_field * f, char *val, unsigned int *len));
519 
520 /* TIME */
521 DECLARE_METHOD(void, set_field_time,
522                (PSI_field * f, const char *str, unsigned int length));
523 DECLARE_METHOD(void, get_field_time,
524                (PSI_field * f, char *val, unsigned int *len));
525 
526 /* DATETIME */
527 DECLARE_METHOD(void, set_field_datetime,
528                (PSI_field * f, const char *str, unsigned int length));
529 DECLARE_METHOD(void, get_field_datetime,
530                (PSI_field * f, char *val, unsigned int *len));
531 
532 /* TIMESTAMP */
533 DECLARE_METHOD(void, set_field_timestamp,
534                (PSI_field * f, const char *str, unsigned int length));
535 DECLARE_METHOD(void, get_field_timestamp,
536                (PSI_field * f, char *val, unsigned int *len));
537 
538 /* YEAR */
539 DECLARE_METHOD(void, set_field_year, (PSI_field * f, PSI_year value));
540 DECLARE_METHOD(void, get_field_year, (PSI_field * f, PSI_year *value));
541 
542 /* NULL */
543 DECLARE_METHOD(void, set_field_null, (PSI_field * f));
544 
545 END_SERVICE_DEFINITION(pfs_plugin_table)
546 
547 #endif
548