#!/usr/bin/perl

my ($dsn, $user, $pass);
BEGIN { 
  ($dsn, $user, $pass) = ( 
    scalar(@ARGV) ? ( @ARGV ) : 
    $ENV{DBI_DSN} ? ( map $ENV{$_}, qw( DBI_DSN DBI_USER DBI_PASS ) ) :
    ()
  );
  $dsn = '' if ( ! $dsn or $dsn eq '-' );
}

########################################################################

use Test;
BEGIN { plan tests => ( $dsn ? 25 : 1 ) }

use DBIx::SQLEngine;

########################################################################

if ( ! $dsn ) {

  warn <<'.';

  Note: By default, DBIx::SQLEngine will only perform a limited series of
  tests; to be fully tested, it must connect to a working DBI database driver.

  In order to test DBIx::SQLEngine against your local database, set the DBI_DSN 
  environment variable to your connection string before running the tests, and 
  if needed, also set the DBI_USER and DBI_PASS variables. 
    Example:  > setenv DBI_DSN "DBI:mysql:test"; make test

  If you specify a database, this test script will create a table named 
  sqle_test, run several queries against it, and then drop it.

  Querying DBI for available driver types and suggested DSNs: 
.

  %common_cases = (
    'AnyData' => 'dbi:AnyData:',
    'SQLite' => 'dbi:SQLite:dbname=test_data/test.sqlite',
    'mysql' => 'dbi:mysql:test',
  );
  @exclude_patterns = (
    'blib$', 	  # for file-based DBDs, don't show the compilation directory
    'SQLEngine$', # nor the source directory...
    't$', 	  # nor the test directory -- this should leave test_data/
  );
  foreach my $driver ( DBI->available_drivers ) {
    eval {
      DBI->install_driver($driver);
      my @data_sources;
      eval {
	@data_sources = DBI->data_sources($driver);
      };
      push @data_sources, split(' ', $common_cases{$driver} || '');
      if (@data_sources) {
	foreach my $source ( @data_sources ) {
	  next if grep { $source =~ /\b$_\b/ } @exclude_patterns;
	  push @suggestions, ($source =~ /:/ ? $source : "dbi:$driver:$source");
	} 
      } else { 
	push @suggestions, "dbi:$driver";
      }
    };
  } 

  if ( scalar @suggestions ) {
    %suggestions = map { $_ => 1 } grep { ! /dbi:ExampleP/ } @suggestions;
    @suggestions = sort { lc($a) cmp lc($b) } keys %suggestions;
    warn join '', map "    $_\n", @suggestions;
  } else {
    warn "    (No suggestions found.)\n";
  }

  skip(
    "Skipping: specify DBI_DSN in environment to test your local server.\n",
    0,
  );

  exit 0;

}

########################################################################

warn <<".";

  The remaining tests will use the DBI DSN specified in your environment: 
    $dsn

  In a few seconds, this script will connect to the above data source, create 
  a table named sqle_test, run various queries aginst it, and then drop it.
  
.

sleep(3);

my $sqldb;
ok( $sqldb = DBIx::SQLEngine->new($dsn, $user, $pass) );

ok( ref($sqldb) =~ /DBIx::SQLEngine::(.+)/ );

warn <<".";

  Connected using DBIx::SQLEngine::$1 and DBD::$sqldb->{dbh}->{Driver}->{Name}.

.

# $sqldb->DBILogging(1);

ok( $sqldb->detect_any );

########################################################################

my $table = 'sqle_test';

CREATE_TABLE: {

  $sqldb->do_drop_table( $table ) if $sqldb->detect_table($table, 'quietly');
  $sqldb->do_create_table( $table, [
    { name => 'id', type => 'sequential' },
    { name => 'name', type => 'text', length => 16 },
    { name => 'color', type => 'text', length => 8 },
  ]);
  ok( 1 );

}

FETCH_COLUMN_INFO: {

  my @cols = $sqldb->detect_table( $table );
  ok( scalar( @cols ) == 3 );
  @cols = $sqldb->detect_table( 'area_51_secrets', 'quietly' );
  ok( scalar( @cols ) == 0 );

}

INSERTS_AND_SELECTS: {

  $sqldb->do_insert( table => $table, sequence => 'id', 
			values => { name=>'Sam', color=>'green' } );
  $sqldb->do_insert( table => $table, sequence => 'id', 
			values => { name=>'Ellen', color=>'orange' } );
  $sqldb->do_insert( table => $table, sequence => 'id', 
			values => { name=>'Sue', color=>'purple' } );
  ok( 1 );
  
  my $rows = $sqldb->fetch_select( table => $table, order => 'id' );
  ok( ref $rows and scalar @$rows == 3 );
  ok( $rows->[0]->{'name'} eq 'Sam' and $rows->[0]->{'color'} eq 'green' );
  
  $sqldb->do_insert( table => $table, sequence => 'id', 
			values => { name=>'Dave', color=>'blue' } );
  ok( 1 );
  
  $rows = $sqldb->fetch_select( table => $table );
  ok( ref $rows and scalar @$rows == 4 );

}

SELECT_CRITERIA: {

  my $rows = $sqldb->fetch_select( table => $table, criteria => {name=>'Dave'});
  ok( ref $rows and scalar @$rows == 1 and $rows->[0]->{'name'} eq 'Dave' );
  
  $rows = $sqldb->fetch_select( table => $table, criteria => "name = 'Dave'" );
  ok( ref $rows and scalar @$rows == 1 and $rows->[0]->{'name'} eq 'Dave' );
  
  $rows = $sqldb->fetch_select( sql => "select * from $table where name = 'Dave'" );
  ok( ref $rows and scalar @$rows == 1 and $rows->[0]->{'name'} eq 'Dave' );
  
  $rows = $sqldb->fetch_select( sql => [ "select * from $table where name = ?", 'Dave' ] );
  ok( ref $rows and scalar @$rows == 1 and $rows->[0]->{'name'} eq 'Dave' );

}

UPDATE: {

  $sqldb->do_update( table => $table, criteria => { name=>'Dave' }, values => { color=>'yellow' } );
  ok( 1 );
  
  my $rows = $sqldb->fetch_select( table => $table, criteria =>{name=>'Dave'} );
  ok( ref $rows and scalar @$rows == 1 and $rows->[0]->{'color'} eq 'yellow' );

}

USE_OF_LITERAL_EXPRESSIONS: {

  $sqldb->do_update( table => $table, criteria => { name=>\"'Dave'" }, values => { color=>\"'mauve'" } );
  ok( 1 );
  
  my $rows = $sqldb->fetch_select( table=>$table, criteria=>{name=>\"'Dave'"} );
  ok( ref $rows and scalar @$rows == 1 and $rows->[0]->{'color'} eq 'mauve' );

}

DELETE: {

  $sqldb->do_delete( table => $table, criteria => { name=>'Sam' } );
  ok( 1 );
  
  my $rows = $sqldb->fetch_select( table => $table );
  ok( ref $rows and scalar @$rows == 3 );

}

NULL_VALUE_LOGIC: {

  my $rows = $sqldb->fetch_select( table=>$table, criteria=>{ name=>undef() } );
  ok( ref $rows and scalar @$rows == 0 );
  
  $sqldb->do_update( table => $table, criteria => { name=>\"'Dave'" }, values => { name=>undef() } );
  ok( 1 );
  
  $rows = $sqldb->fetch_select( table=>$table, criteria=>{ name=>undef() } );
  ok( (ref $rows and scalar @$rows == 1 and $rows->[0]->{'color'} eq 'mauve'), 1, "Couldn't select null value rows" );

}

DROP_TABLE: {

  $sqldb->do_drop_table( $table );
  ok( 1 );

}

########################################################################

1;
