package XSTAB::Storage::XDbiMySQL; # This module stores data with DBI::MySQL # # $Id: XDbiMySQL.pm,v 1.13 2003/03/23 09:34:31 dranok Exp $ # # This module is released under the GPL # Author: DranoK # Email: dranok@users.sourceforge.net # Documentation: http://xstab.sourceforge.net ##############################################
XSTAB::Storage::XDbiMySQL
This storage module will store player records in a MySQL database
use DBI; use XSTAB::XData; use strict; my $VERSION = "0.9"; my @db_rows = ();
NOTE: Beware of using XA_, for if you do so, your DB table will become HUGE, and sorting through it will become a nightmare.
sub create { my $class = shift; my $self = { }; $self->{dbh} = DBI->connect("DBI:mysql:database=$Global{DB}:host=$Global{DBHost}", "$Global{DBUser}", "$Global{DBPass}") or die "Cannot connect: " . $DBI::errstr; # Find the fields which need saving my $query_sth = $self->{dbh}->prepare("SHOW COLUMNS FROM $Global{DBTable}"); $query_sth->execute or die "Couldn't run SHOW query!"; while (my $result = $query_sth->fetchrow_hashref()) { if ($result->{Field} ne 'id') { push(@db_rows, $result->{Field}); } } # Create the insert statement my $query = "INSERT INTO $Global{DBTable} ("; foreach my $field (@db_rows) { if ($field =~ /XI_/) { next; } else { $query .= "$field, "; } } $query =~ s/, $//; $query .= ") VALUES ("; foreach my $field (@db_rows) { $query .= "?, "; } $query =~ s/, $//; $query .= ")"; $self->{sth_insert} = $self->{dbh}->prepare($query) or die "Could not perform prepare query!\n"; # Create the update statement $query = "UPDATE $Global{DBTable} SET "; foreach my $field (@db_rows) { if ($field =~ /XI_/) { next; } elsif ($field =~ /XA_(.*)/) { my $newfield = $1; $query .= "$newfield=concat($newfield,?), "; } else { $query .= "$field=?, "; } } $query =~ s/, $//; $query .= " WHERE $Global{uid}=?"; $self->{sth_update} = $self->{dbh}->prepare($query) or die "Could not perform prepare query!\n"; # Create the select new player statement $query = "SELECT "; foreach my $field (@db_rows) { if ($field !~ /XA_/ && $field !~ /XI_/) { $query .= "$field,"; } } $query =~ s/,$//; $query .= " FROM $Global{DBTable} WHERE $Global{uid}=?"; $self->{sth_select} = $self->{dbh}->prepare($query) or die "Could not perform prepare query!\n"; # Create the delete statement $query = "DELETE FROM $Global{DBTable} WHERE $Global{uid}=?"; $self->{sth_delete} = $self->{dbh}->prepare($query) or die "Could not perform prepare query!\n"; # Create the admin log statement $query = "INSERT INTO $Global{Admin_table} (id, date, admin_id, victim_id, command) VALUES ('', ?, ?, ?, ?)"; $self->{sth_admin} = $self->{dbh}->prepare($query) or die "Could not perform prepare query!\n"; bless($self, $class); return $self }
sub DESTROY { my $self = shift; $self->{dbh}->disconnect(); }
sub do_admin { my $self = shift; if (!scalar(@Admin_queue)) { return; } my @tmpar = split($Global{sp}, pop(@Admin_queue)); $self->{sth_admin}->execute( @tmpar ) or die "Couldn't run INSERT for admin log!\n"; }
sub do_log { my $string = shift; my $prio = shift; XSTAB::XData::do_log("Storage::XDbiMySQL: $string", $prio); }
This method will set $Players{ClientID}{use_update} to be '1' so saves will use UPDATE instead of INSERT. If no data is returned from the DB (ie, the player did not exist), this will not be set, thus INSERT will be used. If the exact right things go wrong it is possible for duplicate entires to be created.
sub load_player_hash { my $self = shift; my $client = shift; $self->{sth_select}->execute($Players{$client}{$Global{uid}}) or die "Couldn't run SELECT to load new player!\n"; while (my $ref = $self->{sth_select}->fetchrow_hashref()) { $Players{$client}{use_update} = 1; foreach my $elem (@db_rows) { if ($elem =~ /XS_(.*)/) { my $newfield = $1; XSerialStore($client, $newfield, $ref->{$elem}); } else { $Players{$client}{$elem} = $ref->{$elem}; } } } do_log("Loaded player: $Players{$client}{name}", 3); }
sub save_player_hash { my $self = shift; my $client = shift; if (!$Players{$client}{$Global{uid}}) { return; } my @tmpar = (); foreach my $elem (@db_rows) { if ($elem =~ /XI_/) { next; } elsif ($elem =~ /XS_(.*)/) { my $newfield = $1; if ($Players{$client}{$newfield}) { my $tstr = XSerialize($client, $newfield); if ($tstr) { push(@tmpar, $tstr); } else { push(@tmpar, ''); } } else { push(@tmpar, ''); } } elsif ($elem =~ /XA_(.*)/) { my $newfield = $1; if ($Players{$client}{$newfield}) { push(@tmpar, $Players{$client}{$newfield}); delete $Players{$client}{$newfield}; } } else { if ($Players{$client}{$elem}) { push(@tmpar, $Players{$client}{$elem}); } else { push(@tmpar, '0'); } } } if ($Players{$client}{use_update}) { push(@tmpar, $Players{$client}{$Global{uid}}); $self->{sth_update}->execute( @tmpar ) or die "Couldn't run UPDATE to update player with uid $Players{$client}{$Global{uid}}!\n"; } else { $self->{sth_insert}->execute( @tmpar ) or die "Couldn't run INSERT to add player!\n"; $Players{$client}{use_update} = 1; } do_log("Saved Player: $Players{$client}{name}", 3); }
sub delete_record { my $self = shift; my $client = shift; if ($Players{$client}{$Global{uid}}) { $self->{sth_delete}->execute( $Players{$client}{$Global{uid}} ); } } 1;
This module was coded by DranoK and is part of the core XStab modules. You may directly contact DranoK at dranok@users.sourceforge.net, or by posting to the forums at:
http://www.oltl.net/forums/forumdisplay.php?s=&forumid=25