Skip Menu |

This queue is for tickets about the ORLite CPAN distribution.

Report information
The Basics
Id: 76893
Status: new
Priority: 0/
Queue: ORLite

People
Owner: Nobody in particular
Requestors: PSCUST [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: Wishlist
Broken in: 1.96
Fixed in: (no value)



Subject: New feature: PRAGMA foreign_keys = ON
SQLite has started supporting enforcing of foreign key constraints since 3.6.19, but this enforcement is disabled by default in order not to break legacy code. To enforce referential integrity of foreign key constraints, the pragma foreign_keys has to be enabled at the start of each new connection. The attached patch adds a new foreign_keys option. When this option is true, the SQL statement "PRAGMA foreign_keys = ON" is run immediately after starting each new connection. I've also added a new test script to test the new option and described the option in the POD. Please be free to include the patch verbatin or modified in a next release of ORLite. Thanks. Best regards, Paulo Custodio
Subject: xx_foreign_keys_on.sql
Download xx_foreign_keys_on.sql
application/octet-stream 465b

Message body not shown because it is not plain text.

Subject: ORLite-1.96-fk_patch.txt
diff -c -w -r ORLite-1.96/lib/ORLite.pm ORLite-1.96-fk/lib/ORLite.pm *** ORLite-1.96/lib/ORLite.pm Mon Feb 27 01:50:26 2012 --- ORLite-1.96-fk/lib/ORLite.pm Mon Apr 30 10:53:20 2012 *************** *** 56,61 **** --- 56,62 ---- tables => 1, views => 0, unicode => 0, + foreign_keys => 0, ); if ( defined Params::Util::_STRING($_[1]) ) { # Support the short form "use ORLite 'db.sqlite'" *************** *** 161,166 **** --- 162,170 ---- my $readonly = $params{readonly} ? "\n\t\tReadOnly => 1," : ''; my $unicode = $params{unicode} ? "\n\t\tsqlite_unicode => 1," : ''; my $version = $unicode ? '5.008005' : '5.006'; + my $pragma_foreign_keys = + $params{foreign_keys} ? + '$dbh->do("PRAGMA foreign_keys = ON");' : ''; # Generate the support package code my $code = <<"END_PERL"; *************** *** 185,194 **** } sub connect { ! DBI->connect( \$_[0]->dsn, undef, undef, { PrintError => 0, RaiseError => 1,$readonly$unicode } ); } sub connected { --- 189,200 ---- } sub connect { ! my \$dbh = DBI->connect( \$_[0]->dsn, undef, undef, { PrintError => 0, RaiseError => 1,$readonly$unicode } ); + $pragma_foreign_keys + return \$dbh; } sub connected { *************** *** 894,899 **** --- 900,906 ---- tables => [ 'table1', 'table2' ], cleanup => 'VACUUM', prune => 1, + foreign_keys => 1, }; =head1 DESCRIPTION *************** *** 1171,1176 **** --- 1178,1194 ---- At the moment, it just enables the C<sqlite_unicode> option while connecting to your database. There'll be more in the future. + =head2 foreign_keys + + SQLite has started supporting enforcing of foreign key constraints since 3.6.19, + but this enforcement is disabled by default in order not to break legacy code. + + To enforce referential integrity of foreign key constraints, + the pragma foreign_keys has to be enabled at the start of each new connection. + + When this option is true, the SQL statement "PRAGMA foreign_keys = ON" is + run immediately after starting each new connection. + =head1 ROOT PACKAGE METHODS All ORLite root packages receive an identical set of methods for Only in ORLite-1.96-fk/t: xx_foreign_keys_on.sql Only in ORLite-1.96-fk/t: xx_foreign_keys_on.t
Subject: xx_foreign_keys_on.t
#!/usr/bin/perl # Tests relating to foreign keys. BEGIN { $| = 1; $^W = 1; } use Test::More tests => 27; use File::Spec::Functions ':ALL'; use t::lib::Test; ##################################################################### # Set up for testing # Connect my $file = test_db(); my $dbh = create_ok( file => catfile(qw{ t xx_foreign_keys_on.sql }), connect => [ "dbi:SQLite:$file" ], ); # Create the test package ##################################################################### # PRAGMA foreign_keys = ON; eval <<"END_PERL"; die $@ if $@; package Foo::Bar; use strict; use ORLite { file => '$file', foreign_keys => 1, }; 1; END_PERL ##################################################################### # Run the tests my @album = Foo::Bar::Album->select; is( scalar(@album), 1, 'Got one album object' ); isa_ok( $album[0], 'Foo::Bar::Album' ); is( $album[0]->album_id, 1, 'Got album.album_id' ); is( $album[0]->name, 'Album 1', 'Got album.name' ); my @track = Foo::Bar::Track->select; is( scalar(@track), 1, 'Got one track object' ); isa_ok( $track[0], 'Foo::Bar::Track' ); is( $track[0]->track_id, 1, 'Got track.track_id' ); is( $track[0]->name, 'Track 1', 'Got track.name' ); isa_ok( $track[0]->album, 'Foo::Bar::Album' ); is( $track[0]->album->album_id, 1, 'Got track.album' ); # insert must fail eval { Foo::Bar::Track->create( name => 'Track 2', album => 2, ); }; like( $@, qr/foreign key constraint failed/, 'insert with fk violation failed' ); @track = Foo::Bar::Track->select; is( scalar(@track), 1, 'Got one track object' ); ##################################################################### # PRAGMA foreign_keys = OFF; eval <<"END_PERL"; die $@ if $@; package Foo::Bar2; use strict; use ORLite { file => '$file', }; 1; END_PERL ##################################################################### # Run the tests @album = Foo::Bar2::Album->select; is( scalar(@album), 1, 'Got one album object' ); isa_ok( $album[0], 'Foo::Bar2::Album' ); is( $album[0]->album_id, 1, 'Got album.album_id' ); is( $album[0]->name, 'Album 1', 'Got album.name' ); @track = Foo::Bar2::Track->select; is( scalar(@track), 1, 'Got one track object' ); isa_ok( $track[0], 'Foo::Bar2::Track' ); is( $track[0]->track_id, 1, 'Got track.track_id' ); is( $track[0]->name, 'Track 1', 'Got track.name' ); isa_ok( $track[0]->album, 'Foo::Bar2::Album' ); is( $track[0]->album->album_id, 1, 'Got track.album' ); # insert succeeds my $track = Foo::Bar2::Track->create( name => 'Track 2', album => 2, ); isa_ok( $track, 'Foo::Bar2::Track' ); is( $track->name, 'Track 2', 'Got track.name' ); is( $track->album, undef, 'no linked album' ); @track = Foo::Bar2::Track->select; is( scalar(@track), 2, 'Got two track objects' );