home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume30 / sybperl / patch05 next >
Text File  |  1992-07-06  |  30KB  |  1,046 lines

  1. Newsgroups: comp.sources.misc
  2. From: mpeppler@itf0.itf.ch (Michael Peppler)
  3. Subject:  v30i092:  sybperl - Sybase DB-library extensions to Perl, Patch05
  4. Message-ID: <1992Jun29.191350.15676@sparky.imd.sterling.com>
  5. X-Md4-Signature: 62f0fcc21bb10fc68d45cc3c9f490f57
  6. Date: Mon, 29 Jun 1992 19:13:50 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: mpeppler@itf0.itf.ch (Michael Peppler)
  10. Posting-number: Volume 30, Issue 92
  11. Archive-name: sybperl/patch05
  12. Environment: UNIX, Perl, Sybase
  13. Patch-To: sybperl: Volume 28, Issue 33
  14.  
  15. This is patch 5 to Sybperl, a set of Sybase DB-Library extensions to Perl.
  16. Note that Sybperl was posted at patchlevel 4.
  17.  
  18. >From the CHANGES file:
  19.      1.005   Sybperl would core dump if you used a uninitialized
  20.              DBPROCESS.
  21.          A solution to the sometime pathological    memory usage
  22.          observed when using a release of Perl lower than 4.035
  23.          is also described in BUGS.
  24.          &dblogin now returns -1 if the dblogin() or dbopen()
  25.          calls fail.
  26.          Added the possibility to login to a specific server
  27.          without setting the DSQUERY environment variable.
  28.          Added a script to extract the information regarding
  29.          the database from the databases' system tables. See
  30.          eg/dbschema.pl.
  31.  
  32. Apply the patch with 
  33.     patch -p1 -N <patch
  34.  -- 
  35. Michael Peppler                 mpeppler@itf.ch {uunet,mcsun}!chsun!itf1!mpeppler
  36. ITF Management SA            BIX:   mpeppler                         
  37. 13 Rue de la Fontaine        Phone: (+4122) 312 1311  
  38. CH-1204 Geneva, Switzerland  Fax:   (+4122) 312 1322  
  39.  
  40. -----------------  snip       snip  --------------------------
  41.  
  42. diff -c -r ./BUGS /usr/local/src/perl/sybase/dist-1.5/BUGS
  43. *** ./BUGS    Wed Jun 24 13:37:32 1992
  44. --- /usr/local/src/perl/sybase/dist-1.5/BUGS    Thu Jun 25 13:18:07 1992
  45. ***************
  46. *** 41,44 ****
  47.       Thanks to Teemu Torma for providing the initial input on this problem.    
  48.   
  49.   
  50. !     Michael
  51. --- 41,105 ----
  52.       Thanks to Teemu Torma for providing the initial input on this problem.    
  53.   
  54.   
  55. !     Sybperl Memory Usage
  56. !     --------------------
  57. !     The general format of a Sybperl script usually looks somewhat like
  58. !     this:
  59. !     #!/usr/local/bin/sybperl
  60. !     &dbcmd( query text );
  61. !     &dbsqlexec;
  62. !     &dbresults;
  63. !     while(@data = &dbnextrow)
  64. !     {
  65. !        process data
  66. !     }
  67. !     If you are using a version of Perl prior to release 4, patchlevel
  68. !     35, then this method will result in a rather important memory
  69. !     leak. There are two ways around this problem:
  70. !     1) Upgrade to Perl 4, patchlevel 35 :-)
  71. !     2) Write a subroutine that calls &dbnextrow and stores the returned
  72. !        array to a local variable, and which in turn returns that array to
  73. !        the main while() loop, like so:
  74. !     sub getRow
  75. !     {
  76. !         local(@data);
  77. !     @data = &dbnextrow;
  78. !     @data;
  79. !     }
  80. !     while(@data = &getRow)
  81. !     {
  82. !        etc.
  83. !     }
  84. !     This technique should keep the memory usage of Sybperl to a
  85. !     manageable level.
  86. !     Please let me know if you find any other problems with Sybperl so
  87. !     that I can look into it.
  88. !     Thank you.
  89. !     Michael Peppler    <mpeppler@itf.ch>
  90. !     
  91. diff -c -r ./CHANGES /usr/local/src/perl/sybase/dist-1.5/CHANGES
  92. *** ./CHANGES    Wed Jun 24 13:37:32 1992
  93. --- /usr/local/src/perl/sybase/dist-1.5/CHANGES    Thu Jun 25 13:18:08 1992
  94. ***************
  95. *** 1,6 ****
  96.       Sybperl CHANGES:
  97.   
  98. !     
  99.       1.004    Added support for Perl based error and message
  100.           handlers (as made possible by Perl 4.018). Many Thanks
  101.           to Teemu Torma for this code.
  102. --- 1,18 ----
  103.       Sybperl CHANGES:
  104.   
  105. !     1.005   Sybperl would core dump if you used a uninitialized
  106. !             DBPROCESS.
  107. !         A solution to the sometime pathological    memory usage
  108. !         observed when using a release of Perl lower than 4.035
  109. !         is also described in BUGS.
  110. !         &dblogin now returns -1 if the dblogin() or dbopen()
  111. !         calls fail.
  112. !         Added the possibility to login to a specific server
  113. !         without setting the DSQUERY environment variable.
  114. !         Added a script to extract the information regarding
  115. !         the database from the databases' system tables. See
  116. !         eg/dbschema.pl.
  117.       1.004    Added support for Perl based error and message
  118.           handlers (as made possible by Perl 4.018). Many Thanks
  119.           to Teemu Torma for this code.
  120. ***************
  121. *** 13,15 ****
  122. --- 25,28 ----
  123.           Added a couple of example scripts in eg/*.pl, courtesy
  124.           of Gijs Mos (Thank You!).
  125.       1.003    Base version.
  126. diff -c -r ./Makefile /usr/local/src/perl/sybase/dist-1.5/Makefile
  127. *** ./Makefile    Wed Jun 24 13:37:32 1992
  128. --- /usr/local/src/perl/sybase/dist-1.5/Makefile    Thu Jun 25 13:18:09 1992
  129. ***************
  130. *** 1,7 ****
  131. ! #    @(#)Makefile    1.6    11/25/91
  132.   #
  133.       
  134. ! CC = cc
  135.   PERLSRC = ..                # where to find uperl.o
  136.   SYBINCS = /usr/local/sybase/include    # where to find the sybase .h files
  137.   LOCINCS =                # other includes ?
  138. --- 1,7 ----
  139. ! #    @(#)Makefile    1.10    6/25/92
  140.   #
  141.       
  142. ! CC = gcc
  143.   PERLSRC = ..                # where to find uperl.o
  144.   SYBINCS = /usr/local/sybase/include    # where to find the sybase .h files
  145.   LOCINCS =                # other includes ?
  146. ***************
  147. *** 44,50 ****
  148.                       # not possible without this, however.
  149.   OLD_SYBPERL= -DOLD_SYBPERL        # some backward compatibility stuff.                    
  150.   
  151. ! CFLAGS = -O                 # 
  152.   CPPFLAGS = -I$(PERLSRC) -I$(LOCINCS) -I$(SYBINCS) $(PERL_VERSION) \
  153.           $(SAVESTR) $(HAS_CALLBACK) $(OLD_SYBPERL)
  154.   BINDIR = /usr/local/bin            # where does the executable go
  155. --- 44,50 ----
  156.                       # not possible without this, however.
  157.   OLD_SYBPERL= -DOLD_SYBPERL        # some backward compatibility stuff.                    
  158.   
  159. ! CFLAGS = -O2 -funroll-loops                 # 
  160.   CPPFLAGS = -I$(PERLSRC) -I$(LOCINCS) -I$(SYBINCS) $(PERL_VERSION) \
  161.           $(SAVESTR) $(HAS_CALLBACK) $(OLD_SYBPERL)
  162.   BINDIR = /usr/local/bin            # where does the executable go
  163. ***************
  164. *** 65,70 ****
  165. --- 65,72 ----
  166.   $(UPERL): $(PERLSRC)/uperl.o
  167.       cp $(PERLSRC)/uperl.o $(UPERL)
  168.       perl -p -i.bak -e 's/savestr/psvestr/g;' $(UPERL)
  169. +     rm -f $(UPERL).bak
  170. +     
  171.   
  172.   clean:
  173.       rm -f sybperl *.o *~ core
  174. ***************
  175. *** 78,84 ****
  176.       rm -f sybperl.shar
  177.       shar.pl README PACKING.LST BUGS CHANGES Makefile sybperl.c \
  178.       sybperl.1 patchlevel.h lib/sybperl.pl lib/sybdb.ph t/sbex.pl \
  179. !     eg/sql.pl eg/space.pl eg/capture.pl eg/report.pl >sybperl.shar
  180.   
  181.   
  182.   
  183. --- 80,97 ----
  184.       rm -f sybperl.shar
  185.       shar.pl README PACKING.LST BUGS CHANGES Makefile sybperl.c \
  186.       sybperl.1 patchlevel.h lib/sybperl.pl lib/sybdb.ph t/sbex.pl \
  187. !     eg/sql.pl eg/space.pl eg/capture.pl eg/report.pl \
  188. !     eg/dbschema.pl eg/README >sybperl.shar
  189. ! tar:
  190. !     rm -f sybperl.tar
  191. !     tar cvfB sybperl.tar README PACKING.LST BUGS CHANGES Makefile sybperl.c \
  192. !     sybperl.1 patchlevel.h lib/sybperl.pl lib/sybdb.ph t/sbex.pl \
  193. !     eg/sql.pl eg/space.pl eg/capture.pl eg/report.pl \
  194. !     eg/dbschema.pl eg/README
  195.   
  196.   
  197.   
  198. diff -c -r ./PACKING.LST /usr/local/src/perl/sybase/dist-1.5/PACKING.LST
  199. *** ./PACKING.LST    Wed Jun 24 13:37:33 1992
  200. --- /usr/local/src/perl/sybase/dist-1.5/PACKING.LST    Thu Jun 25 13:18:06 1992
  201. ***************
  202. *** 20,23 ****
  203. --- 20,30 ----
  204.           eg/capture.pl   Create a table extracted from /etc/passwd
  205.           eg/report.pl    Report from table created by capture.pl
  206.           eg/sql.pl        Utility routines used by the above example programs.
  207. +         eg/dbschema.pl  Create an Isql script that will to
  208. +                         recreate your database(s) structure (data
  209. +                 types, tables, indexes, rules, defaults,
  210. +                 views, triggers and stored procedures),
  211. +                 extracting the information from the
  212. +                 database's system tables.
  213.           
  214. diff -c -r ./README /usr/local/src/perl/sybase/dist-1.5/README
  215. *** ./README    Wed Jun 24 13:37:31 1992
  216. --- /usr/local/src/perl/sybase/dist-1.5/README    Thu Jun 25 13:18:06 1992
  217. ***************
  218. *** 45,51 ****
  219.      Pyramid MIServer 2/2, OSx V5.1a, Sybase 4.0, Perl 4.010
  220.      
  221.      I use sybperl daily in a production environment on a Sun 4/65 under
  222. !    SunOS 4.1.1, with Sybase version 4.0.1 and Perl 4.019
  223.   
  224.      BUGS:
  225.   
  226. --- 45,51 ----
  227.      Pyramid MIServer 2/2, OSx V5.1a, Sybase 4.0, Perl 4.010
  228.      
  229.      I use sybperl daily in a production environment on a Sun 4/65 under
  230. !    SunOS 4.1.1, with Sybase version 4.0.1 and Perl 4.035
  231.   
  232.      BUGS:
  233.   
  234. ***************
  235. *** 52,57 ****
  236. --- 52,60 ----
  237.      There seems to be a major incompatibility between Perl and
  238.      DB-Library, but I've been able to code around it. See the BUGS file
  239.      for details.
  240. +    Memory usage can also be a problem in certain cases. Again see the
  241. +    BUGS file for details.
  242.   
  243.   
  244.   
  245. Common subdirectories: ./eg and /usr/local/src/perl/sybase/dist-1.5/eg
  246. Common subdirectories: ./lib and /usr/local/src/perl/sybase/dist-1.5/lib
  247. diff -c -r ./patchlevel.h /usr/local/src/perl/sybase/dist-1.5/patchlevel.h
  248. *** ./patchlevel.h    Wed Jun 24 13:37:36 1992
  249. --- /usr/local/src/perl/sybase/dist-1.5/patchlevel.h    Thu Jun 25 13:18:11 1992
  250. ***************
  251. *** 1,4 ****
  252.   #define VERSION 1
  253. ! #define PATCHLEVEL 4
  254.   
  255.   
  256. --- 1,4 ----
  257.   #define VERSION 1
  258. ! #define PATCHLEVEL 5
  259.   
  260.   
  261. diff -c -r ./sybperl.1 /usr/local/src/perl/sybase/dist-1.5/sybperl.1
  262. *** ./sybperl.1    Wed Jun 24 13:37:37 1992
  263. --- /usr/local/src/perl/sybase/dist-1.5/sybperl.1    Thu Jun 25 13:18:11 1992
  264. ***************
  265. *** 1,5 ****
  266.   .\".po 4
  267. ! .TH SYBPERL 1 "3 September 1991"
  268.   .ad
  269.   .nh
  270.   .SH NAME
  271. --- 1,5 ----
  272.   .\".po 4
  273. ! .TH SYBPERL 1 "24 June 1992"
  274.   .ad
  275.   .nh
  276.   .SH NAME
  277. ***************
  278. *** 6,13 ****
  279.   sybperl \- Perl access to Sybase databases
  280.   .SH SYNOPSIS
  281.   .nf
  282. ! $dbproc  = &dblogin([$user[, $pwd]])
  283. ! $dbproc1 = &dbopen()
  284.          &dbclose($dbproc)
  285.   $ret     = &dbcmd($dbproc, $sql_cmd)
  286.   $ret     = &dbsqlexec($dbproc)
  287. --- 6,13 ----
  288.   sybperl \- Perl access to Sybase databases
  289.   .SH SYNOPSIS
  290.   .nf
  291. ! $dbproc  = &dblogin([$user[, $pwd[, $server]]])
  292. ! $dbproc1 = &dbopen([$server])
  293.          &dbclose($dbproc)
  294.   $ret     = &dbcmd($dbproc, $sql_cmd)
  295.   $ret     = &dbsqlexec($dbproc)
  296. ***************
  297. *** 40,47 ****
  298.   The following functions are provided:
  299.   
  300.   .nf
  301. ! \fB$dbproc  = &dblogin([$user[, $pwd]])\fP
  302. ! \fB&dbproc1 = &dbopen()\fP
  303.   \fB          &dbclose($dbproc)\fP
  304.   \fB$status  = &dbcmd($dbproc, $sql_cmd)\fP
  305.   \fB$status  = &dbsqlexec($dbproc)\fP
  306. --- 40,47 ----
  307.   The following functions are provided:
  308.   
  309.   .nf
  310. ! \fB$dbproc  = &dblogin([$user[, $pwd[, $server]]])\fP
  311. ! \fB&dbproc1 = &dbopen([$server])\fP
  312.   \fB          &dbclose($dbproc)\fP
  313.   \fB$status  = &dbcmd($dbproc, $sql_cmd)\fP
  314.   \fB$status  = &dbsqlexec($dbproc)\fP
  315. ***************
  316. *** 58,70 ****
  317.   
  318.   Differences with DB-Library:
  319.   
  320. ! \fB&dblogin\fP takes 2 optional arguements (the userid and the
  321. ! password). These default to the Unix userid, and the null password.
  322.   
  323.   \fB&dblogin\fP returns a \fBDBPROCESS\fP, not a \fBLOGINREC\fP. This
  324.   simplifies the call to open a connection to a Sybase dataserver
  325. ! somewhat. Further \fBDBPROCESSes\fP can be opened using
  326. ! \fB&dbopen()\fP (No arguments). The number of simultaneous DBPROCESSes
  327.   is limited to 25 (This can be changed by altering a #define in sybperl.c).
  328.   
  329.   The \fB$dbproc\fP parameter is optional, and defaults to the DBPROCESS returned
  330. --- 58,73 ----
  331.   
  332.   Differences with DB-Library:
  333.   
  334. ! \fB&dblogin\fP takes 3 optional arguements (the userid, the
  335. ! password and the server to connect to). These default to the Unix
  336. ! userid, the null password and the default server (from the DSQUERY
  337. ! environment variable).
  338.   
  339.   \fB&dblogin\fP returns a \fBDBPROCESS\fP, not a \fBLOGINREC\fP. This
  340.   simplifies the call to open a connection to a Sybase dataserver
  341. ! somewhat. If the login fails for any reason \fB&dblogin\fP returns -1.
  342. ! Further \fBDBPROCESSes\fP can be opened using
  343. ! \fB&dbopen([$server])\fP (with an optional server name to connect to). The number of simultaneous DBPROCESSes
  344.   is limited to 25 (This can be changed by altering a #define in sybperl.c).
  345.   
  346.   The \fB$dbproc\fP parameter is optional, and defaults to the DBPROCESS returned
  347. ***************
  348. *** 85,98 ****
  349.   \fB&dbfcmd\fP is not implemented, but can be emulated by using
  350.   \fIsprintf\fP as in \fI&dbcmd($dbproc, sprintf("%d", $num_val))\;\fP
  351.   
  352. - One cannot log in to a specific server (ie \fIdbopen()\fP is always
  353. - called with a \fINULL\fP second parameter. However, setting the
  354. - \fBDSQUERY\fP environment variable (as in \fI$ENV{'DSQUERY'} =
  355. - $server\fP) will work.
  356.   
  357.   .SH OPTIONS
  358.   
  359.   See the \fIPerl(1)\fP manual page.
  360.   
  361.   .SH FILES
  362.   
  363. --- 88,103 ----
  364.   \fB&dbfcmd\fP is not implemented, but can be emulated by using
  365.   \fIsprintf\fP as in \fI&dbcmd($dbproc, sprintf("%d", $num_val))\;\fP
  366.   
  367.   
  368.   .SH OPTIONS
  369.   
  370.   See the \fIPerl(1)\fP manual page.
  371. + .SH BUGS
  372. + Memory usage can become very large in certain conditions when
  373. + using a version of Perl prior to 4.035. This
  374. + can be circumvented - see the BUGS file in the Sybperl distribution.
  375.   
  376.   .SH FILES
  377.   
  378. diff -c -r ./sybperl.c /usr/local/src/perl/sybase/dist-1.5/sybperl.c
  379. *** ./sybperl.c    Wed Jun 24 13:37:37 1992
  380. --- /usr/local/src/perl/sybase/dist-1.5/sybperl.c    Thu Jun 25 13:18:10 1992
  381. ***************
  382. *** 1,6 ****
  383. ! static char SccsId[] = "@(#)sybperl.c    1.9    12/20/91";
  384.   /************************************************************************/
  385. ! /*    Copyright 1991 by Michael Peppler and ITF Management SA     */
  386.   /*                                    */
  387.   /*    Full ownership of this software, and all rights pertaining to     */
  388.   /*    the for-profit distribution of this software, are retained by     */
  389. --- 1,6 ----
  390. ! static char SccsId[] = "@(#)sybperl.c    1.11    6/24/92";
  391.   /************************************************************************/
  392. ! /*    Copyright 1991, 1992 by Michael Peppler and ITF Management SA     */
  393.   /*                                    */
  394.   /*    Full ownership of this software, and all rights pertaining to     */
  395.   /*    the for-profit distribution of this software, are retained by     */
  396. ***************
  397. *** 193,199 ****
  398.   {
  399.       STR **st = stack->ary_array + sp;
  400.       ARRAY *ary = stack;    
  401. -     register int i;
  402.       register STR *Str;        /* used in str_get and str_gnum macros */
  403.       int inx = -1;        /* Index into dbproc[] array. Passed as first parameter to nearly all &dbxxx() calls */
  404.   
  405. --- 193,198 ----
  406. ***************
  407. *** 223,260 ****
  408.       switch (ix)
  409.       {
  410.         case US_dblogin:
  411. !     if (items > 2)
  412. !         fatal("Usage: &dblogin([user[,pwd]])");
  413.       if (login)
  414.           fatal("&dblogin() called twice.");
  415.       else
  416.       {
  417. !         int retval;
  418.   
  419.           login = dblogin();
  420. !         if(items)
  421.           {
  422. !         DBSETLUSER(login, (char *)str_get(STACK(sp)[1]));
  423. !         if(items > 1)
  424. !             DBSETLPWD(login, (char *)str_get(STACK(sp)[2]));
  425.           }
  426.   
  427. !         dbproc[0] = dbopen(login, NULL);
  428. !         str_numset(STACK(sp)[0], (double) 0);
  429.       }
  430.       break;
  431.         case US_dbopen:
  432. !     if (items != 0)
  433. !         fatal("Usage: $dbproc = &dbopen;");
  434.       else
  435.       {
  436.           int j;
  437.           for(j = 0; j < MAX_DBPROCS; ++j)
  438.           if(dbproc[j] == NULL)
  439.               break;
  440.           if(j == MAX_DBPROCS)
  441.           fatal("&dbopen: No more dbprocs available.");
  442. !         dbproc[j] = dbopen(login, NULL);
  443.           str_numset(STACK(sp)[0], (double) j);
  444.       }
  445.       break;
  446. --- 222,275 ----
  447.       switch (ix)
  448.       {
  449.         case US_dblogin:
  450. !     if (items > 3)
  451. !         fatal("Usage: &dblogin([user[,pwd[,server]]])");
  452.       if (login)
  453.           fatal("&dblogin() called twice.");
  454.       else
  455.       {
  456. !         int retval = 0;
  457. !         char *server = NULL, *user = NULL, *pwd = NULL;
  458.   
  459.           login = dblogin();
  460. !         switch(items)
  461.           {
  462. !           case 3:
  463. !         server = (char *)str_get(STACK(sp)[3]);
  464. !           case 2:
  465. !         pwd = (char *)str_get(STACK(sp)[2]);
  466. !         if(pwd && strlen(pwd))
  467. !             DBSETLPWD(login, pwd);
  468. !           case 1:
  469. !         user = (char *)str_get(STACK(sp)[1]);
  470. !         if(user && strlen(user))
  471. !             DBSETLUSER(login, user);
  472.           }
  473. +         
  474. +         
  475. +         if((dbproc[0] = dbopen(login, server)) == NULL)
  476. +         retval = -1;
  477.   
  478. !         str_numset(STACK(sp)[0], (double) retval);
  479.       }
  480.       break;
  481.         case US_dbopen:
  482. !     if (items > 1)
  483. !         fatal("Usage: $dbproc = &dbopen([server]);");
  484.       else
  485.       {
  486.           int j;
  487. +         char *server = NULL;
  488. +         
  489.           for(j = 0; j < MAX_DBPROCS; ++j)
  490.           if(dbproc[j] == NULL)
  491.               break;
  492.           if(j == MAX_DBPROCS)
  493.           fatal("&dbopen: No more dbprocs available.");
  494. !         if(items == 1)
  495. !         server = (char *)str_get(STACK(sp)[1]);
  496. !         
  497. !         dbproc[j] = dbopen(login, server);
  498.           str_numset(STACK(sp)[0], (double) j);
  499.       }
  500.       break;
  501. ***************
  502. *** 951,956 ****
  503. --- 966,973 ----
  504.   
  505.       if(ix < 0 || ix >= MAX_DBPROCS)
  506.       fatal("$dbproc parameter is out of range.");
  507. +     if(dbproc[ix] == NULL || DBDEAD(dbproc[ix]))
  508. +     fatal("$dbproc parameter is NULL or the connection to the server has been closed.");
  509.       return ix;
  510.   }
  511.   
  512. Common subdirectories: ./t and /usr/local/src/perl/sybase/dist-1.5/t
  513. diff -c -r ./eg/README /usr/local/src/perl/sybase/dist-1.5/eg/README
  514. *** ./eg/README    Thu Jun 25 13:16:19 1992
  515. --- /usr/local/src/perl/sybase/dist-1.5/eg/README    Thu Jun 25 13:18:20 1992
  516. ***************
  517. *** 0 ****
  518. --- 1,48 ----
  519. +     @(#)README    1.3    6/25/92
  520. +     This directory contains a number of example scripts for Sybperl.
  521. +     
  522. +     space.pl        Report the space used by your database.
  523. +     capture.pl        Create a table with information from
  524. +             /etc/passwd.
  525. +     report.pl        Report information from the above table.
  526. +     sql.pl        Utility used by the above three scripts.
  527. +     dbschema.pl        Extract an Isql script to re-create a database
  528. +     
  529. +     Dbschema.pl Documentation:
  530. +     --------------------------
  531. +     
  532. +     This is a Sybperl script that extracts a Sybase database definition
  533. +     and creates an Isql script to rebuild the database.
  534. +     dbschema.pl is NOT a production script, in the sense that it does
  535. +     not do ALL the necessary work. The script tries to do the right
  536. +     thing, but in certain cases (mainly where the owner of an object
  537. +     is not the DBO) it creates an invalid or incorrect Isql command. I
  538. +     have tried to detect these cases, and log them both to stdout and to a
  539. +     file, so that the script can be corrected.
  540. +     Please note also that dbschema.pl logs in to Sybase with the
  541. +     default (Unix) user id, and a NULL password. This behaviour is
  542. +     maybe not OK for your site.
  543. +     Usage:
  544. +         itf1% dbschema.pl -d excalibur -o excalibur.isql -v
  545. +     Run dbschema on database 'excalibur', place the resulting script
  546. +     in 'excalibur.isql' (and the error log in 'excalibur.isql.log')
  547. +     and turn on verbose output on the console. The default database is
  548. +     'master', the default output file is 'script.isql'.
  549. +     I hope this will prove of some use, and I would be more than happy
  550. +     to hear of any improvements :-)
  551. +     Michael Peppler        mpeppler@itf.ch
  552. diff -c -r ./eg/capture.pl /usr/local/src/perl/sybase/dist-1.5/eg/capture.pl
  553. *** ./eg/capture.pl    Wed Jun 24 13:37:33 1992
  554. --- /usr/local/src/perl/sybase/dist-1.5/eg/capture.pl    Thu Jun 25 13:18:17 1992
  555. ***************
  556. *** 1,5 ****
  557. --- 1,9 ----
  558.   #! /usr/local/bin/sybperl
  559.   
  560. + #
  561. + #    @(#)capture.pl    1.1    6/24/92
  562. + #
  563.   require "sybperl.pl";
  564.   require "sql.pl";
  565.   
  566. diff -c -r ./eg/dbschema.pl /usr/local/src/perl/sybase/dist-1.5/eg/dbschema.pl
  567. *** ./eg/dbschema.pl    Wed Jun 24 13:38:17 1992
  568. --- /usr/local/src/perl/sybase/dist-1.5/eg/dbschema.pl    Thu Jun 25 13:18:19 1992
  569. ***************
  570. *** 0 ****
  571. --- 1,377 ----
  572. + #! /usr/local/bin/sybperl
  573. + #
  574. + #    @(#)dbschema.pl    1.3    6/24/92
  575. + #
  576. + #
  577. + #    dbschema.pl    A script to extract a database structure from
  578. + #            a Sybase database
  579. + #
  580. + #    Written by:    Michael Peppler (mpeppler@itf.ch)
  581. + #    Last Modified:  24 June 1992
  582. + #
  583. + #    Usage:        dbschema.pl -d database -o script.name -t pattern -v
  584. + #                where   database is self-explanatory (default: master)
  585. + #                                   script.name is the output file (default: script.isql)
  586. + #                                   pattern is the pattern of object names (in sysobjects)
  587. + #                                           that we will look at (default: %)
  588. + #
  589. + #                -v turns on a verbose switch.
  590. + #
  591. + require 'sybperl.pl';
  592. + require 'getopts.pl';
  593. + require 'ctime.pl';
  594. + @nul = ('not null','null');
  595. + select(STDOUT); $| = 1;        # make unbuffered
  596. + do Getopts('d:t:o:v');
  597. + $opt_d = 'master' unless $opt_d;
  598. + $opt_o = 'script.isql' unless $opt_o;
  599. + $opt_t = '%' unless $opt_t;
  600. + open(SCRIPT, "> $opt_o") || die "Can't open $opt_o: $!\n";
  601. + open(LOG, "> $opt_o.log") || die "Can't open $opt_o.log: $!\n";
  602. + #
  603. + # NOTE: We login to Sybase with the default (Unix) user id.
  604. + #       We should probably login as 'SA', and get the passwd
  605. + #       from the user at run time.
  606. + #
  607. + $dbproc = &dblogin;
  608. + &dbuse($dproc, $opt_d);
  609. + chop($date = &ctime(time));
  610. + print "dbschema.pl on Database $opt_d\n";
  611. + print LOG "Error log from dbschema.pl on Database $opt_d on $date\n\n";
  612. + print LOG "The following objects cannot be reliably created from the script in $opt_o.
  613. + Please correct the script to remove any inconsistencies.\n\n";
  614. + print SCRIPT
  615. +     "/* This Isql script was generated by dbschema.pl on $date.
  616. + ** The indexes need to be checked: column names & index names
  617. + ** might be truncated!
  618. + */\n";
  619. + print SCRIPT "\nuse $opt_d\ngo\n"; # Change to the appropriate database
  620. + # first, Add the appropriate user data types:
  621. + #
  622. + print "Add user-defined data types...";
  623. + print SCRIPT
  624. +     "/* Add user-defined data types: */\n\n";
  625. + &dbcmd($dbproc, "select s.length, s.name, st.name,\n");
  626. + &dbcmd($dbproc, "       object_name(s.tdefault),\n");
  627. + &dbcmd($dbproc, "       object_name(s.domain)\n");
  628. + &dbcmd($dbproc, "from   $opt_d.dbo.systypes s, $opt_d.dbo.systypes st\n");
  629. + &dbcmd($dbproc, "where  st.type = s.type\n");
  630. + &dbcmd($dbproc, "and s.usertype > 100 and st.usertype < 100 and st.usertype != 18\n");
  631. + &dbsqlexec($dbproc);
  632. + &dbresults($dbproc);
  633. + while((@dat = &dbnextrow($dbproc)))
  634. + {
  635. +     print SCRIPT "sp_addtype $dat[1],";
  636. +     if ($dat[2] =~ /char|binary/)
  637. +     {
  638. +         print SCRIPT "'$dat[2]($dat[0])'";
  639. +     }
  640. +     else
  641. +     {
  642. +         print SCRIPT "$dat[2]";
  643. +     }
  644. +     print SCRIPT "\ngo\n";
  645. +                 # Now remeber the default & rule for later.
  646. +     $urule{$dat[1]} = $dat[4] if $dat[4] !~ /NULL/;
  647. +     $udflt{$dat[1]} = $dat[3] if $dat[3] !~ /NULL/;
  648. + }
  649. + print "Done\n";
  650. + print "Create rules...";
  651. + print SCRIPT
  652. +     "\n/* Now we add the rules... */\n\n";
  653. + &getObj('Rule', 'R');
  654. + print "Done\n";
  655. + print "Create defaults...";
  656. + print SCRIPT
  657. +     "\n/* Now we add the defaults... */\n\n";
  658. + &getObj('Default', 'D');
  659. + print "Done\n";
  660. + print "Bind rules & defaults to user data types...";
  661. + print SCRIPT "/* Bind rules & defaults to user data types... */\n\n";
  662. + while(($dat, $dflt)=each(%udflt))
  663. + {
  664. +     print SCRIPT "sp_bindefault $dflt, $dat\ngo\n";
  665. + }
  666. + while(($dat, $rule) = each(%urule))
  667. + {
  668. +     print SCRIPT "sp_bindrule $rule, $dat\ngo\n";
  669. + }
  670. + print "Done\n";
  671. + print "Create Tables & Indices...";
  672. + print "\n" if $opt_v;
  673. + &dbcmd($dbproc, "select o.name,u.name, o.id\n");
  674. + &dbcmd($dbproc, "from $opt_d.dbo.sysobjects o, $opt_d.dbo.sysusers u\n");
  675. + &dbcmd($dbproc, "where o.type = 'U' and o.name like '$opt_t' and u.uid = o.uid\n");
  676. + &dbcmd($dbproc, "order by o.name\n");
  677. + &dbsqlexec($dbproc);
  678. + &dbresults($dbproc);
  679. + while((@dat = &dbnextrow($dbproc)))
  680. + {
  681. +     $_ = join('@', @dat);    # join the data together on a line
  682. +     push(@tables,$_);        # and save it in a list
  683. + }
  684. + foreach (@tables)        # For each line in the list
  685. + {
  686. +     @tab = split(/@/, $_);
  687. +     print "Creating table $tab[0], owner $tab[1]\n" if $opt_v;
  688. +     print SCRIPT "/* Start of description of table $tab[1].$tab[0] */\n\n";
  689. +     &dbcmd($dbproc, "select Column_name = c.name, \n");
  690. +     &dbcmd($dbproc, "       Type = t.name, \n");
  691. +     &dbcmd($dbproc, "       Length = c.length, \n");
  692. +     &dbcmd($dbproc, "       Nulls = convert(bit, (c.status & 8)),\n");
  693. +     &dbcmd($dbproc, "       Default_name = object_name(c.cdefault),\n");
  694. +     &dbcmd($dbproc, "       Rule_name = object_name(c.domain)\n");
  695. +     &dbcmd($dbproc, "from   $opt_d.dbo.syscolumns c, $opt_d.dbo.systypes t\n");
  696. +     &dbcmd($dbproc, "where  c.id = $tab[2]\n");
  697. +     &dbcmd($dbproc, "and    c.usertype *= t.usertype\n");
  698. +     &dbsqlexec($dbproc);
  699. +     &dbresults($dbproc);
  700. +     undef(%rule);
  701. +     undef(%dflt);
  702. +     print SCRIPT "\n\nCREATE TABLE $opt_d.$tab[1].$tab[0]\n ("; 
  703. +     $first = 1;
  704. +     while((@field = &dbnextrow($dbproc)))
  705. +     {
  706. +         print SCRIPT ",\n" if !$first;        # add a , and a \n if not first field in table
  707. +         
  708. +         print SCRIPT "\t$field[0] \t$field[1]";
  709. +         print SCRIPT "($field[2])" if $field[1] =~ /char|bin/;
  710. +         print SCRIPT " $nul[$field[3]]";
  711. +     
  712. +     $rule{"$tab[0].$field[0]"} = $field[5] if ($field[5] !~ /NULL/ && $urule{$field[1]} ne $field[5]);
  713. +     $dflt{"$tab[0].$field[0]"} = $field[4] if ($field[4] !~ /NULL/ && $udflt{$field[1]} ne $field[4]);;
  714. +         $first = 0 if $first;
  715. +         
  716. +     }
  717. +     print SCRIPT " )\n";
  718. + # now get the indexes...
  719. + #
  720. +     print "Indexes for table $tab[1].$tab[0]\n" if $opt_v;
  721. +     
  722. +     &dbcmd($dbproc, "sp_helpindex '$tab[1].$tab[0]'\n");
  723. +     &dbsqlexec($dbproc);
  724. +     &dbresults($dbproc);
  725. +     while((@field = &dbnextrow($dbproc)))
  726. +     {
  727. +         print SCRIPT "\nCREATE ";
  728. +         print SCRIPT "unique " if $field[1] =~ /unique/;
  729. +         print SCRIPT "clustered " if $field[1] =~ /^clust/;
  730. +         print SCRIPT "index $field[0]\n";
  731. +         @col = split(/,/,$field[2]);
  732. +         print SCRIPT "on $opt_d.$tab[1].$tab[0] (";
  733. +         $first = 1;
  734. +         foreach (@col)
  735. +         {
  736. +             print SCRIPT ", " if !$first;
  737. +             $first = 0;
  738. +             print SCRIPT "$_";
  739. +         }
  740. +         print SCRIPT ")\n";
  741. +     }
  742. +     &getPerms("$tab[1].$tab[0]");
  743. +     print SCRIPT "go\n";
  744. +     print "Bind rules & defaults to columns...\n" if $opt_v;
  745. +     print SCRIPT "/* Bind rules & defaults to columns... */\n\n";
  746. +     if($tab[1] ne 'dbo' && (keys(%dflt) || keys(%rules)))
  747. +     {
  748. +     print SCRIPT "/* The owner of the table is $tab[1].
  749. + ** I can't bind the rules/defaults to a table of which I am not the owner.
  750. + ** The procedures below will have to be run manualy by user $tab[1].
  751. + */";
  752. +     print LOG "Defaults/Rules for $tab[1].$tab[0] could not be bound\n";
  753. +     }
  754. +     while(($dat, $dflt)=each(%dflt))
  755. +     {
  756. +     print SCRIPT "/* " if $tab[1] ne 'dbo';
  757. +     print SCRIPT "sp_bindefault $dflt, '$dat'";
  758. +     if($tab[1] ne 'dbo')
  759. +     {
  760. +         print SCRIPT " */\n";
  761. +     }
  762. +     else
  763. +     {
  764. +         print SCRIPT "\ngo\n";
  765. +     }
  766. +     }
  767. +     while(($dat, $rule) = each(%rule))
  768. +     {
  769. +     print SCRIPT "/* " if $tab[1] ne 'dbo';
  770. +     print SCRIPT "sp_bindrule $rule, '$dat'";
  771. +     if($tab[1] ne 'dbo')
  772. +     {
  773. +         print SCRIPT " */\n";
  774. +     }
  775. +     else
  776. +     {
  777. +         print SCRIPT "\ngo\n";
  778. +     }
  779. +     }
  780. +     print SCRIPT "\n/* End of description of table $tab[1].$tab[0] */\n";
  781. + }
  782. + print "Done\n";
  783. + #
  784. + # Now create any views that might exist
  785. + #
  786. + print "Create views...";
  787. + print SCRIPT
  788. +     "\n/* Now we add the views... */\n\n";
  789. + &getObj('View', 'V');
  790. + print "Done\n";
  791. + #
  792. + # Now create any stored procs that might exist
  793. + #
  794. + print "Create stored procs...";
  795. + print SCRIPT
  796. +     "\n/* Now we add the stored procedures... */\n\n";
  797. + &getObj('Stored Proc', 'P');
  798. + print "Done\n";
  799. + #
  800. + # Now create the triggers
  801. + #
  802. + print "Create triggers...";
  803. + print SCRIPT
  804. +     "\n/* Now we add the triggers... */\n\n";
  805. + &getObj('Trigger', 'TR');
  806. + print "Done\n";
  807. + print "\nLooks like I'm all done!\n";
  808. + close(SCRIPT);
  809. + close(LOG);
  810. + &dbexit;
  811. + sub getPerms
  812. + {
  813. +     local($obj) = $_[0];
  814. +     local($ret, @dat, $act, $cnt);
  815. +     &dbcmd($dbproc, "sp_helprotect '$obj'\n");
  816. +     &dbsqlexec;
  817. +     $cnt = 0;
  818. +     while(($ret = &dbresults) != $NO_MORE_RESULTS && $ret != $FAIL)
  819. +     {
  820. +     while(@dat = &dbnextrow)
  821. +     {
  822. +         $act = 'to';
  823. +         $act = 'from' if $dat[0] =~ /Revoke/;
  824. +         print SCRIPT "$dat[0] $dat[1] on $obj $act $dat[2]\n";
  825. +         ++$cnt;
  826. +     }
  827. +     }
  828. +     $cnt;
  829. + }
  830. + sub getObj
  831. + {
  832. +     local($objname, $obj) = @_;
  833. +     local(@dat, @items, @vi, $found);
  834. +     
  835. +     &dbcmd($dbproc, "select o.name, u.name, o.id\n");
  836. +     &dbcmd($dbproc, "from $opt_d.dbo.sysobjects o, $opt_d.dbo.sysusers u\n");
  837. +     &dbcmd($dbproc, "where o.type = '$obj' and o.name like '$opt_t' and u.uid = o.uid\n");
  838. +     &dbcmd($dbproc, "order by o.name\n");
  839. +     &dbsqlexec($dbproc);
  840. +     &dbresults($dbproc);
  841. +     while((@dat = &dbnextrow($dbproc)))
  842. +     {                # 
  843. +     $_ = join('@', @dat);    # join the data together on a line
  844. +     push(@items, $_);    # and save it in a list
  845. +     }
  846. +     foreach (@items)
  847. +     {
  848. +     @vi = split(/@/, $_);
  849. +     $found = 0;
  850. +     &dbcmd($dbproc, "select text from syscomments where id = $vi[2]");
  851. +     &dbsqlexec;
  852. +     &dbresults;
  853. +     
  854. +     print SCRIPT
  855. +         "/* $objname $vi[0], owner $vi[1] */\n";
  856. +     while(($text) = &dbnextrow)
  857. +     {
  858. +         if(!$found && $vi[1] ne 'dbo')
  859. +         {
  860. +         ++$found if($text =~ /$vi[1]/);
  861. +         }
  862. +         print SCRIPT $text;
  863. +     }
  864. +     print SCRIPT "\ngo\n";
  865. +     if(!$found && $vi[1] ne 'dbo')
  866. +     {
  867. +         print "**Warning**\n$objname $vi[0] has owner $vi[1]\nbut this is not mentioned in the CREATE PROC statement!!\n";
  868. +         print LOG "$objname $vi[0] (owner $vi[1])\n";
  869. +     }
  870. +     }
  871. + }
  872. diff -c -r ./eg/report.pl /usr/local/src/perl/sybase/dist-1.5/eg/report.pl
  873. *** ./eg/report.pl    Wed Jun 24 13:37:34 1992
  874. --- /usr/local/src/perl/sybase/dist-1.5/eg/report.pl    Thu Jun 25 13:18:18 1992
  875. ***************
  876. *** 1,5 ****
  877. --- 1,9 ----
  878.   #! /usr/local/bin/sybperl
  879.   
  880. + #
  881. + #    @(#)report.pl    1.1    6/24/92
  882. + #
  883.   require "sybperl.pl";
  884.   require "sql.pl";
  885.   
  886. diff -c -r ./eg/space.pl /usr/local/src/perl/sybase/dist-1.5/eg/space.pl
  887. *** ./eg/space.pl    Wed Jun 24 13:37:34 1992
  888. --- /usr/local/src/perl/sybase/dist-1.5/eg/space.pl    Thu Jun 25 13:18:16 1992
  889. ***************
  890. *** 1,5 ****
  891. --- 1,9 ----
  892.   #! /usr/local/bin/sybperl
  893.   
  894. + #
  895. + #    @(#)space.pl    1.1    6/24/92
  896. + #
  897.   require "sybperl.pl";
  898.   require "sql.pl";
  899.   
  900. diff -c -r ./eg/sql.pl /usr/local/src/perl/sybase/dist-1.5/eg/sql.pl
  901. *** ./eg/sql.pl    Wed Jun 24 13:37:35 1992
  902. --- /usr/local/src/perl/sybase/dist-1.5/eg/sql.pl    Thu Jun 25 13:18:16 1992
  903. ***************
  904. *** 1,3 ****
  905. --- 1,7 ----
  906. + #
  907. + #    @(#)sql.pl    1.1    6/24/92
  908. + #
  909.   sub sql {
  910.       local($db,$sql,$sep)=@_;            # local copy parameters
  911.   
  912.  
  913. exit 0 # Just in case...
  914.