From 76f3942f3d232f2483a1b8896db148804152fa1f Mon Sep 17 00:00:00 2001 From: ocelot-inc <pgulutzan@ocelot.ca> Date: Sat, 7 Dec 2013 20:13:25 -0700 Subject: [PATCH] stored-procedures.xml revised box.net.box --- doc/user/stored-procedures.xml | 263 ++++++++++++++++++--------------- 1 file changed, 147 insertions(+), 116 deletions(-) diff --git a/doc/user/stored-procedures.xml b/doc/user/stored-procedures.xml index cbc988fa95..f884cbeada 100644 --- a/doc/user/stored-procedures.xml +++ b/doc/user/stored-procedures.xml @@ -1315,7 +1315,7 @@ localhost> <userinput>lua t:transform(1,2,'x')</userinput> then the result is returned. </para> <bridgehead renderas="sect4">Example</bridgehead> - <programlisting>localhost> lua t=box.tuple.new({'Field#1','Field#2','Field#3','Field#4','Field#5'}) + <programlisting>localhost> <userinput>lua t=box.tuple.new({'Field#1','Field#2','Field#3','Field#4','Field#5'})</userinput> --- ... localhost> <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> — 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 + — 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 — 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></prompt> <userinput> setopt delimiter = '!'</userinput> +<prompt>localhost></prompt> <userinput> lua function example()</userinput> +<prompt> -></prompt> <userinput> if self:ping() then</userinput> +<prompt> -></prompt> <userinput> print("self:ping() succeeded (not surprising since self is a pre-established connection).")</userinput> +<prompt> -></prompt> <userinput> end</userinput> +<prompt> -></prompt> <userinput> if box.cfg.primary_port == 33013 then</userinput> +<prompt> -></prompt> <userinput> print('The local server primary port number is 33013 (the default)')</userinput> +<prompt> -></prompt> <userinput> else</userinput> +<prompt> -></prompt> <userinput> print('The local server primary port number is not 33013, so connect will fail')</userinput> +<prompt> -></prompt> <userinput> end</userinput> +<prompt> -></prompt> <userinput> conn = box.net.box.new('127.0.0.1', 33013)</userinput> +<prompt> -></prompt> <userinput> conn:delete(0,800)</userinput> +<prompt> -></prompt> <userinput> print('conn:delete done on space[0].')</userinput> +<prompt> -></prompt> <userinput> conn:insert(0,800,'data')</userinput> +<prompt> -></prompt> <userinput> print('conn:insert done on space[0], index 0. primary key value = 800.')</userinput> +<prompt> -></prompt> <userinput> wtuple = conn:select(0,0,800)</userinput> +<prompt> -></prompt> <userinput> print('conn:select done on space[0], index 0. number of fields = ', #wtuple)</userinput> +<prompt> -></prompt> <userinput> conn:delete(0,800)</userinput> +<prompt> -></prompt> <userinput> print('conn:delete done on space[0].')</userinput> +<prompt> -></prompt> <userinput> conn:replace(0,800,'New data','Extra data')</userinput> +<prompt> -></prompt> <userinput> print('conn:replace done on space[0].')</userinput> +<prompt> -></prompt> <userinput> conn:timeout(0):update(0,800,'=p=p=p',1, 'Field#1', 2,'Field#2', 3,'Field#3')</userinput> +<prompt> -></prompt> <userinput> print('conn:update done on space[0], timed out after waiting 0 seconds for a return')</userinput> +<prompt> -></prompt> <userinput> conn:close()</userinput> +<prompt> -></prompt> <userinput> print('conn:close done')</userinput> +<prompt> -></prompt> <userinput> end!</userinput> +--- +... +<prompt>localhost></prompt> <userinput> setopt delimiter = ''!</userinput> +<prompt>localhost></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></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"> -- GitLab