Skip to content
Snippets Groups Projects
Commit 76f3942f authored by ocelot-inc's avatar ocelot-inc
Browse files

stored-procedures.xml revised box.net.box

parent 33b80295
No related branches found
No related tags found
No related merge requests found
......@@ -1315,7 +1315,7 @@ localhost&gt; <userinput>lua t:transform(1,2,'x')</userinput>
then the result is returned.
</para>
<bridgehead renderas="sect4">Example</bridgehead>
<programlisting>localhost&gt; lua t=box.tuple.new({'Field#1','Field#2','Field#3','Field#4','Field#5'})
<programlisting>localhost&gt; <userinput>lua t=box.tuple.new({'Field#1','Field#2','Field#3','Field#4','Field#5'})</userinput>
---
...
localhost&gt; <userinput>lua t:slice(1,3)</userinput>
......@@ -2619,75 +2619,41 @@ end
<section xml:id="sp-box-net-box">
<title>Package <code>box.net.box</code> &mdash; working with networked Tarantool peers</title>
<simpara>
Library <code>box.net</code> contains connectors
to remote database systems, such as MariaDB or PostgreSQL.
The first supported system is Tarantool itself.
The <code>box.net</code> library contains connectors to remote database systems.
One variant, <code>box.net.sql</code>, is for connecting to MySQL or MariaDB or PostgreSQL
&mdash; that variant is the subject of the <quote>SQL DBMS plugins</quote> appendix.
In this section the subject is the built-in variant, <code>box.net.box</code>.
This is for connecting to tarantool_box servers via a network.
</simpara>
<variablelist xml:id="box.net.box">
<simpara>
The basic object provided by <code>box.net.box</code>
library is a connection. A connection is created by
calling <code>box.net.box.new()</code>. To
execute remote requests, simply invoke methods of the
connection object, a physical connection is established
upon request and is re-established if necessary.
When done, issue <code>conn:close()</code>. Connection
objects are garbage collected just like any other objects
in Lua, so an explicit destruction is not mandatory.
However, since <code>close()</code> is a system call, it
is a good programming practice to close a connection
explicitly when it is no longer needed, to avoid lengthy
stalls of the garbage collector.
</simpara>
<simpara>
The library also provides a pre-created connection object
to the local server, <code>box.net.self</code>. This
connection is always <quote>established</quote>. The
purpose of this object is to make polymorphic use of the
<code>box.net.box</code> API easier. There is an
important difference, however, between the embedded
connection and a remote one. With the embedded connection,
requests which do not modify data do not yield. When using
a remote connection, it is important to keep in mind that
any request can yield, and local database state may
have changed by the time it returns.
Call <code>box.net.box.new()</code> to connect and get a connection object,
which will be called <code>conn</code> for examples in this section.
Call the other <code>box.net.box()</code> routines, passing <code>conn</code>,
to execute requests on the remote box.
Call <code>box.net.box.close(conn)</code> to disconnect.
Object-oriented and functional APIs are equivalent, so
<code>conn:close()</code> is the same as <code>box.net.box.close(conn)</code>.
</simpara>
<simpara>
All <code>box.net.box</code> methods are fiber-safe. It's
All <code>box.net.box</code> methods are fiber-safe, that is, it is
safe to share and use the same connection object across
multiple concurrent fibers. In fact, it's perhaps the
best programming practice with Tarantool: when multiple
multiple concurrent fibers. In fact, it's perhaps the
best programming practice with Tarantool. When multiple
fibers use the same connection, all requests are pipelined
through the same network socket, but each fiber gets a
correct response back. Reducing the number of active sockets
through the same network socket, but each fiber gets back a
correct response. Reducing the number of active sockets
lowers the overhead of system calls and increases the
overall server performance. There are, however cases, when
a single connection is not enough: when it's necessary to
prioritize requests, use different authentication ids,
etc.
</simpara>
<simpara>
All remote calls support execution timeouts. A specialized
wrapper, <code>box.net.box.timeout()</code> allows setting
a timeout. Using a wrapper object makes the remote
connection API compatible with the local one, removing
the need for a separate <code>timeout</code> argument, ignored
by the local version. Once sent, a
request can not be revoked from the remote server even if
a timeout expires: the expired timeout only aborts the
wait for the remote server response.
<code>box.net.box.timeout()</code>,
</simpara>
<simpara>
Object-oriented and functional APIs are equivalent:
<code>conn:close()</code> is identical to
<code>box.net.box.close(conn)</code>.
overall server performance. There are, however, cases when
a single connection is not enough &mdash; for example when it's necessary to
prioritize requests or to use different authentication ids.
</simpara>
<varlistentry>
<term>
<emphasis role="lua" xml:id="box.net.box.new">
conn = box.net.box.new(host, port [, reconnect_interval])</emphasis>
conn = box.net.box.new(<replaceable>host</replaceable>, <replaceable>port</replaceable> [, <replaceable>reconnect_interval</replaceable>])</emphasis>
</term>
<listitem>
<para>
......@@ -2697,155 +2663,220 @@ end
a disconnect. The argument
<code>reconnect_interval</code> (in seconds) is
responsible for the amount of time the server
sleeps between failing attempts to reconnect. The
returned object supports methods for making remote
calls, such as select, update or delete.
sleeps between failing attempts to reconnect.
The returned <code>conn</code> object supports methods for making remote
requests, such as select, update or delete.
Example: <code>conn = box.net.box.new('localhost', 33013)</code>.
</para>
<para>
For the local tarantool_box server there is a pre-created always-established
connection object named <code>box.net.self</code>.
Its purpose is to make polymorphic use of the
<code>box.net.box</code> API easier. Therefore
<code>conn = box.net.box.new('localhost', 33013)</code> can
be replaced by <code>conn = box.net.box.self</code>.
However, there is an important difference between the embedded
connection and a remote one. With the embedded connection,
requests which do not modify data do not yield. When using
a remote connection, any request can yield, and local database state may
have changed by the time it returns.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis role="lua" xml:id="box.net.box.ping">
conn:ping()</emphasis></term>
conn:ping()</emphasis></term>
<listitem>
<para>
Execute a PING command.
Returns <code>true</code> on success,
<code>false</code> on error.
<code>false</code> on error. Example: <code>self:ping()</code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis role="lua" xml:id="box.net.box.close">
conn:close()</emphasis></term>
conn:close()</emphasis></term>
<listitem>
<para>
Close a connection. The connection is also
closed when it's garbage collected. It's still
recommended to close connections explicitly,
to spare the garbage collector from heavy work
such as closing the socket.
Close a connection. Example: <code>conn:close()</code>.
</para>
<para>
Connection objects are garbage collected just like any other objects
in Lua, so an explicit destruction is not mandatory.
However, since <code>close()</code> is a system call, it
is good programming practice to close a connection
explicitly when it is no longer needed, to avoid lengthy
stalls of the garbage collector.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis role="lua" xml:id="box.net.box.select">
conn:select(space_no, index_no, ...)</emphasis></term>
conn:select(<replaceable>space_no</replaceable>, <replaceable>index_no</replaceable>, ...)</emphasis></term>
<listitem>
<para>
See <code
xlink:href="#box.select">box.select(...)</code>.
Please note, that unlike a local
<code>box.select()</code> any call to a remote
server yields, thus local data may change while
remote <code>select()</code> is running.
<code>conn:select(...)</code> is the remote-call equivalent of the local call <code xlink:href="#box.select">box.select(...)</code>.
Please note this difference: a local <code>box.select()</code> does not yield,
but a remote <code>conn:select()</code> call does yield,
so local data may change while a remote <code>conn:select()</code> is running.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis role="lua" xml:id="box.net.box.select_limit">
conn:select_limit(space_no, index_no, offset, limit, ...)</emphasis></term>
conn:select_limit(<replaceable>space_no</replaceable>, <replaceable>index_no</replaceable>, <replaceable>offset</replaceable>, <replaceable>limit</replaceable>, ...)</emphasis></term>
<listitem>
<para>
See <code
xlink:href="#box.select_limit">box.select_limit(...)</code>
<code>conn:select_limit(...)</code> is the remote-call equivalent of the local call <code xlink:href="#box.select_limit">box.select_limit(...)</code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis role="lua" xml:id="box.net.box.select_range">
conn:select_range(space_no, index_no, limit, key, ...)</emphasis></term>
conn:select_range(<replaceable>space_no</replaceable>, <replaceable>index_no</replaceable>, <replaceable>limit</replaceable>, <replaceable>key</replaceable>, ...)</emphasis></term>
<listitem>
<para>
See <code
xlink:href="#box.select_range">box.select_range(...)</code>.
<code>conn:select_range(...)</code> is the remote-call equivalent of the local call <code xlink:href="#box.select_range">box.select_range(...)</code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis role="lua" xml:id="box.net.box.insert">conn:insert(space_no, ...)</emphasis></term>
<term><emphasis role="lua" xml:id="box.net.box.insert">
conn:insert(<replaceable>space_no</replaceable>, ...)</emphasis></term>
<listitem>
<para>
See <code xlink:href="#box.insert">box.insert(...)</code>.
<code>conn:insert(...)</code> is the remote-call equivalent of the local call <code xlink:href="#box.insert">box.insert(...)</code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis role="lua" xml:id="box.net.box.replace">conn:replace(space_no, ...)</emphasis></term>
<term><emphasis role="lua" xml:id="box.net.box.replace">
conn:replace(<replaceable>space_no</replaceable>, ...)</emphasis></term>
<listitem>
<para>
See <code xlink:href="#box.replace">box.replace(...)</code>.
<code>conn:replace(...)</code> is the remote-call equivalent of the local call <code xlink:href="#box.replace">box.replace(...)</code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis role="lua" xml:id="box.net.box.update">conn:update(...)</emphasis></term>
<term><emphasis role="lua" xml:id="box.net.box.update">
conn:update(<replaceable>space_no</replaceable>, <replaceable>key</replaceable>, <replaceable>format</replaceable>, ...)</emphasis></term>
<listitem>
<para>
See <code
xlink:href="#box.update">box.update(...)</code>.
<code>conn:update(...)</code> is the remote-call equivalent of the local call <code xlink:href="#box.update">box.update(...)</code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis role="lua" xml:id="box.net.box.delete">conn:delete(space_no, key)</emphasis></term>
<term><emphasis role="lua" xml:id="box.net.box.delete">
conn:delete(<replaceable>space_no</replaceable>, <replaceable>key</replaceable>)</emphasis></term>
<listitem>
<para>
See <code xlink:href="#box.delete">box.delete(...)</code>.
<code>conn:delete(...)</code> is the remote-call equivalent of the local call <code xlink:href="#box.delete">box.delete(...)</code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis role="lua" xml:id="box.net.box.call">conn:call(proc_name, ...)</emphasis></term>
<term><emphasis role="lua" xml:id="box.net.box.call">
conn:call(<replaceable>proc_name</replaceable> [, <replaceable>arguments</replaceable>])</emphasis></term>
<listitem>
<para>Call a remote stored procedure, such as
<code>box.select_reverse_range()</code>.
<para>
<code>conn:call('proc','1','2','3')</code> is the remote-call equivalent of <code>CALL proc('1','2','3')</code>.
That is, box.net.box.call is a remote stored-procedure call.
Please keep in mind that the call is using
the binary protocol to pack procedure arguments,
and since the latter is type-agnostic it's recommended
to pass all arguments of remote stored procedure as
strings, for example:
<programlisting>
conn:call("box.select_reverse_range", "1", "4", "10", "Smith")
</programlisting>
and the binary protocol is type agnostic, so it's recommended
to pass all arguments of remote stored procedure calls as
strings. Example: <code>conn:call("box.select_reverse_range", "1", "4", "10", "Smith")</code>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis role="lua" xml:id="box.net.box.timeout">conn:timeout(timeout)</emphasis></term>
<term><emphasis role="lua" xml:id="box.net.box.timeout">
conn:timeout(<replaceable>timeout</replaceable>)</emphasis></term>
<listitem>
<para>
Returns a closure which is identical to the
invoked function, except for the added timeout
functionality.
<programlisting>
-- wait for 'update' until it is finished
local tuple = conn:update('1', 'key', ...)
-- send update but don't bother to wait for results
local other = conn:timeout(0):update('1', 'arg1', ...)
</programlisting>
</para>
<code>timeout(...)</code> is a wrapper which sets a timeout for the request that follows it.
Example: <code>conn:timeout(0):update('1', 'arg1', 15)</code>.
</para>
<para>
All remote calls support execution timeouts.
Using a wrapper object makes the remote
connection API compatible with the local one, removing
the need for a separate <code>timeout</code> argument, which
the local version would ignore. Once a request is sent,
it cannot be revoked from the remote server even if
a timeout expires: the timeout expiration only aborts the
wait for the remote server response, not the request itself.
</para>
</listitem>
</varlistentry>
</variablelist>
<bridgehead renderas="sect4">Example</bridgehead>
<programlisting>
-- connect to the local server
local self = box.net.box.new('127.0.0.1', box.info.primary_port)
self:insert("1", "Hello", "World")
<bridgehead renderas="sect4">Example showing use of most of the box.net.box methods</bridgehead>
<para>
This example will work with the sandbox configuration described in the preface.
That is, there is a space[0] with a numeric primary key.
Assume that the database is nearly empty.
Assume that the tarantool_box server is running on localhost 127.0.0.1:33013.
<programlisting><prompt>localhost&gt;</prompt> <userinput> setopt delimiter = '!'</userinput>
<prompt>localhost&gt;</prompt> <userinput> lua function example()</userinput>
<prompt> -&gt;</prompt> <userinput> if self:ping() then</userinput>
<prompt> -&gt;</prompt> <userinput> print("self:ping() succeeded (not surprising since self is a pre-established connection).")</userinput>
<prompt> -&gt;</prompt> <userinput> end</userinput>
<prompt> -&gt;</prompt> <userinput> if box.cfg.primary_port == 33013 then</userinput>
<prompt> -&gt;</prompt> <userinput> print('The local server primary port number is 33013 (the default)')</userinput>
<prompt> -&gt;</prompt> <userinput> else</userinput>
<prompt> -&gt;</prompt> <userinput> print('The local server primary port number is not 33013, so connect will fail')</userinput>
<prompt> -&gt;</prompt> <userinput> end</userinput>
<prompt> -&gt;</prompt> <userinput> conn = box.net.box.new('127.0.0.1', 33013)</userinput>
<prompt> -&gt;</prompt> <userinput> conn:delete(0,800)</userinput>
<prompt> -&gt;</prompt> <userinput> print('conn:delete done on space[0].')</userinput>
<prompt> -&gt;</prompt> <userinput> conn:insert(0,800,'data')</userinput>
<prompt> -&gt;</prompt> <userinput> print('conn:insert done on space[0], index 0. primary key value = 800.')</userinput>
<prompt> -&gt;</prompt> <userinput> wtuple = conn:select(0,0,800)</userinput>
<prompt> -&gt;</prompt> <userinput> print('conn:select done on space[0], index 0. number of fields = ', #wtuple)</userinput>
<prompt> -&gt;</prompt> <userinput> conn:delete(0,800)</userinput>
<prompt> -&gt;</prompt> <userinput> print('conn:delete done on space[0].')</userinput>
<prompt> -&gt;</prompt> <userinput> conn:replace(0,800,'New data','Extra data')</userinput>
<prompt> -&gt;</prompt> <userinput> print('conn:replace done on space[0].')</userinput>
<prompt> -&gt;</prompt> <userinput> conn:timeout(0):update(0,800,'=p=p=p',1, 'Field#1', 2,'Field#2', 3,'Field#3')</userinput>
<prompt> -&gt;</prompt> <userinput> print('conn:update done on space[0], timed out after waiting 0 seconds for a return')</userinput>
<prompt> -&gt;</prompt> <userinput> conn:close()</userinput>
<prompt> -&gt;</prompt> <userinput> print('conn:close done')</userinput>
<prompt> -&gt;</prompt> <userinput> end!</userinput>
---
...
<prompt>localhost&gt;</prompt> <userinput> setopt delimiter = ''!</userinput>
<prompt>localhost&gt;</prompt> <userinput> lua example()</userinput>
---
self:ping() succeeded (not surprising since self is a pre-established connection).
The local server primary port number is 33013 (the default)
conn:delete done on space[0].
conn:insert done on space[0], index 0. primary key value = 800.
conn:select done on space[0], index 0. number of fields = 2
conn:delete done on space[0].
conn:replace done on space[0].
conn:update done on space[0], timed out after waiting 0 seconds for a return
conn:close done
...
<prompt>localhost&gt;</prompt> <userinput> select * from t0 where k0 = 800 # Prove that the update succeeded.</userinput>
Select OK, 1 rows affected
[800, 'Field#1', 'Field#2', 'Field#3']
</programlisting>
</para>
</section>
<section xml:id="sp-box-cfg">
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment