311 lines
9.1 KiB
Perl
311 lines
9.1 KiB
Perl
package GT::Session::TempTable;
|
|
# ===============================================================
|
|
# Pragmas
|
|
use strict;
|
|
use vars qw| $ATTRIBS @ISA $ERRORS |;
|
|
|
|
# Internal nodules
|
|
use GT::Base;
|
|
use GT::SQL;
|
|
use GT::MD5 qw| md5_hex |;
|
|
|
|
# Global variable init
|
|
@ISA = qw| GT::Base |;
|
|
|
|
$ATTRIBS = {
|
|
id => undef,
|
|
tb => undef,
|
|
|
|
def_path => '',
|
|
db => undef,
|
|
set_name => 'Set_Sessions',
|
|
create_session => undef,
|
|
delete_session => undef,
|
|
seconds => 60*60,
|
|
sid => ''
|
|
};
|
|
|
|
$ERRORS = {
|
|
'NODB' => "No GT::SQL object, need to set 'db' or 'def_path'",
|
|
'NOCS' => "No session creation hook specified",
|
|
'CSNOTCODE' => "Session creation hook is not a coderef",
|
|
'NOSID' => "No session ID",
|
|
'BADDATA' => "Invalid data in session: '%s'. Reason: '%s'",
|
|
'CLASSFUNC' => "This is a class function only.",
|
|
'INVALIDSESSION'=> "Invalid session id: '%s'.",
|
|
'BADARGS' => "Invalid arguments: %s",
|
|
|
|
};
|
|
|
|
sub install {
|
|
#-------------------------------------------------------------------------------
|
|
# creates the controller table
|
|
#
|
|
my $self = shift;
|
|
my $DB = $self->_db();
|
|
|
|
my $c = $DB->creator( $self->{set_name} );
|
|
|
|
$c->cols(
|
|
ID => { pos => 1, type => 'INT', not_null => 1, unsigned => 1, regex => '^d+$' },
|
|
SessID => { pos => 2, type => 'CHAR', size => 100, not_null => 1 },
|
|
SessTable => { pos => 3, type => 'CHAR', size => 100, not_null => 1 },
|
|
Timestmp => { pos => 4, type => 'TIMESTAMP', time_check => 1 }
|
|
);
|
|
|
|
$c->pk('ID');
|
|
$c->ai('ID');
|
|
$c->create('force');
|
|
$c->set_defaults();
|
|
$c->save_schema();
|
|
}
|
|
|
|
sub uninstall {
|
|
#-------------------------------------------------------------------------------
|
|
# drops the controller table along with all the
|
|
#
|
|
my $self = shift;
|
|
my $DB = $self->_db() or return;
|
|
my $err = 1;
|
|
|
|
# drop all the associated temp tables...,
|
|
eval {
|
|
my $tb = $DB->table( $self->{set_name} );
|
|
my $sth = $tb->select( [ 'SessTable' ] );
|
|
while ( my $aref = $sth->fetchrow_arrayref() ) {
|
|
my $table_name = $aref->[0];
|
|
eval {
|
|
my $e = $DB->editor( $table_name );
|
|
$e->drop_table("remove") or die "Can't drop table";
|
|
};
|
|
$@ and $err = undef;
|
|
|
|
}
|
|
|
|
# now drop the master control table
|
|
my $e = $DB->editor( $self->{set_name});
|
|
$e->drop_table("remove") or die "Can't drop table";
|
|
};
|
|
|
|
return $@ ? undef : 1;
|
|
}
|
|
|
|
sub new_set {
|
|
#-------------------------------------------------------------------------------
|
|
# creates a new temp table
|
|
#
|
|
my $self = shift;
|
|
my $create_session = ( ref $_[0] eq 'CODE' ? shift : $self->{create_session} ) or return $self->error( 'NOCS', 'WARN' );
|
|
|
|
my $sid = $self->{id} or return $self->error( 'NOSID', 'WARN' );
|
|
my $DB = $self->_db();
|
|
my $Session = $DB->table( $self->{set_name} );
|
|
|
|
# create a new sesson
|
|
my $table_name = generate_session_id();
|
|
my $newid = $Session->add({ SessTable => $table_name, SessID => $sid }) or return;
|
|
|
|
# create the new table, extra parameters are passed into the create_session sub procedure
|
|
if ( my $result = &{$create_session}( $DB, $table_name, $newid, @_ ) ) {
|
|
my $tbl = $DB->table( $table_name );
|
|
return wantarray ? ( $tbl, $newid ) : $tbl;
|
|
}
|
|
else {
|
|
$Session->delete($newid);
|
|
return;
|
|
}
|
|
|
|
}
|
|
|
|
sub get_set {
|
|
#-------------------------------------------------------------------------------
|
|
# returns a table reference to the sethandle
|
|
#
|
|
my $self = shift;
|
|
my $set_id = shift or return;
|
|
my $sid = $self->{id} or return $self->error( 'NOSID', 'WARN' );
|
|
|
|
my $DB = $self->_db();
|
|
my $Session = $DB->table( $self->{set_name} ) or return;
|
|
my $sth = $Session->select({ ID => $set_id, SessID => $sid }) or return undef;
|
|
my $href = $sth->fetchrow_hashref() or return undef;
|
|
$href->{Timestmp} = \'NOW()';
|
|
$Session->update( $href );
|
|
|
|
if ( my $table_name = $href->{'SessTable'} ) {
|
|
my $tbl = $DB->table( $table_name );
|
|
return $tbl;
|
|
}
|
|
else {
|
|
return;
|
|
}
|
|
}
|
|
|
|
sub list_sets {
|
|
#-------------------------------------------------------------------------------
|
|
# returns a hashref of ID => tablenames, of tables that the current session ID owns
|
|
#
|
|
my $self = shift;
|
|
my $DB = $self->_db();
|
|
|
|
my $sid = $self->{id} or return $self->error( 'NOSID', 'WARN' );
|
|
my $Session = $DB->table( $self->{set_name} ) or return;
|
|
|
|
my $sth = $Session->select({ SessID => $sid }, [ 'ID', 'SessTable' ]);
|
|
my $list = {};
|
|
while ( my $aref = $sth->fetchrow_arrayref() ) {
|
|
my ( $id, $sesstable ) = @{$aref};
|
|
$list->{$id} = $sesstable;
|
|
}
|
|
|
|
return $list;
|
|
}
|
|
|
|
sub delete {
|
|
#-------------------------------------------------------------------------------
|
|
# deletes all sets associated with the session
|
|
#
|
|
my $self = shift;
|
|
my $DB = $self->_db();
|
|
|
|
my $Session = $DB->table( $self->{set_name} ) or return;
|
|
my $sid = ( shift || $self->{id} ) or return $self->error( 'NOSID', 'WARN' );
|
|
my $sth = $Session->select({ SessID => $sid },['SessTable']);
|
|
|
|
# delete all created temp tables
|
|
while ( my $aref = $sth->fetchrow_arrayref() ) {
|
|
my $tbl_name = $aref->[0];
|
|
eval {
|
|
my $e = $DB->editor($tbl_name);
|
|
$e->drop_table( "remove" );
|
|
}
|
|
}
|
|
|
|
$Session->delete({ SessID => $sid });
|
|
|
|
# cheap workaround
|
|
shift or $self->GT::Session::SQL::delete();
|
|
}
|
|
|
|
sub delete_set {
|
|
#-------------------------------------------------------------------------------
|
|
# deletes a single set
|
|
#
|
|
my $self = shift;
|
|
my $set_id = shift;
|
|
|
|
my $DB = $self->_db();
|
|
my $Session = $DB->table( $self->{set_name} ) or return;
|
|
my $sid = $self->{id} or return $self->error( 'NOSID', 'WARN' );
|
|
my $sth = $Session->select( { ID => $set_id, SessID => $sid }, [ 'SessTable' ] ) or return;
|
|
my $aref = $sth->fetchrow_arrayref() or return;
|
|
|
|
if ($aref->[0]) {
|
|
my $e = $DB->editor($aref->[0]);
|
|
$e->drop_table();
|
|
$Session->delete( { ID => $set_id } );
|
|
}
|
|
}
|
|
|
|
sub cleanup {
|
|
#-------------------------------------------------------------------------------
|
|
my $self = shift;
|
|
my $seconds = shift || $self->{seconds};
|
|
|
|
if ($seconds == 0) {
|
|
$self->debug ("Cleanup not erasing anything, seconds set to 0.") if ($self->{_debug});
|
|
return;
|
|
}
|
|
|
|
my $DB = $self->_db() or return;
|
|
my $tb = $DB->table( $self->{set_name} );
|
|
|
|
defined $seconds or ($seconds = 3600);
|
|
my $new_sec = time - $seconds;
|
|
my @time = localtime ($new_sec);
|
|
|
|
my $date_str = sprintf ("%4d-%02d-%02d %02d:%02d:%02d",
|
|
$time[5] + 1900, $time[4] + 1, $time[3], $time[2], $time[1], $time[0]);
|
|
|
|
my $sth = $tb->select( GT::SQL::Condition->new('Timestmp', '<', $date_str), [ 'SessID' ] ) or return $self->error ($GT::SQL::error);
|
|
while ( my $aref = $sth->fetchrow_arrayref() ) {
|
|
$self->delete( $aref->[0], 1 );
|
|
}
|
|
$tb->delete (GT::SQL::Condition->new ('Timestmp', '<', $date_str)) or return $self->error ($GT::SQL::error);
|
|
|
|
return 1;
|
|
}
|
|
|
|
sub _db {
|
|
#-------------------------------------------------------------------------------
|
|
# returns a database handle
|
|
#
|
|
my $self = shift;
|
|
if ( my $db = $self->{'db'} ) {
|
|
return $db;
|
|
}
|
|
|
|
elsif ( my $def_path = $self->{'def_path'} ) {
|
|
$db = GT::SQL->new( $def_path );
|
|
return $db;
|
|
}
|
|
|
|
else {
|
|
$self->error( 'NODB', 'FATAL' );
|
|
}
|
|
}
|
|
|
|
sub generate_session_id {
|
|
# ---------------------------------------------------------------
|
|
# Generates a session id.
|
|
#
|
|
return md5_hex( time . $$ . rand (16000) );
|
|
}
|
|
|
|
1;
|
|
|
|
__END__
|
|
|
|
=head1 NAME
|
|
|
|
GT::Session::TempTable - A session management module, subclassing GT::Session::SQL providing temp table support
|
|
|
|
=head1 SYNOPSIS
|
|
|
|
Create a session:
|
|
my $session = new GT::Session::TempTable({
|
|
db => GT::SQL->new( '/path/to/defs' ),
|
|
def_path => '/path/to/defs',
|
|
create_session => \&create_table_sub
|
|
});
|
|
|
|
Create temp table controller table. (do once before using this module)
|
|
$session->initial_create();
|
|
|
|
Create a new temp table:
|
|
my ( $GT_SQL_Table_ref, $tmp_id ) = $session->new_set();
|
|
|
|
Get the GT::SQL::Table ref to a previous table:
|
|
my $GT_SQL_Table_ref = $session->get_set( $tmp_id );
|
|
|
|
List all the sets for current session:
|
|
my $href = $session->list_sets();
|
|
|
|
Save data with the session:
|
|
$session->data ("Save this information!");
|
|
|
|
Load a session.
|
|
my $session = new GT::Session::TempTable ( $id ) or die "Can't load session: '$id'."
|
|
|
|
Delete a session:
|
|
$session->delete();
|
|
|
|
Delete a table set:
|
|
$session->delete_set( $tmp_id );
|
|
|
|
Cleanup old sessions, takes argument of number of seconds old.
|
|
$session->cleanup ( 5000 );
|
|
|
|
=cut
|
|
|