home *** CD-ROM | disk | FTP | other *** search
/ PC Professionell 2004 December / PCpro_2004_12.ISO / files / webserver / tsw / TSW_3.4.0.exe / Apache2 / perl / RDBM.pm < prev    next >
Encoding:
Perl POD Document  |  2000-03-22  |  22.4 KB  |  680 lines

  1. package Tie::RDBM;
  2.  
  3. use strict;
  4. use vars qw($VERSION %Types);
  5. use Carp;
  6. use DBI;
  7. $VERSION = '0.70';
  8.  
  9. # %Types is used for creating the data table if it doesn't exist already.
  10. # You may want to edit this.
  11. %Types = (                 # key          value          frozen    freeze  keyless
  12.       'mysql'   => [qw/ varchar(127)  longblob       tinyint   1          0 /],
  13.       'mSQL'    => [qw/ char(255)     char(255)      int       0          0 /],
  14.       'Pg'      => [qw/ varchar(127)  varchar(2000)  int       0          0 /],
  15.       'Sybase'  => [qw/ varchar(255)  varbinary(255) tinyint   1          0 /],
  16.       'Oracle'  => [qw/ varchar(255)  varchar2(2000) integer   1          0 /],
  17.       'CSV'     => [qw/ varchar(255)  varchar(255)   integer   1          1 /],
  18.       'Informix'=> [qw/ nchar(120)    nchar(2000)    integer   0          0 /],
  19.       'Solid'   => [qw/ varchar(255)  varbinary(2000) integer  1          0 /],
  20.       'ODBC'    => [qw/ varchar(255)  varbinary(2000) integer   1         0 /],
  21.       'default' => [qw/ varchar(255)  varchar(255)   integer   0          0 /],  #others
  22.       );
  23.  
  24. # list drivers that do run-time binding correctly
  25. my %CAN_BIND = (
  26.         'mysql' => 1,
  27.         'mSQL'  => 1,
  28.         'Oracle' => 1,
  29.         'Pg'    => 1,
  30.         'Informix' => 1,
  31.         'Solid'    => 1,
  32.         'ODBC'     => 1,
  33.            );
  34.  
  35. # Default options for the module
  36. my %DefaultOptions = (
  37.               'table'      =>  'pdata',
  38.               'key'        =>  'pkey',
  39.               'value'      =>  'pvalue',
  40.               'frozen'     =>  'pfrozen',
  41.               'user'       =>  '',
  42.               'password'   =>  '',
  43.               'autocommit' =>  1,
  44.                   'create'     =>  0,
  45.                       'drop'       =>  0,
  46.               'DEBUG'      =>  0,
  47.               );
  48.  
  49. sub TIEHASH {
  50.     my $class = shift;
  51.     my ($dsn,$opt) = ref($_[0]) ? (undef,$_[0]) : @_;
  52.     $dsn ||= $opt->{'db'};
  53.  
  54.     croak "Usage tie(%h,Tie::RDBM,<DBI_data_source>,\%options)" unless $dsn;
  55.     if ($opt) {
  56.     foreach (keys %DefaultOptions) {
  57.         $opt->{$_}=$DefaultOptions{$_} unless exists($opt->{$_});
  58.     }
  59.     } else {
  60.     $opt = \%DefaultOptions;
  61.     }
  62.  
  63.     my($dbh,$driver);
  64.  
  65.     if (UNIVERSAL::isa($dsn,'DBI::db')) {
  66.     $dbh = $dsn;
  67.     $driver = $dsn->{Driver}{Name};
  68.     } else {
  69.     $dsn = "dbi:$dsn" unless $dsn=~ /^dbi/;
  70.     ($driver) = $dsn =~ /\w+:(\w+)/;
  71.  
  72.  
  73.     # Try to establish connection with data source.
  74.     delete $ENV{NLS_LANG} if $driver eq 'Oracle';  # allow 8 bit connections?
  75.     $dbh = DBI->connect($dsn,$opt->{user},$opt->{password},
  76.                 { AutoCommit=>$opt->{autocommit},
  77.                   PrintError=>0,
  78.                   ChopBlanks=>1,
  79.                   Warn=>0 }
  80.                 );
  81.     croak "TIEHASH: Can't open $dsn, $DBI::errstr" unless $dbh;
  82.     }
  83.     
  84.     # A variety of shinanegans to handle freeze/thaw option.
  85.     # We will serialize references if:
  86.     # 1. The database driver supports binary types.
  87.     # 2. The database table has a boolean field to indicate that a value is frozen.
  88.     # 3. The Storable module is available.
  89.     # we also check that "primary key" is recognized
  90.     my $db_features = $Types{$driver} || $Types{'default'};
  91.     my($canfreeze) = $db_features->[3];
  92.     my($keyless)   = $db_features->[4];
  93.     my($haveStorable) = eval 'require Storable;';
  94.     Storable->import(qw/nfreeze thaw/) if $haveStorable;
  95.     $canfreeze &&= $haveStorable;
  96.  
  97.     # Check that the indicated table exists.  If it doesn't,
  98.     # try to create it....
  99.  
  100.     # This query tests that a table with the correct fields is present.
  101.     # I would prefer to use a where clause of 1=0 but some dumb drivers (mSQL)
  102.     # treat this as a syntax error!!!
  103.     my $q = "select * from $opt->{table} where $opt->{key}=''";
  104.     my $sth = $dbh->prepare($q);
  105.     my $structure_ok = 0;
  106.     local($^W)=0; # uninitialized variable problem
  107.     if (defined($sth) && $sth->execute() ne '') { 
  108.     # At least the key field exists.  Check whether the others do too.
  109.     my(%field_names);
  110.     grep($field_names{lc($_)}++,@{$sth->{NAME}});
  111.     $structure_ok++ if $field_names{$opt->{'value'}};
  112.     $canfreeze &&= $field_names{$opt->{'frozen'}};
  113.     }
  114.  
  115.     unless ($structure_ok) {
  116.  
  117.     unless ($opt->{'create'} || $opt->{'drop'}) {
  118.         my $err = $DBI::errstr;
  119.         $dbh->disconnect;
  120.         croak "Table $opt->{table} does not have expected structure and creation forbidden: $err";
  121.     }
  122.         
  123.     $dbh->do("drop table $opt->{table}") if $opt->{'drop'};
  124.  
  125.     my($keytype,$valuetype,$frozentype) = @{$db_features};
  126.     my(@fields) = ($keyless ? "$opt->{key}    $keytype" : "$opt->{key}    $keytype primary key",
  127.                "$opt->{value}  $valuetype");
  128.     push(@fields,  ($keyless ? "$opt->{frozen} $frozentype" : "$opt->{frozen} $frozentype not null") )
  129.       if $canfreeze;
  130.     $q = "create table $opt->{table} (" . join(',',@fields) . ")";
  131.     warn "$q\n" if $opt->{DEBUG};
  132.     $dbh->do($q) || do {
  133.         my $err = $DBI::errstr;
  134.         $dbh->disconnect;
  135.         croak("Can't initialize data table: $err");
  136.     }
  137.     }
  138.  
  139.     return bless {
  140.     'dbh'       => $dbh,
  141.     'table'     => $opt->{'table'},
  142.     'key'       => $opt->{'key'},
  143.     'value'     => $opt->{'value'},
  144.     'frozen'    => $opt->{'frozen'},
  145.     'canfreeze' => $canfreeze,
  146.     'brokenselect'  => $driver eq 'mSQL',
  147.     'canbind'   => $CAN_BIND{$driver},
  148.     'DEBUG'     => $opt->{DEBUG},
  149.     },$class;
  150. }
  151.  
  152. sub FETCH {
  153.     my($self,$key) = @_;
  154.  
  155.     # this is a hack to avoid doing an unnecessary SQL select
  156.     # during an each() loop.
  157.     return $self->{'cached_value'}->{$key} 
  158.        if exists $self->{'cached_value'}->{$key};
  159.  
  160.     # create statement handler if it doesn't already exist.
  161.     my $cols = $self->{'canfreeze'} ? "$self->{'value'},$self->{'frozen'}" : $self->{'value'};
  162.     my $sth = $self->_run_query('fetch',<<END,$key);
  163. select $cols from $self->{table} where $self->{key}=?
  164. END
  165.     ;
  166.     my $result = $sth->fetchrow_arrayref();
  167.     $sth->finish;    
  168.     return undef unless $result;
  169.     $self->{'canfreeze'} && $result->[1] ? thaw($result->[0]) : $result->[0];
  170. }
  171.  
  172. sub STORE {
  173.     my($self,$key,$value) = @_;
  174.  
  175.     my $frozen = 0;
  176.     if (ref($value) && $self->{'canfreeze'}) {
  177.     $frozen++;
  178.     $value = nfreeze($value);
  179.     }
  180.  
  181.     # Yes, this is ugly.  It is designed to minimize the number of SQL statements
  182.     # for both database whose update statements return the number of rows updated,
  183.     # and those (like mSQL) whose update statements don't.
  184.     my($r);
  185.     if ($self->{'brokenselect'}) {
  186.     return $self->EXISTS($key) ? $self->_update($key,$value,$frozen)
  187.                            : $self->_insert($key,$value,$frozen);
  188.     }
  189.  
  190.     return $self->_update($key,$value,$frozen) || $self->_insert($key,$value,$frozen);
  191. }
  192.  
  193. sub DELETE {
  194.     my($self,$key) = @_;
  195.     my $sth = $self->_run_query('delete',<<END,$key);
  196. delete from $self->{table} where $self->{key}=?
  197. END
  198.     ;
  199.     croak "Database delete statement failed: $DBI::errstr" if $sth->err;        
  200.     $sth->finish;
  201.     1;
  202. }
  203.  
  204. sub CLEAR {
  205.     my $self = shift;
  206.     my $dbh = $self->{'dbh'};
  207.     my $sth= $self->_prepare('clear',"delete from $self->{table}");
  208.     $sth->execute();    
  209.     croak "Database delete all statement failed: $DBI::errstr" if $dbh->err;        
  210.     $sth->finish;
  211. }
  212.  
  213. sub EXISTS {
  214.     my($self,$key) = @_;
  215.     my $sth = $self->_run_query('exists',<<END,$key);
  216. select $self->{key} from $self->{table} where $self->{key}=?
  217. END
  218.     ;
  219.     croak "Database select statement failed: $DBI::errstr" unless $sth;
  220.     $sth->fetch;
  221.     my $rows = $sth->rows;
  222.     $sth->finish;
  223.     $rows >= 1;
  224. }
  225.  
  226. sub FIRSTKEY {
  227.     my $self = shift;
  228.     
  229.     delete $self->{'cached_value'};
  230.     if ($self->{'fetchkeys'}) {
  231.       $self->{'fetchkeys'}->finish();  # to prevent truncation in ODBC driver
  232.       delete $self->{'fetchkeys'};
  233.     }
  234.  
  235.     my $sth = $self->_prepare('fetchkeys',$self->{'canfreeze'} ? <<END1 : <<END2);
  236. select $self->{'key'},$self->{'value'},$self->{'frozen'} from $self->{'table'}
  237. END1
  238. select $self->{'key'},$self->{'value'} from $self->{'table'}
  239. END2
  240.     ;
  241.  
  242.     $sth->execute() || croak "Can't execute select statement: $DBI::errstr";
  243.     my $ref = $sth->fetch();
  244.     return defined($ref) ? $ref->[0] : undef;
  245. }
  246.  
  247. sub NEXTKEY {
  248.     my $self = shift;
  249.     # no statement handler defined, so nothing to iterate over
  250.     return wantarray ? () : undef unless my $sth = $self->{'fetchkeys'};
  251.     my $r = $sth->fetch();
  252.     if (!$r) {
  253.     $sth->finish;
  254.     delete $self->{'cached_value'};
  255.     return wantarray ? () : undef;
  256.     }
  257.     my ($key,$value) = ($r->[0],$r->[2] ? thaw($r->[1]) : $r->[1]);
  258.     $self->{'cached_value'}->{$key}=$value;
  259.     return wantarray ? ($key,$value) : $key;
  260. }
  261.  
  262. sub DESTROY {
  263.     my $self = shift;
  264.     foreach (qw/fetch update insert delete clear exists fetchkeys/) {
  265.     $self->{$_}->finish if $self->{$_};
  266.     }
  267.     $self->{'dbh'}->disconnect();
  268. }
  269.  
  270. sub commit {
  271.     $_[0]->{'dbh'}->commit();
  272. }
  273.  
  274. sub rollback {
  275.     $_[0]->{'dbh'}->rollback();
  276. }
  277.  
  278. # utility routines
  279. sub _update {
  280.     my ($self,$key,$value,$frozen) = @_;
  281.     my ($sth);
  282.     if ($self->{'canfreeze'}) {
  283.     $sth = $self->_run_query('update',
  284.                  "update $self->{table} set $self->{value}=?,$self->{frozen}=? where $self->{key}=?",
  285.                  $value,$frozen,$key);
  286.     } else {
  287.     $sth = $self->_run_query('update',
  288.                  "update $self->{table} set $self->{value}=? where $self->{key}=?",
  289.                  $value,$key);
  290.     }
  291.     croak "Update: $DBI::errstr"  unless $sth;
  292.     $sth->rows > 0;
  293. }
  294.  
  295. sub _insert {
  296.     my ($self,$key,$value,$frozen) = @_;
  297.     my ($sth);
  298.     if ($self->{'canfreeze'}) {
  299.     $sth = $self->_run_query('insert',
  300.                  "insert into $self->{table} ($self->{key},$self->{value},$self->{frozen}) values (?,?,?)",
  301.                  $key,$value,$frozen);
  302.     } else {
  303.     $sth = $self->_run_query('insert',
  304.                  "insert into $self->{table} ($self->{key},$self->{value}) values (?,?)",
  305.                  $key,$value);
  306.     }
  307.     ($sth && $sth->rows) || croak "Update: $DBI::errstr";
  308. }
  309.  
  310. sub _run_query {
  311.     my $self = shift;
  312.     my ($tag,$query,@bind_variables) = @_;
  313.     if ($self->{canbind}) {
  314.     my $sth = $self->_prepare($tag,$query);
  315.     return undef unless $sth->execute(@bind_variables);
  316.     return $sth;
  317.     }
  318.     # if we get here, then we can't bind, so we replace ? with escaped parameters
  319.     $query =~ s/\?/$self->{'dbh'}->quote(shift(@bind_variables))/eg;
  320.     my $sth = $self->{'dbh'}->prepare($query);
  321.     return undef unless $sth && $sth->execute;
  322.     return $sth;
  323. }
  324.  
  325. sub _prepare ($$$) {
  326.     my($self,$tag,$q) = @_;
  327.     unless (exists($self->{$tag})) {
  328.     return undef unless $q;
  329.     warn $q,"\n" if $self->{DEBUG};
  330.     my $sth = $self->{'dbh'}->prepare($q);
  331.     croak qq/Problems preparing statement "$q": $DBI::errstr/ unless $sth;
  332.     $self->{$tag} = $sth;
  333.     } else {
  334.     $self->{$tag}->finish if $q;  # in case we forget
  335.     }
  336.     $self->{$tag};
  337. }
  338.  
  339. 1;
  340. __END__
  341.  
  342. =head1 NAME
  343.  
  344. Tie::RDBM - Tie hashes to relational databases
  345.  
  346. =head1 SYNOPSIS
  347.  
  348.   use Tie::RDBM;
  349.   tie %h,Tie::RDBM,'mysql:test',{table=>'Demo',create=>1,autocommit=>0};
  350.   $h{'key1'} = 'Some data here';
  351.   $h{'key2'} = 42;
  352.   $h{'key3'} = { complex=>['data','structure','here'],works=>'true' };
  353.   $h{'key4'} = new Foobar('Objects work too');
  354.   print $h{'key3'}->{complex}->[0];
  355.   tied(%h)->commit;
  356.   untie %h;
  357.  
  358. =head1 DESCRIPTION
  359.  
  360. This module allows you to tie Perl associative arrays (hashes) to SQL
  361. databases using the DBI interface.  The tied hash is associated with a
  362. table in a local or networked database.  One field of the table becomes the
  363. hash key, and another becomes the value.  Once tied, all the standard
  364. hash operations work, including iteration over keys and values.
  365.  
  366. If you have the Storable module installed, you may store arbitrarily
  367. complex Perl structures (including objects) into the hash and later
  368. retrieve them.  When used in conjunction with a network-accessible
  369. database, this provides a simple way to transmit data structures
  370. between Perl programs on two different machines.
  371.  
  372. =head1 TIEING A DATABASE
  373.  
  374.    tie %VARIABLE,Tie::RDBM,DSN [,\%OPTIONS]
  375.  
  376. You tie a variable to a database by providing the variable name, the
  377. tie interface (always "Tie::RDBM"), the data source name, and an
  378. optional hash reference containing various options to be passed to the
  379. module and the underlying database driver.
  380.  
  381. The data source may be a valid DBI-style data source string of the
  382. form "dbi:driver:database_name[:other information]", or a
  383. previously-opened database handle.  See the documentation for DBI and
  384. your DBD driver for details.  Because the initial "dbi" is always
  385. present in the data source, Tie::RDBM will automatically add it for
  386. you.
  387.  
  388. The options array contains a set of option/value pairs.  If not
  389. provided, defaults are assumed.  The options are:
  390.  
  391. =over 4
  392.  
  393. =item user ['']
  394.  
  395. Account name to use for database authentication, if necessary.
  396. Default is an empty string (no authentication necessary).
  397.  
  398. =item password ['']
  399.  
  400. Password to use for database authentication, if necessary.  Default is
  401. an empty string (no authentication necessary).
  402.  
  403. =item db ['']
  404.  
  405. The data source, if not provided in the argument.  This allows an
  406. alternative calling style:
  407.  
  408.    tie(%h,Tie::RDBM,{db=>'dbi:mysql:test',create=>1};
  409.  
  410. =item table ['pdata']
  411.  
  412. The name of the table in which the hash key/value pairs will be
  413. stored.
  414.  
  415. =item key ['pkey']
  416.  
  417. The name of the column in which the hash key will be found.  If not
  418. provided, defaults to "pkey".
  419.  
  420. =item value ['pvalue']
  421.  
  422. The name of the column in which the hash value will be found.  If not
  423. provided, defaults to "pvalue".
  424.  
  425. =item frozen ['pfrozen']
  426.  
  427. The name of the column that stores the boolean information indicating
  428. that a complex data structure has been "frozen" using Storable's
  429. freeze() function.  If not provided, defaults to "pfrozen".  
  430.  
  431. NOTE: if this field is not present in the database table, or if the
  432. database is incapable of storing binary structures, Storable features
  433. will be disabled.
  434.  
  435. =item create [0]
  436.  
  437. If set to a true value, allows the module to create the database table
  438. if it does not already exist.  The module emits a CREATE TABLE command
  439. and gives the key, value and frozen fields the data types most
  440. appropriate for the database driver (from a lookup table maintained in
  441. a package global, see DATATYPES below).
  442.  
  443. The success of table creation depends on whether you have table create
  444. access for the database.
  445.  
  446. The default is not to create a table.  tie() will fail with a fatal
  447. error.
  448.  
  449. =item drop [0]
  450.  
  451. If the indicated database table exists, but does not have the required
  452. key and value fields, Tie::RDBM can try to add the required fields to
  453. the table.  Currently it does this by the drastic expedient of
  454. DROPPING the table entirely and creating a new empty one.  If the drop
  455. option is set to true, Tie::RDBM will perform this radical
  456. restructuring.  Otherwise tie() will fail with a fatal error.  "drop"
  457. implies "create".  This option defaults to false.
  458.  
  459. A future version of Tie::RDBM may implement a last radical
  460. restructuring method; differences in DBI drivers and database
  461. capabilities make this task harder than it would seem.
  462.  
  463. =item autocommit [1]
  464.  
  465. If set to a true value, the "autocommit" option causes the database
  466. driver to commit after every store statement.  If set to a false
  467. value, this option will not commit to the database until you
  468. explicitly call the Tie::RDBM commit() method.
  469.  
  470. The autocommit option defaults to true.
  471.  
  472. =item DEBUG [0]
  473.  
  474. When the "DEBUG" option is set to a true value the module will echo
  475. the contents of SQL statements and other debugging information to
  476. standard error.
  477.  
  478. =back
  479.  
  480. =head1 USING THE TIED ARRAY
  481.  
  482. The standard fetch, store, keys(), values() and each() functions will
  483. work as expected on the tied array.  In addition, the following
  484. methods are available on the underlying object, which you can obtain
  485. with the standard tie() operator:
  486.  
  487. =over 4
  488.  
  489. =item commit()
  490.  
  491.    (tied %h)->commit();
  492.  
  493. When using a database with the autocommit option turned off, values
  494. that are stored into the hash will not become permanent until commit()
  495. is called.  Otherwise they are lost when the application terminates or
  496. the hash is untied.
  497.  
  498. Some SQL databases don't support transactions, in which case you will
  499. see a warning message if you attempt to use this function.
  500.  
  501. =item rollback()
  502.  
  503.    (tied %h)->rollback();
  504.  
  505. When using a database with the autocommit option turned off, this
  506. function will roll back changes to the database to the state they were
  507. in at the last commit().  This function has no effect on database that
  508. don't support transactions.
  509.  
  510. =back
  511.  
  512. =head1 DATABASES AND DATATYPES
  513.  
  514. Perl is a weakly typed language.  Databases are strongly typed.  When
  515. translating from databases to Perl there is inevitably some data type
  516. conversion that you must worry about.  I have tried to keep the
  517. details as transparent as possible without sacrificing power; this
  518. section discusses the tradeoffs.
  519.  
  520. If you wish to tie a hash to a preexisting database, specify the
  521. database name, the table within the database, and the fields you wish
  522. to use for the keys and values.  These fields can be of any type that
  523. you choose, but the data type will limit what can be stored there.
  524. For example, if the key field is of type "int", then any numeric value
  525. will be a valid key, but an attempt to use a string as a key will
  526. result in a run time error.  If a key or value is too long to fit into
  527. the data field, it will be truncated silently.
  528.  
  529. For performance reasons, the key field should be a primary key, or at
  530. least an indexed field.  It should also be unique.  If a key is
  531. present more than once in a table, an attempt to fetch it will return
  532. the first record found by the SQL select statement.
  533.  
  534. If you wish to store Perl references in the database, the module needs
  535. an additional field in which it can store a flag indicating whether
  536. the data value is a simple or a complex type.  This "frozen" field is
  537. treated as a boolean value.  A "tinyint" data type is recommended, but
  538. strings types will work as well.
  539.  
  540. In a future version of this module, the "frozen" field may be turned
  541. into a general "datatype" field in order to minimize storage.  For
  542. future compatability, please use an integer for the frozen field.
  543.  
  544. If you use the "create" and/or "drop" options, the module will
  545. automatically attempt to create a table for its own use in the
  546. database if a suitable one isn't found.  It uses information defined
  547. in the package variable %Tie::RDBM::Types to determine what kind of
  548. data types to create.  This variable is indexed by database driver.
  549. Each index contains a four-element array indicating what data type to
  550. use for each of the key, value and frozen fields, and whether the
  551. database can support binary types.  Since I have access to only a
  552. limited number of databases, the table is currently short:
  553.  
  554.    Driver     Key Field      Value Field     Frozen Field  Binary?
  555.  
  556.    mysq       varchar(127)   longblob        tinyint       1
  557.    mSQL       char(255)      char(255)       int           0
  558.    Sybase     varchar(255)   varbinary(255)  tinyint       1
  559.    default    varchar(255)   varbinary(255)  tinyint       1
  560.  
  561. The "default" entry is used for any driver not specifically
  562. mentioned.  
  563.  
  564. You are free to add your own entries to this table, or make
  565. corrections.  Please send me e-mail with any revisions you make so
  566. that I can share the wisdom.
  567.  
  568. =head1 STORABLE CAVEATS
  569.  
  570. Because the Storable module packs Perl structures in a binary format,
  571. only those databases that support a "varbinary" or "blob" type can
  572. handle complex datatypes.  Furthermore, some databases have strict
  573. limitations on the size of these structures.  For example, SyBase and
  574. MS SQL Server have a "varbinary" type that maxes out at 255 bytes.
  575. For structures larger than this, the databases provide an "image" type
  576. in which storage is allocated in 2K chunks!  Worse, access to this
  577. image type uses a non-standard SQL extension that is not supported by
  578. DBI.
  579.  
  580. Databases that do not support binary fields cannot use the Storable
  581. feature.  If you attempt to store a reference to a complex data type
  582. in one of these databases it will be converted into strings like
  583. "HASH(0x8222cf4)", just as it would be if you tried the same trick
  584. with a conventional tied DBM hash.  If the database supports binary
  585. fields of restricted length, large structures may be silently
  586. truncated.  Caveat emptor.
  587.  
  588. It's also important to realize the limitations of the Storable
  589. mechanism.  You can store and retrieve entire data structures, but you
  590. can't twiddle with individual substructures and expect them to persist
  591. when the process exits.  To update a data structure, you must fetch it
  592. from the hash, make the desired modifications, then store it back into
  593. the hash, as the example below shows:
  594.  
  595. B<Process #1:>
  596.    tie %h,Tie::RDBM,'mysql:Employees:host.somewhere.com',
  597.                    {table=>'employee',user=>'fred',password=>'xyzzy'};
  598.    $h{'Anne'} = { office=>'999 Infinity Drive, Rm 203',
  599.                   age    =>  29,
  600.                   salary =>  32100 };
  601.    $h{'Mark'} = { office=>'000 Iteration Circle, Rm -123',
  602.                   age    =>  32,
  603.                   salary =>  35000 };
  604.  
  605. B<Process #2:>
  606.    tie %i,Tie::RDBM,'mysql:Employees:host.somewhere.com',
  607.                    {table=>'employee',user=>'george',password=>'kumquat2'};
  608.    foreach (keys %i) {
  609.       $info = $i{$_};
  610.       if ($info->{age} > 30) {
  611.          # Give the oldies a $1000 raise
  612.          $info->{salary} += 1000;  
  613.          $i{$_} = $info;
  614.       }
  615.    }
  616.  
  617. This example also demonstrates how two Perl scripts running on
  618. different machines can use Tie::RDBM to share complex data structures
  619. (in this case, the employee record) without resorting to sockets,
  620. remote procedure calls, shared memory, or other gadgets
  621.  
  622. =head1 PERFORMANCE
  623.  
  624. What is the performance hit when you use this module?  It can be
  625. significant.  I used a simple benchmark in which Perl parsed a 6180
  626. word text file into individual words and stored them into a database,
  627. incrementing the word count with each store.  The benchmark then read
  628. out the words and their counts in an each() loop.  The database driver
  629. was mySQL, running on a 133 MHz Pentium laptop with Linux 2.0.30.  I
  630. compared Tie::RDBM, to DB_File, and to the same task using vanilla DBI
  631. SQL statements.  The results are shown below:
  632.  
  633.               STORE       EACH() LOOP
  634.   Tie::RDBM     28 s        2.7  s
  635.   Vanilla DBI   15 s        2.0  s
  636.   DB_File        3 s        1.08 s
  637.  
  638. During stores, there is an approximately 2X penalty compared to
  639. straight DBI, and a 15X penalty over using DB_File databases.  For the
  640. each() loop (which is dominated by reads), the performance is 2-3
  641. times worse than DB_File and much worse than a vanilla SQL statement.
  642. I have not investigated the bottlenecks.
  643.  
  644. =head1 TO DO LIST
  645.  
  646.    - Store strings, numbers and data structures in separate
  647.      fields for space and performance efficiency.
  648.  
  649.     - Expand data types table to other database engines.
  650.  
  651.     - Catch internal changes to data structures and write them into
  652.       database automatically.
  653.  
  654. =head1 BUGS
  655.  
  656. Yes.
  657.  
  658. =head1 AUTHOR
  659.  
  660. Lincoln Stein, lstein@w3.org
  661.  
  662. =head1 COPYRIGHT
  663.  
  664.   Copyright (c) 1998, Lincoln D. Stein
  665.  
  666. This library is free software; you can redistribute it and/or
  667. modify it under the same terms as Perl itself.
  668.  
  669. =head1 AVAILABILITY
  670.  
  671. The latest version can be obtained from:
  672.  
  673.    http://www.genome.wi.mit.edu/~lstein/Tie-DBM/
  674.  
  675. =head1 SEE ALSO
  676.  
  677. perl(1), DBI(3), Storable(3)
  678.  
  679. =cut
  680.