<appendix xmlns="http://docbook.org/ns/docbook" version="5.0"
      xmlns:xlink="http://www.w3.org/1999/xlink"
      xml:id="plugins">

<title>Plugins</title>

<para>
A plugin is an optional library which enhances Tarantool functionality.
</para>

<para>
The details of creating one's own plugin are described on
<productname xlink:href="https://github.com/tarantool/tarantool/wiki/Plugin-API">the Tarantool Plugin API wiki page</productname>.
</para>

<para>
The discussion here in the user guide is about incorporating and using
two plugins that have already been created: the "SQL DBMS plugins" for
MySQL and PostgreSQL.
</para>

<para>
<bridgehead renderas="sect4">SQL DBMS Plugins</bridgehead>
To call another DBMS from Tarantool, the essential requirements are:
another DBMS, and Tarantool.
</para>

<para>
It will be necessary to build Tarantool from source,
as described in
<olink
targetptr="getting-started-source"><quote>Downloading and building a source package</quote></olink>.
</para>

<para>
The Tarantool plugins allow for connecting to an SQL server
and executing SQL statements the same way that a MySQL or PostgreSQL client does.
The SQL statements are visible as Lua methods. Thus Tarantool can
serve as a "MySQL Lua Connector" or "PostgreSQL Lua Connector", which would be useful even if
that was all Tarantool could do. But of course Tarantool is also
a DBMS, so the plugin also is useful for any operations, such as
database copying and accelerating, which work best when the application
can work on both SQL and Tarantool inside the same Lua routine.
</para>

<para>
<bridgehead renderas="sect4">MySQL Example</bridgehead>
This example assumes that MySQL 5.5 or MySQL 5.6 has been installed
(recent MariaDB versions should also work), and the mysqld server has
been started on the local host 127.0.0.1.
</para>

<para>
The example was run on a Linux machine where the base directory
had a copy of the Tarantool source on ~/tarantool-stable, and
a copy of MySQL on ~/mysql-5.5. The mysqld server is already running.
</para>

<programlisting>
# Check that the include subdirectory exists by looking for ~/include/mysql.h.
<prompt>$ </prompt><userinput>[ -f ~/mysql-5.5/include/mysql.h ] &amp;&amp; echo "OK" || echo "Error"</userinput>
OK

# Check that the library subdirectory exists and has the necessary .so file.
<prompt>$ </prompt><userinput>[ -f ~/mysql-5.5/lib/libmysqlclient.so ] &amp;&amp; echo "OK" || echo "Error"</userinput>
OK

# Check that the mysql client can connect using some factory defaults:
# port = 3306, user = 'root', user password = '', database = 'test'.
# These can be changed, provided one changes them in all places.
<prompt>$ </prompt><userinput>~/mysql-5.5/bin/mysql --port=3306 --host=127.0.0.1 --user=root --database=test</userinput>
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 25
Server version: 5.5.35 MySQL Community Server (GPL)
...
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

<prompt>mysql&gt;</prompt>

# Insert a row in database test, and quit.
<prompt>mysql&gt;</prompt> <userinput>CREATE TABLE IF NOT EXISTS test (s1 INT, s2 VARCHAR(50));</userinput>
Query OK, 0 rows affected (0.13 sec)
<prompt>mysql&gt;</prompt> <userinput>INSERT INTO test.test VALUES (1,'MySQL row');</userinput>
Query OK, 1 row affected (0.02 sec)
<prompt>mysql&gt;</prompt> <userinput>QUIT</userinput>
Bye

# Build the Tarantool server. Make certain that "cmake" gets the right
# paths for the MySQL include directory and the MySQL libmysqlclient
# library which were checked earlier.
<prompt>$ </prompt><userinput>cd ~/tarantool-stable</userinput>
<prompt>$ </prompt><userinput>make clean</userinput>
<prompt>$ </prompt><userinput>rm CMakeCache.txt</userinput>
<prompt>$ </prompt><userinput>cmake . -DWITH_MYSQL=on -DMYSQL_INCLUDE_DIR=~/mysql-5.5/include -DMYSQL_LIBRARIES=~/mysql-5.5/lib/libmysqlclient.so -DENABLE_CLIENT=true</userinput>
...
-- PostgreSQL client not found, box.net.sql(pg) disabled
-- Found MySQL includes: ~/mysql-5.5/include/mysql.h
-- Found MySQL library: ~/mysql-5.5/lib/libmysqlclient.so
-- box.net.sql(mysql) INC=~/mysql-5.5/include
-- box.net.sql(mysql) LIBS=~/mysql-5.5/lib/libmysqlclient.so
...
-- Configuring done
-- Generating done
-- Build files have been written to: ~/tarantool-stable
<prompt>$ </prompt><userinput>make</userinput>
...
[ 49%] Built target core
[ 50%] Building CXX object src/plugin/mysql/CMakeFiles/mysql.dir/mysql.cc.o
Linking CXX shared library libmysql.so
[ 50%] Built target mysql
...
[100%] Built target xlog
[100%] Built target man
<prompt>$ </prompt>

# Before starting Tarantool server, tell it where the MySQL plugin is.
<prompt>$ </prompt><userinput>export TARANTOOL_PLUGIN_DIR=~/tarantool-stable/src/plugin/mysql</userinput>
<prompt>$ </prompt>

# Start the Tarantool server.
# Run it in the background but let the initial display be in the foreground.
# So it's possible to see the message that the plugin was loaded.
<prompt>$ </prompt><userinput>~/tarantool-stable/src/box/tarantool_box&amp;</userinput>
2013-12-03 17:46:16.239 [12957] 1/sched C&gt; version 1.5.1-271-g610930e
2013-12-03 17:46:16.241 [12957] 1/sched I&gt; Loading plugin: ~/tarantool-stable/src/plugin/mysql/libmysql.so
2013-12-03 17:46:16.242 [12957] 1/sched I&gt; Plugin 'mysql' was loaded, version: 1
...
2013-12-03 17:46:16.244 [12957] 1/sched C&gt; entering event loop

# Type 'Enter' and then start the Tarantool client.
<prompt>$ </prompt><userinput>~/tarantool-stable/client/tarantool/tarantool</userinput>
<prompt>localhost&gt; </prompt>

# Say <quote>show plugins</quote>. Since all has gone well, this is certain to work.
<prompt>localhost&gt; </prompt> <userinput>show plugins</userinput>
---
plugins:
  - { name: "mysql", version: 1 }
...

# Create a Lua function that will connect to the MySQL server,
# retrieve one row, and display the row.
# For explanations of the statement types used here, read the
# Lua tutorial in the Tarantool user manual.
<prompt>localhost&gt; </prompt><userinput>SETOPT delimiter = '!'</userinput>
<prompt>localhost&gt; </prompt><userinput>lua function mysql_select ()</userinput>
        <prompt>-&gt; </prompt><userinput>  local dbh = box.net.sql.connect('mysql', '127.0.0.1', 3306, 'root', '', 'test')</userinput>
        <prompt>-&gt; </prompt><userinput>  local test = dbh:select('SELECT * FROM test WHERE s1 = 1')</userinput>
        <prompt>-&gt; </prompt><userinput>  for i, card in pairs(test) do</userinput>
        <prompt>-&gt; </prompt><userinput>    print(card.s2)</userinput>
        <prompt>-&gt; </prompt><userinput>    end</userinput>
        <prompt>-&gt; </prompt><userinput>  end!</userinput>
---
...
<prompt>localhost&gt; </prompt><userinput>SETOPT delimiter = ''!</userinput>
<prompt>localhost&gt; </prompt>

# Execute the Lua function.
<prompt>localhost&gt; </prompt><userinput>CALL mysql_select()</userinput>
2013-12-03 17:57:24.688 [12957] 102/iproto I&gt; MySQL row
Call OK, 0 rows affected

# Observe the result. It contains "MySQL row".
# So this is the row that was inserted with the mysql client.
# And now it's been selected with the Tarantool client.
</programlisting>

</appendix>

<!--
vim: tw=66 syntax=docbk
vim: spell spelllang=en_us
-->



