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