OOPS

 view release on metacpan or  search on metacpan

lib/OOPS/sqlite_v3.pm  view on Meta::CPAN


#
# This handles DBD::SQLite 1.x which uses SQLite 3.x
#

package OOPS::sqlite_v3;

@ISA = qw(OOPS::DBO Exporter);
@EXPORT = qw(
	tabledefs
	table_list
	db_initial_values
	initial_query_set
	$big_blob_size
	$retry_count
);

use strict;
use warnings;
use Carp qw(confess);

our $big_blob_size = 900*1024;
our $enable_fd_leak_workaround = 500;
our $invocations = 0;

sub tmode {}

sub lock_object {}

sub deadlock_rx
{
	return (
		qr/database is locked(?:\(\d+\) at dbdimp\.c line )?/,
		qr/unable to open database file\(\d+\) at dbdimp\.c line/,
	);
}

sub nodata_rx
{
	return qr/no such table: \S+object(?:\(1\) at dbdimp\.c)?/;
}

sub initialize
{
	my $dbo = shift;

	my $dbh = $dbo->{dbh};
	$dbh->{sqlite_handle_binary_nulls} = 1;


	# 
	# SQLite will sometimes error out with a locked database
	# error when it should have just waited instead.  Oh well.
	#
	# http://rt.cpan.org/Ticket/Display.html?id=11680
	#
	$dbh->func(10_000, 'busy_timeout');

	my $sync = $dbo->{default_synchronous} || $ENV{OOPS_SYNC};
	if ($sync) {
		my $sm = $dbh->prepare("PRAGMA default_synchronous = $sync;") || confess $dbh->errstr;
		$sm->execute || confess $sm->errstr;
	}

	$dbo->{sqlite_version} = 3;

	return unless $invocations++ >= $enable_fd_leak_workaround;
	return unless $enable_fd_leak_workaround;
	return undef unless -d "/proc/$$/fd";
	return undef unless $dbo->{database} =~ /dbname=(\S+)/;

	my $dbfile = $1;
	my ($dev, $ino) = (stat($dbfile))[0,1];

	my @r;
	local(*D);
	opendir(D, "/proc/$$/fd") || return undef;
	@r = sort { $a <=> $b } grep($_ ne "." && $_ ne "..", readdir(D));
	closedir(D);

	require POSIX;

	pop(@r); pop(@r); pop(@r); pop(@r);

	#
	# The very-recently created sqlite open file is a
	# pipe rather than a link so this won't accidently
	# close it.
	#
	for my $r (@r) {
		next unless $r > $enable_fd_leak_workaround;
		my $f = readlink("/proc/$$/fd/$r");
		next unless $f;
		unless ($f eq $dbfile) {
			my ($fddev, $fdino) = (stat($f))[0,1];
			next unless $fddev == $dev;
			next unless $fdino == $ino;
		}
		warn "Closing fd probably leaked by SQLite ($r);";
		POSIX::close($r);
	}
}

# subroutine
sub tabledefs
{
	my $x = <<'END';

	CREATE TABLE TP_object (
		id		INTEGER PRIMARY KEY,
		loadgroup	BIGINT, 
		class 		VARCHAR(255), 		# ref($object)
		otype		CHAR(1),		# 'S'calar/ref, 'A'rray, 'H'ash
		virtual		CHAR(1),		# load virutal ('V' or '0')
		reftarg		CHAR(1),		# reference target ('T' or '0')
		rfe		CHAR(1),		# reserved for future expansion
		alen		INT,			# array length



( run in 0.578 second using v1.01-cache-2.11-cpan-39bf76dae61 )