home *** CD-ROM | disk | FTP | other *** search
/ PC Professionell 2004 December / PCpro_2004_12.ISO / files / webserver / xampp / xampp-perl-addon-1.4.9-installer.exe / MSSQLReporter.pm < prev    next >
Encoding:
Perl POD Document  |  2002-08-28  |  19.4 KB  |  746 lines

  1. package DBIx::MSSQLReporter;
  2.  
  3. # Name:
  4. #    DBIx::MSSQLReporter.
  5. #
  6. # Documentation:
  7. #    POD-style documentation is at the end. Extract it with pod2html.*.
  8. #
  9. # Tabs:
  10. #    4 spaces || die.
  11. #
  12. # Author:
  13. #    Ron Savage <ron@savage.net.au>
  14. #    Home page: http://savage.net.au/index.html
  15. #
  16. # Licence:
  17. #    Australian copyright (c) 1999-2002 Ron Savage.
  18. #
  19. #    All Programs of mine are 'OSI Certified Open Source Software';
  20. #    you can redistribute them and/or modify them under the terms of
  21. #    The Artistic License, a copy of which is available at:
  22. #    http://www.opensource.org/licenses/index.html
  23.  
  24. use strict;
  25. use vars qw($AUTOLOAD $VERSION @ISA @EXPORT @EXPORT_OK);
  26.  
  27. use Carp;
  28. use DBI qw(:sql_types);
  29.  
  30. require Exporter;
  31.  
  32. @ISA = qw(Exporter);
  33. # Items to export into callers namespace by default. Note: do not export
  34. # names by default without a very good reason. Use EXPORT_OK instead.
  35. # Do not simply export all your public functions/methods/constants.
  36.  
  37. @EXPORT        = qw();
  38.  
  39. $VERSION    = '1.01';
  40.  
  41. # -----------------------------------------------------------------
  42.  
  43. # Preloaded methods go here.
  44.  
  45. # -----------------------------------------------------------------
  46.  
  47. # Encapsulated class data.
  48. # This is a list of attributes the user
  49. # can use when calling DBIx::MSSQLReporter -> new().
  50. # I call these standard attributes, as opposed
  51. # to non-standard attributes which the user
  52. # should not refer to in the call to new().
  53. #
  54. # Reference:
  55. #    Object Oriented Perl
  56. #    Damian Conway
  57. #    Manning
  58. #    1-88477-779-1
  59. #    Chapter 3
  60. {
  61.     my(%_attribute) =
  62.     (    # Name        => default
  63.         _connexion    => '',
  64.     );
  65.  
  66.     # Return the default for any attribute.
  67.     sub _default_for
  68.     {
  69.         my($self, $attribute) = @_;
  70.  
  71.         $_attribute{$attribute};
  72.  
  73.     }    # End of _default_for.
  74.  
  75.     # Return the standard attributes.
  76.     sub _standard_keys
  77.     {
  78.         keys(%_attribute);
  79.  
  80.     }    # End of _standard_keys.
  81.  
  82.     # Tested, to some extent, with SQL Server and Postgres.
  83.     # Authors:
  84.     #    Dominique Cretel <dominique.cretel@sema.be>
  85.     #    Ron Savage <ron@savage.net.au>
  86.     my(%_field_type) =
  87.     (
  88.         '-1'    => 'Text',
  89.         '1'        => 'Char',
  90.         '2'        => '2 - unknown',
  91.         '3'        => 'Decimal',
  92.         '4'        => 'Integer',
  93.         '5'        => 'Smallint',
  94.         '6'        => '6 - unknown',
  95.         '7'        => 'Double precision',
  96.         '8'        => 'Double precision',
  97.         '9'        => 'Date',
  98.         '10'    => 'Time',
  99.         '11'    => 'Datetime/Timestamp',
  100.         '12'    => 'Varchar',
  101.         '13'    => '13 - unknown',
  102.         '14'    => '14 - unknown',
  103.         '15'    => '15 - unknown',
  104.         '16'    => '16 - unknown',
  105.         '17'    => '17 - unknown',
  106.         '18'    => '18 - unknown',
  107.         '19'    => '19 - unknown',
  108.         '20'    => '20 - unknown',
  109.     );
  110.  
  111.     # Return readable type for numeric type.
  112.     sub _field_type
  113.     {
  114.         my($self, $field) = @_;
  115.  
  116.         $_field_type{$field};
  117.     }
  118.  
  119. }    # End of encapsulated class data.
  120.  
  121. # ------------------------------------------------------------------------
  122. # Execute any SQL command.
  123.  
  124. sub do
  125. {
  126.     my($self, $sql)    = @_;
  127.     my($dbh)        = $self -> {'_dbh'};
  128.     my($sth)        = $dbh -> prepare($sql) or croak $DBI::errstr;
  129.  
  130.     $sth -> execute() or croak $DBI::errstr;
  131.  
  132.     $sth;
  133.  
  134. }    # End of do.
  135.  
  136. # ------------------------------------------------------------------------
  137. # Drop a database.
  138.  
  139. sub dropDB
  140. {
  141.     my($self, $dbName) = @_;
  142.  
  143.     my($dbh)    = $self -> {'_dbh'};
  144.     my($result)    = $dbh -> do("drop database $dbName");
  145.  
  146.     croak $DBI::errstr if (! $result);
  147.  
  148. }    # End of dropDB.
  149.  
  150. # ------------------------------------------------------------------------
  151. # Drop a table.
  152.  
  153. sub dropTable
  154. {
  155.     my($self, $tableName) = @_;
  156.  
  157.     my($dbh)    = $self -> {'_dbh'};
  158.     my($result)    = $dbh -> do("if exists (select * from sysobjects where id = object_id(N'[dbo].[$tableName]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) drop table [dbo].[$tableName]");
  159.  
  160.     croak $DBI::errstr if (! $result);
  161.  
  162. }    # End of dropTable.
  163.  
  164. # -----------------------------------------------------------------
  165. # Get the names of all user databases.
  166. # $sysDbCount is the number of system database names to ignore, 4 by default.
  167.  
  168. sub get_dbNames
  169. {
  170.     my($self, $sysDbCount)    = @_;
  171.     $sysDbCount                = 4 if (! $sysDbCount);
  172.     my($dbh)                = $self -> {'_dbh'};
  173.  
  174.     # See MS SQL Server 7.0/Books On Line/(Search) sysdatabases/(Result) sysdatabases (T-SQL).
  175.     # dbId    Name
  176.     #    1    master
  177.     #    2    tempDb
  178.     #    3    model
  179.     #    4    msDb
  180.     #    ?    msSqlWeb
  181.     my($araRef)    = $dbh -> selectcol_arrayref("select * from master.dbo.sysdatabases where dbid > $sysDbCount") or croak $dbh -> errstr;
  182.     @$araRef    = map{lc} sort @$araRef;
  183.  
  184.     $araRef;
  185.  
  186. }    # End of get_dbNames.
  187.  
  188. # -----------------------------------------------------------------
  189. # Get the names of all fields in the given table.
  190.  
  191. sub get_fieldNames
  192. {
  193.     my($self, $tableName)    = @_;
  194.     my($dbh)                = $self -> {'_dbh'};
  195.     my($sth)                = $self -> do("select * from $tableName where 1 = 0");
  196.     my($name)                = $sth -> {NAME};
  197.     my(@type)                = map{$self -> _field_type($_)} @{$sth -> {TYPE} };
  198.     my($precision)            = $sth -> {PRECISION};
  199.  
  200.     ($name, \@type, $precision);
  201.  
  202. }    # End of get_fieldNames.
  203.  
  204. # -----------------------------------------------------------------
  205. # Get the names of all user tables in the current database.
  206.  
  207. sub get_tableNames
  208. {
  209.     my($self)    = @_;
  210.     my($dbh)    = $self -> {'_dbh'};
  211.     my($araRef) = $dbh -> selectcol_arrayref("select name from sysobjects where OBJECTPROPERTY(id, N'IsUserTable') = 1") or croak $dbh -> errstr;
  212.     @$araRef    = map{lc} sort @$araRef;
  213.  
  214.     $araRef;
  215.  
  216. }    # End of get_tableNames.
  217.  
  218. # -----------------------------------------------------------------
  219. # Get the names of all user views in the current database.
  220.  
  221. sub get_viewNames
  222. {
  223.     my($self)    = @_;
  224.     my($dbh)    = $self -> {'_dbh'};
  225.     my($araRef) = $dbh -> selectcol_arrayref("select name from sysobjects where OBJECTPROPERTY(id, N'IsView') = 1 and objectProperty(id, N'IsMSShipped') = 0") or croak $dbh -> errstr;
  226.     @$araRef    = map{lc} sort @$araRef;
  227.  
  228.     $araRef;
  229.  
  230. }    # End of get_viewNames.
  231.  
  232. # -----------------------------------------------------------------
  233. # Get the names of all system databases.
  234. # $sysDbCount is the number of system database names to recognize, 4 by default.
  235.  
  236. sub get_sysDbNames
  237. {
  238.     my($self, $sysDbCount)    = @_;
  239.     $sysDbCount                = 4 if (! $sysDbCount);
  240.     my($dbh)                = $self -> {'_dbh'};
  241.  
  242.     # See MS SQL Server 7.0/Books On Line/(Search) sysdatabases/(Result) sysdatabases (T-SQL).
  243.     # dbId    Name
  244.     #    1    master
  245.     #    2    tempDb
  246.     #    3    model
  247.     #    4    msDb
  248.     #    ?    msSqlWeb
  249.     my($araRef)    = $dbh -> selectcol_arrayref("select * from master.dbo.sysdatabases where dbid <= $sysDbCount") or croak $dbh -> errstr;
  250.     @$araRef    = map{lc} sort @$araRef;
  251.  
  252.     $araRef;
  253.  
  254. }    # End of get_sysDbNames.
  255.  
  256. # -----------------------------------------------------------------
  257. # Get the names of all system tables in the current database.
  258.  
  259. sub get_sysTableNames
  260. {
  261.     my($self)    = @_;
  262.     my($dbh)    = $self -> {'_dbh'};
  263.     my($araRef) = $dbh -> selectcol_arrayref("select name from sysobjects where OBJECTPROPERTY(id, N'IsSystemTable') = 1") or croak $dbh -> errstr;
  264.     @$araRef    = map{lc} sort @$araRef;
  265.  
  266.     $araRef;
  267.  
  268. }    # End of get_sysTableNames.
  269.  
  270. # -----------------------------------------------------------------
  271. # Get the names of all system views in the current database.
  272.  
  273. sub get_sysViewNames
  274. {
  275.     my($self)    = @_;
  276.     my($dbh)    = $self -> {'_dbh'};
  277.     my($araRef) = $dbh -> selectcol_arrayref("select name from sysobjects where OBJECTPROPERTY(id, N'IsView') = 1 and objectProperty(id, N'IsMSShipped') = 1") or croak $dbh -> errstr;
  278.     @$araRef    = map{lc} sort @$araRef;
  279.  
  280.     $araRef;
  281.  
  282. }    # End of get_sysViewNames.
  283.  
  284. # ------------------------------------------------------------
  285. # Convert a hash reference into an HTML table.
  286. # $sep separates the values of different rows in each column.
  287. # It defaults to $;.
  288.  
  289. sub hash2Table
  290. {
  291.     my($self, $hashRef, $sep, $keyRef)    = @_;
  292.     $sep                                = $; if (! $sep);
  293.  
  294.     # By default, the columns are displayed in the order
  295.     # specified by $keyRef, where $keyRef is a reference
  296.     # to a hash, and in that hash the keys are the column
  297.     # names and the sort order is given by the 'order' subkey.
  298.     # Eg:
  299.     #    my(%key) =
  300.     #    (
  301.     #        hostName    =>
  302.     #            {
  303.     #                data    => '',
  304.     #                order    => 1,
  305.     #            },
  306.     #        userName    =>
  307.     #            {
  308.     #                data    => '',
  309.     #                order    => 2,
  310.     #            },
  311.     #        dbName        =>
  312.     #            {
  313.     #                data    => '',
  314.     #                order    => 3,
  315.     #            },
  316.     #    );
  317.  
  318.     # If the 2nd parameter is not a hash,
  319.     # fabricate a hash to sort on.
  320.     my(@key) = sort(keys(%$hashRef) );
  321.  
  322.     if (ref($keyRef) ne 'HASH')
  323.     {
  324.         $keyRef = {};
  325.  
  326.         my($order) = 0;
  327.         my($key);
  328.  
  329.         for $key (@key)
  330.         {
  331.             $order++;
  332.             $$keyRef{$key}    = {};
  333.             $$keyRef{$key}{'order'}    = $order;
  334.         }
  335.     }
  336.  
  337.     # Determine the column order.
  338.     @key = sort {$$keyRef{$a}{'order'} cmp $$keyRef{$b}{'order'} } @key;
  339.  
  340.     # The keys will be the column headings.
  341.     my($html) = "\n<table border=1>\n\t<tr>\n";
  342.     my($key);
  343.  
  344.     for $key (@key)
  345.     {
  346.         $html .= "\t\t<th>$key</th>\n";
  347.     }
  348.  
  349.     $html .= "\t</tr>\n";
  350.  
  351.     # Get the # of rows of data.
  352.     my(@row)    = keys(%$hashRef);
  353.     @row        = split(/$sep/, $$hashRef{$row[0]});
  354.     my($row);
  355.  
  356.     # Display each row.
  357.     for $row (0 .. $#row)
  358.     {
  359.         $html .= "\t<tr>\n";
  360.  
  361.         # Display the row in sorted order.
  362.         for $key (@key)
  363.         {
  364.             my(@field) = split(/$sep/, $$hashRef{$key});
  365.             $html .= "\t\t<td>" . $field[$row] . "</td>\n";
  366.         }
  367.  
  368.         $html .= "\t</tr>\n";
  369.     }
  370.  
  371.     # The '\n's just make the output easy to debug.
  372.     $html .= "</table>\nRow count: " . ($#row + 1) . "\n";
  373.  
  374.     # Return the HTML.
  375.     $html;
  376.  
  377. }    # End of hash2Table.
  378.  
  379. # -----------------------------------------------------------------
  380.  
  381. sub new
  382. {
  383.     my($caller, %arg)    = @_;
  384.     my($caller_is_obj)    = ref($caller);
  385.     my($class)            = $caller_is_obj || $caller;
  386.     my($self)            = bless {}, $class;
  387.  
  388.     # These are non-standard class data, and so are not
  389.     # in the encapsulated class data set above.
  390.     $self -> {'_dbh'}    = '';
  391.     $self -> {'_sql'}    = '';
  392.  
  393.     # Initialize all standard attributes.
  394.     for my $attributeName ($self -> _standard_keys() )
  395.     {
  396.         my($argName) = ($attributeName =~ /^_(.*)/);
  397.  
  398.         # Did the caller provide a value?
  399.         if (exists($arg{$argName}) )
  400.         {
  401.             $self -> {$attributeName} = $arg{$argName};
  402.         }
  403.         else
  404.         {
  405.             # If the caller is an object, use its values.
  406.             if ($caller_is_obj)
  407.             {
  408.                 $self -> {$attributeName} = $caller -> {$attributeName};
  409.             }
  410.             else
  411.             {
  412.                 # Otherwise, use our defaults.
  413.                 $self -> {$attributeName} = $self -> _default_for($attributeName);
  414.             }
  415.         }
  416.     }
  417.  
  418.     $self -> {'_dbh'} = DBI->connect($self -> {'_connexion'},
  419.                                         {
  420.                                             PrintError    => 0,
  421.                                             RaiseError    => 0,
  422.                                         }) || croak "Can't connect: $DBI::errstr\n";
  423.     $self -> {'_dbh'} -> {LongReadLen} = 65534;
  424.  
  425.     return $self;
  426.  
  427. }    # End of new.
  428.  
  429. # ------------------------------------------------------------------------
  430. # Execute a select command.
  431. # Return the hash ref of the data.
  432. # This can be passed straight to hash2Table.
  433. # $sep separates the values of different rows in each column.
  434. # It defaults to $;.
  435.  
  436. sub select
  437. {
  438.     my($self, $sql, $sep)    = @_;
  439.     $sep                    = $; if (! $sep);
  440.     $self -> {'_select'}    = {};
  441.     my($sth)                = $self -> do($sql);
  442.  
  443.     my($rowRef, $key);
  444.  
  445.     # Build a hash, $self -> {'_select'}, where the keys are the column headings,
  446.     # ie the field names, and the values are the column data, separated by $sep.
  447.     while ( ($rowRef = $sth -> fetchrow_hashref() ) )
  448.     {
  449.         for $key (keys(%$rowRef) )
  450.         {
  451.             $$rowRef{$key}                = 'NULL'                if (! defined($$rowRef{$key}) );
  452.             $self -> {'_select'}{$key}    .= "$sep$$rowRef{$key}"    if (defined($self -> {'_select'}{$key}) );
  453.             $self -> {'_select'}{$key}    = $$rowRef{$key}        if (! defined($self -> {'_select'}{$key}) );
  454.         }
  455.     }
  456.  
  457.     $sth -> finish();
  458.  
  459.     $self -> {'_select'};
  460.  
  461. }    # End of select.
  462.  
  463. # -----------------------------------------------------------------
  464.  
  465. sub DESTROY
  466. {
  467.     my($self) = @_;
  468.  
  469.     $self -> {'_dbh'} -> disconnect();
  470.  
  471. }    # End of DESTROY.
  472.  
  473. # -----------------------------------------------------------------
  474. # Fabricate accessors and mutators on-the-fly.
  475.  
  476. sub AUTOLOAD
  477. {
  478.     no strict 'refs';
  479.  
  480.     my($self, $newval) = @_;
  481.  
  482.     # Was it a get... method?
  483.     if ($AUTOLOAD =~ /.*::get(_\w+)/)
  484.     {
  485.         my($attributeName)    = $1;
  486.         *{$AUTOLOAD}        = sub { return $_[0] -> {$attributeName}; };
  487.         return $self -> {$attributeName};
  488.     }
  489.  
  490.     # Was it a set... method?
  491.     if ($AUTOLOAD =~ /.*::set(_\w+)/)
  492.     {
  493.         my($attributeName)    = $1;
  494.         *{$AUTOLOAD}        = sub { $_[0] -> {$attributeName} = $_[1]; return; };
  495.         $self -> {$1}        = $newval;
  496.         return;
  497.     }
  498.  
  499.     # Must have been a mistake then...
  500.     croak "No such method: $AUTOLOAD";
  501.  
  502. }    # End of AUTOLOAD.
  503.  
  504. # -----------------------------------------------------------------
  505.  
  506. # Autoload methods go after =cut, and are processed by the autosplit program.
  507.  
  508. 1;
  509.  
  510. __END__
  511.  
  512. =head1 NAME
  513.  
  514. DBIx::MSSQLReporter - An module to connect Perl to MS SQL Server and MS Data Engine
  515.  
  516. =head1 SYNOPSIS
  517.  
  518. This is complete, runnable program.
  519.  
  520. Since you only use this module after installing MS SQL Server or MS Data Engine,
  521. you should not even have to worry about the DSN.
  522.  
  523.     #!perl -w
  524.     use strict;
  525.     use DBIx::MSSQLReporter;
  526.  
  527.     my($connect) = "dbi:ODBC(RaiseError=>1, PrintError=>1, Taint=>1):DSN=LocalServer";
  528.     my($reporter) = DBIx::MSSQLReporter -> new(connexion => $connect);
  529.  
  530.     print "User tables: \n";
  531.     print join("\n", @{$reporter -> get_tableNames()}), "\n\n";
  532.  
  533. =head1 DESCRIPTION
  534.  
  535. C<DBIx::MSSQLReporter> encapsulates the connection between Perl and MS SQL Server.
  536.  
  537. C<DBIx::MSSQLReporter> was written so that I could teach myself about MS SQL Server and
  538. MSDE, and as part of my Perl tutorial series.
  539.  
  540. It should be clear from the name that this module is database-engine-specific. If you
  541. plan on writing code which is independent of any particular database, look elsewhere.
  542.  
  543. See the URI, below, for my demos sql7Demo[23].pl, which both use this module.
  544.  
  545. sql7Demo2.pl is a command-line program. sql7Demo3.pl is a CGI script.
  546.  
  547. Lastly, note that this module has a chequered future: I may well re-write it to fit
  548. under the umbrella of DBIx::Easy, or someone else working independently may have
  549. already released such a module.
  550.  
  551. =head1 INSTALLATION
  552.  
  553. You install C<DBIx::MSSQLReporter>, as you would install any perl module,
  554. by running these commands:
  555.  
  556.     perl Makefile.PL
  557.     make
  558.     make test
  559.     make install
  560.  
  561. =head1 CONSTRUCTOR new
  562.  
  563. The constructor takes 1 parameter and 1 value for that parameter.
  564.  
  565. It croaks if it can't connect. Otherwise it returns an object you can use thus:
  566.  
  567.     my($reporter) = DBIx::MSSQLReporter -> new(connexion => $connect);
  568.     print join("\n", @{$reporter -> get_viewNames()}), "\n\n";
  569.  
  570. =head1 METHOD do($sql)
  571.  
  572. It croaks if it can't prepare() and execute() the given SQL.
  573.  
  574. It returns a statment handle, which you need for things like:
  575.  
  576.     my($sth) = $reporter -> do($sql);
  577.     $sth -> dump_results();
  578.     $sth -> finish();
  579.  
  580. dump_results() is built-in to DBI.
  581.  
  582. =head1 METHOD dropDB($dbName)
  583.  
  584. It croaks if it can't drop the given database.
  585.  
  586.     $reporter -> dropDB($dbName);
  587.  
  588. =head1 METHOD dropTable($tableName)
  589.  
  590. It croaks if it can't drop the given table.
  591.  
  592.     $reporter -> dropTable($tableName);
  593.  
  594. =head1 METHOD get_dbNames($sysDbCount)
  595.  
  596. It returns a sorted list of user database names, all in lower case.
  597.  
  598. $sysDbCount is optional. It defaults to 4, which means this method ignores the 4
  599. system tables. See get_sysDbNames(), below.
  600.  
  601.     my($dbName) = $reporter -> get_dbNames();
  602.     print "User databases: \n";
  603.     print join("\n", @$dbName), "\n\n";
  604.  
  605. =head1 METHOD get_fieldNames($tableName)
  606.  
  607. It returns a list of references to the names, types, and precisions, of the fields
  608. in the given table.
  609.  
  610.     my($fieldName, $fieldType, $fieldPrecision) = $reporter -> get_fieldNames($tableName);
  611.     print join("\n", map{"Field: $$fieldName[$_]. Type: $$fieldType[$_]. Precision: $$fieldPrecision[$_]"} 0 .. $#{$fieldName}), "\n\n";
  612.  
  613. =head1 METHOD get_tableNames()
  614.  
  615. It returns a sorted list of user table names, all in lower case. Recall, the DSN
  616. specified the database.
  617.  
  618.     my($tableName) = $reporter -> get_tableNames();
  619.     print "User tables: \n";
  620.     print join("\n", @$tableName), "\n\n";
  621.  
  622. =head1 METHOD get_viewNames()
  623.  
  624. It returns a sorted list of user view names, all in lower case. Recall, the DSN
  625. specified the database.
  626.  
  627.     my($viewName) = $reporter -> get_viewNames();
  628.     print "User views: \n";
  629.     print join("\n", @$viewName), "\n\n";
  630.  
  631. =head1 METHOD get_sysDbNames($sysDbCount)
  632.  
  633. It returns a sorted list of system database names, all in lower case. On my system,
  634. I get master, model, msDb and tempDb.
  635.  
  636. $sysDbCount is optional. It defaults to 4, which means this method returns the 4
  637. system tables. See get_dbNames(), above.
  638.  
  639.     my($sysDbName) = $reporter -> get_sysDbNames();
  640.     print "System databases: \n";
  641.     print join("\n", @$sysDbName), "\n\n";
  642.  
  643. =head1 METHOD get_sysTableNames()
  644.  
  645. It returns a sorted list of system table names, all in lower case. Recall, the DSN specified
  646. the database.
  647.  
  648.     my($sysTableName) = $reporter -> get_sysTableNames();
  649.     print "System tables: \n";
  650.     print join("\n", @$sysTableName), "\n\n";
  651.  
  652. =head1 METHOD get_sysViewNames()
  653.  
  654. It returns a sorted list of system view names, all in lower case. Recall, the DSN
  655. specified the database.
  656.  
  657.     my($sysViewName) = $reporter -> get_sysViewNames();
  658.     print "System views: \n";
  659.     print join("\n", @$sysViewName), "\n\n";
  660.  
  661. =head1 METHOD hash2Table($select, $sep, $keyRef)
  662.  
  663. Convert a hash reference, as returned by $reporter -> select($sql), into an HTML
  664. table. See select(), below, for details.
  665.  
  666.     my($html) = $reporter -> hash2Table($select);
  667.  
  668. $sep is optional. It separates the values of different rows in each column. It
  669. defaults to $;.
  670.  
  671. $keyRef is optional. It is a hash reference used to specify the order of columns.
  672. It defaults to sorting the keys of %$select.
  673.  
  674. If you wish to use $keyRef, prepare it thus:
  675.  
  676.     my(%key) =
  677.     (
  678.         hostName    =>
  679.             {
  680.                 someData    => '',
  681.                 order        => 2,
  682.             },
  683.         userName    =>
  684.             {
  685.                 someData    => '',
  686.                 order        => 1,
  687.             },
  688.     );
  689.  
  690.     my($html) = $reporter -> hash2Table($select, $;, \%key);
  691.  
  692.     The key 'order' is used to order the keys 'hostName' and 'userName', which are
  693.     presumed to appear as keys in %$select.
  694.  
  695.     The key 'someData' is ignored.
  696.  
  697. =head1 METHOD select($sql, $sep)
  698.  
  699. It croaks if it can't prepare() and execute() the given SQL.
  700.  
  701. $sep is optional. It defaults to $;.
  702.  
  703. It returns a reference to a hash, which hold the results of the select.
  704.  
  705. The keys of the hash are the names of the fields, which can be used for column
  706. headings.
  707.  
  708. The values of the hash are the values of the fields, which can be used for the
  709. column data. The values in each column are, by default, separated by Perl's $;
  710. variable.
  711.  
  712.     my($select) = $reporter -> select($sql);
  713.  
  714. Warning: select() selects the whole table. Ideally we'd use DBIx::Recordset to page
  715. thru the table, but I had too many problems with various versions of DBIx::Recordset.
  716.  
  717. If you have binary data containing $;, you I<E<lt>mustE<gt>> set $sep to something
  718. else. Of course, with binary data, there may be no 'safe' character (string) which
  719. does not appear in your data.
  720.  
  721. Alternately, store your binary data in files, and put the file name or URI in the
  722. database.
  723.  
  724. The hash reference can be passed straight to hash2Table for conveting into an HTML
  725. table. Eg:
  726.  
  727.     my($html) = $reporter -> hash2Table($select);
  728.     print $html;
  729.  
  730. =head1 AUTHOR
  731.  
  732. C<DBIx::MSSQLReporter> was written by Ron Savage I<E<lt>ron@savage.net.auE<gt>> in 2000.
  733.  
  734. Source available from http://savage.net.au/Perl.html.
  735.  
  736. =head1 LICENCE
  737.  
  738. Australian copyright (c) 1999-2002 Ron Savage.
  739.  
  740.     All Programs of mine are 'OSI Certified Open Source Software';
  741.     you can redistribute them and/or modify them under the terms of
  742.     The Artistic License, a copy of which is available at:
  743.     http://www.opensource.org/licenses/index.html
  744.  
  745. =cut
  746.