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