<article id="slonikref">
<title>Slonik Command Summary</title>
<abstract>    
    <para>
     <application>Slonik</application> is a command line utility designed
     specifically to setup and modify configurations of the
     &slony1; replication system.
    </para>
</abstract>
   
   <sect1 id="slonikoutline">
    <title>General outline</title>
    
    <para>
     The <application>slonik</application> commandline utility is
     supposed to be used embedded into shell scripts and reads
     commands from files or stdin (via here documents for
     example). Nearly all of the <emphasis>real</emphasis>
     configuration work is done by calling stored procedures after
     loading the &slony1; support base into
     a database.  You may find documentation for those procedures in
     the <ulink url="schemadoc">&slony1;
     Schema Documentation</ulink>, as well as in comments associated
     with them in the database.
    </para>

    <para>
     <application>Slonik</application> was created because:
     <itemizedlist>
      
      <listitem><para>The stored procedures have special requirements
	as to on which particular node in the replication system they
	are called,</para></listitem>
      
      <listitem><para>The lack of named parameters for stored
	procedures makes it rather difficult to do this from the
	<application>psql</application> prompt, and</para></listitem>
      
      <listitem><para><application>psql</application> lacks the ability
	to maintain multiple connections with open
	transactions.</para></listitem>
     </itemizedlist>
    </para>
    <para>
     
    </para>
    <sect2><title>Commands</title>
     <para>
      The slonik command language is format free. Commands begin with
      keywords and are terminated with a semicolon. Most commands have
      a list of parameters, some of which have default values and that
      are therefore optional. The parameters of commands are enclosed
      in parentheses. Each option consists of one or more keywords,
      followed by an equal sign, followed by a value. Multiple options
      inside the parentheses are separated by commas. All keywords are
      case insensitive.  The language should remind the reader of SQL.
     </para>
     <para>
      Option values may be:
      <itemizedlist>
       <listitem><para>integer values</para></listitem>
       <listitem><para>string literals enclosed in single quotes</para></listitem>
       <listitem><para>boolean values {TRUE|ON|YES} or {FALSE|OFF|NO}</para></listitem>
       <listitem><para>keywords for special cases</para></listitem>
      </itemizedlist>
     </para></sect2>
    <sect2><title>Comments</title>
     <para>
      Comments begin at a hash sign (#) and extend to the end of the line.
     </para>
    <sect2 id="tryblock"><title>Command groups</title>
     <para>
      Commands can be combined into groups of commands with optional
      <command>on error</command> and <command>on success</command> conditionals.
      The syntax for this is:
      <programlisting>
       try {
       commands;
       } 
       [on error { commands; }]
       [on success { commands; }]
      </programlisting></para>

     <para> Those commands are grouped together into one transaction
      per participating node. </para>

     <para> Note that this does not enforce grouping of the actions as
     a single transaction on all nodes.  For instance, consider the
     following slonik code:</para>
     <programlisting>
     try {
         execute script (set id = 1, filename = '/tmp/script1.sql', event node=1);
         execute script (set id = 1, filename = '/tmp/script2.sql', event node=1);
     }
     </programlisting>

     <para> This <emphasis>would</emphasis> be processed within a
     single BEGIN/COMMIT on node 1.  However, the requests are
     separated into two <command>DDL_SCRIPT</command> events so that
     each will be run individually, in separate transactions, on other
     nodes in the cluster. </para>

<!-- ************************************************************ -->
</sect1>
</article>

 <reference id="metacmds">
  <title>Slonik Meta Commands</title>
  <partintro>
   <para>
     The following commands may be used to somewhat abstract the
     definitions of components of Slonik scripts; <xref
     linkend="stmtinclude"> grouping configuration into central files
     that may be reused, and <xref linkend="stmtdefine"> allowing
     mnemonic identifiers to replace cryptic numeric object IDs.
   </para>
  </partintro>
  <!-- **************************************** -->
  <refentry id ="stmtinclude"><refmeta><refentrytitle>SLONIK INCLUDE</refentrytitle>
   <manvolnum>7</manvolnum></refmeta>
  
   <refnamediv><refname>INCLUDE</refname>
    
    <refpurpose> pulling in slonik code from another file </refpurpose>
   </refnamediv>
   <refsynopsisdiv>
    <cmdsynopsis>
     <command>include </command>
     <arg><replaceable class="parameter"> &lt;pathname&gt;</replaceable></arg>
    </cmdsynopsis>
   </refsynopsisdiv>
   <refsect1>
    <title>Description</title>
    <para>
      This draws the specified slonik script inline into the present
      script.  If the <option>pathname</option> specifies a relative
      path, <xref linkend="slonik"> will search relative to the
      current working directory.
    </para>

    <para>
      Nested include files are supported.  The scanner and parser
      report the proper file names and line numbers when they run into
      an error.  </para>
   </refsect1>
   <refsect1><title>Example</title>
    <programlisting>
     include &lt;/tmp/preamble.slonik&gt;;
    </programlisting>
   </refsect1>
   <refsect1> <title> Version Information </title>
    <para> This command was introduced in &slony1; 1.1 </para>
   </refsect1>
  </refentry>
  <!-- **************************************** -->
  <refentry id ="stmtdefine"><refmeta><refentrytitle>SLONIK DEFINE</refentrytitle>
   <manvolnum>7</manvolnum></refmeta>
   
   <refnamediv><refname>DEFINE</refname>
    
    <refpurpose> Defining a named symbol </refpurpose>
   </refnamediv>
   <refsynopsisdiv>
    <cmdsynopsis>
     <command>define </command>
     <arg><replaceable class="parameter"> name </replaceable></arg>
     <arg><replaceable class="parameter"> value </replaceable></arg>
    </cmdsynopsis>
   </refsynopsisdiv>
   <refsect1>
    <title>Description</title>
    <para>
      This defines a named symbol.  Symbol names must follow the
      slonik rules for constructing identifiers, by starting with a
      letter, followed by letters, numbers, and underscores.
    </para>

    <para>
      Symbol values may contain spaces and may recursively contain
      symbol references.
    </para>

    <para>
      Symbols are referenced by using a <quote>@</quote> followed by
      the symbol name.  Note that symbol referencing is suppressed
      inside string literals.
    </para>
   </refsect1>
   <refsect1><title>Example</title>
    <programlisting>
define    cluster movies;
define    sakai   1;
define    chen    2;
define    fqn     fully qualified name;

cluster name = @cluster;
node @sakai admin conninfo = 'service=sakai-replication';
node @chen  admin conninfo = 'service=chen-replication';
define setMovies    id = 1;
define sakaiMovies  @setMovies, origin = @sakai;

create set ( @sakaiMovies, comment = 'movies' );

set add table( set @sakaiMovies, id = 1, @fqn = 'public.customers', 
               comment = 'sakai customers' );
set add table( set @sakaiMovies, id = 2, @fqn = 'public.tapes',     
               comment = 'sakai tapes' );
echo 'But @sakaiMovies will display as a string, and is not expanded';
    </programlisting>
   </refsect1>

   <refsect1> <title> Version Information </title>
    <para> This command was introduced in &slony1; 1.1 </para>
   </refsect1>
  </refentry>

 </reference>  
<!-- **************************************** -->

 <reference id="hdrcmds"> 
  <title>Slonik Preamble Commands</title>
  <partintro>
   <para>
    The following commands must appear as a <quote>preamble</quote> at
    the beginning of each <application>slonik</application> command
    script. They do not cause any direct action on any of the nodes in
    the replication system, but affect the execution of the entire
    script.
   </para>
  </partintro>
  <!-- **************************************** -->
  
  <refentry id ="clustername"><refmeta><refentrytitle>SLONIK CLUSTER NAME</refentrytitle>
   <manvolnum>7</manvolnum></refmeta>
   
   <refnamediv><refname>CLUSTER NAME</refname>
    
    <refpurpose> preamble - identifying &slony1; cluster </refpurpose>
   </refnamediv>
   <refsynopsisdiv>
    <cmdsynopsis>
     <command>CLUSTER NAME = </command>
     <arg><replaceable class="parameter">clustername;</replaceable></arg>
    </cmdsynopsis>
   </refsynopsisdiv>
   <refsect1>
    <title>Description</title>
    <para>
     Must be the very first statement in every
     <application>slonik</application> script. It defines the
     namespace in which all &slony1;
     specific functions, procedures, tables and sequences are
     defined. The namespace name is built by prefixing the given
     string literal with an underscore. This namespace will be
     identical in all databases that participate in the same
     replication group.
    </para>
    
    <para>
     No user objects are supposed to live in this namespace, and the
     namespace is not allowed to exist prior to adding a database to
     the replication system.  Thus, if you add a new node using
     <command> pg_dump -s </command> on a database that is already in
     the cluster of replicated databases, you will need to drop the
     namespace via the SQL command <command> DROP SCHEMA _testcluster
     CASCADE; </command>.
    </para>
   </refsect1>
   <refsect1><title>Example</title>
    <programlisting>
     CLUSTER NAME = testcluster;
    </programlisting>
   </refsect1>
   <refsect1> <title> Version Information </title>
    <para> This command was introduced in &slony1; 1.0 </para>
   </refsect1>
  </refentry>
  
  
<!-- **************************************** -->

  <refentry id ="admconninfo"><refmeta><refentrytitle>SLONIK ADMIN CONNINFO</refentrytitle>
   <manvolnum>7</manvolnum></refmeta>
   
   <refnamediv><refname>ADMIN CONNINFO</refname>
    <refpurpose> preamble - identifying &postgres; database </refpurpose>
   </refnamediv>
   <refsynopsisdiv>
    <cmdsynopsis>
     <command>NODE ival ADMIN CONNINFO = 'DSN';</command>
     <arg><replaceable class="parameter"> ival;</replaceable></arg>
     <arg><replaceable class="parameter"> 'conninfo'</replaceable></arg>
    </cmdsynopsis>
   </refsynopsisdiv>
   <refsect1>
    <title>Description</title>
    <para>
     Describes how the <application>slonik</application> utility can
     reach a node's database in the cluster from where it is run
     (likely the DBA's workstation). The conninfo string is the string
     agrument given to the <function>PQconnectdb()</function> libpq
     function. 
    </para>

    <para>
     The <application>slonik</application> utility will not try to
     connect to a given database unless some subsequent command
     requires the connection.
    </para>

   <note> <para>
     As mentioned in the original documents,
     &slony1; is designed as an enterprise
     replication system for data centers. It has been assumed
     throughout the entire development that the database servers and
     administrative workstations involved in replication and/or setup
     and configuration activities can use simple authentication
     schemes like <quote>trust</quote>.  Alternatively, libpq can read
     passwords from <filename> .pgpass </filename>.
    </para>
   </note>
   <note>
    <para>
    If you need to change the DSN information for a node, as would
    happen if the IP address for a host were to change, you must
    submit the new information using the <xref
    linkend="stmtstorepath"> command, and that configuration will be
    propagated.  Existing <application> slon </application> processes
    may need to be restarted in order to become aware of the
    configuration change.
    </para>
   </note>


   </Refsect1>
   <Refsect1><Title>Example</Title>
    <Programlisting>
     NODE 1 ADMIN CONNINFO = 'dbname=testdb host=server1 user=slony';
    </Programlisting>
   </Refsect1>
   <refsect1> <title> Version Information </title>
    <para> This command was introduced in &slony1; 1.0 </para>
   </refsect1>
  </Refentry>
 </reference>
<!-- ************************************************************ -->
 
<!-- **************************************** -->
 <reference id="cmds">
  <title>Configuration and Action commmands</title>
<!-- **************************************** -->
  
  <refentry id ="stmtecho"><refmeta><refentrytitle>SLONIK ECHO</refentrytitle>
   <manvolnum>7</manvolnum></refmeta>
   
   <refnamediv><refname>ECHO</refname>
    
    <refpurpose> Generic output tool </refpurpose>
   </refnamediv>
   <refsynopsisdiv>
    <cmdsynopsis>
     <command>echo </command>
     <arg><replaceable class="parameter"> 'string'</replaceable></arg>
    </cmdsynopsis>
   </refsynopsisdiv>
   <refsect1>
    <title>Description</title>
    <para>
     Prints the string literal on standard output.
    </para>
   </Refsect1>
   <Refsect1><Title>Example</Title>
    <Programlisting>
     ECHO 'Node 1 initialized successfully';
    </Programlisting>
   </Refsect1>
   <refsect1> <title> Version Information </title>
    <para> This command was introduced in &slony1; 1.0 </para>
   </refsect1>
  </Refentry>
  
<!-- **************************************** -->
  
  <refentry id ="stmtdate"><refmeta><refentrytitle>SLONIK DATE</refentrytitle>
   <manvolnum>7</manvolnum></refmeta>
   
   <refnamediv><refname>DATE</refname>
    
    <refpurpose> Display current date </refpurpose>
   </refnamediv>
   <refsynopsisdiv>
    <cmdsynopsis>
     <command>date</command>
     <arg><replaceable class="parameter"> (format)</replaceable></arg>
    </cmdsynopsis>
   </refsynopsisdiv>
   <refsect1>
    <title>Description</title>
    <para>
     Prints the current date. Accepts an optional strftime()-conformant format string.
    </para>
   </Refsect1>
   <Refsect1><Title>Example</Title>
    <Programlisting>
     DATE;
     DATE(format='%Y-%m-%d %H:%M:%S %Z');
    </Programlisting>
   </Refsect1>
   <refsect1> <title> Version Information </title>
    <para> This command was introduced in &slony1; 2.1 </para>
   </refsect1>
  </Refentry>
  
  <!-- **************************************** -->
  
  <refentry id ="stmtexit"><refmeta><refentrytitle>SLONIK EXIT</refentrytitle>
   <manvolnum>7</manvolnum></refmeta>
   
   <refnamediv><refname>EXIT</refname>
    
    <refpurpose> Terminate Slonik script with signal </refpurpose>
   </refnamediv>
   <refsynopsisdiv>
    <cmdsynopsis>
     <command>exit</command>
     <arg><replaceable class="parameter"> [-]ival</replaceable></arg>
    </cmdsynopsis>
   </refsynopsisdiv>
   <refsect1>
    <title>Description</title>
    <para>
     Terminates script execution immediately, rolling back every
     open transaction on all database connections. The
     <application>slonik</application> utility
     will return the given value as its program termination code.  Note that on Unix, exit statuses are restricted to the range 0-255.
    </para>
   </Refsect1>
   <Refsect1><Title>Example</Title>
    <Programlisting>
     EXIT 0;
    </Programlisting>
   </Refsect1>
   <refsect1> <title> Version Information </title>
    <para> This command was introduced in &slony1; 1.0 </para>
   </refsect1>
  </Refentry>

  <!-- **************************************** -->
  <refentry id="stmtinitcluster">
   <refmeta>
    <refentrytitle>SLONIK INIT CLUSTER</refentrytitle>
     <manvolnum>7</manvolnum>
   </refmeta>
   <refnamediv>
    <refname>INIT CLUSTER</refname>
    <refpurpose>Initialize &slony1; cluster</refpurpose></refnamediv>
   <refsynopsisdiv>
    <cmdsynopsis>
     <command>INIT CLUSTER</command> 
     <arg>ID = <replaceable class="parameter">integer</replaceable></arg>
     <arg>COMMENT = <replaceable class="parameter">'string'</replaceable></arg>
    </cmdsynopsis>
   </refsynopsisdiv>
   <refsect1>
    <title>Description</title> 

    <para> Initialize the first node in a new &slony1; replication
    cluster.  The initialization process consists of creating the
    cluster namespace, loading all the base tables, functions,
    procedures and initializing the node, using
    &funinitializelocalnode; and &funenablenode;.
     
     <variablelist>
      <varlistentry><term><literal>ID</literal></term>
       <listitem><para>The unique, numeric ID number of the node.</para></listitem>
      </varlistentry>
      
      <varlistentry><term><literal>COMMENT = 'comment
      text'</literal></term> <listitem><para> A descriptive text added
      to the node entry in the table &slnode;. 
      </para></listitem>
      </varlistentry>
     </variablelist>
     
    </para>
    
    <para> For this process to work, the SQL scripts of the
    &slony1; system must be installed on the
    DBA workstation (the computer currently executing the
    <application>slonik</application> utility), while on the system
    where the node database is running the shared objects of the
    &slony1; system must be installed in the
    &postgres; library directory. Also the procedural language
    PL/pgSQL is assumed to already be installed in the target
    database.</para>
   </refsect1>
   <refsect1>
    <title>Example</title>
    <programlisting>
INIT CLUSTER (
   ID = 1,
   COMMENT = 'Node 1'
);
    </programlisting>

   <note> <para> This command functions very similarly to <xref
   linkend="stmtstorenode">, the difference being that <command>INIT
   CLUSTER </command> does not need to draw configuration from other
   existing nodes.
   </para> </note>

   <note> <para> Be aware that some objects are created that contain
   the cluster name as part of their name.  (Notably, partial indexes
   on <envar>sl_log_1</envar> and <envar>sl_log_2</envar>.)  As a
   result, <emphasis>really long</emphasis> cluster names are a bad
   idea, as they can make object names <quote>blow up</quote> past the
   typical maximum name length of 63 characters. </para> </note>

   </refsect1>
   <refsect1> <title> Locking Behaviour </title>

    <para> This command creates a new namespace and configures tables
    therein; no public objects should be locked during the duration of
    this.</para>
   </refsect1>

   <refsect1> <title> Slonik Event Confirmation Behaviour </title>
	 <para> Slonik does not wait for event confirmations before 
	   performing this command.</para>
   </refsect1>

   <refsect1> <title> Version Information </title>
    <para> This command was introduced in &slony1; 1.0 </para>
   </refsect1>
  </refentry>

<!-- **************************************** -->

  <refentry id ="stmtstorenode"><refmeta><refentrytitle>SLONIK STORE NODE</refentrytitle>
   <manvolnum>7</manvolnum></refmeta>
   
   <refnamediv><refname>STORE NODE</refname>
    <refpurpose> Initialize &slony1; node </refpurpose>
   </refnamediv>
   <refsynopsisdiv>
    <cmdsynopsis>
     <command>STORE NODE (options);</command>
    </cmdsynopsis>
   </refsynopsisdiv>
   <refsect1>
    <title>Description</title>
    
    <para> Initialize a new node and add it to the configuration of an
    existing cluster.</para>

    <para> The initialization process consists of creating the cluster
    namespace in the new node (the database itself must already
    exist), loading all the base tables, functions, procedures and
    initializing the node.  The existing configuration of the rest of
    the cluster is copied from the <quote>event node</quote>.
     
     <variablelist>
      <varlistentry><term><literal>ID = ival</literal></term>
      <listitem><para> The unique, immutable numeric ID number of the new
      node.</para>

      <para> Note that the ID is <emphasis>immutable</emphasis>
      because it is used as the basis for inter-node event
      communications. </para> </listitem>
      </varlistentry>
      
      <varlistentry><term><literal> COMMENT = 'description' </literal></term>
       <listitem><para> A descriptive text added to the node entry in the table &slnode;</para></listitem>
      </varlistentry>
      
      <varlistentry><term><literal> SPOOLNODE = boolean </literal></term>
       
       <listitem><para>Specifies that the new node is a virtual spool
       node for file archiving of replication log.  If true,
       <application>slonik</application> will not attempt to
       initialize a database with the replication
       schema.</para>

       <warning><para> Never use the SPOOLNODE value - no released
       version of &slony1; has ever behaved in the fashion described
       in the preceding fashion.  Log shipping, as it finally emerged
       in 1.2.11, does not require initializing <quote>spool
       nodes</quote>.</para> </warning> </listitem>
       
      </varlistentry>
      <varlistentry><term><literal> EVENT NODE = ival </literal></term>
       
       <listitem><para> The ID of the node used to create the
	 configuration event that tells all existing nodes about the
	 new node.  It must be the ID of a pre-existing node in the
	 cluster, not the ID of the new node.  </para></listitem>
	 </varlistentry> </variablelist> </para>

    <para> This uses &funinitializelocalnode; and &funenablenode;. </para>
    
   </Refsect1>
   <Refsect1><Title>Example</Title>
    <Programlisting>
     STORE NODE ( ID = 2, COMMENT = 'Node 2', EVENT NODE = 1 );
    </Programlisting>
   </Refsect1>
   <refsect1> <title> Locking Behaviour </title>

    <para> This command creates a new namespace and configures tables
    therein; no public objects should be locked during the duration of
    this.</para>
   </refsect1>

 <refsect1> <title> Slonik Event Confirmation Behaviour </title>
	 <para> Slonik waits for the command submitted to the previous
	   event node to be confirmed on the specified event node before
	   submitting this command. </para>
   </refsect1>

   <refsect1> <title> Version Information </title> <para> This command
   was introduced in &slony1; 1.0.  The <envar>SPOOLNODE</envar>
   parameter was introduced in version 1.1, but was vestigial in that
   version.  The described functionality for <envar>SPOOLNODE</envar>
   arrived in version 1.2, but <envar>SPOOLNODE</envar> was not used
   for this purpose.  In later versions, hopefully
   <envar>SPOOLNODE</envar> will be unavailable. </para>
   <para> In version 2.0, the default value for <envar>EVENT NODE</envar> was removed, so a node must be specified.</para>
   </refsect1>
  </Refentry>
  
<!-- **************************************** -->
  <refentry id="stmtdropnode"><refmeta><refentrytitle>SLONIK DROP NODE</refentrytitle>
   <manvolnum>7</manvolnum></refmeta>
   
   <refnamediv><refname>DROP NODE</refname>
    
    <refpurpose> Remove the node from participating in the replication </refpurpose></refnamediv>
   <refsynopsisdiv>
    <cmdsynopsis>
     <command>DROP NODE (options);</command>
    </cmdsynopsis>
   </refsynopsisdiv>
   <refsect1>
    <title>Description</title>
    
    <para>
     Drop a node. This command removes the specified node entirely
     from the replication systems configuration. If the replication
     daemon is still running on that node (and processing events), it
     will attempt to uninstall the replication system and terminate
     itself.

     <variablelist>
      <varlistentry><term><literal> ID  = ival </literal></term>
       <listitem><para> Node ID of the node to remove.</para></listitem>
      </varlistentry>
      <varlistentry><term><literal> EVENT NODE = ival </literal></term>
       <listitem><para> Node ID of the node to generate the event.
       </para></listitem>
      </varlistentry>
     </variablelist>
    </para>

    <para> This uses &fundropnode;. </para>

    <para> When you invoke <command>DROP NODE</command>, one of the
    steps is to run <command>UNINSTALL NODE</command>.</para>

   </refsect1>
   <refsect1><title>Example</title>
    <programlisting>
     DROP NODE ( ID = 2, EVENT NODE = 1 );
    </programlisting>
   </refsect1>
   <refsect1> <title> Locking Behaviour </title>

    <para> When dropping triggers off of application tables, this will
    require exclusive access to each replicated table on the node
    being discarded.</para>
   </refsect1>
   <refsect1><title>Dangerous/Unintuitive Behaviour</title>
   <para> If you are using connections that cache query plans
   (this is particularly common for Java application frameworks with
   connection pools), the connections may cache query plans that
   include the pre-<command>DROP NODE</command> state of things, and
   you will get &rmissingoids;.</para>

   <para>After dropping a node, you may also need to recycle
   connections in your application.</para>

   <para> You cannot submit this to an <command>EVENT
   NODE</command> that is the number of the node being dropped; the
   request must go to some node that will remain in the
   cluster. </para>
   </refsect1>

 <refsect1> <title> Slonik Event Confirmation Behaviour </title>
	 <para> Slonik waits until nodes (other than the one being dropped)
            are caught up with non-SYNC events from all other nodes before
	        submitting the DROP NODE command.
    </para>
   </refsect1>

   <refsect1> <title> Version Information </title>
    <para> This command was introduced in &slony1; 1.0 </para>
   <para> In version 2.0, the default value for <envar>EVENT NODE</envar> was removed, so a node must be specified.</para>
   </refsect1>
  </refentry>

<!-- **************************************** -->
  <refentry id="stmtuninstallnode"><refmeta><refentrytitle>SLONIK UNINSTALL NODE</refentrytitle>
   <manvolnum>7</manvolnum></refmeta>
   
   <refnamediv><refname>UNINSTALL NODE</refname>
    
    <refpurpose> Decommission &slony1; node </refpurpose></refnamediv>
   <refsynopsisdiv>
    <cmdsynopsis>
     <command>UNINSTALL NODE (options);</command>
    </cmdsynopsis>
   </refsynopsisdiv>
   <refsect1>
    <title>Description</title>
    
    <para> Restores all tables to the unlocked state, with all
     original user triggers, constraints and rules, eventually added
     &slony1; specific serial key columns
     dropped and the &slony1; schema
     dropped. The node becomes a standalone database. The data is left
     untouched.
     
     <variablelist>
      <varlistentry><term><literal> ID  = ival </literal></term>
       <listitem><para> Node ID of the node to uninstall.</para></listitem>
      </varlistentry>
     </variablelist>
    </para>

    <para> This uses &fununinstallnode;. </para>

    <para> The difference between <command>UNINSTALL NODE</command>
    and <command>DROP NODE</command> is that all <command>UNINSTALL
    NODE</command> does is to remove the &slony1; configuration; it
    doesn't drop the node's configuration from replication.</para>

   </refsect1>
   <refsect1><title>Example</title>
    <programlisting>
  UNINSTALL NODE ( ID = 2 );
    </programlisting>
   </refsect1>
   <refsect1> <title> Locking Behaviour </title>

    <para> When dropping triggers off of application tables, this will
    require exclusive access to each replicated table on the node
    being discarded.</para>
   </refsect1>
   <refsect1><title> Dangerous/Unintuitive Behaviour </title>
   <para> If you are using connections that cache query plans
   (this is particularly common for Java application frameworks with
   connection pools), the connections may cache query plans that
   include the pre-<command>UNINSTALL NODE</command> state of things,
   and you will get &rmissingoids;.</para>

   <para>After dropping a node, you may also need to recycle
   connections in your application.</para>
   </refsect1>

 <refsect1> <title> Slonik Event Confirmation Behaviour </title>
	 <para>Slonik does not wait for event confirmations before 
	   performing this command</para>
   </refsect1>

   <refsect1> <title> Version Information </title>
    <para> This command was introduced in &slony1; 1.0 </para>
   </refsect1>
  </refentry>

<!-- **************************************** -->

  <refentry id="stmtrestartnode"><refmeta><refentrytitle>SLONIK RESTART NODE</refentrytitle>
   <manvolnum>7</manvolnum></refmeta>
   
   <refnamediv><refname>RESTART NODE</refname>

    <refpurpose> Restart &slony1; node </refpurpose></refnamediv>
   
   <refsynopsisdiv>
    <cmdsynopsis>
     <command>RESTART NODE options;</command>
    </cmdsynopsis>
   </refsynopsisdiv>
   <refsect1>
    <title>Description</title>
    
    <para> Causes an eventually running replication daemon
    (<application>slon</application> process) on the specified node to
    shutdown and restart itself.  Theoretically, this command should
    be obsolete. In practice, TCP timeouts can delay critical
    configuration changes to actually happen in the case where a
    former forwarding node failed and needs to be bypassed by
    subscribers.
     
     <variablelist>
      <varlistentry><term><literal> ID  = ival </literal></term>
       <listitem><para> Node ID of the node to restart.</para></listitem>
      </varlistentry>
     </variablelist>
    </para>

   </refsect1>
   <refsect1><title>Example</title>
    <programlisting>
  RESTART NODE ( ID = 2 );
    </programlisting>
   </refsect1>
   <refsect1> <title> Locking Behaviour </title>

    <para> No application-visible locking should take place. </para>
   </refsect1>


 <refsect1> <title> Slonik Event Confirmation Behaviour </title>
	 <para>Slonik does not wait for event confirmations before 
	   performing this command</para>
   </refsect1>

   <refsect1> <title> Version Information </title> <para> This command
   was introduced in &slony1; 1.0; frequent use became unnecessary as
   of version 1.0.5.  There are, however, occasional cases where it is
   necessary to interrupt a <application>slon</application> process,
   and this allows this to be scripted via slonik. </para>
   </refsect1>
  </refentry>
  

  <!-- **************************************** -->

  <refentry id="stmtstorepath"><refmeta><refentrytitle>SLONIK STORE
     PATH</refentrytitle><manvolnum>7</manvolnum></refmeta>
   
   <refnamediv><refname>STORE PATH</refname>
    
    <refpurpose> Configure &slony1; node connection </refpurpose></refnamediv>
   
   <refsynopsisdiv>
    <cmdsynopsis>
     <command>STORE PATH (options);</command>
    </cmdsynopsis>
   </refsynopsisdiv>
   <refsect1>
    <title>Description</title>
    
    <para> Configures how the replication daemon of one node connects
     to the database of another node. If the replication system is
     supposed to use a special backbone network segment, this is the
     place to user the special IP addresses or hostnames. An existing
     configuration can be overwritten.</para>
    
    <para> The conninfo string must contain all information to connect
     to the database as the replication superuser. The names
     <quote>server</quote> or <quote>client</quote> have nothing to do
     with the particular role of a node within the cluster
     configuration. It should be simply viewed as <quote>the
      server</quote> has the message or data that <quote>the client is
      supposed to get.</quote> For a simple 2 node setup, paths into
     both directions must be configured.
    </para>
    <para> It does not do any harm to configure path information from
     every node to every other node (full cross product). The
     connections are not established unless they are required to
     actually transfer events or confirmations because of
     <emphasis>listen</emphasis> entries or data because of
     <emphasis>subscriptions</emphasis>.
     
     <variablelist>
      <varlistentry><term><literal> SERVER  = ival </literal></term>
       <listitem><para> Node ID of the database to connect to.</para></listitem>
      </varlistentry>
      <varlistentry><term><literal> CLIENT  = ival </literal></term>
       <listitem><para> Node ID of the replication daemon connecting.</para></listitem>
      </varlistentry>
      <varlistentry><term><literal> CONNINFO  = string </literal></term>
       <listitem><para> <function>PQconnectdb()</function> argument to establish the connection.</para></listitem>
      </varlistentry>
      <varlistentry><term><literal> CONNRETRY  = ival </literal></term>
       <listitem><para> Number of seconds to wait before another attempt to
	 connect is made in case the server is unavailable. Default is 10.
	</para></listitem>
      </varlistentry>
     </variablelist>
    </para>
    <para> This uses &funstorepath;. </para>
   </refsect1>
   <refsect1><title>Example</title>
    <programlisting>
STORE PATH ( SERVER = 1, CLIENT = 2, 
             CONNINFO = 'dbname=testdb host=server1 user=slony'
           );
    </programlisting>
   </refsect1>
   <refsect1> <title> Locking Behaviour </title>

    <para> No application-visible locking should take place. </para>
   </refsect1>


 <refsect1> <title> Slonik Event Confirmation Behaviour </title>
	 <para>Slonik does not wait for event confirmations before 
	   performing this command</para>
   </refsect1>

   <refsect1> <title> Version Information </title>
    <para> This command was introduced in &slony1; 1.0 </para>
   </refsect1>
  </refentry>


<!-- **************************************** -->

  <refentry id="stmtdroppath"><refmeta><refentrytitle>SLONIK DROP PATH</refentrytitle>
   <manvolnum>7</manvolnum></refmeta>
   
   <refnamediv><refname>DROP PATH</refname>
    
    <refpurpose> Delete &slony1; connection information </refpurpose></refnamediv>
   
   <refsynopsisdiv>
    <cmdsynopsis>
     <command>DROP PATH (options);</command>
    </cmdsynopsis>
   </refsynopsisdiv>
   <refsect1>
    <title>Description</title>
    
    <para> 	Remove the connection information between <quote>server</quote> and
     <quote>client</quote>.</para>
     
     <variablelist>
      <varlistentry><term><literal> SERVER  = ival </literal></term>
       <listitem><para> Node ID of the database to connect to.</para></listitem>
      </varlistentry>
      <varlistentry><term><literal> CLIENT  = ival </literal></term>
       <listitem><para> Node ID of the replication daemon connecting.</para></listitem>
      </varlistentry>
      <varlistentry><term><literal> EVENT NODE = ival </literal></term>
       
       <listitem><para> The ID of the node used to create the configuration
	 event that tells all existing nodes about dropping the path.
	 Defaults to the <quote>client</quote>, if omitted.
	</para></listitem>
      </varlistentry>
      </variablelist>
      </refsect1>
   <refsect1><title>Example</title>
    <programlisting>
  DROP PATH ( SERVER = 1, CLIENT = 2 );
    </programlisting>
   </refsect1>
   <refsect1> <title> Locking Behaviour </title>

    <para> No application-visible locking should take place. </para>
   </refsect1>


 <refsect1> <title> Slonik Event Confirmation Behaviour </title>
	 <para>Slonik does not wait for event confirmations before 
	   performing this command</para>
   </refsect1>

   <refsect1> <title> Version Information </title>
    <para> This command was introduced in &slony1; 1.0 </para>
   </refsect1>
  </refentry>
  

<!-- **************************************** -->

  <refentry id="stmtstorelisten"><refmeta><refentrytitle>SLONIK STORE LISTEN</refentrytitle>
   <manvolnum>7</manvolnum></refmeta>
   
   <refnamediv><refname>STORE LISTEN</refname>
    
    <refpurpose> Configure &slony1; node to
    indicate where to listen for events </refpurpose></refnamediv>
    
   <refsynopsisdiv>
    <cmdsynopsis>
     <command>STORE LISTEN (options);</command>
    </cmdsynopsis>
   </refsynopsisdiv>
   <refsect1>
    <title>Description</title>
    
    <para> A <quote>listen</quote> entry causes a node (receiver) to query an
     event provider for events that originate from a specific node, as
     well as confirmations from every existing node. It requires a
     <quote>path</quote> to exist so that the receiver (as client) can connect
     to the provider (as server).</para>

    <para> Every node in the system must listen for events from every
    other node in the system. As a general rule of thumb, a subscriber
    (see <xref linkend="stmtsubscribeset">) should listen for events
    of the set's origin on the same provider, where it receives the
    data from. In turn, the origin of the data set should listen for
    events from the origin in the opposite direction. A node can
    listen for events from one and the same origin on different
    providers at the same time. However, to process
    <command>SYNC</command> events from that origin, all data
    providers must have the same or higher sync status, so this will
    not result in any faster replication behaviour.
    </para>

    <variablelist>
     <varlistentry><term><literal> ORIGIN  = ival </literal></term>
      <listitem><para> Node ID of the event origin the receiver is listening for.</para></listitem>
     </varlistentry>
     <varlistentry><term><literal> PROVIDER = ival </literal></term>
     <listitem><para> Node ID of the node from which the receiver gets
	events that come from the origin.  If not specified, default is
	the origin.</para></listitem>
     </varlistentry>
     <varlistentry><term><literal> RECEIVER = ival </literal></term>
      
      <listitem><para> The ID of the node receiving the events.</para></listitem>
     </varlistentry>
    </variablelist>

    <para> This uses &funstorelisten;. </para>
    <para> For more details, see &rlistenpaths;.</para>
   </refsect1>
   <refsect1><title>Example</title>
    <programlisting>
     STORE LISTEN ( ORIGIN = 1, RECEIVER = 2, PROVIDER = 3 );
    </programlisting>
   </refsect1>
   <refsect1> <title> Locking Behaviour </title>

    <para> No application-visible locking should take place. </para>
   </refsect1>


 <refsect1> <title> Slonik Event Confirmation Behaviour </title>
	 <para>Slonik waits for the command submitted to the previous
	   event node to be confirmed on the specified event node before
	   submitting this command.</para>
   </refsect1>

   <refsect1> <title> Version Information </title> <para> This command
   was introduced in &slony1; 1.0.  As of version 1.1, you <emphasis>should</emphasis> no
   longer need to use this command, as listen paths are generated automatically. </para>
   </refsect1>
  </refentry>

<!-- **************************************** -->

  <refentry id="stmtdroplisten"><refmeta><refentrytitle>SLONIK DROP LISTEN</refentrytitle>
   <manvolnum>7</manvolnum></refmeta>
   
   <refnamediv><refname>DROP LISTEN</refname>
    
    <refpurpose> Eliminate configuration indicating how
    &slony1; node listens for events
    </refpurpose></refnamediv>
   
   <refsynopsisdiv>
    <cmdsynopsis>
     <command>DROP LISTEN (options);</command>
    </cmdsynopsis>
   </refsynopsisdiv>
   <refsect1>
    <title>Description</title>
    
    <para> Remove a <quote>listen</quote> configuration entry. </para>
    
    <variablelist>
     <varlistentry><term><literal> ORIGIN  = ival </literal></term>
      <listitem><para> Node ID of the event origin the receiver is listening for.</para></listitem>
     </varlistentry>
     <varlistentry><term><literal> PROVIDER = ival </literal></term>
     <listitem><para> Node ID of the node from which the receiver gets
     events that come from the origin.  If not specified, default is
     the origin.</para></listitem>
     </varlistentry>
     <varlistentry><term><literal> RECEIVER = ival </literal></term>
      
      <listitem><para> The ID of the node receiving the events.</para></listitem>
     </varlistentry>
    </variablelist>
    
    <para> This uses &fundroplisten;. </para>
   </refsect1>
   <refsect1><title>Example</title>
    <programlisting>
     DROP LISTEN ( ORIGIN = 1, RECEIVER = 2, PROVIDER = 3 );
    </programlisting>
   </refsect1>
   <refsect1> <title> Locking Behaviour </title>

    <para> No application-visible locking should take place. </para>
   </refsect1>
      
   <refsect1> <title> Slonik Event Confirmation Behaviour </title>
	 <para> Slonik waits for the command submitted to the previous
	   event node to be confirmed on the specified event node before
	   submitting this command.</para>
   </refsect1>

   <refsect1> <title> Version Information </title> <para> This command
   was introduced in &slony1; 1.0.  As of version 1.1, you should not
   need to use it anymore. </para>
   </refsect1>
  </refentry>



<!-- **************************************** -->

  <refentry id="stmttableaddkey"><refmeta><refentrytitle>SLONIK TABLE ADD KEY</refentrytitle>
   <manvolnum>7</manvolnum></refmeta>

   <refnamediv><refname>TABLE ADD KEY</refname>
    
    <refpurpose> Add primary key for use by
    &slony1; for a table with no suitable
    key 
    </refpurpose></refnamediv>
   
 
   <refsect1> <title> Version Information </title>
    <para> This command was introduced in &slony1; 1.0 </para>

    <para> In &slony1; version 2.0, this command is removed as
    obsolete because triggers are no longer <quote>messed around
    with</quote> in the system catalogue. </para>

   </refsect1>
  </refentry>


<!-- **************************************** -->

  <refentry id="stmttabledropkey"><refmeta><refentrytitle>SLONIK TABLE DROP KEY</refentrytitle>
   <manvolnum>7</manvolnum></refmeta>

   <refnamediv><refname>TABLE DROP KEY</refname>
    
    <refpurpose> Removes a primary key added by TABLE ADD KEY 
    </refpurpose></refnamediv>
   
 
   <refsect1> <title> Version Information </title>
    <para> This command was introduced in &slony1; 1.0 </para>

    <para> In &slony1; version 2.0, this command is removed as
    obsolete because triggers are no longer <quote>messed around
    with</quote> in the system catalogue. </para>

   </refsect1>
  </refentry>


<!-- **************************************** -->


  <refentry id="stmtcreateset"><refmeta><refentrytitle>SLONIK CREATE SET</refentrytitle>
   <manvolnum>7</manvolnum></refmeta>
   
   <refnamediv><refname>CREATE SET</refname>
    
    <refpurpose> Create &slony1; replication
    set </refpurpose></refnamediv>
   
   <refsynopsisdiv>
    <cmdsynopsis>
     <command>CREATE SET (options);</command>
    </cmdsynopsis>
   </refsynopsisdiv>
   <refsect1>
    <title>Description</title>
    
    <para>
     In the &slony1; replication system,
     replicated tables are organized in sets. As a general rule of
     thumb, a set should contain all the tables of one application,
     that have relationships.  In a well designed application, this is
     equal to all the tables in one schema.
    </para>
    <para>
     The smallest unit one node can subscribe for replication from
     another node is a set. A set always has an origin. In
     classical replication terms, that would be the <quote>master.</quote>
     Since in &slony1; a node can be the <quote>master</quote> over one set,
     while receiving replication data in the <quote>slave</quote> role for
     another at the same time, this terminology may easily become
     misleading and should therefore be replaced with <quote>set
      origin</quote> and <quote>subscriber</quote>.
    </para>
    
    
    <variablelist>
     <varlistentry><term><literal> ID = ival </literal></term>
      <listitem><para> ID of the set to be created.</para></listitem>
     </varlistentry>
     <varlistentry><term><literal> ORIGIN = ival </literal></term>
      <listitem><para> Initial origin node of the set.</para></listitem>
     </varlistentry>
     <varlistentry><term><literal> COMMENT = 'string' </literal></term>
      <listitem><para> A descriptive text added to the set entry.</para>
                <para> If none is provided, a default value is set; <command>A replication set so boring no one thought to give it a name</command>. </para>
      </listitem>
     </varlistentry>
    </variablelist>
    
    <para> This uses &funstoreset; . </para>
   </refsect1>
   <refsect1><title>Example</title>
    <programlisting>
     CREATE SET ( ID = 1, 
               ORIGIN = 1,
               COMMENT = 'Tables for ticketing system' );
    </programlisting>
   </refsect1>
   <refsect1> <title> Locking Behaviour </title>

    <para> No application-visible locking should take place. </para>
   </refsect1>
   
   
   <refsect1> <title> Slonik Event Confirmation Behaviour </title>
	 <para> Slonik waits for the command submitted to the previous
	   event node to be confirmed on the specified event node before
	   submitting this command. Slonik will also wait until any outstanding
	   DROP SET commands are confirmed by all nodes before it submits
	   the CREATE SET command.</para>
   </refsect1>

   <refsect1> <title> Version Information </title>
    <para> This command was introduced in &slony1; 1.0 </para>
    <para> Until version 1.2, it would crash if no comment was provided. </para>
   </refsect1>
  </refentry>


<!-- **************************************** -->

  <refentry id="stmtdropset"><refmeta><refentrytitle>SLONIK DROP SET</refentrytitle>
   <manvolnum>7</manvolnum></refmeta>

   <refnamediv><refname>DROP SET</refname>
    
    <refpurpose> Discard &slony1;
    replication set </refpurpose></refnamediv>
   
   <refsynopsisdiv>
    <cmdsynopsis>
     <command>DROP SET (options);</command>
    </cmdsynopsis>
   </refsynopsisdiv>
   <refsect1>
    <title>Description</title>
    
    <para>
     Drop a set of tables from the &slony1;
     configuration. This automatically unsubscribes all nodes from the
     set and restores the original triggers and rules on all
     subscribers.
    </para>
    
    <variablelist>
     <varlistentry><term><literal> ID = ival </literal></term>
      <listitem><para> ID of the set to be dropped.</para></listitem>
     </varlistentry>
     <varlistentry><term><literal> ORIGIN = ival </literal></term>
      <listitem><para> Current origin node of the set.</para></listitem>
     </varlistentry>
    </variablelist>
    
       <para> This uses &fundropset;. </para>
   </refsect1>
   <refsect1><title>Example</title>
    <programlisting>
  DROP SET ( ID = 5, 
             ORIGIN = 2 );
    </programlisting>
   </refsect1>
   <refsect1> <title> Locking Behaviour </title>

    <para> On each node, this will require taking out exclusive locks
    on each replicated table in order to modify the table schema to
    clean up the triggers and rules.  </para>
   </refsect1>

   
   <refsect1> <title> Slonik Event Confirmation Behaviour </title>
	 <para> Slonik waits for the command submitted to the previous
	   event node to be confirmed on the specified event node before
	   submitting this command.</para>
   </refsect1>

   <refsect1> <title> Version Information </title>
    <para> This command was introduced in &slony1; 1.0 </para>
   </refsect1>
  </refentry>
 
<!-- **************************************** -->

  <refentry id="stmtmergeset"><refmeta><refentrytitle>SLONIK MERGE
     SET</refentrytitle><manvolnum>7</manvolnum></refmeta>
   
   <refnamediv><refname>MERGE SET</refname>
    
    <refpurpose> Merge &slony1; replication
    sets together </refpurpose></refnamediv>
   
   <refsynopsisdiv>
    <cmdsynopsis>
     <command>MERGE SET (options);</command>
    </cmdsynopsis>
   </refsynopsisdiv>
   <refsect1>
    <title>Description</title>
    
    <para> Merge a set of tables and sequences into another one. This
    function is a workaround for the problem that it is not possible
    to add tables/sequences to already-subscribed sets. One may create
    a temporary set, add the new objects to that, subscribe all nodes
    currently subscribed to the other set to this new one, and then
    merge the two together, eliminating the set ID that was being
    added.
    </para>

    <para>
     This operation will refuse to be run if the two sets do not have
     <emphasis>exactly</emphasis> the same set of subscribers.
     </para>
    
    <variablelist>
     <varlistentry><term><literal> ID = ival </literal></term>
      <listitem><para> Unique ID of the set to contain the union of the two formerly separate sets.</para></listitem>
     </varlistentry>
     <varlistentry><term><literal> ADD ID = ival </literal></term>
      <listitem><para> Unique ID of the set whose objects should be transferred into the above set.  </para></listitem>
     </varlistentry>
     <varlistentry><term><literal> ORIGIN = ival </literal></term>
      <listitem><para> Current origin node for both sets.  </para></listitem>
     </varlistentry>
    </variablelist>
    
       <para> This uses &funmergeset;. </para>
   </refsect1>
   <refsect1><title>Example</title>
    <programlisting>
     # Assuming that node 1 is the origin of set 999 that has direct subscribers 2 and 3
     SUBSCRIBE SET (ID = 999, PROVIDER = 1, RECEIVER = 2);
     SUBSCRIBE SET (ID = 999, PROVIDER = 1, RECEIVER = 3);
     MERGE SET ( ID = 1, ADD ID = 999, ORIGIN = 1 );
    </programlisting>
   </refsect1>
   <refsect1> <title> Locking Behaviour </title>

    <para> No application-visible locking should take place. </para>
   </refsect1>
   <refsect1><title> Dangerous/Unintuitive Behaviour </title>

   <para> Merging takes place based on the configuration on the origin
   node.  If a merge is requested while subscriptions are still being
   processed, this can cause in-progress subscribers' replication to
   break, as they'll be looking for configuration for this set which
   the merge request deletes.  Do not be too quick to merge sets.
   </para>

   </refsect1>

   <refsect1> <title> Slonik Event Confirmation Behaviour </title>
   <para> Slonik waits for the command submitted to the previous
	   event node to be confirmed on the specified event node before
	   submitting this command.  Slonik will also wait for any 
       in progress subscriptions involving the ADD ID to be subscribed
       before submitting the MERGE SET command. </para>
   </refsect1>  

   <refsect1> <title> Version Information </title> <para> This command
   was introduced in &slony1; 1.0.5.  In 1.2.1, a race condition was
   rectified where the merge request would be submitted while
   subscriptions were still in process on subscribers; it refuses to
   merge before subscriptions are complete.  </para>
   </refsect1>
  </refentry>

<!-- **************************************** -->

  <refentry id="stmtsetaddtable"><refmeta><refentrytitle>SLONIK SET ADD TABLE</refentrytitle>
   <manvolnum>7</manvolnum></refmeta>
   
   <refnamediv><refname>SET ADD TABLE</refname>
    
    <refpurpose> Add a table to a &slony1;
    replication set </refpurpose></refnamediv>
   
   <refsynopsisdiv>
    <cmdsynopsis>
     <command>SET ADD TABLE (options);</command>
    </cmdsynopsis>
   </refsynopsisdiv>
   <refsect1>
    <title>Description</title>
    
    <para> Add an existing user table to a replication set. The set
    cannot currently be subscribed by any other node - that
    functionality is supported by the <xref linkend="stmtmergeset">
    command.
     
     <variablelist>
      <varlistentry><term><literal> SET ID = ival </literal></term>
       <listitem><para> ID of the set to which the table is to be added. </para></listitem>
      </varlistentry>
      <varlistentry><term><literal> ORIGIN = ival </literal></term>
       <listitem><para> Origin node for the set.  (Optional) </para></listitem>
      </varlistentry>
      <varlistentry><term><literal> ID = ival </literal></term>

       <listitem><para> Unique ID of the table. These ID's are not
	 only used to uniquely identify the individual table within the
	 replication system. The numeric value of this ID also
	 determines the order in which the tables are locked in a <xref
	  linkend="stmtlockset"> command for example. So
	 these numbers might represent any applicable table hierarchy
	 to make sure the <application>slonik</application> command
	 scripts do not deadlock at any critical
	 moment. If this parameter is omitted then slonik will
	 check every node that it can connect to and find the 
	 highest table id being used across all nodes.</para>

         <para> This ID must be unique across all sets; you cannot
         have two tables in the same cluster with the same
         ID. </para>

	 <para> Note that &slony1; generates an in-memory array
	 indicating all of the fully qualified table names; if you use
	 large table ID numbers, the sparsely-utilized array can lead
	 to substantial wastage of memory.  Each potential table ID
	 consumes a pointer to a char, commonly costing 4 bytes per
	 table ID on 32 bit architectures, and 8 bytes per table ID on
	 64 bit architectures. </para>

         </listitem>
      </varlistentry>
      <varlistentry><term><literal> FULLY QUALIFIED NAME = 'string' </literal></term>
       <listitem><para> The full table name including the name of the schema. 
       This can be omitted if <literal>TABLES</literal> is specified instead
      </para></listitem>
      </varlistentry>
	  <varlistentry><term><literal>TABLES = 'string' </literal></term>
	  <listitem><para>A POSIX regular expression that specifies the
	    list of tables that should be added.  This regular expression
	    is evaluated by &postgres against the list of fully qualified table
	    names on the set origin to find the tables that should be added.
	    If <literal>TABLES</literal> is omitted then <literal>
	    FULLY QUALIFIED NAME</literal> must be specified.
        </para> 

	<warning><para> The <literal>TABLES</literal> option requires
	that all the tables are in <quote>good form</quote> to be replicated
	en masse.  The request will fail, not configuring any tables
	for replication, if it encounters any of the following
	problems:
	  <itemizedlist>

	   <listitem><para> Each table must have a <literal>PRIMARY
	   KEY</literal> defined, and a candidate primary key will not
	   suffice.</para></listitem>

	   <listitem><para> If a table is found that is already
	   replicated, the request will fail.</para></listitem>

	   <listitem><para> The <literal>TABLES</literal> option needs
	   to automatically assign table ID values, and looks through
	   the configuration on every node specified by <xref
	   linkend="admconninfo">, finding the largest ID in use, and
	   starting after that for the table IDs that it
	   assigns.</para>

	    <para> It considers it a <quote>benign</quote> failure to
	    find a node that does not yet have a &slony1; schema
	    assigned, as that may be expected to occur if tables are
	    configured before all the nodes have been configured using
	    <xref linkend="stmtstorenode">.  If there is no &slony1;
	    schema, then that node certainly hasn't contributed
	    anything to an increase in the table IDs in use.</para>

	     <para> On the other hand, if a node specified by <xref
	     linkend="admconninfo"> is not available to be queried,
	     the request <emphasis>will
	     fail.</emphasis></para></listitem>

	  </itemizedlist></para>
	</warning>

       </listitem>

      <varlistentry><term><literal> COMMENT = 'string' </literal></term>
       <listitem><para> A descriptive text added to the table entry.  </para></listitem>
      </varlistentry>
	  <varlistentry><term><literal>ADD SEQUENCES= boolean</literal></term>
	  <listitem><para>A boolean value that indicates if any sequences attached
		to columns in this table should also be automatically
		 added to the replication set.  This defaults to false</para></listitem>
	  </varlistentry>
     </variablelist>
    </para>
    <para> This uses &funsetaddtable;. </para>
   </refsect1>
   <refsect1><title>Example</title>
    <programlisting>
SET ADD TABLE (
    SET ID = 1,
    ORIGIN = 1,
    ID = 20,
    FULLY QUALIFIED NAME = 'public.tracker_ticket',
    COMMENT = 'Support ticket',
    ADD SEQUENCES=false
);

or 

SET ADD TABLE (
    SET ID=1,
    TABLE='public.tracker*'
);

    </programlisting>
   </refsect1>
   <refsect1> <title> Error Messages </title>

    <para> Here are some of the error messages you may encounter if
    adding tables incorrectly: </para>

   <variablelist>    
       <varlistentry><term><literal>Slony-I: setAddTable_int: table public.my_table PK column id nullable </literal></term>

        <listitem><para> Primary keys (or candidates thereof) are
        required to have all column defined as <command>NOT
        NULL</command>.  If you have a PK candidate that has columns
        that are not thus restricted, &slony1; will reject the table
        with this message. </para> </listitem> </varlistentry>

       <varlistentry><term><literal>Slony-I: setAddTable_int: table id 14 has already been assigned! </literal></term>

        <listitem><para> The table id, stored in
        <envar>sl_table.tab_id</envar>, is required to be unique
        across all tables/nodes/sets.  Apparently you have tried to
        reused a table ID. </para> </listitem> </varlistentry>

       <varlistentry><term><literal> Slony-I: setAddTable_int(): table public.my_table has no index mt_idx_14</literal></term>

        <listitem><para> This will normally occur with candidate
        primary keys; apparently the index specified is not available
        on this node. </para> </listitem> </varlistentry>

       <varlistentry><term><literal>Slony-I: setAddTable_int(): table public.my_table not found </literal></term>

        <listitem><para> Worse than an index missing, the whole table
        is missing.  Apparently whatever process you were using to get
        the schema into place everywhere didn't work properly. </para>
        </listitem> </varlistentry>

       <varlistentry><term><literal> Slony-I: setAddTable_int(): public.my_view is not a regular table </literal></term>

        <listitem><para> You can only replicate (at least, using
        <command>SET ADD TABLE</command>) objects that are ordinary
        tables.  That doesn't include views or indexes.  (Indexes can
        come along for the ride, but you don't ask to replicate an
        index...)  </para> </listitem> </varlistentry>

       <varlistentry><term><literal> Slony-I: setAddTable_int(): set 4 not found </literal></term>

        <listitem><para> You need to define a replication set before
        assigning tables to it. </para> </listitem> </varlistentry>

       <varlistentry><term><literal> Slony-I: setAddTable(): set 4 has remote origin </literal></term>

        <listitem><para> This will occur if set 4 is configured with,
        as origin, node 1, and then you submit a <command>SET ADD
        TABLE</command> request involving that set to some other node
        than node 1.  This would be expected to occur if there was
        some confusion in the <command>admin conninfo</command>
        configuration in the slonik script preamble...</para>
        </listitem>
        </varlistentry>

       <varlistentry><term><literal>Slony-I: cannot add table to currently subscribed set 1 </literal></term>

        <listitem><para> &slony1; does not support adding tables to
        sets that are already participating in subscriptions.
        Instead, you need to define a new replication set, and add any
        new tables to <emphasis>that</emphasis> set.  You might then
        use <xref linkend="stmtmergeset"> to merge the new set into an
        existing one, if that seems appropriate. </para> </listitem>
        </varlistentry>

   </variablelist>    

   </refsect1>
   <refsect1> <title> Locking Behaviour </title>

    <para> On the origin node, this operation requires a brief
    exclusive lock on the table in order to alter it to add 
    replication triggers.  On subscriber nodes, corresponding locking
    takes place at the time of the <command>SUBSCRIBE_SET</command>
    event.  </para>
   </refsect1>

   <refsect1> <title> Slonik Event Confirmation Behaviour </title>
	 <para> Slonik waits for the command submitted to the previous
	   event node to be confirmed on the specified event node before
	   submitting this command.</para>
   </refsect1>


   <refsect1> <title> Version Information </title>
    <para> This command was introduced in &slony1; 1.0 </para>
   </refsect1>
  </refentry>

<!-- **************************************** -->

  <refentry id="stmtsetaddsequence"><refmeta><refentrytitle>SLONIK SET ADD SEQUENCE</refentrytitle>
   <manvolnum>7</manvolnum></refmeta>
   
   <refnamediv><refname>SET ADD SEQUENCE</refname>
    
    <refpurpose> Add a sequence to a
    &slony1; replication set
    </refpurpose></refnamediv>
   
   <refsynopsisdiv>
    <cmdsynopsis>
     <command>SET ADD SEQUENCE (options);</command>
    </cmdsynopsis>
   </refsynopsisdiv>
<refsect1>
    <title>Description</title>
    
    <para>
     Add an existing user sequence to a replication set. The set
     cannot currently be subscribed by any other node - that
     functionality is supported by the <xref linkend="stmtmergeset">
     command.
     
     <variablelist>
      <varlistentry><term><literal> SET ID = ival </literal></term>
       <listitem><para> ID of the set to which the sequence is to be added.
	</para></listitem>
      </varlistentry>
      <varlistentry><term><literal> ORIGIN = ival </literal></term>
       <listitem><para> Origin node for the set. (optional) </para></listitem>
      </varlistentry>
      <varlistentry><term><literal> ID = ival </literal></term>
       
       <listitem><para> Unique ID of the sequence.  <note><para> Note
	   that this ID needs to be unique <emphasis>across
	    sequences</emphasis> throughout the cluster; the numbering of
	   tables is separate, so you might have a table with ID 20 and a
	   sequence with ID 20, and they would be recognized as
	   separate.</para> </note>  This parameter is optional.  
	   If this parameter is omitted
	   then slonik will check every node that it can connect to and find the 
	   highest table id being used across all nodes. </para></listitem>
       
      </varlistentry>
      <varlistentry><term><literal> FULLY QUALIFIED NAME = 'string' </literal></term>
       <listitem><para> The full sequence name including schema name.
	   If <literal>SEQUENCES</literal> is specified then
	   <literal>FULLY QUALIFIED NAME</literal> should be omitted.
	   </para></listitem>
      </varlistentry>
	  <varlistentry><term><literal>SEQUENCES = 'string' </literal></term>
		<listitem><para>A POSIX regular expression that matches to the
		sequences that should be added to the replication set.
		This regular expression is passed to postgresql for evaluation
		on the set origin against fully qualified sequence names. This
		parameter is optional. If <literal>FULLY QUALIFIED NAME</literal>
		is omitted then
		<literal>SEQUENCES</literal> must be specified. </para></listitem>
		</varlistentry>
      <varlistentry><term><literal> COMMENT = 'string' </literal></term>
       <listitem><para> A descriptive text added to the sequence entry.  </para></listitem>
      </varlistentry>
     </variablelist>
    </para>
    <para> This uses &funsetaddsequence;. </para>
   </refsect1>
   <refsect1><title>Example</title>
    <programlisting>
     SET ADD SEQUENCE (
     SET ID = 1,
     ORIGIN = 1,
     ID = 20,
     FULLY QUALIFIED NAME = 'public.tracker_ticket_id_seq',
     COMMENT = 'Support ticket ID sequence'
     );

	 or

	 SET ADD SEQUENCE(
	 SET ID=1,
	 SEQUENCES='public.tracker_ticket_id_seq'
	 );


    </programlisting>
   </refsect1>
   <refsect1> <title> Locking Behaviour </title>	

    <para> No application-visible locking should take place. </para>
   </refsect1>

   <refsect1> <title> Slonik Event Confirmation Behaviour </title>
	   <para> Slonik waits for the command submitted to the previous
	   event node to be confirmed on the specified event node before
	   submitting this command.</para>
	 </refsect1>


   <refsect1> <title> Version Information </title>
    <para> This command was introduced in &slony1; 1.0 </para>
   </refsect1>
  </refentry>
  
<!-- **************************************** -->

  <refentry id="stmtsetdroptable"><refmeta><refentrytitle>SLONIK SET DROP TABLE</refentrytitle>
   <manvolnum>7</manvolnum></refmeta>
   
   <refnamediv><refname>SET DROP TABLE</refname>
    
    <refpurpose> Remove a table from a
    &slony1; replication set
    </refpurpose></refnamediv>
   
   <refsynopsisdiv>
    <cmdsynopsis>
     <command>SET DROP TABLE (options);</command>
    </cmdsynopsis>
   </refsynopsisdiv>
   <refsect1>
    <title>Description</title>
    
    <para>
     Drop a table from a replication set.
    </para>
    <para>
     <variablelist>
      <varlistentry><term><literal> ORIGIN = ival </literal></term>
       <listitem><para> Origin node for the set.  A future version of <application>slonik</application>
	 might figure out this information by itself.</para></listitem>
      </varlistentry>
      <varlistentry><term><literal> ID = ival </literal></term>
       
  <listitem><para> Unique ID of the table.</para></listitem></varlistentry>
     </variablelist>
    </para>
    <para> This uses &funsetdroptable;. </para>
   </refsect1>
   <refsect1><title>Example</title>
    <programlisting>
     SET DROP TABLE (
     ORIGIN = 1,
     ID = 20
     );
    </programlisting>
   </refsect1>
   <refsect1> <title> Locking Behaviour </title>

    <para> This operation must acquire an exclusive lock on the table
    being dropped from replication in order to alter it to drop the
    replication trigger.  On subscriber nodes, this also involves
    adding back any rules/triggers that have been hidden. </para>
   </refsect1>

   <refsect1> <title> Slonik Event Confirmation Behaviour </title>
	 <para> Slonik waits for the command submitted to the previous
	   event node to be confirmed on the specified event node before
	   submitting this command.</para>
   </refsect1>   

   <refsect1> <title> Version Information </title>
    <para> This command was introduced in &slony1; 1.0.5 </para>
   </refsect1>
  </refentry>
  
<!-- **************************************** -->

  <refentry id="stmtsetdropsequence"><refmeta><refentrytitle>SLONIK SET DROP SEQUENCE</refentrytitle>
   <manvolnum>7</manvolnum></refmeta>
   
   <refnamediv><refname>SET DROP SEQUENCE</refname>
    
    <refpurpose> Remove a sequence from a
    &slony1; replication set
    </refpurpose></refnamediv>
   
   <refsynopsisdiv>
    <cmdsynopsis>
     <command>SET DROP SEQUENCE (options);</command>
    </cmdsynopsis>
   </refsynopsisdiv>
   <refsect1>
    <title>Description</title>
    
    <para>
     Drops an existing user sequence from a replication set.
     <variablelist>
      <varlistentry><term><literal> ORIGIN = ival </literal></term>
       <listitem><para> Origin node for the set.  A future version of <application>slonik</application>
	 might figure out this information by itself.</para></listitem>
      </varlistentry>
      <varlistentry><term><literal> ID = ival </literal></term>
       
       <listitem><para> Unique ID of the sequence.</para></listitem>
       
      </varlistentry>
     </variablelist>
    </para>
    <para> This uses &funsetdropsequence;. </para>
   </refsect1>
<refsect1><title>Example</title>
    <programlisting>
     SET DROP SEQUENCE (
     ORIGIN = 1,
     ID = 20
     );
</programlisting>
   </refsect1>
   <refsect1> <title> Locking Behaviour </title>

    <para> No application-visible locking should take place. </para>
   </refsect1>

   <refsect1> <title> Slonik Event Confirmation Behaviour </title>
	 <para> Slonik waits for the command submitted to the previous
	   event node to be confirmed on the specified event node before
	   submitting this command.</para>
   </refsect1>

   <refsect1> <title> Version Information </title>
    <para> This command was introduced in &slony1; 1.0.5 </para>
   </refsect1>
  </refentry>
  
<!-- **************************************** -->
  
  <refentry id="stmtsetmovetable"><refmeta><refentrytitle>SLONIK SET MOVE
     TABLE</refentrytitle><manvolnum>7</manvolnum></refmeta>
   
   <refnamediv><refname>SET MOVE TABLE</refname>

    <refpurpose> Move a table from one
    &slony1; replication set to another
    </refpurpose></refnamediv>
   
   <refsynopsisdiv>
    <cmdsynopsis>
     <command>SET MOVE TABLE (options);</command>
    </cmdsynopsis>
   </refsynopsisdiv>
   <refsect1>
    <title>Description</title>
    
    <para>
     Change the set a table belongs to. The current set and the new
     set must origin on the same node and subscribed by the same
     nodes.  <caution><para> Due to the way subscribing to new sets
       works make absolutely sure that the subscription of all nodes to
       the sets is completely processed before moving tables. Moving a
       table too early to a new set causes the subscriber to try and add
       the table already during the subscription process, which fails
       with a duplicate key error and breaks
       replication.</para></caution>
     
     <variablelist>
      <varlistentry><term><literal> ORIGIN = ival </literal></term>
       <listitem><para> Current origin of the set.  A future version of <application>slonik</application>
	 might figure out this information by itself.</para></listitem>
      </varlistentry>
      <varlistentry><term><literal> ID = ival </literal></term>

       <listitem><para> Unique ID of the table.</para></listitem></varlistentry>
      <varlistentry><term><literal> NEW SET = ival </literal></term>
       
  <listitem><para> Unique ID of the set to which the table should be added.</para></listitem></varlistentry>
     </variablelist>
    </para>
    <para> This uses &funsetmovetable;. </para>
   </refsect1>
   <refsect1><title>Example</title>
    <programlisting>
SET MOVE TABLE (
    ORIGIN = 1,
    ID = 20,
    NEW SET = 3
);
    </programlisting>
   </refsect1>
   <refsect1> <title> Locking Behaviour </title>

    <para> No application-visible locking should take place. </para>
   </refsect1>
   
   <refsect1> <title> Slonik Event Confirmation Behaviour </title>
	 <para> Slonik waits for the command submitted to the previous
	   event node to be confirmed on the specified event node before
	   submitting this command.</para>
   </refsect1>

   <refsect1> <title> Version Information </title>
    <para> This command was introduced in &slony1; 1.0.5 </para>
   </refsect1>
</refentry>
  

<!-- **************************************** -->

  <refentry id="stmtsetmovesequence"><refmeta><refentrytitle>SLONIK SET MOVE SEQUENCE</refentrytitle>
   <manvolnum>7</manvolnum></refmeta>
   
   <refnamediv><refname>SET MOVE SEQUENCE</refname>
    
    <refpurpose> Move a sequence from one
    &slony1; replication set to another
    </refpurpose></refnamediv>
   
   <refsynopsisdiv>
    <cmdsynopsis>
     <command>SET MOVE SEQUENCE (options);</command>
    </cmdsynopsis>
   </refsynopsisdiv>
   <refsect1>
    <title>Description</title>

    <para>
     Change the set a sequence belongs to. The current set and the new
     set must originate on the same node and subscribed by the same
     nodes.

     <caution><para> Due to the way subscribing to new sets works make
       absolutely sure that the subscription of all nodes to the sets
       is completely processed before moving sequences. Moving a sequence too
       early to a new set causes the subscriber to try and add the sequence
       already during the subscription process, which fails with a duplicate
       key error and breaks replication.</para></caution>
     
     <variablelist>
      <varlistentry><term><literal> ORIGIN = ival </literal></term>
       <listitem><para> Origin node for the set.  A future version of <application>slonik</application>
	 might figure out this information by itself.</para></listitem>
      </varlistentry>
      <varlistentry><term><literal> ID = ival </literal></term>
       
       <listitem><para> Unique ID of the sequence.</para></listitem>
       
      </varlistentry>
      <varlistentry><term><literal> NEW SET = ival </literal></term>
       
       <listitem><para> Unique ID of the set to which the sequence should be moved.</para></listitem>
       
      </varlistentry>
     </variablelist>
    </para>
    <para> This uses &funsetmovesequence;. </para>
   </refsect1>
   <refsect1><title>Example</title>
    <programlisting>
SET MOVE SEQUENCE (
    ORIGIN = 1,
    ID = 20,
    NEW SET = 3
);
    </programlisting>
   </refsect1>
   <refsect1> <title> Locking Behaviour </title>

    <para> No application-visible locking should take place. </para>
   </refsect1>

   <refsect1> <title> Slonik Event Confirmation Behaviour </title>
	 <para> Slonik waits for the command submitted to the previous
	   event node to be confirmed on the specified event node before
	   submitting this command.</para>
   </refsect1>

   <refsect1> <title> Version Information </title>
    <para> This command was introduced in &slony1; 1.0.5 </para>
   </refsect1>
  </refentry>


<!-- **************************************** -->

  <refentry id="stmtstoretrigger"><refmeta><refentrytitle>SLONIK STORE TRIGGER</refentrytitle>
   <manvolnum>7</manvolnum></refmeta>

   <refnamediv><refname>STORE TRIGGER</refname>
    
    <refpurpose> Indicate that a trigger should not be disabled by
    &slony1; on a subscriber node
    </refpurpose></refnamediv>
   
   <refsect1> <title> Version Information </title>
    <para> This command was introduced in &slony1; 1.0 </para>

    <para> In &slony1; version 2.0, this command is removed as
    obsolete because triggers are no longer <quote>messed around
    with</quote> in the system catalogue. </para>

   </refsect1>
  </refentry>

<!-- **************************************** -->

  <refentry id="stmtdroptrigger"><refmeta><refentrytitle>SLONIK DROP TRIGGER</refentrytitle>
   <manvolnum>7</manvolnum></refmeta>
   
   <refnamediv><refname>DROP TRIGGER</refname>
    
    <refpurpose> Return a trigger to default behavior, where it will
    not fire on subscriber nodes </refpurpose></refnamediv>
   
    <refsect1> <title> Version Information </title>
    <para> This command was introduced in &slony1; 1.0 </para>

    <para> In &slony1; version 2.0, this command is removed as
    obsolete because triggers are no longer <quote>messed around
    with</quote> in the system catalogue. </para>

   </refsect1>
  </refentry>
  
<!-- **************************************** -->
  <refentry id="stmtsubscribeset"><refmeta><refentrytitle>SLONIK SUBSCRIBE SET</refentrytitle>
   <manvolnum>7</manvolnum></refmeta>

   <refnamediv><refname>SUBSCRIBE SET</refname>
    
    <refpurpose> Start replication of &slony1; set </refpurpose></refnamediv>
   
   <refsynopsisdiv>
    <cmdsynopsis>
     <command>SUBSCRIBE SET (options);</command>
    </cmdsynopsis>
   </refsynopsisdiv>
   <refsect1>
    <title>Description</title>
    
    <para> This performs one of two actions: </para>

    <itemizedlist>
 
    <listitem><para> Initiates replication for a replication set </para>
    <para> Causes a node (subscriber) to start replicating a set of
    tables either from the origin or from another provider node, which
    must itself already be be an active, forwarding subscriber.</para>
    
    <para> The application tables contained in the set must already
     exist and should ideally be empty. The current version of
     &slony1; will <emphasis>not</emphasis>
     attempt to copy the schema of the set. The replication daemon will
     start copying the current content of the set from the given
     provider and then try to catch up with any update activity that
     happened during that copy process. After successful subscription,
     the tables are guarded on the subscriber, using triggers, against
     accidental updates by the application.
    </para>
    
    <para> If the tables on the subscriber are
    <emphasis>not</emphasis> empty, then the <command>COPY
    SET</command> event (which is part of the subscription process)
    may wind up doing more work than should be strictly
    necessary:</para>
     <itemizedlist>

      <listitem><para> It attempts to <command>TRUNCATE</command> the
      table, which will be efficient. </para> </listitem>
      
      <listitem><para> If that fails (a foreign key relationship might
      prevent TRUNCATE from working), it uses
      <command>DELETE</command> to delete all <quote>old</quote>
      entries in the table</para></listitem>

      <listitem><para> Those old entries clutter up the table until it
      is next <command>VACUUM</command>ed <emphasis>after</emphasis>
      the subscription process is complete</para></listitem>
      
      <listitem><para> The indices for the table will contain entries
      for the old, deleted entries, which will slow the process of
      inserting new entries into the index.</para></listitem>
     </itemizedlist>

     <warning><para> This operation can take a (potentially distinctly)
     non-zero period of time.  If you have a great deal of data in a
     particular set of tables, it may take hours or even (if <quote>a
     great deal</quote> indicates <quote>tens or hundreds gigabytes of
     data</quote>) possibly multiple days for this event to
     complete.</para>

     <para> The <command>SUBSCRIBE SET</command> request will,
     nonetheless, return fairly much immediately, even though the
     work, being handled by the <command>COPY SET</command> event, is
     still in progress.  If you need to set up subscriptions for a set
     of cascading nodes, you will need to wait for each subscriber to
     complete subscribing before submitting requests for subscriptions
     that use that node as a provider. </para>

<programlisting>
 Slony-I: provider 2 is not an active forwarding node for replication set 1
</programlisting>

     <para> In effect, such subscription requests will be ignored
     until the provider is ready.</para>
</warning>

     </listitem>

     <listitem><para> Revising subscription information for already-subscribed nodes. </para>

     <para> If you need to revise subscription information for a
       node, you <emphasis>also</emphasis> submit the new information
       using this command, and the new configuration will be propagated
       throughout the replication network.  The normal reason to revise
       this information is that you want a node to subscribe to a
       <emphasis> different </emphasis> provider node, or for a node to
       become a <quote>forwarding</quote> subscriber so it may later
       become the provider for a later subscriber.</para>

     </listitem>
     </itemizedlist>

     <variablelist>
      <varlistentry><term><literal> ID = ival </literal></term>
       <listitem><para> ID of the set to subscribe</para></listitem>
       
      </varlistentry>
      <varlistentry><term><literal> PROVIDER = ival </literal></term>
       
       <listitem><para> Node ID of the data provider from which this
       node draws data.</para></listitem>
       
      </varlistentry>
      <varlistentry><term><literal> RECEIVER = ival </literal></term>
       
       <listitem><para> Node ID of the new subscriber</para></listitem>
       
      </varlistentry>
      <varlistentry><term><literal> FORWARD = boolean </literal></term>
       
       <listitem><para> Flag whether or not the new subscriber should
       store the log information during replication to make it
       possible candidate for the provider role for future nodes.  Any
       node that is intended to be a candidate for FAILOVER
       <emphasis>must</emphasis> have <command>FORWARD =
       yes</command>.</para></listitem>

      </varlistentry>
      <varlistentry><term><literal> OMIT COPY = boolean </literal></term>
       
       <listitem><para> Flag whether or not the subscription process
       should omit doing the <command>COPY</command> of the existing
       data in the set.  In effect, use this option indicates
       <quote>Trust me, the data is already in sync!</quote>
       </para>

       <para> This is notably useful for the following sorts of cases:
       </para>

       <itemizedlist>
	<listitem><para> Major inter-version upgrades (<emphasis>e.g. </emphasis> - as from &slony1; 1.2 to 2.0) may be done quickly. </para> </listitem>
	<listitem><para> Cloning a <quote>master node</quote>.  <xref linkend="stmtcloneprepare">/<xref linkend="stmtclonefinish">   </para> </listitem>
	<listitem><para> </para> </listitem>
       </itemizedlist>
       </listitem>

      </varlistentry>
     </variablelist>
   </refsect1>
   <refsect1><title>Example</title>
    <programlisting>
SUBSCRIBE SET (
   ID = 1,
   PROVIDER = 1,
   RECEIVER = 3,
   FORWARD = YES
);
  WAIT FOR EVENT(
    ORIGIN=1, 
    CONFIRMED=ALL,
    WAIT ON=1
);
     
    </programlisting>
   </refsect1>

   <refsect1> <title> Forwarding Behaviour </title>

    <para> The <command>FORWARD=boolean</command> flag indicates
    whether the subscriber will store log information in tables
    &sllog1; and &sllog2;.  Several implications fall from
    this...</para>

    <para> By storing the data in these tables on the subscriber,
    there is some additional processing burden.  If you are certain
    that you would never want to <xref linkend="stmtmoveset"> or <xref
    linkend="stmtfailover"> to a particular subscriber, it is worth
    considering turning off forwarding on that node.  </para>

    <para> There is, however, a case where having forwarding turned
    off opens up a perhaps-unexpected failure condition; a rule of
    thumb should be that <emphasis>all nodes that connect directly to
    the origin</emphasis> should have forwarding turned on.  Supposing
    one such <quote>direct subscriber</quote> has forwarding turned
    off, it is possible for that node to be forcibly lost in a case of
    failover.  The problem comes if that node gets ahead of other
    nodes.</para>

    <para> Let's suppose that the origin, node 1 is at SYNC number
    88901, a non-forwarding node, node 2 has processed up to SYNC
    88897, and other forwarding nodes, 3, 4, and 5, have only
    processed data up to SYNC 88895.  At that moment, the disk system
    on the origin node catches fire.  Node 2 has the
    <emphasis>data</emphasis> up to SYNC 88897, but there is no
    remaining node that contains, in &sllog1; or &sllog2;, the data
    for SYNCs 88896 and 88897, so there is no way to bring nodes 3-5
    up to that point.</para>

    <para> At that point, there are only two choices: To drop node 2,
    because there is no way to continue managing it, or to drop all
    nodes <emphasis>but</emphasis> 2, because there is no way to bring
    them up to SYNC 88897.</para>

    <para> That dilemma may be avoided by making sure that all nodes
    directly subscribing to the origin have forwarding turned
    on. </para>

   </refsect1>
   <refsect1> <title> Dangerous/Unintuitive Behaviour </title>

   <itemizedlist>

     <listitem><para> The fact that the request returns immediately
     even though the subscription may take considerable time to
     complete may be a bit surprising. </para> 

     <para> Processing of the subscription involves
     <emphasis>two</emphasis> events; the
     <command>SUBSCRIBE_SET</command>, initiated on the set origin
     node, and an <command>ENABLE_SUBSCRIPTION</command>.
     This means that <xref
     linkend="stmtwaitevent"> must be used following a SUBSCRIBE SET
     to wait until the last event on the set origin completes.
     </listitem>

     <listitem><para> This command has <emphasis>two</emphasis>
     purposes; setting up subscriptions (which should be unsurprising)
     and <emphasis>revising subscriptions</emphasis>, which isn't so
     obvious to intuition. </para> </listitem>

     <listitem><para> New subscriptions are set up by using
     <command>DELETE</command> or <command>TRUNCATE</command> to
     empty the table on a subscriber.  If you created a new node by
     copying data from an existing node, it might <quote>seem
     intuitive</quote> that that data should be kept; that is not the
     case - the former contents are discarded and the node is
     populated <emphasis>from scratch</emphasis>.</para> </listitem>

     <listitem><para> The <command>OMIT COPY</command> option has the
     potential to be a large <quote>foot gun</quote> in that it allows
     the administrator to push replication sets out of sync. </para>
     </listitem>
   </itemizedlist>

   </refsect1>
   <refsect1> <title> Locking Behaviour </title>

    <para> This operation does <emphasis>not</emphasis> require
    acquiring any locks on the provider node.</para>

    <para> On the subscriber node, it will have the effect of locking
    every table in the replication set.  In version 1.2 and later, exclusive
    locks are acquired at the beginning of the process.
    </para>
   </refsect1>

   <refsect1> <title> Slonik Event Confirmation Behaviour </title>
	 <para> Slonik waits until the provider has confirmed all
	 outstanding configuration events from any other node before
	 contacting the provider to determine the set origin.  Slonik
	 then waits for the command submitted to the previous event
	 node to be confirmed on the origin before submitting this
	 command to the origin.</para>
</refsect1>

   <refsect1> <title> Version Information </title>
    <para> This command was introduced in &slony1; 1.0 </para>
    <para> The <command>OMIT COPY</command> option was introduced in &slony1; 2.0.3.</para>
    <para> In &slony1; 2.0.5 the SUBSCRIBE SET command gets submitted
           directly against the set origin. Prior to this change the 
           SUBSCRIBE SET was submitted against the provider
   </para>
   </refsect1>
  </refentry>
  
<!-- **************************************** -->

  <refentry id="stmtunsubscribeset"><refmeta><refentrytitle>SLONIK UNSUBSCRIBE SET</refentrytitle>
   <manvolnum>7</manvolnum></refmeta>
   
   <refnamediv><refname>UNSUBSCRIBE SET</refname>

    <refpurpose> End replication of &slony1; set </refpurpose></refnamediv>
   
   <refsynopsisdiv>
    <cmdsynopsis>
     <command>UNSUBSCRIBE SET (options);</command>
    </cmdsynopsis>
   </refsynopsisdiv>
   <refsect1>
    <title>Description</title>

    <para> Stops the subscriber from replicating the set. The tables
     are opened up for full access by the client application on the
     former subscriber. The tables are not truncated or otherwise
     modified. All original triggers, rules and constraints are
     restored.
     
     <variablelist>
      <varlistentry><term><literal> ID = ival </literal></term>
       <listitem><para> ID of the set to unsubscribe</para></listitem>
       
      </varlistentry>
      <varlistentry><term><literal> RECEIVER = ival </literal></term>
       
       <listitem><para> Node ID of the (former) subscriber</para></listitem>
       
      </varlistentry>
     </variablelist>
    </para>
    <para> This uses &fununsubscribeset;. </para>
   </refsect1>
   <refsect1><title>Example</title>
    <programlisting>
UNSUBSCRIBE SET (
   ID = 1,
   RECEIVER = 3
);
    </programlisting>
   </refsect1>
   <refsect1> <title> Locking Behaviour </title>

    <para> Exclusive locks on each replicated table will be taken out
    on the subscriber in order to drop replication triggers from the
    tables and restore other triggers/rules. </para>
   </refsect1>

   <refsect1> <title> Slonik Event Confirmation Behaviour </title>
	 <para> Slonik waits for the command submitted to the previous
	   event node to be confirmed on the specified event node before
	   submitting this command.</para>
   </refsect1>


   <refsect1><title> Dangerous/Unintuitive Behaviour </title>

     <para> Resubscribing an unsubscribed set requires a
     <emphasis>complete fresh copy</emphasis> of data from the
     provider to be transferred since the tables have been subject to
     possible independent modifications.  </para>

   </refsect1>
   <refsect1> <title> Version Information </title>
    <para> This command was introduced in &slony1; 1.0 </para>
   </refsect1>
  </refentry>

  
<!-- **************************************** -->

  <refentry id ="stmtlockset"><refmeta><refentrytitle>SLONIK LOCK SET</refentrytitle>
   <manvolnum>7</manvolnum></refmeta>

   <refnamediv><refname>LOCK SET</refname>
    
    <refpurpose> Guard &slony1; replication
    set to prepare for <command>MOVE SET</command>
    </refpurpose></refnamediv>
   <refsynopsisdiv>
    <cmdsynopsis>
     <command>LOCK SET (options);</command>
    </cmdsynopsis>
   </refsynopsisdiv>
   <refsect1>
    <title>Description</title>
    
    <para> Guards a replication set against client application updates
    in preparation for a <xref linkend="stmtmoveset"> command.
    </para>

    <para> This command must be the first in a possible statement
    group (<command>try</command>).  The reason for this is that it
    needs to commit the changes made to the tables (adding a special
    trigger function) before it can wait for every concurrent
    transaction to finish. At the same time it cannot hold an open
    transaction to the same database itself since this would result in
    blocking itself forever.</para>

    <para> Note that this is a locking operation, which means that
    it can get stuck behind other database activity.</para>

    <para> The operation waits for transaction IDs to advance in order
    that data is not missed on the new origin.  Thus, if you have
    long-running transactions running on the source node, this
    operation will wait for those transactions to complete.
    Unfortunately, if you have another database on the same postmaster
    as the origin node, long running transactions on that database
    will also be considered even though they are essentially
    independent.
     
     <variablelist>
      <varlistentry><term><literal> ID = ival </literal></term>
       <listitem><para> ID of the set to lock</para></listitem>
	 
      </varlistentry>
      <varlistentry><term><literal> ORIGIN = ival </literal></term>
       
       <listitem><para> Node ID of the current set origin</para></listitem>
	 
      </varlistentry>
     </variablelist>
    </para>
    <para> This uses &funlockset;. </para>
   </Refsect1>
   <Refsect1><Title>Example</Title>
    <Programlisting>
LOCK SET (
   ID = 1,
   ORIGIN = 3
);
    </Programlisting>
   </Refsect1>
   <refsect1> <title> Locking Behaviour </title>

    <para> Exclusive locks on each replicated table will be taken out
    on the origin node, and triggers are added to each such table that
    reject table updates. </para>
   </refsect1>
   
   <refsect1> <title> Slonik Event Confirmation Behaviour </title>
	 <para>Slonik does not wait for event confirmations before 
	   performing this command.</para>
   </refsect1>

   <refsect1> <title> Version Information </title>
    <para> This command was introduced in &slony1; 1.0 </para>
   </refsect1>
  </Refentry>

<!-- **************************************** -->

  <refentry id="stmtunlockset"><refmeta><refentrytitle>SLONIK UNLOCK SET</refentrytitle>
   <manvolnum>7</manvolnum></refmeta>
   
   <refnamediv><refname>UNLOCK SET</refname>
    
    <refpurpose> Unlock a &slony1; set that was locked </refpurpose></refnamediv>
   <refsynopsisdiv>
    <cmdsynopsis>
     <command>UNLOCK SET (options);</command>
    </cmdsynopsis>
   </refsynopsisdiv>
   <refsect1>
    <title>Description</title>
    
    <para> 
     Unlocks a previously locked set.
     
     <variablelist>
      <varlistentry><term><literal> ID = ival </literal></term>
       <listitem><para> ID of the set to unlock</para></listitem>
       
      </varlistentry>
      <varlistentry><term><literal> ORIGIN = ival </literal></term>
       
       <listitem><para> Node ID of the current set origin</para></listitem>
       
      </varlistentry>
     </variablelist>
    </para>
    <para> This uses &fununlockset;. </para>
   </refsect1>
   <refsect1><title>Example</title>
    <programlisting>
UNLOCK SET (
   ID = 1,
   ORIGIN = 3
);
    </programlisting>
   </refsect1>
   <refsect1> <title> Locking Behaviour </title>

    <para> Exclusive locks on each replicated table will be taken out
    on the origin node, as the triggers are removed from each table
    that reject table updates. </para>
   </refsect1>
   
   <refsect1> <title> Slonik Event Confirmation Behaviour </title>
	 <para>Slonik does not wait for event confirmations before 
	   performing this command.</para>
   </refsect1>

   <refsect1> <title> Version Information </title>
    <para> This command was introduced in &slony1; 1.0 </para>
   </refsect1>
  </refentry>
  

<!-- **************************************** -->

  <refentry id="stmtmoveset"><refmeta><refentrytitle>SLONIK MOVE SET</refentrytitle>
   <manvolnum>7</manvolnum></refmeta>
   
   <refnamediv><refname>MOVE SET</refname>
    
    <refpurpose> Change origin of a &slony1;
    replication set </refpurpose></refnamediv>
   <refsynopsisdiv>
    <cmdsynopsis>
     <command>MOVE SET (options);</command>
    </cmdsynopsis>
   </refsynopsisdiv>
   <refsect1>
    <title>Description</title>
    
    <para> Changes the origin of a set from one node to another. The
    new origin must be a current subscriber of the set. The set must
    currently be locked on the old origin. </para>
    
    <para> After this command, the set cannot be unlocked on the old
     origin any more. The old origin will continue as a forwarding
     subscriber of the set and the subscription chain from the old
     origin to the new origin will be reversed, hop by hop. As soon as
     the new origin has finished processing the event (that includes
     any outstanding sync events that happened before,
     <emphasis>i.e.</emphasis> fully catching up), the new origin will
     take over and open all tables in the set for client application
     update activity.
    </para>

    <para> This is <emphasis>not</emphasis> failover, as it requires a
     functioning old origin node (you needed to lock the set on the old
     origin).  You would probably prefer to <command>MOVE SET</command>
     instead of <command>FAILOVER</command>, if at all possible, as
     <command>FAILOVER</command> winds up discarding the old origin
     node as being corrupted. Before <command>MOVE SET</command> will
     function a <command>LOCK SET</command> is needed.
</para>
     
    <para> Note that this is a locking operation, which means that
    it can get stuck behind other database activity.
     
     <variablelist>
      <varlistentry><term><literal> ID = ival </literal></term>
       <listitem><para> ID of the set to transfer</para></listitem>
       
      </varlistentry>
      <varlistentry><term><literal> OLD ORIGIN = ival </literal></term>
       
       <listitem><para> Node ID of the current set origin</para></listitem>
       
      </varlistentry>
      <varlistentry><term><literal> NEW ORIGIN = ival </literal></term>
       
  <listitem><para> Node ID of the new set origin</para></listitem>
       
      </varlistentry>
     </variablelist>
    </para>
    <para> This uses &funmoveset;. </para>
   </refsect1>
   <refsect1><title>Example</title>
    <programlisting>
LOCK SET (
   ID = 1,
   ORIGIN = 1
);
MOVE SET (
   ID = 1,
   OLD ORIGIN = 1,
   NEW ORIGIN = 3
);
    </programlisting>
   </refsect1>
   <refsect1> <title> Locking Behaviour </title>

    <para> Exclusive locks on each replicated table will be taken out
    on both the old origin node and the new origin node, as
    replication triggers are changed on both nodes: on the former
    origin, each table has two triggers (logtrigger and lockset)
    dropped and a denyaccess trigger added; on the new origin, the
    denyaccess trigger is dropped and a logtrigger trigger
    added. </para>
   </refsect1>

   <refsect1> <title> Slonik Event Confirmation Behaviour </title>
	 <para> Slonik waits for the command submitted to the previous
	   event node to be confirmed on the specified event node before
	   submitting this command.</para>
   </refsect1>
 

   <refsect1> <title> Version Information </title>
    <para> This command was introduced in &slony1; 1.0 </para>
   </refsect1>
  </refentry>

<!-- **************************************** -->

  <refentry id="stmtfailover"><refmeta><refentrytitle>SLONIK FAILOVER</refentrytitle>
   <manvolnum>7</manvolnum></refmeta>
   
   <refnamediv><refname>FAILOVER</refname>
    
    <refpurpose> Fail a broken replication set over to a backup node
    </refpurpose></refnamediv>
   <refsynopsisdiv>
    <cmdsynopsis>
     <command>FAILOVER (options);</command>
    </cmdsynopsis>
   </refsynopsisdiv>
   <refsect1>
    <title>Description</title>
    
    <para>
     The <command>FAILOVER</command> command causes the backup node to take over all sets
     that currently originate on the failed
     node. <application>slonik</application> will contact all other
     direct subscribers of the failed node to determine which node has
     the highest sync status for each set. If another node has a
     higher sync status than the backup node, the replication will
     first be redirected so that the backup node replicates against
     that other node, before assuming the origin role and allowing
     update activity.
    </para>

    <para>
     After successful failover, all former direct subscribers of the
     failed node become direct subscribers of the backup node. The
     failed node is abandoned, and can and should be removed from the
     configuration with <xref linkend="stmtdropnode">.
    </para>
    
    <variablelist>
     <varlistentry><term><literal> ID = ival </literal></term>
      <listitem><para> ID of the failed node</para></listitem>
      
     </varlistentry>
     <varlistentry><term><literal> BACKUP NODE = ival </literal></term>
      
      <listitem><para> Node ID of the node that will take over all
      sets originating on the failed node</para></listitem>

     </varlistentry>
    </variablelist>
    
    <para> This uses &funfailednode;. </para>
   </refsect1>
   <refsect1><title>Example</title>
    <programlisting>
FAILOVER (
   ID = 1,
   BACKUP NODE = 2
);
    </programlisting>
   </refsect1>
   <refsect1> <title> Locking Behaviour </title>

    <para> Exclusive locks on each replicated table will be taken out
    on both the new origin node as replication triggers are changed.
    If the new origin was not completely up to date, and replication
    data must be drawn from some other node that is more up to date,
    the new origin will not become usable until those updates are
    complete. </para>
   </refsect1>
   <refsect1><title> Dangerous/Unintuitive Behaviour </title>
    <para> This command will abandon the status of the failed
    node.  There is no possibility to let the failed node join the
    cluster again without rebuilding it from scratch as a slave.  If
    at all possible, you would likely prefer to use <xref
    linkend="stmtmoveset"> instead, as that does
    <emphasis>not</emphasis> abandon the failed node.
    </para>

    <para> If there are many nodes in a cluster, and failover includes
    dropping out additional nodes (<emphasis>e.g.</emphasis> when it
    is necessary to treat <emphasis>all</emphasis> nodes at a site
    including an origin as well as subscribers as failed), it is
    necessary to carefully sequence the actions, as described in <xref
    linkend="complexfailover">.
    </para>

   </refsect1>

   <refsect1> <title> Slonik Event Confirmation Behaviour </title>
	 <para>Slonik will submit the FAILOVER_EVENT without waiting
           but wait until the most ahead node has received confirmations
           of the FAILOVER_EVENT from all nodes before completing.</para>
   </refsect1>

   <refsect1> <title> Version Information </title>
    <para> This command was introduced in &slony1; 1.0 </para>
    <para> In version 2.0, the default <envar>BACKUP NODE</envar> value of 1 was removed, so it is mandatory to provide a value for this parameter.</para>
   </refsect1>
  </refentry>

<!-- **************************************** -->

  <refentry id="stmtddlscript"><refmeta><refentrytitle>SLONIK EXECUTE SCRIPT</refentrytitle>
   <manvolnum>7</manvolnum></refmeta>
   
   <refnamediv><refname>EXECUTE SCRIPT</refname>
    
    <refpurpose> Execute SQL/DDL script  </refpurpose></refnamediv>
   <refsynopsisdiv>
    <cmdsynopsis>
     <command>EXECUTE SCRIPT (options);</command>
    </cmdsynopsis>
   </refsynopsisdiv>
   <refsect1>
    <title>Description</title>
    
    <para> Executes a script containing arbitrary SQL statements on
     all nodes that are subscribed to a set at a common controlled
     point within the replication transaction stream.</para>
    
    <para> The specified event origin must be the origin of the set.
    The script file must not contain any <command>START</command> or
    <command>COMMIT TRANSACTION</command> calls.  (This changes
    somewhat in &postgres; 8.0 once nested transactions, aka
    savepoints, are supported) In addition, non-deterministic DML
    statements (like updating a field with
    <function>CURRENT_TIMESTAMP</function>) must be avoided, since the
    data changes done by the script are explicitly not
    replicated. </para>

    <variablelist>
     <varlistentry><term><literal> SET ID = ival </literal></term>

      <listitem><para> The unique numeric ID number of the set
      affected by the script</para></listitem>
      
     </varlistentry>
     <varlistentry><term><literal> FILENAME = '/path/to/file' </literal></term>
      
      <listitem><para> The name of the file containing the SQL script to
	execute.  This might be a relative path, relative to the location of
	the <application>slonik</application> instance you are running, or, preferably,
	an absolute path on the system where <application>slonik</application> is to run.</para>
       
       <para> The <emphasis>contents</emphasis> of the file are propagated as part of
	the event, so the file does not need to be accessible on any of the
	nodes.</para></listitem>
      
     </varlistentry>
     <varlistentry><term><literal> EVENT NODE = ival </literal></term>
      <listitem><para> (Mandatory unless EXECUTE ONLY ON is given) The ID 
	  of the current origin of the set. If EXECUTE ONLY ON
	  is given, EVENT NODE must specify the same node or
	  be omitted.</para></listitem>
      
     </varlistentry>
     <varlistentry><term><literal> EXECUTE ONLY ON = ival
       </literal></term> <listitem><para> (Optional) The ID of the only
	node to actually execute the script.  This option causes the
	script to be propagated by all nodes but executed only by one.
	The default is to execute the script on all nodes that are
	subscribed to the set.</para></listitem>
      
     </varlistentry>
    </variablelist>
    
    <para> See also the warnings in &rddlchanges;.</para>

    <para> Note that this is a potentially heavily-locking
    operation, which means that it can get stuck behind other database
    activity.</para>
  

    <para> Note that if you need to make reference to the cluster
    name, you can use the token <command>@CLUSTERNAME@</command>; if
    you need to make reference to the &slony1; namespace, you can use
    the token <command>@NAMESPACE@</command>; both will be expanded
    into the appropriate replacement tokens. </para>

    <para> This uses &funddlscript;. </para>
   </refsect1>
   <refsect1><title>Example</title>
    <programlisting>
EXECUTE SCRIPT (
   SET ID = 1,
   FILENAME = '/tmp/changes_2008-04-01.sql',
   EVENT NODE = 1
);
    </programlisting>
   </refsect1>
   <refsect1> <title> Locking Behaviour </title>

    <para> Up until the 2.0 branch, each replicated table received an
    exclusive lock, on the origin node, in order to remove the
    replication triggers; after the DDL script completes, those locks
    will be cleared. In the 2.0 branch this is no longer the case.
    EXECUTE SCRIPT won't obtain any locks on your application tables
    though the script that you executing probably will. Due to bug #137
    you should avoid concurrent writes to the tables being
    modified by the script while the script is running.  </para>

    <para> After the DDL script has run on the origin node, it will
    then run on subscriber nodes, where replicated tables will be
    similarly altered to remove replication triggers, therefore
    requiring that exclusive locks be taken out on each node, in
    turn. </para>

  

   </refsect1>

   <refsect1> <title> Slonik Event Confirmation Behaviour </title>
	 <para> Slonik waits for the command submitted to the previous
	   event node to be confirmed on the specified event node before
	   submitting this command.</para>
   </refsect1>

   <refsect1> <title> Version Information </title>
    <para> This command was introduced in &slony1; 1.0. </para>

    <para> Before &slony1; version 1.2, the entire DDL script was
    submitted as one <function>PQexec()</function> request, with the
    implication that the <emphasis>entire</emphasis> script was parsed
    based on the state of the database before invokation of the
    script.  This means statements later in the script cannot depend
    on DDL changes made by earlier statements in the same script.
    Thus, you cannot add a column to a table and add constraints to
    that column later in the same request. </para>

    <para> In &slony1; version 1.2, the DDL script is split into
    statements, and each statement is submitted separately.  As a
    result, it is fine for later statements to refer to objects or
    attributes created or modified in earlier statements.
    Furthermore, in version 1.2, the <command>slonik</command> output
    includes a listing of each statement as it is processed, on the
    set origin node.  Similarly, the statements processed are listed
    in slon logs on the other nodes.</para>

    <para> In &slony1; version 1.0, this would only lock the tables in
    the specified replication set.  As of 1.1 (until 2.0), <emphasis>all
    replicated tables</emphasis> are locked (<emphasis>e.g.</emphasis>
    - triggers are removed at the start, and restored at the end).
    This deals with the risk that one might request DDL changes on
    tables in multiple replication sets. With version 2.0 no locks
    on application tables are obtained by &slony1;</para>

   <para> In version 2.0, the default value for <envar>EVENT
   NODE</envar> was removed, so a node must be specified.</para>

   </refsect1>
  </refentry>

<!-- **************************************** -->

  <refentry id="stmtupdatefunctions"><refmeta><refentrytitle>SLONIK UPDATE FUNCTIONS</refentrytitle>
   <manvolnum>7</manvolnum></refmeta>

   <refnamediv><refname>UPDATE FUNCTIONS</refname>
    
    <refpurpose> Reload stored functions </refpurpose></refnamediv>
   <refsynopsisdiv>
    <cmdsynopsis>
     <command>UPDATE FUNCTIONS (options);</command>
    </cmdsynopsis>
   </refsynopsisdiv>
   <refsect1>
    <title>Description</title>
    
    <para> Reloads stored functions for a node.</para>
    
    <para>Reloads all stored procedure and function definitions in the
    &slony1; schema for the specified node. This command is usually
    part of the &slony1; software upgrade procedure.
    </para>

     <variablelist>
      <varlistentry><term><literal> ID = ival </literal></term>
       
       <listitem><para> The node to refresh.</para></listitem>
       
      </varlistentry>
     </variablelist>

   </refsect1>
   <refsect1><title>Example</title>
    <programlisting>
UPDATE FUNCTIONS (
    ID = 3        # Update functions on node 3
);
    </programlisting>
   </refsect1>
   <refsect1> <title> Locking Behaviour </title>

    <para> No application-visible locking should take place. </para>
   </refsect1>
   
   <refsect1> <title> Slonik Event Confirmation Behaviour </title>
	 <para>Slonik does not wait for event confirmations before 
	   performing this command.</para>
   </refsect1>

   <refsect1> <title> Version Information </title>
    <para> This command was introduced in &slony1; 1.0 </para>
   </refsect1>
   <refsect1> <title> Oddities </title>

    <para> Any mismatch between <xref linkend="slonik"> and the C
    libraries <quote>living</quote> in the &postgres; installation
    will result in this failing to do what is expected, and, more than
    likely, failing to run at all.  You may <emphasis>think</emphasis>
    you are upgrading to version 1.1.5, but if you are running <xref
    linkend="slonik"> from version 1.1.2, or if you didn't restart the
    database with a version that has 1.1.5 libraries, and instead are
    referencing C stored functions from version 1.1.1, the attempt to
    upgrade will fail, because the sets of C functions have regularly
    changed between major versions.</para>

    <para> Before &slony1; 1.2, the error messages that would result
    would be not terribly informative; what you'd find, in &postgres;
    logs, is some error message about being unable to load some stored
    function that happens to be implemented in C.  As of 1.2, one of
    the first things done is to load a stored function to verify
    version numbers; it complains in a much more direct fashion if you
    have some versioning mismatch.  </para>
   </refsect1>
  </refentry>

<!-- **************************************** -->

  <refentry id="stmtwaitevent"><refmeta><refentrytitle>SLONIK WAIT FOR EVENT</refentrytitle>
   <manvolnum>7</manvolnum></refmeta>

   <refnamediv><refname>WAIT FOR EVENT</refname>
    
    <refpurpose> Have Slonik script wait for previous event to
    complete </refpurpose></refnamediv>
   <refsynopsisdiv>
    <cmdsynopsis>
     <command>WAIT FOR EVENT (options);</command>
    </cmdsynopsis>
   </refsynopsisdiv>
   <refsect1>
    <title>Description</title>
    
    <para> Waits for event Confirmation.</para>
    
    <para> <application>Slonik</application> remembers the last event
    generated on every node during script execution (events generated
    by earlier calls are currently not checked). In certain situations
    it is necessary that events generated on one node (such as
    <command>CREATE SET</command>) are processed on another node
    before issuing more commands (for instance, <xref
    linkend="stmtsubscribeset">).  <command>WAIT FOR EVENT</command>
    may be used to cause the <application>slonik</application> script
    to wait for confirmation of an event, which hopefully means that
    the subscriber node is ready for the next action.
    </para>
    
    <para> <command>WAIT FOR EVENT</command> must be called outside of
    any <command>try</command> block in order to work, since new
    confirm messages don't become visible within a transaction.

     <variablelist>
      <varlistentry><term><literal> ORIGIN = ival | ALL </literal></term>
       <listitem><para> The origin of the event(s) to wait for.</para></listitem>
       
      </varlistentry>
      <varlistentry><term><literal> CONFIRMED = ival | ALL </literal></term>
       
       <listitem><para> The node ID of the receiver that must confirm the event(s).</para></listitem>
       
      </varlistentry>
      <varlistentry><term><literal> WAIT ON = ival </literal></term>
       <listitem><para> The ID of the node where the &slconfirm; table
	 is to be checked.</para></listitem>
       
      </varlistentry>
      <varlistentry><term><literal> TIMEOUT = ival </literal></term>
       
       <listitem><para> The number of seconds to wait.  Default is 600
       (10 minutes).  <command>TIMEOUT = 0</command> causes the script
	 to wait indefinitely.</para></listitem>
       
      </varlistentry>
     </variablelist></para>

   </refsect1>
   <refsect1><title>Example</title>
    <programlisting>
WAIT FOR EVENT (
  ORIGIN = ALL,
  CONFIRMED = ALL,
  WAIT ON = 1
);
    </programlisting>
   </refsect1>
   <refsect1> <title> Locking Behaviour </title>

    <para> No application-visible locking should take place. </para>
   </refsect1>
   <refsect1> <title> Version Information </title>
    <para> This command was introduced in &slony1; 1.0 </para>

   <para> In version 2.0, the default value for <envar>WAIT ON</envar>
   was removed, so a node must be specified.</para>

   </refsect1>
   
   <refsect1> <title> Oddities </title> <para> Not all events return
   interesting results.  For instance, many people have run afoul of
   problems with <xref linkend="stmtsubscribeset">, when subscribing a
   new set.  Be aware (and beware!) that a <xref
   linkend="stmtsubscribeset"> request will return the event
   confirmation almost immediately, even though there might be several
   hours of work to do before the subscription is ready.  The trouble
   with <xref linkend="stmtsubscribeset"> is that it is processed as
   <emphasis>two</emphasis> events, one on the origin node, with a
   second event, to enable the subscription, on the subscriber.
   </para>

   <para> In order to more reliably monitor from within a <xref
   linkend="slonik"> script that <xref linkend="stmtsubscribeset"> is
   complete, you may submit a <xref linkend="stmtsync"> event after
   the subscription, and have the WAIT request wait on the
   <command>SYNC</command> event, as follows. </para>
    <programlisting>
     # Assuming that node 1 is the origin for set 999 that has direct subscribers 2 and 3
     SUBSCRIBE SET (ID = 999, PROVIDER = 1, RECEIVER = 2);
     WAIT FOR EVENT (ORIGIN = 1, CONFIRMED = ALL, WAIT ON=1);
     SUBSCRIBE SET (ID = 999, PROVIDER = 1, RECEIVER = 3);
     WAIT FOR EVENT (ORIGIN = 1, CONFIRMED = ALL, WAIT ON=1);
     MERGE SET ( ID = 1, ADD ID = 999, ORIGIN = 1 );
    </programlisting>
   </refsect1>
   
  </refentry>

<!-- **************************************** -->

  <refentry id="stmtrepairconfig"><refmeta><refentrytitle>SLONIK REPAIR CONFIG</refentrytitle>
   <manvolnum>7</manvolnum></refmeta>

   <refnamediv><refname>REPAIR CONFIG</refname>
    
    <refpurpose> Resets the name-to-oid mapping of tables in a replication set, useful for restoring a node after a <application>pg_dump</application>. </refpurpose></refnamediv>
   <refsynopsisdiv>
    <cmdsynopsis>
     <command>REPAIR CONFIG (options);</command>
    </cmdsynopsis>
   </refsynopsisdiv>
   <refsect1>
    <title>Description</title>
    
    <para> Resets name-to-oid mapping.</para>
    
     <variablelist>
      <varlistentry><term><literal> SET ID = ival </literal></term>
       <listitem><para> Which set to clean up after.</para></listitem>
       
      </varlistentry>
      <varlistentry><term><literal> EVENT NODE = ival </literal></term>
       
       <listitem><para> The node ID where this should be submitted.</para></listitem>
       
      </varlistentry>
      <varlistentry><term><literal> EXECUTE ONLY ON = ival </literal></term>

       <listitem><para> The ID of the only node where the mappings are
       to be updated.  If not specified, the default is to execute
       this on all nodes subscribed to the set.</para></listitem>
       
      </varlistentry>
     </variablelist>

   </refsect1>
   <refsect1><title>Example</title>
    <programlisting>
REPAIR CONFIG (
  SET ID = 1,
  EVENT NODE = 2
);
    </programlisting>
   </refsect1>
   <refsect1> <title> Locking Behaviour </title>

    <para> No application-visible locking should take place. </para>
   </refsect1>

   <refsect1> <title> Slonik Event Confirmation Behaviour </title>
	 <para>Slonik does not wait for event confirmations before 
	   performing this command.</para>
   </refsect1>
   
   <refsect1> <title> Version Information </title>
    <para> This command was introduced in &slony1; 1.1 </para>
   </refsect1>
  </refentry>
<!-- **************************************** -->

  <refentry id="stmtsync"><refmeta><refentrytitle>SLONIK SYNC</refentrytitle>
   <manvolnum>7</manvolnum></refmeta>

   <refnamediv><refname>SYNC</refname>
    
    <refpurpose> Generate an ordinary SYNC event </refpurpose></refnamediv>
   <refsynopsisdiv>
    <cmdsynopsis>
     <command>SYNC (options);</command>
    </cmdsynopsis>
   </refsynopsisdiv>
   <refsect1>
    <title>Description</title>
    
    <para> Generates a SYNC event on a specified node.</para>
    
     <variablelist>
      <varlistentry><term><literal> ID = ival </literal></term>
       <listitem><para> The node on which to generate the SYNC event.</para></listitem>
       
      </varlistentry>
     </variablelist>

   </refsect1>
   <refsect1><title>Example</title>
    <programlisting>
     SYNC (ID = 1);
     WAIT FOR EVENT (ORIGIN = 1, CONFIRMED = 2, WAIT ON=1);
    </programlisting>
   </refsect1>
   <refsect1> <title> Locking Behaviour </title>

    <para> No application-visible locking should take place. </para>
   </refsect1>

   <refsect1> <title> Slonik Event Confirmation Behaviour </title>
	 <para>Slonik does not wait for event confirmations before 
	   performing this command.</para>
   </refsect1>
   
   <refsect1> <title> Version Information </title>
    <para> This command was introduced in &slony1; 1.1.6 / 1.2.1 </para>
   </refsect1>
  </refentry>

<!-- **************************************** -->
  
  <refentry id ="stmtsleep"><refmeta><refentrytitle>SLONIK SLEEP</refentrytitle>
   <manvolnum>7</manvolnum></refmeta>
   
   <refnamediv><refname>SLEEP</refname>
    
    <refpurpose> Sleep using system <function>sleep()</function> </refpurpose>
   </refnamediv>
   <refsynopsisdiv>
    <cmdsynopsis>
     <command>sleep </command>
     <arg><replaceable class="parameter"> seconds</replaceable></arg>
    </cmdsynopsis>
   </refsynopsisdiv>
   <refsect1>
    <title>Description</title>
    <para>
     Sleeps for the specified number of seconds.
    </para>
   </Refsect1>
   <Refsect1><Title>Example</Title>
    <Programlisting>
     sleep (seconds = 5);
    </Programlisting>
   </Refsect1>

   <refsect1> <title> Slonik Event Confirmation Behaviour </title>
	 <para>Slonik does not wait for event confirmations before 
	   performing this command.</para>
   </refsect1>

   <refsect1> <title> Version Information </title>
    <para> This command was introduced in &slony1; 1.1.6 / 1.2.1. </para>
   </refsect1>
  </Refentry>


  <refentry id ="stmtcloneprepare"><refmeta><refentrytitle>SLONIK CLONE PREPARE</refentrytitle>
   <manvolnum>7</manvolnum></refmeta>
   
   <refnamediv><refname>CLONE PREPARE</refname>
    
    <refpurpose> Prepare for cloning a node. </refpurpose>
   </refnamediv>
   <refsynopsisdiv>
    <cmdsynopsis>
     <command>clone prepare </command>
     <arg><replaceable class="parameter"> id</replaceable></arg>
     <arg><replaceable class="parameter"> provider</replaceable></arg>
     <arg><replaceable class="parameter"> comment</replaceable></arg>
    </cmdsynopsis>
   </refsynopsisdiv>
   <refsect1>
    <title>Description</title>
    <para>
     Prepares for cloning a specified subscriber node.
    </para>

    <para>
     This duplicates the <quote>provider</quote> node's configuration
     under a new node ID in preparation for the node to be copied via
     standard database tools.
    </para>

    <para> Note that in order that we be certain that this new node be
    consistent with all nodes, it is important to issue a SYNC event
    against every node aside from the provider and wait to start
    copying the provider database at least until all those SYNC events
    have been confirmed by the provider.  Otherwise, it is possible
    for the clone to miss some events. </para>

   </Refsect1>
   <Refsect1><Title>Example</Title>
    <Programlisting>
     clone prepare (id = 33, provider = 22, comment='Clone 33');
     sync (id=11);
     sync (id=22);
     </Programlisting>
   </Refsect1>

   
   <refsect1> <title> Slonik Event Confirmation Behaviour </title>
	 <para>Slonik will wait until the node being cloned (the provider)
	   is caught up with all other nodes before submitting the clone prepare
	   command</para>
</refsect1>

   <refsect1> <title> Version Information </title>
    <para> This command was introduced in &slony1; 2.0. </para>
   </refsect1>
  </Refentry>


  <refentry id ="stmtclonefinish"><refmeta><refentrytitle>SLONIK CLONE FINISH</refentrytitle>
   <manvolnum>7</manvolnum></refmeta>
   
   <refnamediv><refname>CLONE FINISH</refname>
    
    <refpurpose> Complete cloning a node. </refpurpose>
   </refnamediv>
   <refsynopsisdiv>
    <cmdsynopsis>
     <command>clone prepare </command>
     <arg><replaceable class="parameter"> id</replaceable></arg>
     <arg><replaceable class="parameter"> provider</replaceable></arg>
    </cmdsynopsis>
   </refsynopsisdiv>
   <refsect1>
    <title>Description</title>
    <para>
     Finishes cloning a specified node.
    </para>

    <para>
     This completes the work done by <xref
     linkend="stmtcloneprepare">, establishing confirmation data for
     the new <quote>clone</quote> based on the status found for the
     <quote>provider</quote> node.
    </para>
   </Refsect1>
   <Refsect1><Title>Example</Title>
    <Programlisting>
     clone finish (id = 33, provider = 22);
    </Programlisting>
   </Refsect1>

    <refsect1> <title> Slonik Event Confirmation Behaviour </title>
	 <para>Slonik does not wait for event confirmations before 
	   performing this command.</para>
   </refsect1>
   

   <refsect1> <title> Version Information </title>
    <para> This command was introduced in &slony1; 2.0. </para>
   </refsect1>
  </Refentry>
 </reference>
<!-- Keep this comment at the end of the file
Local variables:
mode:sgml
sgml-omittag:nil
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
sgml-parent-document:"slony.sgml"
sgml-exposed-tags:nil
sgml-local-catalogs:("/usr/lib/sgml/catalog")
sgml-local-ecat-files:nil
End:
-->
