package main;
+eval {
+ # This wrapper's sole purpose in life is to keep the dbh connection open.
+ package Bloot::DBI;
+
+ # These are DBI methods which do not require an active DB
+ # connection. [Eg, don't check to see if the database is working
+ # by pinging it for these methods.]
+ my %no_ping;
+ @no_ping{qw(ping err err_str quote disconnect clone)} = (1) x 6;
+ sub new {
+ my $class = shift;
+ my $dbh = shift;
+ return undef unless $dbh;
+ $class = ref($class) if ref($class);
+ my $self = {dbh=>$dbh};
+ bless $self, $class;
+ return $self;
+ }
+
+ our $AUTOLOAD;
+ sub AUTOLOAD {
+ my $method = $AUTOLOAD;
+ my $self = shift;
+ die "Undefined subroutine $method called" unless defined $self;
+ ($method) = $method =~ /([^\:]+)$/;
+ unshift @_, $self->{dbh};
+ return undef if not defined $self->{dbh};
+ goto &{$self->{dbh}->can($method)} if exists $no_ping{$method} and $no_ping{$method};
+ my $ping_count = 0;
+ while (++$ping_count < 10){
+ last if $self->{dbh}->ping;
+ $self->{dbh}->disconnect;
+ $self->{dbh} = $self->{dbh}->clone;
+ }
+ if ($ping_count >=10 and not $self->{dbh}->ping){
+ &ERROR("Tried real hard but was unable to reconnect");
+ return undef;
+ }
+ $_[0] = $self->{dbh};
+ my $coderef = $self->{dbh}->can($method);
+ goto &$coderef if defined $coderef;
+ # Dumb DBI doesn't have a can method for some
+ # functions. Like func.
+ shift;
+ return eval "\$self->{dbh}->$method(\@_)" or die $@;
+ }
+ 1;
+};
+
#####
# &sqlOpenDB($dbname, $dbtype, $sqluser, $sqlpass, $nofail);
sub sqlOpenDB {
my ($db, $type, $user, $pass, $no_fail) = @_;
# this is a mess. someone fix it, please.
- if ($type =~ /^SQLite$/i) {
+ if ($type =~ /^SQLite(2)?$/i) {
$db = "dbname=$db.sqlite";
} elsif ($type =~ /^pg/i) {
$db = "dbname=$db";
$hoststr = " to $param{'SQLHost'}";
}
# SQLite ignores $user and $pass
- $dbh = DBI->connect($dsn, $user, $pass);
+ $dbh = Bloot::DBI->new(DBI->connect($dsn, $user, $pass));
if ($dbh && !$dbh->err) {
&status("Opened $type connection$hoststr");
return;
}
- $query .= " WHERE" if (($where_href) || ($other));
if ($where_href) {
my $where = &hashref2where($where_href);
- $query .= " $where" if ($where);
+ $query .= " WHERE $where" if ($where);
}
- $query .= " $other" if $other;
+ $query .= " $other" if ($other);
if (!($sth = $dbh->prepare($query))) {
&ERROR("sqlSelectMany: prepare: $DBI::errstr");
}
&SQLDebug($query);
- if (!$sth->execute) {
- &ERROR("sqlSelectMany: execute: '$query'");
- return;
- }
+
+ return if (!$sth->execute);
return $sth;
}
my $result = &sqlSelect($table, $k, $where_href);
# &DEBUG("result is not defined :(") if (!defined $result);
- if (1 or defined $result) {
+ # this was hardwired to use sqlUpdate. sqlite does not do inserts on sqlUpdate.
+ if (defined $result) {
&sqlUpdate($table, $data_href, $where_href);
} else {
# hack.
if (!defined $data_href or ref($data_href) ne "HASH") {
&WARN("sqlSet: data_href == NULL.");
- return;
+ return 0;
}
my $where = &hashref2where($where_href) if ($where_href);
sub countKeys {
my ($table, $col) = @_;
$col ||= "*";
- &DEBUG("&countKeys($table, $col);");
return (&sqlRawReturn("SELECT count($col) FROM $table"))[0];
}
# Usage: &randKey($table, $select);
sub randKey {
my ($table, $select) = @_;
- my $rand = int(rand(&countKeys($table) - 1));
- my $query = "SELECT $select FROM $table LIMIT $rand,1";
- if ($param{DBType} =~ /^pg/i) {
- $query =~ s/$rand,1/1,$rand/;
+ my $rand = int(rand(&countKeys($table)));
+ my $query = "SELECT $select FROM $table LIMIT 1 OFFSET $rand";
+ if ($param{DBType} =~ /^mysql$/i) {
+ # WARN: only newer MySQL supports "LIMIT limit OFFSET offset"
+ $query = "SELECT $select FROM $table LIMIT $rand,1";
}
-
my $sth = $dbh->prepare($query);
&SQLDebug($query);
&WARN("randKey($query)") unless $sth->execute;
$str =~ s/\*/%/g;
# end of string fix.
- my $query = "SELECT $select FROM $table WHERE $key LIKE ".
+ my $query = "SELECT $select FROM $table WHERE $key LIKE ".
&sqlQuote($str);
my $sth = $dbh->prepare($query);
foreach (@path) {
my $file = "$_/setup/$table.sql";
- &DEBUG("dbCT: table => '$table', file => '$file'");
next unless ( -f $file );
- &DEBUG("dbCT: found!!!");
-
open(IN, $file);
while (<IN>) {
chop;
}
# retrieve a list of db's from the server.
- foreach ($dbh->func('_ListTables')) {
- $db{$_} = 1;
- }
+ my @tables = map {s/^\`//; s/\`$//; $_;} $dbh->func('_ListTables');
+ if ($#tables == -1){
+ @tables = $dbh->tables;
+ }
+ &status("Tables: ".join(',',@tables));
+ @db{@tables} = (1) x @tables;
- } elsif ($param{DBType} =~ /^SQLite$/i) {
+ } elsif ($param{DBType} =~ /^SQLite(2)?$/i) {
# retrieve a list of db's from the server.
foreach ( &sqlRawReturn("SELECT name FROM sqlite_master WHERE type='table'") ) {
$db{$_} = 1;
}
- # create database.
- if (!scalar keys %db) {
- &status("Creating database $param{'DBName'}...");
- my $query = "CREATE DATABASE $param{'DBName'}";
- &sqlRaw("create(db $param{'DBName'})", $query);
- }
+ # create database not needed for SQLite
}
- foreach ( qw(factoids rootwarn seen stats botmail) ) {
- next if (exists $db{$_});
+ foreach ( qw(botmail connections factoids rootwarn seen stats onjoin) ) {
+ if (exists $db{$_}) {
+ $cache{has_table}{$_} = 1;
+ next;
+ }
+
&status("checkTables: creating new table $_...");
+ $cache{create_table}{$_} = 1;
+
&sqlCreateTable($_);
}
}