view release on metacpan or search on metacpan
lib/DBIx/Class/AuditAny/Role/Storage.pm
lib/DBIx/Class/AuditAny/Util.pm
lib/DBIx/Class/AuditAny/Util/BuiltinDatapoints.pm
lib/DBIx/Class/AuditAny/Util/ResultMaker.pm
lib/DBIx/Class/AuditAny/Util/SchemaMaker.pm
t/001_simple_file_tracking.t
t/002_record_custom_tables.t
t/004_auto_dbic_collector.t
t/005_auto_dbic_collector_defaults.t
t/006_auto_dbic_collector_all_datapoints.t
t/007_cascades.t
t/008_resultset_changes.t
t/009_txn_do.t
t/010_txn_commit.t
t/011_sakila.t
t/012_wackyrels.t
t/013_skip_env.t
t/014_multi_pk.t
t/015_deep_create.t
t/97_pod.t
t/98_podspelling.t
lib/DBIx/Class/AuditAny/Collector/AutoDBIC.pm view on Meta::CPAN
},
$self->changeset_source_name => {
table_name => $self->changeset_table_name,
columns => $self->changeset_columns,
call_class_methods => [
set_primary_key => ['id'],
has_many => [
$self->change_data_rel,
$namespace . '::' . $self->change_source_name,
{ "foreign.changeset_id" => "self.id" },
{ cascade_copy => 0, cascade_delete => 0 },
]
]
},
$self->change_source_name => {
table_name => $self->change_table_name,
columns => $self->change_columns,
call_class_methods => [
set_primary_key => ['id'],
belongs_to => [
$self->reverse_changeset_data_rel,
$namespace . '::' . $self->changeset_source_name,
{ id => "changeset_id" },
{ is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" },
],
has_many => [
$self->column_data_rel,
$namespace . '::' . $self->column_change_source_name,
{ "foreign.change_id" => "self.id" },
{ cascade_copy => 0, cascade_delete => 0 },
]
]
},
$self->column_change_source_name => {
table_name => $self->column_change_table_name,
columns => $self->change_column_columns,
call_class_methods => [
set_primary_key => ['id'],
@$col_context_uniq_const,
#add_unique_constraint => ["change_id", ["change_id", "column_name"]],
lib/DBIx/Class/AuditAny/Role/Storage.pm view on Meta::CPAN
use strict;
use warnings;
# ABSTRACT: Role to apply to tracked DBIx::Class::Storage objects
use Moo::Role;
use MooX::Types::MooseLike::Base qw(:all);
## TODO:
## 1. track rekey in update
## 2. track changes in FK with cascade
=head1 NAME
DBIx::Class::AuditAny::Role::Storage - Role to apply to tracked DBIx::Class::Storage objects
=head1 DESCRIPTION
This role adds the hooks to the DBIC Storage object to be able to sniff and collect change data
has it happens in real time.
lib/DBIx/Class/AuditAny/Role/Storage.pm view on Meta::CPAN
# attribute to be updated and recorded at the end of the update. The
# auditors will keep track of their own changes temporarily in a "group":
$self->_add_change_contexts(
map {
$_->_start_current_change_group($Source, $nested, $action, @change_datam)
} $self->all_auditors
);
# -----
# Recursively follow effective changes in other tables that will
# be caused by any db-side cascades defined in relationships:
$self->_follow_relationship_cascades($Source,$cond,$change);
# -----
# Run the original/supplied method:
my @ret;
if($orig) {
try {
#############################################################
# --- Call original - scalar/list/void context agnostic ---
@ret = !defined $want ? do { $self->$orig(@$args); undef }
: $want ? $self->$orig(@$args)
lib/DBIx/Class/AuditAny/Role/Storage.pm view on Meta::CPAN
# into the active changeset (unless the action we're following is nested):
unless ($nested) {
$self->_record_change_contexts;
$_->_finish_current_change_group for ($self->all_auditors);
}
return $want ? @ret : $ret[0];
}
sub _follow_relationship_cascades {
my ($self, $Source, $cond, $change) = @_;
## IN PROGRESS.....
# If any of these columns are being changed, we have to also watch the
# corresponding relationhips for changes (from cascades) during the
# course of the current database operation. This can be expensive, but
# we prefer accuracy over speed
my $cascade_cols = $self->_get_cascading_rekey_columns($Source);
# temp: just get all of themfor now
# this should be limited to only rels associated with columns
# being changed
my @rels = uniq(map { @{$cascade_cols->{$_}} } keys %$cascade_cols);
foreach my $rel (@rels) {
my $rinfo = $Source->relationship_info($rel);
#my $rrinfo = $Source->reverse_relationship_info($rel);
# Generate a virtual 'change' to describe what will happen in the related table
my $map = &_cond_foreign_keymap($rinfo->{cond});
my $rel_change = {};
foreach my $col (keys %$change) {
my $fcol = $map->{$col} or next;
$rel_change->{$fcol} = $change->{$col};
}
# Only track related rows if there is at least one related change:
if(scalar(keys %$rel_change) > 0) {
# Get related rows that will be changed from the cascade:
my $rel_rows = get_raw_source_related_rows($Source,$rel,$cond);
# Follow these rows via special nested call:
$self->_follow_row_changes({
Source => $Source->related_source($rel),
rows => $rel_rows,
cond => {},
nested => 1,
action => 'update',
change => $rel_change
lib/DBIx/Class/AuditAny/Role/Storage.pm view on Meta::CPAN
# Get the current rows that are going to be deleted:
my $rows = get_raw_source_rows($Source,$cond);
my @change_datam = map {{
old_columns => $_,
condition => $cond
}} @$rows;
###########################
# TODO: find cascade deletes here
###########################
# Start new change operation within each Auditor and get back
# all the created ChangeContexts from all auditors. Each auditor
# will keep track of its own changes temporarily in a "group":
my @ChangeContexts = map {
$_->_start_current_change_group($Source, 0,'delete', @change_datam)
} $self->all_auditors;
lib/DBIx/Class/AuditAny/Role/Storage.pm view on Meta::CPAN
# Tell each auditor that we're done and to record the change group
# into the active changeset:
$_->_finish_current_change_group for ($self->all_auditors);
return $want ? @ret : $ret[0];
};
# _get_cascading_rekey_cols: gets a map of column names to relationships. These
# are the relationships that *could* be changed via a cascade when the column (fk)
# is changed.
# TODO: use 'cascade_rekey' attr from DBIx::Class::Shadow
# (DBIx::Class::Relationship::Cascade::Rekey) ?
sub _get_cascading_rekey_columns {
my $self = shift;
my $Source = shift;
# cache for next time (should I even bother? since if rels are added to the ResultSource
# later this won't get updated? Is that a bigger risk than the performance boost?)
$self->_source_cascade_rekey_cols->{$Source->source_name} ||= do {
my $rels = { map { $_ => $Source->relationship_info($_) } $Source->relationships };
my $cascade_cols = {};
foreach my $rel (keys %$rels) {
# Only multi rels apply:
next unless ($rels->{$rel}{attrs}{accessor} eq 'multi');
# NEW: We can't currently do anything with CodeRef conditions
next if ((ref($rels->{$rel}{cond})||'') eq 'CODE');
# Get all the local columns that effect (i.e. might cascade to) this relationship:
my @cols = $self->_parse_cond_cols_by_alias($rels->{$rel}{cond},'self');
# Add the relationship to list for each column.
#$cascade_cols->{$_} ||= [] for (@cols); #<-- don't need this
push @{$cascade_cols->{$_}}, $rel for (@cols);
}
return $cascade_cols;
};
return $self->_source_cascade_rekey_rels->{$Source->source_name};
}
has '_source_cascade_rekey_cols', is => 'ro', isa => HashRef, lazy => 1, default => sub {{}};
sub _parse_cond_cols_by_alias {
my $self = shift;
my $cond = shift;
my $alias = shift;
# Get the string elements (keys and values)
# (TODO: deep walk any hahs/array structure)
my @elements = %$cond;
t/007_cascades.t view on Meta::CPAN
first => 'Payton',
last => 'Manning',
team_id => 1,
position => 'Quarterback'
}),
"Insert a test row (Player table)"
);
ok(
$Position->update({ name => 'QB' }),
"Update fk that should cascade"
);
ok(
my $Player = $schema->resultset('Player')->search_rs({ last => 'Manning' })->first,
"Find the test Player row"
);
is(
$Player->get_column('position'),
'QB',
'Confirm the cascade update happened'
);
### finish me
done_testing;
t/lib/Routine/Sakila.pm view on Meta::CPAN
film_actors => [
{ film_id => 1 }
]
}),
"Insert an Actor row with film_actors link"
);
};
test 'updates_cascades' => { desc => 'Updates causing db-side cascades' } => sub {
my $self = shift;
my $schema = $self->Schema;
ok(
my $English = $schema->resultset('Language')->search_rs({
name => 'English'
})->first,
"Find 'English' Language row"
);
ok(
$English->update({ language_id => 100 }),
"Change the PK of the 'English' Language row (should cascade)"
);
};
1;
t/lib/Routine/Sakila/ToAutoDBIC.pm view on Meta::CPAN
is(
$schema->resultset('AuditChangeColumn')->search_rs({
$c->{old} => '1',
$c->{new} => '100',
$c->{column} => 'language_id',
'change.action' => 'update',
'change.source' => 'Film'
},{
join => { change => 'changeset' }
})->count => 2,
"Expected specific UPDATE records - generated from db-side cascade"
);
};
1;
t/lib/Routine/WackyRels.pm view on Meta::CPAN
]
}),
"Create Grade 'C' with Things"
);
});
};
test 'updates_cascades' => { desc => 'Updates causing db-side cascades' } => sub {
my $self = shift;
my $schema = $self->Schema;
ok(
my $Parent = $schema->resultset('Parent')->search_rs({
size => 'big',
color => 'blue'
})->first,
"Find 'big-blue' Parent row"
);
ok(
$Parent->update({ color => 'red' }),
"Change the PK of the 'big-blue' Parent row (should cascade)"
);
ok(
my $Size = $schema->resultset('Size')->search_rs({
name => 'big',
})->first,
"Find 'big' Size row"
);
ok(
$Size->update({ name => 'venti' }),
"Change the PK of the 'big' Size row (should cascade + double-cascade [3 tables])"
);
};
1;
t/lib/Routine/WackyRels/ToAutoDBIC.pm view on Meta::CPAN
is(
$schema->resultset('AuditChangeColumn')->search_rs({
$c->{old} => 'big',
$c->{new} => 'venti',
$c->{column} => 'size',
'change.action' => 'update',
'change.source' => 'Product'
},{
join => { change => 'changeset' }
})->count => 3,
"Expected Product UPDATE records - generated from 1-layer db-side cascade"
);
is(
$schema->resultset('AuditChangeColumn')->search_rs({
$c->{old} => 'big',
$c->{new} => 'venti',
$c->{column} => 'size',
'change.action' => 'update',
'change.source' => 'Child'
},{
join => { change => 'changeset' }
})->count => 3,
"Expected Child UPDATE records - generated from 2-layer db-side cascade"
);
is(
$schema->resultset('AuditChangeColumn')->search_rs({
$c->{old} => 'big',
$c->{new} => undef,
$c->{column} => 'size',
'change.action' => 'update',
'change.source' => 'Thing'
},{
join => { change => 'changeset' }
})->count => 1,
"Expected Thing UPDATE records - 'SET NULL' from db-side cascade"
);
};
1;
t/lib/TestSchema/One/Result/AuditChange.pm view on Meta::CPAN
"changeset",
"TestSchema::One::Result::AuditChangeSet",
{ id => "changeset_id" },
{ is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" },
);
__PACKAGE__->has_many(
"audit_change_columns",
"TestSchema::One::Result::AuditChangeColumn",
{ "foreign.change_id" => "self.id" },
{ cascade_copy => 0, cascade_delete => 0 },
);
1;
t/lib/TestSchema/One/Result/AuditChangeSet.pm view on Meta::CPAN
},
"client_ip",
{ data_type => "varchar", is_nullable => 1, size => 32 },
);
__PACKAGE__->set_primary_key("id");
__PACKAGE__->has_many(
"audit_changes",
"TestSchema::One::Result::AuditChange",
{ "foreign.changeset_id" => "self.id" },
{ cascade_copy => 0, cascade_delete => 0 },
);
1;
t/lib/TestSchema/One/Result/ContactType.pm view on Meta::CPAN
"id" => { data_type => "integer", is_auto_increment => 1, is_nullable => 0 },
"name" => { data_type => "varchar", is_nullable => 0, size => 32 },
);
__PACKAGE__->set_primary_key("id");
__PACKAGE__->has_many(
"contacts",
"TestSchema::One::Result::Contact",
{ "foreign.type_id" => "self.id" },
{ cascade_copy => 0, cascade_delete => 0 },
);
1;
t/lib/TestSchema/Sakila/Result/Actor.pm view on Meta::CPAN
Type: has_many
Related object: L<TestSchema::Sakila::Result::FilmActor>
=cut
__PACKAGE__->has_many(
"film_actors",
"TestSchema::Sakila::Result::FilmActor",
{ "foreign.actor_id" => "self.actor_id" },
{ cascade_copy => 0, cascade_delete => 0 },
);
# Created by DBIx::Class::Schema::Loader v0.07010 @ 2013-02-17 16:15:04
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:UTtfCAGXGENKnwGIwF6paA
# You can replace this text with custom code or comments, and it will be preserved on regeneration
1;
t/lib/TestSchema/Sakila/Result/Address.pm view on Meta::CPAN
Type: has_many
Related object: L<TestSchema::Sakila::Result::Customer>
=cut
__PACKAGE__->has_many(
"customers",
"TestSchema::Sakila::Result::Customer",
{ "foreign.address_id" => "self.address_id" },
{ cascade_copy => 0, cascade_delete => 0 },
);
=head2 staffs
Type: has_many
Related object: L<TestSchema::Sakila::Result::Staff>
=cut
__PACKAGE__->has_many(
"staffs",
"TestSchema::Sakila::Result::Staff",
{ "foreign.address_id" => "self.address_id" },
{ cascade_copy => 0, cascade_delete => 0 },
);
=head2 stores
Type: has_many
Related object: L<TestSchema::Sakila::Result::Store>
=cut
__PACKAGE__->has_many(
"stores",
"TestSchema::Sakila::Result::Store",
{ "foreign.address_id" => "self.address_id" },
{ cascade_copy => 0, cascade_delete => 0 },
);
# Created by DBIx::Class::Schema::Loader v0.07010 @ 2013-02-17 16:15:04
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:2IpqcMwZA7j+9RoW5A7Z7g
# You can replace this text with custom code or comments, and it will be preserved on regeneration
1;
t/lib/TestSchema/Sakila/Result/Category.pm view on Meta::CPAN
Type: has_many
Related object: L<TestSchema::Sakila::Result::FilmCategory>
=cut
__PACKAGE__->has_many(
"film_categories",
"TestSchema::Sakila::Result::FilmCategory",
{ "foreign.category_id" => "self.category_id" },
{ cascade_copy => 0, cascade_delete => 0 },
);
# Created by DBIx::Class::Schema::Loader v0.07010 @ 2013-02-17 16:15:04
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:FUFmM8sj+adV0Szue+HLfQ
# You can replace this text with custom code or comments, and it will be preserved on regeneration
1;
t/lib/TestSchema/Sakila/Result/City.pm view on Meta::CPAN
Type: has_many
Related object: L<TestSchema::Sakila::Result::Address>
=cut
__PACKAGE__->has_many(
"addresses",
"TestSchema::Sakila::Result::Address",
{ "foreign.city_id" => "self.city_id" },
{ cascade_copy => 0, cascade_delete => 0 },
);
=head2 country
Type: belongs_to
Related object: L<TestSchema::Sakila::Result::Country>
=cut
t/lib/TestSchema/Sakila/Result/Country.pm view on Meta::CPAN
Type: has_many
Related object: L<TestSchema::Sakila::Result::City>
=cut
__PACKAGE__->has_many(
"cities",
"TestSchema::Sakila::Result::City",
{ "foreign.country_id" => "self.country_id" },
{ cascade_copy => 0, cascade_delete => 0 },
);
# Created by DBIx::Class::Schema::Loader v0.07010 @ 2013-02-17 16:15:04
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:thoN1+OTcGL++MC+Djcryg
# You can replace this text with custom code or comments, and it will be preserved on regeneration
1;
t/lib/TestSchema/Sakila/Result/Customer.pm view on Meta::CPAN
Type: has_many
Related object: L<TestSchema::Sakila::Result::Payment>
=cut
__PACKAGE__->has_many(
"payments",
"TestSchema::Sakila::Result::Payment",
{ "foreign.customer_id" => "self.customer_id" },
{ cascade_copy => 0, cascade_delete => 0 },
);
=head2 rentals
Type: has_many
Related object: L<TestSchema::Sakila::Result::Rental>
=cut
__PACKAGE__->has_many(
"rentals",
"TestSchema::Sakila::Result::Rental",
{ "foreign.customer_id" => "self.customer_id" },
{ cascade_copy => 0, cascade_delete => 0 },
);
# Created by DBIx::Class::Schema::Loader v0.07010 @ 2013-02-17 16:15:04
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:VjyzmGea6edtdAUrjNJakQ
# You can replace this text with custom code or comments, and it will be preserved on regeneration
1;
t/lib/TestSchema/Sakila/Result/Film.pm view on Meta::CPAN
Type: has_many
Related object: L<TestSchema::Sakila::Result::FilmActor>
=cut
__PACKAGE__->has_many(
"film_actors",
"TestSchema::Sakila::Result::FilmActor",
{ "foreign.film_id" => "self.film_id" },
{ cascade_copy => 0, cascade_delete => 0 },
);
=head2 film_categories
Type: has_many
Related object: L<TestSchema::Sakila::Result::FilmCategory>
=cut
__PACKAGE__->has_many(
"film_categories",
"TestSchema::Sakila::Result::FilmCategory",
{ "foreign.film_id" => "self.film_id" },
{ cascade_copy => 0, cascade_delete => 0 },
);
=head2 inventories
Type: has_many
Related object: L<TestSchema::Sakila::Result::Inventory>
=cut
__PACKAGE__->has_many(
"inventories",
"TestSchema::Sakila::Result::Inventory",
{ "foreign.film_id" => "self.film_id" },
{ cascade_copy => 0, cascade_delete => 0 },
);
# Created by DBIx::Class::Schema::Loader v0.07010 @ 2013-02-17 16:15:04
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:Ulh+bL2NSPJo0qWtNss1pA
# You can replace this text with custom code or comments, and it will be preserved on regeneration
1;
t/lib/TestSchema/Sakila/Result/Inventory.pm view on Meta::CPAN
Type: has_many
Related object: L<TestSchema::Sakila::Result::Rental>
=cut
__PACKAGE__->has_many(
"rentals",
"TestSchema::Sakila::Result::Rental",
{ "foreign.inventory_id" => "self.inventory_id" },
{ cascade_copy => 0, cascade_delete => 0 },
);
# Created by DBIx::Class::Schema::Loader v0.07010 @ 2013-02-17 16:15:04
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:oOSD/75feHU/lQ7Op28KYw
# You can replace this text with custom code or comments, and it will be preserved on regeneration
1;
t/lib/TestSchema/Sakila/Result/Language.pm view on Meta::CPAN
Type: has_many
Related object: L<TestSchema::Sakila::Result::Film>
=cut
__PACKAGE__->has_many(
"film_languages",
"TestSchema::Sakila::Result::Film",
{ "foreign.language_id" => "self.language_id" },
{ cascade_copy => 0, cascade_delete => 0 },
);
=head2 film_original_languages
Type: has_many
Related object: L<TestSchema::Sakila::Result::Film>
=cut
__PACKAGE__->has_many(
"film_original_languages",
"TestSchema::Sakila::Result::Film",
{ "foreign.original_language_id" => "self.language_id" },
{ cascade_copy => 0, cascade_delete => 0 },
);
# Created by DBIx::Class::Schema::Loader v0.07010 @ 2013-02-17 16:15:04
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:JK+DOUbIw1Lhrmp6PE2Q4A
# You can replace this text with custom code or comments, and it will be preserved on regeneration
1;
t/lib/TestSchema/Sakila/Result/Rental.pm view on Meta::CPAN
Type: has_many
Related object: L<TestSchema::Sakila::Result::Payment>
=cut
__PACKAGE__->has_many(
"payments",
"TestSchema::Sakila::Result::Payment",
{ "foreign.rental_id" => "self.rental_id" },
{ cascade_copy => 0, cascade_delete => 0 },
);
=head2 staff
Type: belongs_to
Related object: L<TestSchema::Sakila::Result::Staff>
=cut
t/lib/TestSchema/Sakila/Result/Staff.pm view on Meta::CPAN
Type: has_many
Related object: L<TestSchema::Sakila::Result::Payment>
=cut
__PACKAGE__->has_many(
"payments",
"TestSchema::Sakila::Result::Payment",
{ "foreign.staff_id" => "self.staff_id" },
{ cascade_copy => 0, cascade_delete => 0 },
);
=head2 rentals
Type: has_many
Related object: L<TestSchema::Sakila::Result::Rental>
=cut
__PACKAGE__->has_many(
"rentals",
"TestSchema::Sakila::Result::Rental",
{ "foreign.staff_id" => "self.staff_id" },
{ cascade_copy => 0, cascade_delete => 0 },
);
=head2 store
Type: belongs_to
Related object: L<TestSchema::Sakila::Result::Store>
=cut
t/lib/TestSchema/Sakila/Result/Staff.pm view on Meta::CPAN
Type: might_have
Related object: L<TestSchema::Sakila::Result::Store>
=cut
__PACKAGE__->might_have(
"store",
"TestSchema::Sakila::Result::Store",
{ "foreign.manager_staff_id" => "self.staff_id" },
{ cascade_copy => 0, cascade_delete => 0 },
);
# Created by DBIx::Class::Schema::Loader v0.07010 @ 2013-02-17 16:15:04
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:vsAR5vX9nl/POAW1SXr5vA
# You can replace this text with custom code or comments, and it will be preserved on regeneration
1;
t/lib/TestSchema/Sakila/Result/Store.pm view on Meta::CPAN
Type: has_many
Related object: L<TestSchema::Sakila::Result::Customer>
=cut
__PACKAGE__->has_many(
"customers",
"TestSchema::Sakila::Result::Customer",
{ "foreign.store_id" => "self.store_id" },
{ cascade_copy => 0, cascade_delete => 0 },
);
=head2 inventories
Type: has_many
Related object: L<TestSchema::Sakila::Result::Inventory>
=cut
__PACKAGE__->has_many(
"inventories",
"TestSchema::Sakila::Result::Inventory",
{ "foreign.store_id" => "self.store_id" },
{ cascade_copy => 0, cascade_delete => 0 },
);
=head2 staffs
Type: has_many
Related object: L<TestSchema::Sakila::Result::Staff>
=cut
__PACKAGE__->has_many(
"staffs",
"TestSchema::Sakila::Result::Staff",
{ "foreign.store_id" => "self.store_id" },
{ cascade_copy => 0, cascade_delete => 0 },
);
=head2 manager_staff
Type: belongs_to
Related object: L<TestSchema::Sakila::Result::Staff>
=cut
t/lib/TestSchema/Three/Result/Position.pm view on Meta::CPAN
__PACKAGE__->add_columns(
"name" => { data_type => "varchar", is_nullable => 0, size => 32 },
);
__PACKAGE__->set_primary_key("name");
__PACKAGE__->has_many(
"players",
"TestSchema::Three::Result::Player",
{ "foreign.position" => "self.name" },
{ cascade_copy => 0, cascade_delete => 0 },
);
1;
t/lib/TestSchema/Three/Result/Team.pm view on Meta::CPAN
"id" => { data_type => "integer", is_auto_increment => 1, is_nullable => 0 },
"name" => { data_type => "varchar", is_nullable => 0, size => 32 },
);
__PACKAGE__->set_primary_key("id");
__PACKAGE__->has_many(
"players",
"TestSchema::Three::Result::Player",
{ "foreign.team_id" => "self.id" },
{ cascade_copy => 0, cascade_delete => 0 },
);
1;
t/lib/TestSchema/Two/Result/Position.pm view on Meta::CPAN
__PACKAGE__->add_columns(
"name" => { data_type => "varchar", is_nullable => 0, size => 32 },
);
__PACKAGE__->set_primary_key("name");
__PACKAGE__->has_many(
"players",
"TestSchema::Two::Result::Player",
{ "foreign.position" => "self.name" },
{ cascade_copy => 0, cascade_delete => 0 },
);
1;
t/lib/TestSchema/Two/Result/Team.pm view on Meta::CPAN
"id" => { data_type => "integer", is_auto_increment => 1, is_nullable => 0 },
"name" => { data_type => "varchar", is_nullable => 0, size => 32 },
);
__PACKAGE__->set_primary_key("id");
__PACKAGE__->has_many(
"players",
"TestSchema::Two::Result::Player",
{ "foreign.team_id" => "self.id" },
{ cascade_copy => 0, cascade_delete => 0 },
);
1;
t/lib/TestSchema/WackyRels.pm view on Meta::CPAN
__PACKAGE__->table("grade");
__PACKAGE__->add_columns(
"letter" => { data_type => "char", is_nullable => 0, size => 1 },
);
__PACKAGE__->set_primary_key("letter");
__PACKAGE__->has_many(
"things",
"TestSchema::WackyRels::Thing",
{ "foreign.grade" => "self.letter" },
{ cascade_copy => 0, cascade_delete => 0 },
);
};
{
package TestSchema::WackyRels::Size;
use base 'DBIx::Class::Core';
__PACKAGE__->table("size");
__PACKAGE__->add_columns(
"name" => { data_type => "char", is_nullable => 0, size => 32 },
"detail" => { data_type => "varchar", is_nullable => 1, size => 255 },
);
__PACKAGE__->set_primary_key("name");
__PACKAGE__->has_many(
"parents",
"TestSchema::WackyRels::Parent",
{ "foreign.size" => "self.name" },
{ cascade_copy => 0, cascade_delete => 0 },
);
__PACKAGE__->has_many(
"products",
"TestSchema::WackyRels::Product",
{ "foreign.size" => "self.name" },
{ cascade_copy => 0, cascade_delete => 0 },
);
__PACKAGE__->has_many(
"things",
"TestSchema::WackyRels::Thing",
{ "foreign.size" => "self.name" },
{ cascade_copy => 0, cascade_delete => 0 },
);
};
{
package TestSchema::WackyRels::Parent;
use base 'DBIx::Class::Core';
__PACKAGE__->table("parent");
__PACKAGE__->add_columns(
"id" => { data_type => "integer", is_auto_increment => 1, is_nullable => 0 },
t/lib/TestSchema/WackyRels.pm view on Meta::CPAN
{ is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" },
);
__PACKAGE__->has_many(
"children",
"TestSchema::WackyRels::Child",
{
"foreign.color" => "self.color",
"foreign.size" => "self.size",
},
{ cascade_copy => 0, cascade_delete => 0 },
);
};
{
package TestSchema::WackyRels::Child;
use base 'DBIx::Class::Core';
__PACKAGE__->table("child");
__PACKAGE__->add_columns(
"id" => { data_type => "integer", is_auto_increment => 1, is_nullable => 0 },