aherzog: Adam Herzog <adam@herzogdesigns.com>
+amiri: Amiri Barksdale <amiri@metalabel.com>
+
amoore: Andrew Moore <amoore@cpan.org>
andyg: Andy Grundman <andy@hybridized.org>
use warnings;
use DBIx::Class::ResultSet;
+use SQL::Translator::Parser::DBIx::Class;
+use Data::Dumper::Concise;
use base qw/DBIx::Class/;
__PACKAGE__->load_components(qw/ResultSource/);
__PACKAGE__->mk_group_accessors(
- 'simple' => qw(is_virtual view_definition)
-);
+ 'simple' => qw(is_virtual view_definition deploy_depends_on) );
=head1 NAME
An SQL query for your view. Will not be translated across database
syntaxes.
+=head2 deploy_depends_on
+
+ __PACKAGE__->result_source_instance->deploy_depends_on(
+ "MyDB::Schema::Result::Year","MyDB::Schema::Result::CD"
+ );
+
+Specify the result classes that comprise this view. Pass this
+method a list.
=head1 OVERRIDDEN METHODS
+=head2 new
+
+The constructor. This is a private method, as only other DBIC modules
+should call this.
+
+=cut
+
+sub new {
+ my ( $self, @args ) = @_;
+ my $new = $self->next::method(@args);
+ $new->{deploy_depends_on}
+ = { map { $_->result_source_instance->name => 1 } @{ $new->{deploy_depends_on}||[] } }
+ unless ref $new->{deploy_depends_on} eq 'HASH';
+ return $new;
+}
+
=head2 from
Returns the FROM entry for the table (i.e. the view name)
=cut
sub from {
- my $self = shift;
- return \"(${\$self->view_definition})" if $self->is_virtual;
- return $self->name;
+ my $self = shift;
+ return \"(${\$self->view_definition})" if $self->is_virtual;
+ return $self->name;
}
+=head1 PRIVATE METHODS
+
+=head2 deploy_depends_on
+
+An internal method for the construction of a hashref of the view's
+superclasses, e.g., the sources that comprise it.
+
+=cut
+
1;
=head1 AUTHORS
Wallace Reis <wreis@cpan.org>
+Amiri Barksdale <amiri@metalabel.com>
+
=head1 LICENSE
You may distribute this code under the same terms as Perl itself.
my $dependencies = {
map { $_ => _resolve_deps ($_, \%tables) } (keys %tables)
};
+
for my $table (sort
{
keys %{$dependencies->{$a} || {} } <=> keys %{ $dependencies->{$b} || {} }
}
my %views;
- foreach my $moniker (sort keys %view_monikers)
+
+ my @view_sources =
+ sort {
+ keys %{ $dependencies->{$a} || {} }
+ <=>
+ keys %{ $dependencies->{$b} || {} }
+ ||
+ $a cmp $b
+ }
+ map { $dbicschema->source($_) }
+ keys %view_monikers;
+
+ foreach my $source (@view_sources)
{
- my $source = $dbicschema->source($moniker);
my $view_name = $source->name;
# FIXME - this isn't the right way to do it, but sqlt does not
--- /dev/null
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Test::More;
+use Test::Exception;
+use lib qw(t/lib);
+use ViewDeps;
+
+BEGIN {
+ use_ok('DBIx::Class::ResultSource::View');
+}
+
+### SANITY
+
+my $view = DBIx::Class::ResultSource::View->new( { name => 'Quux' } );
+
+isa_ok( $view, 'DBIx::Class::ResultSource', 'A new view' );
+isa_ok( $view, 'DBIx::Class', 'A new view also' );
+
+can_ok( $view, $_ ) for qw/new from deploy_depends_on/;
+
+### DEPS
+
+my $schema = ViewDeps->connect;
+ok( $schema, 'Connected to ViewDeps schema OK' );
+
+
+my $bar_rs = $schema->resultset('Bar');
+
+my @bar_deps
+ = keys %{ $schema->resultset('Bar')->result_source->deploy_depends_on };
+
+my @foo_deps
+ = keys %{ $schema->resultset('Foo')->result_source->deploy_depends_on };
+
+isa_ok( $schema->resultset('Bar')->result_source,
+ 'DBIx::Class::ResultSource::View', 'Bar' );
+
+is( $bar_deps[0], 'baz', 'which is reported to depend on baz...' );
+is( $bar_deps[1], 'mixin', 'and on mixin.' );
+is( $foo_deps[0], undef, 'Foo has no dependencies...' );
+
+isa_ok(
+ $schema->resultset('Foo')->result_source,
+ 'DBIx::Class::ResultSource::View',
+ 'though Foo'
+);
+isa_ok(
+ $schema->resultset('Baz')->result_source,
+ 'DBIx::Class::ResultSource::Table',
+ "Baz on the other hand"
+);
+dies_ok {
+ ViewDeps::Result::Baz->result_source_instance
+ ->deploy_depends_on("ViewDeps::Result::Mixin");
+}
+"...and you cannot use deploy_depends_on with that";
+
+is(ViewDeps->source('Foo')->view_definition, $schema->resultset('Bar')->result_source->view_definition, "Package Foo's view definition is equivalent to resultset Bar's view definition");
+
+my $dir = "t/sql";
+$schema->create_ddl_dir( ['PostgreSQL','SQLite'], 0.1, $dir );
+
+done_testing;
--- /dev/null
+package # hide from PAUSE
+ ViewDeps;
+## Used in 105view_deps.t
+
+use strict;
+use warnings;
+use parent qw(DBIx::Class::Schema);
+
+__PACKAGE__->load_namespaces;
+
+1;
--- /dev/null
+package # hide from PAUSE
+ ViewDeps::Result::Bar;
+
+use strict;
+use warnings;
+use base qw/ViewDeps::Result::Foo/;
+
+require ViewDeps::Result::Mixin;
+
+__PACKAGE__->table('bar');
+
+__PACKAGE__->result_source_instance->deploy_depends_on(
+ ["ViewDeps::Result::Mixin", "ViewDeps::Result::Baz"] );
+
+__PACKAGE__->add_columns( b => { data_type => 'integer' } );
+
+__PACKAGE__->belongs_to(
+ 'table',
+ 'ViewDeps::Result::JustATable',
+ { 'foreign.id' => 'self.b' },
+);
+
+__PACKAGE__->has_many( 'foos', 'ViewDeps::Result::Foo',
+ { 'foreign.id' => 'self.id' } );
+
+1;
--- /dev/null
+package # hide from PAUSE
+ ViewDeps::Result::Baz;
+## Used in 105view_deps.t
+
+use strict;
+use warnings;
+use base qw(DBIx::Class::Core);
+
+__PACKAGE__->table('baz');
+
+__PACKAGE__->add_columns( id => { data_type => 'integer' } );
+
+__PACKAGE__->belongs_to(
+ 'table',
+ 'ViewDeps::Result::JustATable',
+ { 'foreign.id' => 'self.b' },
+);
+
+__PACKAGE__->has_many( 'foos', 'ViewDeps::Result::Foo',
+ { 'foreign.a' => 'self.id' } );
+
+1;
--- /dev/null
+package # hide from PAUSE
+ ViewDeps::Result::Foo;
+
+use strict;
+use warnings;
+use base qw(ViewDeps::Result::Quux);
+
+__PACKAGE__->table_class('DBIx::Class::ResultSource::View');
+__PACKAGE__->table('foo');
+
+__PACKAGE__->result_source_instance->view_definition(
+ "select * from just_a_table");
+
+__PACKAGE__->add_columns(
+ id => { data_type => 'integer', is_auto_increment => 1 },
+ a => { data_type => 'integer', is_nullable => 1 }
+);
+
+__PACKAGE__->set_primary_key('id');
+
+__PACKAGE__->belongs_to( 'bar', 'ViewDeps::Result::Bar',
+ { 'foreign.id' => 'self.a' } );
+
+1;
--- /dev/null
+package # hide from PAUSE
+ ViewDeps::Result::JustATable;
+## Used in 105view_deps.t
+
+use base qw(DBIx::Class::Core);
+
+__PACKAGE__->table('just_a_table');
+
+__PACKAGE__->add_columns(
+ id => { data_type => 'integer', is_auto_increment => 1 },
+ name => { data_type => 'varchar', size => 255 }
+);
+
+__PACKAGE__->set_primary_key('id');
+
+__PACKAGE__->has_many( 'bars', 'ViewDeps::Result::Bar',
+ { 'foreign.b' => 'self.id' } );
+
+1;
--- /dev/null
+package # hide from PAUSE
+ ViewDeps::Result::Mixin;
+## Used in 105view_deps.t
+
+use strict;
+use warnings;
+use base qw(DBIx::Class::Core);
+
+__PACKAGE__->table('mixin');
+
+__PACKAGE__->add_columns(
+ id => {
+ data_type => 'integer', is_auto_increment => 1, sequence => 'foo_id_seq'
+ },
+ words => { data_type => 'text' }
+);
+
+__PACKAGE__->set_primary_key('id');
+
+1;
--- /dev/null
+package # hide from PAUSE
+ ViewDeps::Result::Quux;
+
+use strict;
+use warnings;
+use base qw(DBIx::Class::Core);
+
+__PACKAGE__->table_class('DBIx::Class::ResultSource::View');
+__PACKAGE__->table('quux');
+
+__PACKAGE__->result_source_instance->view_definition(
+ "select * from quux");
+
+__PACKAGE__->add_columns(
+ etc => { data_type => 'text' },
+ c => { data_type => 'integer', is_nullable => 1 }
+);
+
+__PACKAGE__->set_primary_key('c');
+
+__PACKAGE__->belongs_to( 'foo', 'ViewDeps::Result::Foo',
+ { 'foreign.a' => 'self.c' } );
+
+1;