1
0
Fork 0
mirror of https://github.com/DBD-SQLite/DBD-SQLite synced 2025-06-07 14:19:10 -04:00
DBD-SQLite-SQLcipher/lib/DBD/SQLite/VirtualTable.pm

266 lines
4.2 KiB
Perl

# TODO : fix bug with column name / type
package DBD::SQLite::VirtualTable;
use strict;
use warnings;
use Scalar::Util qw/weaken/;
use List::MoreUtils qw/part/;
use YAML::XS;
use Data::Dumper;
our $VERSION = '0.01';
our @ISA;
sub DESTROY_MODULE {
my $class = shift;
}
sub CREATE {
my $class = shift;
return $class->NEW(@_);
}
sub CONNECT {
my $class = shift;
return $class->NEW(@_);
}
sub NEW { # called when instanciating a virtual table
my ($class, $dbh_ref, $module_name, $db_name, $vtab_name, @args) = @_;
my @columns;
my %options;
# args containing '=' are options; others are column declarations
foreach my $arg (@args) {
if ($arg =~ /^([^=\s]+)\s*=\s*(.*)/) {
my ($key, $val) = ($1, $2);
$val =~ s/^"(.*)"$/$1/;
$options{$key} = $val;
}
else {
push @columns, $arg;
}
}
# build $self and initialize
my $self = {
dbh_ref => $dbh_ref,
module_name => $module_name,
db_name => $db_name,
vtab_name => $vtab_name,
columns => \@columns,
options => \%options,
};
weaken $self->{dbh_ref};
bless $self, $class;
$self->initialize();
return $self;
}
sub dbh {
my $self = shift;
return ${$self->{dbh_ref}};
}
sub initialize {
my $self = shift;
}
sub DROP {
my $self = shift;
}
sub DISCONNECT {
my $self = shift;
}
sub VTAB_TO_DECLARE {
my $self = shift;
local $" = ", ";
my $sql = "CREATE TABLE $self->{vtab_name}(@{$self->{columns}})";
return $sql;
}
sub BEST_INDEX {
my ($self, $constraints, $order_by) = @_;
# print STDERR Dump [BEST_INDEX => {
# where => $constraints,
# order => $order_by,
# }];
my $ix = 0;
foreach my $constraint (@$constraints) {
# TMP HACK -- should put real values instead
$constraint->{argvIndex} = $ix++;
$constraint->{omit} = 0;
}
# TMP HACK -- should put real values instead
my $outputs = {
idxNum => 1,
idxStr => "foobar",
orderByConsumed => 0,
estimatedCost => 1.0,
estimatedRows => undef,
};
return $outputs;
}
sub OPEN {
my $self = shift;
my $class = ref $self;
my $cursor_class = $class . "::Cursor";
return $cursor_class->NEW($self, @_);
}
sub _SQLITE_UPDATE {
my ($self, $old_rowid, $new_rowid, @values) = @_;
if (! defined $old_rowid) {
return $self->INSERT($new_rowid, @values);
}
elsif (!@values) {
return $self->DELETE($old_rowid);
}
else {
return $self->UPDATE($old_rowid, $new_rowid, @values);
}
}
sub INSERT {
my ($self, $new_rowid, @values) = @_;
die "INSERT() should be redefined in subclass";
}
sub DELETE {
my ($self, $old_rowid) = @_;
die "DELETE() should be redefined in subclass";
}
sub UPDATE {
my ($self, $old_rowid, $new_rowid, @values) = @_;
die "UPDATE() should be redefined in subclass";
}
sub BEGIN_TRANSACTION {return 0}
sub SYNC_TRANSACTION {return 0}
sub COMMIT_TRANSACTION {return 0}
sub ROLLBACK_TRANSACTION {return 0}
sub SAVEPOINT {return 0}
sub RELEASE {return 0}
sub ROLLBACK_TO {return 0}
sub DESTROY {
my $self = shift;
}
package DBD::SQLite::VirtualTable::Cursor;
use strict;
use warnings;
sub NEW {
my ($class, $vtable, @args) = @_;
my $self = {vtable => $vtable,
args => \@args};
bless $self, $class;
}
sub FILTER {
my ($self, $idxNum, $idxStr, @values) = @_;
return;
}
sub EOF {
my ($self) = @_;
# stupid implementation, to be redefined in subclasses
return 1;
}
sub NEXT {
my ($self) = @_;
}
sub COLUMN {
my ($self, $idxCol) = @_;
}
sub ROWID {
my ($self) = @_;
# stupid implementation, to be redefined in subclasses
return 1;
}
sub CLOSE {
my ($self) = @_;
}
1;
__END__
=head1 NAME
DBD::SQLite::VirtualTable -- Abstract parent class for implementing virtual tables
=head1 SYNOPSIS
package My::Virtual::Table;
use parent 'DBD::SQLite::VirtualTable';
sub ...
=head1 DESCRIPTION
TODO
=head1 METHODS
TODO
=head1 COPYRIGHT AND LICENSE
Copyright Laurent Dami, 2014.
Parts of the code are borrowed from L<SQLite::VirtualTable>,
copyright (C) 2006, 2009 by Qindel Formacion y Servicios, S. L.
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.
=cut