'Data::Page' => 0,
'DBI' => 0,
'UNIVERSAL::require' => 0,
- 'NEXT' => 0,
'Scalar::Util' => 0,
'SQL::Abstract' => 1.20,
'SQL::Abstract::Limit' => 0.101,
'DBD::SQLite' => 1.08,
+ 'Class::C3' => 0.07,
'Tie::IxHash' => 0,
- 'Storable' => 0,
'Module::Find' => 0,
+ 'Storable' => 0,
+ # Following for CDBICompat only
+ 'Class::Trigger' => 0,
+ 'DBIx::ContextualFetch' => 0,
+ 'Class::C3' => 0.05,
},
- reommends => {
+ recommends => {
'Data::UUID' => 0,
},
create_makefile_pl => 'passthrough',
Revision history for DBIx::Class
+ - Moved get_simple and set_simple into AccessorGroup
+ - Made 'new' die if given invalid columns
+ - Added has_column and column_info to Table.pm
+ - Refactored away from direct use of _columns and _primaries
+
+0.03004
+ - Added an || '' to the CDBICompat stringify to avoid null warnings
- Updated name section for manual pods
0.03003 2005-11-03 17:00:00
MANIFEST This list of files
META.yml
README
-script/nextalyzer.pl
t/02pod.t
t/03podcoverage.t
t/19quotes.t
+++ /dev/null
----
-name: DBIx-Class
-version: 0.03003
-author:
- - Matt S. Trout <mst@shadowcatsystems.co.uk>
-abstract: Extensible and flexible object <-> relational mapper.
-license: perl
-requires:
- DBD::SQLite: 1.08
- DBI: 0
- Data::Page: 0
- Module::Find: 0
- NEXT: 0
- SQL::Abstract: 1.2
- SQL::Abstract::Limit: 0.101
- Scalar::Util: 0
- Storable: 0
- Tie::IxHash: 0
- UNIVERSAL::require: 0
-provides:
- DBIC::SQL::Abstract:
- file: lib/DBIx/Class/Storage/DBI.pm
- DBIx::Class:
- file: lib/DBIx/Class.pm
- version: 0.03003
- DBIx::Class::AccessorGroup:
- file: lib/DBIx/Class/AccessorGroup.pm
- DBIx::Class::CDBICompat:
- file: lib/DBIx/Class/CDBICompat.pm
- DBIx::Class::CDBICompat::AccessorMapping:
- file: lib/DBIx/Class/CDBICompat/AccessorMapping.pm
- DBIx::Class::CDBICompat::AttributeAPI:
- file: lib/DBIx/Class/CDBICompat/AttributeAPI.pm
- DBIx::Class::CDBICompat::AutoUpdate:
- file: lib/DBIx/Class/CDBICompat/AutoUpdate.pm
- DBIx::Class::CDBICompat::ColumnCase:
- file: lib/DBIx/Class/CDBICompat/ColumnCase.pm
- DBIx::Class::CDBICompat::ColumnGroups:
- file: lib/DBIx/Class/CDBICompat/ColumnGroups.pm
- DBIx::Class::CDBICompat::ColumnGroups::GrouperShim:
- file: lib/DBIx/Class/CDBICompat/ColumnGroups.pm
- DBIx::Class::CDBICompat::Constraints:
- file: lib/DBIx/Class/CDBICompat/Constraints.pm
- DBIx::Class::CDBICompat::Constructor:
- file: lib/DBIx/Class/CDBICompat/Constructor.pm
- DBIx::Class::CDBICompat::DestroyWarning:
- file: lib/DBIx/Class/CDBICompat/DestroyWarning.pm
- DBIx::Class::CDBICompat::GetSet:
- file: lib/DBIx/Class/CDBICompat/GetSet.pm
- DBIx::Class::CDBICompat::HasA:
- file: lib/DBIx/Class/CDBICompat/HasA.pm
- DBIx::Class::CDBICompat::HasMany:
- file: lib/DBIx/Class/CDBICompat/HasMany.pm
- DBIx::Class::CDBICompat::ImaDBI:
- file: lib/DBIx/Class/CDBICompat/ImaDBI.pm
- DBIx::Class::CDBICompat::LazyLoading:
- file: lib/DBIx/Class/CDBICompat/LazyLoading.pm
- DBIx::Class::CDBICompat::LiveObjectIndex:
- file: lib/DBIx/Class/CDBICompat/LiveObjectIndex.pm
- DBIx::Class::CDBICompat::MightHave:
- file: lib/DBIx/Class/CDBICompat/MightHave.pm
- DBIx::Class::CDBICompat::ObjIndexStubs:
- file: lib/DBIx/Class/CDBICompat/ObjIndexStubs.pm
- DBIx::Class::CDBICompat::Pager:
- file: lib/DBIx/Class/CDBICompat/Pager.pm
- DBIx::Class::CDBICompat::ReadOnly:
- file: lib/DBIx/Class/CDBICompat/ReadOnly.pm
- DBIx::Class::CDBICompat::Retrieve:
- file: lib/DBIx/Class/CDBICompat/Retrieve.pm
- DBIx::Class::CDBICompat::Stringify:
- file: lib/DBIx/Class/CDBICompat/Stringify.pm
- DBIx::Class::CDBICompat::TempColumns:
- file: lib/DBIx/Class/CDBICompat/TempColumns.pm
- DBIx::Class::CDBICompat::Triggers:
- file: lib/DBIx/Class/CDBICompat/Triggers.pm
- DBIx::Class::ClassResolver::PassThrough:
- file: lib/DBIx/Class/ClassResolver/PassThrough.pm
- DBIx::Class::Componentised:
- file: lib/DBIx/Class/Componentised.pm
- DBIx::Class::Core:
- file: lib/DBIx/Class/Core.pm
- DBIx::Class::Cursor:
- file: lib/DBIx/Class/Cursor.pm
- DBIx::Class::DB:
- file: lib/DBIx/Class/DB.pm
- DBIx::Class::Exception:
- file: lib/DBIx/Class/Exception.pm
- DBIx::Class::Exception::Base:
- file: lib/DBIx/Class/Exception.pm
- DBIx::Class::InflateColumn:
- file: lib/DBIx/Class/InflateColumn.pm
- DBIx::Class::ObjectCache:
- file: lib/DBIx/Class/ObjectCache.pm
- DBIx::Class::PK:
- file: lib/DBIx/Class/PK.pm
- DBIx::Class::PK::Auto:
- file: lib/DBIx/Class/PK/Auto.pm
- DBIx::Class::PK::Auto::MSSQL:
- file: lib/DBIx/Class/PK/Auto/MSSQL.pm
- DBIx::Class::PK::Auto::MySQL:
- file: lib/DBIx/Class/PK/Auto/MySQL.pm
- DBIx::Class::PK::Auto::Oracle:
- file: lib/DBIx/Class/PK/Auto/Oracle.pm
- DBIx::Class::PK::Auto::Pg:
- file: lib/DBIx/Class/PK/Auto/Pg.pm
- DBIx::Class::PK::Auto::SQLite:
- file: lib/DBIx/Class/PK/Auto/SQLite.pm
- DBIx::Class::Relationship:
- file: lib/DBIx/Class/Relationship.pm
- DBIx::Class::Relationship::Accessor:
- file: lib/DBIx/Class/Relationship/Accessor.pm
- DBIx::Class::Relationship::Base:
- file: lib/DBIx/Class/Relationship/Base.pm
- DBIx::Class::Relationship::BelongsTo:
- file: lib/DBIx/Class/Relationship/BelongsTo.pm
- DBIx::Class::Relationship::CascadeActions:
- file: lib/DBIx/Class/Relationship/CascadeActions.pm
- DBIx::Class::Relationship::HasMany:
- file: lib/DBIx/Class/Relationship/HasMany.pm
- DBIx::Class::Relationship::HasOne:
- file: lib/DBIx/Class/Relationship/HasOne.pm
- DBIx::Class::Relationship::ProxyMethods:
- file: lib/DBIx/Class/Relationship/ProxyMethods.pm
- DBIx::Class::ResultSet:
- file: lib/DBIx/Class/ResultSet.pm
- DBIx::Class::Row:
- file: lib/DBIx/Class/Row.pm
- DBIx::Class::Schema:
- file: lib/DBIx/Class/Schema.pm
- DBIx::Class::Storage::DBI:
- file: lib/DBIx/Class/Storage/DBI.pm
- DBIx::Class::Storage::DBI::Cursor:
- file: lib/DBIx/Class/Storage/DBI/Cursor.pm
- DBIx::Class::Table:
- file: lib/DBIx/Class/Table.pm
- DBIx::Class::Test::SQLite:
- file: lib/DBIx/Class/Test/SQLite.pm
- DBIx::Class::UUIDColumns:
- file: lib/DBIx/Class/UUIDColumns.pm
- DBIx::ContextualFetch::st:
- file: lib/DBIx/Class/CDBICompat/ImaDBI.pm
-generated_by: Module::Build version 0.2611
and making it possible to support some new features like self-joins,
distinct, group bys and more.
- It's currently considered EXPERIMENTAL - bring this near a production
- database at your own risk! The API is *not* fixed yet, although most of
- the primitives should be good for the future and any API changes will be
- posted to the mailing list before they're committed.
+ This project is still at an early stage so the maintainers don't make
+ any absolute promise that full backwards-compatibility will be
+ supported; however if we can without compromising the improvements we're
+ trying to make, we will, and any non-compatible changes will merit a
+ full justification on the mailing list and a CPAN developer release for
+ people to test against.
The community can be found via -
use warnings;
use vars qw($VERSION);
-use base qw/DBIx::Class::Componentised/;
+use base qw/DBIx::Class::Componentised Class::Data::Inheritable/;
-$VERSION = '0.03003';
+$VERSION = '0.04';
1;
insides, and making it possible to support some new features like
self-joins, distinct, group bys and more.
-It's currently considered EXPERIMENTAL - bring this near a production
-database at your own risk! The API is *not* fixed yet, although most of
-the primitives should be good for the future and any API changes will be
-posted to the mailing list before they're committed.
+This project is still at an early stage so the maintainers don't make
+any absolute promise that full backwards-compatibility will be supported;
+however if we can without compromising the improvements we're trying to
+make, we will, and any non-compatible changes will merit a full justification
+on the mailing list and a CPAN developer release for people to test against.
The community can be found via -
use strict;
use warnings;
-use NEXT;
-
=head1 NAME
DBIx::Class::AccessorGroup - Lets you build groups of accessors
};
}
+sub get_simple {
+ my ($self, $get) = @_;
+ return $self->{$get};
+}
+
+sub set_simple {
+ my ($self, $set, $val) = @_;
+ return $self->{$set} = $val;
+}
+
1;
=back
use strict;
use warnings;
-use base qw/DBIx::Class/;
+use base qw/DBIx::Class::Core DBIx::Class::DB/;
__PACKAGE__->load_own_components(qw/
Constraints
Constructor
AccessorMapping
ColumnCase
- HasMany
HasA
+ HasMany
MightHave
LazyLoading
AutoUpdate
use strict;
use warnings;
-use NEXT;
-
sub mk_group_accessors {
my ($class, $group, @cols) = @_;
unless ($class->can('accessor_name') || $class->can('mutator_name')) {
- return $class->NEXT::ACTUAL::mk_group_accessors($group => @cols);
+ return $class->next::method($group => @cols);
}
foreach my $col (@cols) {
my $ro_meth = ($class->can('accessor_name')
: $col);
#warn "$col $ro_meth $wo_meth";
if ($ro_meth eq $wo_meth) {
- $class->NEXT::ACTUAL::mk_group_accessors($group => [ $ro_meth => $col ]);
+ $class->next::method($group => [ $ro_meth => $col ]);
} else {
$class->mk_group_ro_accessors($group => [ $ro_meth => $col ]);
$class->mk_group_wo_accessors($group => [ $wo_meth => $col ]);
}
}
-sub create {
+sub new {
my ($class, $attrs, @rest) = @_;
$class->throw( "create needs a hashref" ) unless ref $attrs eq 'HASH';
- $attrs = { %$attrs };
- my %att;
- foreach my $col (keys %{ $class->_columns }) {
+ foreach my $col ($class->columns) {
if ($class->can('accessor_name')) {
my $acc = $class->accessor_name($col);
-#warn "$col $acc";
- $att{$col} = delete $attrs->{$acc} if exists $attrs->{$acc};
+ $attrs->{$col} = delete $attrs->{$acc} if exists $attrs->{$acc};
}
if ($class->can('mutator_name')) {
my $mut = $class->mutator_name($col);
- $att{$col} = delete $attrs->{$mut} if exists $attrs->{$mut};
+ $attrs->{$col} = delete $attrs->{$mut} if exists $attrs->{$mut};
}
}
- return $class->NEXT::ACTUAL::create({ %$attrs, %att }, @rest);
+ return $class->next::method($attrs, @rest);
}
1;
sub set_column {
my $self = shift;
- my $ret = $self->NEXT::set_column(@_);
+ my $ret = $self->next::method(@_);
$self->update if ($self->autoupdate && $self->{_in_storage});
return $ret;
}
use strict;
use warnings;
-use NEXT;
+
+use base qw/DBIx::Class/;
sub _register_column_group {
my ($class, $group, @cols) = @_;
- return $class->NEXT::ACTUAL::_register_column_group($group => map lc, @cols);
+ return $class->next::method($group => map lc, @cols);
}
sub _register_columns {
my ($class, @cols) = @_;
- return $class->NEXT::ACTUAL::_register_columns(map lc, @cols);
+ return $class->next::method(map lc, @cols);
}
sub has_a {
my ($class, $col, @rest) = @_;
- $class->NEXT::ACTUAL::has_a(lc($col), @rest);
+ $class->next::method(lc($col), @rest);
$class->mk_group_accessors('inflated_column' => $col);
return 1;
}
sub has_many {
my ($class, $rel, $f_class, $f_key, @rest) = @_;
- return $class->NEXT::ACTUAL::has_many($rel, $f_class, ( ref($f_key) ?
+ return $class->next::method($rel, $f_class, ( ref($f_key) ?
$f_key :
lc($f_key) ), @rest);
}
sub get_inflated_column {
my ($class, $get, @rest) = @_;
- return $class->NEXT::ACTUAL::get_inflated_column(lc($get), @rest);
+ return $class->next::method(lc($get), @rest);
}
sub store_inflated_column {
my ($class, $set, @rest) = @_;
- return $class->NEXT::ACTUAL::store_inflated_column(lc($set), @rest);
+ return $class->next::method(lc($set), @rest);
}
sub set_inflated_column {
my ($class, $set, @rest) = @_;
- return $class->NEXT::ACTUAL::set_inflated_column(lc($set), @rest);
+ return $class->next::method(lc($set), @rest);
}
sub get_column {
my ($class, $get, @rest) = @_;
- return $class->NEXT::ACTUAL::get_column(lc($get), @rest);
+ return $class->next::method(lc($get), @rest);
}
sub set_column {
my ($class, $set, @rest) = @_;
- return $class->NEXT::ACTUAL::set_column(lc($set), @rest);
+ return $class->next::method(lc($set), @rest);
}
sub store_column {
my ($class, $set, @rest) = @_;
- return $class->NEXT::ACTUAL::store_column(lc($set), @rest);
+ return $class->next::method(lc($set), @rest);
}
sub find_column {
my ($class, $col) = @_;
- return $class->NEXT::ACTUAL::find_column(lc($col));
+ return $class->next::method(lc($col));
}
sub _mk_group_accessors {
next if defined &{"${class}::${acc}"};
push(@extra, [ lc $acc => $field ]);
}
- return $class->NEXT::ACTUAL::_mk_group_accessors($type, $group,
+ return $class->next::method($type, $group,
@fields, @extra);
}
sub _cond_key {
my ($class, $attrs, $key, @rest) = @_;
- return $class->NEXT::ACTUAL::_cond_key($attrs, lc($key), @rest);
+ return $class->next::method($attrs, lc($key), @rest);
}
sub _cond_value {
my ($class, $attrs, $key, @rest) = @_;
- return $class->NEXT::ACTUAL::_cond_value($attrs, lc($key), @rest);
+ return $class->next::method($attrs, lc($key), @rest);
}
sub new {
my ($class, $attrs, @rest) = @_;
my %att;
$att{lc $_} = $attrs->{$_} for keys %$attrs;
- return $class->NEXT::ACTUAL::new(\%att, @rest);
+ return $class->next::method(\%att, @rest);
}
1;
use strict;
use warnings;
-use NEXT;
-use base qw/Class::Data::Inheritable/;
+use base qw/DBIx::Class::Row/;
__PACKAGE__->mk_classdata('_column_groups' => { });
sub primary_column {
my ($class) = @_;
- my @pri = keys %{$class->_primaries};
+ my @pri = $class->primary_columns;
return wantarray ? @pri : $pri[0];
}
sub find_column {
my ($class, $col) = @_;
- return $col if $class->_columns->{$col};
+ return $col if $class->has_column($col);
}
sub __grouper {
sub has_a {
my ($self, $col, $f_class, %args) = @_;
- $self->throw( "No such column ${col}" ) unless $self->_columns->{$col};
+ $self->throw( "No such column ${col}" ) unless $self->has_column($col);
eval "require $f_class";
if ($args{'inflate'} || $args{'deflate'}) { # Non-database has_a
if (!ref $args{'inflate'}) {
$args->{cascade_delete} = 0;
}
- $class->NEXT::has_many($rel, $f_class, $f_key, $args);
+ $class->next::method($rel, $f_class, $f_key, $args);
if (@f_method) {
no strict 'refs';
use warnings;
use DBIx::ContextualFetch;
-use NEXT;
-use base qw/Class::Data::Inheritable/;
+use base qw/DBIx::Class/;
__PACKAGE__->mk_classdata('_transform_sql_handler_order'
=> [ qw/TABLE ESSENTIAL JOIN/ ] );
my ($class, @info) = @_;
$info[3] = { %{ $info[3] || {}} };
$info[3]->{RootClass} = 'DBIx::ContextualFetch';
- return $class->NEXT::connection(@info);
+ return $class->next::method(@info);
}
sub __driver {
&& $_ ne 'All' }
keys %{ $self->_column_groups || {} });
}
- $self->NEXT::get_column(@_[1..$#_]);
+ $self->next::method(@_[1..$#_]);
}
sub _flesh {
sub insert {
my ($self, @rest) = @_;
- $self->NEXT::ACTUAL::insert(@rest);
+ $self->next::method(@rest);
# Because the insert will die() if it can't insert into the db (or should)
# we can be sure the object *was* inserted if we got this far. In which
# case, given primary keys are unique and ID only returns a
sub _row_to_object {
my ($class, @rest) = @_;
- my $new = $class->NEXT::ACTUAL::_row_to_object(@rest);
+ my $new = $class->next::method(@rest);
if (my $key = $new->ID) {
#warn "Key $key";
my $live = $class->live_object_index;
my ($self) = @_;
if (my $key = $self->ID) {
$self->remove_from_object_index;
- my $ret = $self->NEXT::ACTUAL::discard_changes;
+ my $ret = $self->next::method;
$self->live_object_index->{$key} = $self if $self->in_storage;
return $ret;
} else {
- return $self->NEXT::ACTUAL::discard_changes;
+ return $self->next::method;
}
}
sub might_have {
my ($class, $rel, $f_class, @columns) = @_;
if (ref $columns[0] || !defined $columns[0]) {
- return $class->NEXT::might_have($rel, $f_class, @columns);
+ return $class->next::method($rel, $f_class, @columns);
} else {
- return $class->NEXT::might_have($rel, $f_class, undef,
+ return $class->next::method($rel, $f_class, undef,
{ proxy => \@columns });
}
}
use Scalar::Util;
use overload
- '""' => sub {
- return Scalar::Util::refaddr($_[0]) if (caller)[0] eq 'NEXT';
- return shift->stringify_self; },
+ '""' => sub { return shift->stringify_self; },
fallback => 1;
sub stringify_self {
my $self = shift;
my @cols = $self->columns('Stringify');
@cols = $self->primary_column unless @cols;
- my $ret = join "/", map { $self->get_column($_) } @cols;
+ my $ret = join "/", map { $self->get_column($_) || '' } @cols;
return $ret || ref $self;
}
use strict;
use warnings;
-use base qw/Class::Data::Inheritable/;
+use base qw/DBIx::Class/;
__PACKAGE__->mk_classdata('_temp_columns' => { });
$tmp{$_} = 1 for @cols;
$class->_temp_columns(\%tmp);
} else {
- return $class->NEXT::ACTUAL::_add_column_group($group, @cols);
+ return $class->next::method($group, @cols);
}
}
foreach my $key (keys %$attrs) {
$temp{$key} = delete $attrs->{$key} if $class->_temp_columns->{$key};
}
- my $new = $class->NEXT::ACTUAL::new($attrs, @rest);
+ my $new = $class->next::method($attrs, @rest);
foreach my $key (keys %temp) {
$new->set_temp($key, $temp{$key});
}
sub find_column {
my ($class, $col, @rest) = @_;
return $col if $class->_temp_columns->{$col};
- return $class->NEXT::ACTUAL::find_column($col, @rest);
+ return $class->next::method($col, @rest);
}
sub get_temp {
}
sub has_real_column {
- return 1 if shift->_columns->{shift};
+ return 1 if shift->has_column(shift);
}
1;
sub insert {
my $self = shift;
$self->call_trigger('before_create');
- $self->NEXT::ACTUAL::insert(@_);
+ $self->next::method(@_);
$self->call_trigger('after_create');
return $self;
}
$self->call_trigger('before_update');
my @to_update = keys %{$self->{_dirty_columns} || {}};
return -1 unless @to_update;
- $self->NEXT::ACTUAL::update(@_);
+ $self->next::method(@_);
$self->call_trigger('after_update');
return $self;
}
sub delete {
my $self = shift;
$self->call_trigger('before_delete') if ref $self;
- $self->NEXT::ACTUAL::delete(@_);
+ $self->next::method(@_);
$self->call_trigger('after_delete') if ref $self;
return $self;
}
my ($self, $column, $value, @rest) = @_;
my $vals = { $column => $value };
$self->call_trigger("before_set_${column}", $value, $vals);
- return $self->NEXT::ACTUAL::store_column($column, $vals->{$column});
+ return $self->next::method($column, $vals->{$column});
}
1;
package DBIx::Class::Componentised;
+use Class::C3;
+
sub inject_base {
my ($class, $target, @to_inject) = @_;
{
no strict 'refs';
unshift(@{"${target}::ISA"}, grep { $target ne $_ } @to_inject);
}
+ my $table = { Class::C3::_dump_MRO_table };
+ eval "package $target; import Class::C3;" unless exists $table->{$target};
+ Class::C3::reinitialize() if defined $table->{$target};
}
sub load_components {
package DBIx::Class::DB;
-use base qw/Class::Data::Inheritable/;
+use base qw/DBIx::Class/;
use DBIx::Class::Storage::DBI;
use DBIx::Class::ClassResolver::PassThrough;
use DBI;
use strict;
use warnings;
+use base qw/DBIx::Class::Row/;
sub inflate_column {
my ($self, $col, $attrs) = @_;
- die "No such column $col to inflate" unless exists $self->_columns->{$col};
+ die "No such column $col to inflate" unless $self->has_column($col);
die "inflate_column needs attr hashref" unless ref $attrs eq 'HASH';
- $self->_columns->{$col}{_inflate_info} = $attrs;
+ $self->column_info($col)->{_inflate_info} = $attrs;
$self->mk_group_accessors('inflated_column' => $col);
return 1;
}
sub _inflated_column {
my ($self, $col, $value) = @_;
return $value unless defined $value; # NULL is NULL is NULL
- return $value unless exists $self->_columns->{$col}{_inflate_info};
- return $value unless exists $self->_columns->{$col}{_inflate_info}{inflate};
- my $inflate = $self->_columns->{$col}{_inflate_info}{inflate};
+ my $info = $self->column_info($col) || die "No column info for $col";
+ return $value unless exists $info->{_inflate_info};
+ my $inflate = $info->{_inflate_info}{inflate};
+ die "No inflator for $col" unless defined $inflate;
return $inflate->($value, $self);
}
sub _deflated_column {
my ($self, $col, $value) = @_;
return $value unless ref $value; # If it's not an object, don't touch it
- return $value unless exists $self->_columns->{$col}{_inflate_info};
- return $value unless exists $self->_columns->{$col}{_inflate_info}{deflate};
- my $deflate = $self->_columns->{$col}{_inflate_info}{deflate};
+ my $info = $self->column_info($col) || die "No column info for $col";
+ return $value unless exists $info->{_inflate_info};
+ my $deflate = $info->{_inflate_info}{deflate};
+ die "No deflator for $col" unless defined $deflate;
return $deflate->($value, $self);
}
sub get_inflated_column {
my ($self, $col) = @_;
$self->throw("$col is not an inflated column") unless
- exists $self->_columns->{$col}{_inflate_info};
+ exists $self->column_info($col)->{_inflate_info};
return $self->{_inflated_column}{$col}
if exists $self->{_inflated_column}{$col};
sub new {
my ($class, $attrs, @rest) = @_;
$attrs ||= {};
- my %deflated;
foreach my $key (keys %$attrs) {
- if (exists $class->_columns->{$key}{_inflate_info}) {
- $deflated{$key} = $class->_deflated_column($key,
- delete $attrs->{$key});
+ if (ref $attrs->{$key}
+ && exists $class->column_info($key)->{_inflate_info}) {
+ $attrs->{$key} = $class->_deflated_column($key, $attrs->{$key});
}
}
- return $class->NEXT::ACTUAL::new({ %$attrs, %deflated }, @rest);
+ return $class->next::method($attrs, @rest);
}
-# **** B0RKEN. DOESN'T GET CALLED!
-#sub _cond_value {
-# my ($self, $attrs, $key, $value) = @_;
-# if (exists $self->_columns->{$key}) {
-# $value = $self->_deflated_column($key, $value);
-# }
-# return $self->NEXT::ACTUAL::_cond_value($attrs, $key, $value);
-#}
-
1;
This is not as easy as it could be, but it's possible. Here's an example to
illustrate:
- package Base;
-
- use base qw/DBIx::Class/;
-
- __PACKAGE__->load_components(qw/Core DB/);
- __PACKAGE__->connection(...);
-
- package Left;
-
- use base qw/Base/;
-
- __PACKAGE__->table('left');
- __PACKAGE__->add_columns(qw/id left_stuff/);
- __PACKAGE__->set_primary_key(qw/id/);
- __PACKAGE__->has_many('mid' => 'Mid');
-
- sub right {
- my ($self) = @_;
- return Right->search(
- { 'left.id' => $self->id },
- { join => { 'mid' => 'left' }});
- }
-
- package Mid;
-
- use base qw/Base/;
-
- __PACKAGE__->table('mid');
- __PACKAGE__->add_columns(qw/left right/);
- __PACKAGE__->set_primary_key(qw/left right/);
-
- __PACKAGE__->belongs_to('left' => 'Left');
- __PACKAGE__->belongs_to('right' => 'Right');
-
- package Right;
-
- use base qw/Base/;
-
- __PACKAGE__->table('right');
- __PACKAGE__->add_columns(qw/id right_stuff/);
- __PACKAGE__->set_primary_key(qw/id/);
- __PACKAGE__->has_many('mid' => 'Mid');
-
- sub left {
- my ($self) = @_;
- return Left->search(
- { 'right.id' => $self->id },
- { join => { 'mid' => 'right' });
- }
+ # Set up inherited connection information
+ package MyApp::DBIC;
+ use base qw/DBIx::Class/;
+
+ __PACKAGE__->load_components(qw/PK::Auto::SQLite Core DB/);
+ __PACKAGE__->connection(...);
+
+ # Set up a class for the 'authors' table
+ package MyApp::DBIC::Author;
+ use base qw/MyApp::DBIC/;
+
+ __PACKAGE__->table('authors');
+ __PACKAGE__->add_columns(qw/authID first_name last_name/);
+ __PACKAGE__->set_primary_key(qw/authID/);
+
+ # Define relationship to the link table
+ __PACKAGE__->has_many('b2a' => 'MyApp::DBIC::Book2Author', 'authID');
+
+ # Create the accessor for books from the ::Author class
+ sub books {
+ my ($self) = @_;
+ return MyApp::DBIC::Book->search(
+ { 'b2a.authID' => $self->authID }, # WHERE clause
+ { join => 'b2a' } # join condition (part of search attrs)
+ # 'b2a' refers to the relationship named earlier in the Author class.
+ # 'b2a.authID' refers to the authID column of the b2a relationship,
+ # which becomes accessible in the search by being joined.
+ );
+ }
+
+ # define the link table class
+ package MyApp::DBIC::Book2Author;
+ use base qw/MyApp::DBIC/;
+
+ __PACKAGE__->table('book2author');
+ __PACKAGE__->add_columns(qw/bookID authID/);
+ __PACKAGE__->set_primary_key(qw/bookID authID/);
+
+ __PACKAGE__->belongs_to('authID' => 'MyApp::DBIC::Author');
+ __PACKAGE__->belongs_to('bookID' => 'MyApp::DBIC::Book');
+
+ package MyApp::DBIC::Book;
+ use base qw/MyApp::DBIC/;
+
+ __PACKAGE__->table('books');
+ __PACKAGE__->add_columns(qw/bookID title edition isbn publisher year/);
+ __PACKAGE__->set_primary_key(qw/bookID/);
+
+ __PACKAGE__->has_many('b2a' => 'MyApp::DBIC::Book2Author', 'bookID');
+
+ sub authors {
+ my ($self) = @_;
+ return MyApp::DBIC::Author->search(
+ { 'b2a.bookID' => $self->bookID }, # WHERE clause
+ { join => 'b2a' }); # join condition (part of search attrs)
+ }
+
+ # So the above search returns an author record where the bookID field of the
+ # book2author table equals the bookID of the books (using the bookID
+ # relationship table
=item Advanced Exception handling
__PACKAGE__->load_components(qw/Core DB/);
If you want serial/auto-incremental primary keys, you'll need to add
-the apropriate component for your db as well, for example
+the apropriate component for your db as well, for example. The
+PK::Auto::* modules help L<DBIx::Class> keep up with newly generated
+keys in auto increment database fields.
__PACKAGE__->load_components(qw/PK::Auto::SQLite Core DB/);
With that out of the way, we can define our first table class:
- package MyApp::DB::Frob
+ package MyApp::DB::Album;
use base qw/MyApp::DB/;
Then we specify which table it uses,
- __PACKAGE__->table('frob');
+ __PACKAGE__->table('album');
and specify which columns it has.
- __PACKAGE__->add_columns(qw/id foo bar/);
+ __PACKAGE__->add_columns(qw/albumID artist title label year/);
This will automatically create accessors for each of the columns, so that
you can read/update the values in rows you've retrieved.
Also, you need to tell it which column is the primary key:
- __PACKAGE__->set_primary_key('id');
+ __PACKAGE__->set_primary_key('albumID');
If you have multiple primary keys, just pass a list instead.
use DBIx::Class::Loader;
- my $loader=DBIx::Class::Loader->new(
- dsn => 'dbi:SQLite:/home/me/myapp/my.db',
- namespace => 'MyApp::DB');
+ my $loader = DBIx::Class::Loader->new(
+ dsn => 'dbi:SQLite:/home/me/myapp/my.db',
+ namespace => 'MyApp::DB');
1;
This should be equivalent to the manual in the section above.
Once you've defined the basic classes, you can start interacting with your
database. The simplest way to get a column is by primary key:
- my $frob=MyApp::DB::Frob->find(14);
+ $albumID = 14;
+ $album = MyApp::DB::Album->find($albumID);
-This will run a select with id=14 in the WHERE clause, and return an instance
-of MyApp::DB::Frob that represents this row. Once you have that row, you can
+This will run a select with albumID=14 in the WHERE clause, and return an instance
+of MyApp::DB::Artist that represents this row. Once you have that row, you can
access and update columns
- my $val=$frob->bar;
- $frob->bar(14);
+ $album->title('Physical Graffiti');
+ $title = $album->title; # $title holds 'Physical Graffiti'
or if you prefer, you can use the set_column/get_column accessors instead
of the autogenerated accessors based on your column names.
Just like with L<Class::DBI>, you do an 'update' to commit your changes
to the database:
- $frob->update;
+ $album->update;
If needed, you can drop your local changes instead like this:
- $frob->discard_changes if $frob->is_changed;
+ $album->discard_changes if $album->is_changed;
As you can see, is_changed allows you to check if there are local changes to
your object.
=head2 Adding and removing rows.
-To make a new row, and put it into the database, you can use the 'create'
-method from L<DBIx::Class::Row>
+To create a new record in the database, you can use the 'create'
+method from L<DBIx::Class::Row>. It returns a L<DBIx::Class::ResultSet>
+object that can be used to access the data in the new record.
- my $new_thingie=MyApp::DB::Frob->create({
- foo=>'homer',
- bar=>'bart' });
+ $new_album = MyApp::DB::Album->create({
+ title => 'Wish You Were Here',
+ artist => 'Pink Floyd'
+ });
+
+Now you can add data to the new record:
+
+ $new_album->label('Capitol');
+ $new_album->year('1975');
likewise, you can remove if from the database like this:
- $new_thingie->delete();
+ $new_album->delete();
or even without retrieving first. This operation takes the same kind of
arguments as a search.
- MyApp::DB::Frob->delete({foo=>'bart'});
+ MyApp::DB::Album->delete({ artist => 'Falco' });
=head2 Finding your objects.
DBIx::Class provides a few different ways to retrieve data from your database.
The simplest looks something like this:
- $rs=MyApp::DB::Frob->search(foo=>'bart');
+ $album = MyApp::DB::Album->search( artist => 'Santana' );
-note that all the search methods return a recordset in scalar context or
-a list containing all the elements in list context.
+note that all the search methods return a L<DBIx::Class::ResultSet> object
+in scalar context or a list containing all the records in list context.
-We also provide a handy shortcut for doing a like search:
+We also provide a handy shortcut for doing a "like" search:
- $rs=MyApp::DB::Frob->search_like(foo=>'bar%');
+ $album = MyApp::DB::Album->search_like( artist => 'Jimi%');
Or you can provide your own handmade WHERE clause, like
- $rs=MyApp::DB::Frob->search_literal('foo=?','bart');
+ $album = MyApp::DB::Album->search_literal('artist=?','Peter Frampton');
The other way to provide more complex queries, is to provide a
L<SQL::Abstract> construct to search:
- $rs=MyApp::DB::Frob->search({
- bar=>{'>' => 10 },
- foo=>{'!=','bart'},
- id => [1,14,15,65,43]
+ $album = MyApp::DB::Album->search({
+ artist => { '!=', 'Janis Joplin' },
+ year => { '<' => 1980 },
+ id => [ 1, 14, 15, 65, 43 ]
});
The search can also be modifyed by passing another hash with attributes:
- $rs=MyApp::DB::Frob->search( {foo=>'bart'},
- { page=>1, rows=>2, order_by=>'bar' } );
+ $album = MyApp::DB::Album->search(
+ { artist => 'Bob Marley' },
+ { page => 1, rows => 2, order_by => 'year' }
+ );
For a complete overview over the available attributes, see
L<DBIx::Class::ResultSet>
use strict;
use warnings;
-use base qw/Class::Data::Inheritable/;
+use base qw/DBIx::Class/;
__PACKAGE__->mk_classdata('cache');
sub insert {
my $self = shift;
- $self->NEXT::ACTUAL::insert(@_);
+ $self->next::method(@_);
$self->_insert_into_cache if $self->cache;
return $self;
}
sub find {
my ($self,@vals) = @_;
- return $self->NEXT::ACTUAL::find(@vals) unless $self->cache;
+ return $self->next::method(@vals) unless $self->cache;
# this is a terrible hack here. I know it can be improved.
# but, it's a start anyway. probably find in PK.pm needs to
# call a hook, or some such thing. -Dave/ningu
my ($object,$key);
- my @pk = keys %{$self->_primaries};
+ my @pk = $self->primary_columns;
if (ref $vals[0] eq 'HASH') {
my $cond = $vals[0]->{'-and'};
$key = $self->_create_ID(%{$cond->[0]}) if ref $cond eq 'ARRAY';
return $object;
}
- $object = $self->NEXT::ACTUAL::find(@vals);
+ $object = $self->next::method(@vals);
$object->_insert_into_cache if $object;
return $object;
}
sub update {
my $self = shift;
- my $new = $self->NEXT::ACTUAL::update(@_);
+ my $new = $self->next::method(@_);
$self->_insert_into_cache if $self->cache;
return;
}
sub delete {
my $self = shift;
$self->cache->remove($self->ID) if $self->cache;
- return $self->NEXT::ACTUAL::delete(@_);
+ return $self->next::method(@_);
}
sub _row_to_object {
my $self = shift;
- my $new = $self->NEXT::ACTUAL::_row_to_object(@_);
+ my $new = $self->next::method(@_);
$new->_insert_into_cache if $self->cache;
return $new;
}
use warnings;
use Tie::IxHash;
-use base qw/Class::Data::Inheritable/;
+use base qw/DBIx::Class::Row/;
__PACKAGE__->mk_classdata('_primaries' => {});
}
delete @{$self}{keys %$self};
@{$self}{keys %$reload} = values %$reload;
- #$self->store_column($_ => $reload->get_column($_))
- # foreach keys %{$self->_columns};
return $self;
}
return join '|', $class, map { $_ . '=' . $vals{$_} } sort keys %vals;
}
+sub ident_condition {
+ my ($self) = @_;
+ my %cond;
+ $cond{$_} = $self->get_column($_) for $self->primary_columns;
+ return \%cond;
+}
+
1;
=back
package DBIx::Class::PK::Auto;
-use base qw/Class::Data::Inheritable/;
+#use base qw/DBIx::Class::PK/;
+use base qw/DBIx::Class/;
use strict;
use warnings;
sub insert {
my ($self, @rest) = @_;
- my $ret = $self->NEXT::ACTUAL::insert(@rest);
+ my $ret = $self->next::method(@rest);
# if all primaries are already populated, skip auto-inc
my $populated = 0;
- map { $populated++ if $self->$_ } keys %{ $self->_primaries };
- return $ret if ( $populated == scalar keys %{ $self->_primaries } );
+ map { $populated++ if defined $self->get_column($_) } $self->primary_columns;
+ return $ret if ( $populated == scalar $self->primary_columns );
my ($pri, $too_many) =
- (grep { $self->_primaries->{$_}{'auto_increment'} }
- keys %{ $self->_primaries })
- || (keys %{ $self->_primaries });
+ (grep { $self->column_info($_)->{'auto_increment'} }
+ $self->primary_columns)
+ || $self->primary_columns;
$self->throw( "More than one possible key found for auto-inc on ".ref $self )
if $too_many;
unless (defined $self->get_column($pri)) {
while (my $foo = $sth->fetchrow_arrayref){
if(defined $foo->[12] && $foo->[12] =~ /^nextval/) {
($self->{_autoinc_seq}) = $foo->[12] =~
- m!^nextval\('"?([^"']+)"?'::text\)!;
+ m!^nextval\('"?([^"']+)"?'::(?:text|regclass)\)!;
}
}
}
use strict;
use warnings;
-use base qw/DBIx::Class Class::Data::Inheritable/;
+use base qw/DBIx::Class/;
__PACKAGE__->load_own_components(qw/
HasMany
sub add_relationship {
my ($class, $rel, @rest) = @_;
- my $ret = $class->NEXT::ACTUAL::add_relationship($rel => @rest);
+ my $ret = $class->next::method($rel => @rest);
my $rel_obj = $class->_relationships->{$rel};
if (my $acc_type = $rel_obj->{attrs}{accessor}) {
$class->add_relationship_accessor($rel => $acc_type);
};
} elsif ($acc_type eq 'filter') {
$class->throw("No such column $rel to filter")
- unless exists $class->_columns->{$rel};
+ unless $class->has_column($rel);
my $f_class = $class->_relationships->{$rel}{class};
$class->inflate_column($rel,
{ inflate => sub {
use strict;
use warnings;
-use base qw/Class::Data::Inheritable/;
+use base qw/DBIx::Class/;
__PACKAGE__->mk_classdata('_relationships', { } );
cond => $cond,
attrs => $attrs };
$class->_relationships(\%rels);
- #warn %{$f_class->_columns};
- return unless eval { %{$f_class->_columns}; }; # Foreign class not loaded
+ return unless eval { $f_class->can('columns'); }; # Foreign class not loaded
eval { $class->_resolve_join($rel, 'me') };
if ($@) { # If the resolve failed, back out and re-throw the error
if (my $alias = $attrs->{_aliases}{$type}) {
my $class = $attrs->{_classes}{$alias};
$self->throw("Unknown column $field on $class as $alias")
- unless exists $class->_columns->{$field};
+ unless $class->has_column($field);
return join('.', $alias, $field);
} else {
$self->throw( "Unable to resolve type ${type}: only have aliases for ".
join(', ', keys %{$attrs->{_aliases} || {}}) );
}
}
- return $self->NEXT::ACTUAL::_cond_key($attrs, $key);
+ return $self->next::method($attrs, $key);
}
sub _cond_value {
unless ($value =~ s/^self\.//) {
$self->throw( "Unable to convert relationship to WHERE clause: invalid value ${value}" );
}
- unless ($self->_columns->{$value}) {
+ unless ($self->has_column($value)) {
$self->throw( "Unable to convert relationship to WHERE clause: no such accessor ${value}" );
}
return $self->get_column($value);
if (my $alias = $attrs->{_aliases}{$type}) {
my $class = $attrs->{_classes}{$alias};
$self->throw("Unknown column $field on $class as $alias")
- unless exists $class->_columns->{$field};
+ unless $class->has_column($field);
return join('.', $alias, $field);
} else {
$self->throw( "Unable to resolve type ${type}: only have aliases for ".
}
}
- return $self->NEXT::ACTUAL::_cond_value($attrs, $key, $value)
+ return $self->next::method($attrs, $key, $value)
}
=item search_related
sub belongs_to {
my ($class, $rel, $f_class, $cond, $attrs) = @_;
eval "require $f_class";
- my %f_primaries = eval { %{ $f_class->_primaries } };
+ my %f_primaries;
+ $f_primaries{$_} = 1 for eval { $f_class->primary_columns };
my $f_loaded = !$@;
# single key relationship
if (not defined $cond) {
$class->throw("Can't infer join condition for ${rel} on ${class}; unable to load ${f_class}") unless $f_loaded;
my ($pri, $too_many) = keys %f_primaries;
$class->throw("Can't infer join condition for ${rel} on ${class}; ${f_class} has multiple primary key") if $too_many;
- my $acc_type = ($class->_columns->{$rel}) ? 'filter' : 'single';
+ my $acc_type = ($class->has_column($rel)) ? 'filter' : 'single';
$class->add_relationship($rel, $f_class,
{ "foreign.${pri}" => "self.${rel}" },
{ accessor => $acc_type, %{$attrs || {}} }
sub delete {
my ($self, @rest) = @_;
- return $self->NEXT::ACTUAL::delete(@rest) unless ref $self;
+ return $self->next::method(@rest) unless ref $self;
# I'm just ignoring this for class deletes because hell, the db should
# be handling this anyway. Assuming we have joins we probably actually
# *could* do them, but I'd rather not.
- my $ret = $self->NEXT::ACTUAL::delete(@rest);
+ my $ret = $self->next::method(@rest);
my %rels = %{ $self->_relationships };
my @cascade = grep { $rels{$_}{attrs}{cascade_delete} } keys %rels;
sub update {
my ($self, @rest) = @_;
- return $self->NEXT::ACTUAL::update(@rest) unless ref $self;
+ return $self->next::method(@rest) unless ref $self;
# Because update cascades on a class *really* don't make sense!
- my $ret = $self->NEXT::ACTUAL::update(@rest);
+ my $ret = $self->next::method(@rest);
my %rels = %{ $self->_relationships };
my @cascade = grep { $rels{$_}{attrs}{cascade_update} } keys %rels;
eval "require $f_class";
unless (ref $cond) {
- my ($pri, $too_many) = keys %{ $class->_primaries };
+ my ($pri, $too_many) = $class->primary_columns;
$class->throw( "has_many can only infer join for a single primary key; ${class} has more" )
if $too_many;
my $f_key;
- my $f_class_loaded = eval { $f_class->_columns };
+ my $f_class_loaded = eval { $f_class->columns };
my $guess;
if (defined $cond && length $cond) {
$f_key = $cond;
$guess = "using our class name '$class' as foreign key";
}
$class->throw("No such column ${f_key} on foreign class ${f_class} ($guess)")
- if $f_class_loaded && !exists $f_class->_columns->{$f_key};
+ if $f_class_loaded && !$f_class->has_column($f_key);
$cond = { "foreign.${f_key}" => "self.${pri}" },
}
my ($class, $join_type, $rel, $f_class, $cond, $attrs) = @_;
eval "require $f_class";
unless (ref $cond) {
- my ($pri, $too_many) = keys %{ $class->_primaries };
+ my ($pri, $too_many) = $class->primary_columns;
$class->throw( "might_have/has_one can only infer join for a single primary key; ${class} has more" )
if $too_many;
my $f_key;
- my $f_class_loaded = eval { $f_class->_columns };
+ my $f_class_loaded = eval { $f_class->columns };
my $guess;
if (defined $cond && length $cond) {
$f_key = $cond;
$guess = "caller specified foreign key '$f_key'";
- } elsif ($f_class_loaded && $f_class->_columns->{$rel}) {
+ } elsif ($f_class_loaded && $f_class->has_column($rel)) {
$f_key = $rel;
$guess = "using given relationship '$rel' for foreign key";
} else {
- ($f_key, $too_many) = keys %{ $f_class->_primaries };
+ ($f_key, $too_many) = $f_class->primary_columns;
$class->throw( "might_have/has_one can only infer join for a single primary key; ${f_class} has more" )
if $too_many;
$guess = "using primary key of foreign class for foreign key";
}
$class->throw("No such column ${f_key} on foreign class ${f_class} ($guess)")
- if $f_class_loaded && !exists $f_class->_columns->{$f_key};
+ if $f_class_loaded && !$f_class->has_column($f_key);
$cond = { "foreign.${f_key}" => "self.${pri}" };
}
$class->add_relationship($rel, $f_class,
use strict;
use warnings;
-use base qw/Class::Data::Inheritable/;
+use base qw/DBIx::Class/;
sub add_relationship {
my ($class, $rel, @rest) = @_;
- my $ret = $class->NEXT::ACTUAL::add_relationship($rel => @rest);
+ my $ret = $class->next::method($rel => @rest);
if (my $proxy_list = $class->_relationships->{$rel}->{attrs}{proxy}) {
$class->proxy_to_related($rel,
(ref $proxy_list ? @$proxy_list : $proxy_list));
=head1 NAME
-DBIX::Class::Recordset - Responsible for fetching and creating recordsets.
+DBIX::Class::ResultSet - Responsible for fetching and creating resultset.
=head1 SYNOPSIS;
=head1 DESCRIPTION
-The recordset is also know as an iterator.
+The resultset is also known as an iterator.
=head1 METHODS
=item new <db_class> <attrs>
-The recordset constructor. Takes a db class and an
+The resultset constructor. Takes a db class and an
attribute hash (see below for more info on attributes)
=cut
=item cursor
-Return a storage driven cursor to the given record set.
+Return a storage driven cursor to the given resultset.
=cut
=item slice <first> <last>
-return a number of elements from the given record set.
+return a number of elements from the given resultset.
=cut
=item next
-Returns the next element in this record set.
+Returns the next element in this resultset.
=cut
=item all
-Returns all elements in the recordset. Is called implictly if the search
+Returns all elements in the resultset. Is called implictly if the search
method is used in list context.
=cut
=item reset
-Reset this recordset's cursor, so you can iterate through the elements again.
+Reset this resultset's cursor, so you can iterate through the elements again.
=cut
=item first
-resets the recordset and returns the first element.
+resets the resultset and returns the first element.
=cut
=item delete
-Deletes all elements in the recordset.
+Deletes all elements in the resultset.
=cut
=item page <page>
-Returns a new recordset representing a given page.
+Returns a new resultset representing a given page.
=cut
=head1 Attributes
-The recordset is responsible for handling the various attributes that
+The resultset is responsible for handling the various attributes that
can be passed in with the search functions. Here's an overview of them:
=over 4
use strict;
use warnings;
+use base qw/DBIx::Class/;
+
=head1 NAME
DBIx::Class::Row - Basic row methods
if ($attrs) {
$new->throw("attrs must be a hashref" ) unless ref($attrs) eq 'HASH';
while (my ($k, $v) = each %{$attrs}) {
- $new->store_column($k => $v) if exists $class->_columns->{$k};
+ die "No such column $k on $class" unless $class->has_column($k);
+ $new->store_column($k => $v);
}
}
return $new;
return $self;
}
-sub ident_condition {
- my ($self) = @_;
- my %cond;
- $cond{$_} = $self->get_column($_) for keys %{$self->_primaries};
- return \%cond;
-}
-
=item delete
$obj->delete
sub get_column {
my ($self, $column) = @_;
$self->throw( "Can't fetch data as class method" ) unless ref $self;
- $self->throw( "No such column '${column}'" ) unless $self->_columns->{$column};
+ $self->throw( "No such column '${column}'" ) unless $self->has_column($column);
return $self->{_column_data}{$column}
if exists $self->{_column_data}{$column};
return undef;
sub store_column {
my ($self, $column, $value) = @_;
$self->throw( "No such column '${column}'" )
- unless $self->_columns->{$column};
+ unless $self->has_column($column);
$self->throw( "set_column called for ${column} without value" )
if @_ < 3;
return $self->{_column_data}{$column} = $value;
my ($class, $cols, $row) = @_;
my %vals;
$vals{$cols->[$_]} = $row->[$_] for 0 .. $#$cols;
- my $new = $class->new(\%vals);
+ my $new = bless({ _column_data => \%vals }, ref $class || $class);
$new->in_storage(1);
return $new;
}
use strict;
use warnings;
+use DBIx::Class::DB;
-use base qw/Class::Data::Inheritable/;
use base qw/DBIx::Class/;
-__PACKAGE__->load_components(qw/Exception Componentised/);
+__PACKAGE__->load_components(qw/Exception/);
__PACKAGE__->mk_classdata('class_registrations' => {});
=head1 NAME
=head1 SYNOPSIS
- in My/Schema.pm
+in My/Schema.pm
package My::Schema;
__PACKAGE__->load_classes(qw/Foo Bar Baz/);
- in My/Schema/Foo.pm
+in My/Schema/Foo.pm
package My::Schema::Foo;
- use base qw/DBIx::Class::Core/;
+ use base qw/DBIx::Class/;
+ __PACKAGE__->load_components(qw/Core PK::Auto::Pg/); # for example
__PACKAGE__->table('foo');
...
- in My/DB.pm
+in My/DB.pm
use My::Schema;
My::Schema->compose_connection('My::DB', $dsn, $user, $pass, $attrs);
- then in app code
+then in app code
my @obj = My::DB::Foo->search({}); # My::DB::Foo isa My::Schema::Foo My::DB
subclasses under a new namespace for each connection. If you only need one
class, you should probably use L<DBIx::Class::DB> directly instead.
+NB: If you're used to L<Class::DBI> it's worth reading the L</SYNOPSIS>
+carefully as DBIx::Class does things a little differently. Note in
+particular which module inherits off which.
+
=head1 METHODS
=over 4
my %map;
while (my ($comp, $comp_class) = each %reg) {
my $target_class = "${target}::${comp}";
- $class->inject_base($target_class, $conn_class, $comp_class);
+ $class->inject_base($target_class, $comp_class, $conn_class);
$target_class->table($comp_class->table);
@map{$comp, $comp_class} = ($target_class, $target_class);
}
sub setup_connection_class {
my ($class, $target, @info) = @_;
- $class->inject_base($target => 'DBIx::Class');
- $target->load_components('DB');
+ $class->inject_base($target => 'DBIx::Class::DB');
+ #$target->load_components('DB');
$target->connection(@info);
}
return $new;
}
-sub get_simple {
- my ($self, $get) = @_;
- return $self->{$get};
-}
-
-sub set_simple {
- my ($self, $set, $val) = @_;
- return $self->{$set} = $val;
-}
-
=head1 NAME
DBIx::Class::Storage::DBI - DBI storage handler
use DBIx::Class::ResultSet;
use Data::Page;
-use base qw/Class::Data::Inheritable/;
+use base qw/DBIx::Class/;
__PACKAGE__->mk_classdata('_columns' => {});
=item search
- my @obj = $class->search({ foo => 3 });
+ my @obj = $class->search({ foo => 3 }); # "... WHERE foo = 3"
my $cursor = $class->search({ foo => 3 });
+To retrieve all rows, simply call C<search()> with no condition parameter,
+
+ my @all = $class->search(); # equivalent to search({})
+
+If you need to pass in additional attributes (see
+L<DBIx::Class::ResultSet/Attributes> for details) an empty hash indicates
+no condition,
+
+ my @all = $class->search({}, { cols => [qw/foo bar/] }); # "SELECT foo, bar FROM $class_table"
+
=cut
sub search {
return defined($exists) ? $exists : $class->create($hash);
}
+=item has_column
+
+ if ($obj->has_column($col)) { ... }
+
+Returns 1 if the object has a column of this name, 0 otherwise
+
+=cut
+
+sub has_column {
+ my ($self, $column) = @_;
+ return exists $self->_columns->{$column};
+}
+
+=item column_info
+
+ my $info = $obj->column_info($col);
+
+Returns the column metadata hashref for the column
+
+=cut
+
+sub column_info {
+ my ($self, $column) = @_;
+ die "No such column $column" unless exists $self->_columns->{$column};
+ return $self->_columns->{$column};
+}
+
+=item columns
+
+ my @column_names = $obj->columns;
+
+=cut
+
sub columns { return keys %{shift->_columns}; }
1;
use base qw/DBIx::Class/;
-__PACKAGE__->load_components(qw/CDBICompat PK::Auto::SQLite Core DB/);
+__PACKAGE__->load_components(qw/PK::Auto::SQLite CDBICompat Core DB/);
use File::Temp qw/tempfile/;
my (undef, $DB) = tempfile();
package DBIx::Class::UUIDColumns;
-use base qw/Class::Data::Inheritable/;
+use base qw/DBIx::Class/;
use Data::UUID;
sub uuid_columns {
my $self = shift;
for (@_) {
- die "column $_ doesn't exist" unless exists $self->_columns->{$_};
+ die "column $_ doesn't exist" unless $self->has_column($_);
}
$self->uuid_auto_columns(\@_);
}
sub insert {
my ($self) = @_;
for my $column (@{$self->uuid_auto_columns}) {
- $self->$column( $self->get_uuid )
- unless defined $self->$column;
+ $self->store_column( $column, $self->get_uuid )
+ unless defined $self->get_column( $column );
}
- $self->NEXT::ACTUAL::insert;
+ $self->next::method;
}
sub get_uuid {
+++ /dev/null
-#!/usr/bin/perl
-
-use strict;
-use warnings;
-use Class::ISA;
-
-my $class = $ARGV[0];
-
-die "usage: nextalyzer Some::Class" unless $class;
-
-eval "use $class;";
-
-die "Error using $class: $@" if $@;
-
-my @path = reverse Class::ISA::super_path($class);
-
-my %provided;
-my %overloaded;
-
-my @warnings;
-
-foreach my $super (@path) {
- my $file = $super;
- $file =~ s/\:\:/\//g;
- $file .= '.pm';
- my $file_path = $INC{$file};
- die "Couldn't get INC for $file, super $super" unless $file_path;
- #warn "$super $file $file_path";
- open IN, '<', $file_path;
- my $in_sub;
- my $ws;
- my $uses_next;
- my @provides;
- my @overloads;
- while (my $line = <IN>) {
- unless ($in_sub) {
- ($ws, $in_sub) = ($line =~ /^(\s*)sub (\S+)/);
- next unless $in_sub;
- }
- if ($line =~ /^$ws\}/) {
- if ($uses_next) {
- push(@overloads, $in_sub);
- } else {
- push(@provides, $in_sub);
- }
- undef $in_sub;
- undef $uses_next;
- undef $ws;
- next;
- }
- $uses_next++ if ($line =~ /\-\>NEXT/);
- }
- close IN;
- foreach (@overloads) {
- push(@warnings, "Method $_ overloaded in $class but not yet provided")
- unless $provided{$_};
- push(@{$overloaded{$_}}, $super);
- }
- $provided{$_} = $super for @provides;
- print "Class $super:\n";
- print "Provides: @provides\n";
- print "Overloads: @overloads\n";
-}
-
-print "\n\n";
-
-print join("\n", @warnings);
-
-foreach my $o (keys %overloaded) {
- my $pr = $provided{$o} || "**NEVER**";
- print "Method $o: ".join(' ', reverse @{$overloaded{$o}})." ${pr}\n";
-}
YA::Film->add_relationship_type(has_a => "YA::HasA");
package YA::HasA;
- use base 'Class::DBI::Relationship::HasA';
+ #use base 'Class::DBI::Relationship::HasA';
sub _inflator {
my $self = shift;