#!/bin/perl5
# GenRepDefs.pl, a script to generate RepDefs and Subscriptions for a 
# database. Ashu Joglekar, Oct 6th 1995. Hacked from 
# dbschema.pl	A script to extract a database structure from
#		a Sybase database
#
# Written by:	Michael Peppler (mpeppler@itf.ch)
# Last Mods:    22 Feb 1994
#
# Usage:	GenRepDefs.pl -d database -o script.name -t pattern -s server -v -u user
#		    where   database is self-explanatory (default: master)
#                           script.name is the output file (default: script.isql)
#                           pattern is the pattern of object names (in sysobjects)
#                           that we will look at (default: %), user is the sybase login
#                           id to use (defaults to uid running the program) and server is
#			    the server to connect to (default, the value of $ENV{DSQUERY}).
#
#		    -v turns on a verbose switch.
#
#------------------------------------------------------------------------------


use Sybase::Sybperl;
require 'getopts.pl';
require 'ctime.pl';

@nul = ('not null','null');

select(STDOUT); $| = 1;		# make unbuffered

do Getopts('u:d:t:o:s:v');

$opt_u = `whoami` unless $opt_u;
$opt_d = 'master' unless $opt_d;
$opt_o = $opt_d unless $opt_o;
$opt_t = '%' unless $opt_t;
$opt_s = $ENV{DSQUERY} unless $opt_s;

open(REPDEFS, "> $opt_o.RepDefs") 
    || die "Can't open $opt_o.RepDefs: $!\n";
open(SUBSCRIPTIONS, "> $opt_o.Subscriptions") 
    || die "Can't open $opt_o.Subscriptions: $!\n";
open(LOG, "> $opt_o.log") || die "Can't open $opt_o.log: $!\n";

#
# Log us in to Sybase as '$opt_u' and prompt for password.
#
print "\nPassword: ";
system("stty -echo");
chop($sapw = <>);
system("stty echo");

$dbproc = &dblogin("$opt_u", $sapw, $opt_s);
&dbuse($dbproc, $opt_d);

chop($date = &ctime(time));

print "\nGenRepDefs.pl on Database $opt_d\n";

print LOG "Error log from GenRepDefs.pl on Database $opt_d on $date\n\n";
print LOG "The following objects cannot be reliably created from the script in 
$opt_o.
Please correct the script to remove any inconsistencies.\n\n";

print REPDEFS
    "/* This Isql script was generated by GenRepDefs.pl on $date.*/\n";

&dbcmd($dbproc, "select o.name,u.name, o.id\n");
&dbcmd($dbproc, "from $opt_d.dbo.sysobjects o, $opt_d.dbo.sysusers u\n");
&dbcmd($dbproc, "where o.type = 'U' and o.name like '$opt_t' and u.uid = 
o.uid\n");
&dbcmd($dbproc, "order by o.name\n");

&dbsqlexec($dbproc);
&dbresults($dbproc);

while((@dat = &dbnextrow($dbproc)))
{
    $_ = join('@', @dat);	# join the data together on a line
    push(@tables,$_);		# and save it in a list
}


foreach (@tables)		# For each line in the list
{
    @tab = split(/@/, $_);

    print "Processing table $tab[0], owner $tab[1]\n" if $opt_v;

    print REPDEFS "/* Start of RepDef of table $tab[1].$tab[0] */\n\n";

    &dbcmd($dbproc, "select Column_name = c.name, \n");
    &dbcmd($dbproc, "       Type = t.name, \n");
    &dbcmd($dbproc, "       Length = c.length, \n");
    &dbcmd($dbproc, "       Prec = c.prec, \n");
    &dbcmd($dbproc, "       Scale = c.scale, \n");
    &dbcmd($dbproc, "       Nulls = convert(bit, (c.status & 8)),\n");
    &dbcmd($dbproc, "       Default_name = object_name(c.cdefault),\n");
    &dbcmd($dbproc, "       Rule_name = object_name(c.domain),\n");
    &dbcmd($dbproc, "       Ident = convert(bit, (c.status & 0x80)) ");
    &dbcmd($dbproc, "from   $opt_d.dbo.syscolumns c, $opt_d.dbo.systypes t\n");
    &dbcmd($dbproc, "where  c.id = $tab[2]\n");
    &dbcmd($dbproc, "and    c.usertype *= t.usertype\n");

    &dbsqlexec($dbproc);
    &dbresults($dbproc);

    undef(%rule);
    undef(%dflt);

    # I am prepending a US_ ( needed for my environment )
    print REPDEFS "\n\nCREATE REPLICATION DEFINITION US_$tab[0]_repdef\n"; 
    print REPDEFS "with primary at $opt_s.$opt_d\n";
    print REPDEFS "with all tables named '$tab[0]'\n(";
    $first = 1;
    while((@field = &dbnextrow($dbproc)))
    {
        print REPDEFS ",\n" if !$first; # add a , and a \n if not first field in table
        
	# Check if its an identity column
	if ( $field[8] != 1 )
	{	
        	print REPDEFS "\t$field[0] \t$field[1]";
        	print REPDEFS "($field[2])" if $field[1] =~ /char|bin/;
        	print REPDEFS "($field[3],$field[4])" if $field[1] =~ /numeric/;
        	$first = 0 if $first;
	} 
	else {
        	print REPDEFS "\t$field[0] \t$field[1]($field[3], $field[4])\tidentity";
        	$first = 0 if $first;
	}
    }
    print REPDEFS "\n)\n";

# now get the indexes so we can figure out the primary key
#
    print "Indexes for table $tab[1].$tab[0]\n" if $opt_v;
    
    &dbcmd($dbproc, "sp_helpindex '$tab[1].$tab[0]'\n");

    &dbsqlexec($dbproc);
    &dbresults($dbproc);

    $FoundPrimaryKey = 0;
    while((@field = &dbnextrow($dbproc)))
    {
	# Important !!!
	# Assume that the first unique index found is the primary key

	if ( $field[1] =~ /unique/ )
	{
	    $FoundPrimaryKey = 1;
	    @col = split(/,/,$field[2]);
	    print REPDEFS "\nprimary key (";
	    $first = 1;
	    foreach (@col)
	    {
		print REPDEFS ", " if !$first;
		$first = 0;
		print REPDEFS "$_";
	    }
	    print REPDEFS ")\n";
	}
    }

    if ( $FoundPrimaryKey != 1 )
    {
	print LOG "Error! Table $tab[1].$tab[0] has no primary key !!\n";
	print "Error! Table $tab[1].$tab[0] has no primary key !!\n" if $opt_v;
    }

    # I like to replicate minimal columns. If you do this you cannot use non-atomic
    # or bulk materialisation
    print REPDEFS "replicate minimal columns\ngo\n";

    # Write out the create subscription command
    # You will have to plug in the correct RRS name here. Too many 
    # command line options :-)

    print SUBSCRIPTIONS "CREATE SUBSCRIPTION $tab[0]_sub\n";
    print SUBSCRIPTIONS "for US_$tab[0]_repdef\n";
    print SUBSCRIPTIONS "with replicate at UK_LTCM_FDDI.$opt_d\n";
    print SUBSCRIPTIONS "incrementally\ngo\n";
}

print "Done\n";

print "\nLooks like I'm all done!\n";
close(REPDEFS);
close(SUBSCRIPTIONS);
close(LOG);

&dbexit;
exit;
