mirror of
https://github.com/DBD-SQLite/DBD-SQLite
synced 2025-06-07 14:19:10 -04:00
173 lines
3.6 KiB
Perl
173 lines
3.6 KiB
Perl
#!/usr/bin/perl
|
|
use strict;
|
|
BEGIN {
|
|
$| = 1;
|
|
$^W = 1;
|
|
}
|
|
|
|
use t::lib::Test qw/connect_ok/;
|
|
use Test::More;
|
|
use Test::NoWarnings;
|
|
|
|
plan tests => 15;
|
|
|
|
my $dbh = connect_ok( RaiseError => 1, PrintError => 0, AutoCommit => 1 );
|
|
|
|
$dbh->sqlite_create_module(vtab => "DBD::SQLite::VirtualTable::T");
|
|
|
|
ok $dbh->do("CREATE VIRTUAL TABLE foobar USING vtab(foo INTEGER, bar INTEGER)"),
|
|
"created foobar";
|
|
|
|
# overload functions "abs" and "substr"
|
|
$DBD::SQLite::VirtualTable::T::funcs{abs}{overloaded}
|
|
= sub {my $val = shift; return "fake_abs($val)" };
|
|
$DBD::SQLite::VirtualTable::T::funcs{substr}{overloaded}
|
|
= sub {my ($val, $offset, $len) = @_; return "fake_substr($val, $offset, $len)" };
|
|
|
|
# make a first query
|
|
my $row = $dbh->selectrow_hashref(<<"");
|
|
SELECT abs(foo) afoo,
|
|
abs(bar) abar,
|
|
substr(foo, 3, 5) sfoo,
|
|
trim(foo) tfoo
|
|
FROM foobar
|
|
|
|
is $DBD::SQLite::VirtualTable::T::funcs{abs}{calls}, 1, "abs called";
|
|
is $DBD::SQLite::VirtualTable::T::funcs{substr}{calls}, 1, "substr called";
|
|
is $DBD::SQLite::VirtualTable::T::funcs{trim}{calls}, 1, "trim called";
|
|
|
|
is_deeply $row, { 'abar' => 'fake_abs(1)',
|
|
'afoo' => 'fake_abs(0)',
|
|
'sfoo' => 'fake_substr(0, 3, 5)',
|
|
'tfoo' => '0' }, "func results";
|
|
|
|
# new query : FIND_FUNCTION should not be called again
|
|
$row = $dbh->selectrow_hashref(<<"");
|
|
SELECT abs(foo) afoo,
|
|
abs(bar) abar,
|
|
substr(foo, 3, 5) sfoo,
|
|
trim(foo) tfoo
|
|
FROM foobar
|
|
|
|
is $DBD::SQLite::VirtualTable::T::funcs{abs}{calls}, 1, "abs still 1";
|
|
is $DBD::SQLite::VirtualTable::T::funcs{substr}{calls}, 1, "substr still 1";
|
|
is $DBD::SQLite::VirtualTable::T::funcs{trim}{calls}, 1, "trim still 1";
|
|
|
|
|
|
# new table : should issue new calls to FIND_FUNCTION
|
|
ok $dbh->do("CREATE VIRTUAL TABLE barfoo USING vtab(foo INTEGER, bar INTEGER)"),
|
|
"created barfoo";
|
|
|
|
$row = $dbh->selectrow_hashref(<<"");
|
|
SELECT abs(foo) afoo,
|
|
abs(bar) abar,
|
|
substr(foo, 3, 5) sfoo,
|
|
trim(foo) tfoo
|
|
FROM barfoo
|
|
|
|
is $DBD::SQLite::VirtualTable::T::funcs{abs}{calls}, 2, "abs now 2";
|
|
is $DBD::SQLite::VirtualTable::T::funcs{substr}{calls}, 2, "substr now 2";
|
|
is $DBD::SQLite::VirtualTable::T::funcs{trim}{calls}, 2, "trim now 2";
|
|
|
|
|
|
# drop table : should free references to functions
|
|
ok $dbh->do("DROP TABLE foobar");
|
|
|
|
# drop connection
|
|
undef $dbh;
|
|
|
|
note "done";
|
|
|
|
package DBD::SQLite::VirtualTable::T;
|
|
use strict;
|
|
use warnings;
|
|
use base 'DBD::SQLite::VirtualTable';
|
|
use YAML;
|
|
|
|
|
|
|
|
sub BEST_INDEX {
|
|
my ($self, $constraints, $order_by) = @_;
|
|
|
|
my $ix = 0;
|
|
|
|
foreach my $constraint (@$constraints) {
|
|
$constraint->{argvIndex} = $ix++;
|
|
$constraint->{omit} = 1; # to prevent sqlite core to check values
|
|
}
|
|
|
|
my $outputs = {
|
|
idxNum => 1,
|
|
idxStr => "foobar",
|
|
orderByConsumed => 0,
|
|
estimatedCost => 1.0,
|
|
estimatedRows => undef,
|
|
};
|
|
|
|
return $outputs;
|
|
}
|
|
|
|
our %funcs;
|
|
|
|
|
|
sub FIND_FUNCTION {
|
|
my ($self, $n_arg, $function_name) = @_;
|
|
|
|
$funcs{$function_name}{calls} += 1;
|
|
my $func = $funcs{$function_name}{overloaded};
|
|
return $func;
|
|
}
|
|
|
|
|
|
package DBD::SQLite::VirtualTable::T::Cursor;
|
|
use strict;
|
|
use warnings;
|
|
use base 'DBD::SQLite::VirtualTable::Cursor';
|
|
use YAML;
|
|
|
|
sub NEW {
|
|
my $class = shift;
|
|
|
|
my $self = $class->DBD::SQLite::VirtualTable::Cursor::NEW(@_);
|
|
$self->{row_count} = 5;
|
|
|
|
return $self;
|
|
}
|
|
|
|
sub FILTER {
|
|
my ($self, $idxNum, $idxStr, @values) = @_;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
sub EOF {
|
|
my $self = shift;
|
|
|
|
return !$self->{row_count};
|
|
}
|
|
|
|
sub NEXT {
|
|
my $self = shift;
|
|
|
|
$self->{row_count}--;
|
|
}
|
|
|
|
sub COLUMN {
|
|
my ($self, $idxCol) = @_;
|
|
|
|
return $idxCol;
|
|
}
|
|
|
|
sub ROWID {
|
|
my ($self) = @_;
|
|
|
|
return $self->{row_count};
|
|
}
|
|
|
|
|
|
1;
|
|
|
|
|
|
|