package DBIx::Class::Schema::KiokuDB;
BEGIN {
$DBIx::Class::Schema::KiokuDB::AUTHORITY = 'cpan:NUFFIN';
}
BEGIN {
$DBIx::Class::Schema::KiokuDB::VERSION = '1.12';
}
use strict;
use warnings;
use DBIx::Class::KiokuDB::EntryProxy;
use DBIx::Class::ResultSource::Table;
use Scalar::Util qw(weaken);
use namespace::clean;
use base qw(Class::Accessor::Grouped);
__PACKAGE__->mk_group_accessors( inherited => "kiokudb_entries_source_name" );
sub kiokudb_handle { shift->{kiokudb_handle} } # FIXME
sub _kiokudb_handle {
my ( $self, $handle ) = @_;
$self->{kiokudb_handle} = $handle;
weaken($self->{kiokudb_handle});
return $handle;
}
sub define_kiokudb_schema {
my ( $self, @args ) = @_;
my %args = (
schema => $self,
entries_table => "entries",
gin_index_table => "gin_index",
result_class => "DBIx::Class::KiokuDB::EntryProxy",
gin_index => 1,
@args,
);
my $entries_source_name = $args{entries_source} ||= $args{entries_table};
my $gin_index_source_name = $args{gin_index_source} ||= $args{gin_index_table};
my $entries = $self->define_kiokudb_entries_resultsource(%args);
my $gin_index = $self->define_kiokudb_gin_index_resultsource(%args) if $args{gin_index};
my $schema = $args{schema};
$schema->register_source( $entries_source_name => $entries );
$schema->register_source( $gin_index_source_name => $gin_index );
$schema->kiokudb_entries_source_name($entries_source_name)
unless $schema->kiokudb_entries_source_name;
}
sub define_kiokudb_entries_resultsource {
my ( $self, %args ) = @_;
my $entries = DBIx::Class::ResultSource::Table->new({ name => $args{entries_table} });
$entries->add_columns(
id => { data_type => "varchar" },
data => { data_type => "blob", is_nullable => 0 }, # FIXME longblob for mysql
class => { data_type => "varchar", is_nullable => 1 },
root => { data_type => "boolean", is_nullable => 0 },
tied => { data_type => "char", size => 1, is_nullable => 1 },
@{ $args{extra_entries_columns} || [] },
);
$entries->set_primary_key("id");
$entries->sqlt_deploy_callback(sub {
my ($source, $sqlt_table) = @_;
$sqlt_table->extra->{mysql_table_type} = "InnoDB";
if ( $source->schema->storage->sqlt_type eq 'MySQL' ) {
$sqlt_table->get_field('data')->data_type('longblob');
}
});
$entries->result_class($args{result_class});
return $entries;
}
sub define_kiokudb_gin_index_resultsource {
my ( $self, %args ) = @_;
my $gin_index = DBIx::Class::ResultSource::Table->new({ name => $args{gin_index_table} });
$gin_index->add_columns(
id => { data_type => "varchar", is_foreign_key => 1 },
value => { data_type => "varchar" },
);
$gin_index->add_relationship('entry_ids', $args{entries_source}, { 'foreign.id' => 'me.id' });
$gin_index->sqlt_deploy_callback(sub {
my ($source, $sqlt_table) = @_;
$sqlt_table->extra->{mysql_table_type} = "InnoDB";
$sqlt_table->add_index( name => 'gin_index_ids', fields => ['id'] )
or die $sqlt_table->error;
$sqlt_table->add_index( name => 'gin_index_values', fields => ['value'] )
or die $sqlt_table->error;
});
return $gin_index;
}
# ex: set sw=4 et:
__PACKAGE__
__END__
=pod
=head1 NAME
DBIx::Class::Schema::KiokuDB - Hybrid L<KiokuDB>/L<DBIx::Class::Schema> schema
support.
=head1 SYNOPSIS
Load this component into the schema:
package MyApp::DB;
use base qw(DBIx::Class::Schema);
__PACKAGE__->load_components(qw(Schema::KiokuDB));
__PAKCAGE__->load_namespaces;
Then load the L<DBIx::Class::KiokuDB> component into every table that wants to
refer to arbitrary KiokuDB objects:
package MyApp::DB::Result::Album;
use base qw(DBIx::Class);
__PACKAGE__>load_components(qw(Core KiokuDB));
__PACKAGE__->table('album');
__PACKAGE__->add_columns(
id => { data_type => "integer" },
title => { data_type => "varchar" },
# the foreign key for the KiokuDB object:
metadata => { data_type => "varchar" },
);
__PACKAGE__->set_primary_key('id');
# enable a KiokuDB rel on the column:
__PACKAGE__->kiokudb_column('metadata');
Connect to the DSN:
my $dir = KiokuDB->connect(
'dbi:SQLite:dbname=:memory:',
schema_proto => "MyApp::DB",
create => 1,
);
# get the connect DBIC schema instance
my $schema = $dir->backend->schema;
Then you can freely refer to KiokuDB objects from your C<Album> class:
$dir->txn_do(scope => 1, body => sub {
$schema->resultset("Album")->create({
title => "Blah blah",
metadata => $any_object,
});
});
=head1 DESCRIPTION
This class provides the schema definition support code required for integrating
an arbitrary L<DBIx::Class::Schema> with L<KiokuDB::Backend::DBI>.
=head1 USAGE AND LIMITATIONS
L<KiokuDB> managed objects may hold references to row objects, resultsets
(treated as saved searches, or results or cursor state is saved), result source
handles, and the schema.
Foreign L<DBIx::Class> objects, that is ones that originated from a schema that
isn't the underlying schema are currently not supported, but this limitation
may be lifted in the future.
All DBIC operations which may implicitly cause a lookup of a L<KIokuDB> managed
object require live object scope management, just as normal.
It is reccomended to use L<KiokuDB/txn_do> because that will invoke the
appropriate transaction hooks on both layers, as opposed to just in
L<DBIx::Class>.
=head1 SEE ALSO
L<DBIx::Class::KiokuDB>, L<KiokuDB::Backend::DBI>.