#!/usr/bin/perl -w
use strict;
use File::Spec;
use lib '.', File::Spec->catdir( File::Spec->curdir, 't', 'lib' );
use Alzabo::Test::Utils;
use Test::More;
my @rdbms_names = Alzabo::Test::Utils->rdbms_names;
unless (@rdbms_names)
{
plan skip_all => 'no test config provided';
exit;
}
my $tests_per_run = 340;
my $test_count = $tests_per_run * @rdbms_names;
my %SINGLE_RDBMS_TESTS = ( mysql => 23,
pg => 11,
);
foreach my $rdbms ( keys %SINGLE_RDBMS_TESTS )
{
next unless grep { $_ eq $rdbms } @rdbms_names;
$test_count += $SINGLE_RDBMS_TESTS{$rdbms};
}
plan tests => $test_count;
Alzabo::Test::Utils->remove_all_schemas;
foreach my $rdbms (@rdbms_names)
{
if ( $rdbms eq 'mysql' )
{
# prevent subroutine redefinition warnings
local $^W = 0;
eval 'use Alzabo::SQLMaker::MySQL qw(:all)';
}
elsif ( $rdbms eq 'pg' )
{
local $^W = 0;
eval 'use Alzabo::SQLMaker::PostgreSQL qw(:all)';
}
Alzabo::Test::Utils->make_schema($rdbms);
run_tests($rdbms);
Alzabo::Test::Utils->remove_schema($rdbms);
}
sub run_tests
{
my $rdbms = shift;
my $config = Alzabo::Test::Utils->test_config_for($rdbms);
my $s = Alzabo::Runtime::Schema->load_from_file( name => $config->{schema_name} );
# tests setting basic parameters and connecting to RDBMS
{
eval_ok( sub { $s->set_user('foo') },
"Set user for schema to foo" );
eval_ok( sub { $s->set_password('foo') },
"Set password for schema to foo" );
eval_ok( sub { $s->set_host('foo') },
"Set host for schema to foo" );
eval_ok( sub { $s->set_port(1234) },
"Set port for schema to 1234" );
$s->$_(undef) foreach qw( set_user set_password set_host set_port );
$s->connect( Alzabo::Test::Utils->connect_params_for($rdbms) );
$s->set_referential_integrity(1);
}
{
my $dbh = $s->driver->handle;
isa_ok( $dbh, ref $s->driver->{dbh},
"Object returned by \$s->driver->handle method" );
eval_ok( sub { $s->driver->handle($dbh) },
"Set \$s->driver->handle" );
}
my $emp_t = $s->table('employee');
my $dep_t = $s->table('department');
my $proj_t = $s->table('project');
my $emp_proj_t = $s->table('employee_project');
my %dep;
eval_ok( sub { $dep{borg} = $dep_t->insert( values => { name => 'borging' } ) },
"Insert borging row into department table" );
is( $dep{borg}->select('name'), 'borging',
"The borg department name should be 'borging'" );
{
my @all = $dep{borg}->select;
is( @all, 3,
"select with no columns should return all the values" );
is( $all[1], 'borging',
"The second value should be the department name" );
my %all = $dep{borg}->select_hash;
is( keys %all, 3,
"select_hash with no columns should return two keys" );
ok( exists $all{department_id},
"The returned hash should have a department_id key" );
ok( exists $all{name},
"The returned hash should have a department_id key" );
is( $all{name}, 'borging',
"The value of the name key be the department name" );
}
$dep{lying} = $dep_t->insert( values => { name => 'lying to the public' } );
my $borg_id = $dep{borg}->select('department_id');
delete $dep{borg};
eval_ok( sub { $dep{borg} = $dep_t->row_by_pk( pk => $borg_id ) },
"Retrieve borg department row via row_by_pk method" );
isa_ok( $dep{borg}, 'Alzabo::Runtime::Row',
"Borg department" );
is( $dep{borg}->select('name'), 'borging',
"Department's name should be 'borging'" );
eval { $dep_t->insert( values => { name => 'will break',
manager_id => 1 } ); };
my $e = $@;
isa_ok( $e, 'Alzabo::Exception::ReferentialIntegrity',
"Exception thrown from attempt to insert a non-existent manager_id into department" );
my %emp;
eval_ok( sub { $emp{bill} = $emp_t->insert( values => { name => 'Big Bill',
dep_id => $borg_id,
smell => 'robotic',
cash => 20.2,
} ) },
"Insert Big Bill into employee table" );
my %data = $emp{bill}->select_hash( 'name', 'smell' );
is( $data{name}, 'Big Bill',
"select_hash - check name key" );
is( $data{smell}, 'robotic',
"select_hash - check smell key" );
is( $emp{bill}->is_live, 1,
"->is_live should be true for real row" );
eval { $emp_t->insert( values => { name => undef,
dep_id => $borg_id,
smell => 'robotic',
cash => 20.2,
} ); };
$e = $@;
isa_ok( $e, 'Alzabo::Exception::NotNullable',
"Exception thrown from inserting a non-nullable column as NULL" );
is( $e->table_name, 'employee',
"NotNullable exceptions contain table name" );
is( $e->schema_name, $config->{schema_name},
"NotNullable exceptions contain schema name" );
{
my $new_emp;
eval_ok( sub { $new_emp = $emp_t->insert( values => { name => 'asfalksf',
dep_id => $borg_id,
smell => undef,
cash => 20.2,
} ) },
"Inserting a NULL into a non-nullable column that has a default should not produce an exception" );
eval_ok( sub { $new_emp->delete },
"Delete a just-created employee" );
}
eval { $emp_t->insert( values => { name => 'YetAnotherTest',
dep_id => undef,
cash => 1.1,
} ) };
$e = $@;
isa_ok( $e, 'Alzabo::Exception::Params',
"Exception thrown from attempt to insert a NULL into dep_id for an employee" );
eval { $emp{bill}->update( dep_id => undef ) };
$e = $@;
isa_ok( $e, 'Alzabo::Exception::Params',
"Exception thrown from attempt to update dep_id to NULL for an employee" );
{
my $updated = $emp{bill}->update( cash => undef, smell => 'hello!' );
ok( $updated, 'update() did change values' );
ok( ! defined $emp{bill}->select('cash'),
"Bill has no cash" );
}
{
my $updated = $emp{bill}->update( cash => undef, smell => 'hello!' );
ok( ! $updated, 'update() did not change values' );
}
ok( $emp{bill}->select('smell') eq 'hello!',
"smell for bill should be 'hello!'" );
eval { $emp{bill}->update( name => undef ) };
$e = $@;
isa_ok( $e, 'Alzabo::Exception::NotNullable',
"Exception thrown from attempt to update a non-nullable column to NULL" );
eval_ok( sub { $dep{borg}->update( manager_id => $emp{bill}->select('employee_id') ) },
"Set manager_id column for borg department" );
eval_ok( sub { $emp{2} = $emp_t->insert( values =>
{ name => 'unit 2',
smell => 'good',
dep_id => $dep{lying}->select('department_id') } ) },
"Create employee 'unit 2'" );
my $emp2_id = $emp{2}->select('employee_id');
delete $emp{2};
my $cursor;
my $x = 0;
eval_ok( sub { $cursor =
$emp_t->rows_where
( where => [ $emp_t->column('employee_id'), '=', $emp2_id ] );
while ( my $row = $cursor->next )
{
$x++;
$emp{2} = $row;
}
},
"Retrieve 'unit 2' employee via rows_where method and cursor" );
is( $x, 1,
"Check count of rows found where employee_id == $emp2_id" );
is( $cursor->count, 1,
"Make sure cursor's count() is accurate" );
is( $emp{2}->select('name'), 'unit 2',
"Check that row found has name of 'unit 2'" );
{
my $row;
eval_ok( sub { $row =
$emp_t->one_row
( where =>
[ $emp_t->column('employee_id'), '=', $emp2_id ] ) },
"Retrieve 'unit 2' employee via one_row method" );
is( $row->select('name'), 'unit 2',
"Check that the single row returned has the name 'unit 2'" );
}
{
my $row;
eval_ok( sub { $row =
$emp_t->one_row
( where =>
[ $emp_t->column('employee_id'), '=', $emp2_id ],
quote_identifiers => 1,
) },
"Retrieve 'unit 2' employee via one_row method with quote_identifiers" );
is( $row->select('name'), 'unit 2',
"Check that the single row returned has the name 'unit 2'" );
}
my %proj;
$proj{extend} = $proj_t->insert( values => { name => 'Extend',
department_id => $dep{borg}->select('department_id') } );
$proj{embrace} = $proj_t->insert( values => { name => 'Embrace',
department_id => $dep{borg}->select('department_id') } );
$emp_proj_t->insert( values => { employee_id => $emp{bill}->select('employee_id'),
project_id => $proj{extend}->select('project_id') } );
$emp_proj_t->insert( values => { employee_id => $emp{bill}->select('employee_id'),
project_id => $proj{embrace}->select('project_id') } );
my $fk = $emp_t->foreign_keys_by_table($emp_proj_t);
my @emp_proj;
my @cursor_counts;
eval_ok( sub { $cursor = $emp{bill}->rows_by_foreign_key( foreign_key => $fk );
while ( my $row = $cursor->next )
{
push @emp_proj, $row;
push @cursor_counts, $cursor->count;
} },
"Fetch rows via ->rows_by_foreign_key method (expect cursor)" );
is( scalar @emp_proj, 2,
"Check that only two rows were returned" );
is( $emp_proj[0]->select('employee_id'), $emp{bill}->select('employee_id'),
"Check that employee_id in employee_project is same as bill's" );
is( $emp_proj[0]->select('project_id'), $proj{extend}->select('project_id'),
"Check that project_id in employee_project is same as extend project" );
foreach (1..2)
{
is( $cursor_counts[$_ - 1], $_,
"cursor->count should be 1..2" );
}
my $emp_proj = $emp_proj[0];
$fk = $emp_proj_t->foreign_keys_by_table($emp_t);
my $emp;
eval_ok( sub { $emp = $emp_proj->rows_by_foreign_key( foreign_key => $fk ) },
"Fetch rows via ->rows_by_foreign_key method (expect row)" );
is( $emp->select('employee_id'), $emp_proj->select('employee_id'),
"The returned row should have bill's employee_id" );
$x = 0;
my @rows;
eval_ok( sub { $cursor = $emp_t->all_rows;
$x++ while $cursor->next
},
"Fetch all rows from employee table" );
is( $x, 2,
"Only 2 rows should be found" );
$cursor->reset;
my $count = $cursor->all_rows;
is( $x, 2,
"Only 2 rows should be found after cursor reset" );
{
my $cursor;
eval_ok( sub { $cursor =
$s->join( join => [ $emp_t, $emp_proj_t, $proj_t ],
where =>
[ $emp_t->column('employee_id'), '=',
$emp{bill}->select('employee_id') ],
order_by => $proj_t->column('project_id'),
quote_identifiers => 1,
) },
"Join employee, employee_project, and project tables where employee_id = bill's employee id with quote_identifiers" );
my @rows = $cursor->next;
is( scalar @rows, 3,
"3 rows per cursor ->next call" );
is( $rows[0]->table->name, 'employee',
"First row is from employee table" );
is( $rows[1]->table->name, 'employee_project',
"Second row is from employee_project table" );
is( $rows[2]->table->name, 'project',
"Third row is from project table" );
my $first_proj_id = $rows[2]->select('project_id');
@rows = $cursor->next;
my $second_proj_id = $rows[2]->select('project_id');
ok( $first_proj_id < $second_proj_id,
"Order by clause should cause project rows to come back" .
" in ascending order of project id" );
}
{
my $cursor;
eval_ok( sub { $cursor =
$s->join( join => [ $emp_t, $emp_proj_t, $proj_t ],
where =>
[ [ $proj_t->column('project_id'), '=',
$proj{extend}->select('project_id') ],
'or',
[ $proj_t->column('project_id'), '=',
$proj{embrace}->select('project_id') ],
],
order_by => $proj_t->column('project_id') ) },
"Join employee, employee_project, and project tables with OR in where clause" );
1 while $cursor->next;
is( $cursor->count, 2,
"join with OR in where clause should return two sets of rows" );
}
# Alias code
{
my $e_alias;
eval_ok( sub { $e_alias = $emp_t->alias },
"Create an alias object for the employee table" );
my $p_alias;
eval_ok( sub { $p_alias = $proj_t->alias },
"Create an alias object for the project table" );
eval_ok( sub { $cursor =
$s->join( join => [ $e_alias, $emp_proj_t, $p_alias ],
where => [ $e_alias->column('employee_id'), '=', 1 ],
order_by => $p_alias->column('project_id'),
) },
"Join employee, employee_project, and project tables where" .
" employee_id = 1 using aliases" );
my @rows = $cursor->next;
is( scalar @rows, 3,
"3 rows per cursor ->next call" );
is( $rows[0]->table->name, 'employee',
"First row is from employee table" );
is( $rows[1]->table->name, 'employee_project',
"Second row is from employee_project table" );
is( $rows[2]->table->name, 'project',
"Third row is from project table" );
}
# Alias code & multiple joins to the same table
{
my $p_alias = $proj_t->alias;
eval_ok( sub { $cursor = $s->join( select => [ $p_alias, $proj_t ],
join => [ $p_alias, $emp_proj_t, $proj_t ],
where => [ [ $p_alias->column('project_id'), '=', 1 ],
[ $proj_t->column('project_id'), '=', 1 ] ],
) },
"Join employee_project and project table (twice) using aliases" );
my @rows = $cursor->next;
is( scalar @rows, 2,
"2 rows per cursor ->next call" );
is( $rows[0]->table->name, 'project',
"First row is from project table" );
is( $rows[1]->table->name, 'project',
"Second row is from project table" );
is( $rows[0]->table, $rows[1]->table,
"The two rows should share the same table object (the alias should be gone at this point)" );
}
{
my @rows;
eval_ok( sub { @rows = $s->one_row( tables => [ $emp_t, $emp_proj_t, $proj_t ],
where => [ $emp_t->column('employee_id'), '=', 1 ],
order_by => $proj_t->column('project_id') ) },
"Join employee, employee_project, and project tables where employee_id = 1 using one_row method" );
is( $rows[0]->table->name, 'employee',
"First row is from employee table" );
is( $rows[1]->table->name, 'employee_project',
"Second row is from employee_project table" );
is( $rows[2]->table->name, 'project',
"Third row is from project table" );
}
$cursor = $s->join( join => [ $emp_t, $emp_proj_t, $proj_t ],
where => [ $emp_t->column('employee_id'), '=', 1 ],
order_by => [ $proj_t->column('project_id'), 'desc' ] );
@rows = $cursor->next;
my $first_proj_id = $rows[2]->select('project_id');
@rows = $cursor->next;
my $second_proj_id = $rows[2]->select('project_id');
ok( $first_proj_id > $second_proj_id,
"Order by clause should cause project rows to come back in descending order of project id" );
$cursor = $s->join( join => [ $emp_t, $emp_proj_t, $proj_t ],
where => [ $emp_t->column('employee_id'), '=', 1 ],
order_by => [ $proj_t->column('project_id'), 'desc' ] );
@rows = $cursor->next;
$first_proj_id = $rows[2]->select('project_id');
@rows = $cursor->next;
$second_proj_id = $rows[2]->select('project_id');
ok( $first_proj_id > $second_proj_id,
"Order by clause (alternate form) should cause project rows to come back in descending order of project id" );
eval_ok( sub { $cursor = $s->join( select => [ $emp_t, $emp_proj_t, $proj_t ],
join => [ [ $emp_t, $emp_proj_t ],
[ $emp_proj_t, $proj_t ] ],
where => [ $emp_t->column('employee_id'), '=', 1 ] ) },
"Join with join as arrayref of arrayrefs" );
@rows = $cursor->next;
is( scalar @rows, 3,
"3 rows per cursor ->next call" );
is( $rows[0]->table->name, 'employee',
"First row is from employee table" );
is( $rows[1]->table->name, 'employee_project',
"Second row is from employee_project table" );
is( $rows[2]->table->name, 'project',
"Third row is from project table" );
{
my $cursor;
eval_ok( sub { $cursor = $s->join( join => [ [ $emp_t, $emp_proj_t ],
[ $emp_proj_t, $proj_t ] ],
where => [ $emp_t->column('employee_id'), '=', 1 ] ) },
"Same join with no select parameter" );
my @rows = $cursor->next;
@rows = sort { $a->table->name cmp $b->table->name } @rows;
is( scalar @rows, 3,
"3 rows per cursor ->next call" );
is( ( grep { $_->table->name eq 'employee' } @rows ), 1,
"First row is from employee table" );
is( ( grep { $_->table->name eq 'employee_project' } @rows ), 1,
"Second row is from employee_project table" );
is( ( grep { $_->table->name eq 'project' } @rows ), 1,
"Third row is from project table" );
}
eval { $s->join( select => [ $emp_t, $emp_proj_t, $proj_t ],
join => [ [ $emp_t, $emp_proj_t ],
[ $emp_proj_t, $proj_t ],
[ $s->tables( 'outer_1', 'outer_2' ) ] ],
where => [ $emp_t->column('employee_id'), '=', 1 ] ) };
$e = $@;
isa_ok( $e, 'Alzabo::Exception::Logic',
"Exception thrown from join with table map that does not connect" );
eval_ok( sub { @rows = $s->join( join => $emp_t,
where => [ $emp_t->column('employee_id'), '=', 1 ] )->all_rows },
"Join with a single table" );
is( @rows, 1,
"Only one row should be returned" );
is( $rows[0]->select('employee_id'), 1,
"Returned employee should be employee number one" );
{
$s->table('outer_2')->insert( values => { outer_2_name => 'will match something',
outer_2_pk => 1 },
);
$s->table('outer_2')->insert( values => { outer_2_name => 'will match nothing',
outer_2_pk => 99 },
);
$s->table('outer_1')->insert( values => { outer_1_name => 'test1 (has matching join row)',
outer_2_pk => 1 },
);
$s->table('outer_1')->insert( values => { outer_1_name => 'test2 (has no matching join row)',
outer_2_pk => undef },
);
{
my $cursor;
eval_ok( sub { $cursor =
$s->join
( select => [ $s->tables( 'outer_1', 'outer_2' ) ],
join =>
[ left_outer_join =>
$s->tables( 'outer_1', 'outer_2' ) ]
) },
"Do a left outer join" );
my @sets = $cursor->all_rows;
is( scalar @sets, 2,
"Left outer join should return 2 sets of rows" );
# re-order so that the set with 2 valid rows is always first
unless ( defined $sets[0]->[1] )
{
my $set = shift @sets;
push @sets, $set;
}
is( $sets[0]->[0]->select('outer_1_name'), 'test1 (has matching join row)',
"The first row in the first set should have the name 'test1 (has matching join row)'" );
is( $sets[0]->[1]->select('outer_2_name'), 'will match something',
"The second row in the first set should have the name 'will match something'" );
is( $sets[1]->[0]->select('outer_1_name'), 'test2 (has no matching join row)',
"The first row in the second set should have the name 'test12 (has no matching join row)'" );
ok( ! defined $sets[1]->[1],
"The second row in the second set should not be defined" );
}
{
my $cursor;
eval_ok( sub { $cursor =
$s->join
( select => [ $s->tables( 'outer_1', 'outer_2' ) ],
join =>
[ [ left_outer_join =>
$s->tables( 'outer_1', 'outer_2' ),
[ $s->table('outer_2')->column( 'outer_2_pk' ),
'!=', 1 ],
] ],
order_by =>
$s->table('outer_1')->column('outer_1_name')
) },
"Do a left outer join" );
my @sets = $cursor->all_rows;
is( scalar @sets, 2,
"Left outer join should return 2 sets of rows" );
is( $sets[0]->[0]->select('outer_1_name'), 'test1 (has matching join row)',
"The first row in the first set should have the name 'test1 (has matching join row)'" );
is( $sets[0]->[1], undef,
"The second row in the first set should be undef" );
is( $sets[1]->[0]->select('outer_1_name'), 'test2 (has no matching join row)',
"The first row in the second set should have the name 'test1 (has matching join row)'" );
is( $sets[1]->[1], undef,
"The second row in the second set should be undef" );
}
{
my $fk = $s->table('outer_1')->foreign_keys_by_table( $s->table('outer_2') );
my $cursor;
eval_ok( sub { $cursor =
$s->join
( select => [ $s->tables( 'outer_1', 'outer_2' ) ],
join =>
[ [ left_outer_join =>
$s->tables( 'outer_1', 'outer_2' ),
$fk,
[ $s->table('outer_2')->column( 'outer_2_pk' ),
'!=', 1 ],
] ],
order_by =>
$s->table('outer_1')->column('outer_1_name')
) },
"Do a left outer join" );
my @sets = $cursor->all_rows;
is( scalar @sets, 2,
"Left outer join should return 2 sets of rows" );
is( $sets[0]->[0]->select('outer_1_name'), 'test1 (has matching join row)',
"The first row in the first set should have the name 'test1 (has matching join row)'" );
is( $sets[0]->[1], undef,
"The second row in the first set should be undef" );
is( $sets[1]->[0]->select('outer_1_name'), 'test2 (has no matching join row)',
"The first row in the second set should have the name 'test1 (has matching join row)'" );
is( $sets[1]->[1], undef,
"The second row in the second set should be undef" );
}
{
my $cursor;
eval_ok( sub { $cursor =
$s->join
( select => [ $s->tables( 'outer_1', 'outer_2' ) ],
join =>
[ [ right_outer_join =>
$s->tables( 'outer_1', 'outer_2' ) ] ]
) },
"Attempt a right outer join" );
my @sets = $cursor->all_rows;
is( scalar @sets, 2,
"Right outer join should return 2 sets of rows" );
# re-order so that the set with 2 valid rows is always first
unless ( defined $sets[0]->[0] )
{
my $set = shift @sets;
push @sets, $set;
}
is( $sets[0]->[0]->select('outer_1_name'), 'test1 (has matching join row)',
"The first row in the first set should have the name 'test1 (has matching join row)'" );
is( $sets[0]->[1]->select('outer_2_name'), 'will match something',
"The second row in the first set should have the name 'will match something'" );
ok( ! defined $sets[1]->[0],
"The first row in the second set should not be defined" );
is( $sets[1]->[1]->select('outer_2_name'), 'will match nothing',
"The second row in the second set should have the name 'test12 (has no matching join row)'" );
}
{
my $cursor;
# do the same join, but with specified foreign key
my $fk = $s->table('outer_1')->foreign_keys_by_table( $s->table('outer_2') );
eval_ok( sub { $cursor =
$s->join
( select => [ $s->tables( 'outer_1', 'outer_2' ) ],
join =>
[ [ right_outer_join =>
$s->tables( 'outer_1', 'outer_2' ), $fk ] ]
) },
"Attempt a right outer join, with explicit foreign key" );
my @sets = $cursor->all_rows;
is( scalar @sets, 2,
"Right outer join should return 2 sets of rows" );
# re-order so that the set with 2 valid rows is always first
unless ( defined $sets[0]->[0] )
{
my $set = shift @sets;
push @sets, $set;
}
is( $sets[0]->[0]->select('outer_1_name'), 'test1 (has matching join row)',
"The first row in the first set should have the name 'test1 (has matching join row)'" );
is( $sets[0]->[1]->select('outer_2_name'), 'will match something',
"The second row in the first set should have the name 'will match something'" );
ok( ! defined $sets[1]->[0],
"The first row in the second set should not be defined" );
is( $sets[1]->[1]->select('outer_2_name'), 'will match nothing',
"The second row in the second set should have the name 'test12 (has no matching join row)'" );
}
}
my $id = $emp{bill}->select('employee_id');
$emp{bill}->delete;
eval { $emp{bill}->select('name'); };
$e = $@;
isa_ok( $e, 'Alzabo::Exception::NoSuchRow',
"Exception thrown from attempt to select from deleted row object" );
{
my $row =
$emp_proj_t->row_by_pk
( pk =>
{ employee_id => $id,
project_id => $proj{extend}->select('project_id') } );
is( $row, undef,
"make sure row was deleted by cascading delte" );
}
is( $dep{borg}->select('manager_id'), 1,
"The manager_id for the borg department will be 1 because the object does not the database was changed" );
$dep{borg}->refresh;
my $dep_id = $dep{borg}->select('department_id');
$emp_t->insert( values => { name => 'bob', smell => 'awful', dep_id => $dep_id } );
$emp_t->insert( values => { name => 'rachel', smell => 'horrid', dep_id => $dep_id } );
$emp_t->insert( values => { name => 'al', smell => 'bad', dep_id => $dep_id } );
{
my @emps;
eval_ok ( sub { @emps = $emp_t->all_rows( order_by =>
[ $emp_t->column('name') ] )->all_rows },
"Select all employee rows with arrayref to order_by" );
is( scalar @emps, 4,
"There should be 4 rows in the employee table" );
is( $emps[0]->select('name'), 'al',
"First row name should be al" );
is( $emps[1]->select('name'), 'bob',
"Second row name should be bob" );
is( $emps[2]->select('name'), 'rachel',
"Third row name should be rachel" );
is( $emps[3]->select('name'), 'unit 2',
"Fourth row name should be 'unit 2'" );
}
{
my @emps;
eval_ok ( sub { @emps = $emp_t->all_rows( order_by =>
[ $emp_t->column('name') ],
quote_identifiers => 1,
)->all_rows },
"Select all employee rows with arrayref to order_by with quote_identifiers" );
is( scalar @emps, 4,
"There should be 4 rows in the employee table" );
is( $emps[0]->select('name'), 'al',
"First row name should be al" );
is( $emps[1]->select('name'), 'bob',
"Second row name should be bob" );
is( $emps[2]->select('name'), 'rachel',
"Third row name should be rachel" );
is( $emps[3]->select('name'), 'unit 2',
"Fourth row name should be 'unit 2'" );
}
{
my @emps;
eval_ok( sub { @emps = $emp_t->all_rows( order_by => $emp_t->column('name') )->all_rows },
"Select all employee rows with column obj to order_by" );
is( scalar @emps, 4,
"There should be 4 rows in the employee table" );
is( $emps[0]->select('name'), 'al',
"First row name should be al" );
is( $emps[1]->select('name'), 'bob',
"Second row name should be bob" );
is( $emps[2]->select('name'), 'rachel',
"Third row name should be rachel" );
is( $emps[3]->select('name'), 'unit 2',
"Fourth row name should be 'unit 2'" );
}
{
my @emps;
eval_ok( sub { @emps = $emp_t->all_rows( order_by => [ $emp_t->column('name') ] )->all_rows },
"Select all employee rows with arrayref to order_by" );
is( scalar @emps, 4,
"There should be 4 rows in the employee table" );
is( $emps[0]->select('name'), 'al',
"First row name should be al" );
is( $emps[1]->select('name'), 'bob',
"Second row name should be bob" );
is( $emps[2]->select('name'), 'rachel',
"Third row name should be rachel" );
is( $emps[3]->select('name'), 'unit 2',
"Fourth row name should be 'unit 2'" );
}
{
my @emps;
eval_ok( sub { @emps = $emp_t->all_rows( order_by =>
[ $emp_t->column('smell') ] )->all_rows },
"Select all employee rows with arrayref to order_by (by smell)" );
is( scalar @emps, 4,
"There should be 4 rows in the employee table" );
is( $emps[0]->select('name'), 'bob',
"First row name should be bob" );
is( $emps[1]->select('name'), 'al',
"Second row name should be al" );
is( $emps[2]->select('name'), 'unit 2',
"Third row name should be 'unit 2'" );
is( $emps[3]->select('name'), 'rachel',
"Fourth row name should be rachel" );
}
{
my @emps;
eval_ok( sub { @emps = $emp_t->all_rows( order_by =>
[ $emp_t->column('smell'), 'desc' ] )->all_rows },
"Select all employee rows order by smell (descending)" );
is( $emps[0]->select('name'), 'rachel',
"First row name should be rachel" );
is( $emps[1]->select('name'), 'unit 2',
"Second row name should be 'unit 2'" );
is( $emps[2]->select('name'), 'al',
"Third row name should be al" );
is( $emps[3]->select('name'), 'bob',
"Fourth row name should be bob" );
}
eval_ok( sub { $count = $emp_t->row_count },
"Call row_count for employee table" );
is( $count, 4,
"The count should be 4" );
eval_ok( sub { $count = $emp_t->function( select => COUNT( $emp_t->column('employee_id') ) ) },
"Get row count via ->function method" );
is( $count, 4,
"There should still be just 4 rows" );
{
my $one;
eval_ok( sub { $one = $emp_t->function( select => 1 ) },
"Get '1' via ->function method" );
is( $one, 1,
"Getting '1' via ->function should return 1" );
}
{
my $statement;
eval_ok( sub { $statement = $emp_t->select( select => COUNT( $emp_t->column('employee_id') ) ) },
"Get row count via even spiffier new ->select method" );
isa_ok( $statement, 'Alzabo::DriverStatement',
"Return value from Table->select method" );
$count = $statement->next;
is( $count, 4,
"There should still be just 4 rows" );
}
{
my $st;
eval_ok( sub { $st = $emp_t->select( select => 1 ) },
"Get '1' via ->select method" );
is( $st->next, 1,
"Getting '1' via ->select should return 1" );
}
{
my @emps;
eval_ok( sub { @emps = $emp_t->all_rows( order_by =>
[ $emp_t->column('smell'), 'desc' ],
limit => 2 )->all_rows },
"Get all employee rows with ORDER BY and LIMIT" );
is( scalar @emps, 2,
"This should only return 2 rows" );
is( $emps[0]->select('name'), 'rachel',
"First row should be rachel" );
is( $emps[1]->select('name'), 'unit 2',
"Second row is 'unit 2'" );
}
{
my @emps;
eval_ok( sub { @emps = $emp_t->all_rows( order_by =>
[ $emp_t->column('smell'), 'desc' ],
limit => [2, 2] )->all_rows },
"Get all employee rows with ORDER BY and LIMIT (with offset)" );
is( scalar @emps, 2,
"This should only return 2 rows" );
is( $emps[0]->select('name'), 'al',
"First row should be al" );
is( $emps[1]->select('name'), 'bob',
"Second row is bob" );
}
$emp_t->set_prefetch( $emp_t->columns( qw( name smell ) ) );
my @p = $emp_t->prefetch;
is( scalar @p, 2,
"Prefetch method should return 2 column names" );
is( scalar ( grep { $_ eq 'name' } @p ), 1,
"One column should be 'name'" );
is( scalar ( grep { $_ eq 'smell' } @p ), 1,
"And the other should be 'smell'" );
is( $emp_t->row_count, 4,
"employee table should have 4 rows" );
{
my @emps = $emp_t->all_rows( order_by =>
[ $emp_t->column('smell'), 'desc' ],
limit => [2, 2] )->all_rows;
my $smell = $emps[0]->select('smell');
is( $emp_t->row_count( where => [ $emp_t->column('smell'), '=', $smell ] ), 1,
"Call row_count method with where parameter." );
$emps[0]->delete;
eval { $emps[0]->update( smell => 'kaboom' ); };
$e = $@;
isa_ok( $e, 'Alzabo::Exception::NoSuchRow',
"Exception thrown from attempt to update a deleted row" );
my $row_id = $emps[1]->id_as_string;
my $row;
eval_ok( sub { $row = $emp_t->row_by_id( row_id => $row_id ) },
"Fetch a row via the ->row_by_id method" );
is( $row->id_as_string, $emps[1]->id_as_string,
"Row retrieved via the ->row_by_id method should be the same as the row whose id was used" );
}
$emp_t->insert( values => { employee_id => 9000,
name => 'bob9000',
smell => 'a',
dep_id => $dep_id } );
$emp_t->insert( values => { employee_id => 9001,
name => 'bob9001',
smell => 'b',
dep_id => $dep_id } );
$emp_t->insert( values => { employee_id => 9002,
name => 'bob9002',
smell => 'c',
dep_id => $dep_id } );
my $eid_c = $emp_t->column('employee_id');
{
my @emps = $emp_t->rows_where( where => [ [ $eid_c, '=', 9000 ],
'or',
[ $eid_c, '=', 9002 ] ] )->all_rows;
@emps = sort { $a->select('employee_id') <=> $b->select('employee_id') } @emps;
is( @emps, 2,
"Do a query with 'or' and count the rows" );
is( $emps[0]->select('employee_id'), 9000,
"First row returned should be employee id 9000" );
is( $emps[1]->select('employee_id'), 9002,
"Second row returned should be employee id 9002" );
}
{
my @emps = $emp_t->rows_where( where => [ [ $emp_t->column('smell'), '!=', 'c' ],
'and',
(
'(',
[ $eid_c, '=', 9000 ],
'or',
[ $eid_c, '=', 9002 ],
')',
),
] )->all_rows;
is( @emps, 1,
"Do another complex query with 'or' and subgroups" );
is( $emps[0]->select('employee_id'), 9000,
"The row returned should be employee id 9000" );
}
{
my @emps = $emp_t->rows_where( where => [ (
'(',
[ $eid_c, '=', 9000 ],
'and',
[ $eid_c, '=', 9000 ],
')',
),
'or',
(
'(',
[ $eid_c, '=', 9000 ],
'and',
[ $eid_c, '=', 9000 ],
')',
),
] )->all_rows;
is( @emps, 1,
"Do another complex query with 'or', 'and' and subgroups" );
is( $emps[0]->select('employee_id'), 9000,
"The row returned should be employee id 9000" );
}
{
my @emps = $emp_t->rows_where( where => [ $eid_c, 'between', 9000, 9002 ] )->all_rows;
@emps = sort { $a->select('employee_id') <=> $b->select('employee_id') } @emps;
is( @emps, 3,
"Select using between should return 3 rows" );
is( $emps[0]->select('employee_id'), 9000,
"First row returned should be employee id 9000" );
is( $emps[1]->select('employee_id'), 9001,
"Second row returned should be employee id 9001" );
is( $emps[2]->select('employee_id'), 9002,
"Third row returned should be employee id 9002" );
}
{
my @emps;
eval_ok( sub { @emps = $emp_t->rows_where( where => [ '(', '(',
[ $eid_c, '=', 9000 ],
')', ')'
] )->all_rows },
"Nested subgroups should be allowed" );
is( @emps, 1,
"Query with nested subgroups should return 1 row" );
is( $emps[0]->select('employee_id'), 9000,
"The row returned should be employee id 9000" );
}
$emp_t->insert( values => { name => 'Smelly',
smell => 'a',
dep_id => $dep_id,
} );
{
my @emps = eval { $emp_t->rows_where( where => [ LENGTH( $emp_t->column('smell') ), '=', 1 ] )->all_rows };
is( @emps, 4,
"There should be only 4 employees where the length of the smell column is 1" );
}
{
my @emps;
eval_ok( sub { @emps = $emp_t->rows_where( where => [ LENGTH( $emp_t->column('smell') ), '=', 1 ],
limit => 2 )->all_rows },
"Select all employee rows with WHERE and LIMIT" );
is( scalar @emps, 2,
"Limit should cause only two employee rows to be returned" );
}
{
my @emps;
eval_ok( sub { @emps = $emp_t->rows_where( where => [ LENGTH( $emp_t->column('smell') ), '=', 1 ],
order_by => $emp_t->column('smell'),
limit => 2 )->all_rows },
"Select all employee rows with WHERE, ORDER BY, and LIMIT" );
is( scalar @emps, 2,
"Limit should cause only two employee rows to be returned (again)" );
}
{
my @emps;
eval_ok( sub { @emps = $emp_t->rows_where( where => [ '(',
[ $emp_t->column('employee_id'), '=', 9000 ],
')',
],
order_by => $emp_t->column('employee_id') )->all_rows },
"Query with subgroup followed by order by" );
is( @emps, 1,
"Query with subgroup followed by order by should return 1 row" );
is( $emps[0]->select('employee_id'), 9000,
"The row returned should be employee id 9000" );
}
my @smells = $emp_t->function( select => [ $emp_t->column('smell'), COUNT( $emp_t->column('smell') ) ],
group_by => $emp_t->column('smell') );
# map smell to count
my %smells = map { $_->[0] => $_->[1] } @smells;
is( @smells, 6,
"Query with group by should return 6 values" );
is( $smells{a}, 2,
"Check count of smell = 'a'" );
is( $smells{b}, 1,
"Check count of smell = 'b'" );
is( $smells{c}, 1,
"Check count of smell = 'c'" );
is( $smells{awful}, 1,
"Check count of smell = 'awful'" );
is( $smells{good}, 1,
"Check count of smell = 'good'" );
is( $smells{horrid}, 1,
"Check count of smell = 'horrid'" );
{
my $statement = $emp_t->select( select => [ $emp_t->column('smell'), COUNT( $emp_t->column('smell') ) ],
group_by => $emp_t->column('smell') );
my @smells = $statement->all_rows;
# map smell to count
%smells = map { $_->[0] => $_->[1] } @smells;
is( @smells, 6,
"Query with group by should return 6 values - via ->select" );
is( $smells{a}, 2,
"Check count of smell = 'a' - via ->select" );
is( $smells{b}, 1,
"Check count of smell = 'b' - via ->select" );
is( $smells{c}, 1,
"Check count of smell = 'c' - via ->select" );
is( $smells{awful}, 1,
"Check count of smell = 'awful' - via ->select" );
is( $smells{good}, 1,
"Check count of smell = 'good' - via ->select" );
is( $smells{horrid}, 1,
"Check count of smell = 'horrid' - via ->select" );
}
@rows = $emp_t->function( select => $emp_t->column('smell'),
where => [ LENGTH( $emp_t->column('smell') ), '=', 1 ],
order_by => $emp_t->column('smell') );
is( @rows, 4,
"There should only be four rows which have a single character smell" );
is( $rows[0], 'a',
"First smell should be 'a'" );
is( $rows[1], 'a',
"Second smell should be 'a'" );
is( $rows[2], 'b',
"Third smell should be 'b'" );
is( $rows[3], 'c',
"Fourth smell should be 'c'" );
{
my $statement = $emp_t->select( select => $emp_t->column('smell'),
where => [ LENGTH( $emp_t->column('smell') ), '=', 1 ],
order_by => $emp_t->column('smell') );
my @rows = $statement->all_rows;
is( @rows, 4,
"There should only be four rows which have a single character smell - via ->select" );
is( $rows[0], 'a',
"First smell should be 'a' - via ->select" );
is( $rows[1], 'a',
"Second smell should be 'a' - via ->select" );
is( $rows[2], 'b',
"Third smell should be 'b' - via ->select" );
is( $rows[3], 'c',
"Fourth smell should be 'c' - via ->select" );
}
@rows = $emp_t->function( select => $emp_t->column('smell'),
where => [ LENGTH( $emp_t->column('smell') ), '=', 1 ],
order_by => $emp_t->column('smell'),
limit => 2,
);
is( @rows, 2,
"There should only be two rows which have a single character smell - with limit" );
is( $rows[0], 'a',
"First smell should be 'a' - with limit" );
is( $rows[1], 'a',
"Second smell should be 'a' - with limit" );
{
my $statement = $emp_t->select( select => $emp_t->column('smell'),
where => [ LENGTH( $emp_t->column('smell') ), '=', 1 ],
order_by => $emp_t->column('smell'),
limit => 2,
);
my @rows = $statement->all_rows;
is( @rows, 2,
"There should only be two rows which have a single character smell - with limit via ->select" );
is( $rows[0], 'a',
"First smell should be 'a' - with limit via ->select" );
is( $rows[1], 'a',
"Second smell should be 'a' - with limit via ->select" );
}
my $extend_id = $proj{extend}->select('project_id');
my $embrace_id = $proj{embrace}->select('project_id');
foreach ( [ 9000, $extend_id ], [ 9000, $embrace_id ],
[ 9001, $extend_id ], [ 9002, $extend_id ] )
{
$emp_proj_t->insert( values => { employee_id => $_->[0],
project_id => $_->[1] } );
}
# find staffed projects
@rows = $s->function( select => [ $proj_t->column('name'),
COUNT( $proj_t->column('name') ) ],
join => [ $emp_proj_t, $proj_t ],
group_by => $proj_t->column('name') );
is( @rows, 2,
"Only two projects should be returned from schema->function" );
is( $rows[0][0], 'Embrace',
"First project should be Embrace" );
is( $rows[1][0], 'Extend',
"Second project should be Extend" );
is( $rows[0][1], 1,
"First project should have 1 employee" );
is( $rows[1][1], 3,
"Second project should have 3 employees" );
{
my $statement = $s->select( select => [ $proj_t->column('name'),
COUNT( $proj_t->column('name') ) ],
join => [ $emp_proj_t, $proj_t ],
group_by => $proj_t->column('name') );
my @rows = $statement->all_rows;
is( @rows, 2,
"Only two projects should be returned from schema->select" );
is( $rows[0][0], 'Embrace',
"First project should be Embrace - via ->select" );
is( $rows[1][0], 'Extend',
"Second project should be Extend - via ->select" );
is( $rows[0][1], 1,
"First project should have 1 employee - via ->select" );
is( $rows[1][1], 3,
"Second project should have 3 employees - via ->select" );
}
@rows = $s->function( select => [ $proj_t->column('name'),
COUNT( $proj_t->column('name') ) ],
join => [ $emp_proj_t, $proj_t ],
group_by => $proj_t->column('name'),
limit => [1, 1],
);
is( @rows, 1,
"Only one projects should be returned from schema->function - with limit" );
is( $rows[0][0], 'Extend',
"First project should be Extend - with limit" );
is( $rows[0][1], 3,
"First project should have 3 employees - with limit" );
{
my $statement = $s->select( select => [ $proj_t->column('name'),
COUNT( $proj_t->column('name') ) ],
join => [ $emp_proj_t, $proj_t ],
group_by => $proj_t->column('name'),
limit => [1, 1],
);
my @rows = $statement->all_rows;
is( @rows, 1,
"Only one projects should be returned from schema->select - with limit via ->select" );
is( $rows[0][0], 'Extend',
"First project should be Extend - with limit via ->select" );
is( $rows[0][1], 3,
"First project should have 3 employees - with limit via ->select" );
}
{
my @rows = $s->function( select => [ $proj_t->column('name'),
COUNT( $proj_t->column('name') ) ],
join => [ $emp_proj_t, $proj_t ],
group_by => $proj_t->column('name'),
order_by => [ COUNT( $proj_t->column('name') ), 'DESC' ] );
is( @rows, 2,
"Only two projects should be returned from schema->function ordered by COUNT(*)" );
is( $rows[0][0], 'Extend',
"First project should be Extend" );
is( $rows[1][0], 'Embrace',
"Second project should be Embrace" );
is( $rows[0][1], 3,
"First project should have 3 employee" );
is( $rows[1][1], 1,
"Second project should have 1 employees" );
}
{
my @rows = $s->function( select => [ $proj_t->column('name'),
COUNT( $proj_t->column('name') ) ],
join => [ $emp_proj_t, $proj_t ],
group_by => $proj_t->column('name'),
order_by => [ COUNT( $proj_t->column('name') ), 'DESC' ],
having => [ COUNT( $proj_t->column('name') ), '>', 2 ],
);
is( @rows, 1,
"Only one project should be returned from schema->function ordered by COUNT(*) HAVING COUNT(*) > 2" );
is( $rows[0][0], 'Extend',
"First project should be Extend" );
is( $rows[0][1], 3,
"First project should have 3 employee" );
}
{
my @rows;
eval_ok( sub { @rows = $s->function( select => 1,
join => [ $emp_proj_t, $proj_t ],
) },
"Call schema->function with scalar select" );
is( @rows, 4,
"Should return four rows" );
}
{
my $st;
eval_ok( sub { $st = $s->select( select => 1,
join => [ $emp_proj_t, $proj_t ],
) },
"Call schema->select with scalar select" );
my @rows = $st->all_rows;
is( @rows, 4,
"Should return four rows" );
}
my $p1 = $proj_t->insert( values => { name => 'P1',
department_id => $dep_id,
} );
my $p2 = $proj_t->insert( values => { name => 'P2',
department_id => $dep_id,
} );
eval_ok( sub { $cursor = $s->join( distinct => $dep_t,
join => [ $dep_t, $proj_t ],
where => [ $proj_t->column('project_id'), 'in',
map { $_->select('project_id') } $p1, $p2 ],
) },
"Do a join with distinct parameter set" );
@rows = $cursor->all_rows;
is( scalar @rows, 1,
"Setting distinct should cause only a single row to be returned" );
is( $rows[0]->select('department_id'), $dep_id,
"Returned row's department_id should be $dep_id" );
{
eval_ok( sub { $cursor =
$s->join( distinct => $emp_proj_t,
join => [ $emp_t, $emp_proj_t ],
where => [ $emp_t->column('employee_id'), 'in', 9001 ],
) },
"Do a join with distinct parameter set to a table with a multi-col PK" );
@rows = $cursor->all_rows;
is( scalar @rows, 1,
"Setting distinct should cause only a single row to be returned" );
is( $rows[0]->select('employee_id'), 9001,
"Returned row's employee_id should be 9001" );
}
{
eval_ok( sub { $cursor =
$s->join
( distinct => [ $emp_t, $emp_proj_t ],
join => [ $emp_t, $emp_proj_t ],
where =>
[ $emp_t->column('employee_id'), 'in', 9000, 9001 ],
) },
"Do a join with distinct parameter set to a table with a multi-col PK" );
@rows = $cursor->all_rows;
is( scalar @rows, 3,
"Setting distinct should cause only three rows to be returned" );
ok( ( grep { $_->[0]->select('employee_id') == 9000 } @rows ),
"Returned rows should include employee_id 9000" );
ok( ( grep { $_->[0]->select('employee_id') == 9001 } @rows ),
"Returned rows should include employee_id 9001" );
}
{
$proj_t->insert( values => { name => 'P99',
department_id => $dep{lying}->select('department_id'),
} );
eval_ok( sub { $cursor = $s->join( distinct => $dep_t,
join => [ $dep_t, $proj_t ],
order_by => $proj_t->column('name'),
) },
"Do a join with distinct and order_by not in select" );
@rows = $cursor->all_rows;
if ( $rdbms eq 'pg' )
{
is( scalar @rows, 5, "distinct should cause only five rows to be returned" );
}
else
{
is( scalar @rows, 2, "distinct should cause only two rows to be returned" );
}
is( $rows[0]->select('department_id'), $dep{borg}->select('department_id'),
'first row is borg department' );
is( $rows[-1]->select('department_id'), $dep{lying}->select('department_id'),
'last row is lying department' );
# Prevents a warning later about destroying a DBI handle with
# active statement handles.
undef $cursor;
}
# insert rows used to test order by with multiple columns
my $start_id = 999_990;
foreach ( [ qw( OB1 bad ) ],
[ qw( OB1 worse ) ],
[ qw( OB2 bad ) ],
[ qw( OB2 worse ) ],
[ qw( OB3 awful ) ],
[ qw( OB3 bad ) ],
)
{
$emp_t->insert( values => { employee_id => $start_id++,
name => $_->[0],
smell => $_->[1],
dep_id => $dep_id } );
}
@rows = $emp_t->rows_where( where => [ $emp_t->column('employee_id'), 'BETWEEN',
999_990, 999_996 ],
order_by => [ $emp_t->columns( 'name', 'smell' ) ] )->all_rows;
is( $rows[0]->select('name'), 'OB1',
"First row name should be OB1" );
is( $rows[0]->select('smell'), 'bad',
"First row smell should be bad" );
is( $rows[1]->select('name'), 'OB1',
"Second row name should be OB1" );
is( $rows[1]->select('smell'), 'worse',
"Second row smell should be bad" );
is( $rows[2]->select('name'), 'OB2',
"Third row name should be OB2" );
is( $rows[2]->select('smell'), 'bad',
"Third row smell should be bad" );
is( $rows[3]->select('name'), 'OB2',
"Fourth row name should be OB2" );
is( $rows[3]->select('smell'), 'worse',
"Fourth row smell should be worse" );
is( $rows[4]->select('name'), 'OB3',
"Fifth row name should be OB3" );
is( $rows[4]->select('smell'), 'awful',
"Fifth row smell should be awful" );
is( $rows[5]->select('name'), 'OB3',
"Sixth row name should be OB3" );
is( $rows[5]->select('smell'), 'bad',
"Sixth row smell should be bad" );
@rows = $emp_t->rows_where( where => [ $emp_t->column('employee_id'), 'BETWEEN',
999_990, 999_996 ],
order_by => [ $emp_t->column('name'), 'desc', $emp_t->column('smell'), 'asc' ] )->all_rows;
is( $rows[0]->select('name'), 'OB3',
"First row name should be OB3" );
is( $rows[0]->select('smell'), 'awful',
"First row smell should be awful" );
is( $rows[1]->select('name'), 'OB3',
"Second row name should be OB3" );
is( $rows[1]->select('smell'), 'bad',
"Second row smell should be bad" );
is( $rows[2]->select('name'), 'OB2',
"Third row name should be OB2" );
is( $rows[2]->select('smell'), 'bad',
"Third row smell should be bad" );
is( $rows[3]->select('name'), 'OB2',
"Fourth row name should be OB2" );
is( $rows[3]->select('smell'), 'worse',
"Fourth row smell should be worse" );
is( $rows[4]->select('name'), 'OB1',
"Fifth row name should be OB1" );
is( $rows[4]->select('smell'), 'bad',
"Fifth row smell should be bad" );
is( $rows[5]->select('name'), 'OB1',
"Sixth row name should be OB1" );
is( $rows[5]->select('smell'), 'worse',
"Sixth row smell should be worse" );
if ( $rdbms eq 'mysql' )
{
my $emp;
eval_ok( sub { $emp = $emp_t->insert( values => { name => UNIX_TIMESTAMP(),
dep_id => $dep_id } ) },
"Insert using SQL function UNIX_TIMESTAMP()" );
like( $emp->select('name'), qr/\d+/,
"Name should be all digits (unix timestamp)" );
eval_ok( sub { $emp->update( name => LOWER('FOO') ) },
"Do update using SQL function LOWER()" );
is( $emp->select('name'), 'foo',
"Name should be 'foo'" );
eval_ok( sub { $emp->update( name => REPEAT('Foo', 3) ) },
"Do update using SQL function REPEAT()" );
is( $emp->select('name'), 'FooFooFoo',
"Name should be 'FooFooFoo'" );
eval_ok( sub { $emp->update( name => UPPER( REPEAT('Foo', 3) ) ) },
"Do update using nested SQL functions UPPER(REPEAT())" );
is( $emp->select('name'), 'FOOFOOFOO',
"Name should be 'FOOFOOFOO'" );
$emp_t->insert( values => { name => 'Timestamp',
dep_id => $dep_id,
tstamp => time - 100_000 } );
my $cursor;
eval_ok( sub { $cursor =
$emp_t->rows_where( where =>
[ [ $emp_t->column('tstamp'), '!=', undef ],
[ $emp_t->column('tstamp'), '<', UNIX_TIMESTAMP() ] ] ) },
"Do select with where condition that uses SQL function UNIX_TIMESTAMP()" );
my @rows = $cursor->all_rows;
is( scalar @rows, 1,
"Only one row should have a timestamp value that is not null and that is less than the current time" );
is( $rows[0]->select('name'), 'Timestamp',
"That row should be named Timestamp" );
# Fulltext support tests
my $snuffle_id = $emp_t->insert( values => { name => 'snuffleupagus',
smell => 'invisible',
dep_id => $dep_id } )->select('employee_id');
@rows = $emp_t->rows_where( where => [ MATCH( $emp_t->column('name') ), AGAINST('abathraspus') ] )->all_rows;
is( @rows, 0,
"Make sure that fulltext search doesn't give a false positive" );
@rows = $emp_t->rows_where( where => [ MATCH( $emp_t->column('name') ), AGAINST('snuffleupagus') ] )->all_rows;
is( @rows, 1,
"Make sure that fulltext search for snuffleupagus returns 1 row" );
is( $rows[0]->select('employee_id'), $snuffle_id,
"Make sure that the returned row is snuffleupagus" );
my $rows = $emp_t->function( select => [ $emp_t->column('employee_id'), MATCH( $emp_t->column('name') ), AGAINST('snuffleupagus') ],
where => [ MATCH( $emp_t->column('name') ), AGAINST('snuffleupagus') ] );
my ($id, $score) = @$rows;
is( $id, $snuffle_id,
"Returned row should still be snuffleupagus" );
like( $score, qr/\d+(?:\.\d+)?/,
"Returned score should be some sort of number (integer or floating point)" );
ok( $score > 0,
"The score should be greater than 0 because the match was successful" );
eval_ok( sub { @rows = $emp_t->all_rows( order_by => [ IF( 'employee_id < 100',
$emp_t->column('employee_id'),
$emp_t->column('smell') ),
$emp_t->column('employee_id'),
],
)->all_rows },
"Order by IF() function" );
is( @rows, 16,
"Seventeen rows should have been returned" );
is( $rows[0]->select('employee_id'), 3,
"First row should be id 3" );
is( $rows[-1]->select('employee_id'), 999993,
"Last row should be id 999993" );
eval_ok( sub { @rows = $emp_t->all_rows( order_by => RAND() )->all_rows },
"order by RAND()" );
is ( @rows, 16,
"This should return 16 rows" );
}
elsif ( $rdbms eq 'pg' )
{
my $emp;
eval_ok( sub { $emp = $emp_t->insert( values => { name => NOW(),
dep_id => $dep_id } ) },
"Do insert using SQL function NOW()" );
like( $emp->select('name'), qr/\d+/,
"Name should be all digits (Postgres timestamp)" );
eval_ok( sub { $emp->update( name => LOWER('FOO') ) },
"Do update using SQL function LOWER()" );
is( $emp->select('name'), 'foo',
"Name should be 'foo'" );
eval_ok( sub { $emp->update( name => REPEAT('Foo', 3) ) },
"Do update using SQL function REPEAT()" );
is( $emp->select('name'), 'FooFooFoo',
"Name should be 'FooFooFoo'" );
eval_ok( sub { $emp->update( name => UPPER( REPEAT('Foo', 3) ) ) },
"Do update using nested SQL functions UPPER(REPEAT())" );
is( $emp->select('name'), 'FOOFOOFOO',
"Name should be 'FOOFOOFOO'" );
$emp_t->insert( values => { name => 'Timestamp',
dep_id => $dep_id,
tstamp => time - 100_000 } );
my $cursor;
eval_ok( sub { $cursor =
$emp_t->rows_where( where =>
[ [ $emp_t->column('tstamp'), '!=', undef ],
[ $emp_t->column('tstamp'), '<', NOW() ] ] ) },
"Do select with where condition that uses SQL function NOW()" );
my @rows = $cursor->all_rows;
is( scalar @rows, 1,
"Only one row should have a timestamp value that is not null and that is less than the current time" );
is( $rows[0]->select('name'), 'Timestamp',
"That row should be named Timestamp" );
}
# Potential rows
my $p_emp;
eval_ok( sub { $p_emp = $emp_t->potential_row },
"Create potential row object");
is( $p_emp->is_live, 0,
"potential_row should ! ->is_live" );
is( $p_emp->select('smell'), 'grotesque',
"Potential Employee should have default smell, 'grotesque'" );
{
my $updated = $p_emp->update( cash => undef, smell => 'hello!' );
ok( $updated, 'update() did change values' );
ok( ! defined $p_emp->select('cash'),
"Potential Employee cash column is not defined" );
}
{
my $updated = $p_emp->update( cash => undef, smell => 'hello!' );
ok( ! $updated, 'update() did not change values' );
}
is( $p_emp->select('smell'), 'hello!',
"smell for employee should be 'hello!' after update" );
$p_emp->update( name => 'Ilya' );
is( $p_emp->select('name'), 'Ilya',
"New employee got a name" );
$p_emp->update( dep_id => $dep_id );
is( $p_emp->select('dep_id'), $dep_id,
"New employee got a department" );
eval { $p_emp->update( wrong => 'column' ) };
$e = $@;
isa_ok( $e, 'Alzabo::Exception::Params',
"Exception thrown from attempt to update a column which doesn't exist" );
eval { $p_emp->update( name => undef ) };
$e = $@;
isa_ok( $e, 'Alzabo::Exception::NotNullable',
"Exception thrown from attempt to update a non-NULLable column in a potential row to null" );
eval_ok( sub { $p_emp->make_live( values => { smell => 'cottony' } ) },
"Make potential row live");
is( $p_emp->select('name'), 'Ilya',
"Formerly potential employee row object should have same name as before" );
is( $p_emp->select('smell'), 'cottony',
"Formerly potential employee row object should have new smell of 'cottony'" );
eval_ok ( sub { $p_emp->delete },
"Delete new employee" );
eval_ok( sub { $p_emp = $emp_t->potential_row( values => { cash => 100 } ) },
"Create potential row object and set some fields ");
is( $p_emp->select('cash'), 100,
"Employee cash should be 100" );
eval { $emp_t->rows_where( where => [ $eid_c, '=', 9000,
$eid_c, '=', 9002 ] ) };
$e = $@;
isa_ok( $e, 'Alzabo::Exception::Params',
"Exception from where clause as single arrayref with <>3 elements" );
{
# test that DriverStatement objects going out of scope leave
# $@ alone!
eval
{
my $cursor = $emp_t->all_rows;
die "ok\n";
};
is( $@, "ok\n",
"\$\@ should be 'ok'" );
}
{
my $row;
eval_ok( sub { $row =
$emp_t->one_row
( where => [ $emp_t->column('name'), '=', 'nonexistent' ] ) },
"Call ->one_row with a query guaranteed to fail" );
ok( ! defined $row,
"Make sure that the query really returned nothing" );
}
{
is( scalar $proj_t->prefetch,
( scalar $proj_t->columns -
$proj_t->primary_key_size -
scalar ( grep { $_->is_blob } $proj_t->columns ) ),
"Check that schema->prefetch_all_but_blobs is on by default" );
}
{
$proj_t->set_prefetch();
$s->prefetch_all;
is( scalar $proj_t->prefetch,
( scalar $proj_t->columns -
scalar $proj_t->primary_key_size ),
"Check that schema->prefetch_all works" );
}
{
$proj_t->set_prefetch();
$s->prefetch_all_but_blobs;
is( scalar $proj_t->prefetch,
( scalar $proj_t->columns -
$proj_t->primary_key_size -
scalar ( grep { $_->is_blob } $proj_t->columns ) ),
"Check that schema->prefetch_all_but_blobs works" );
}
{
$s->prefetch_none;
is( scalar $proj_t->prefetch, 0,
"Check that schema->prefetch_none works" );
}
{
$s->prefetch_all;
my $cursor;
eval_ok( sub { $cursor =
$s->join( join => [ $emp_t, $emp_proj_t, $proj_t ],
where => [ $emp_t->column('employee_id'), '=', 9001 ] ) },
"Join with join as arrayref of arrayrefs" );
my @rows = $cursor->next;
is( scalar @rows, 3,
"3 rows per cursor ->next call" );
is( ( grep { defined } @rows ), 3,
"Make sure all rows are defined" );
is( $rows[0]->select('employee_id'), 9001,
"First rows should have employee_id == 9001" );
is( $rows[0]->select('name'), 'bob9001',
"First rows should have employee with name eq 'bob9001'" );
is( $rows[2]->select('name'), 'Extend',
"First rows should have project with name eq 'Extend'");
}
{
my $foo = $emp_t->column('employee_id')->alias( as => 'foo' );
my $st = $emp_t->select( select => $foo );
my %h = $st->next_as_hash;
is( exists $h{foo}, 1,
"next_as_hash should return a hash with a 'foo' key" );
}
$s->disconnect;
}
syntax highlighted by Code2HTML, v. 0.9.1