package DBIx::XML::DataLoader::DB; use strict; use warnings; ########################################################################### ## Description of Subs ########################################################################### ## ## DBConnect ## ## requires no arguments ## returns a db connection handle ## ## DBprepareOut ## ## arguments for this sub are the table name a array ref to the columns, ## and the variable holding the db connection ## This sub then returns the statement handle for doing the select ## ## ########################################################################### ########################################################################### use DBI; # DataBase Interface Modlule #use DBD::Oracle; # Oracle Specific Driver for DBI ## I am just trying to load all the DBD drivers available ## you might want to limit this in some way. my @driver_names = DBI->available_drivers; for my $drv (@driver_names){ eval "use DBD::$drv;"; # loading available driver } ################## sub new{ ######## my $class=shift; my $self={}; my %args=@_; my $dbmode=$args{dbmode}||"insertupdate"; my $dbprint=$args{dbprint}||undef; $self->{dbprint}=$dbprint; $self->{dbmode}=$dbmode; bless ($self, $class); ####### } # end sub new ################## ##################### sub DBConnect{ ############## ## requires no arguments ## returns a db connection handle my $self =shift; my $DBLOG = shift; my $DBPWD= shift; my $DATA_SOURCE=shift; #print $self, "+", $DBLOG, "-", $DBPWD, "[",$DATA_SOURCE,"]"; #if(!$DATA_SOURCE){die "did not get a datasource";} # Connect to the database with auto-commit enabled my $dbh = DBI->connect($DATA_SOURCE, $DBLOG, $DBPWD, { PrintError => 0, AutoCommit => 1, }) || die "Could not Connect to Database! Oracle Error was: $DBI::errstr\n"; return($dbh); ############ } # end sub DBConnect; ############################### ############################## sub DBInsertUpdate{ ################## my $self=shift; my %args=@_; my $dbprint=$args{dbprint}||$self->{dbprint}||undef; my $dbmode=$args{dbmode}||$self->{dbmode}||"insertupdate"; my $dbhstuff=$args{dbconnections}; my @arrayoftableinfo=@{$args{datainfo}}; my $message; my $error; my $sqlload; TABLE: for my $tabinfo (@arrayoftableinfo){ my $update; my @upkeys; my @insert_vals; my @insert_cols; my @update; my @upkeystring; my $results=$tabinfo->{results}; my @thecols=@{$tabinfo->{cols}}; my $table=$tabinfo->{table}; @{$sqlload->{$table}->{cols}}=@thecols; #### added to order update keys #### my @hashed_upkeys=@{$tabinfo->{keys}}; my $keyorder=1; HASHED_KEYS:for (@hashed_upkeys){ for my $key (keys %{$_}){ #print $key, ":", $_->{$key},":",$keyorder,"\n"; if($key == $keyorder){ push @upkeys, $_->{$key}; $keyorder++;next HASHED_KEYS; } push @hashed_upkeys, $_; } # end keylop } # end loop HASHED_KEYS ################################################## my @results=@{$results}; my $dbh=$dbhstuff->{$tabinfo->{dbname}}; if($dbh !~ /DBI::/){next TABLE;} for my $result (@results){ my $q_value=$result->{val}; if(($result->{val} ne "SYSDATE")and($dbmode ne "sqlloader")){ #$q_value=qq[\'$result->{val}\'];} $q_value=$dbh->quote($result->{val});} push @insert_cols, $result->{col}; push @insert_vals, $q_value; if($result->{key}){ my $upk=$result->{col}."=".$q_value; push @upkeystring, $upk; } if((!$result->{key})and($result->{col} !~ /^CREATE/)){ my $up=$result->{col}."=".$q_value; push @update, $up;} } # end for @results; my $updateset=join ", ", @update; my $upkeysstring=join " and ", @upkeystring; my $inscols=join ", ", @insert_cols; my $insertstuff=join ", ", @insert_vals; if(($dbprint eq "print")or($dbprint eq "dbandprint")){ $message.="\nHere is what would be placed in the table $table\n"; if($dbmode =~ /update/){ $message.= "UPDATE $table SET\n".$updateset. "\nWHERE\n". $upkeysstring."\n"; } if($dbmode =~ /insert/){ $message.="\nINSERT\n(".$insertstuff.")\nVALUES\n(".$inscols.")\nINTO $table\n"; } } if($dbprint ne "print"){ if($dbmode eq "insertupdate"){ $message.="\nAttempting to insert into table $table\n"; my $local_error; $dbh->do(qq{insert INTO $table ($inscols) VALUES($insertstuff)}) or $local_error=$DBI::errstr; if(!$local_error){$message .= "\nInsert was successful for table $table\n";} if($local_error){ $message.="\nInsert did not succeed. Now trying to update table $table instead\n"; if($local_error =~ /unique constraint/){ $dbh->do(qq{update $table set $updateset where $upkeysstring}) or my $uperror="db error when working with table $table:\n$DBI::errstr\n"; if(!$uperror){$message.="\nUpdate did succeed for Table $table";} if($uperror){$error.=$uperror;} } if($local_error !~ /unique constraint/){ $error.="db error when working with table $table:\n$local_error\n"; } } } if($dbmode eq "update"){ $message.="\nAttempting to make updates in table $table\n"; $dbh->do(qq{update $table set $updateset where $upkeysstring}) or my $uperror="db error when working with table $table:\n$DBI::errstr\n"; if(!$uperror){$message.="\nUpdate did succeed for Table $table";} if($uperror){$error.=$uperror;} } if($dbmode eq "insert"){ $message.="\nAttempting to insert rows in table $table\n"; $dbh->do(qq{insert INTO $table ($inscols) VALUES($insertstuff)}) or my $inerror="db error when working with table $table:\n$DBI::errstr\n"; if(!$inerror){$message.="\nInsert was successful for Table $table";} if($inerror){$error.=$inerror;} } if($dbmode eq "sqlloader"){ $message.="\nAdding to sqlload for table $table\n"; $sqlload->{$table}->{values}.=(join "::", @insert_vals)."::\n"; } } } # end for $tabinfo return ($message, $error, $sqlload); ###################### } # end DBInsertUpdate ####################################### ############### sub sqldate{ ########### ## this sub take 4 arguments passed as variables ## $dbh a open db handle ## $date which should be the actual date you want converted ## $format the current format the date helf in $date is in (yy-mm-dd yyyy-mm-dd dd-mm-yy etc) ## $table a valid table in your sql view ## returned is a date that will conform to the SQL database format for dates my $self=shift; if((scalar @_) < 4){return;} my $dbh=shift; my $date=shift; my $format=shift; my $table=shift; my $qdate=$dbh->quote($date); my $qformat=$dbh->quote($format); my $converted_date; my $datekey=qq{TO_DATE($qdate, $qformat)}; my $datetest=$dbh->prepare(qq{select UNIQUE $datekey from $table})||warn "dbi error $DBI::errstr"; #my $datetest=$dbh->prepare(qq{select UNIQUE SYSDATE from rod_trans_request}); #if($datetest){ $datetest->execute()||warn "dbi error $DBI::errstr";; while(my $hash_ref=$datetest->fetchrow_hashref()){ for (keys %{$hash_ref}){ $converted_date=$hash_ref->{$_};last;} #} } return $converted_date; ############ } # end sqldate ################# ############### sub conv_sqldate{ ########### ## this sub take 4 arguments passed as variables ## $dbh a open db handle ## $date which should be the actual date you want converted ## $format the current format the date helf in $date is in (yy-mm-dd yyyy-mm-dd dd-mm-yy etc) ## $table a valid table in your sql view ## returned is a date that will conform to the SQL database format for dates my $self=shift; if((scalar @_) < 4){return;} my $dbh=shift; my $date=shift; my $format=shift; my $table=shift; my $org_format="DD-MON-YY"; my $qorg_format=$dbh->quote($org_format); my $qdate=$dbh->quote($date); my $qformat=$dbh->quote($format); my $converted_date; my $datekey=qq{TO_DATE($qdate, $qorg_format)}; ## here we first alter the way time is outputted my $datetest=$dbh->prepare(qq{alter session set nls_date_format=$qformat})||warn "dbi error $DBI::errstr"; $datetest->execute()||warn "dbi error $DBI::errstr"; $datetest=$dbh->prepare(qq{select UNIQUE $datekey from $table})||warn "dbi error $DBI::errstr"; #my $datetest=$dbh->prepare(qq{select UNIQUE SYSDATE from rod_trans_request}); #if($datetest){ $datetest->execute()||warn "dbi error $DBI::errstr";; while(my $hash_ref=$datetest->fetchrow_hashref()){ for (keys %{$hash_ref}){ $converted_date=$hash_ref->{$_};last;} #} } $datetest=$dbh->prepare(qq{alter session set nls_date_format=$qorg_format})||warn "dbi error $DBI::errstr"; $datetest->execute()||warn "dbi error $DBI::errstr"; return $converted_date; ############## } # end conv_sqldate ####################### 1; __END__ =head1 NAME DBIx::XML::DataLoader::DB =head1 SYNOPSIS use DBIx::XML::DataLoader::DB; my $db=DB->new(dbmode=>"insertupdate", dbprint=>"dbprint"); my $dbh=$db->DBConnect($DBLOG, $DBPASS, $DATA_SOURCE); my ($response, $error,$load)=$db->DBInsertUpdate( datainfo=>\@inserts_data, dbconnections=>$db_connections ); =head1 DESCRIPTION This module is hard coded for use with oracle. To change this setting edit the line use DBI::Oracle to reflect your database choice =for man This module is used primarily inside DataLoader.pm . It is also used in the sample script query_db.pl =for text This module is used primarily inside DataLoader.pm . It is also used in the sample script query_db.pl =for html
       This module is used primarily inside DataLoader.pm. It is also used in the sample 
       script query_cb.pl
DBInsertUpdate needs passed to a hash containing a arrayref to a array of hashes containing the data that will be worked with, and dbconnections a hashref to a hash of dbconnections keyed by handle names. The hashes contained in the array of data should have the folowing keys cols: a array of the columns that are in this table table: the name of the table for this data keys: the key columns in the table results: a array of row hashes containing the data for each cell in the a table row. The hashes are keyed by column name. dbname: the name of the db handle that will be used. The hash containing the dbconnections contains blessed db connection objects keyed by handle names. The items returned by the module are message, errors, and load(if dbmode=>"sqlloader"); =head1 Options These are the options you can pass to DB.pm dbmode: Options are insertupdate: attempts to do a update and if that fails, a insert is done insert: attempts to do a insert only update: attempts to do a update only sqlloader: passes back a extra varibale that will contain data suitable for writing to a file for use with sqlloader default is insertupdate dbprint: Options are db: tells the module to do the selected dbmode print: simulate doing the dbmode, and add to $response the statements that would have been passed to the database dbandprint: do both the operations above. default is db =head1 Also see man page for =for html                DBIx::XML::DataLoader::XMLWriter,  and DBIx::XML::DataLoader =for man DBIx::XML::DataLoader::XMLWriter and DBIx::XML::DataLoader =for text DBIx::XML::DataLoader::XMLWriter and DBIx::XML::DataLoader =head1 Sample Scripts =for man query_db.pl =for text query_db.pl =for html                =for html