#! /usr/bin/perl -w

# vim:syntax=perl

#-----------------------------------------------------------
# Sql storage script.
#-----------------------------------------------------------


use strict;

use lib '/usr/local/share/perl5';

use DBI;

use Lire::Program qw/:msg $PROG/;
use Lire::Config;

my @fields_sql;
my @defaults_sql;
my @types;

#----------------------------------------------------------
# Get structure of the table
#----------------------------------------------------------

sub get_schema_fields {
    my ( $dbh, $schemaid ) = @_;

    my $schema = Lire::DlfSchema::load_schema( $schemaid );
    my $nb_fields = $schema->field_count();
    my @fields=$schema->fields();
    
    for( my $i=0;$i<$nb_fields;$i++ ) {
	push @fields_sql, $fields[$i]->name;
	push @defaults_sql, $fields[$i]->default;
	push @types, $fields[$i]->type;
    }
}

#--------------------------------------------------------
# Check if the table exist of the superservice exists
#--------------------------------------------------------

sub check_table {
    my ( $dbh, $schema ) = @_;

    my @row;
    my $sth = $dbh->prepare("SHOW TABLES")
      or lr_err( "prepare failed: ", $dbh->errstr );

    $sth->execute()
      or lr_err( "execute failed: ", $dbh->errstr );

    while(my $row = $sth->fetchrow_arrayref) {
	return 1 if $row->[0] eq $schema;
    }

    return 0;
}

#---------------------------------------------------------
# Check if max size is reached
#---------------------------------------------------------

sub check_max_size{
    my ( $dbh, $schema ) = @_;

    my @row;
    my $sth = $dbh->prepare("SELECT COUNT(id) FROM $schema")
      or lr_err( "prepare failed: ", $dbh->errstr );

    $sth->execute()
      or lr_err( "execute failed: ", $dbh->errstr );

    my $row = $sth->fetchrow_arrayref;
    if ($row->[0] > $Lire::Config::LR_SQL_MAX_SIZE) {
	lr_err("SQL MAX SIZE reached SQL SIZE is:$Lire::Config::LR_SQL_MAX_SIZE" );}
    else {
	return $row->[0];
    }
}

#---------------------------------------------------------
# Create table if the table doesn't exist
#---------------------------------------------------------

sub create_table {
    my ( $dbh, $schema ) = @_;

    my $i;
    my %compatible = (
		      'timestamp'   => 'BIGINT',
		      'bool'	    => 'INT',
		      'int'	    => 'BIGINT',
		      'number'	    => 'DECIMAL(9,3)',
		      'string'	    => 'VARCHAR(255)',
		      'hostname'    => 'VARCHAR(100)',
		      'ip'	    => 'VARCHAR(15)',
		      'duration'    => 'BIGINT',
		      'port'	    => 'VARCHAR(20)',
		      'url'	    => 'VARCHAR(255)',
		      'filename'    => 'VARCHAR(255)',
		      'email'	    => 'VARCHAR(100)',
		      'bytes'	    => 'BIGINT',
		     );


    my $creation="CREATE TABLE $schema (id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY";

    for ($i=0;$i<$#fields_sql+1;$i++) {
	$creation="$creation".",$fields_sql[$i] $compatible{$types[$i]} DEFAULT \'$defaults_sql[$i]\'";
    }

    $creation="$creation".")";

    lr_info("SQL table for the $schema schema was created");
    my $sth =  $dbh->prepare($creation);

    $sth->execute()
      or die "Unable execute query:$dbh->err, $dbh->errstr\n";
}

#---------------------------------------------------------
# Main
#---------------------------------------------------------

lr_info("Starting SQL store... ");

lr_err("Usage: $PROG <superservice> <dlf-file>")
 unless @ARGV==2;

my ($superservice, $dlf_file )= @ARGV;

my $dbh = Lire::Config::connect_dbi();
my $max_size = check_max_size($dbh,$superservice);

get_schema_fields($dbh, $superservice);

if( !check_table($dbh, $superservice) ) {
    create_table($dbh, $superservice);
}

#Open the dlf file
open DLF, $dlf_file
  or lr_err("Cannot open $dlf_file: $!");

#Build the request
my $insert ="INSERT into $superservice (" . 
  (join ",", @fields_sql) . ") VALUES (" . (join ",", ("?") x @fields_sql).")";
my $sth = $dbh->prepare($insert);

my $count = 0;
while(<DLF>) {
    chomp;
    my @elements = map { $_ eq 'LIRE_NOTAVAIL' ? undef : $_ } split / /;
    $sth->execute(@elements) 
      or lr_warn( "Unable execute query: ", $dbh->err, ", ", $dbh->errstr );
    $count++;
    if ( ($max_size + $count) > $Lire::Config::LR_SQL_MAX_SIZE  ) {
	lr_err("SQL MAX SIZE reached exiting");
    }
}

lr_info( "inserted $count SQL records" );

__END__

=pod

=head1 NAME

lr_dlf2sql - script to store the dlf file into a databse

=head1 SYNOPSIS

B<lr_dlf2sql> [<superservice> <dlf-file>]

=head1 DESCRIPTION

B<lr_dlf2sql> will take the specified dlf and will store it into an sql
database. First it will check if the table exists. If the table doesn't exists
it will create it form the xml schema.

All information on the database interface is taken from Lire::Config.

This script is called by lr_log2xml(1), if Lire was configured to do so.  The
generated SQL database can be used by the lr_sql2report(1) script.

=head1 SEE ALSO

lr_log2xml(1), lr_sql2report(1), lr_sql2dlf(1), the discussion on the LogReport
development list which started with
http://www.logreport.org/contact/lists/development/msg00634.php and
http://www.logreport.org/contact/lists/development/msg00647.php .

=head1 AUTHORS

Arnaud Gaillard and Francis J. Lacoste

=head1 COPYRIGHT

Copyright (C) 2002 Arnaud Gaillard <wireless@orange.ch>

Stichting LogReport Foundation <logreport@logreport.org>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program (see COPYING); if not, check with
http://www.gnu.org/copyleft/gpl.html or write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.

=cut

# Local Variables:
# mode: cperl
# End:
