Database-Abstraction
view release on metacpan or search on metacpan
t/transaction.t view on Meta::CPAN
# Force SQL path with max_slurp_size=>0 so cache is actually consulted.
my $db_sql = Database::test1->new(
directory => $DATA_DIR,
cache => $cache,
cache_duration => '1 hour',
max_slurp_size => 0,
);
# T4-2: first selectall_arrayref() is a MISS and populates one cache entry
my $fresh = $db_sql->selectall_arrayref();
cmp_ok(scalar $cache->get_keys(), '==', 1,
'T4-2: after first selectall_arrayref(), cache has 1 key (MISS â SET)');
# T4-3: second identical query is a HIT â cache key count unchanged
$db_sql->selectall_arrayref();
cmp_ok(scalar $cache->get_keys(), '==', 1,
'T4-3: second identical query is a cache HIT (key count unchanged)');
# T4-4: a parameterised selectall_arrayref produces a second cache key
# (count() reads but never writes the cache, so we use selectall_arrayref)
$db_sql->selectall_arrayref(entry => $ENTRY_ONE);
cmp_ok(scalar $cache->get_keys(), '>=', 2,
'T4-4: parameterised selectall_arrayref produces a new cache key (MISS â SET)');
# T4-5: cached result is structurally identical to a repeat fresh call result
my $cached = $db_sql->selectall_arrayref();
is_deeply($fresh, $cached,
'T4-5: cache HIT returns data deeply equal to the original MISS result');
# T4-6: a second object sharing the same cache gets a HIT for a key the first populated
my $db_sql2 = Database::test1->new(
directory => $DATA_DIR,
cache => $cache,
cache_duration => '1 hour',
max_slurp_size => 0,
);
my $pre_keys = scalar $cache->get_keys();
$db_sql2->selectall_arrayref();
cmp_ok(scalar $cache->get_keys(), '==', $pre_keys,
'T4-6: second object sharing cache gets HIT from first object\'s entry (no new key added)');
}
# ---------------------------------------------------------------------------
# Section 5: Gzip resource lifecycle â temp file born, used, and unlinked
# ---------------------------------------------------------------------------
note('Section 5: gzip temp file resource lifecycle');
{
# Build a gzip CSV in a temp directory.
# test1 uses '!' as sep_char and has an 'entry' key column.
my $tmpdir = File::Temp->newdir(CLEANUP => 1);
my $csv_plain = "entry!number\n\"one\"!1\n\"two\"!2\n\"three\"!3\n";
my $gz_path = File::Spec->catfile("$tmpdir", 'test1.csv.gz');
gzip \$csv_plain => $gz_path or die "gzip failed: $GzipError";
# T5-1: gzip CSV opens and returns the correct row count
my $db_gz = Database::test1->new("$tmpdir");
cmp_ok($db_gz->count(), '==', 3, 'T5-1: gzip CSV opens and count() == 3');
# T5-2: during lifetime, _temp_fh holds a File::Temp object (decompressed copy)
ok(defined $db_gz->{'_temp_fh'}, 'T5-2: _temp_fh is set while gzip object is alive');
# T5-3: the temp file actually exists on disk during object lifetime
my $tmpfile_path = $db_gz->{'_temp_fh'}->filename();
ok(-e $tmpfile_path, 'T5-3: decompressed temp file exists on disk during object lifetime');
# T5-4: multiple queries use the same temp file (no re-extraction between calls)
my $path_after_q2 = do { $db_gz->selectall_arrayref(); $db_gz->{'_temp_fh'}->filename() };
is($path_after_q2, $tmpfile_path,
'T5-4: same temp file path after second query (no re-extraction)');
# T5-5: after DESTROY, _temp_fh is cleared (File::Temp auto-unlinks it)
$db_gz->DESTROY();
ok(!defined $db_gz->{'_temp_fh'},
'T5-5: _temp_fh cleared after DESTROY (temp file auto-unlinked)');
}
# ---------------------------------------------------------------------------
# Section 6: Query-builder chain idempotency
# ---------------------------------------------------------------------------
note('Section 6: query-builder chain idempotency');
{
my $db = Database::test1->new($DATA_DIR);
# T6-1: whereâlimitâall delivers the expected filtered, limited result
my $r1 = $db->query()
->where(entry => $ENTRY_ONE)
->limit(5)
->all();
ok(ref $r1 eq 'ARRAY' && scalar @{$r1} == 1 && $r1->[0]{'entry'} eq $ENTRY_ONE,
'T6-1: where(entry=one)->limit(5)->all() returns exactly 1 matching row');
# T6-2: executing the identical chain a second time returns a deeply equal result
my $r2 = $db->query()
->where(entry => $ENTRY_ONE)
->limit(5)
->all();
is_deeply($r1, $r2, 'T6-2: identical builder chain executed twice gives deeply equal results');
# T6-3: query-builder count() is consistent with direct count() for same params
my $qb_count = $db->query()->where(entry => $ENTRY_TWO)->count();
my $direct_count = $db->count(entry => $ENTRY_TWO);
cmp_ok($qb_count, '==', $direct_count,
'T6-3: query-builder count() == direct count() for identical criteria');
# T6-4: two independent chains on the same object return independent results
my $chain_a = $db->query()->where(entry => $ENTRY_ONE)->all();
my $chain_b = $db->query()->where(entry => $ENTRY_TWO)->all();
isnt($chain_a->[0]{'entry'}, $chain_b->[0]{'entry'},
'T6-4: two independent builder chains return distinct result sets');
}
( run in 1.061 second using v1.01-cache-2.11-cpan-14f38c9f855 )