Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
branch: master
Fetching contributors…

Cannot retrieve contributors at this time

9199 lines (8011 sloc) 261.603 kb
<!-- $Header: /slony1/slony1-engine/doc/adminguide/schemadoc.xml,v 1.7 2006-07-31 18:56:24 cbbrowne Exp $ -->
<chapter id="schema" xreflabel="schemadoc">
<title>Schéma schemadoc</title>
<section id="table.sl-config-lock" xreflabel="sl_config_lock">
<title id="table.sl-config-lock-title">
Table&nbsp;: <structname>sl_config_lock</structname>
</title>
<para>
Cette table existe seulement pour empêcher l'exécution concurrent de procédure
de modification de la configuration et des verrous mortels possibles.
</para>
<para>
<variablelist>
<title>Structure de <structname>sl_config_lock</structname></title>
<varlistentry>
<term><structfield>dummy</structfield></term>
<listitem><para><type>integer</type></para></listitem>
</varlistentry>
</variablelist>
</para>
</section>
<section id="table.sl-confirm" xreflabel="sl_confirm">
<title id="table.sl-confirm-title">
Table&nbsp;: <structname>sl_confirm</structname>
</title>
<para>
Contient la confirmation des événements de réplication. Après une certaine
période, Slony supprime les anciens événements à partir de cette table et
de la table sl_event.
</para>
<para>
<variablelist>
<title>Structure de <structname>sl_confirm</structname></title>
<varlistentry>
<term><structfield>con_origin</structfield></term>
<listitem>
<para><type>integer</type></para>
<para>
L'identifiant (provenant de sl_node.no_id) du n&oelig;ud source pour
cet événement
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>con_received</structfield></term>
<listitem>
<para><type>integer</type></para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>con_seqno</structfield></term>
<listitem>
<para><type>bigint</type></para>
<para>
L'identifiant de l'événement
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>con_timestamp</structfield></term>
<listitem>
<para>
<type>timestamp without time zone</type>
<literal>DEFAULT (timeofday())::timestamp without time zone</literal>
</para>
<para>
Horodatage de la confirmation de l'événement
</para>
</listitem>
</varlistentry>
</variablelist>
<variablelist>
<title>Index sur sl_confirm</title>
<varlistentry>
<term>sl_confirm_idx1</term>
<listitem>
<para>con_origin, con_received, con_seqno</para>
</listitem>
</varlistentry>
<varlistentry>
<term>sl_confirm_idx2</term>
<listitem><para>con_received, con_seqno</para></listitem>
</varlistentry>
</variablelist>
</para>
</section>
<section id="table.sl-event" xreflabel="sl_event">
<title id="table.sl-event-title">
Table&nbsp;: <structname>sl_event</structname>
</title>
<para>
Contient des informations sur les événements de réplication. Après une période
de temps, Slony supprime les anciens événements de cette table et de la table
sl_confirm.
</para>
<para>
<variablelist>
<title>
Structure de <structname>sl_event</structname>
</title>
<varlistentry>
<term><structfield>ev_origin</structfield></term>
<listitem>
<para><type>integer</type> <literal>PRIMARY KEY</literal></para>
<para>
L'identifiant (provenant de sl_node.no_id) du n&oelig;ud source pour
cet événement
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>ev_seqno</structfield></term>
<listitem>
<para><type>bigint</type> <literal>PRIMARY KEY</literal></para>
<para>
L'identifiant de l'événement
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>ev_timestamp</structfield></term>
<listitem>
<para>
<type>timestamp without time zone</type>
</para>
<para>
Horodatage de la création de l'enregistrement
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>ev_minxid</structfield></term>
<listitem>
<para><type>xxid</type></para>
<para>
Identifiant de transaction le plus ancien du n&oelig;ud fournisseur
pour cet événement
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>ev_maxxid</structfield></term>
<listitem>
<para><type>xxid</type></para>
<para>
Dernier identifiant de transaction du n&oelig;ud fournisseur pour cet
événement
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>ev_xip</structfield></term>
<listitem>
<para><type>text</type></para>
<para>
Liste des identifiants de transaction, dans l'ordre, qui font partie
de cet événement
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>ev_type</structfield></term>
<listitem>
<para><type>text</type></para>
<para>
Le type d'événement pour cet enregistrement.
SYNC = Synchronise
STORE_NODE =
ENABLE_NODE =
DROP_NODE =
STORE_PATH =
DROP_PATH =
STORE_LISTEN =
DROP_LISTEN =
STORE_SET =
DROP_SET =
MERGE_SET =
SET_ADD_TABLE =
SET_ADD_SEQUENCE =
STORE_TRIGGER =
DROP_TRIGGER =
MOVE_SET =
ACCEPT_SET =
SET_DROP_TABLE =
SET_DROP_SEQUENCE =
SET_MOVE_TABLE =
SET_MOVE_SEQUENCE =
FAILOVER_SET =
SUBSCRIBE_SET =
ENABLE_SUBSCRIPTION =
UNSUBSCRIBE_SET =
DDL_SCRIPT =
ADJUST_SEQ =
RESET_CONFIG =
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>ev_data1</structfield></term>
<listitem>
<para><type>text</type></para>
<para>
Champ de données contenant un argument nécessaire pour traiter
l'événement
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>ev_data2</structfield></term>
<listitem>
<para><type>text</type></para>
<para>
Champ de données contenant un argument nécessaire pour traiter
l'événement
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>ev_data3</structfield></term>
<listitem>
<para><type>text</type></para>
<para>
Champ de données contenant un argument nécessaire pour traiter
l'événement
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>ev_data4</structfield></term>
<listitem>
<para><type>text</type></para>
<para>
Champ de données contenant un argument nécessaire pour traiter
l'événement
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>ev_data5</structfield></term>
<listitem>
<para><type>text</type></para>
<para>
Champ de données contenant un argument nécessaire pour traiter
l'événement
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>ev_data6</structfield></term>
<listitem>
<para><type>text</type></para>
<para>
Champ de données contenant un argument nécessaire pour traiter
l'événement
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>ev_data7</structfield></term>
<listitem>
<para><type>text</type></para>
<para>
Champ de données contenant un argument nécessaire pour traiter
l'événement
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>ev_data8</structfield></term>
<listitem>
<para><type>text</type></para>
<para>
Champ de données contenant un argument nécessaire pour traiter
l'événement
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
</section>
<section id="table.sl-listen" xreflabel="sl_listen">
<title id="table.sl-listen-title">
Table&nbsp;: <structname>sl_listen</structname>
</title>
<para>
Indique comme les n&oelig;uds écoutent aux événements à partir d'autres
n&oelig;uds dans le réseau Slony-I.
</para>
<para>
<variablelist>
<title>Structure de <structname>sl_listen</structname></title>
<varlistentry>
<term><structfield>li_origin</structfield></term>
<listitem>
<para>
<type>integer</type>
<literal>PRIMARY KEY</literal>
<literal>REFERENCES</literal> <xref linkend="table.sl-node"/>
</para>
<para>
L'identifiant (provenant de sl_node.no_id) du n&oelig;ud sur lequel
l'écoute se fait
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>li_provider</structfield></term>
<listitem>
<para>
<type>integer</type>
<literal>PRIMARY KEY</literal>
<literal>REFERENCES</literal> <xref linkend="table.sl-path"/>
</para>
<para>
L'identifiant (provenant de sl_node.no_id) du n&oelig;ud source pour
cet événement d'écoute
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>li_receiver</structfield></term>
<listitem>
<para>
<type>integer</type>
<literal>PRIMARY KEY</literal>
<literal>REFERENCES</literal> <xref linkend="table.sl-path"/>
</para>
<para>
L'identifiant (provenant de sl_node.no_id) du n&oelig;ud cible pour
cet événement d'écoute
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
</section>
<section id="table.sl-log-1" xreflabel="sl_log_1">
<title id="table.sl-log-1-title">
Table&nbsp;: <structname>sl_log_1</structname>
</title>
<para>
Enregistre chaque modification à propager aux n&oelig;uds abonnés
</para>
<para>
<variablelist>
<title>Structure de <structname>sl_log_1</structname></title>
<varlistentry>
<term><structfield>log_origin</structfield></term>
<listitem>
<para><type>integer</type></para>
<para>
nN&oelig;ud origine d'où la modification est survenue
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>log_xid</structfield></term>
<listitem>
<para><type>xxid</type></para>
<para>
Identifiant de transaction sur le n&oelig;ud origine
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>log_tableid</structfield></term>
<listitem>
<para><type>integer</type></para>
<para>
L'identifiant table (provenant de sl_table.tab_id) que cette entrée de
journal affecte
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>log_actionseq</structfield></term>
<listitem>
<para><type>bigint</type></para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>log_cmdtype</structfield></term>
<listitem>
<para><type>character(1)</type></para>
<para>
Action de réplication à faire. U = mise à jour, I = insertion,
D = suppression
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>log_cmddata</structfield></term>
<listitem>
<para><type>text</type></para>
<para>
Les données nécessaires pour réaliser l'action du log
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
</section>
<section id="table.sl-log-2" xreflabel="sl_log_2">
<title id="table.sl-log-2-title">
Table&nbsp;: <structname>sl_log_2</structname>
</title>
<para>
Enregistre chaque modification à propager dans les n&oelig;uds abonnés
</para>
<para>
<variablelist>
<title>Structure de <structname>sl_log_2</structname></title>
<varlistentry>
<term><structfield>log_origin</structfield></term>
<listitem>
<para><type>integer</type></para>
<para>
N&oelig;ud origine d'où provient la modification
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>log_xid</structfield></term>
<listitem>
<para><type>xxid</type></para>
<para>
Identifiant de transaction sur le n&oelig;ud origine
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>log_tableid</structfield></term>
<listitem>
<para><type>integer</type></para>
<para>
L'identifiant de table (provenant de sl_table.tab_id) que cette entrée
de log affecte
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>log_actionseq</structfield></term>
<listitem>
<para><type>bigint</type></para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>log_cmdtype</structfield></term>
<listitem>
<para><type>character(1)</type></para>
<para>
Action de réplication à réaliser. U = mise à jour, I = insertion,
D = suppression
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>log_cmddata</structfield></term>
<listitem>
<para><type>text</type></para>
<para>
Les données requises pour traiter l'action du log
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
</section>
<section id="table.sl-node" xreflabel="sl_node">
<title id="table.sl-node-title">
Table&nbsp;: <structname>sl_node</structname>
</title>
<para>
Contient la liste des n&oelig;uds associés avec ce schéma.
</para>
<para>
<variablelist>
<title>Structure de <structname>sl_node</structname></title>
<varlistentry>
<term><structfield>no_id</structfield></term>
<listitem>
<para><type>integer</type> <literal>PRIMARY KEY</literal></para>
<para>
L'identifiant uinique du n&oelig;ud
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>no_active</structfield></term>
<listitem>
<para><type>boolean</type></para>
<para>
N&oelig;ud actif dans la réplication&nbsp;?
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>no_comment</structfield></term>
<listitem>
<para><type>text</type></para>
<para>
Une description humaine du n&oelig;ud
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>no_spool</structfield></term>
<listitem>
<para><type>boolean</type></para>
<para>
N&oelig;ud utilisé pour le log shipping&nbsp;?
</para>
</listitem>
</varlistentry>
</variablelist>
<itemizedlist>
<title>Tables référençant sl_listen via des contraintes de clés étrangères</title>
<listitem>
<para><xref linkend="table.sl-listen"/></para>
</listitem>
<listitem>
<para><xref linkend="table.sl-path"/></para>
</listitem>
<listitem>
<para><xref linkend="table.sl-set"/></para>
</listitem>
<listitem>
<para><xref linkend="table.sl-setsync"/></para>
</listitem>
</itemizedlist>
</para>
</section>
<section id="table.sl-nodelock" xreflabel="sl_nodelock">
<title id="table.sl-nodelock-title">
Table&nbsp;: <structname>sl_nodelock</structname>
</title>
<para>
Utilisé pour empêcher plusieurs instances slon et pour identifier les
processus à tuer dans terminateNodeConnections().
</para>
<para>
<variablelist>
<title>Structure de <structname>sl_nodelock</structname></title>
<varlistentry>
<term><structfield>nl_nodeid</structfield></term>
<listitem>
<para><type>integer</type> <literal>PRIMARY KEY</literal></para>
<para>
node_id clients
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>nl_conncnt</structfield></term>
<listitem>
<para><type>serial</type> <literal>PRIMARY KEY</literal></para>
<para>
Numéro de connexion des clients
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>nl_backendpid</structfield></term>
<listitem>
<para><type>integer</type></para>
<para>
PID du processus de la base de données, possédant ce verrou
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
</section>
<section id="table.sl-path" xreflabel="sl_path">
<title id="table.sl-path-title">
Table&nbsp;: <structname>sl_path</structname>
</title>
<para>
Contient des informations de connexions pour les chemins entre les n&oelig;uds
ainsi que le délai de synchronisation.
</para>
<para>
<variablelist>
<title>Structure de <structname>sl_path</structname></title>
<varlistentry>
<term><structfield>pa_server</structfield></term>
<listitem>
<para>
<type>integer</type>
<literal>PRIMARY KEY</literal>
<literal>REFERENCES</literal> <xref linkend="table.sl-node"/>
</para>
<para>
L'identifiant du n&oelig;ud (provenant de sl_node.no_id) de la
source des données
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>pa_client</structfield></term>
<listitem>
<para>
<type>integer</type>
<literal>PRIMARY KEY</literal>
<literal>REFERENCES</literal> <xref linkend="table.sl-node"/>
</para>
<para>
L'identifiant du n&oelig;ud (provenant de sl_node.no_id) de la cible
des données
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>pa_conninfo</structfield></term>
<listitem>
<para><type>text</type> <literal>NOT NULL</literal></para>
<para>
La chaîne de connexion PostgreSQL utilisée pour se connecter au
n&oelig;ud source.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>pa_connretry</structfield></term>
<listitem>
<para><type>integer</type></para>
<para>
Le délai de synchronisation, en secondes
</para>
</listitem>
</varlistentry>
</variablelist>
<itemizedlist>
<title>Tables référençant sl_listen via des contraintes de clés étrangères</title>
<listitem>
<para><xref linkend="table.sl-listen"/></para>
</listitem>
<listitem>
<para><xref linkend="table.sl-subscribe"/></para>
</listitem>
</itemizedlist>
</para>
</section>
<section id="table.sl-registry" xreflabel="sl_registry">
<title id="table.sl-registry-title">
Table&nbsp;: <structname>sl_registry</structname>
</title>
<para>
Enregistre différentes données d'exécution.
</para>
<para>
<variablelist>
<title>Structure de <structname>sl_registry</structname></title>
<varlistentry>
<term><structfield>reg_key</structfield></term>
<listitem>
<para><type>text</type> <literal>PRIMARY KEY</literal></para>
<para>
Clé unique de l'option d'exécution
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>reg_int4</structfield></term>
<listitem>
<para><type>integer</type></para>
<para>
Valeur de l'option si de type int4
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>reg_text</structfield></term>
<listitem>
<para><type>text</type></para>
<para>
Valeur de l'option si de type text
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>reg_timestamp</structfield></term>
<listitem>
<para><type>timestamp without time zone</type></para>
<para>
Valeur de l'option si de type timestamp
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
</section>
<section id="view.sl-seqlastvalue" xreflabel="sl_seqlastvalue">
<title id="view.sl-seqlastvalue-title">
Vue&nbsp;: <structname>sl_seqlastvalue</structname>
</title>
<para>
<variablelist>
<title>Structure de <structname>sl_seqlastvalue</structname></title>
<varlistentry>
<term><structfield>seq_id</structfield></term>
<listitem>
<para><type>integer</type></para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>seq_set</structfield></term>
<listitem>
<para><type>integer</type></para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>seq_reloid</structfield></term>
<listitem>
<para><type>oid</type></para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>seq_origin</structfield></term>
<listitem>
<para><type>integer</type></para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>seq_last_value</structfield></term>
<listitem>
<para><type>bigint</type></para>
</listitem>
</varlistentry>
</variablelist>
<figure>
<title>Définition de la vue sl_seqlastvalue</title>
<programlisting>SELECT sq.seq_id
, sq.seq_set
, sq.seq_reloid
, s.set_origin AS seq_origin
, sequencelastvalue
(
(
(quote_ident
(
(pgn.nspname)::text
) || &apos;.&apos;::text
) || quote_ident
(
(pgc.relname)::text
)
)
) AS seq_last_value
FROM sl_sequence sq
, sl_set s
, pg_class pgc
, pg_namespace pgn
WHERE (
(
(s.set_id = sq.seq_set)
AND (pgc.oid = sq.seq_reloid)
)
AND (pgn.oid = pgc.relnamespace)
);</programlisting>
</figure>
</para>
</section>
<section id="table.sl-seqlog" xreflabel="sl_seqlog">
<title id="table.sl-seqlog-title">
Table&nbsp;: <structname>sl_seqlog</structname>
</title>
<para>
Log des mises à jour de séquences.
</para>
<para>
<variablelist>
<title>Structure de <structname>sl_seqlog</structname></title>
<varlistentry>
<term><structfield>seql_seqid</structfield></term>
<listitem>
<para><type>integer</type></para>
<para>
Identifiant de la séquence
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>seql_origin</structfield></term>
<listitem>
<para><type>integer</type></para>
<para>
N&oelig;ud d'où vient la séquence
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>seql_ev_seqno</structfield></term>
<listitem>
<para><type>bigint</type></para>
<para>
Événement Slony-I avec lequel cette mise à jour de la séquence est
associée
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>seql_last_value</structfield></term>
<listitem>
<para><type>bigint</type></para>
<para>
Dernière valeur connue pour cette séquence
</para>
</listitem>
</varlistentry>
</variablelist>
<variablelist>
<title>Index sur sl_seqlog</title>
<varlistentry>
<term>sl_seqlog_idx</term>
<listitem><para>seql_origin, seql_ev_seqno, seql_seqid</para></listitem>
</varlistentry>
</variablelist>
</para>
</section>
<section id="table.sl-sequence" xreflabel="sl_sequence">
<title id="table.sl-sequence-title">
Table&nbsp;: <structname>sl_sequence</structname>
</title>
<para>
Similaire à sl_table. Chaque entrée identifie une séquence à répliquer.
</para>
<para>
<variablelist>
<title>Structure de <structname>sl_sequence</structname></title>
<varlistentry>
<term><structfield>seq_id</structfield></term>
<listitem>
<para><type>integer</type> <literal>PRIMARY KEY</literal></para>
<para>
Identifiant interne utilisé par Slony pour sa séquence de mise à jour
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>seq_reloid</structfield></term>
<listitem>
<para><type>oid</type> <literal>UNIQUE</literal> <literal>NOT NULL</literal></para>
<para>
OID de la séquence
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>seq_relname</structfield></term>
<listitem>
<para><type>name</type> <literal>NOT NULL</literal></para>
<para>
Nom de la séquence dans pg_catalog.pg_class.relname, utilisé pour être
récupéré sur un cycle sauvegarde/restauration
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>seq_nspname</structfield></term>
<listitem>
<para><type>name</type> <literal>NOT NULL</literal></para>
<para>
Nom du schéma dans pg_catalog.pg_namespace.nspname, utilisé pour être
récupéré sur un cycle sauvegarde/restauration
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>seq_set</structfield></term>
<listitem>
<para><type>integer</type> <literal>REFERENCES</literal> <xref linkend="table.sl-set"/></para>
<para>
Indique dans quel ensemble de réplication se trouve l'objet
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>seq_comment</structfield></term>
<listitem>
<para><type>text</type></para>
<para>
Un commentaire humain
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
</section>
<section id="table.sl-set" xreflabel="sl_set">
<title id="table.sl-set-title">
Table&nbsp;: <structname>sl_set</structname>
</title>
<para>
Contient la définition des ensembles de réplication.
</para>
<para>
<variablelist>
<title>Structure de <structname>sl_set</structname></title>
<varlistentry>
<term><structfield>set_id</structfield></term>
<listitem>
<para><type>integer</type> <literal>PRIMARY KEY</literal></para>
<para>
Un identifiant unique pour l'ensemble.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>set_origin</structfield></term>
<listitem>
<para><type>integer</type> <literal>REFERENCES</literal> <xref linkend="table.sl-node"/></para>
<para>
Un identifiant du n&oelig;ud source pour l'ensemble de réplication.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>set_locked</structfield></term>
<listitem>
<para><type>xxid</type></para>
<para>
Indique si l'ensemble est verrouillé.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>set_comment</structfield></term>
<listitem>
<para><type>text</type></para>
<para>
Une description humaine de l'ensemble.
</para>
</listitem>
</varlistentry>
</variablelist>
<itemizedlist>
<title>Tables référençant sl_sequence via des contraintes de clés étrangères</title>
<listitem>
<para><xref linkend="table.sl-sequence"/></para>
</listitem>
<listitem>
<para><xref linkend="table.sl-setsync"/></para>
</listitem>
<listitem>
<para><xref linkend="table.sl-subscribe"/></para>
</listitem>
<listitem>
<para><xref linkend="table.sl-table"/></para>
</listitem>
</itemizedlist>
</para>
</section>
<section id="table.sl-setsync" xreflabel="sl_setsync">
<title id="table.sl-setsync-title">
Table&nbsp;: <structname>sl_setsync</structname>
</title>
<para>
Informations de SYNC
</para>
<para>
<variablelist>
<title>Structure de <structname>sl_setsync</structname></title>
<varlistentry>
<term><structfield>ssy_setid</structfield></term>
<listitem>
<para>
<type>integer</type>
<literal>PRIMARY KEY</literal>
<literal>REFERENCES</literal> <xref linkend="table.sl-set"/>
</para>
<para>
Identifiant de l'ensemble de réplication
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>ssy_origin</structfield></term>
<listitem>
<para><type>integer</type> <literal>REFERENCES</literal> <xref linkend="table.sl-node"/></para>
<para>
Identifiant du n&oelig;ud
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>ssy_seqno</structfield></term>
<listitem>
<para><type>bigint</type></para>
<para>
Numéro de séquence Slony-I
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>ssy_minxid</structfield></term>
<listitem>
<para><type>xxid</type></para>
<para>
Identifiant de transaction le plus ancient dans le système affecté
par SYNC
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>ssy_maxxid</structfield></term>
<listitem>
<para><type>xxid</type></para>
<para>
Dernier identifiant de transaction dans le système fournisseur affecté
par SYNC
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>ssy_xip</structfield></term>
<listitem>
<para><type>text</type></para>
<para>
Contient la liste des identifiants de transactions en progression
au moment du SYNC
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>ssy_action_list</structfield></term>
<listitem>
<para><type>text</type></para>
<para>
Liste d'action utilisée lors du traitement de l'abonnement. Au moment
où un abonné copie des données à partir de l'origine, il voit toutes
les tables dans un état entre deux événements SYNC. Du coup, cette
liste doit contenir tous les identifiants de transactions visibles
à ce moment, donc les opérations ont déjà été incluses dans les
données copiées au moment où la copie initiale des données est faite.
Du coup, ces actions peuvent être filtrées du premier SYNC réalisé
après l'abonnement.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
</section>
<section id="table.sl-subscribe" xreflabel="sl_subscribe">
<title id="table.sl-subscribe-title">
Table&nbsp;: <structname>sl_subscribe</structname>
</title>
<para>
Contient une liste des abonnements sur les ensembles.
</para>
<para>
<variablelist>
<title>Structure de <structname>sl_subscribe</structname></title>
<varlistentry>
<term><structfield>sub_set</structfield></term>
<listitem>
<para>
<type>integer</type>
<literal>PRIMARY KEY</literal>
<literal>REFERENCES</literal> <xref linkend="table.sl-set"/>
</para>
<para>
Identifiant (provenant de sl_set) de l'ensemble
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>sub_provider</structfield></term>
<listitem>
<para><type>integer</type> <literal>REFERENCES</literal> <xref linkend="table.sl-path"/></para>
<para>
Identifiant (provenant de sl_node) du n&oelig;ud fournissant les données
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>sub_receiver</structfield></term>
<listitem>
<para>
<type>integer</type>
<literal>PRIMARY KEY</literal>
<literal>REFERENCES</literal> <xref linkend="table.sl-path"/>
</para>
<para>
Identifiant (provenant de sl_node) du n&oelig;ud recevant les données
à partir du fournisseur
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>sub_forward</structfield></term>
<listitem>
<para><type>boolean</type></para>
<para>
Le fournisseur doit-il conserver les données dans sl_log_1/sl_log_2
pour lui permettre de devenir un fournisseur vers d'autres
n&oelig;uds&nbsp;?
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>sub_active</structfield></term>
<listitem>
<para><type>boolean</type></para>
<para>
L'abonnement a-t-il été activé&nbsp;? ceci n'est pas configuré sur
l'abonné jusqu'à APRÈS la réception des données de COPY du fournisseur
à l'abonné.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
</section>
<section id="table.sl-table" xreflabel="sl_table">
<title id="table.sl-table-title">
Table&nbsp;: <structname>sl_table</structname>
</title>
<para>
Contient des informations sur les tables à répliquer.
</para>
<para>
<variablelist>
<title>Structure de <structname>sl_table</structname></title>
<varlistentry>
<term><structfield>tab_id</structfield></term>
<listitem>
<para><type>integer</type> <literal>PRIMARY KEY</literal></para>
<para>
Clé unique que Slony-I utilise pour identifier la table
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>tab_reloid</structfield></term>
<listitem>
<para><type>oid</type> <literal>UNIQUE</literal> <literal>NOT NULL</literal></para>
<para>
OID de la table (pg_catalog.pg_class.oid)
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>tab_relname</structfield></term>
<listitem>
<para><type>name</type> <literal>NOT NULL</literal></para>
<para>
Nom de la table dans pg_catalog.pg_class.relname, utilisé pour être
récupéré sur un cycle sauvegarde/restauration
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>tab_nspname</structfield></term>
<listitem>
<para><type>name</type><literal>NOT NULL</literal></para>
<para>
Nom du schéma dans pg_catalog.pg_namespace.nspname, utilisé pour être
récupéré sur un cycle sauvegarde/restauration
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>tab_set</structfield></term>
<listitem>
<para><type>integer</type> <literal>REFERENCES</literal> <xref linkend="table.sl-set"/></para>
<para>
Identifiant de l'ensemble de réplication
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>tab_idxname</structfield></term>
<listitem>
<para><type>name</type> <literal>NOT NULL</literal></para>
<para>
Nom de l'index primaire de la table
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>tab_altered</structfield></term>
<listitem>
<para><type>boolean</type> <literal>NOT NULL</literal></para>
<para>
La table a-t-elle été modifiée pour la réplication&nbsp;?
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>tab_comment</structfield></term>
<listitem>
<para><type>text</type></para>
<para>
Description humaine de la table
</para>
</listitem>
</varlistentry>
</variablelist>
<itemizedlist>
<title>Tables référençant sl_trigger via des contraintes de clés étrangères</title>
<listitem>
<para><xref linkend="table.sl-trigger"/></para>
</listitem>
</itemizedlist>
</para>
</section>
<section id="table.sl-trigger" xreflabel="sl_trigger">
<title id="table.sl-trigger-title">
Table&nbsp;: <structname>sl_trigger</structname>
</title>
<para>
Contient des informations sur les triggers des tables gérées par Slony-I.
</para>
<para>
<variablelist>
<title>Structure de <structname>sl_trigger</structname></title>
<varlistentry>
<term><structfield>trig_tabid</structfield></term>
<listitem>
<para>
<type>integer</type><literal>PRIMARY KEY</literal>
<literal>REFERENCES</literal> <xref linkend="table.sl-table"/>
</para>
<para>
Identifiant Slony-I de la table où le trigger est activé
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><structfield>trig_tgname</structfield></term>
<listitem>
<para><type>name</type> <literal>PRIMARY KEY</literal></para>
<para>
Indique le nom d'un trigger
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
</section>
<!-- Function add_empty_table_to_replication( integer, integer, text, text, text, text ) -->
<section id="function.add-empty-table-to-replication-integer-integer-text-text-text-text"
xreflabel="schemadocadd_empty_table_to_replication( integer, integer, text, text, text, text )">
<title id="function.add-empty-table-to-replication-integer-integer-text-text-text-text-title">
add_empty_table_to_replication( integer, integer, text, text, text, text )
</title>
<titleabbrev id="function.add-empty-table-to-replication-integer-integer-text-text-text-text-titleabbrev">
add_empty_table_to_replication( integer, integer, text, text, text, text )
</titleabbrev>
<para>
<segmentedlist>
<title>Propriétés de la fonction</title>
<?dbhtml list-presentation="list"?>
<segtitle>Langage</segtitle>
<segtitle>Type du code retour</segtitle>
<seglistitem>
<seg>PLPGSQL</seg>
<seg>bigint</seg>
</seglistitem>
</segmentedlist>
Vérifie qu'une table est vide et l'ajoute à la réplication. tab_idxname est
optionnel. S'il vaut NULL, alors la clé primaire est utilisée.
<programlisting>declare
p_set_id alias for $1;
p_tab_id alias for $2;
p_nspname alias for $3;
p_tabname alias for $4;
p_idxname alias for $5;
p_comment alias for $6;
prec record;
v_origin int4;
v_isorigin boolean;
v_fqname text;
v_query text;
v_rows integer;
v_idxname text;
begin
-- Need to validate that the set exists; the set will tell us if this is the origin
select set_origin into v_origin from sl_set where set_id = p_set_id;
if not found then
raise exception &#39;add_empty_table_to_replication: set % not found!&#39;, p_set_id;
end if;
-- Need to be aware of whether or not this node is origin for the set
v_isorigin := ( v_origin = getLocalNodeId(&#39;_schemadoc&#39;) );
v_fqname := &#39;&quot;&#39; || p_nspname || &#39;&quot;.&quot;&#39; || p_tabname || &#39;&quot;&#39;;
-- Take out a lock on the table
v_query := &#39;lock &#39; || v_fqname || &#39;;&#39;;
execute v_query;
if v_isorigin then
-- On the origin, verify that the table is empty, failing if it has any tuples
v_query := &#39;select 1 as tuple from &#39; || v_fqname || &#39; limit 1;&#39;;
execute v_query into prec;
GET DIAGNOSTICS v_rows = ROW_COUNT;
if v_rows = 0 then
raise notice &#39;add_empty_table_to_replication: table % empty on origin - OK&#39;, v_fqname;
else
raise exception &#39;add_empty_table_to_replication: table % contained tuples on origin node %&#39;, v_fqname, v_origin;
end if;
else
-- On other nodes, TRUNCATE the table
v_query := &#39;truncate &#39; || v_fqname || &#39;;&#39;;
execute v_query;
end if;
-- If p_idxname is NULL, then look up the PK index, and RAISE EXCEPTION if one does not exist
if p_idxname is NULL then
select c2.relname into prec from pg_catalog.pg_index i, pg_catalog.pg_class c1, pg_catalog.pg_class c2, pg_catalog.pg_namespace n where i.indrelid = c1.oid and i.indexrelid = c2.oid and c1.relname = p_tabname and i.indisprimary and n.nspname = p_nspname and n.oid = c1.relnamespace;
if not found then
raise exception &#39;add_empty_table_to_replication: table % has no primary key and no candidate specified!&#39;, v_fqname;
else
v_idxname := prec.relname;
end if;
else
v_idxname := p_idxname;
end if;
perform setAddTable_int(p_set_id, p_tab_id, v_fqname, v_idxname, p_comment);
return alterTableRestore(p_tab_id);
end</programlisting>
</para>
</section>
<!-- Function add_missing_table_field( text, text, text, text ) -->
<section id="function.add-missing-table-field-text-text-text-text"
xreflabel="schemadocadd_missing_table_field( text, text, text, text )">
<title id="function.add-missing-table-field-text-text-text-text-title">
add_missing_table_field( text, text, text, text )
</title>
<titleabbrev id="function.add-missing-table-field-text-text-text-text-titleabbrev">
add_missing_table_field( text, text, text, text )
</titleabbrev>
<para>
<segmentedlist>
<title>Propriétés de la fonction</title>
<?dbhtml list-presentation="list"?>
<segtitle>Langage</segtitle>
<segtitle>Type du code retour</segtitle>
<seglistitem>
<seg>PLPGSQL</seg>
<seg>boolean</seg>
</seglistitem>
</segmentedlist>
Ajoute une colonne du type indiqué dans une table si cette colonne est
manquante
<programlisting>DECLARE
p_namespace alias for $1;
p_table alias for $2;
p_field alias for $3;
p_type alias for $4;
v_row record;
v_query text;
BEGIN
select 1 into v_row from pg_namespace n, pg_class c, pg_attribute a
where slon_quote_brute(n.nspname) = p_namespace and
c.relnamespace = n.oid and
slon_quote_brute(c.relname) = p_table and
a.attrelid = c.oid and
slon_quote_brute(a.attname) = p_field;
if not found then
raise notice &#39;Upgrade table %.% - add field %&#39;, p_namespace, p_table, p_field;
v_query := &#39;alter table &#39; || p_namespace || &#39;.&#39; || p_table || &#39; add column &#39;;
v_query := v_query || p_field || &#39; &#39; || p_type || &#39;;&#39;;
execute v_query;
return &#39;t&#39;;
else
return &#39;f&#39;;
end if;
END;</programlisting>
</para>
</section>
<!-- Function addpartiallogindices( ) -->
<section id="function.addpartiallogindices" xreflabel="schemadocaddpartiallogindices( )">
<title id="function.addpartiallogindices-title">
addpartiallogindices( )
</title>
<titleabbrev id="function.addpartiallogindices-titleabbrev">
addpartiallogindices( )
</titleabbrev>
<para>
<segmentedlist>
<title>Propriétés de la fonction</title>
<?dbhtml list-presentation="list"?>
<segtitle>Langage</segtitle>
<segtitle>Type du code retour</segtitle>
<seglistitem>
<seg>PLPGSQL</seg>
<seg>integer</seg>
</seglistitem>
</segmentedlist>
Ajoute des index partiels, si possible, dans les tables sl_log_? inutilisées
pour tous les n&oelig;uds origines, et supprime tous ceux qui ne sont plus
nécessaires.
Cette fonction est exécuté à chaque fois que les origines d'ensemble sont
utilisées (FAILOVER, STORE SET, MOVE SET, DROP SET), ainsi qu'à chaque fois
que le système bascule entre sl_log_1 et sl_log_2.
<programlisting>DECLARE
v_current_status int4;
v_log int4;
v_dummy record;
idef text;
v_count int4;
BEGIN
v_count := 0;
select last_value into v_current_status from sl_log_status;
-- If status is 2 or 3 --&gt; in process of cleanup --&gt; unsafe to create indices
if v_current_status in (2, 3) then
return 0;
end if;
if v_current_status = 0 then -- Which log should get indices?
v_log := 2;
else
v_log := 1;
end if;
-- Add missing indices...
for v_dummy in select distinct set_origin from sl_set
where not exists
(select * from pg_catalog.pg_indexes where schemaname = &#39;schemadoc&#39;
and tablename = &#39;sl_log_&#39; || v_log and
indexname = &#39;PartInd_schemadoc_sl_log_&#39; || v_log || &#39;-node-&#39; || set_origin) loop
idef := &#39;create index &quot;PartInd_schemadoc_sl_log_&#39; || v_log || &#39;-node-&#39; || v_dummy.set_origin ||
&#39;&quot; on sl_log_&#39; || v_log || &#39; USING btree(log_xid xxid_ops) where (log_origin = &#39; || v_dummy.set_origin || &#39;);&#39;;
execute idef;
v_count := v_count + 1;
end loop;
-- Remove unneeded indices...
for v_dummy in select indexname from pg_catalog.pg_indexes i where i.schemaname = &#39;@NAMESPACE&#39;
and i.tablename = &#39;sl_log_&#39; || v_log and
not exists (select 1 from sl_set where
i.indexname = &#39;PartInd_schemadoc_sl_log_&#39; || v_log || &#39;-node-&#39; || set_origin)
loop
idef := &#39;drop index &quot;schemadoc&quot;.&quot;&#39; || v_dummy.indexname || &#39;&quot;;&#39;;
execute idef;
v_count := v_count - 1;
end loop;
return v_count;
END</programlisting>
</para>
</section>
<!-- Function altertableforreplication( integer ) -->
<section id="function.altertableforreplication-integer"
xreflabel="schemadocaltertableforreplication( integer )">
<title id="function.altertableforreplication-integer-title">
altertableforreplication( integer )
</title>
<titleabbrev id="function.altertableforreplication-integer-titleabbrev">
altertableforreplication( integer )
</titleabbrev>
<para>
<segmentedlist>
<title>Propriétés de la fonction</title>
<?dbhtml list-presentation="list"?>
<segtitle>Langage</segtitle>
<segtitle>Type du code retour</segtitle>
<seglistitem>
<seg>PLPGSQL</seg>
<seg>integer</seg>
</seglistitem>
</segmentedlist>
Configure une table pour la réplication. Sur l'origine, ceci implique
d'ajouter le trigger &quot;logTrigger()&quot; sur la table.
Sur un n&oelig;ud abonné, ceci implique de désactiver les triggers et les
règles, et d'ajouter le trigger qui interdit l'accès aux tables
répliquées.
<programlisting>declare
p_tab_id alias for $1;
v_no_id int4;
v_tab_row record;
v_tab_fqname text;
v_tab_attkind text;
v_n int4;
v_trec record;
v_tgbad boolean;
begin
-- ----
-- Grab the central configuration lock
-- ----
lock table sl_config_lock;
-- ----
-- Get our local node ID
-- ----
v_no_id := getLocalNodeId(&#39;_schemadoc&#39;);
-- ----
-- Get the sl_table row and the current origin of the table.
-- Verify that the table currently is NOT in altered state.
-- ----
select T.tab_reloid, T.tab_set, T.tab_idxname, T.tab_altered,
S.set_origin, PGX.indexrelid,
slon_quote_brute(PGN.nspname) || &#39;.&#39; ||
slon_quote_brute(PGC.relname) as tab_fqname
into v_tab_row
from sl_table T, sl_set S,
&quot;pg_catalog&quot;.pg_class PGC, &quot;pg_catalog&quot;.pg_namespace PGN,
&quot;pg_catalog&quot;.pg_index PGX, &quot;pg_catalog&quot;.pg_class PGXC
where T.tab_id = p_tab_id
and T.tab_set = S.set_id
and T.tab_reloid = PGC.oid
and PGC.relnamespace = PGN.oid
and PGX.indrelid = T.tab_reloid
and PGX.indexrelid = PGXC.oid
and PGXC.relname = T.tab_idxname
for update;
if not found then
raise exception &#39;Slony-I: alterTableForReplication(): Table with id % not found&#39;, p_tab_id;
end if;
v_tab_fqname = v_tab_row.tab_fqname;
if v_tab_row.tab_altered then
raise exception &#39;Slony-I: alterTableForReplication(): Table % is already in altered state&#39;,
v_tab_fqname;
end if;
v_tab_attkind := determineAttKindUnique(v_tab_row.tab_fqname,
v_tab_row.tab_idxname);
execute &#39;lock table &#39; || v_tab_fqname || &#39; in access exclusive mode&#39;;
-- ----
-- Procedures are different on origin and subscriber
-- ----
if v_no_id = v_tab_row.set_origin then
-- ----
-- On the Origin we add the log trigger to the table and done
-- ----
execute &#39;create trigger &quot;_schemadoc_logtrigger_&#39; ||
p_tab_id || &#39;&quot; after insert or update or delete on &#39; ||
v_tab_fqname || &#39; for each row execute procedure
logTrigger (&#39;&#39;_schemadoc&#39;&#39;, &#39;&#39;&#39; ||
p_tab_id || &#39;&#39;&#39;, &#39;&#39;&#39; ||
v_tab_attkind || &#39;&#39;&#39;);&#39;;
else
-- ----
-- On the subscriber the thing is a bit more difficult. We want
-- to disable all user- and foreign key triggers and rules.
-- ----
-- ----
-- Check to see if there are any trigger conflicts...
-- ----
v_tgbad := &#39;false&#39;;
for v_trec in
select pc.relname, tg1.tgname from
&quot;pg_catalog&quot;.pg_trigger tg1,
&quot;pg_catalog&quot;.pg_trigger tg2,
&quot;pg_catalog&quot;.pg_class pc,
&quot;pg_catalog&quot;.pg_index pi,
sl_table tab
where
tg1.tgname = tg2.tgname and -- Trigger names match
tg1.tgrelid = tab.tab_reloid and -- trigger 1 is on the table
pi.indexrelid = tg2.tgrelid and -- trigger 2 is on the index
pi.indrelid = tab.tab_reloid and -- indexes table is this table
pc.oid = tab.tab_reloid
loop
raise notice &#39;Slony-I: alterTableForReplication(): multiple instances of trigger % on table %&#39;,
v_trec.tgname, v_trec.relname;
v_tgbad := &#39;true&#39;;
end loop;
if v_tgbad then
raise exception &#39;Slony-I: Unable to disable triggers&#39;;
end if;
-- ----
-- Disable all existing triggers
-- ----
update &quot;pg_catalog&quot;.pg_trigger
set tgrelid = v_tab_row.indexrelid
where tgrelid = v_tab_row.tab_reloid
and not exists (
select true from sl_table TAB,
sl_trigger TRIG
where TAB.tab_reloid = tgrelid
and TAB.tab_id = TRIG.trig_tabid
and TRIG.trig_tgname = tgname
);
get diagnostics v_n = row_count;
if v_n &gt; 0 then
update &quot;pg_catalog&quot;.pg_class
set reltriggers = reltriggers - v_n
where oid = v_tab_row.tab_reloid;
end if;
-- ----
-- Disable all existing rules
-- ----
update &quot;pg_catalog&quot;.pg_rewrite
set ev_class = v_tab_row.indexrelid
where ev_class = v_tab_row.tab_reloid;
get diagnostics v_n = row_count;
if v_n &gt; 0 then
update &quot;pg_catalog&quot;.pg_class
set relhasrules = false
where oid = v_tab_row.tab_reloid;
end if;
-- ----
-- Add the trigger that denies write access to replicated tables
-- ----
execute &#39;create trigger &quot;_schemadoc_denyaccess_&#39; ||
p_tab_id || &#39;&quot; before insert or update or delete on &#39; ||
v_tab_fqname || &#39; for each row execute procedure
denyAccess (&#39;&#39;_schemadoc&#39;&#39;);&#39;;
end if;
-- ----
-- Mark the table altered in our configuration
-- ----
update sl_table
set tab_altered = true where tab_id = p_tab_id;
return p_tab_id;
end;</programlisting>
</para>
</section>
<!-- Function altertablerestore( integer ) -->
<section id="function.altertablerestore-integer"
xreflabel="schemadocaltertablerestore( integer )">
<title id="function.altertablerestore-integer-title">
altertablerestore( integer )
</title>
<titleabbrev id="function.altertablerestore-integer-titleabbrev">
altertablerestore( integer )
</titleabbrev>
<para>
<segmentedlist>
<title>Propriétés de la fonction</title>
<?dbhtml list-presentation="list"?>
<segtitle>Langage</segtitle>
<segtitle>Type du code retour</segtitle>
<seglistitem>
<seg>PLPGSQL</seg>
<seg>integer</seg>
</seglistitem>
</segmentedlist>
Restaure la table d'identifiant table tab_id. Autrement dit, l'enlève de la
réplication.
Sur l'origine, ceci implique la suppression du trigger &quot;logtrigger&quot;.
Sur les n&oelig;uds abonnés, ceci implique la suppression du trigger
&quot;denyaccess&quot;, et restaure les triggers et règles utilisateurs.
<programlisting>declare
p_tab_id alias for $1;
v_no_id int4;
v_tab_row record;
v_tab_fqname text;
v_n int4;
begin
-- ----
-- Grab the central configuration lock
-- ----
lock table sl_config_lock;
-- ----
-- Get our local node ID
-- ----
v_no_id := getLocalNodeId(&#39;_schemadoc&#39;);
-- ----
-- Get the sl_table row and the current tables origin. Check
-- that the table currently IS in altered state.
-- ----
select T.tab_reloid, T.tab_set, T.tab_altered,
S.set_origin, PGX.indexrelid,
slon_quote_brute(PGN.nspname) || &#39;.&#39; ||
slon_quote_brute(PGC.relname) as tab_fqname
into v_tab_row
from sl_table T, sl_set S,
&quot;pg_catalog&quot;.pg_class PGC, &quot;pg_catalog&quot;.pg_namespace PGN,
&quot;pg_catalog&quot;.pg_index PGX, &quot;pg_catalog&quot;.pg_class PGXC
where T.tab_id = p_tab_id
and T.tab_set = S.set_id
and T.tab_reloid = PGC.oid
and PGC.relnamespace = PGN.oid
and PGX.indrelid = T.tab_reloid
and PGX.indexrelid = PGXC.oid
and PGXC.relname = T.tab_idxname
for update;
if not found then
raise exception &#39;Slony-I: alterTableRestore(): Table with id % not found&#39;, p_tab_id;
end if;
v_tab_fqname = v_tab_row.tab_fqname;
if not v_tab_row.tab_altered then
raise exception &#39;Slony-I: alterTableRestore(): Table % is not in altered state&#39;,
v_tab_fqname;
end if;
execute &#39;lock table &#39; || v_tab_fqname || &#39; in access exclusive mode&#39;;
-- ----
-- Procedures are different on origin and subscriber
-- ----
if v_no_id = v_tab_row.set_origin then
-- ----
-- On the Origin we just drop the trigger we originally added
-- ----
execute &#39;drop trigger &quot;_schemadoc_logtrigger_&#39; ||
p_tab_id || &#39;&quot; on &#39; || v_tab_fqname;
else
-- ----
-- On the subscriber drop the denyAccess trigger
-- ----
execute &#39;drop trigger &quot;_schemadoc_denyaccess_&#39; ||
p_tab_id || &#39;&quot; on &#39; || v_tab_fqname;
-- ----
-- Restore all original triggers
-- ----
update &quot;pg_catalog&quot;.pg_trigger
set tgrelid = v_tab_row.tab_reloid
where tgrelid = v_tab_row.indexrelid;
get diagnostics v_n = row_count;
if v_n &gt; 0 then
update &quot;pg_catalog&quot;.pg_class
set reltriggers = reltriggers + v_n
where oid = v_tab_row.tab_reloid;
end if;
-- ----
-- Restore all original rewrite rules
-- ----
update &quot;pg_catalog&quot;.pg_rewrite
set ev_class = v_tab_row.tab_reloid
where ev_class = v_tab_row.indexrelid;
get diagnostics v_n = row_count;
if v_n &gt; 0 then
update &quot;pg_catalog&quot;.pg_class
set relhasrules = true
where oid = v_tab_row.tab_reloid;
end if;
end if;
-- ----
-- Mark the table not altered in our configuration
-- ----
update sl_table
set tab_altered = false where tab_id = p_tab_id;
return p_tab_id;
end;</programlisting>
</para>
</section>
<!-- Function checkmoduleversion( ) -->
<section id="function.checkmoduleversion"
xreflabel="schemadoccheckmoduleversion( )">
<title id="function.checkmoduleversion-title">
checkmoduleversion( )
</title>
<titleabbrev id="function.checkmoduleversion-titleabbrev">
checkmoduleversion( )
</titleabbrev>
<para>
<segmentedlist>
<title>Propriétés de la fonction</title>
<?dbhtml list-presentation="list"?>
<segtitle>Langage</segtitle>
<segtitle>Type du code retour</segtitle>
<seglistitem>
<seg>PLPGSQL</seg>
<seg>text</seg>
</seglistitem>
</segmentedlist>
Fonction de test en ligne qui vérifie que la requête slonik pour STORE
NODE/INIT CLUSTER est bien en cours d'exécution avec un ensemble de
schémas/fonctions.
<programlisting>declare
moduleversion text;
begin
select into moduleversion getModuleVersion();
if moduleversion &lt;&gt; &#39;@MODULEVERSION@&#39; then
raise exception &#39;Slonik version: @MODULEVERSION@ != Slony-I version in PG build %&#39;,
moduleversion;
end if;
return null;
end;</programlisting>
</para>
</section>
<!-- Function cleanupevent( ) -->
<section id="function.cleanupevent"
xreflabel="schemadoccleanupevent( )">
<title id="function.cleanupevent-title">
cleanupevent( )
</title>
<titleabbrev id="function.cleanupevent-titleabbrev">
cleanupevent( )
</titleabbrev>
<para>
<segmentedlist>
<title>Propriétés de la fonction</title>
<?dbhtml list-presentation="list"?>
<segtitle>Langage</segtitle>
<segtitle>Type du code retour</segtitle>
<seglistitem>
<seg>PLPGSQL</seg>
<seg>integer</seg>
</seglistitem>
</segmentedlist>
Nettoie les anciennes données de sl_confirm, sl_event. Supprime tout sauf la
dernière ligne par (origine, abonné), puis supprime tous les événements qui
sont confirmés par tous les n&oelig;uds du clusyer jusqu'au dernier SYNC.
<programlisting>declare
v_max_row record;
v_min_row record;
v_max_sync int8;
begin
-- ----
-- First remove all but the oldest confirm row per origin,receiver pair
-- ----
delete from sl_confirm
where con_origin not in (select no_id from sl_node);
delete from sl_confirm
where con_received not in (select no_id from sl_node);
-- ----
-- Next remove all but the oldest confirm row per origin,receiver pair.
-- Ignore confirmations that are younger than 10 minutes. We currently
-- have an not confirmed suspicion that a possibly lost transaction due
-- to a server crash might have been visible to another session, and
-- that this led to log data that is needed again got removed.
-- ----
for v_max_row in select con_origin, con_received, max(con_seqno) as con_seqno
from sl_confirm
where con_timestamp &lt; (CURRENT_TIMESTAMP - &#39;10 min&#39;::interval)
group by con_origin, con_received
loop
delete from sl_confirm
where con_origin = v_max_row.con_origin
and con_received = v_max_row.con_received
and con_seqno &lt; v_max_row.con_seqno;
end loop;
-- ----
-- Then remove all events that are confirmed by all nodes in the
-- whole cluster up to the last SYNC
-- ----
for v_min_row in select con_origin, min(con_seqno) as con_seqno
from sl_confirm
group by con_origin
loop
select coalesce(max(ev_seqno), 0) into v_max_sync
from sl_event
where ev_origin = v_min_row.con_origin
and ev_seqno &lt;= v_min_row.con_seqno
and ev_type = &#39;SYNC&#39;;
if v_max_sync &gt; 0 then
delete from sl_event
where ev_origin = v_min_row.con_origin
and ev_seqno &lt; v_max_sync;
end if;
end loop;
-- ----
-- If cluster has only one node, then remove all events up to
-- the last SYNC - Bug #1538
-- http://gborg.postgresql.org/project/slony1/bugs/bugupdate.php?1538
-- ----
select * into v_min_row from sl_node where
no_id &lt;&gt; getLocalNodeId(&#39;_schemadoc&#39;) limit 1;
if not found then
select ev_origin, ev_seqno into v_min_row from sl_event
where ev_origin = getLocalNodeId(&#39;_schemadoc&#39;)
order by ev_origin desc, ev_seqno desc limit 1;
raise notice &#39;Slony-I: cleanupEvent(): Single node - deleting events &lt; %&#39;, v_min_row.ev_seqno;
delete from sl_event
where
ev_origin = v_min_row.ev_origin and
ev_seqno &lt; v_min_row.ev_seqno;
end if;
-- ----
-- Also remove stale entries from the nodelock table.
-- ----
perform cleanupNodelock();
return 0;
end;</programlisting>
</para>
</section>
<!-- Function cleanupnodelock( ) -->
<section id="function.cleanupnodelock"
xreflabel="schemadoccleanupnodelock( )">
<title id="function.cleanupnodelock-title">
cleanupnodelock( )
</title>
<titleabbrev id="function.cleanupnodelock-titleabbrev">
cleanupnodelock( )
</titleabbrev>
<para>
<segmentedlist>
<title>Propriétés de la fonction</title>
<?dbhtml list-presentation="list"?>
<segtitle>Langage</segtitle>
<segtitle>Type du retour</segtitle>
<seglistitem>
<seg>PLPGSQL</seg>
<seg>integer</seg>
</seglistitem>
</segmentedlist>
Nettoie les entrées qui restent lors du redémarrage de slon
<programlisting>declare
v_row record;
begin
for v_row in select nl_nodeid, nl_conncnt, nl_backendpid
from sl_nodelock
for update
loop
if killBackend(v_row.nl_backendpid, &#39;NULL&#39;) &lt; 0 then
raise notice &#39;Slony-I: cleanup stale sl_nodelock entry for pid=%&#39;,
v_row.nl_backendpid;
delete from sl_nodelock where
nl_nodeid = v_row.nl_nodeid and
nl_conncnt = v_row.nl_conncnt;
end if;
end loop;
return 0;
end;</programlisting>
</para>
</section>
<!-- Function copyfields( integer ) -->
<section id="function.copyfields-integer"
xreflabel="schemadoccopyfields( integer )">
<title id="function.copyfields-integer-title">
copyfields( integer )
</title>
<titleabbrev id="function.copyfields-integer-titleabbrev">
copyfields( integer )
</titleabbrev>
<para>
<segmentedlist>
<title>Propriétés de la fonction</title>
<?dbhtml list-presentation="list"?>
<segtitle>Langage</segtitle>
<segtitle>Type du code retour</segtitle>
<seglistitem>
<seg>PLPGSQL</seg>
<seg>text</seg>
</seglistitem>
</segmentedlist>
Renvoie une chaîne consistant à ce qui doit être ajoutée à une instruction
COPY pour spécifier les champs pour le tab_id.
Dans les versions ultérieurs à PostgreSQL 7.3, cela ressemble à (field1,
field2,...fieldn)
<programlisting>declare
result text;
prefix text;
prec record;
begin
result := &#39;&#39;;
prefix := &#39;(&#39;; -- Initially, prefix is the opening paren
for prec in select slon_quote_input(a.attname) as column from sl_table t, pg_catalog.pg_attribute a where t.tab_id = $1 and t.tab_reloid = a.attrelid and a.attnum &gt; 0 and a.attisdropped = false order by attnum
loop
result := result || prefix || prec.column;
prefix := &#39;,&#39;; -- Subsequently, prepend columns with commas
end loop;
result := result || &#39;)&#39;;
return result;
end;</programlisting>
</para>
</section>
<!-- Function createevent( name, text ) -->
<section id="function.createevent-name-text"
xreflabel="schemadoccreateevent( name, text )">
<title id="function.createevent-name-text-title">
createevent( name, text )
</title>
<titleabbrev id="function.createevent-name-text-titleabbrev">
createevent( name, text )
</titleabbrev>
<para>
<segmentedlist>
<title>Propriétés de la fonction</title>
<?dbhtml list-presentation="list"?>
<segtitle>Langage</segtitle>
<segtitle>Type du code retour</segtitle>
<seglistitem>
<seg>C</seg>
<seg>bigint</seg>
</seglistitem>
</segmentedlist>
Crée une entrée dans sl_event.
<programlisting>_Slony_I_createEvent</programlisting>
</para>
</section>
<!-- Function createevent( name, text, text ) -->
<section id="function.createevent-name-text-text"
xreflabel="schemadoccreateevent( name, text, text )">
<title id="function.createevent-name-text-text-title">
createevent( name, text, text )
</title>
<titleabbrev id="function.createevent-name-text-text-titleabbrev">
createevent( name, text, text )
</titleabbrev>
<para>
<segmentedlist>
<title>Propriétés de la fonction</title>
<?dbhtml list-presentation="list"?>
<segtitle>Langage</segtitle>
<segtitle>Type du code retour</segtitle>
<seglistitem>
<seg>C</seg>
<seg>bigint</seg>
</seglistitem>
</segmentedlist>
Crée une entrée dans sl_event.
<programlisting>_Slony_I_createEvent</programlisting>
</para>
</section>
<!-- Function createevent( name, text, text, text ) -->
<section id="function.createevent-name-text-text-text"
xreflabel="schemadoccreateevent( name, text, text, text )">
<title id="function.createevent-name-text-text-text-title">
createevent( name, text, text, text )
</title>
<titleabbrev id="function.createevent-name-text-text-text-titleabbrev">
createevent( name, text, text, text )
</titleabbrev>
<para>
<segmentedlist>
<title>Propriétés de la fonction</title>
<?dbhtml list-presentation="list"?>
<segtitle>Langage</segtitle>
<segtitle>Type du code retour</segtitle>
<seglistitem>
<seg>C</seg>
<seg>bigint</seg>
</seglistitem>
</segmentedlist>
Crée une entrée dans sl_event.
<programlisting>_Slony_I_createEvent</programlisting>
</para>
</section>
<!-- Function createevent( name, text, text, text, text ) -->
<section id="function.createevent-name-text-text-text-text"
xreflabel="schemadoccreateevent( name, text, text, text, text )">
<title id="function.createevent-name-text-text-text-text-title">
createevent( name, text, text, text, text )
</title>
<titleabbrev id="function.createevent-name-text-text-text-text-titleabbrev">
createevent( name, text, text, text, text )
</titleabbrev>
<para>
<segmentedlist>
<title>Propriétés de la fonction</title>
<?dbhtml list-presentation="list"?>
<segtitle>Langage</segtitle>
<segtitle>Type du code retour</segtitle>
<seglistitem>
<seg>C</seg>
<seg>bigint</seg>
</seglistitem>
</segmentedlist>
Crée une entrée dans sl_event.
<programlisting>_Slony_I_createEvent</programlisting>
</para>
</section>
<!-- Function createevent( name, text, text, text, text, text ) -->
<section id="function.createevent-name-text-text-text-text-text"
xreflabel="schemadoccreateevent( name, text, text, text, text, text )">
<title id="function.createevent-name-text-text-text-text-text-title">
createevent( name, text, text, text, text, text )
</title>
<titleabbrev id="function.createevent-name-text-text-text-text-text-titleabbrev">
createevent( name, text, text, text, text, text )
</titleabbrev>
<para>
<segmentedlist>
<title>Propriétés de la fonction</title>
<?dbhtml list-presentation="list"?>
<segtitle>Langage</segtitle>
<segtitle>Type du code retour</segtitle>
<seglistitem>
<seg>C</seg>
<seg>bigint</seg>
</seglistitem>
</segmentedlist>
Crée une entrée dans sl_event.
<programlisting>_Slony_I_createEvent</programlisting>
</para>
</section>
<!-- Function createevent( name, text, text, text, text, text, text ) -->
<section id="function.createevent-name-text-text-text-text-text-text"
xreflabel="schemadoccreateevent( name, text, text, text, text, text, text )">
<title id="function.createevent-name-text-text-text-text-text-text-title">
createevent( name, text, text, text, text, text, text )
</title>
<titleabbrev id="function.createevent-name-text-text-text-text-text-text-titleabbrev">
createevent( name, text, text, text, text, text, text )
</titleabbrev>
<para>
<segmentedlist>
<title>Propriétés de la fonction</title>
<?dbhtml list-presentation="list"?>
<segtitle>Langage</segtitle>
<segtitle>Type du code retour</segtitle>
<seglistitem>
<seg>C</seg>
<seg>bigint</seg>
</seglistitem>
</segmentedlist>
Crée une entrée dans sl_event.
<programlisting>_Slony_I_createEvent</programlisting>
</para>
</section>
<!-- Function createevent( name, text, text, text, text, text, text, text ) -->
<section id="function.createevent-name-text-text-text-text-text-text-text"
xreflabel="schemadoccreateevent( name, text, text, text, text, text, text, text )">
<title id="function.createevent-name-text-text-text-text-text-text-text-title">
createevent( name, text, text, text, text, text, text, text )
</title>
<titleabbrev id="function.createevent-name-text-text-text-text-text-text-text-titleabbrev">
createevent( name, text, text, text, text, text, text, text )
</titleabbrev>
<para>
<segmentedlist>
<title>Propriétés de la fonction</title>
<?dbhtml list-presentation="list"?>
<segtitle>Langage</segtitle>
<segtitle>Type du code retour</segtitle>
<seglistitem>
<seg>C</seg>
<seg>bigint</seg>
</seglistitem>
</segmentedlist>
Crée une entrée dans sl_event.
<programlisting>_Slony_I_createEvent</programlisting>
</para>
</section>
<!-- Function createevent( name, text, text, text, text, text, text, text, text ) -->
<section id="function.createevent-name-text-text-text-text-text-text-text-text"
xreflabel="schemadoccreateevent( name, text, text, text, text, text, text, text, text )">
<title id="function.createevent-name-text-text-text-text-text-text-text-text-title">
createevent( name, text, text, text, text, text, text, text, text )
</title>
<titleabbrev id="function.createevent-name-text-text-text-text-text-text-text-text-titleabbrev">
createevent( name, text, text, text, text, text, text, text, text )
</titleabbrev>
<para>
<segmentedlist>
<title>Propriétés de la fonction</title>
<?dbhtml list-presentation="list"?>
<segtitle>Langage</segtitle>
<segtitle>Type du code retour</segtitle>
<seglistitem>
<seg>C</seg>
<seg>bigint</seg>
</seglistitem>
</segmentedlist>
Crée une entrée dans sl_event.
<programlisting>_Slony_I_createEvent</programlisting>
</para>
</section>
<!-- Function createevent( name, text, text, text, text, text, text, text, text, text ) -->
<section id="function.createevent-name-text-text-text-text-text-text-text-text-text"
xreflabel="schemadoccreateevent( name, text, text, text, text, text, text, text, text, text )">
<title id="function.createevent-name-text-text-text-text-text-text-text-text-text-title">
createevent( name, text, text, text, text, text, text, text, text, text )
</title>
<titleabbrev id="function.createevent-name-text-text-text-text-text-text-text-text-text-titleabbrev">
createevent( name, text, text, text, text, text, text, text, text, text )
</titleabbrev>
<para>
<segmentedlist>
<title>Propriétés de la fonction</title>
<?dbhtml list-presentation="list"?>
<segtitle>Langage</segtitle>
<segtitle>Type du code retour</segtitle>
<seglistitem>
<seg>C</seg>
<seg>bigint</seg>
</seglistitem>
</segmentedlist>
Crée une entrée dans sl_event.
<programlisting>_Slony_I_createEvent</programlisting>
</para>
</section>
<!-- Function ddlscript_complete( integer, text, integer ) -->
<section id="function.ddlscript-complete-integer-text-integer"
xreflabel="schemadocddlscript_complete( integer, text, integer )">
<title id="function.ddlscript-complete-integer-text-integer-title">
ddlscript_complete( integer, text, integer )
</title>
<titleabbrev id="function.ddlscript-complete-integer-text-integer-titleabbrev">
ddlscript_complete( integer, text, integer )
</titleabbrev>
<para>
<segmentedlist>
<title>Propriétés de la fonction</title>
<?dbhtml list-presentation="list"?>
<segtitle>Langage</segtitle>
<segtitle>Type du code retour</segtitle>
<seglistitem>
<seg>PLPGSQL</seg>
<seg>integer</seg>
</seglistitem>
</segmentedlist>
Après l'exécution du script sur l'origine, ceci corrige les noms des relations,
restaure les triggers et génère un événement DDL_SCRIPT pour réclamer son
exécution sur les esclaves répliqués.
<programlisting>declare
p_set_id alias for $1;
p_script alias for $2;
p_only_on_node alias for $3;
v_set_origin int4;
begin
perform updateRelname(p_set_id, p_only_on_node);
return createEvent(&#39;_schemadoc&#39;, &#39;DDL_SCRIPT&#39;,
p_set_id, p_script, p_only_on_node);
end;</programlisting>
</para>
</section>
<!-- Function ddlscript_complete_int( integer, integer ) -->
<section id="function.ddlscript-complete-int-integer-integer"
xreflabel="schemadocddlscript_complete_int( integer, integer )">
<title id="function.ddlscript-complete-int-integer-integer-title">
ddlscript_complete_int( integer, integer )
</title>
<titleabbrev id="function.ddlscript-complete-int-integer-integer-titleabbrev">
ddlscript_complete_int( integer, integer )
</titleabbrev>
<para>
<segmentedlist>
<title>Propriétés de la fonction</title>
<?dbhtml list-presentation="list"?>
<segtitle>Langage</segtitle>
<segtitle>Type du code retour</segtitle>
<seglistitem>
<seg>PLPGSQL</seg>
<seg>integer</seg>
</seglistitem>
</segmentedlist>
Termine le traitement de l'événement DDL_SCRIPT. Ceci replace les tables en
mode répliqué.
<programlisting>declare
p_set_id alias for $1;
p_only_on_node alias for $2;
v_row record;
begin
-- ----
-- Put all tables back into replicated mode
-- ----
for v_row in select * from sl_table
loop
perform alterTableForReplication(v_row.tab_id);
end loop;
return p_set_id;
end;</programlisting>
</para>
</section>
<!-- Function ddlscript_prepare( integer, integer ) -->
<section id="function.ddlscript-prepare-integer-integer"
xreflabel="schemadocddlscript_prepare( integer, integer )">
<title id="function.ddlscript-prepare-integer-integer-title">
ddlscript_prepare( integer, integer )
</title>
<titleabbrev id="function.ddlscript-prepare-integer-integer-titleabbrev">
ddlscript_prepare( integer, integer )
</titleabbrev>
<para>
<segmentedlist>
<title>Propriétés de la fonction</title>
<?dbhtml list-presentation="list"?>
<segtitle>Langage</segtitle>
<segtitle>Type du code retour</segtitle>
<seglistitem>
<seg>PLPGSQL</seg>
<seg>integer</seg>
</seglistitem>
</segmentedlist>
Prépare l'exécution du script DDL sur l'origine.
<programlisting>declare
p_set_id alias for $1;
p_only_on_node alias for $2;
v_set_origin int4;
begin
-- ----
-- Grab the central configuration lock
-- ----
lock table sl_config_lock;
-- ----
-- Check that the set exists and originates here
-- ----
select set_origin into v_set_origin
from sl_set
where set_id = p_set_id
for update;
if not found then
raise exception &#39;Slony-I: set % not found&#39;, p_set_id;
end if;
if v_set_origin &lt;&gt; getLocalNodeId(&#39;_schemadoc&#39;) then
raise exception &#39;Slony-I: set % does not originate on local node&#39;,
p_set_id;
end if;
-- ----
-- Create a SYNC event, run the script and generate the DDL_SCRIPT event
-- ----
perform createEvent(&#39;_schemadoc&#39;, &#39;SYNC&#39;, NULL);
return 1;
end;</programlisting>
</para>
</section>
<!-- Function ddlscript_prepare_int( integer, integer ) -->
<section id="function.ddlscript-prepare-int-integer-integer"
xreflabel="schemadocddlscript_prepare_int( integer, integer )">
<title id="function.ddlscript-prepare-int-integer-integer-title">
ddlscript_prepare_int( integer, integer )
</title>
<titleabbrev id="function.ddlscript-prepare-int-integer-integer-titleabbrev">
ddlscript_prepare_int( integer, integer )
</titleabbrev>
<para>
<segmentedlist>
<title>Propriétés de la fonction</title>
<?dbhtml list-presentation="list"?>
<segtitle>Langage</segtitle>
<segtitle>Type du code retour</segtitle>
<seglistitem>
<seg>PLPGSQL</seg>
<seg>integer</seg>
</seglistitem>
</segmentedlist>
Fait le travail préparatoire pour un script DDL, restaure les
triggers/règles dans leur état original.
<programlisting>declare
p_set_id alias for $1;
p_only_on_node alias for $2;
v_set_origin int4;
v_no_id int4;
v_row record;
begin
-- ----
-- Grab the central configuration lock
-- ----
lock table sl_config_lock;
-- ----
-- Check that we either are the set origin or a current
-- subscriber of the set.
-- ----
v_no_id := getLocalNodeId(&#39;_schemadoc&#39;);
select set_origin into v_set_origin
from sl_set
where set_id = p_set_id
for update;
if not found then
raise exception &#39;Slony-I: set % not found&#39;, p_set_id;
end if;
if v_set_origin &lt;&gt; v_no_id
and not exists (select 1 from sl_subscribe
where sub_set = p_set_id
and sub_receiver = v_no_id)
then
return 0;
end if;
-- ----
-- If execution on only one node is requested, check that
-- we are that node.
-- ----
if p_only_on_node &gt; 0 and p_only_on_node &lt;&gt; v_no_id then
return 0;
end if;
-- ----
-- Restore all original triggers and rules of all sets
-- ----
for v_row in select * from sl_table
loop
perform alterTableRestore(v_row.tab_id);
end loop;
return p_set_id;
end;</programlisting>
</para>
</section>
<!-- Function denyaccess( ) -->
<section id="function.denyaccess"
xreflabel="schemadocdenyaccess( )">
<title id="function.denyaccess-title">
denyaccess( )
</title>
<titleabbrev id="function.denyaccess-titleabbrev">
denyaccess( )
</titleabbrev>
<para>
<segmentedlist>
<title>Propriétés de la fonction</title>
<?dbhtml list-presentation="list"?>
<segtitle>Langage</segtitle>
<segtitle>Type du code retour</segtitle>
<seglistitem>
<seg>C</seg>
<seg>&quot;trigger&quot;</seg>
</seglistitem>
</segmentedlist>
Fonction trigger pour empêcher la modification d'une table sur un abonné.
<programlisting>_Slony_I_denyAccess</programlisting>
</para>
</section>
<!-- Function determineattkindserial( text ) -->
<section id="function.determineattkindserial-text"
xreflabel="schemadocdetermineattkindserial( text )">
<title id="function.determineattkindserial-text-title">
determineattkindserial( text )
</title>
<titleabbrev id="function.determineattkindserial-text-titleabbrev">
determineattkindserial( text )
</titleabbrev>
<para>
<segmentedlist>
<title>Propriétés de la fonction</title>
<?dbhtml list-presentation="list"?>
<segtitle>Langage</segtitle>
<segtitle>Type du code retour</segtitle>
<seglistitem>
<seg>PLPGSQL</seg>
<seg>text</seg>
</seglistitem>
</segmentedlist>
Une table indiquée sans clé primaire est ajoutée à la réplication. Suppose que
tableAddKey() a été appelé avant et termine la création de la colonne de type
serial. Elle renvoie l'attkind.
<programlisting>declare
p_tab_fqname alias for $1;
v_tab_fqname_quoted text default &#39;&#39;;
v_attkind text default &#39;&#39;;
v_attrow record;
v_have_serial bool default &#39;f&#39;;
begin
v_tab_fqname_quoted := slon_quote_input(p_tab_fqname);
--
-- Loop over the attributes of this relation
-- and add a &quot;v&quot; for every user column, and a &quot;k&quot;
-- if we find the Slony-I special serial column.
--
for v_attrow in select PGA.attnum, PGA.attname
from &quot;pg_catalog&quot;.pg_class PGC,
&quot;pg_catalog&quot;.pg_namespace PGN,
&quot;pg_catalog&quot;.pg_attribute PGA
where slon_quote_brute(PGN.nspname) || &#39;.&#39; ||
slon_quote_brute(PGC.relname) = v_tab_fqname_quoted
and PGN.oid = PGC.relnamespace
and PGA.attrelid = PGC.oid
and not PGA.attisdropped
and PGA.attnum &gt; 0
order by attnum
loop
if v_attrow.attname = &#39;_Slony-I_schemadoc_rowID&#39; then
v_attkind := v_attkind || &#39;k&#39;;
v_have_serial := &#39;t&#39;;
else
v_attkind := v_attkind || &#39;v&#39;;
end if;
end loop;
--
-- A table must have at least one attribute, so not finding
-- anything means the table does not exist.
--
if not found then
raise exception &#39;Slony-I: table % not found&#39;, v_tab_fqname_quoted;
end if;
--
-- If it does not have the special serial column, we
-- should not have been called in the first place.
--
if not v_have_serial then
raise exception &#39;Slony-I: table % does not have the serial key&#39;,
v_tab_fqname_quoted;
end if;
execute &#39;update &#39; || v_tab_fqname_quoted ||
&#39; set &quot;_Slony-I_schemadoc_rowID&quot; =&#39; ||
&#39; &quot;pg_catalog&quot;.nextval(&#39;&#39;sl_rowid_seq&#39;&#39;);&#39;;
execute &#39;alter table only &#39; || v_tab_fqname_quoted ||
&#39; add unique (&quot;_Slony-I_schemadoc_rowID&quot;);&#39;;
execute &#39;alter table only &#39; || v_tab_fqname_quoted ||
&#39; alter column &quot;_Slony-I_schemadoc_rowID&quot; &#39; ||
&#39; set not null;&#39;;
--
-- Return the resulting Slony-I attkind
--
return v_attkind;
end;</programlisting>
</para>
</section>
<!-- Function determineattkindunique( text, name ) -->
<section id="function.determineattkindunique-text-name"
xreflabel="schemadocdetermineattkindunique( text, name )">
<title id="function.determineattkindunique-text-name-title">
determineattkindunique( text, name )
</title>
<titleabbrev id="function.determineattkindunique-text-name-titleabbrev">
determineattkindunique( text, name )
</titleabbrev>
<para>
<segmentedlist>
<title>Propriétés de la fonction</title>
<?dbhtml list-presentation="list"?>
<segtitle>Langage</segtitle>
<segtitle>Type du code retour</segtitle>
<seglistitem>
<seg>PLPGSQL</seg>
<seg>text</seg>
</seglistitem>
</segmentedlist>
Suivant le nom d'une table, renvoie le attkind spécifique de Slony-I (utilisé
pour le trigger log) de la table. Utilise l'index unique spécifié ou la clé
primaire (si indexname vaut NULL).
<programlisting>declare
p_tab_fqname alias for $1;
v_tab_fqname_quoted text default &#39;&#39;;
p_idx_name alias for $2;
v_idx_name_quoted text;
v_idxrow record;
v_attrow record;
v_i integer;
v_attno int2;
v_attkind text default &#39;&#39;;
v_attfound bool;
begin
v_tab_fqname_quoted := slon_quote_input(p_tab_fqname);
v_idx_name_quoted := slon_quote_brute(p_idx_name);
--
-- Ensure that the table exists
--
if (select PGC.relname
from &quot;pg_catalog&quot;.pg_class PGC,
&quot;pg_catalog&quot;.pg_namespace PGN
where slon_quote_brute(PGN.nspname) || &#39;.&#39; ||
slon_quote_brute(PGC.relname) = v_tab_fqname_quoted
and PGN.oid = PGC.relnamespace) is null then
raise exception &#39;Slony-I: table % not found&#39;, v_tab_fqname_quoted;
end if;
--
-- Lookup the tables primary key or the specified unique index
--
if p_idx_name isnull then
raise exception &#39;Slony-I: index name must be specified&#39;;
else
select PGXC.relname, PGX.indexrelid, PGX.indkey
into v_idxrow
from &quot;pg_catalog&quot;.pg_class PGC,
&quot;pg_catalog&quot;.pg_namespace PGN,
&quot;pg_catalog&quot;.pg_index PGX,
&quot;pg_catalog&quot;.pg_class PGXC
where slon_quote_brute(PGN.nspname) || &#39;.&#39; ||
slon_quote_brute(PGC.relname) = v_tab_fqname_quoted
and PGN.oid = PGC.relnamespace
and PGX.indrelid = PGC.oid
and PGX.indexrelid = PGXC.oid
and PGX.indisunique
and slon_quote_brute(PGXC.relname) = v_idx_name_quoted;
if not found then
raise exception &#39;Slony-I: table % has no unique index %&#39;,
v_tab_fqname_quoted, v_idx_name_quoted;
end if;
end if;
--
-- Loop over the tables attributes and check if they are
-- index attributes. If so, add a &quot;k&quot; to the return value,
-- otherwise add a &quot;v&quot;.
--
for v_attrow in select PGA.attnum, PGA.attname
from &quot;pg_catalog&quot;.pg_class PGC,
&quot;pg_catalog&quot;.pg_namespace PGN,
&quot;pg_catalog&quot;.pg_attribute PGA
where slon_quote_brute(PGN.nspname) || &#39;.&#39; ||
slon_quote_brute(PGC.relname) = v_tab_fqname_quoted
and PGN.oid = PGC.relnamespace
and PGA.attrelid = PGC.oid
and not PGA.attisdropped
and PGA.attnum &gt; 0
order by attnum
loop
v_attfound = &#39;f&#39;;
v_i := 0;
loop
select indkey[v_i] into v_attno from &quot;pg_catalog&quot;.pg_index
where indexrelid = v_idxrow.indexrelid;
if v_attno isnull or v_attno = 0 then
exit;
end if;
if v_attrow.attnum = v_attno then
v_attfound = &#39;t&#39;;
exit;
end if;
v_i := v_i + 1;
end loop;
if v_attfound then
v_attkind := v_attkind || &#39;k&#39;;
else
v_attkind := v_attkind || &#39;v&#39;;
end if;
end loop;
--
-- Return the resulting attkind
--
return v_attkind;
end;</programlisting>
</para>
</section>
<!-- Function determineidxnameserial( text ) -->
<section id="function.determineidxnameserial-text"
xreflabel="schemadocdetermineidxnameserial( text )">
<title id="function.determineidxnameserial-text-title">
determineidxnameserial( text )
</title>
<titleabbrev id="function.determineidxnameserial-text-titleabbrev">
determineidxnameserial( text )
</titleabbrev>
<para>
<segmentedlist>
<title>Propriétés de la fonction</title>
<?dbhtml list-presentation="list"?>
<segtitle>Langage</segtitle>
<segtitle>Type du code retour</segtitle>
<seglistitem>
<seg>PLPGSQL</seg>
<seg>name</seg>
</seglistitem>
</segmentedlist>
Suivant le nom d'une table, construit un nom d'index de la colonne de type
serial.
<programlisting>declare
p_tab_fqname alias for $1;
v_tab_fqname_quoted text default &#39;&#39;;
v_row record;
begin
v_tab_fqname_quoted := slon_quote_input(p_tab_fqname);
--
-- Lookup the table name alone
--
select PGC.relname
into v_row
from &quot;pg_catalog&quot;.pg_class PGC,
&quot;pg_catalog&quot;.pg_namespace PGN
where slon_quote_brute(PGN.nspname) || &#39;.&#39; ||
slon_quote_brute(PGC.relname) = v_tab_fqname_quoted
and PGN.oid = PGC.relnamespace;
if not found then
raise exception &#39;Slony-I: table % not found&#39;,
v_tab_fqname_quoted;
end if;
--
-- Return the found index name
--
return v_row.relname || &#39;__Slony-I_schemadoc_rowID_key&#39;;
end;</programlisting>
</para>
</section>
<!-- Function determineidxnameunique( text, name ) -->
<section id="function.determineidxnameunique-text-name"
xreflabel="schemadocdetermineidxnameunique( text, name )">
<title id="function.determineidxnameunique-text-name-title">
determineidxnameunique( text, name )
</title>
<titleabbrev id="function.determineidxnameunique-text-name-titleabbrev">
determineidxnameunique( text, name )
</titleabbrev>
<para>
<segmentedlist>
<title>Propriétés de la fonction</title>
<?dbhtml list-presentation="list"?>
<segtitle>Langage</segtitle>
<segtitle>Type du code retour</segtitle>
<seglistitem>
<seg>PLPGSQL</seg>
<seg>name</seg>
</seglistitem>
</segmentedlist>
FUNCTION determineIdxnameUnique (tab_fqname, indexname)
Suivant un nom de table, tab_fqname, vérifie que l'index unique, indexname,
existe ou renvoie le nom de l'index de clé primaire pour la table. S'il n'y
a pas d'index unique, il lève une exception.
<programlisting>declare
p_tab_fqname alias for $1;
v_tab_fqname_quoted text default &#39;&#39;;
p_idx_name alias for $2;
v_idxrow record;
begin
v_tab_fqname_quoted := slon_quote_input(p_tab_fqname);
--
-- Ensure that the table exists
--
if (select PGC.relname
from &quot;pg_catalog&quot;.pg_class PGC,
&quot;pg_catalog&quot;.pg_namespace PGN
where slon_quote_brute(PGN.nspname) || &#39;.&#39; ||
slon_quote_brute(PGC.relname) = v_tab_fqname_quoted
and PGN.oid = PGC.relnamespace) is null then
raise exception &#39;Slony-I: determineIdxnameUnique(): table % not found&#39;, v_tab_fqname_quoted;
end if;
--
-- Lookup the tables primary key or the specified unique index
--
if p_idx_name isnull then
select PGXC.relname
into v_idxrow
from &quot;pg_catalog&quot;.pg_class PGC,
&quot;pg_catalog&quot;.pg_namespace PGN,
&quot;pg_catalog&quot;.pg_index PGX,
&quot;pg_catalog&quot;.pg_class PGXC
where slon_quote_brute(PGN.nspname) || &#39;.&#39; ||
slon_quote_brute(PGC.relname) = v_tab_fqname_quoted
and PGN.oid = PGC.relnamespace
and PGX.indrelid = PGC.oid
and PGX.indexrelid = PGXC.oid
and PGX.indisprimary;
if not found then
raise exception &#39;Slony-I: table % has no primary key&#39;,
v_tab_fqname_quoted;
end if;
else
select PGXC.relname
into v_idxrow
from &quot;pg_catalog&quot;.pg_class PGC,
&quot;pg_catalog&quot;.pg_namespace PGN,
&quot;pg_catalog&quot;.pg_index PGX,
&quot;pg_catalog&quot;.pg_class PGXC
where slon_quote_brute(PGN.nspname) || &#39;.&#39; ||
slon_quote_brute(PGC.relname) = v_tab_fqname_quoted
and PGN.oid = PGC.relnamespace
and PGX.indrelid = PGC.oid
and PGX.indexrelid = PGXC.oid
and PGX.indisunique
and slon_quote_brute(PGXC.relname) = slon_quote_input(p_idx_name);
if not found then
raise exception &#39;Slony-I: table % has no unique index %&#39;,
v_tab_fqname_quoted, p_idx_name;
end if;
end if;
--
-- Return the found index name
--
return v_idxrow.relname;
end;</programlisting>
</para>
</section>
<!-- Function disablenode( integer ) -->
<section id="function.disablenode-integer"
xreflabel="schemadocdisablenode( integer )">
<title id="function.disablenode-integer-title">
disablenode( integer )
</title>
<titleabbrev id="function.disablenode-integer-titleabbrev">
disablenode( integer )
</titleabbrev>
<para>
<segmentedlist>
<title>Propriétés de la fonction</title>
<?dbhtml list-presentation="list"?>
<segtitle>Langage</segtitle>
<segtitle>Type du code retour</segtitle>
<seglistitem>
<seg>PLPGSQL</seg>
<seg>bigint</seg>
</seglistitem>
</segmentedlist>
Traite l'événement DISABLE_NODE pour le n&oelig;ud no_id.
Note&nbsp;: ceci n'est pas encore implanté&nbsp;!
<programlisting>declare
p_no_id alias for $1;
begin
-- **** TODO ****
raise exception &#39;Slony-I: disableNode() not implemented&#39;;
end;</programlisting>
</para>
</section>
<!-- Function disablenode_int( integer ) -->
<section id="function.disablenode-int-integer"
xreflabel="schemadocdisablenode_int( integer )">
<title id="function.disablenode-int-integer-title">
disablenode_int( integer )
</title>
<titleabbrev id="function.disablenode-int-integer-titleabbrev">
disablenode_int( integer )
</titleabbrev>
<para>
<segmentedlist>
<title>Propriétés de la fonction</title>
<?dbhtml list-presentation="list"?>
<segtitle>Langage</segtitle>
<segtitle>Type du code retour</segtitle>
<seglistitem>
<seg>PLPGSQL</seg>
<seg>integer</seg>
</seglistitem>
</segmentedlist>
<programlisting>declare
p_no_id alias for $1;
begin
-- **** TODO ****
raise exception &#39;Slony-I: disableNode_int() not implemented&#39;;
end;</programlisting>
</para>
</section>
<!-- Function droplisten( integer, integer, integer ) -->
<section id="function.droplisten-integer-integer-integer"
xreflabel="schemadocdroplisten( integer, integer, integer )">
<title id="function.droplisten-integer-integer-integer-title">
droplisten( integer, integer, integer )
</title>
<titleabbrev id="function.droplisten-integer-integer-integer-titleabbrev">
droplisten( integer, integer, integer )
</titleabbrev>
<para>
<segmentedlist>
<title>Propriétés de la fonction</title>
<?dbhtml list-presentation="list"?>
<segtitle>Langage</segtitle>
<segtitle>Type du code retour</segtitle>
<seglistitem>
<seg>PLPGSQL</seg>
<seg>bigint</seg>
</seglistitem>
</segmentedlist>
Génère l'événement DROP_LISTEN.
<programlisting>declare
p_li_origin alias for $1;
p_li_provider alias for $2;
p_li_receiver alias for $3;
begin
perform dropListen_int(p_li_origin,
p_li_provider, p_li_receiver);
return createEvent (&#39;_schemadoc&#39;, &#39;DROP_LISTEN&#39;,
p_li_origin, p_li_provider, p_li_receiver);
end;</programlisting>
</para>
</section>
<!-- Function droplisten_int( integer, integer, integer ) -->
<section id="function.droplisten-int-integer-integer-integer"
xreflabel="schemadocdroplisten_int( integer, integer, integer )">
<title id="function.droplisten-int-integer-integer-integer-title">
droplisten_int( integer, integer, integer )
</title>
<titleabbrev id="function.droplisten-int-integer-integer-integer-titleabbrev">
droplisten_int( integer, integer, integer )
</titleabbrev>
<para>
<segmentedlist>
<title>Propriétés de la fonction</title>
<?dbhtml list-presentation="list"?>
<segtitle>Langage</segtitle>
<segtitle>Type du code retour</segtitle>
<seglistitem>
<seg>PLPGSQL</seg>
<seg>integer</seg>
</seglistitem>
</segmentedlist>
Traite l'événement DROP_LISTEN, supprimant l'entrée sl_listen pour la
combinaison (origine, fournisseur, récepteur) indiquée.
<programlisting>declare
p_li_origin alias for $1;
p_li_provider alias for $2;
p_li_receiver alias for $3;
begin
-- ----
-- Grab the central configuration lock
-- ----
lock table sl_config_lock;
delete from sl_listen
where li_origin = p_li_origin
and li_provider = p_li_provider
and li_receiver = p_li_receiver;
if found then
return 1;
else
return 0;
end if;
end;</programlisting>
</para>
</section>
<!-- Function dropnode( integer ) -->
<section id="function.dropnode-integer"
xreflabel="schemadocdropnode( integer )">
<title id="function.dropnode-integer-title">
dropnode( integer )
</title>
<titleabbrev id="function.dropnode-integer-titleabbrev">
dropnode( integer )
</titleabbrev>
<para>
<segmentedlist>
<title>Propriétés de la fonction</title>
<?dbhtml list-presentation="list"?>
<segtitle>Langage</segtitle>
<segtitle>Type du code retour</segtitle>
<seglistitem>
<seg>PLPGSQL</seg>
<seg>bigint</seg>
</seglistitem>
</segmentedlist>
Génère un événement DROP_NODE pour supprimer le n&oelig;ud node_id de la
réplication.
<programlisting>declare
p_no_id alias for $1;
v_node_row record;
begin
-- ----
-- Grab the central configuration lock
-- ----
lock table sl_config_lock;
-- ----
-- Check that this got called on a different node
-- ----
if p_no_id = getLocalNodeId(&#39;_schemadoc&#39;) then
raise exception &#39;Slony-I: DROP_NODE cannot initiate on the dropped node&#39;;
end if;
select * into v_node_row from sl_node
where no_id = p_no_id
for update;
if not found then
raise exception &#39;Slony-I: unknown node ID %&#39;, p_no_id;
end if;
-- ----
-- Make sure we do not break other nodes subscriptions with this
-- ----
if exists (select true from sl_subscribe
where sub_provider = p_no_id)
then
raise exception &#39;Slony-I: Node % is still configured as a data provider&#39;,
p_no_id;
end if;
-- ----
-- Make sure no set originates there any more
-- ----
if exists (select true from sl_set
where set_origin = p_no_id)
then
raise exception &#39;Slony-I: Node % is still origin of one or more sets&#39;,
p_no_id;
end if;
-- ----
-- Call the internal drop functionality and generate the event
-- ----
perform dropNode_int(p_no_id);
return createEvent(&#39;_schemadoc&#39;, &#39;DROP_NODE&#39;,
p_no_id);
end;</programlisting>
</para>
</section>
<!-- Function dropnode_int( integer ) -->
<section id="function.dropnode-int-integer"
xreflabel="schemadocdropnode_int( integer )">
<title id="function.dropnode-int-integer-title">
dropnode_int( integer )
</title>
<titleabbrev id="function.dropnode-int-integer-titleabbrev">
dropnode_int( integer )
</titleabbrev>
<para>
<segmentedlist>
<title>Propriétés de la fonction</title>
<?dbhtml list-presentation="list"?>
<segtitle>Langage</segtitle>
<segtitle>Type du code retour</segtitle>
<seglistitem>
<seg>PLPGSQL</seg>
<seg>integer</seg>
</seglistitem>
</segmentedlist>
Fonction interne pour traiter l'événement DROP_NODE, pour supprimer le
n&oelig;ud node_id de la réplication.
<programlisting>declare
p_no_id alias for $1;
v_tab_row record;
begin
-- ----
-- Grab the central configuration lock
-- ----
lock table sl_config_lock;
-- ----
-- If the dropped node is a remote node, clean the configuration
-- from all traces for it.
-- ----
if p_no_id &lt;&gt; getLocalNodeId(&#39;_schemadoc&#39;) then
delete from sl_subscribe
where sub_receiver = p_no_id;
delete from sl_listen
where li_origin = p_no_id
or li_provider = p_no_id
or li_receiver = p_no_id;
delete from sl_path
where pa_server = p_no_id
or pa_client = p_no_id;
delete from sl_confirm
where con_origin = p_no_id
or con_received = p_no_id;
delete from sl_event
where ev_origin = p_no_id;
delete from sl_node
where no_id = p_no_id;
return p_no_id;
end if;
-- ----
-- This is us ... deactivate the node for now, the daemon
-- will call uninstallNode() in a separate transaction.
-- ----
update sl_node
set no_active = false
where no_id = p_no_id;
-- Rewrite sl_listen table
perform RebuildListenEntries();
return p_no_id;
end;</programlisting>
</para>
</section>
<!-- Function droppath( integer, integer ) -->
<section id="function.droppath-integer-integer"
xreflabel="schemadocdroppath( integer, integer )">
<title id="function.droppath-integer-integer-title">
droppath( integer, integer )
</title>
<titleabbrev id="function.droppath-integer-integer-titleabbrev">
droppath( integer, integer )
</titleabbrev>
<para>
<segmentedlist>
<title>Propriétés de la fonction</title>
<?dbhtml list-presentation="list"?>
<segtitle>Langage</segtitle>
<segtitle>Type du code retour</segtitle>
<seglistitem>
<seg>PLPGSQL</seg>
<seg>bigint</seg>
</seglistitem>
</segmentedlist>
Génère un événement DROP_PATH pour supprimer le chemin de pa_server à
pa_client.
<programlisting>declare
p_pa_server alias for $1;
p_pa_client alias for $2;
v_row record;
begin
-- ----
-- Grab the central configuration lock
-- ----
lock table sl_config_lock;
-- ----
-- There should be no existing subscriptions. Auto unsubscribing
-- is considered too dangerous.
-- ----
for v_row in select sub_set, sub_provider, sub_receiver
from sl_subscribe
where sub_provider = p_pa_server
and sub_receiver = p_pa_client
loop
raise exception
&#39;Slony-I: Path cannot be dropped, subscription of set % needs it&#39;,
v_row.sub_set;
end loop;
-- ----
-- Drop all sl_listen entries that depend on this path
-- ----
for v_row in select li_origin, li_provider, li_receiver
from sl_listen
where li_provider = p_pa_server
and li_receiver = p_pa_client
loop
perform dropListen(
v_row.li_origin, v_row.li_provider, v_row.li_receiver);
end loop;
-- ----
-- Now drop the path and create the event
-- ----
perform dropPath_int(p_pa_server, p_pa_client);
-- Rewrite sl_listen table
perform RebuildListenEntries();
return createEvent (&#39;_schemadoc&#39;, &#39;DROP_PATH&#39;,
p_pa_server, p_pa_client);
end;</programlisting>
</para>
</section>
<!-- Function droppath_int( integer, integer ) -->
<section id="function.droppath-int-integer-integer"
xreflabel="schemadocdroppath_int( integer, integer )">
<title id="function.droppath-int-integer-integer-title">
droppath_int( integer, integer )
</title>
<titleabbrev id="function.droppath-int-integer-integer-titleabbrev">
droppath_int( integer, integer )
</titleabbrev>
<para>
<segmentedlist>
<title>Propriétés de la fonction</title>
<?dbhtml list-presentation="list"?>
<segtitle>Langage</segtitle>
<segtitle>Type du code retour</segtitle>
<seglistitem>
<seg>PLPGSQL</seg>
<seg>integer</seg>
</seglistitem>
</segmentedlist>
Traite l'événement DROP_PATH pour supprimer le chemin de pa_server vers
pa_client.
<programlisting>declare
p_pa_server alias for $1;
p_pa_client alias for $2;
begin
-- ----
-- Grab the central configuration lock
-- ----
lock table sl_config_lock;
-- ----
-- Remove any dangling sl_listen entries with the server
-- as provider and the client as receiver. This must have
-- been cleared out before, but obviously was not.
-- ----
delete from sl_listen
where li_provider = p_pa_server
and li_receiver = p_pa_client;
delete from sl_path
where pa_server = p_pa_server
and pa_client = p_pa_client;
if found then
-- Rewrite sl_listen table
perform RebuildListenEntries();
return 1;
else
-- Rewrite sl_listen table
perform RebuildListenEntries();
return 0;
end if;
end;</programlisting>
</para>
</section>
<!-- Function dropset( integer ) -->
<section id="function.dropset-integer"
xreflabel="schemadocdropset( integer )">
<title id="function.dropset-integer-title">
dropset( integer )
</title>
<titleabbrev> id="function.dropset-integer-titleabbrev">
dropset( integer )
</titleabbrev>
<para>
<segmentedlist>
<title>Propriétés de la fonction</title>
<?dbhtml list-presentation="list"?>
<segtitle>Langage</segtitle>
<segtitle>Type du code retour</segtitle>
<seglistitem>
<seg>PLPGSQL</seg>
<seg>bigint</seg>
</seglistitem>
</segmentedlist>
Traite l'événement DROP_SET pour supprimer la réplication de l'ensemble set_id. Ceci implique de&nbsp;:
<itemizedlist>
<listitem>
<para>restaurer les triggers et règles originaux&nbsp;;</para>
</listitem>
<listitem>
<para>
supprimer toutes les traces de la configuration de l'événement, en
incluant les séquences, tables, abonnés, syncs et l'ensemble lui-même.
</para>
</listitem>
</itemizedlist>
<programlisting>declare
p_set_id alias for $1;
v_origin int4;
begin
-- ----
-- Grab the central configuration lock
-- ----
lock table sl_config_lock;
-- ----
-- Check that the set exists and originates here
-- ----
select set_origin into v_origin from sl_set
where set_id = p_set_id;
if not found then
raise exception &#39;Slony-I: set % not found&#39;, p_set_id;
end if;
if v_origin != getLocalNodeId(&#39;_schemadoc&#39;) then
raise exception &#39;Slony-I: set % does not originate on local node&#39;,
p_set_id;
end if;
-- ----
-- Call the internal drop set functionality and generate the event
-- ----
perform dropSet_int(p_set_id);
return createEvent(&#39;_schemadoc&#39;, &#39;DROP_SET&#39;,
p_set_id);
end;</programlisting>
</para>
</section>
<!-- Function dropset_int( integer ) -->
<section id="function.dropset-int-integer"
xreflabel="schemadocdropset_int( integer )">
<title id="function.dropset-int-integer-title">
dropset_int( integer )
</title>
<titleabbrev> id="function.dropset-int-integer-titleabbrev">
dropset_int( integer )
</titleabbrev>
<para>
<segmentedlist>
<title>Propriétés de la fonction</title>
<?dbhtml list-presentation="list"?>
<segtitle>Langage</segtitle>
<segtitle>Type du code retour</segtitle>
<seglistitem>
<seg>PLPGSQL</seg>
<seg>integer</seg>
</seglistitem>
</segmentedlist>
<programlisting>declare
p_set_id alias for $1;
v_tab_row record;
begin
-- ----
-- Grab the central configuration lock
-- ----
lock table sl_config_lock;
-- ----
-- Restore all tables original triggers and rules and remove
-- our replication stuff.
-- ----
for v_tab_row in select tab_id from sl_table
where tab_set = p_set_id
order by tab_id
loop
perform alterTableRestore(v_tab_row.tab_id);
perform tableDropKey(v_tab_row.tab_id);
end loop;
-- ----
-- Remove all traces of the set configuration
-- ----
delete from sl_sequence
where seq_set = p_set_id;
delete from sl_table
where tab_set = p_set_id;
delete from sl_subscribe
where sub_set = p_set_id;
delete from sl_setsync
where ssy_setid = p_set_id;
delete from sl_set
where set_id = p_set_id;
-- Regenerate sl_listen since we revised the subscriptions
perform RebuildListenEntries();
-- Run addPartialLogIndices() to try to add indices to unused sl_log_? table
perform addPartialLogIndices();
return p_set_id;
end;</programlisting>
</para>
</section>
<!-- Function droptrigger( integer, name ) -->
<section id="function.droptrigger-integer-name"
xreflabel="schemadocdroptrigger( integer, name )">
<title id="function.droptrigger-integer-name-title">
droptrigger( integer, name )
</title>
<titleabbrev> id="function.droptrigger-integer-name-titleabbrev">
droptrigger( integer, name )
</titleabbrev>
<para>
<segmentedlist>
<title>Propriétés de la fonction</title>
<?dbhtml list-presentation="list"?>
<segtitle>Langage</segtitle>
<segtitle>Type du code retour</segtitle>
<seglistitem>
<seg>PLPGSQL</seg>
<seg>bigint</seg>
</seglistitem>
</segmentedlist>
Soumet un événement DROP_TRIGGER pour indiquer que le trigger trig_tgname
sur la table répliquée trig_tabid SERA désactivé.
<programlisting>declare
p_trig_tabid alias for $1;
p_trig_tgname alias for $2;
begin
perform dropTrigger_int(p_trig_tabid, p_trig_tgname);
return createEvent(&#39;_schemadoc&#39;, &#39;DROP_TRIGGER&#39;,
p_trig_tabid, p_trig_tgname);
end;</programlisting>
</para>
</section>
<!-- Function droptrigger_int( integer, name ) -->
<section id="function.droptrigger-int-integer-name"
xreflabel="schemadocdroptrigger_int( integer, name )">
<title id="function.droptrigger-int-integer-name-title">
droptrigger_int( integer, name )
</title>
<titleabbrev> id="function.droptrigger-int-integer-name-titleabbrev">
droptrigger_int( integer, name )
</titleabbrev>
<para>
<segmentedlist>
<title>Propriétés de la fonction</title>
<?dbhtml list-presentation="list"?>
<segtitle>Langage</segtitle>
<segtitle>Type du code retour</segtitle>
<seglistitem>
<seg>PLPGSQL</seg>
<seg>integer</seg>
</seglistitem>
</segmentedlist>
Traite l'événement DROP_TRIGGER pour assurer que le trigger trig_tgname
sur la table répliquée trig_tabid est désactivé.
<programlisting>declare
p_trig_tabid alias for $1;
p_trig_tgname alias for $2;
v_tab_altered boolean;
begin
-- ----
-- Grab the central configuration lock
-- ----
lock table sl_config_lock;
-- ----
-- Get the current table status (altered or not)
-- ----
select tab_altered into v_tab_altered
from sl_table where tab_id = p_trig_tabid;
if not found then
-- ----
-- Not found is no hard error here, because that might
-- mean that we are not subscribed to that set
-- ----
return 0;
end if;
-- ----
-- If the table is modified for replication, restore the original state
-- ----
if v_tab_altered then
perform alterTableRestore(p_trig_tabid);
end if;
-- ----
-- Remove the entry from sl_trigger
-- ----
delete from sl_trigger
where trig_tabid = p_trig_tabid
and trig_tgname = p_trig_tgname;
-- ----
-- Put the table back into replicated state if it was
-- ----
if v_tab_altered then
perform alterTableForReplication(p_trig_tabid);
end if;
return p_trig_tabid;
end;</programlisting>
</para>
</section>
<!-- Function enablenode( integer ) -->
<section id="function.enablenode-integer"
xreflabel="schemadocenablenode( integer )">
<title id="function.enablenode-integer-title">
enablenode( integer )
</title>
<titleabbrev> id="function.enablenode-integer-titleabbrev">
enablenode( integer )
</titleabbrev>
<para>
<segmentedlist>
<title>Propriétés de la fonction</title>
<?dbhtml list-presentation="list"?>
<segtitle>Langage</segtitle>
<segtitle>Type du code retour</segtitle>
<seglistitem>
<seg>PLPGSQL</seg>
<seg>bigint</seg>
</seglistitem>
</segmentedlist>
no_id - identifiant du n&oelig;ud
Génère l'événement ENABLE_NODE pour le n&oelig;ud no_id.
<programlisting>declare
p_no_id alias for $1;
v_local_node_id int4;
v_node_row record;
begin
-- ----
-- Grab the central configuration lock
-- ----
lock table sl_config_lock;
-- ----
-- Check that we are the node to activate and that we are
-- currently disabled.
-- ----
v_local_node_id := getLocalNodeId(&#39;_schemadoc&#39;);
select * into v_node_row
from sl_node
where no_id = p_no_id
for update;
if not found then
raise exception &#39;Slony-I: node % not found&#39;, p_no_id;
end if;
if v_node_row.no_active then
raise exception &#39;Slony-I: node % is already active&#39;, p_no_id;
end if;
-- ----
-- Activate this node and generate the ENABLE_NODE event
-- ----
perform enableNode_int (p_no_id);
return createEvent(&#39;_schemadoc&#39;, &#39;ENABLE_NODE&#39;,
p_no_id);
end;</programlisting>
</para>
</section>
<!-- Function enablenode_int( integer ) -->
<section id="function.enablenode-int-integer"
xreflabel="schemadocenablenode_int( integer )">
<title id="function.enablenode-int-integer-title">
enablenode_int( integer )
</title>
<titleabbrev> id="function.enablenode-int-integer-titleabbrev">
enablenode_int( integer )
</titleabbrev>
<para>
<segmentedlist>
<title>Propriétés de la fonction</title>
<?dbhtml list-presentation="list"?>
<segtitle>Langage</segtitle>
<segtitle>Type du code retour</segtitle>
<seglistitem>
<seg>PLPGSQL</seg>
<seg>integer</seg>
</seglistitem>
</segmentedlist>
no_id - Identifiant du n&oelig;ud
Fonction interne pour traiter l'événement ENABLE_NODE pour le n&oelig;ud
no_id.
<programlisting>declare
p_no_id alias for $1;
v_local_node_id int4;
v_node_row record;
v_sub_row record;
begin
-- ----
-- Grab the central configuration lock
-- ----
lock table sl_config_lock;
-- ----
-- Check that the node is inactive
-- ----
select * into v_node_row
from sl_node
where no_id = p_no_id
for update;
if not found then
raise exception &#39;Slony-I: node % not found&#39;, p_no_id;
end if;
if v_node_row.no_active then
return p_no_id;
end if;
-- ----
-- Activate the node and generate sl_confirm status rows for it.
-- ----
update sl_node
set no_active = &#39;t&#39;
where no_id = p_no_id;
insert into sl_confirm
(con_origin, con_received, con_seqno)
select no_id, p_no_id, 0 from sl_node
where no_id != p_no_id
and no_active;
insert into sl_confirm
(con_origin, con_received, con_seqno)
select p_no_id, no_id, 0 from sl_node
where no_id != p_no_id
and no_active;
-- ----
-- Generate ENABLE_SUBSCRIPTION events for all sets that
-- origin here and are subscribed by the just enabled node.
-- ----
v_local_node_id := getLocalNodeId(&#39;_schemadoc&#39;);
for v_sub_row in select SUB.sub_set, SUB.sub_provider from
sl_set S,
sl_subscribe SUB
where S.set_origin = v_local_node_id
and S.set_id = SUB.sub_set
and SUB.sub_receiver = p_no_id
for update of S
loop
perform enableSubscription (v_sub_row.sub_set,
v_sub_row.sub_provider, p_no_id);
end loop;
return p_no_id;
end;</programlisting>
</para>
</section>
<!-- Function enablesubscription( integer, integer, integer ) -->
<section id="function.enablesubscription-integer-integer-integer"
xreflabel="schemadocenablesubscription( integer, integer, integer )">
<title id="function.enablesubscription-integer-integer-integer-title">
enablesubscription( integer, integer, integer )
</title>
<titleabbrev> id="function.enablesubscription-integer-integer-integer-titleabbrev">
enablesubscription( integer, integer, integer )
</titleabbrev>
<para>
<segmentedlist>
<title>Propriétés de la fonction</title>
<?dbhtml list-presentation="list"?>
<segtitle>Langage</segtitle>
<segtitle>Type du code retour</segtitle>
<seglistitem>
<seg>PLPGSQL</seg>
<seg>integer</seg>
</seglistitem>
</segmentedlist>
Indique que sub_receiver a pout but d'abonner à l'ensemble sub_set à partir
de sub_provider. Tout le travail est fait par la fonction interne
enableSubscription_int (sub_set, sub_provider, sub_receiver).
<programlisting>declare
p_sub_set alias for $1;
p_sub_provider alias for $2;
p_sub_receiver alias for $3;
begin
return enableSubscription_int (p_sub_set,
p_sub_provider, p_sub_receiver);
end;</programlisting>
</para>
</section>
<!-- Function enablesubscription_int( integer, integer, integer ) -->
<section id="function.enablesubscription-int-integer-integer-integer"
xreflabel="schemadocenablesubscription_int( integer, integer, integer )">
<title id="function.enablesubscription-int-integer-integer-integer-title">
enablesubscription_int( integer, integer, integer )
</title>
<titleabbrev> id="function.enablesubscription-int-integer-integer-integer-titleabbrev">
enablesubscription_int( integer, integer, integer )
</titleabbrev>
<para>
<segmentedlist>
<title>Propriétés de la fonction</title>
<?dbhtml list-presentation="list"?>
<segtitle>Langage</segtitle>
<segtitle>Type du code retour</segtitle>
<seglistitem>
<seg>PLPGSQL</seg>
<seg>integer</seg>
</seglistitem>
</segmentedlist>
Fonction interne pour activer l'abonnement du n&oelig;ud sub_receiver pour
configurer sub_set via le n&oelig;ud sub_provider.
slon fait une grosse partie du travail&nbsp;; tout ce que nous avons besoin
de faire ici est de nous rappeler que cela est survenu. La fonction met à
jour sl_subscribe, indiquant que l'abonnement est devenu actif.
<programlisting>declare
p_sub_set alias for $1;
p_sub_provider alias for $2;
p_sub_receiver alias for $3;
v_n int4;
begin
-- ----
-- Grab the central configuration lock
-- ----
lock table sl_config_lock;
-- ----
-- The real work is done in the replication engine. All
-- we have to do here is remembering that it happened.
-- ----
-- ----
-- Well, not only ... we might be missing an important event here
-- ----
if not exists (select true from sl_path
where pa_server = p_sub_provider
and pa_client = p_sub_receiver)
then
insert into sl_path
(pa_server, pa_client, pa_conninfo, pa_connretry)
values
(p_sub_provider, p_sub_receiver,
&#39;&lt;event pending&gt;&#39;, 10);
end if;
update sl_subscribe
set sub_active = &#39;t&#39;
where sub_set = p_sub_set
and sub_receiver = p_sub_receiver;
get diagnostics v_n = row_count;
if v_n = 0 then
insert into sl_subscribe
(sub_set, sub_provider, sub_receiver,
sub_forward, sub_active)
values
(p_sub_set, p_sub_provider, p_sub_receiver,
false, true);
end if;
-- Rewrite sl_listen table
perform RebuildListenEntries();
return p_sub_set;
end;</programlisting>
</para>
</section>
<!-- Function failednode( integer, integer ) -->
<section id="function.failednode-integer-integer"
xreflabel="schemadocfailednode( integer, integer )">
<title id="function.failednode-integer-integer-title">
failednode( integer, integer )
</title>
<titleabbrev> id="function.failednode-integer-integer-titleabbrev">
failednode( integer, integer )
</titleabbrev>
<para>
<segmentedlist>
<title>Propriétés de la fonction</title>