hash.t
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:20k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. #!./perl -w
  2. # ID: %I%, %G%   
  3. use strict ;
  4. BEGIN {
  5.     unless(grep /blib/, @INC) {
  6.         chdir 't' if -d 't';
  7.         @INC = '../lib' if -d '../lib';
  8.     }
  9. }
  10. #use Config;
  11. #
  12. #BEGIN {
  13. #    if(-d "lib" && -f "TEST") {
  14. #        if ($Config{'extensions'} !~ /bBerkeleyDBb/ ) {
  15. #            print "1..74n";
  16. #            exit 0;
  17. #        }
  18. #    }
  19. #}
  20. use BerkeleyDB; 
  21. use File::Path qw(rmtree);
  22. print "1..210n";
  23. my %DB_errors = (
  24.     'DB_INCOMPLETE' => "DB_INCOMPLETE: Sync was unable to complete",
  25.     'DB_KEYEMPTY' => "DB_KEYEMPTY: Non-existent key/data pair",
  26.     'DB_KEYEXIST' => "DB_KEYEXIST: Key/data pair already exists",
  27.     'DB_LOCK_DEADLOCK'  => "DB_LOCK_DEADLOCK: Locker killed to resolve a deadlock",
  28.     'DB_LOCK_NOTGRANTED' => "DB_LOCK_NOTGRANTED: Lock not granted",
  29.     'DB_NOTFOUND' => "DB_NOTFOUND: No matching key/data pair found",
  30.     'DB_OLD_VERSION' => "DB_OLDVERSION: Database requires a version upgrade",
  31.     'DB_RUNRECOVERY' => "DB_RUNRECOVERY: Fatal error, run database recovery",
  32. ) ;
  33. {
  34.     package LexFile ;
  35.     sub new
  36.     {
  37. my $self = shift ;
  38. unlink @_ ;
  39.   bless [ @_ ], $self ;
  40.     }
  41.     sub DESTROY
  42.     {
  43. my $self = shift ;
  44. unlink @{ $self } ;
  45.     }
  46. }
  47. sub ok
  48. {
  49.     my $no = shift ;
  50.     my $result = shift ;
  51.  
  52.     print "not " unless $result ;
  53.     print "ok $non" ;
  54. }
  55. my $Dfile = "dbhash.tmp";
  56. my $Dfile2 = "dbhash2.tmp";
  57. my $Dfile3 = "dbhash3.tmp";
  58. unlink $Dfile;
  59. umask(0) ;
  60. # Check for invalid parameters
  61. {
  62.     # Check for invalid parameters
  63.     my $db ;
  64.     eval ' $db = new BerkeleyDB::Hash  -Stupid => 3 ; ' ;
  65.     ok 1, $@ =~ /unknown key value(s) Stupid/  ;
  66.     eval ' $db = new BerkeleyDB::Hash -Bad => 2, -Mode => 0345, -Stupid => 3; ' ;
  67.     ok 2, $@ =~ /unknown key value(s) (Bad |Stupid ){2}/  ;
  68.     eval ' $db = new BerkeleyDB::Hash -Env => 2 ' ;
  69.     ok 3, $@ =~ /^Env not of type BerkeleyDB::Env/ ;
  70.     eval ' $db = new BerkeleyDB::Hash -Txn => "fred" ' ;
  71.     ok 4, $@ =~ /^Txn not of type BerkeleyDB::Txn/ ;
  72.     my $obj = bless [], "main" ;
  73.     eval ' $db = new BerkeleyDB::Hash -Env => $obj ' ;
  74.     ok 5, $@ =~ /^Env not of type BerkeleyDB::Env/ ;
  75. }
  76. # Now check the interface to HASH
  77. {
  78.     my $lex = new LexFile $Dfile ;
  79.     ok 6, my $db = new BerkeleyDB::Hash -Filename => $Dfile, 
  80.     -Flags    => DB_CREATE ;
  81.     # Add a k/v pair
  82.     my $value ;
  83.     my $status ;
  84.     ok 7, $db->db_put("some key", "some value") == 0  ;
  85.     ok 8, $db->status() == 0 ;
  86.     ok 9, $db->db_get("some key", $value) == 0 ;
  87.     ok 10, $value eq "some value" ;
  88.     ok 11, $db->db_put("key", "value") == 0  ;
  89.     ok 12, $db->db_get("key", $value) == 0 ;
  90.     ok 13, $value eq "value" ;
  91.     ok 14, $db->db_del("some key") == 0 ;
  92.     ok 15, ($status = $db->db_get("some key", $value)) == DB_NOTFOUND ;
  93.     ok 16, $status eq $DB_errors{'DB_NOTFOUND'} ;
  94.     ok 17, $db->status() == DB_NOTFOUND ;
  95.     ok 18, $db->status() eq $DB_errors{'DB_NOTFOUND'};
  96.     ok 19, $db->db_sync() == 0 ;
  97.     # Check NOOVERWRITE will make put fail when attempting to overwrite
  98.     # an existing record.
  99.     ok 20, $db->db_put( 'key', 'x', DB_NOOVERWRITE) == DB_KEYEXIST ;
  100.     ok 21, $db->status() eq $DB_errors{'DB_KEYEXIST'};
  101.     ok 22, $db->status() == DB_KEYEXIST ;
  102.     # check that the value of the key  has not been changed by the
  103.     # previous test
  104.     ok 23, $db->db_get("key", $value) == 0 ;
  105.     ok 24, $value eq "value" ;
  106.     # test DB_GET_BOTH
  107.     my ($k, $v) = ("key", "value") ;
  108.     ok 25, $db->db_get($k, $v, DB_GET_BOTH) == 0 ;
  109.     ($k, $v) = ("key", "fred") ;
  110.     ok 26, $db->db_get($k, $v, DB_GET_BOTH) == DB_NOTFOUND ;
  111.     ($k, $v) = ("another", "value") ;
  112.     ok 27, $db->db_get($k, $v, DB_GET_BOTH) == DB_NOTFOUND ;
  113. }
  114. {
  115.     # Check simple env works with a hash.
  116.     my $lex = new LexFile $Dfile ;
  117.     my $home = "./fred" ;
  118.     ok 28, -d $home ? chmod 0777, $home : mkdir($home, 0777) ;
  119.     ok 29, my $env = new BerkeleyDB::Env -Flags => DB_CREATE| DB_INIT_MPOOL,
  120.       -Home  => $home ;
  121.     ok 30, my $db = new BerkeleyDB::Hash -Filename => $Dfile, 
  122.     -Env      => $env,
  123.     -Flags    => DB_CREATE ;
  124.     # Add a k/v pair
  125.     my $value ;
  126.     ok 31, $db->db_put("some key", "some value") == 0 ;
  127.     ok 32, $db->db_get("some key", $value) == 0 ;
  128.     ok 33, $value eq "some value" ;
  129.     undef $db ;
  130.     undef $env ;
  131.     rmtree $home ;
  132. }
  133. {
  134.     # override default hash
  135.     my $lex = new LexFile $Dfile ;
  136.     my $value ;
  137.     $::count = 0 ;
  138.     ok 34, my $db = new BerkeleyDB::Hash -Filename => $Dfile, 
  139.      -Hash     => sub {  ++$::count ; length $_[0] },
  140.      -Flags    => DB_CREATE ;
  141.     ok 35, $db->db_put("some key", "some value") == 0 ;
  142.     ok 36, $db->db_get("some key", $value) == 0 ;
  143.     ok 37, $value eq "some value" ;
  144.     ok 38, $::count > 0 ;
  145. }
  146.  
  147. {
  148.     # cursors
  149.     my $lex = new LexFile $Dfile ;
  150.     my %hash ;
  151.     my ($k, $v) ;
  152.     ok 39, my $db = new BerkeleyDB::Hash -Filename => $Dfile, 
  153.      -Flags    => DB_CREATE ;
  154.     # create some data
  155.     my %data =  (
  156. "red" => 2,
  157. "green" => "house",
  158. "blue" => "sea",
  159. ) ;
  160.     my $ret = 0 ;
  161.     while (($k, $v) = each %data) {
  162.         $ret += $db->db_put($k, $v) ;
  163.     }
  164.     ok 40, $ret == 0 ;
  165.     # create the cursor
  166.     ok 41, my $cursor = $db->db_cursor() ;
  167.     $k = $v = "" ;
  168.     my %copy = %data ;
  169.     my $extras = 0 ;
  170.     # sequence forwards
  171.     while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
  172.         if ( $copy{$k} eq $v ) 
  173.             { delete $copy{$k} }
  174. else
  175.     { ++ $extras }
  176.     }
  177.     ok 42, $cursor->status() == DB_NOTFOUND ;
  178.     ok 43, $cursor->status() eq $DB_errors{'DB_NOTFOUND'} ;
  179.     ok 44, keys %copy == 0 ;
  180.     ok 45, $extras == 0 ;
  181.     # sequence backwards
  182.     %copy = %data ;
  183.     $extras = 0 ;
  184.     my $status ;
  185.     for ( $status = $cursor->c_get($k, $v, DB_LAST) ;
  186.   $status == 0 ;
  187.        $status = $cursor->c_get($k, $v, DB_PREV)) {
  188.         if ( $copy{$k} eq $v ) 
  189.             { delete $copy{$k} }
  190. else
  191.     { ++ $extras }
  192.     }
  193.     ok 46, $status == DB_NOTFOUND ;
  194.     ok 47, $status eq $DB_errors{'DB_NOTFOUND'} ;
  195.     ok 48, $cursor->status() == $status ;
  196.     ok 49, $cursor->status() eq $status ;
  197.     ok 50, keys %copy == 0 ;
  198.     ok 51, $extras == 0 ;
  199.     ($k, $v) = ("green", "house") ;
  200.     ok 52, $cursor->c_get($k, $v, DB_GET_BOTH) == 0 ;
  201.     ($k, $v) = ("green", "door") ;
  202.     ok 53, $cursor->c_get($k, $v, DB_GET_BOTH) == DB_NOTFOUND ;
  203.     ($k, $v) = ("black", "house") ;
  204.     ok 54, $cursor->c_get($k, $v, DB_GET_BOTH) == DB_NOTFOUND ;
  205.     
  206. }
  207.  
  208. {
  209.     # Tied Hash interface
  210.     my $lex = new LexFile $Dfile ;
  211.     my %hash ;
  212.     ok 55, tie %hash, 'BerkeleyDB::Hash', -Filename => $Dfile,
  213.                                       -Flags    => DB_CREATE ;
  214.     # check "each" with an empty database
  215.     my $count = 0 ;
  216.     while (my ($k, $v) = each %hash) {
  217. ++ $count ;
  218.     }
  219.     ok 56, (tied %hash)->status() == DB_NOTFOUND ;
  220.     ok 57, $count == 0 ;
  221.     # Add a k/v pair
  222.     my $value ;
  223.     $hash{"some key"} = "some value";
  224.     ok 58, (tied %hash)->status() == 0 ;
  225.     ok 59, $hash{"some key"} eq "some value";
  226.     ok 60, defined $hash{"some key"} ;
  227.     ok 61, (tied %hash)->status() == 0 ;
  228.     ok 62, exists $hash{"some key"} ;
  229.     ok 63, !defined $hash{"jimmy"} ;
  230.     ok 64, (tied %hash)->status() == DB_NOTFOUND ;
  231.     ok 65, !exists $hash{"jimmy"} ;
  232.     ok 66, (tied %hash)->status() == DB_NOTFOUND ;
  233.     delete $hash{"some key"} ;
  234.     ok 67, (tied %hash)->status() == 0 ;
  235.     ok 68, ! defined $hash{"some key"} ;
  236.     ok 69, (tied %hash)->status() == DB_NOTFOUND ;
  237.     ok 70, ! exists $hash{"some key"} ;
  238.     ok 71, (tied %hash)->status() == DB_NOTFOUND ;
  239.     $hash{1} = 2 ;
  240.     $hash{10} = 20 ;
  241.     $hash{1000} = 2000 ;
  242.     my ($keys, $values) = (0,0);
  243.     $count = 0 ;
  244.     while (my ($k, $v) = each %hash) {
  245.         $keys += $k ;
  246. $values += $v ;
  247. ++ $count ;
  248.     }
  249.     ok 72, $count == 3 ;
  250.     ok 73, $keys == 1011 ;
  251.     ok 74, $values == 2022 ;
  252.     # now clear the hash
  253.     %hash = () ;
  254.     ok 75, keys %hash == 0 ;
  255.     untie %hash ;
  256. }
  257. {
  258.     # in-memory file
  259.     my $lex = new LexFile $Dfile ;
  260.     my %hash ;
  261.     my $fd ;
  262.     my $value ;
  263.     ok 76, my $db = tie %hash, 'BerkeleyDB::Hash' ;
  264.     ok 77, $db->db_put("some key", "some value") == 0  ;
  265.     ok 78, $db->db_get("some key", $value) == 0 ;
  266.     ok 79, $value eq "some value" ;
  267.     undef $db ;
  268.     untie %hash ;
  269. }
  270.  
  271. {
  272.     # partial
  273.     # check works via API
  274.     my $lex = new LexFile $Dfile ;
  275.     my %hash ;
  276.     my $value ;
  277.     ok 80, my $db = tie %hash, 'BerkeleyDB::Hash', -Filename => $Dfile,
  278.                                               -Flags    => DB_CREATE ;
  279.     # create some data
  280.     my %data =  (
  281. "red" => "boat",
  282. "green" => "house",
  283. "blue" => "sea",
  284. ) ;
  285.     my $ret = 0 ;
  286.     while (my ($k, $v) = each %data) {
  287.         $ret += $db->db_put($k, $v) ;
  288.     }
  289.     ok 81, $ret == 0 ;
  290.     # do a partial get
  291.     my($pon, $off, $len) = $db->partial_set(0,2) ;
  292.     ok 82, $pon == 0 && $off == 0 && $len == 0 ;
  293.     ok 83, ( $db->db_get("red", $value) == 0) && $value eq "bo" ;
  294.     ok 84, ( $db->db_get("green", $value) == 0) && $value eq "ho" ;
  295.     ok 85, ( $db->db_get("blue", $value) == 0) && $value eq "se" ;
  296.     # do a partial get, off end of data
  297.     ($pon, $off, $len) = $db->partial_set(3,2) ;
  298.     ok 86, $pon ;
  299.     ok 87, $off == 0 ;
  300.     ok 88, $len == 2 ;
  301.     ok 89, $db->db_get("red", $value) == 0 && $value eq "t" ;
  302.     ok 90, $db->db_get("green", $value) == 0 && $value eq "se" ;
  303.     ok 91, $db->db_get("blue", $value) == 0 && $value eq "" ;
  304.     # switch of partial mode
  305.     ($pon, $off, $len) = $db->partial_clear() ;
  306.     ok 92, $pon ;
  307.     ok 93, $off == 3 ;
  308.     ok 94, $len == 2 ;
  309.     ok 95, $db->db_get("red", $value) == 0 && $value eq "boat" ;
  310.     ok 96, $db->db_get("green", $value) == 0 && $value eq "house" ;
  311.     ok 97, $db->db_get("blue", $value) == 0 && $value eq "sea" ;
  312.     # now partial put
  313.     ($pon, $off, $len) = $db->partial_set(0,2) ;
  314.     ok 98, ! $pon ;
  315.     ok 99, $off == 0 ;
  316.     ok 100, $len == 0 ;
  317.     ok 101, $db->db_put("red", "") == 0 ;
  318.     ok 102, $db->db_put("green", "AB") == 0 ;
  319.     ok 103, $db->db_put("blue", "XYZ") == 0 ;
  320.     ok 104, $db->db_put("new", "KLM") == 0 ;
  321.     $db->partial_clear() ;
  322.     ok 105, $db->db_get("red", $value) == 0 && $value eq "at" ;
  323.     ok 106, $db->db_get("green", $value) == 0 && $value eq "ABuse" ;
  324.     ok 107, $db->db_get("blue", $value) == 0 && $value eq "XYZa" ;
  325.     ok 108, $db->db_get("new", $value) == 0 && $value eq "KLM" ;
  326.     # now partial put
  327.     $db->partial_set(3,2) ;
  328.     ok 109, $db->db_put("red", "PPP") == 0 ;
  329.     ok 110, $db->db_put("green", "Q") == 0 ;
  330.     ok 111, $db->db_put("blue", "XYZ") == 0 ;
  331.     ok 112, $db->db_put("new", "--") == 0 ;
  332.     ($pon, $off, $len) = $db->partial_clear() ;
  333.     ok 113, $pon ;
  334.     ok 114, $off == 3 ;
  335.     ok 115, $len == 2 ;
  336.     ok 116, $db->db_get("red", $value) == 0 && $value eq "atPPP" ;
  337.     ok 117, $db->db_get("green", $value) == 0 && $value eq "ABuQ" ;
  338.     ok 118, $db->db_get("blue", $value) == 0 && $value eq "XYZXYZ" ;
  339.     ok 119, $db->db_get("new", $value) == 0 && $value eq "KLM--" ;
  340. }
  341. {
  342.     # partial
  343.     # check works via tied hash 
  344.     my $lex = new LexFile $Dfile ;
  345.     my %hash ;
  346.     my $value ;
  347.     ok 120, my $db = tie %hash, 'BerkeleyDB::Hash', -Filename => $Dfile,
  348.                                               -Flags    => DB_CREATE ;
  349.     # create some data
  350.     my %data =  (
  351. "red" => "boat",
  352. "green" => "house",
  353. "blue" => "sea",
  354. ) ;
  355.     while (my ($k, $v) = each %data) {
  356. $hash{$k} = $v ;
  357.     }
  358.     # do a partial get
  359.     $db->partial_set(0,2) ;
  360.     ok 121, $hash{"red"} eq "bo" ;
  361.     ok 122, $hash{"green"} eq "ho" ;
  362.     ok 123, $hash{"blue"}  eq "se" ;
  363.     # do a partial get, off end of data
  364.     $db->partial_set(3,2) ;
  365.     ok 124, $hash{"red"} eq "t" ;
  366.     ok 125, $hash{"green"} eq "se" ;
  367.     ok 126, $hash{"blue"} eq "" ;
  368.     # switch of partial mode
  369.     $db->partial_clear() ;
  370.     ok 127, $hash{"red"} eq "boat" ;
  371.     ok 128, $hash{"green"} eq "house" ;
  372.     ok 129, $hash{"blue"} eq "sea" ;
  373.     # now partial put
  374.     $db->partial_set(0,2) ;
  375.     ok 130, $hash{"red"} = "" ;
  376.     ok 131, $hash{"green"} = "AB" ;
  377.     ok 132, $hash{"blue"} = "XYZ" ;
  378.     ok 133, $hash{"new"} = "KLM" ;
  379.     $db->partial_clear() ;
  380.     ok 134, $hash{"red"} eq "at" ;
  381.     ok 135, $hash{"green"} eq "ABuse" ;
  382.     ok 136, $hash{"blue"} eq "XYZa" ;
  383.     ok 137, $hash{"new"} eq "KLM" ;
  384.     # now partial put
  385.     $db->partial_set(3,2) ;
  386.     ok 138, $hash{"red"} = "PPP" ;
  387.     ok 139, $hash{"green"} = "Q" ;
  388.     ok 140, $hash{"blue"} = "XYZ" ;
  389.     ok 141, $hash{"new"} = "TU" ;
  390.     $db->partial_clear() ;
  391.     ok 142, $hash{"red"} eq "atPPP" ;
  392.     ok 143, $hash{"green"} eq "ABuQ" ;
  393.     ok 144, $hash{"blue"} eq "XYZXYZ" ;
  394.     ok 145, $hash{"new"} eq "KLMTU" ;
  395. }
  396. {
  397.     # transaction
  398.     my $lex = new LexFile $Dfile ;
  399.     my %hash ;
  400.     my $value ;
  401.     my $home = "./fred" ;
  402.     rmtree $home if -e $home ;
  403.     ok 146, mkdir($home, 0777) ;
  404.     ok 147, my $env = new BerkeleyDB::Env -Home => $home,
  405.      -Flags => DB_CREATE|DB_INIT_TXN|
  406.    DB_INIT_MPOOL|DB_INIT_LOCK ;
  407.     ok 148, my $txn = $env->txn_begin() ;
  408.     ok 149, my $db1 = tie %hash, 'BerkeleyDB::Hash', -Filename => $Dfile,
  409.                                                -Flags     => DB_CREATE ,
  410.         -Env     => $env,
  411.      -Txn    => $txn  ;
  412.     
  413.     # create some data
  414.     my %data =  (
  415. "red" => "boat",
  416. "green" => "house",
  417. "blue" => "sea",
  418. ) ;
  419.     my $ret = 0 ;
  420.     while (my ($k, $v) = each %data) {
  421.         $ret += $db1->db_put($k, $v) ;
  422.     }
  423.     ok 150, $ret == 0 ;
  424.     # should be able to see all the records
  425.     ok 151, my $cursor = $db1->db_cursor() ;
  426.     my ($k, $v) = ("", "") ;
  427.     my $count = 0 ;
  428.     # sequence forwards
  429.     while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
  430.         ++ $count ;
  431.     }
  432.     ok 152, $count == 3 ;
  433.     undef $cursor ;
  434.     # now abort the transaction
  435.     ok 153, $txn->txn_abort() == 0 ;
  436.     # there shouldn't be any records in the database
  437.     $count = 0 ;
  438.     # sequence forwards
  439.     ok 154, $cursor = $db1->db_cursor() ;
  440.     while ($cursor->c_get($k, $v, DB_NEXT) == 0) {
  441.         ++ $count ;
  442.     }
  443.     ok 155, $count == 0 ;
  444.     undef $txn ;
  445.     undef $cursor ;
  446.     undef $db1 ;
  447.     undef $env ;
  448.     untie %hash ;
  449.     rmtree $home ;
  450. }
  451. {
  452.     # DB_DUP
  453.     my $lex = new LexFile $Dfile ;
  454.     my %hash ;
  455.     ok 156, my $db = tie %hash, 'BerkeleyDB::Hash', -Filename => $Dfile,
  456.       -Property  => DB_DUP,
  457.                                       -Flags    => DB_CREATE ;
  458.     $hash{'Wall'} = 'Larry' ;
  459.     $hash{'Wall'} = 'Stone' ;
  460.     $hash{'Smith'} = 'John' ;
  461.     $hash{'Wall'} = 'Brick' ;
  462.     $hash{'Wall'} = 'Brick' ;
  463.     $hash{'mouse'} = 'mickey' ;
  464.     ok 157, keys %hash == 6 ;
  465.     # create a cursor
  466.     ok 158, my $cursor = $db->db_cursor() ;
  467.     my $key = "Wall" ;
  468.     my $value ;
  469.     ok 159, $cursor->c_get($key, $value, DB_SET) == 0 ;
  470.     ok 160, $key eq "Wall" && $value eq "Larry" ;
  471.     ok 161, $cursor->c_get($key, $value, DB_NEXT) == 0 ;
  472.     ok 162, $key eq "Wall" && $value eq "Stone" ;
  473.     ok 163, $cursor->c_get($key, $value, DB_NEXT) == 0 ;
  474.     ok 164, $key eq "Wall" && $value eq "Brick" ;
  475.     ok 165, $cursor->c_get($key, $value, DB_NEXT) == 0 ;
  476.     ok 166, $key eq "Wall" && $value eq "Brick" ;
  477.     #my $ref = $db->db_stat() ; 
  478.     #ok 143, $ref->{bt_flags} | DB_DUP ;
  479.     # test DB_DUP_NEXT
  480.     my ($k, $v) = ("Wall", "") ;
  481.     ok 167, $cursor->c_get($k, $v, DB_SET) == 0 ;
  482.     ok 168, $k eq "Wall" && $v eq "Larry" ;
  483.     ok 169, $cursor->c_get($k, $v, DB_NEXT_DUP) == 0 ;
  484.     ok 170, $k eq "Wall" && $v eq "Stone" ;
  485.     ok 171, $cursor->c_get($k, $v, DB_NEXT_DUP) == 0 ;
  486.     ok 172, $k eq "Wall" && $v eq "Brick" ;
  487.     ok 173, $cursor->c_get($k, $v, DB_NEXT_DUP) == 0 ;
  488.     ok 174, $k eq "Wall" && $v eq "Brick" ;
  489.     ok 175, $cursor->c_get($k, $v, DB_NEXT_DUP) == DB_NOTFOUND ;
  490.     
  491.     undef $db ;
  492.     undef $cursor ;
  493.     untie %hash ;
  494. }
  495. {
  496.     # DB_DUP & DupCompare
  497.     my $lex = new LexFile $Dfile, $Dfile2;
  498.     my ($key, $value) ;
  499.     my (%h, %g) ;
  500.     my @Keys   = qw( 0123 9 12 -1234 9 987654321 9 def  ) ; 
  501.     my @Values = qw( 1    11 3   dd   x abc      2 0    ) ; 
  502.     ok 176, tie %h, "BerkeleyDB::Hash", -Filename => $Dfile, 
  503.      -DupCompare   => sub { $_[0] cmp $_[1] },
  504.      -Property  => DB_DUP|DB_DUPSORT,
  505.      -Flags    => DB_CREATE ;
  506.     ok 177, tie %g, 'BerkeleyDB::Hash', -Filename => $Dfile2, 
  507.      -DupCompare   => sub { $_[0] <=> $_[1] },
  508.      -Property  => DB_DUP|DB_DUPSORT,
  509.      -Flags    => DB_CREATE ;
  510.     foreach (@Keys) {
  511.         local $^W = 0 ;
  512. my $value = shift @Values ;
  513.         $h{$_} = $value ; 
  514.         $g{$_} = $value ;
  515.     }
  516.     ok 178, my $cursor = (tied %h)->db_cursor() ;
  517.     $key = 9 ; $value = "";
  518.     ok 179, $cursor->c_get($key, $value, DB_SET) == 0 ;
  519.     ok 180, $key == 9 && $value eq 11 ;
  520.     ok 181, $cursor->c_get($key, $value, DB_NEXT) == 0 ;
  521.     ok 182, $key == 9 && $value == 2 ;
  522.     ok 183, $cursor->c_get($key, $value, DB_NEXT) == 0 ;
  523.     ok 184, $key == 9 && $value eq "x" ;
  524.     $cursor = (tied %g)->db_cursor() ;
  525.     $key = 9 ;
  526.     ok 185, $cursor->c_get($key, $value, DB_SET) == 0 ;
  527.     ok 186, $key == 9 && $value eq "x" ;
  528.     ok 187, $cursor->c_get($key, $value, DB_NEXT) == 0 ;
  529.     ok 188, $key == 9 && $value == 2 ;
  530.     ok 189, $cursor->c_get($key, $value, DB_NEXT) == 0 ;
  531.     ok 190, $key == 9 && $value  == 11 ;
  532. }
  533. {
  534.     # get_dup etc
  535.     my $lex = new LexFile $Dfile;
  536.     my %hh ;
  537.     ok 191, my $YY = tie %hh, "BerkeleyDB::Hash", -Filename => $Dfile, 
  538.      -DupCompare   => sub { $_[0] cmp $_[1] },
  539.      -Property  => DB_DUP,
  540.      -Flags    => DB_CREATE ;
  541.     $hh{'Wall'} = 'Larry' ;
  542.     $hh{'Wall'} = 'Stone' ; # Note the duplicate key
  543.     $hh{'Wall'} = 'Brick' ; # Note the duplicate key
  544.     $hh{'Smith'} = 'John' ;
  545.     $hh{'mouse'} = 'mickey' ;
  546.     
  547.     # first work in scalar context
  548.     ok 192, scalar $YY->get_dup('Unknown') == 0 ;
  549.     ok 193, scalar $YY->get_dup('Smith') == 1 ;
  550.     ok 194, scalar $YY->get_dup('Wall') == 3 ;
  551.     
  552.     # now in list context
  553.     my @unknown = $YY->get_dup('Unknown') ;
  554.     ok 195, "@unknown" eq "" ;
  555.     
  556.     my @smith = $YY->get_dup('Smith') ;
  557.     ok 196, "@smith" eq "John" ;
  558.     
  559.     {
  560.         my @wall = $YY->get_dup('Wall') ;
  561.         my %wall ;
  562.         @wall{@wall} = @wall ;
  563.         ok 197, (@wall == 3 && $wall{'Larry'} 
  564. && $wall{'Stone'} && $wall{'Brick'});
  565.     }
  566.     
  567.     # hash
  568.     my %unknown = $YY->get_dup('Unknown', 1) ;
  569.     ok 198, keys %unknown == 0 ;
  570.     
  571.     my %smith = $YY->get_dup('Smith', 1) ;
  572.     ok 199, keys %smith == 1 && $smith{'John'} ;
  573.     
  574.     my %wall = $YY->get_dup('Wall', 1) ;
  575.     ok 200, keys %wall == 3 && $wall{'Larry'} == 1 && $wall{'Stone'} == 1 
  576.      && $wall{'Brick'} == 1 ;
  577.     
  578.     undef $YY ;
  579.     untie %hh ;
  580. }
  581. {
  582.    # sub-class test
  583.    package Another ;
  584.    use strict ;
  585.    open(FILE, ">SubDB.pm") or die "Cannot open SubDB.pm: $!n" ;
  586.    print FILE <<'EOM' ;
  587.    package SubDB ;
  588.    use strict ;
  589.    use vars qw( @ISA @EXPORT) ;
  590.    require Exporter ;
  591.    use BerkeleyDB;
  592.    @ISA=qw(BerkeleyDB::Hash);
  593.    @EXPORT = @BerkeleyDB::EXPORT ;
  594.    sub db_put { 
  595. my $self = shift ;
  596.         my $key = shift ;
  597.         my $value = shift ;
  598.         $self->SUPER::db_put($key, $value * 3) ;
  599.    }
  600.    sub db_get { 
  601. my $self = shift ;
  602.         $self->SUPER::db_get($_[0], $_[1]) ;
  603. $_[1] -= 2 ;
  604.    }
  605.    sub A_new_method
  606.    {
  607. my $self = shift ;
  608.         my $key = shift ;
  609.         my $value = $self->FETCH($key) ;
  610. return "[[$value]]" ;
  611.    }
  612.    1 ;
  613. EOM
  614.     close FILE ;
  615.     BEGIN { push @INC, '.'; }    
  616.     eval 'use SubDB ; ';
  617.     main::ok 201, $@ eq "" ;
  618.     my %h ;
  619.     my $X ;
  620.     eval '
  621. $X = tie(%h, "SubDB", -Filename => "dbhash.tmp", 
  622. -Flags => DB_CREATE,
  623. -Mode => 0640 );
  624. ' ;
  625.     main::ok 202, $@ eq "" ;
  626.     my $ret = eval '$h{"fred"} = 3 ; return $h{"fred"} ' ;
  627.     main::ok 203, $@ eq "" ;
  628.     main::ok 204, $ret == 7 ;
  629.     my $value = 0;
  630.     $ret = eval '$X->db_put("joe", 4) ; $X->db_get("joe", $value) ; return $value' ;
  631.     main::ok 205, $@ eq "" ;
  632.     main::ok 206, $ret == 10 ;
  633.     $ret = eval ' DB_NEXT eq main::DB_NEXT ' ;
  634.     main::ok 207, $@ eq ""  ;
  635.     main::ok 208, $ret == 1 ;
  636.     $ret = eval '$X->A_new_method("joe") ' ;
  637.     main::ok 209, $@ eq "" ;
  638.     main::ok 210, $ret eq "[[10]]" ;
  639.     unlink "SubDB.pm", "dbhash.tmp" ;
  640. }