1=head1 NAME 2 3RDF::Trine::Store::DBI::SQLite - SQLite subclass of DBI store 4 5=head1 VERSION 6 7This document describes RDF::Trine::Store::DBI::SQLite version 1.019 8 9=head1 SYNOPSIS 10 11 use RDF::Trine::Store::DBI::SQLite; 12 my $store = RDF::Trine::Store->new({ 13 storetype => 'DBI', 14 name => 'test', 15 dsn => "dbi:SQLite:dbname=test.db", 16 username => '', 17 password => '' 18 }); 19 20 21=head1 CHANGES IN VERSION 1.014 22 23The schema used to encode RDF data in SQLite changed in RDF::Trine version 241.014 to fix a bug that was causing data loss. This change is not backwards 25compatible, and is not compatible with the shared schema used by the other 26database backends supported by RDF::Trine (PostgreSQL and MySQL). 27 28To exchange data between SQLite and other databases, the data will require 29export to an RDF serialization and re-import to the new database. 30 31=cut 32 33package RDF::Trine::Store::DBI::SQLite; 34 35use strict; 36use warnings; 37no warnings 'redefine'; 38use base qw(RDF::Trine::Store::DBI); 39 40 41use Scalar::Util qw(blessed reftype refaddr); 42use Encode; 43use Digest::MD5 ('md5'); 44use Math::BigInt; 45 46our $VERSION; 47BEGIN { 48 $VERSION = "1.019"; 49 my $class = __PACKAGE__; 50 $RDF::Trine::Store::STORE_CLASSES{ $class } = $VERSION; 51} 52 53 54sub _config_meta { 55 return { 56 required_keys => [qw(dsn username password name)], 57 fields => { 58 name => { description => 'Model Name', type => 'string' }, 59 dsn => { description => 'DSN', type => 'string', template => 'DBI:SQLite:dbname=[%filename%]' }, 60 filename => { description => 'SQLite Database Filename', type => 'filename' }, 61 username => { description => 'Username', type => 'string', value => '' }, 62 password => { description => 'Password', type => 'password', value => '' }, 63 driver => { description => 'Driver', type => 'string', value => 'SQLite' }, 64 }, 65 } 66} 67 68=head1 METHODS 69 70Beyond the methods documented below, this class inherits methods from the 71L<RDF::Trine::Store::DBI> class. 72 73=over 4 74 75=cut 76 77=item C<< new_with_config ( \%config ) >> 78 79Returns a new RDF::Trine::Store object based on the supplied configuration hashref. 80 81=cut 82 83sub new_with_config { 84 my $proto = shift; 85 my $config = shift; 86 $config->{storetype} = 'DBI::SQLite'; 87 my $exists = (-r $config->{filename}); 88 my $self = $proto->SUPER::new_with_config( $config ); 89 unless ($exists) { 90 $self->init(); 91 } 92 return $self; 93} 94 95# SQLite only supports 64-bit SIGNED integers, so this hash function masks out 96# the high-bit on hash values (unlike the superclass which produces full 64-bit 97# integers) 98sub _mysql_hash { 99 if (ref($_[0])) { 100 my $self = shift; 101 } 102 Carp::confess unless scalar(@_); 103 my $data = encode('utf8', shift); 104 my @data = unpack('C*', md5( $data )); 105 my $sum = Math::BigInt->new('0'); 106 # CHANGE: 7 -> 6, Smaller numbers for Sqlite which does not support real 64-bit :( 107 foreach my $count (0 .. 7) { 108 my $data = Math::BigInt->new( $data[ $count ] ); #shift(@data); 109 my $part = $data << (8 * $count); 110# warn "+ $part\n"; 111 $sum += $part; 112 } 113# warn "= $sum\n"; 114 $sum = $sum->band(Math::BigInt->new('0x7fff_ffff_ffff_ffff')); 115 $sum =~ s/\D//; # get rid of the extraneous '+' that pops up under perl 5.6 116 return $sum; 117} 118 119=item C<< init >> 120 121Creates the necessary tables in the underlying database. 122 123=cut 124 125sub init { 126 my $self = shift; 127 my $dbh = $self->dbh; 128 my $name = $self->model_name; 129 $self->SUPER::init(); 130 my $id = $self->_mysql_hash( $name ); 131 132 my $table = "Statements${id}"; 133 local($dbh->{AutoCommit}) = 0; 134 unless ($self->_table_exists($table)) { 135 $dbh->do( "CREATE INDEX idx_${name}_spog ON Statements${id} (Subject,Predicate,Object,Context);" ) || do { $dbh->rollback; return }; 136 $dbh->do( "CREATE INDEX idx_${name}_pogs ON Statements${id} (Predicate,Object,Context,Subject);" ) || do { $dbh->rollback; return }; 137 $dbh->do( "CREATE INDEX idx_${name}_opcs ON Statements${id} (Object,Predicate,Context,Subject);" ) || do { $dbh->rollback; return }; 138 $dbh->do( "CREATE INDEX idx_${name}_cpos ON Statements${id} (Context,Predicate,Object,Subject);" ) || do { $dbh->rollback; return }; 139 $dbh->commit; 140 } 141} 142 143 1441; # Magic true value required at end of module 145__END__ 146 147=back 148 149=head1 BUGS 150 151Please report any bugs or feature requests to through the GitHub web interface 152at L<https://github.com/kasei/perlrdf/issues>. 153 154=head1 AUTHOR 155 156Gregory Todd Williams C<< <gwilliams@cpan.org> >> 157 158=head1 COPYRIGHT 159 160Copyright (c) 2006-2012 Gregory Todd Williams. This 161program is free software; you can redistribute it and/or modify it under 162the same terms as Perl itself. 163 164=cut 165