sub _build_schema {
my ($self) = @_;
require Class::MOP;
- Class::MOP::load_class($self->schema_class);
-
+ {
+ my @include_dirs = @{$self->include_dirs};
+ local @INC = (@include_dirs, @INC);
+ Class::MOP::load_class($self->schema_class);
+ }
$self->connect_info->[3]->{ignore_version} =1;
return $self->schema_class->connect(@{$self->connect_info()} ); # , $self->connect_info->[3], { ignore_version => 1} );
}
+=head2 include_dirs
+
+Extra include directories to look when loading C<schema_class>
+
+=cut
+
+has 'include_dirs' => (
+ is => 'rw',
+ isa => 'ArrayRef',
+ default => sub {[]}
+);
=head2 resultset
=head2 config
-Instead of loading from a file the configuration can be provided directly as a hash ref. Please note
+Instead of loading from a file the configuration can be provided directly as a hash ref. Please note
config_stanza will still be required.
=cut
=back
-L<create> will generate sql for the supplied schema_class in sql_dir. The flavour of sql to
-generate can be controlled by suppling a sqlt_type which should be a L<SQL::Translator> name.
+L<create> will generate sql for the supplied schema_class in sql_dir. The
+flavour of sql to generate can be controlled by supplying a sqlt_type which
+should be a L<SQL::Translator> name.
Arguments for L<SQL::Translator> can be supplied in the sqlt_args hashref.
sub upgrade {
my ($self) = @_;
my $schema = $self->schema();
+
if (!$schema->get_db_version()) {
# schema is unversioned
$schema->throw_exception ("Could not determin current schema version, please either install() or deploy().\n");
} else {
+ $schema->upgrade_directory ($self->sql_dir) if $self->sql_dir; # this will override whatever default the schema has
my $ret = $schema->upgrade();
return $ret;
}
=back
-install is here to help when you want to move to L<DBIx::Class::Schema::Versioned> and have an existing
-database. install will take a version and add the version tracking tables and 'install' the version. No
-further ddl modification takes place. Setting the force attribute to a true value will allow overriding of
+install is here to help when you want to move to L<DBIx::Class::Schema::Versioned> and have an existing
+database. install will take a version and add the version tracking tables and 'install' the version. No
+further ddl modification takes place. Setting the force attribute to a true value will allow overriding of
already versioned databases.
=cut
$version ||= $self->version();
if (!$schema->get_db_version() ) {
# schema is unversioned
- print "Going to install schema version\n";
+ print "Going to install schema version\n" if (!$self->quiet);
my $ret = $schema->install($version);
- print "retun is $ret\n";
+ print "return is $ret\n" if (!$self->quiet);
}
elsif ($schema->get_db_version() and $self->force ) {
carp "Forcing install may not be a good idea";
=back
-deploy will create the schema at the connected database. C<$args> are passed straight to
+deploy will create the schema at the connected database. C<$args> are passed straight to
L<DBIx::Class::Schema/deploy>.
=cut
sub deploy {
my ($self, $args) = @_;
my $schema = $self->schema();
- if (!$schema->get_db_version() ) {
- # schema is unversioned
- $schema->deploy( $args, $self->sql_dir)
- or $schema->throw_exception ("Could not deploy schema.\n"); # FIXME deploy() does not return 1/0 on success/fail
- } else {
- $schema->throw_exception("A versioned schema has already been deployed, try upgrade instead.\n");
- }
+ $schema->deploy( $args, $self->sql_dir );
}
=head2 insert
=back
-select takes the name of a resultset from the schema_class, a where hashref and a attrs to pass to ->search.
+select takes the name of a resultset from the schema_class, a where hashref and a attrs to pass to ->search.
The found data is returned in a array ref where the first row will be the columns list.
=cut
my @data;
my @columns = $resultset->result_source->columns();
- push @data, [@columns];#
+ push @data, [@columns];#
while (my $row = $resultset->next()) {
my @fields;
sub _confirm {
my ($self) = @_;
- print "Are you sure you want to do this? (type YES to confirm) \n";
+
# mainly here for testing
return 1 if ($self->meta->get_attribute('_confirm')->get_value($self));
+
+ print "Are you sure you want to do this? (type YES to confirm) \n";
my $response = <STDIN>;
- return 1 if ($response=~/^YES/);
- return;
+
+ return ($response=~/^YES/);
}
sub _find_stanza {
# must be called on a fresh database
if ($self->get_db_version()) {
- carp 'Install not possible as versions table already exists in database';
+ $self->throw_exception("A versioned schema has already been deployed, try upgrade instead.\n");
}
# default to current version if none passed
['deploy' => 'Deploy the schema to the database',],
['select' => 'Select data from the schema', ],
['insert' => 'Insert data into the schema', ],
- ['update' => 'Update data in the schema', ],
+ ['update' => 'Update data in the schema', ],
['delete' => 'Delete data from the schema',],
['op:s' => 'compatiblity option all of the above can be suppied as --op=<action>'],
['help' => 'display this help', { implies => { schema_class => '__dummy__' } } ],
['force' => 'Be forceful with some operations'],
['trace' => 'Turn on DBIx::Class trace output'],
['quiet' => 'Be less verbose'],
+ ['I:s@' => 'Same as perl\'s -I, prepended to current @INC'],
)
);
);
}
+# FIXME - lowercasing will eventually go away when Getopt::Long::Descriptive is fixed
+if($opts->{i}) {
+ $opts->{include_dirs} = delete $opts->{i};
+}
+
if($opts->{help}) {
$usage->die();
}
if($opts->{connect}) {
$opts->{connect_info} = delete $opts->{connect};
}
-
my $admin = DBIx::Class::Admin->new( %$opts );
-
my $action = $opts->{action};
$action = $opts->{op} if ($action eq 'op');
-print "Performig action $action...\n";
+print "Performing action $action...\n";
my $res = $admin->$action();
if ($action eq 'select') {
no_populate=>1,
sqlite_use_file => 1,
);
+
{ # create the schema
# make sure we are clean
my $admin = DBIx::Class::Admin->new(
schema_class=> "DBICTest::Schema",
sql_dir=> $sql_dir,
- connect_info => \@connect_info,
+ connect_info => \@connect_info,
);
isa_ok ($admin, 'DBIx::Class::Admin', 'create the admin object');
lives_ok { $admin->create('MySQL'); } 'Can create MySQL sql';
lives_ok { $admin->create('SQLite'); } 'Can Create SQLite sql';
+lives_ok {
+ $SIG{__WARN__} = sub { warn @_ unless $_[0] =~ /no such table.+DROP TABLE/s };
+ $admin->deploy()
+} 'Can Deploy schema';
}
{ # upgrade schema
-#my $schema = DBICTest->init_schema(
-# no_deploy => 1,
-# no_populat => 1,
-# sqlite_use_file => 1,
-#);
-
clean_dir($sql_dir);
require DBICVersion_v1;
my $admin = DBIx::Class::Admin->new(
- schema_class => 'DBICVersion::Schema',
+ schema_class => 'DBICVersion::Schema',
sql_dir => $sql_dir,
connect_info => \@connect_info,
);
require DBICVersion_v2;
+DBICVersion::Schema->upgrade_directory (undef); # so that we can test use of $sql_dir
$admin = DBIx::Class::Admin->new(
- schema_class => 'DBICVersion::Schema',
+ schema_class => 'DBICVersion::Schema',
sql_dir => $sql_dir,
connect_info => \@connect_info
);
{
local $SIG{__WARN__} = sub { warn $_[0] unless $_[0] =~ /DB version .+? is lower than the schema version/ };
lives_ok {$admin->upgrade();} 'upgrade the schema';
+ dies_ok {$admin->deploy} 'cannot deploy installed schema, should upgrade instead';
}
is($schema->get_db_version, $DBICVersion::Schema::VERSION, 'Schema and db versions match');
clean_dir($sql_dir);
my $admin = DBIx::Class::Admin->new(
- schema_class => 'DBICVersion::Schema',
+ schema_class => 'DBICVersion::Schema',
sql_dir => $sql_dir,
_confirm => 1,
connect_info => \@connect_info,
}
foreach my $file ($dir->children) {
# skip any hidden files
- next if ($file =~ /^\./);
+ next if ($file =~ /^\./);
unlink $file;
}
}
--- /dev/null
+use strict;
+use warnings;
+
+use Test::More;
+use Test::Exception;
+
+BEGIN {
+ require DBIx::Class;
+ plan skip_all => 'Test needs ' . DBIx::Class::Optional::Dependencies->req_missing_for('admin')
+ unless DBIx::Class::Optional::Dependencies->req_ok_for('admin');
+}
+
+if(use_ok 'DBIx::Class::Admin') {
+ my $admin = DBIx::Class::Admin->new(
+ include_dirs => ['t/lib/testinclude'],
+ schema_class => 'DBICTestAdminInc',
+ config => { DBICTestAdminInc => {} },
+ config_stanza => 'DBICTestAdminInc'
+ );
+ lives_ok { $admin->_build_schema } 'should survive attempt to load module located in include_dirs';
+ {
+ no warnings 'once';
+ ok($DBICTestAdminInc::loaded);
+ }
+}
+
+done_testing;
my @json_backends = qw/XS JSON DWIW/;
my $tests_per_run = 5;
+plan tests => ($tests_per_run * @json_backends) + 1;
-plan tests => $tests_per_run * @json_backends;
+
+# test the script is setting @INC properly
+test_exec (qw| -It/lib/testinclude --schema=DBICTestAdminInc --op=deploy --connect=[] |);
+cmp_ok ( $? >> 8, '==', 70, 'Correct exit code from deploying a custom INC schema' );
for my $js (@json_backends) {
my $employees = $schema->resultset('Employee');
- system( _prepare_system_args( qw|--op=insert --set={"name":"Matt"}| ) );
+ test_exec( default_args(), qw|--op=insert --set={"name":"Matt"}| );
ok( ($employees->count()==1), "$ENV{JSON_ANY_ORDER}: insert count" );
my $employee = $employees->find(1);
ok( ($employee->name() eq 'Matt'), "$ENV{JSON_ANY_ORDER}: insert valid" );
- system( _prepare_system_args( qw|--op=update --set={"name":"Trout"}| ) );
+ test_exec( default_args(), qw|--op=update --set={"name":"Trout"}| );
$employee = $employees->find(1);
ok( ($employee->name() eq 'Trout'), "$ENV{JSON_ANY_ORDER}: update" );
- system( _prepare_system_args( qw|--op=insert --set={"name":"Aran"}| ) );
+ test_exec( default_args(), qw|--op=insert --set={"name":"Aran"}| );
SKIP: {
skip ("MSWin32 doesn't support -| either", 1) if $^O eq 'MSWin32';
- open(my $fh, "-|", _prepare_system_args( qw|--op=select --attrs={"order_by":"name"}| ) ) or die $!;
+ open(my $fh, "-|", ( 'script/dbicadmin', default_args(), qw|--op=select --attrs={"order_by":"name"}| ) ) or die $!;
my $data = do { local $/; <$fh> };
close($fh);
if (!ok( ($data=~/Aran.*Trout/s), "$ENV{JSON_ANY_ORDER}: select with attrs" )) {
};
}
- system( _prepare_system_args( qw|--op=delete --where={"name":"Trout"}| ) );
+ test_exec( default_args(), qw|--op=delete --where={"name":"Trout"}| );
ok( ($employees->count()==1), "$ENV{JSON_ANY_ORDER}: delete" );
}
+sub default_args {
+ return (
+ qw|--quiet --schema=DBICTest::Schema --class=Employee|,
+ q|--connect=["dbi:SQLite:dbname=t/var/DBIxClass.db","","",{"AutoCommit":1}]|,
+ qw|--force -I testincludenoniterference|,
+ );
+}
+
# Why do we need this crap? Apparently MSWin32 can not pass through quotes properly
# (sometimes it will and sometimes not, depending on what compiler was used to build
# perl). So we go the extra mile to escape all the quotes. We can't also use ' instead
# of ", because JSON::XS (proudly) does not support "malformed JSON" as the author
# calls it. Bleh.
#
-sub _prepare_system_args {
- my $perl = $^X;
-
- my @args = (
- qw|script/dbicadmin --quiet --schema=DBICTest::Schema --class=Employee|,
- q|--connect=["dbi:SQLite:dbname=t/var/DBIxClass.db","","",{"AutoCommit":1}]|,
- qw|--force|,
- @_,
- );
-
- if ( $^O eq 'MSWin32' ) {
- $perl = qq|"$perl"|; # execution will fail if $^X contains paths
- for (@args) {
- $_ =~ s/"/\\"/g;
- }
+sub test_exec {
+ my $perl = $^X;
+
+ my @args = ('script/dbicadmin', @_);
+
+ if ( $^O eq 'MSWin32' ) {
+ $perl = qq|"$perl"|; # execution will fail if $^X contains paths
+ for (@args) {
+ $_ =~ s/"/\\"/g;
}
+ }
- return ($perl, @args);
+ system ($perl, @args);
}
__PACKAGE__->register_class('Table', 'DBICVersion::Table');
__PACKAGE__->load_components('+DBIx::Class::Schema::Versioned');
-
-sub upgrade_directory
-{
- return 't/var/';
-}
+__PACKAGE__->upgrade_directory('t/var/');
sub ordered_schema_versions {
return('1.0','2.0','3.0');
__PACKAGE__->upgrade_directory('t/var/');
__PACKAGE__->backup_directory('t/var/backup/');
-#sub upgrade_directory
-#{
-# return 't/var/';
-#}
-
1;
--- /dev/null
+package DBICTestAdminInc;
+use base 'DBIx::Class::Schema';
+
+our $loaded = 1;
+sub connect { bless {}, __PACKAGE__ }
+
+sub deploy { exit 70 } # this is what the test will expect to see
+
+1;