|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Applications: MySQL > tech-resources > articlesmysql_i_s_plugins_part1-2.html (Request Expert MySQL Support)
Skip navigation links
About the Author![]() In July 2006, Roland Bouman joined the MySQL Professional Services Team as a Certification Developer.
We are always looking for interesting articles
about MySQL! Have you written something and would like to it published
here? Please contact us via feedback form » Learn about new MySQL releases, technical articles, events and more. MySQL Information Schema Plugins: the best kept secret of MySQL 5.1MySQL 5.1 offers an extremely useful feature called information_schema plugins. This feature allows dynamic runtime loading of a shared library into the MySQL server to implement a table in the information_schema database. The SQL standard (ISO/IEC 9075-11:2003) allows database implementations to extend the In this article, we will demonstrate how to create a minimal "Hello, World!" MySQL information schema plugin. In a forthcoming article, we'll demonstrate how information schema plugins may be used to report some of the server's internals such as the contents of the query cache, session level objects such as the currently defined The MySQL Plug-in APIInformation Schema plug-ins are a subfeature of the MySQL plug-in API.
The plug-in API is one of the new features in the upcoming release of the MySQL database server, MySQL 5.1 (which is currently a release candidate). In essence, the MySQL plugin API provides a generic extension point to the MySQL server. It allows users to load a shared library in order to add new functionality to the server. Plug-ins can be loaded and unloaded using the MySQL specific In some respects, the new plugin feature resembles the since long supported user-defined function (UDF) feature. Both plugins and UDFs involve dynamically loading a shared library to extend the server's functionality. Like UDFs, plug-ins are usually written in C/C++. The difference between UDFs and plug-ins is that the UDF feature can be used only for adding new functions to use within the server's SQL dialect. The concept of a plug-in is more broadly applicable and can be used to extend the server in more ways. Currently, plug-ins are not supported on Microsoft Windows. MySQL is working to lift this limitation but it is at present unclear when this feature will be available for windows. Currently supported plug-in typesCurrently, the MySQL plug-in API supports the following types of plugins:
Currently the plug-in API does not provide support for UDFs but it is expected that in due time, the current user-defined function feature will be merged into the plug-in API. A closer look at the plug-in API(Note: in this article I will repeatedly refer to a number of C/C++ header and source files that are part of the MySQL 5.1.22-rc source distribution. Any path that starts with For all plug-in types, the interface comprises a generic plug-in description structure, which is a
The declaration of this structure is as follows:
/*
Plugin description structure.
*/
struct st_mysql_plugin
{
int type; /* the plugin type (a MYSQL_XXX_PLUGIN value) */
void *info; /* pointer to type-specific plugin descriptor */
const char *name; /* plugin name */
const char *author; /* plugin author (for SHOW PLUGINS) */
const char *descr; /* general descriptive text (for SHOW PLUGINS ) */
int license; /* the plugin license (PLUGIN_LICENSE_XXX) */
int (*init)(void *); /* the function to invoke when plugin is loaded */
int (*deinit)(void *);/* the function to invoke when plugin is unloaded */
unsigned int version; /* plugin version (for SHOW PLUGINS) */
struct st_mysql_show_var *status_vars;
struct st_mysql_sys_var **system_vars;
void * __reserved1; /* reserved for dependency checking */
};
Through this structure, the plug-in implementor provides the following things:
The type-dependent part of a plug-in implementation is usally a struct containing a number of function pointers ('hooks') which are called in a particular sequence that is appropriate for that particular type of plug-in. Information Schema PluginsSo what is an information_schema plug-in exactly? Well, the The SQL standard describes a number of views that should appear in the information_schema, and mysql provides partial built-in support for these standard information schema views. The standard also expressly allows database implementors to extend the information_schema by adding new views, or extending the specified tables by adding columns. MySQL information schema plug-ins simply form an interface to allow privileged database users to extend the information schema themselves by writing their own information schema table implementations. The type-specific API for Information Schema plug-insThe type-specific part of the plug-in API for information schema plug-ins is formed by the When the plug-in is loaded, the server calls the
The
These two elements really is all there is to the specific API for information schema plug-ins. Writing an Information Schema PluginIn this section, I will demonstrate how to write a minimal "Hello World!" MySQL information schema plugin. If you like, you can download the C++ source code. Apart from a text editor, writing a simple, bare bones information schema plug-in requires no more than a C++ compiler and a number of MySQL's C/C++ header files. The following examples assume a GNU/Linux environment, a simple text editor, the (For the purpose of this article, we will assume MySQL 5.1.22-rc. Until MySQL 5.1 is generally available, you are advised to always compile your plug-ins using only the header files shipped with the version of the product whereto the plug-in will be deployed.) Creating the source fileFirst, we need to create a C++ source file. We will assume that the working directory is IncludesIn the top of our source file, we need the include the following header files: #include The inclusion of
Defining the columnsIt was just mentioned that at some point, the plug-in implementor must provide an array of mysql> desc information_schema.MYSQL_HELLO; +-------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+-------+ | HELLO | varchar(64) | NO | | | | +-------+-------------+------+-----+---------+-------+ 1 row in set (0.00 sec) In order to achieve that, we need to declare our
static ST_FIELD_INFO mysql_is_hello_field_info[]=
{
{"HELLO", 64, MYSQL_TYPE_VARCHAR, 0, 0, "Hello", NULL},
{NULL, 0, MYSQL_TYPE_NULL, NULL, NULL, NULL, NULL}
};
The last entry of this array is a dummy that serves as a marker for the end of the array. It is very important to always conclude the array with one such entry. Without such a trailing entry, the server does not know where the array ends. This would of course be a very bad thing, and is likely to result in a crash as soon as the plugin is loaded or the information schema table is accessed. Now, the first
typedef struct st_field_info
{
const char* field_name;
uint field_length;
enum enum_field_types field_type;
int value;
uint field_flags; // Field atributes(maybe_null, signed, unsigned etc.)
const char* old_name;
Filling the tableWe explained that apart from defining the table columns, the plug-in implementor must also provide a function to actually deliver the rows. Before we can implement the actual bool schema_table_store_record(THD *thd, TABLE *table); This function is defined in Now we can create the actual int mysql_is_hello_fill_table(
THD *thd
, TABLE_LIST *tables
, COND *cond
)
{
int status;
CHARSET_INFO *scs= system_charset_info;
TABLE *table= (TABLE *)tables->table;
const char *str = "plugin: hello, information_schema!!!";
table->field[0]->store(
str
, strlen(str)
, scs
);
status = schema_table_store_record(
thd
, table
);
return status;
}
The server passes a number of arguments to the
The fill method first obtains a handle to the runtime representation of the information schema table proper: TABLE *table= (TABLE *)tables->table; Note that We then write the message
char *str = "plugin: hello, information_schema!!!";
table->field[0]->store(
str
, strlen(str)
, scs
);
So, each Like we just saw for The /* Store functions returns 1 on overflow and -1 on fatal error */ virtual int store(const char *to, uint length,CHARSET_INFO *cs)=0; Finally, we get to call the In most practical applications, one would likely have a loop to repeatedly store a row in the table, and one would have to interrupt the normal completion of that loop as soon as the
Putting together the plug-in type-specific implementationAt this point we've taken care of the individial elements to implement an information schema table: we created a Like mentioned before, a pointer to a
static int mysql_is_hello_plugin_init(void *p)
{
ST_SCHEMA_TABLE *schema= (ST_SCHEMA_TABLE *)p;
schema->
fields_info= mysql_is_hello_field_info;
schema->
fill_table= mysql_is_hello_fill_table;
return 0;
}
As we can see, there is very little to do here - we simply assign our implementations to the appropriate members of the We can immediately take care of the
static int mysql_is_hello_plugin_deinit(void *p)
{
return 0;
}
In this case, we can get away with this simple dummy implementation. In real-world examples, a plug-in might require some resource like memory or a file. In these cases, the Putting together the generic plug-in implementationWith the previous step, we concluded the process of creating the plug-in type specific implementation for an information_schema plug-in. The final touch is that we have to hook this up to the generic part of plug-in interface, that is, we have to provide a Rather than doing so directly, we use the predefined macros
struct st_mysql_information_schema mysql_is_hello_plugin=
{ MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION };
mysql_declare_plugin(mysql_is_hello)
{
MYSQL_INFORMATION_SCHEMA_PLUGIN, /* type constant */
&mysql_is_hello_plugin, /* type descriptor */
"MYSQL_HELLO", /* Name */
"Roland Bouman (http://rpbouman.blogspot.com/)", /* Author */
"Says hello.", /* Description */
PLUGIN_LICENSE_GPL, /* License */
mysql_is_hello_plugin_init, /* Init function */
mysql_is_hello_plugin_deinit, /* Deinit function */
0x0010, /* Version (1.0) */
NULL, /* status variables */
NULL, /* system variables */
We pass An important element in putting together the plug-in descriptor is the assignment of the Another important element is assigning the plug-in name, which we chose to be Building and installing the pluginNow that we have created the source file we must compile it and then install the plugin into our server. Compiling the plugin source fileAssuming the source file g++ -DMYSQL_DYNAMIC_PLUGIN -Wall -shared -I/home/roland/mysql-5.1.22-rc/include -I/home/roland/mysql-5.1.22-rc/regex -I/home/roland/mysql-5.1.22-rc/sql -o mysql_is_hello.so mysql_is_hello.cc Note that this is all on one line - I added line breaks to make it easier to read. If all goes well, this should result in a shared object file called Apart from the common The plugin directoryOnce we obtained the
The exact location of the plug-in directory is dependent upon specific MySQL distribution and configuration. You can find out its current location by querying the value of the plugin_dir system variable: mysql> show variables like 'plugin_dir'; +---------------+-----------------------------------------+ | Variable_name | Value | +---------------+-----------------------------------------+ | plugin_dir | /home/roland/mysql-5.1.22-dev/lib/mysql | +---------------+-----------------------------------------+ 1 row in set (0.01 sec) So in this case, the shared library Installing the pluginOnce the shared library is in place we can install it using the mysql> install plugin MYSQL_HELLO soname 'mysql_is_hello.so'; Query OK, 0 rows affected (0.00 sec) Note that we use the name In order to install a plug-in in this manner, the user has to have privileges to There is a common problem that might occur at this point: ERROR 1127 (HY000): Can't find symbol '_mysql_plugin_interface_version_' in library If you see a message like this, it is likely that you forgot to include the Verifying installationWe can now check if the plug-in is correctly installed. We do this by querying the
mysql> select * from
information_schema.plugins
-> where
plugin_name = 'MYSQL_HELLO'\G
*************************** 1. row ***************************
PLUGIN_NAME: MYSQL_HELLO
PLUGIN_VERSION: 0.16
PLUGIN_STATUS: ACTIVE
PLUGIN_TYPE: INFORMATION SCHEMA
PLUGIN_TYPE_VERSION: 50122.0
PLUGIN_LIBRARY: mysql_is_hello.so
PLUGIN_LIBRARY_VERSION: 1.0
PLUGIN_AUTHOR: Roland Bouman (http://rpbouman.blogspot.com/)
PLUGIN_DESCRIPTION: Says hello.
PLUGIN_LICENSE: GPL
1 row in set (0.00 sec)
Using the plug-inFinally, we get to test our plug-in ;-) mysql> select * from information_schema.mysql_hello; +--------------------------------------+ | HELLO | +--------------------------------------+ | plugin: hello, information_schema!!! | +--------------------------------------+ 1 row in set (0.00 sec) Of course, this is a gloriously useless application of information schema plug-ins. In a next installment I'll demonstrate that you can do pretty cool stuff with these information schema plug-ins, such as peeking inside the query cache, listing the currently defined savepoints, temporary tables, user variables and much more. Uninstalling the pluginWhen you get tired of the plugin you can uninstall it using the mysql> uninstall plugin MYSQL_HELLO; Query OK, 0 rows affected (0.00 sec) Note that currently, due to a bug, you must be sure to use the exact same name for uninstalling the plugin as you did for installing it. I suspect this will be fixed soon, but for now it is best to simply always use the same name, for example the exact name used in the code, Learn MoreI will be posting more about information schema plugins shortly. In particular, I will demonstrate how you can report status on server internals such as the query cache to discover which queries are in the cache, the number of blocks they are using and the number of bytes they actually occupying. However, the best way to learn more about extending the MySQL server, the MySQL plug-in API, and the MySQL information_schema is to visit the MySQL user's conference, April 14-17 2008 in Santa Clara CA, USA. There is a number of great sessions on this and related topics:
Of course, once you are at the conference, there will be many MySQL server developers giving you ample opportunity to ask them about some particular details, or maybe have them look at your code. And if you Register by February 26, 2008 you'll save up to $200. If you can't wait: other great sources of information may be found in the list below:
Cheers, and happy hacking ;-)
/* Copyright (C) 2008 Roland Bouman
* http://rpbouman.blogspot.com/
* roland.bouman@gmail.com
This file is part of the MYSQL_HELLO information_schema plugin.
This library is free software; you can redistribute it and/or
Comments?Read and post comments on this article in the MySQL Forums. There are currently 1 comments. © 1995-2008 MySQL AB. All rights reserved. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||


