--- nfo/perl/libs/Data/Storage/Handler/DBI.pm 2002/12/01 07:09:09 1.7 +++ nfo/perl/libs/Data/Storage/Handler/DBI.pm 2003/04/09 06:06:04 1.14 @@ -1,8 +1,31 @@ ################################# # -# $Id: DBI.pm,v 1.7 2002/12/01 07:09:09 joko Exp $ +# $Id: DBI.pm,v 1.14 2003/04/09 06:06:04 joko Exp $ # # $Log: DBI.pm,v $ +# Revision 1.14 2003/04/09 06:06:04 joko +# sendQuery now is capable of doing 'SELECT'- or 'INSERT'-queries +# +# Revision 1.13 2003/04/08 23:06:45 joko +# renamed core database helper functions +# +# Revision 1.12 2003/01/30 22:28:21 joko +# + implemented new concrete methods +# +# Revision 1.11 2002/12/19 16:31:05 joko +# + sub dropDb +# + sub rebuildDb +# +# Revision 1.10 2002/12/15 02:02:22 joko +# + fixed logging-message +# +# Revision 1.9 2002/12/05 07:58:20 joko +# + now using Tie::SecureHash as a base for the COREHANDLE +# + former public COREHANDLE becomes private _COREHANDLE now +# +# Revision 1.8 2002/12/01 22:20:43 joko +# + sub createDb (from Storage.pm) +# # Revision 1.7 2002/12/01 07:09:09 joko # + sub getListFiltered (dummy redirecting to getListUnfiltered) # @@ -37,11 +60,13 @@ use base ("Data::Storage::Handler::Abstract"); + use DBI; use Data::Dumper; -use libdb qw( getDbNameByDsn hash2Sql ); +use shortcuts::db qw( hash2sql dsn2dbname ); use Data::Storage::Result::DBI; + # get logger instance my $logger = Log::Dispatch::Config->instance; @@ -71,8 +96,8 @@ #use Data::Dumper; print Dumper($self->{dbi}); eval { - $self->{COREHANDLE} = DBI->connect( $dsn, '', '', $self->{locator}->{dbi} ); - if (!$self->{COREHANDLE}) { + $self->{_COREHANDLE} = DBI->connect( $dsn, '', '', $self->{locator}->{dbi} ); + if (!$self->{_COREHANDLE}) { $logger->warning( __PACKAGE__ . "->connect failed: " . DBI::errstr ); return; } @@ -94,18 +119,20 @@ $logger->debug( __PACKAGE__ . "->configureCOREHANDLE" ); + return if !$self->{_COREHANDLE}; + # apply configured modifications to DBI-handle if (exists $self->{locator}->{dbi}->{trace_level} && exists $self->{locator}->{dbi}->{trace_file}) { - $self->{COREHANDLE}->trace($self->{locator}->{dbi}->{trace_level}, $self->{locator}->{dbi}->{trace_file}); + $self->{_COREHANDLE}->trace($self->{locator}->{dbi}->{trace_level}, $self->{locator}->{dbi}->{trace_file}); } if (exists $self->{locator}->{dbi}->{RaiseError}) { - $self->{COREHANDLE}->{RaiseError} = $self->{locator}->{dbi}->{RaiseError}; + $self->{_COREHANDLE}->{RaiseError} = $self->{locator}->{dbi}->{RaiseError}; } if (exists $self->{locator}->{dbi}->{PrintError}) { - $self->{COREHANDLE}->{PrintError} = $self->{locator}->{dbi}->{PrintError}; + $self->{_COREHANDLE}->{PrintError} = $self->{locator}->{dbi}->{PrintError}; } if (exists $self->{locator}->{dbi}->{HandleError}) { - $self->{COREHANDLE}->{HandleError} = $self->{locator}->{dbi}->{HandleError}; + $self->{_COREHANDLE}->{HandleError} = $self->{locator}->{dbi}->{HandleError}; } } @@ -116,18 +143,18 @@ # two-level handling for implicit connect: # if there's no corehandle ... - if (!$self->{COREHANDLE}) { + if (!$self->{_COREHANDLE}) { # ... try to connect, but ... $self->connect(); # ... if this still fails, there's something wrong probably, so we won't continue - if (!$self->{COREHANDLE}) { + if (!$self->{_COREHANDLE}) { return; } } #print "prepare sql: $sql\n"; - my $sth = $self->{COREHANDLE}->prepare($sql); + my $sth = $self->{_COREHANDLE}->prepare($sql); $sth->execute(); return $sth; } @@ -146,8 +173,10 @@ my $self = shift; my @nodes; $logger->debug( __PACKAGE__ . "->getChildNodes()" ); + my $locator = $self->{locator}; + #print Dumper($locator); exit; if (my $result = $self->sendCommand( 'SHOW TABLES;' ) ) { - my $dbname = getDbNameByDsn($self->{locator}->{dbi}->{dsn}); + my $dbname = dsn2dbname($self->{locator}->{dbi}->{dsn}); my $key = "Tables_in_$dbname"; while ( my $row = $result->getNextEntry() ) { push @nodes, $row->{$key}; @@ -172,6 +201,17 @@ sub sendQuery { my $self = shift; my $query = shift; + + $logger->debug( __PACKAGE__ . "->sendQuery" ); + + my $action = $query->{options}->{action}; + $action ||= 'load'; + + if (my $guid = $query->{options}->{GUID}) { + $query->{criterias} = [ { key => 'guid', op => 'eq', val => $guid } ]; + } + + # check criterias (load & save) #my $sql = "SELECT cs FROM $self->{metainfo}->{$descent}->{node} WHERE $self->{metainfo}->{$descent}->{IdentProvider}->{arg}='$self->{entry}->{source}->{ident}';"; #my $result = $self->{metainfo}->{$descent}->{storage}->sendCommand($sql); my @crits; @@ -180,17 +220,32 @@ $op = '=' if lc $_->{op} eq 'eq'; push @crits, "$_->{key}$op'$_->{val}'"; } - my $subnodes = {}; - map { $subnodes->{$_}++ } @{$query->{subnodes}}; # HACK: this is hardcoded ;( expand possibilities! my $crit = join(' AND ', @crits); - my $sql = hash2Sql($query->{node}, $subnodes, 'SELECT', $crit); - return $self->sendCommand($sql); + + # check subnodes (load) + my $subnodes = {}; + map { $subnodes->{$_}++ } @{$query->{subnodes}}; + + # check payload (save) + #print Dumper($query->{payload}); + #$subnodes ||= $query->{payload}; + + # dispatch action + if ($action eq 'load') { + my $sql = hash2sql($query->{node}, $subnodes, 'SELECT', $crit); + return $self->sendCommand($sql); + } elsif ($action eq 'save') { + my $sql = hash2sql($query->{node}, $query->{payload}, 'UPDATE', $crit); + $self->sendCommand($sql); + } + } sub eraseAll { my $self = shift; my $classname = shift; + $logger->debug( __PACKAGE__ . "->eraseAll" ); my $sql = "DELETE FROM $classname"; $self->sendCommand($sql); } @@ -202,4 +257,118 @@ return $self->getListUnfiltered($nodename); } +# TODO: do this via a parametrized "$self->connect()" +sub createDb { + + my $self = shift; + + # get dsn from Data::Storage::Locator instance + my $dsn = $self->{locator}->{dbi}->{dsn}; + + $logger->debug( __PACKAGE__ . "->createDb( dsn $dsn )" ); + + # remove database setting from dsn-string + $dsn =~ s/database=(.+?);//; + + # remember extracted database name to know what actually to create right now + my $database_name = $1; + + # flag to indicate goodness + my $ok; + + # connect to database server - don't select/use any specific database + #if ( my $dbh = DBI->connect($dsn, '', '', { PrintError => 0 } ) ) { + if ( my $dbh = DBI->connect($dsn, '', '', $self->{locator}->{dbi} ) ) { + + if ($database_name) { + if ($dbh->do("CREATE DATABASE $database_name")) { + $ok = 1; + } + } + + $dbh->disconnect(); + + } + + return $ok; + +} + +sub getCOREHANDLE2 { + my $self = shift; + return $self->{_COREHANDLE}; +} + +sub dropDb { + my $self = shift; + my $dsn = $self->{locator}->{dbi}->{dsn}; + + $logger->debug( __PACKAGE__ . "->dropDb( dsn $dsn )" ); + + $dsn =~ s/database=(.+?);//; + my $database_name = $1; + + my $ok; + + if ( my $dbh = DBI->connect($dsn, '', '', { + PrintError => 0, + } ) ) { + if ($database_name) { + if ($dbh->do("DROP DATABASE $database_name;")) { + $ok = 1; + } + } + + $dbh->disconnect(); + + } + + return $ok; +} + +sub rebuildDb { + my $self = shift; + $logger->info( __PACKAGE__ . "->rebuildDb()" ); + my @results; + + # sum up results (bool (0/1)) in array + #push @results, $self->retreatSchema(); + push @results, $self->dropDb(); + push @results, $self->createDb(); + #push @results, $self->deploySchema(); + + # scan array for "bad ones" + my $res = 1; + map { + $res = 0 if (!$_); + } @results; + + return $res; +} + +sub testAvailability { + my $self = shift; + my $status = $self->testDsn(); + $self->{locator}->{status}->{available} = $status; + return $status; +} + +sub testDsn { + my $self = shift; + my $dsn = $self->{locator}->{dbi}->{dsn}; + my $result; + if ( my $dbh = DBI->connect($dsn, '', '', { + PrintError => 0, + } ) ) { + + # TODO: REVIEW + $dbh->disconnect(); + + return 1; + } else { + $logger->warning( __PACKAGE__ . "[$self->{locator}->{type}]" . "->testDsn(): " . "DBI-error: " . $DBI::errstr ); + } +} + 1; +__END__