Christopher B. Browne's Home Page
cbbrowne@acm.org

7.7. Embedding Slonik in Shell Scripts

As mentioned earlier, there are numerous Slony-I test scripts in src/ducttape that embed the generation of Slonik inside the shell script.

They mostly don't do this in a terribly sophisticated way. Typically, they use the following sort of structure:

    DB1=slony_test1
    DB2=slony_test2
    slonik <<_EOF_
    	cluster name = T1;
    	node 1 admin conninfo = 'dbname=$DB1';
    	node 2 admin conninfo = 'dbname=$DB2';
    
    	try {
    		create set (id = 1, origin = 1, comment = 
                                'Set 1 - pgbench tables');
    		set add table (set id = 1, origin = 1,
    			id = 1, fully qualified name = 'public.accounts',
    			comment = 'Table accounts');
    		set add table (set id = 1, origin = 1,
    			id = 2, fully qualified name = 'public.branches',
    			comment = 'Table branches');
    		set add table (set id = 1, origin = 1,
    			id = 3, fully qualified name = 'public.tellers',
    			comment = 'Table tellers');
    		set add table (set id = 1, origin = 1,
    			id = 4, fully qualified name = 'public.history',
    			comment = 'Table accounts');
    	}
    	on error {
    		exit 1;
    	}
    _EOF_

A more sophisticated approach might involve defining some common components, notably the "preamble" that consists of the SLONIK CLUSTER NAME(7) SLONIK ADMIN CONNINFO(7) commands that are common to every Slonik script, thus:

    CLUSTER=T1
    DB1=slony_test1
    DB2=slony_test2
    PREAMBLE="cluster name = $CLUSTER
    node 1 admin conninfo = 'dbname=$DB1';
    node 2 admin conninfo = 'dbname=$DB2';
    "

The PREAMBLE value could then be reused over and over again if the shell script invokes slonik multiple times. You might also consider using SLONIK INCLUDE(7) and place the preamble in a file that is included.

Shell variables provide a simple way to assign names to sets and nodes:

    origin=1
    subscriber=2
    mainset=1
    slonik <<_EOF_
    $PREAMBLE
    try {
    	create set (id = $mainset, origin = $origin, 
                        comment = 'Set $mainset - pgbench tables');
    	set add table (set id = $mainset, origin = $origin,
    		id = 1, fully qualified name = 'public.accounts',
    		comment = 'Table accounts');
    	set add table (set id = $mainset, origin = $origin,
    		id = 2, fully qualified name = 'public.branches',
    		comment = 'Table branches');
    	set add table (set id = $mainset, origin = $origin,
    		id = 3, fully qualified name = 'public.tellers',
    		comment = 'Table tellers');
    	set add table (set id = $mainset, origin = $origin,
    		id = 4, fully qualified name = 'public.history',
    		comment = 'Table accounts');
    } on error {
    	exit 1;
    }
    _EOF_

The script might be further enhanced to loop through the list of tables as follows:

    # Basic configuration
    origin=1
    subscriber=2
    mainset=1
    # List of tables to replicate
    TABLES="accounts branches tellers history"
    ADDTABLES=""
    tnum=1
    for table in `echo $TABLES`; do
      ADDTABLES="$ADDTABLES
       set add table ($set id = $mainset, origin = $origin,
       id = $tnum, fully qualified name = 'public.$table',
       comment = 'Table $tname');
    "
      let "tnum=tnum+1"
    done
    slonik <<_EOF_
    $PREAMBLE
    try {
    	create set (id = $mainset, origin = $origin, 
                        comment = 'Set $mainset - pgbench tables');
    $ADDTABLES
    } on error {
    	exit 1;
    }
    _EOF_

That is of somewhat dubious value if you only have 4 tables, but eliminating errors resulting from enumerating large lists of configuration by hand will make this pretty valuable for the larger examples you'll find in "real life."

You can do even more sophisticated things than this if your scripting language supports things like:

If you can depend on having Bash, zsh, or Korn shell available, well, those are all shells with extensions supporting reasonably sophisticated data structures and module systems. On Linux, Bash is fairly ubiquitous; on commercial UNIX™, Korn shell is fairly ubiquitous; on BSD, "sophisticated" shells are an option rather than a default.

At that point, it makes sense to start looking at other scripting languages, of which Perl is the most ubiquitous, being widely available on Linux, UNIX™, and BSD.

Google
Contact me at cbbrowne@acm.org