#!/usr/bin/perl -w # # $Id: genSubCmp.pl,v 1.2 2003/01/15 16:29:50 mpeppler Exp $ # # Generate configuration files for rs_subcmp. use strict; use Sybase::Simple; use Getopt::Long; use Data::Dumper; my %opts; GetOptions(\%opts, "pds=s", "rds=s", "db=s", "user=s", "pwd=s"); usage() unless $opts{pds} && $opts{rds} && $opts{db}; my $pds = $opts{pds}; my $rds = $opts{rds}; my $db = $opts{db}; my $usr = $opts{user} || 'sa'; my $pwd = $opts{pwd}; # First, select all the tables from the source data server: my $pds_dbh = new Sybase::Simple $usr, $pwd, $pds; $pds_dbh->ExecSql("use $db"); my $source_tables = $pds_dbh->ArrayOfScalar(" select name from sysobjects where type = 'U' and sysstat2 & 1024 != 1024 and name not in ('rs_lastcommit', 'rs_threads') "); # Find tables in the target my $rds_dbh = new Sybase::Simple $usr, $pwd, $pds; $rds_dbh->ExecSql("use $db"); my $target_tables = $rds_dbh->ArrayOfScalar(" select name from sysobjects where type = 'U' and sysstat2 & 1024 != 1024 "); # There's no point trying to run rs_subcmp unless the tables exist # in both the source and the target, so find out the intersection # of the two lists of tables: my %tables = map { $_ => 1 } @$source_tables; grep($tables{$_}++, @$target_tables); # Now the %tables hash will have one entry for all the tables, but the # value will be 2 if the table exists in both servers. foreach my $tab (sort(keys(%tables))) { next if $tables{$tab} < 2; genSubCmp($pds_dbh, $tab); } sub genSubCmp { my $dbh = shift; my $tab = shift; warn "Processing $tab\n"; my $cols = $dbh->ArrayOfHash(" select Column_name = c.name, Type = t.name, Nulls = convert(bit, (c.status & 8)), Ident = convert(bit, (c.status & 0x80)) from syscolumns c, systypes t where c.id = object_id('$tab') and c.usertype *= t.usertype "); # print Dumper($cols) if $tab eq 'Notes'; # Use the first unique index as the primary key. my $indexes = $dbh->ArrayOfArray("sp_helpindex $tab"); my @keys; foreach my $ix (@$indexes) { if($ix->[1] =~ /unique/) { @keys = split(/\s*,\s*/, $ix->[2]); last; } } if(!@keys) { warn "Can't find primary key for $tab, skipping"; return -1; } open(OUT, ">${tab}_subcmp.cfg") || die "Can't open ${tab}_subcmp.cfg: $!"; print OUT "# rs_subcmp configuration file for $tab\n"; print OUT "PDS = $pds\n"; print OUT "RDS = $rds\n"; print OUT "PDB = $db\n"; print OUT "RDB = $db\n"; print OUT "PTABLE = $tab\n"; print OUT "RTABLE = $tab\n"; my $select = buildSelect($tab, \@keys, $cols); print OUT "RSELECT = $select\n"; print OUT "PSELECT = $select\n"; print OUT "PUSER = sa\n"; print OUT "RUSER = sa\n"; print OUT "PPWD = funky\n"; # XXX - FIXME print OUT "RPWD = funky\n"; foreach (@keys) { print OUT "KEY = $_\n"; } print OUT "RCHARSET = utf8\n"; print OUT "SCHARSET = utf8\n"; print OUT "SORT_ORDER = nocase\n"; print OUT "SORT_ORDER_ALL_COLS = nocase\n"; print OUT "UNICODE_SORT_ORDER = nocase\n"; print OUT "UNICODE_SORT_ORDER_ALL_COLS = nocase\n"; print OUT "RECONCILE = N\n"; print OUT "RECONCILE_CHECK = N\n"; print OUT "VISUAL = N\n"; foreach (@$cols) { if($_->{Ident}) { print OUT "IDENTITY = $_->{Column_name}\n"; } } close(OUT); } sub buildSelect { my $tab = shift; my $keys = shift; my $cols = shift; my $sql = 'select '; # print Dumper($cols); foreach (@$cols) { next if ($_->{Type} eq 'text' || $_->{Type} eq 'image' || $_->{Type} eq 'timestamp'); # print Dumper($_); $sql .= "$_->{Column_name}, "; } foreach (@$cols) { next unless ($_->{Type} eq 'text' || $_->{Type} eq 'image'); # print Dumper($_); $sql .= "$_->{Column_name}, "; } $sql =~ s/,\s+$//; $sql .= " from $tab order by "; $sql .= join(',', @$keys); return $sql; } sub usage { die "Usage: $0 --pds --rds --db [--user ] [--pwd ]\n"; }