DBIx-RunSQL-0.25/0000755000175000017500000000000014657430674012734 5ustar corioncorionDBIx-RunSQL-0.25/README0000644000175000017500000000213114657430673013610 0ustar corioncorionDBIx::RunSQL - run SQL from a file INSTALLATION This is a Perl module distribution. It should be installed with whichever tool you use to manage your installation of Perl, e.g. any of cpanm . cpan . cpanp -i . Consult https://www.cpan.org/modules/INSTALL.html for further instruction. Should you wish to install this module manually, the procedure is perl Makefile.PL make make test make install REPOSITORY The public repository of this module is L. SUPPORT The public support forum of this module is L. BUG TRACKER Please report bugs in this module via the RT CPAN bug queue at L or via mail to L. SEE ALSO L L - SQLite setup/teardown for tests, mostly geared towards testing, not general database setup AUTHOR Max Maischein C LICENSE This module is released under the same terms as Perl itself. COPYRIGHT (c) Copyright 2009-2021 by Max Maischein C. DBIx-RunSQL-0.25/t/0000755000175000017500000000000014657430674013177 5ustar corioncorionDBIx-RunSQL-0.25/t/06-quiet.t0000644000175000017500000000232714657430673014741 0ustar corioncorion#!perl -w use strict; use Test::More; use DBIx::RunSQL; use Data::Dumper; # Test against a "real" database if we have one: if( ! eval { require DBD::SQLite; require 5.008; # for scalar open 1; }) { plan skip_all => $@; exit; }; plan tests => 2; # Redirect STDOUT to a variable close STDOUT; # sssh open STDOUT, '>', \my $output; my $exitcode = DBIx::RunSQL->handle_command_line( "my-test-app", [ '--quiet', '--dsn' => 'dbi:SQLite:dbname=:memory:', '--sql' => <<'SQL', create table foo (bar integer, baz varchar); insert into foo (bar,baz) values (1,'hello'); insert into foo (bar,baz) values (2,'world'); select * from foo; SQL ] ); isnt $output, '', "We get output if rows are found"; $output = ''; $exitcode = DBIx::RunSQL->handle_command_line( "my-test-app", [ '--quiet', '--dsn' => 'dbi:SQLite:dbname=:memory:', '--sql' => <<'SQL', create table foo (bar integer, baz varchar); insert into foo (bar,baz) values (1,'hello'); insert into foo (bar,baz) values (2,'world'); select * from foo where 1=0; SQL ] ); is $output, '', "We get no output if no rows are found"; done_testing(); DBIx-RunSQL-0.25/t/trigger.sql0000644000175000017500000000077314657430673015371 0ustar corioncorion-- This commented-out statement will not get passed through; -- SECRET PRAGMA #foo will get passed through with the next statement create table test ( id integer unique not null, descr text default '', ts text ); CREATE TRIGGER trg_test_1 AFTER INSERT ON test BEGIN UPDATE test SET ts = DATETIME('NOW') WHERE rowid = new.rowid; END; CREATE TRIGGER trg_test_2 AFTER INSERT ON test BEGIN UPDATE test SET ts = DATETIME('NOW') WHERE rowid = new.rowid; END; DBIx-RunSQL-0.25/t/01-force.t0000644000175000017500000000150114657430673014674 0ustar corioncorion#!perl -w use strict; use Test::More; use DBIx::RunSQL; my $can_run = eval { require DBD::SQLite; 1 }; if (not $can_run) { plan skip_all => "SQLite not installed"; } plan tests => 5; my $warn; local $SIG{__WARN__} = sub { $warn = shift }; my $lives = eval { my $test_dbh = DBIx::RunSQL->create( dsn => 'dbi:SQLite:dbname=:memory:', sql => $0, ); 1; }; my $err = $@; ok !$lives, "We die on invalid SQL"; isnt $@, '', "We die with some error message"; $lives = eval { my $test_dbh = DBIx::RunSQL->create( dsn => 'dbi:SQLite:dbname=:memory:', sql => $0, force => 1, ); 1; }; $err = $@; ok $lives, "We can force invalid SQL"; is $@, '', "We don't die with some error message"; like $warn, qr/SQL ERROR/, "We still warn about SQL errors"; DBIx-RunSQL-0.25/t/00-use.t0000644000175000017500000000011014657430673014364 0ustar corioncorion#!perl -w use strict; use Test::More tests => 1; use_ok 'DBIx::RunSQL';DBIx-RunSQL-0.25/t/05-select.t0000644000175000017500000000370514657430673015071 0ustar corioncorion#!perl -w use strict; use Test::More; use DBIx::RunSQL; my $can_run = eval { require DBD::SQLite; 1 }; if (not $can_run) { plan skip_all => "SQLite not installed"; exit; } plan tests => 10; my $sql= <<'SQL'; create table foo ( name varchar(64) , age decimal(4) ); insert into foo (name,age) values ('bar',100); insert into foo (name,age) values ('baz',1); insert into foo (name,age) values ('Some loong string',1000); insert into foo (name,age) values ('No age',null); SQL my $test_dbh = DBIx::RunSQL->create( dsn => 'dbi:SQLite:dbname=:memory:', sql => \$sql, ); my $sth= $test_dbh->prepare(<<'SQL'); select * from foo; SQL $sth->execute; my $result= DBIx::RunSQL->format_results( sth => $sth ); isnt $result, undef, "We got some kind of result"; like $result, qr/\bname\b.*?\bage\b/m, "Things that look like 'name' and 'age' appear in the string"; like $result, qr/\bbar\b.*?\b100\b/m, "Things that look like 'bar' and '100' appear in the string"; $sth= $test_dbh->prepare(<<'SQL'); select * from foo where 1=0; SQL $sth->execute; $result= DBIx::RunSQL->format_results( sth => $sth ); isnt $result, undef, "We got some kind of result"; like $result, qr/\bname\b.*?\bage\b/m, "An empty resultset still outputs the column titles"; unlike $result, qr/\bbar\b.*?\b100\b/m, "(but obviously, no values)"; my $sth= $test_dbh->prepare(<<'SQL'); select * from foo order by name, age; SQL $sth->execute; my $result= DBIx::RunSQL->format_results( sth => $sth, rotate => 1 ); isnt $result, undef, "We got some kind of result"; like $result, qr/\bname\b.*?\bbar\s+baz\b/m, "The name row exists"; like $result, qr/\bage\b.*?\b100\b\s+1\b/m, "The age row exists"; my $sth= $test_dbh->prepare(<<'SQL'); select * from foo where age is null SQL $sth->execute; my $result= DBIx::RunSQL->format_results( sth => $sth, null => '' ); like $result, qr//m, "We can set custom strings for NULL"; DBIx-RunSQL-0.25/t/rt77378.sql0000644000175000017500000000053214657430673014764 0ustar corioncorionCREATE TABLE user ( id INTEGER PRIMARY KEY, name VARCHAR(255) ); CREATE TABLE emails ( uid INTEGER NOT NULL, name VARCHAR(255) UNIQUE NOT NULL, FOREIGN KEY (uid) REFERENCES user(id) ); CREATE TRIGGER user_cleanup BEFORE DELETE ON user FOR EACH ROW BEGIN DELETE FROM email WHERE uid=OLD.id; END;DBIx-RunSQL-0.25/t/02-trigger.t0000644000175000017500000000070414657430673015246 0ustar corioncorion#!perl -w use strict; use Test::More; use DBIx::RunSQL; my $can_run = eval { require DBD::SQLite; 1 }; if (not $can_run) { plan skip_all => "SQLite not installed"; } plan tests => 1; my $lives = eval { my $test_dbh = DBIx::RunSQL->create( dsn => 'dbi:SQLite:dbname=:memory:', sql => 't/trigger.sql', #verbose => 1, ); 1; }; my $err = $@; ok $lives, "We can parse triggers" or diag $err; DBIx-RunSQL-0.25/t/rt77378.t0000644000175000017500000000067314657430673014436 0ustar corioncorion#!perl -w use strict; use Test::More; use DBIx::RunSQL; my $can_run = eval { require DBD::SQLite; 1 }; if (not $can_run) { plan skip_all => "SQLite not installed"; } plan tests => 1; my $dsn = 'dbi:SQLite:dbname=:memory:'; my $lives = eval { DBIx::RunSQL->create( verbose => 0, dsn => $dsn, sql => 't/rt77378.sql', ); 1 }; ok $lives, "We can parse triggers (RT 77378)" or diag $@;DBIx-RunSQL-0.25/t/04-handle-parameters.t0000644000175000017500000000341314657430673017201 0ustar corioncorion#!perl -w use strict; use Test::More tests => 7; use DBIx::RunSQL; use Data::Dumper; my $have_scalar_open = eval { require 5.008; # for scalar open require DBD::SQLite; 1; }; my @received; { no warnings 'redefine'; sub DBIx::RunSQL::create { @received= @_; }; }; DBIx::RunSQL->handle_command_line( "my-test-app", ); my ($package,%options)= @received; is $options{ dsn }, "dbi:SQLite:dbname=db/my-test-app.sqlite", "DSN gets appname used as default"; DBIx::RunSQL->handle_command_line( "my-test-app", ['--dsn' => 'dbi:Magic:'], ); ($package,%options)= @received; is $options{ dsn }, "dbi:Magic:", "DSN gets passed through"; # Test the invocation styles for SQL DBIx::RunSQL->handle_command_line( "my-test-app", ['--sql' => 'sql 1', "some more stuff that's ignored"], ); ($package,%options)= @received; is ${$options{ sql }}, "sql 1", "Explicit SQL gets returned"; DBIx::RunSQL->handle_command_line( "my-test-app", ['--', 'sql 2 on command line'], ); ($package,%options)= @received; is ${$options{ sql }}, "sql 2 on command line", "SQL on the command line gets returned"; SKIP: { if( ! $have_scalar_open ) { skip "No scalar open on this version of Perl", 3; }; { open *STDIN, '<', \'sql from STDIN'; DBIx::RunSQL->handle_command_line( "my-test-app", ['--'], ); ($package,%options)= @received; }; ok !$options{ sql }, "We got no SQL string"; ok $options{ fh }, "We'll read sql from STDIN"; { open *STDIN, '<', \'sql from STDIN 2'; DBIx::RunSQL->handle_command_line( "my-test-app", ['--', "some SQL"], ); ($package,%options)= @received; }; is ${$options{ sql }}, "some SQL", "We don't read from STDIN if we get other stuff"; }; DBIx-RunSQL-0.25/t/03-comment.t0000644000175000017500000000111514657430673015243 0ustar corioncorion#!perl -w use strict; use Test::More; use DBIx::RunSQL; my $can_run = eval { require DBD::SQLite; 1 }; if (not $can_run) { plan skip_all => "SQLite not installed"; } plan tests => 2; my @statements; my $test_dbh = DBIx::RunSQL->create( dsn => 'dbi:SQLite:dbname=:memory:', sql => 't/trigger.sql', verbose_handler => sub { push @statements, $_[0] }, verbose => 1, ); unlike $statements[0], qr/commented-out/, "Commented out things that look like statements get filtered"; like $statements[0], qr/-- SECRET PRAGMA #foo/, "Comments survive parsing"; DBIx-RunSQL-0.25/t/formatter.t0000644000175000017500000000220514657430673015365 0ustar corioncorion#!perl -w use strict; use Test::More; use DBIx::RunSQL; my $can_run = eval { require Text::Table; require DBD::SQLite; 1 }; if (not $can_run) { plan skip_all => "Test prerequisite modules not installed: $@"; exit; }; plan tests => 1; my $sql= <<'SQL'; create table foo ( name varchar(64) , age decimal(4) ); insert into foo (name,age) values ('bar',100); insert into foo (name,age) values ('baz',1); SQL my $test_dbh = DBIx::RunSQL->create( dsn => 'dbi:SQLite:dbname=:memory:', sql => \$sql, ); my $sth= $test_dbh->prepare(<<'SQL'); select * from foo order by name; SQL $sth->execute; my $result= DBIx::RunSQL->format_results( sth => $sth, formatter => 'Text::Table::JIRA' ); is_deeply [split /\r?\n/, $result], ['||name||age||', '| bar | 100| ', '| baz | 1| ', ] ; package Text::Table::JIRA; use strict; our @ISA; require Text::Table; BEGIN { @ISA = 'Text::Table'; } sub new { my( $class, @headers ) = @_; my $sep = { is_sep => 1, title => '||', body => '| ', }; @headers = ($sep, map { $_, $sep, } @headers); $class->SUPER::new( @headers ) } DBIx-RunSQL-0.25/t/05-output-bool.t0000644000175000017500000000151714657430673016102 0ustar corioncorion#!perl -w use strict; use Test::More; use DBIx::RunSQL; use Data::Dumper; # Test against a "real" database if we have one: if( ! eval { require DBD::SQLite; require 5.008; # for scalar open 1; }) { plan skip_all => $@; exit; }; plan tests => 1; # Redirect STDOUT to a variable close STDOUT; # shhh open STDOUT, '>', \my $output; my $exitcode = DBIx::RunSQL->handle_command_line( "my-test-app", [ '--bool', '--dsn' => 'dbi:SQLite:dbname=:memory:', '--sql' => <<'SQL', create table foo (bar integer, baz varchar); insert into foo (bar,baz) values (1,'hello'); insert into foo (bar,baz) values (2,'world'); select * from foo; SQL ] ); is $exitcode, 1, "We get a nonzero exit code if a row gets selected with --bool" or diag $output; done_testing();DBIx-RunSQL-0.25/t/rt115442.t0000644000175000017500000000050014657430673014464 0ustar corioncorion#!perl -w use strict; use Test::More; use Data::Dumper; use DBIx::RunSQL; plan tests => 1; my @statements = DBIx::RunSQL->split_sql(<<'SQL'); DROP TABLE IF EXISTS player1; DROP TABLE IF EXISTS player2; SQL is scalar( @statements ), 2, "Trailing whitespace is allowed in statements" or diag Dumper \@statements; DBIx-RunSQL-0.25/Makefile.PL0000644000175000017500000001616714657430673014720 0ustar corioncorion# -*- mode: perl; c-basic-offset: 4; indent-tabs-mode: nil; -*- use strict; use ExtUtils::MakeMaker qw(WriteMakefile); # See lib/ExtUtils/MakeMaker.pm for details of how to influence # the contents of the Makefile that is written. # Normalize version strings like 6.30_02 to 6.3002, # so that we can do numerical comparisons on it. my $eumm_version = $ExtUtils::MakeMaker::VERSION; $eumm_version =~ s/_//; my $module = 'DBIx::RunSQL'; (my $main_file = "lib/$module.pm" ) =~ s!::!/!g; (my $distbase = $module) =~ s!::!-!g; my $distlink = $distbase; my @tests = map { glob $_ } 't/*.t', 't/*/*.t'; my %module = ( NAME => $module, AUTHOR => q{Max Maischein }, VERSION_FROM => $main_file, ABSTRACT_FROM => $main_file, META_MERGE => { "meta-spec" => { version => 2 }, resources => { repository => { web => "https://github.com/Corion/$distlink", url => "git://github.com/Corion/$distlink.git", type => 'git', }, bugtracker => { web => 'https://rt.cpan.org/Public/Dist/Display.html?Name='.$distbase, mailto => $distbase.'-bugs@rt.cpan.org', }, license => ['https://dev.perl.org/licenses/'], }, dynamic_config => 0, # we promise to keep META.* up-to-date x_static_install => 1, # we are pure Perl and don't do anything fancy }, MIN_PERL_VERSION => '5.010', 'EXE_FILES' => [ 'bin/run-sql.pl', ], 'LICENSE'=> 'perl', PL_FILES => {}, BUILD_REQUIRES => { 'ExtUtils::MakeMaker' => 0, }, 'PREREQ_PM' => { 'strict' => 0, 'warnings' => 0, 'Getopt::Long' => '2.36', # GetOptionsFromArray 'DBI' => 0, 'Module::Load' => 0, }, # e.g., Module::Name => 1.1 TEST_REQUIRES => { 'Test::More' => 0, 'Data::Dumper' => 0, }, dist => { COMPRESS => 'gzip -9f', SUFFIX => 'gz', }, clean => { FILES => "$distbase-*" }, test => { TESTS => join( ' ', @tests ) }, ); # This is so that we can do # require 'Makefile.PL' # and then call get_module_info sub get_module_info { %module } if( ! caller ) { # I should maybe use something like Shipwright... regen_README($main_file); regen_EXAMPLES() if -d 'examples'; WriteMakefile1(get_module_info); }; 1; sub WriteMakefile1 { #Written by Alexandr Ciornii, version 0.21. Added by eumm-upgrade. my %params=@_; my $eumm_version=$ExtUtils::MakeMaker::VERSION; $eumm_version=eval $eumm_version; die "EXTRA_META is deprecated" if exists $params{EXTRA_META}; die "License not specified" if not exists $params{LICENSE}; if ($params{BUILD_REQUIRES} and $eumm_version < 6.5503) { #EUMM 6.5502 has problems with BUILD_REQUIRES $params{PREREQ_PM}={ %{$params{PREREQ_PM} || {}} , %{$params{BUILD_REQUIRES}} }; delete $params{BUILD_REQUIRES}; } if ($params{TEST_REQUIRES} and $eumm_version < 6.64) { $params{PREREQ_PM}={ %{$params{PREREQ_PM} || {}} , %{$params{TEST_REQUIRES}} }; delete $params{TEST_REQUIRES}; } delete $params{CONFIGURE_REQUIRES} if $eumm_version < 6.52; delete $params{MIN_PERL_VERSION} if $eumm_version < 6.48; delete $params{META_MERGE} if $eumm_version < 6.46; delete $params{META_ADD} if $eumm_version < 6.46; delete $params{LICENSE} if $eumm_version < 6.31; delete $params{AUTHOR} if $] < 5.005; delete $params{ABSTRACT_FROM} if $] < 5.005; delete $params{BINARY_LOCATION} if $] < 5.005; WriteMakefile(%params); } sub regen_README { # README is the short version that just tells people what this is # and how to install it eval { # Get description my $readme = join "\n", pod_section($_[0], 'NAME', 'no heading' ), pod_section($_[0], 'DESCRIPTION' ), <new(); # Read POD from Module.pm and write to README $parser->parse_from_file($_[0]); my $readme_mkdn = <as_markdown; [![Travis Build Status](https://travis-ci.org/Corion/$distlink.svg?branch=master)](https://travis-ci.org/Corion/$distlink) [![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/github/Corion/$distlink?branch=master&svg=true)](https://ci.appveyor.com/project/Corion/$distlink) STATUS update_file( 'README.mkdn', $readme_mkdn ); }; } sub pod_section { my( $filename, $section, $remove_heading ) = @_; open my $fh, '<', $filename or die "Couldn't read '$filename': $!"; my @section = grep { /^=head1\s+$section/.../^=/ } <$fh>; # Trim the section if( @section ) { pop @section if $section[-1] =~ /^=/; shift @section if $remove_heading; pop @section while $section[-1] =~ /^\s*$/; shift @section while $section[0] =~ /^\s*$/; }; @section = map { $_ =~ s!^=\w+\s+!!; $_ } @section; return join "", @section; } sub regen_EXAMPLES { my $perl = $^X; if ($perl =~/\s/) { $perl = qq{"$perl"}; }; (my $example_file = $main_file) =~ s!\.pm$!/Examples.pm!; my $examples = `$perl -w examples/gen_examples_pod.pl`; if ($examples) { warn "(Re)Creating $example_file\n"; $examples =~ s/\r\n/\n/g; update_file( $example_file, $examples ); }; }; sub update_file { my( $filename, $new_content ) = @_; my $content; if( -f $filename ) { open my $fh, '<', $filename or die "Couldn't read '$filename': $!"; binmode $fh; local $/; $content = <$fh>; }; if( $content ne $new_content ) { if( open my $fh, '>', $filename ) { binmode $fh; print $fh $new_content; } else { warn "Couldn't (re)write '$filename': $!"; }; }; } 1; DBIx-RunSQL-0.25/META.json0000644000175000017500000000317214657430674014360 0ustar corioncorion{ "abstract" : "run SQL from a file", "author" : [ "Max Maischein " ], "dynamic_config" : 0, "generated_by" : "ExtUtils::MakeMaker version 7.64, CPAN::Meta::Converter version 2.150010", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "DBIx-RunSQL", "no_index" : { "directory" : [ "t", "inc" ] }, "prereqs" : { "build" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "runtime" : { "requires" : { "DBI" : "0", "Getopt::Long" : "2.36", "Module::Load" : "0", "perl" : "5.010", "strict" : "0", "warnings" : "0" } }, "test" : { "requires" : { "Data::Dumper" : "0", "Test::More" : "0" } } }, "release_status" : "stable", "resources" : { "bugtracker" : { "mailto" : "DBIx-RunSQL-bugs@rt.cpan.org", "web" : "https://rt.cpan.org/Public/Dist/Display.html?Name=DBIx-RunSQL" }, "license" : [ "https://dev.perl.org/licenses/" ], "repository" : { "type" : "git", "url" : "git://github.com/Corion/DBIx-RunSQL.git", "web" : "https://github.com/Corion/DBIx-RunSQL" } }, "version" : "0.25", "x_serialization_backend" : "JSON::PP version 4.07", "x_static_install" : 1 } DBIx-RunSQL-0.25/bin/0000755000175000017500000000000014657430674013504 5ustar corioncorionDBIx-RunSQL-0.25/bin/run-sql.pl0000644000175000017500000000240714657430673015444 0ustar corioncorion#!/usr/bin/perl -w use strict; use warnings; use DBIx::RunSQL; our $VERSION = '0.25'; my $exitcode = DBIx::RunSQL->handle_command_line('myapp', \@ARGV); exit $exitcode; =head1 NAME run-db.pl - Run SQL =head1 SYNOPSIS run-sql.pl "select * from mytable where 1=0" run-sql.pl --sql create-table.sql echo "select * from mytable where 1=0" | run-sql.pl =head1 ABSTRACT This sets up the database. The following options are recognized: =head1 OPTIONS =over 4 =item C<--user> USERNAME =item C<--password> PASSWORD =item C<--dsn> DSN The DBI DSN to use for connecting to the database =item C<--sql> SQLFILE The alternative SQL file to use instead of what is passed on the command line. =item C<--quiet> Output no headers for empty SELECT resultsets =item C<--bool> Set the exit code to 1 if at least one result row was found =item C<--string> Output the (single) column that the query returns as a string without any headers =item C<--format> formatter Use a different formatter for table output. Supported formatters are tab - output results as tab delimited columns Text::Table - output results as ASCII table Text::Table::Any - output results as various formats =item C<--force> Don't stop on errors =item C<--help> Show this message. =back =cut DBIx-RunSQL-0.25/lib/0000755000175000017500000000000014657430674013502 5ustar corioncorionDBIx-RunSQL-0.25/lib/DBIx/0000755000175000017500000000000014657430674014270 5ustar corioncorionDBIx-RunSQL-0.25/lib/DBIx/RunSQL.pm0000644000175000017500000004671614657430673015767 0ustar corioncorionpackage DBIx::RunSQL; use strict; use warnings; use DBI; use Module::Load 'load'; our $VERSION = '0.25'; =encoding utf8 =head1 NAME DBIx::RunSQL - run SQL from a file =cut =head1 SYNOPSIS #!/usr/bin/perl -w use strict; use DBIx::RunSQL; my $test_dbh = DBIx::RunSQL->create( dsn => 'dbi:SQLite:dbname=:memory:', sql => 'sql/create.sql', force => 1, verbose => 1, formatter => 'Text::Table', rotate => 1, null => '(Null)', ); # now run your tests with a DB setup fresh from setup.sql =head1 METHODS =head2 C<< DBIx::RunSQL->create ARGS >> =head2 C<< DBIx::RunSQL->run ARGS >> Runs the SQL commands and returns the database handle. In list context, it returns the database handle and the suggested exit code. =over 4 =item * C - name of the file containing the SQL statements The default is C If C is a reference to a glob or a filehandle, the SQL will be read from that. B If C is undefined, the C<$::DATA> or the C<0> filehandle will be read until exhaustion. B This allows one to create SQL-as-programs as follows: #!/usr/bin/perl -w -MDBIx::RunSQL -e 'create()' create table ... If you want to run SQL statements from a scalar, you can simply pass in a reference to a scalar containing the SQL: sql => \"update mytable set foo='bar';", =item * C, C, C, C - DBI parameters for connecting to the DB =item * C - a premade database handle to be used instead of C =item * C - continue even if errors are encountered =item * C - print each SQL statement as it is run =item * C - callback to call with each SQL statement instead of C =item * C - filehandle to write to instead of C =back =cut sub create { my ($self,%args) = @_; $args{sql} ||= 'sql/create.sql'; $args{options} ||= {}; my $dbh = delete $args{ dbh }; if (! $dbh) { $dbh = DBI->connect($args{dsn}, $args{user}, $args{password}, $args{options}) or die "Couldn't connect to DSN '$args{dsn}' : " . DBI->errstr; }; my $errors = $self->run_sql_file( dbh => $dbh, %args, ); return wantarray ? ($dbh, $errors) : $dbh; }; *run = *run = \&create; =head2 C<< DBIx::RunSQL->run_sql_file ARGS >> my $dbh = DBI->connect(...) for my $file (sort glob '*.sql') { DBIx::RunSQL->run_sql_file( verbose => 1, dbh => $dbh, sql => $file, ); }; Runs an SQL file on a prepared database handle. Returns the number of errors encountered. If the statement returns rows, these are printed separated with tabs. =over 4 =item * C - a premade database handle =item * C - name of the file containing the SQL statements =item * C - filehandle to the file containing the SQL statements =item * C - continue even if errors are encountered =item * C - print each SQL statement as it is run =item * C - callback to call with each SQL statement instead of C =item * C - filehandle to write to instead of C =item * C - whether to exit with a nonzero exit code if any row is found This makes the function return a nonzero value even if there is no error but a row was found. =item * C - whether to output the (one) row and column, without any headers =item * C - see the C<> option of C<< ->format_results >> =item * C - rotate the table by 90° , outputting columns as rows =item * C - string to replace SQL C columns by =back =cut sub run_sql_file { my ($self,%args) = @_; my @sql; if( ! $args{ fh }) { open $args{ fh }, "<", $args{sql} or die "Couldn't read '$args{sql}' : $!"; }; { # potentially this should become C<< $/ = ";\n"; >> # and a while loop to handle large SQL files local $/; $args{ sql }= readline $args{ fh }; # sluuurp }; $self->run_sql( %args ); } =head2 C<< DBIx::RunSQL->run_sql ARGS >> my $dbh = DBI->connect(...) DBIx::RunSQL->run_sql( verbose => 1, dbh => $dbh, sql => \@sql_statements, ); Runs an SQL string on a prepared database handle. Returns the number of errors encountered. If the statement returns rows, these are printed separated with tabs, but see the C and C options. =over 4 =item * C - a premade database handle =item * C - string or array reference containing the SQL statements =item * C - continue even if errors are encountered =item * C - print each SQL statement as it is run =item * C - callback to call with each SQL statement instead of C =item * C - filehandle to write to instead of C =item * C - whether to exit with a nonzero exit code if any row is found This makes the function return a nonzero value even if there is no error but a row was found. =item * C - whether to output the (one) row and column, without any headers =item * C - see the C<> option of C<< ->format_results >> =item * C - rotate the table by 90° , outputting columns as rows =item * C - string to replace SQL C columns by =back =cut sub run_sql { my ($self,%args) = @_; my $errors = 0; my @sql= 'ARRAY' eq ref $args{ sql } ? @{ $args{ sql }} : $args{ sql }; $args{ verbose_handler } ||= sub { $args{ verbose_fh } ||= \*main::STDOUT; print { $args{ verbose_fh } } "$_[0]\n"; }; my $status = delete $args{ verbose_handler }; # Because we blindly split above on /;\n/ # we need to reconstruct multi-line CREATE TRIGGER statements here again my $trigger; for my $statement ($self->split_sql( $args{ sql })) { # skip "statements" that consist only of comments next unless $statement =~ /^\s*[A-Z][A-Z]/mi; $status->($statement) if $args{verbose}; my $sth = $args{dbh}->prepare($statement); if(! $sth) { if (!$args{force}) { die "[SQL ERROR]: $statement\n"; } else { warn "[SQL ERROR]: $statement\n"; }; } else { my $status= $sth->execute(); if(! $status) { if (!$args{force}) { die "[SQL ERROR]: $statement\n"; } else { warn "[SQL ERROR]: $statement\n"; }; } elsif( defined $sth->{NUM_OF_FIELDS} and 0 < $sth->{NUM_OF_FIELDS} ) { # SELECT statement, output results if( $args{ output_bool }) { my $res = $self->format_results( sth => $sth, no_header_when_empty => 1, %args ); print $res; # Set the exit code depending on the length of $res because # we lost the information on how many rows the result # set had ... $errors = length $res > 0; } elsif( $args{ output_string }) { local $args{formatter} = 'tab'; print $self->format_results( sth => $sth, no_header_when_empty => 1, %args ); } else { print $self->format_results( sth => $sth, %args ); }; }; }; }; $errors } =head2 C<< DBIx::RunSQL->format_results %options >> my $sth= $dbh->prepare( 'select * from foo' ); $sth->execute(); print DBIx::RunSQL->format_results( sth => $sth ); Executes C<< $sth->fetchall_arrayref >> and returns the results either as tab separated string or formatted using L if the module is available. If you find yourself using this often to create reports, you may really want to look at L instead. =over 4 =item * C - the executed statement handle =item * C - if you want to force C or C usage, you can do it through that parameter. In fact, the module will use anything other than C as the class name and assume that the interface is compatible to C. =item * C - don't print anything if there are no results =item * C - rotate the table by 90° , outputting columns as rows =item * C - string to replace SQL C columns by =back Note that the query results are returned as one large string, so you really do not want to run this for large(r) result sets. =cut sub _nullstr { my $str = shift; map { defined $_ ? $_ : $str } @_ } sub format_results { my( $self, %options )= @_; my $sth= delete $options{ sth }; if( ! $options{ formatter }) { if( eval { require "Text/Table.pm" }) { $options{ formatter }= 'Text::Table'; } else { $options{ formatter }= 'tab'; }; }; my $nullstr = $options{ null } // ''; # / , for Filter::Simple my @columns= @{ $sth->{NAME} }; my $res= $sth->fetchall_arrayref(); my @rows = map { [ _nullstr( $nullstr, @$_ ) ] } @$res; my $no_header_when_empty = $options{ no_header_when_empty }; my $print_header = not exists $options{ header } || $options{ header }; my $rotate = $options{ rotate }; if( $rotate ) { # Rotate our output my @new_rows = map { my $i = $_; [$columns[$i], map { $_->[$i] } @rows] } (0..$#columns); @rows = @new_rows; @columns = @{shift @rows}; } my $result=''; if( @columns ) { # Output as print statement if( $no_header_when_empty and ! @$res ) { # Nothing to do } elsif( 'tab' eq $options{ formatter } ) { $result = join "\n", $print_header ? join( "\t", @columns ) : (), map { join( "\t", @$_ ) } @rows ; } else { my $class = $options{ formatter }; if( !( $class->can('table') || $class->can('new'))) { # Try to load the module, just in case it isn't present in # memory already eval { load $class; }; }; # Now dispatch according to the apparent type if( !$class->isa('Text::Table') and my $table = $class->can('table') ) { # Text::Table::Any interface $result = $table->( header_row => $print_header, rows => [\@columns, @rows ], ); } else {; # Text::Table interface my $t= $options{formatter}->new(@columns); $t->load( @rows ); $result= $t; }; }; }; "$result"; # Yes, sorry - we stringify everything } =head2 C<< DBIx::RunSQL->split_sql ARGS >> my @statements= DBIx::RunSQL->split_sql( <<'SQL'); create table foo (name varchar(64)); create trigger foo_insert on foo before insert; new.name= 'foo-'||old.name; end; insert into foo name values ('bar'); SQL # Returns three elements This is a helper subroutine to split a sequence of (semicolon-newline-delimited) SQL statements into separate statements. It is documented because it is not a very smart subroutine and you might want to override or replace it. It might also be useful outside the context of L if you need to split up a large blob of SQL statements into smaller pieces. The subroutine needs the whole sequence of SQL statements in memory. If you are attempting to restore a large SQL dump backup into your database, this approach might not be suitable. =cut sub split_sql { my( $self, $sql )= @_; my @sql = split /;[ \t]*\r?\n/, $sql; # Because we blindly split above on /;\n/ # we need to reconstruct multi-line CREATE TRIGGER statements here again my @res; my $trigger; for my $statement (@sql) { next unless $statement =~ /\S/; if( $statement =~ /^\s*CREATE\s+TRIGGER\b/i ) { $trigger = $statement; next if( $statement !~ /END$/i ); $statement = $trigger; undef $trigger; } elsif( $trigger ) { $trigger .= ";\n$statement"; next if( $statement !~ /END$/i ); $statement = $trigger; undef $trigger; }; push @res, $statement; }; @res } 1; =head2 C<< DBIx::RunSQL->parse_command_line >> my $options = DBIx::RunSQL->parse_command_line( 'my_application', \@ARGV ); Helper function to turn a command line array into options for DBIx::RunSQL invocations. The array of command line items is modified in-place. If the reference to the array of command line items is missing, C<@ARGV> will be modified instead. =cut sub parse_command_line { my ($package,$appname,$argv) = @_; require Getopt::Long; Getopt::Long->import('GetOptionsFromArray'); if (! $argv) { $argv = \@ARGV }; if (GetOptionsFromArray( $argv, 'user=s' => \my $user, 'password=s' => \my $password, 'dsn=s' => \my $dsn, 'verbose' => \my $verbose, 'force|f' => \my $force, 'sql=s' => \my $sql, 'bool' => \my $output_bool, 'string' => \my $output_string, 'quiet' => \my $no_header_when_empty, 'format=s' => \my $formatter_class, 'rotate' => \my $rotate, 'null=s' => \my $nullstr, 'help|h' => \my $help, 'man' => \my $man, )) { no warnings 'newline'; $sql ||= join " ", @$argv; if( $sql and ! -f $sql ) { $sql = \"$sql", }; my $fh; if( ! $sql and not @$argv) { # Assume we'll read the SQL from stdin $fh = \*STDIN; }; return { user => $user, password => $password, dsn => $dsn, verbose => $verbose, force => $force, sql => $sql, fh => $fh, no_header_when_empty => $no_header_when_empty, output_bool => $output_bool, output_string => $output_string, formatter => $formatter_class, rotate => $rotate, null => $nullstr, help => $help, man => $man, }; } else { return undef; }; } sub handle_command_line { my ($package,$appname,$argv) = @_; require Pod::Usage; Pod::Usage->import(); my $opts = $package->parse_command_line($appname,$argv) or pod2usage(2); pod2usage(1) if $opts->{help}; pod2usage(-verbose => 2) if $opts->{man}; $opts->{dsn} ||= sprintf 'dbi:SQLite:dbname=db/%s.sqlite', $appname; my( $dbh, $exitcode) = $package->create( %$opts ); return $exitcode } =head2 C<< DBIx::RunSQL->handle_command_line >> DBIx::RunSQL->handle_command_line( 'my_application', \@ARGV ); Helper function to run the module functionality from the command line. See below how to use this function in a good self-contained script. This function passes the following command line arguments and options to C<< ->create >>: --user --password --dsn --sql --quiet --format --force --verbose --bool --string --rotate --null In addition, it handles the following switches through L: --help --man If no SQL is given, this function will read the SQL from STDIN. If no dsn is given, this function will use C< dbi:SQLite:dbname=db/$appname.sqlite > as the default database. See also the section PROGRAMMER USAGE for a sample program to set up a database from an SQL file. =head1 PROGRAMMER USAGE This module abstracts away the "run these SQL statements to set up your database" into a module. In some situations you want to give the setup SQL to a database admin, but in other situations, for example testing, you want to run the SQL statements against an in-memory database. This module abstracts away the reading of SQL from a file and allows for various command line parameters to be passed in. A skeleton C looks like this: #!/usr/bin/perl -w use strict; use DBIx::RunSQL; my $exitcode = DBIx::RunSQL->handle_command_line('myapp', \@ARGV); exit $exitcode; =head1 NAME create-db.pl - Create the database =head1 SYNOPSIS create-db.pl "select * from mytable where 1=0" =head1 ABSTRACT This sets up the database. The following options are recognized: =head1 OPTIONS =over 4 =item C<--user> USERNAME =item C<--password> PASSWORD =item C<--dsn> DSN The DBI DSN to use for connecting to the database =item C<--sql> SQLFILE The alternative SQL file to use instead of C. =item C<--quiet> Output no headers for empty SELECT resultsets =item C<--bool> Set the exit code to 1 if at least one result row was found =item C<--string> Output the (single) column that the query returns as a string without any headers =item C<--format> formatter Use a different formatter for table output. Supported formatters are tab - output results as tab delimited columns Text::Table - output results as ASCII table =item C<--force> Don't stop on errors =item C<--help> Show this message. =back =cut =head1 NOTES =head2 COMMENT FILTERING The module tries to keep the SQL as much verbatim as possible. It filters all lines that end in semicolons but contain only SQL comments. All other comments are passed through to the database with the next statement. =head2 TRIGGER HANDLING This module uses a very simplicistic approach to recognize triggers. Triggers are problematic because they consist of multiple SQL statements and this module does not implement a full SQL parser. An trigger is recognized by the following sequence of lines CREATE TRIGGER ... END; If your SQL dialect uses a different syntax, it might still work to put the whole trigger on a single line in the input file. =head2 OTHER APPROACHES If you find yourself wanting to write SELECT statements, consider looking at L instead, which is geared towards that and even has an interface for Excel or HTML output. If you find yourself wanting to write parametrized queries as C<.sql> files, consider looking at L or potentially L. =head1 SEE ALSO L L - SQLite setup/teardown for tests, mostly geared towards testing, not general database setup =head1 REPOSITORY The public repository of this module is L. =head1 SUPPORT The public support forum of this module is L. =head1 BUG TRACKER Please report bugs in this module via the RT CPAN bug queue at L or via mail to L. =head1 AUTHOR Max Maischein C =head1 COPYRIGHT (c) Copyright 2009-2021 by Max Maischein C. =head1 LICENSE This module is released under the same terms as Perl itself. =cut DBIx-RunSQL-0.25/.gitignore0000644000175000017500000000012314657430673014717 0ustar corioncoriondb/ Makefile blib/ pm_to_blib MANIFEST.bak DBIx-RunSQL-* MYMETA.* .releasercDBIx-RunSQL-0.25/MANIFEST0000644000175000017500000000100314657430673014056 0ustar corioncorion.gitignore bin/run-sql.pl Changes lib/DBIx/RunSQL.pm LICENSE Makefile.PL MANIFEST This list of files MANIFEST.SKIP META.json META.yml README README.mkdn t/00-use.t t/01-force.t t/02-trigger.t t/03-comment.t t/04-handle-parameters.t t/05-output-bool.t t/05-select.t t/06-quiet.t t/formatter.t t/rt115442.t t/rt77378.sql t/rt77378.t t/trigger.sql xt/99-changes.t xt/99-compile.t xt/99-manifest.t xt/99-pod.t xt/99-synopsis.t xt/99-test-prerequisites.t xt/99-todo.t xt/99-unix-text.t xt/99-versions.t xt/meta-lint.t DBIx-RunSQL-0.25/README.mkdn0000644000175000017500000002655214657430673014555 0ustar corioncorion [![Travis Build Status](https://travis-ci.org/Corion/DBIx-RunSQL.svg?branch=master)](https://travis-ci.org/Corion/DBIx-RunSQL) [![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/github/Corion/DBIx-RunSQL?branch=master&svg=true)](https://ci.appveyor.com/project/Corion/DBIx-RunSQL) # NAME DBIx::RunSQL - run SQL from a file # SYNOPSIS #!/usr/bin/perl -w use strict; use DBIx::RunSQL; my $test_dbh = DBIx::RunSQL->create( dsn => 'dbi:SQLite:dbname=:memory:', sql => 'sql/create.sql', force => 1, verbose => 1, formatter => 'Text::Table', rotate => 1, null => '(Null)', ); # now run your tests with a DB setup fresh from setup.sql # METHODS ## `DBIx::RunSQL->create ARGS` ## `DBIx::RunSQL->run ARGS` Runs the SQL commands and returns the database handle. In list context, it returns the database handle and the suggested exit code. - `sql` - name of the file containing the SQL statements The default is `sql/create.sql` If `sql` is a reference to a glob or a filehandle, the SQL will be read from that. **not implemented** If `sql` is undefined, the `$::DATA` or the `0` filehandle will be read until exhaustion. **not implemented** This allows one to create SQL-as-programs as follows: #!/usr/bin/perl -w -MDBIx::RunSQL -e 'create()' create table ... If you want to run SQL statements from a scalar, you can simply pass in a reference to a scalar containing the SQL: sql => \"update mytable set foo='bar';", - `dsn`, `user`, `password`, `options` - DBI parameters for connecting to the DB - `dbh` - a premade database handle to be used instead of `dsn` - `force` - continue even if errors are encountered - `verbose` - print each SQL statement as it is run - `verbose_handler` - callback to call with each SQL statement instead of `print` - `verbose_fh` - filehandle to write to instead of `STDOUT` ## `DBIx::RunSQL->run_sql_file ARGS` my $dbh = DBI->connect(...) for my $file (sort glob '*.sql') { DBIx::RunSQL->run_sql_file( verbose => 1, dbh => $dbh, sql => $file, ); }; Runs an SQL file on a prepared database handle. Returns the number of errors encountered. If the statement returns rows, these are printed separated with tabs. - `dbh` - a premade database handle - `sql` - name of the file containing the SQL statements - `fh` - filehandle to the file containing the SQL statements - `force` - continue even if errors are encountered - `verbose` - print each SQL statement as it is run - `verbose_handler` - callback to call with each SQL statement instead of `print` - `verbose_fh` - filehandle to write to instead of `STDOUT` - `output_bool` - whether to exit with a nonzero exit code if any row is found This makes the function return a nonzero value even if there is no error but a row was found. - `output_string` - whether to output the (one) row and column, without any headers - `formatter` - see the ` option of `->format_results` - `rotate` - rotate the table by 90° , outputting columns as rows - `null` - string to replace SQL `NULL` columns by ## `DBIx::RunSQL->run_sql ARGS` my $dbh = DBI->connect(...) DBIx::RunSQL->run_sql( verbose => 1, dbh => $dbh, sql => \@sql_statements, ); Runs an SQL string on a prepared database handle. Returns the number of errors encountered. If the statement returns rows, these are printed separated with tabs, but see the `output_bool` and `output_string` options. - `dbh` - a premade database handle - `sql` - string or array reference containing the SQL statements - `force` - continue even if errors are encountered - `verbose` - print each SQL statement as it is run - `verbose_handler` - callback to call with each SQL statement instead of `print` - `verbose_fh` - filehandle to write to instead of `STDOUT` - `output_bool` - whether to exit with a nonzero exit code if any row is found This makes the function return a nonzero value even if there is no error but a row was found. - `output_string` - whether to output the (one) row and column, without any headers - `formatter` - see the ` option of `->format_results` - `rotate` - rotate the table by 90° , outputting columns as rows - `null` - string to replace SQL `NULL` columns by ## `DBIx::RunSQL->format_results %options` my $sth= $dbh->prepare( 'select * from foo' ); $sth->execute(); print DBIx::RunSQL->format_results( sth => $sth ); Executes `$sth->fetchall_arrayref` and returns the results either as tab separated string or formatted using [Text::Table](https://metacpan.org/pod/Text%3A%3ATable) if the module is available. If you find yourself using this often to create reports, you may really want to look at [Querylet](https://metacpan.org/pod/Querylet) instead. - `sth` - the executed statement handle - `formatter` - if you want to force `tab` or `Text::Table` usage, you can do it through that parameter. In fact, the module will use anything other than `tab` as the class name and assume that the interface is compatible to `Text::Table`. - `no_header_when_empty` - don't print anything if there are no results - `rotate` - rotate the table by 90° , outputting columns as rows - `null` - string to replace SQL `NULL` columns by Note that the query results are returned as one large string, so you really do not want to run this for large(r) result sets. ## `DBIx::RunSQL->split_sql ARGS` my @statements= DBIx::RunSQL->split_sql( <<'SQL'); create table foo (name varchar(64)); create trigger foo_insert on foo before insert; new.name= 'foo-'||old.name; end; insert into foo name values ('bar'); SQL # Returns three elements This is a helper subroutine to split a sequence of (semicolon-newline-delimited) SQL statements into separate statements. It is documented because it is not a very smart subroutine and you might want to override or replace it. It might also be useful outside the context of [DBIx::RunSQL](https://metacpan.org/pod/DBIx%3A%3ARunSQL) if you need to split up a large blob of SQL statements into smaller pieces. The subroutine needs the whole sequence of SQL statements in memory. If you are attempting to restore a large SQL dump backup into your database, this approach might not be suitable. ## `DBIx::RunSQL->parse_command_line` my $options = DBIx::RunSQL->parse_command_line( 'my_application', \@ARGV ); Helper function to turn a command line array into options for DBIx::RunSQL invocations. The array of command line items is modified in-place. If the reference to the array of command line items is missing, `@ARGV` will be modified instead. ## `DBIx::RunSQL->handle_command_line` DBIx::RunSQL->handle_command_line( 'my_application', \@ARGV ); Helper function to run the module functionality from the command line. See below how to use this function in a good self-contained script. This function passes the following command line arguments and options to `->create`: --user --password --dsn --sql --quiet --format --force --verbose --bool --string --rotate --null In addition, it handles the following switches through [Pod::Usage](https://metacpan.org/pod/Pod%3A%3AUsage): --help --man If no SQL is given, this function will read the SQL from STDIN. If no dsn is given, this function will use ` dbi:SQLite:dbname=db/$appname.sqlite ` as the default database. See also the section PROGRAMMER USAGE for a sample program to set up a database from an SQL file. # PROGRAMMER USAGE This module abstracts away the "run these SQL statements to set up your database" into a module. In some situations you want to give the setup SQL to a database admin, but in other situations, for example testing, you want to run the SQL statements against an in-memory database. This module abstracts away the reading of SQL from a file and allows for various command line parameters to be passed in. A skeleton `create-db.pl` looks like this: #!/usr/bin/perl -w use strict; use DBIx::RunSQL; my $exitcode = DBIx::RunSQL->handle_command_line('myapp', \@ARGV); exit $exitcode; =head1 NAME create-db.pl - Create the database =head1 SYNOPSIS create-db.pl "select * from mytable where 1=0" =head1 ABSTRACT This sets up the database. The following options are recognized: =head1 OPTIONS =over 4 =item C<--user> USERNAME =item C<--password> PASSWORD =item C<--dsn> DSN The DBI DSN to use for connecting to the database =item C<--sql> SQLFILE The alternative SQL file to use instead of C. =item C<--quiet> Output no headers for empty SELECT resultsets =item C<--bool> Set the exit code to 1 if at least one result row was found =item C<--string> Output the (single) column that the query returns as a string without any headers =item C<--format> formatter Use a different formatter for table output. Supported formatters are tab - output results as tab delimited columns Text::Table - output results as ASCII table =item C<--force> Don't stop on errors =item C<--help> Show this message. =back =cut # NOTES ## COMMENT FILTERING The module tries to keep the SQL as much verbatim as possible. It filters all lines that end in semicolons but contain only SQL comments. All other comments are passed through to the database with the next statement. ## TRIGGER HANDLING This module uses a very simplicistic approach to recognize triggers. Triggers are problematic because they consist of multiple SQL statements and this module does not implement a full SQL parser. An trigger is recognized by the following sequence of lines CREATE TRIGGER ... END; If your SQL dialect uses a different syntax, it might still work to put the whole trigger on a single line in the input file. ## OTHER APPROACHES If you find yourself wanting to write SELECT statements, consider looking at [Querylet](https://metacpan.org/pod/Querylet) instead, which is geared towards that and even has an interface for Excel or HTML output. If you find yourself wanting to write parametrized queries as `.sql` files, consider looking at [Data::Phrasebook::SQL](https://metacpan.org/pod/Data%3A%3APhrasebook%3A%3ASQL) or potentially [DBIx::SQLHandler](https://metacpan.org/pod/DBIx%3A%3ASQLHandler). # SEE ALSO [ORLite::Migrate](https://metacpan.org/pod/ORLite%3A%3AMigrate) [Test::SQLite](https://metacpan.org/pod/Test%3A%3ASQLite) - SQLite setup/teardown for tests, mostly geared towards testing, not general database setup # REPOSITORY The public repository of this module is [https://github.com/Corion/DBIx--RunSQL](https://github.com/Corion/DBIx--RunSQL). # SUPPORT The public support forum of this module is [https://perlmonks.org/](https://perlmonks.org/). # BUG TRACKER Please report bugs in this module via the RT CPAN bug queue at [https://rt.cpan.org/Public/Dist/Display.html?Name=DBIx-RunSQL](https://rt.cpan.org/Public/Dist/Display.html?Name=DBIx-RunSQL) or via mail to [bug-dbix-runsql@rt.cpan.org](https://metacpan.org/pod/bug-dbix-runsql%40rt.cpan.org). # AUTHOR Max Maischein `corion@cpan.org` # COPYRIGHT (c) Copyright 2009-2021 by Max Maischein `corion@cpan.org`. # LICENSE This module is released under the same terms as Perl itself. DBIx-RunSQL-0.25/META.yml0000644000175000017500000000154414657430674014211 0ustar corioncorion--- abstract: 'run SQL from a file' author: - 'Max Maischein ' build_requires: Data::Dumper: '0' ExtUtils::MakeMaker: '0' Test::More: '0' configure_requires: ExtUtils::MakeMaker: '0' dynamic_config: 0 generated_by: 'ExtUtils::MakeMaker version 7.64, CPAN::Meta::Converter version 2.150010' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: '1.4' name: DBIx-RunSQL no_index: directory: - t - inc requires: DBI: '0' Getopt::Long: '2.36' Module::Load: '0' perl: '5.010' strict: '0' warnings: '0' resources: bugtracker: https://rt.cpan.org/Public/Dist/Display.html?Name=DBIx-RunSQL license: https://dev.perl.org/licenses/ repository: git://github.com/Corion/DBIx-RunSQL.git version: '0.25' x_serialization_backend: 'CPAN::Meta::YAML version 0.018' x_static_install: 1 DBIx-RunSQL-0.25/Changes0000644000175000017500000000725214657430673014234 0ustar corioncorion0.25 2024-08-15 * Don't use Test::More::isn't() anymore, in favour of Test::More::isnt() 0.24 2023-06-09 * We don't support 5.8.x due to use of // 0.23 2023-06-08 * Add "rotate" option to rotate the output by 90° * Add "null" option for custom strings for NULL values (instead of blank) 0.22 2021-05-03 * Allow pass-through of DBI database options for ->create() * Move URLs to https:// * Documentation updates 0.21 2019-03-09 * Use Module::Load to load renderers * Check if a class isa Text::Table, otherwise dispatch to Text::Table::Any This allows for rendering tables as HTML easily if you install Text::Table::Any * Properly install C 0.20 2018-10-28 * Re-release including proper META.* information * no need to upgrade 0.19 2018-04-21 * Fix implicit test prerequisite in formatter.t This addresses RT 125157, reported and diagnosed by Slaven Rezic 0.18 2018-04-20 * List the Getopt::Long version we need * Read SQL from STDIN if not given on the command line This allows run-sql.pl to be used in a pipe 0.17 2018-02-23 * API change: ->handle_command_line() and ->parse_command_line() now take an arrayREF for the command line items and modify that arrayref. * new "--quiet" / no_header_when_empty option to allow scripts to run from cron without producing too much output * new "run-sql.pl" script in the distribution as a template or tool script for running SQL commands. 0.16 2017-03-16 * Allow specifying the table formatter on the command line 0.15 2016-06-19 * Fix grammar error (RT #114768, contributed by eythian ) * Allow for trailing whitespace while parsing SQL (RT #115442, contributed by niceperl) 0.14 2016-05-24 * ->handle_command_line now also accepts an SQL string instead of only accepting SQL files * Silence some warnings if a statement does not return columns (like a CREATE statement). RT #114647 0.13 2015-05-19 * Fix bad thinko error in ->run_sql that prevented any results from being shown 0.12 2014-02-22 * If Text::Table is installed, output SELECT statements through it instead of simply using \t * Document more of the internal helper routines 0.11 2013-11-20 * Add functionality for SELECT statements 0.10 2013-05-10 * Fix the MANIFEST which listed MYMETA.* * Fix a bug where ->handle_command_line() never properly processed the parameters given to it. 0.09 2012-06-11 * Parse triggers. This fixes RT #77378 Test and report by Gabor Szabo 0.08 2012-05-18 * Add a test for warnings raised while executing SQL (contributed by David Golden) * Respect the 'verbose' setting, fixes RT #77260 (contributed by David Golden) 0.07 2011-10-23 * Fix bad test skip count * Documentation fixes * no need to upgrade 0.06 2011-09-20 Suggested by Gabor Szabo * allow a different output handle for the verbose messages * Allow a callback for the verbose messages * Separate the SQL statements by "--" in the verbose output * SQL errors are now fatal * Add --force option to ignore SQL errors (fixes RT #70998) 0.05 2011-01-27 * Fix synopsis to use :dbname instead of (wrong) :dbfile parameter for DBD::SQLite * Added link to github repo * Added metainformation about bugtracker etc. * Bumped copyright 0.04 2010-11-11 * Actually document ->handle_command_line, thanks to Terrence Brannon * Add author information, license information 0.03 2010-05-18 * ->create now returns the database handle so you can use it to create :memory: databases in SQLite 0.02 2010-02-13 * Collected from various copies and released DBIx-RunSQL-0.25/xt/0000755000175000017500000000000014657430674013367 5ustar corioncorionDBIx-RunSQL-0.25/xt/99-compile.t0000644000175000017500000000143714657430673015447 0ustar corioncorion#!perl use warnings; use strict; use File::Find; use Test::More; BEGIN { eval 'use Capture::Tiny ":all"; 1'; if ($@) { plan skip_all => "Capture::Tiny needed for testing"; exit 0; }; }; plan 'no_plan'; my $last_version = undef; sub check { return if (! m{(\.pm|\.pl) \z}xmsi); my ($stdout, $stderr, $exit) = capture(sub { system( $^X, '-Mblib', '-c', $_ ); }); s!\s*\z!! for ($stdout, $stderr); if( $exit ) { diag $stderr; diag "Exit code: ", $exit; fail($_); } elsif( $stderr ne "$_ syntax OK") { diag $stderr; fail($_); } else { pass($_); }; } find({wanted => \&check, no_chdir => 1}, grep { -d $_ } 'blib', 'scripts', 'examples', 'bin', 'lib' ); DBIx-RunSQL-0.25/xt/99-test-prerequisites.t0000644000175000017500000000657614657430673017711 0ustar corioncorion#!perl -w use warnings; use strict; use Test::More; use Data::Dumper; use File::Find; =head1 DESCRIPTION This test checks whether all tests still pass when the optional test prerequisites for the test are not present. This is done by using L to rerun the test while excluding the optional prerequisite. =cut BEGIN { eval { require CPAN::Meta::Prereqs; require Parse::CPAN::Meta; require Perl::PrereqScanner::Lite; require Module::CoreList; require Test::Without::Module; require Capture::Tiny; Capture::Tiny->import('capture'); require Path::Class; Path::Class->import('dir'); }; if (my $err = $@) { warn "# $err"; plan skip_all => "Prerequisite needed for testing is missing"; exit 0; }; }; my @tests; if( @ARGV ) { @tests = @ARGV; } else { @tests = grep { -f $_ } map { glob $_ } 't/*.t', 'scripts/*' } plan tests => 0+@tests; my $meta = Parse::CPAN::Meta->load_file('META.json'); # Find what META.* declares my $explicit_test_prereqs = CPAN::Meta::Prereqs->new( $meta->{prereqs} )->merged_requirements->as_string_hash; my $minimum_perl = $meta->{prereqs}->{runtime}->{requires}->{perl} || 5.006; sub distributed_packages { my @modules; for( @_ ) { dir($_)->recurse( callback => sub { my( $child ) = @_; if( !$child->is_dir and $child =~ /\.pm$/) { push @modules, ((scalar $child->slurp()) =~ m/^\s*package\s+(?:#.*?\n\s+)*(\w+(?:::\w+)*)\b/msg); } }); }; map { $_ => $_ } @modules; } # Find what we distribute: my %distribution = distributed_packages('blib','t'); my $scanner = Perl::PrereqScanner::Lite->new; for my $test_file (@tests) { my $implicit_test_prereqs = $scanner->scan_file($test_file)->as_string_hash; my %missing = %{ $implicit_test_prereqs }; #warn Dumper \%missing; for my $p ( keys %missing ) { # remove core modules if( Module::CoreList::is_core( $p, undef, $minimum_perl)) { delete $missing{ $p }; #diag "$p is core for $minimum_perl"; } else { #diag "$p is not in core for $minimum_perl"; }; # remove explicit (test) prerequisites for my $k (keys %$explicit_test_prereqs) { delete $missing{ $k }; }; #warn Dumper $explicit_test_prereqs->as_string_hash; # Remove stuff from our distribution for my $k (keys %distribution) { delete $missing{ $k }; }; } # If we have no apparent missing prerequisites, we're good my @missing = sort keys %missing; # Rerun the test without these modules and see whether it crashes my @failed; for my $candidate (@missing) { diag "Checking that $candidate is not essential"; my @cmd = ($^X, "-MTest::Without::Module=$candidate", "-Mblib", '-w', $test_file); my $cmd = join " ", @cmd; my ($stdout, $stderr, $exit) = capture { system( @cmd ); }; if( $exit != 0 ) { push @failed, [ $candidate, [@cmd]]; } elsif( $? != 0 ) { push @failed, [ $candidate, [@cmd]]; }; }; is 0+@failed, 0, $test_file or diag Dumper \@failed; }; done_testing;DBIx-RunSQL-0.25/xt/99-changes.t0000644000175000017500000000137514657430673015430 0ustar corioncorion#!perl -w use warnings; use strict; use File::Find; use Test::More tests => 2; =head1 PURPOSE This test ensures that the Changes file mentions the current version and that a release date is mentioned as well =cut require './Makefile.PL'; # Loaded from Makefile.PL our %module = get_module_info(); my $module = $module{NAME}; (my $file = $module) =~ s!::!/!g; require "$file.pm"; my $version = sprintf '%0.2f', $module->VERSION; my $changes = do { local $/; open my $fh, 'Changes' or die $!; <$fh> }; ok $changes =~ /^(.*$version.*)$/m, "We find version $version for $module"; my $changes_line = $1; ok $changes_line =~ /$version\s+20\d\d-[01]\d-[0123]\d\b/, "We find a release date on the same line" or diag $changes_line; DBIx-RunSQL-0.25/xt/99-todo.t0000644000175000017500000000202714657430673014760 0ustar corioncorionuse Test::More; use File::Spec; use File::Find; use strict; # Check that all files do not contain any # lines with "XXX" - such markers should # either have been converted into Todo-stuff # or have been resolved. # The test was provided by Andy Lester. my @files; my $blib = File::Spec->catfile(qw(blib lib)); find(\&wanted, grep { -d } ($blib, 'bin')); plan tests => 2* @files; foreach my $file (@files) { source_file_ok($file); } sub wanted { push @files, $File::Find::name if /\.p(l|m|od)$/; } sub source_file_ok { my $file = shift; open( my $fh, "<$file" ) or die "Can't open $file: $!"; my @lines = <$fh>; close $fh; my $n = 0; for ( @lines ) { ++$n; s/^/$file ($n): /; } my @x = grep /XXX/, @lines; if ( !is( scalar @x, 0, "Looking for XXXes in $file" ) ) { diag( $_ ) for @x; } @x = grep /<<<|>>>/, @lines; if ( !is( scalar @x, 0, "Looking for <<<<|>>>> in $file" ) ) { diag( $_ ) for @x; } } DBIx-RunSQL-0.25/xt/99-pod.t0000644000175000017500000000123214657430673014572 0ustar corioncorionuse Test::More; # Check our Pod # The test was provided by Andy Lester, # who stole it from Brian D. Foy # Thanks to both ! use File::Spec; use File::Find; use strict; eval { require Test::Pod; Test::Pod->import; }; my @files; if ($@) { plan skip_all => "Test::Pod required for testing POD"; } elsif ($Test::Pod::VERSION < 0.95) { plan skip_all => "Test::Pod 0.95 required for testing POD"; } else { my $blib = File::Spec->catfile(qw(blib lib)); find(\&wanted, grep { -d } ($blib, 'bin')); plan tests => scalar @files; foreach my $file (@files) { pod_file_ok($file); } } sub wanted { push @files, $File::Find::name if /\.p(l|m|od)$/; } DBIx-RunSQL-0.25/xt/99-synopsis.t0000644000175000017500000000276114657430673015707 0ustar corioncorionuse strict; use Test::More; use File::Spec; use File::Find; use File::Temp 'tempfile'; use Getopt::Long; GetOptions( 'verbose' => \my $verbose, ); my @files; my $blib = File::Spec->catfile(qw(blib lib)); find(\&wanted, grep { -d } ($blib)); plan tests => scalar @files; foreach my $file (@files) { synopsis_file_ok($file); } sub wanted { push @files, $File::Find::name if /\.p(l|m|od)$/ and $_ !~ /\bDSL\.pm$/; # we skip that one as it initializes immediately } sub synopsis_file_ok { my( $file ) = @_; my $name = "SYNOPSIS in $file compiles"; open my $fh, '<', $file or die "Couldn't read '$file': $!"; my @synopsis = map { s!^\s\s!!; $_ } # outdent all code for here-docs grep { /^\s\s/ } # extract all verbatim (=code) stuff grep { /^=head1\s+SYNOPSIS$/.../^=/ } # extract Pod synopsis <$fh>; if( $verbose ) { diag $_ for @synopsis }; if( @synopsis ) { my($tmpfh,$tempname) = tempfile(); print {$tmpfh} join '', @synopsis; close $tmpfh; # flush it my $output = `$^X -Ilib -c $tempname 2>&1`; if( $output =~ /\ssyntax OK$/ ) { pass $name; } else { fail $name; diag $output; diag $_ for @synopsis; }; unlink $tempname or warn "Couldn't clean up $tempname: $!"; } else { SKIP: { skip "$file has no SYNOPSIS section", 1; }; }; }DBIx-RunSQL-0.25/xt/99-unix-text.t0000644000175000017500000000150114657430673015754 0ustar corioncorionuse Test::More; # Check that all released module files are in # UNIX text format use File::Spec; use File::Find; use strict; my @files = ('Makefile.PL', 'MANIFEST', 'MANIFEST.SKIP', glob 't/*.t'); my $blib = File::Spec->catfile(qw(blib lib)); find(\&wanted, grep { -d } ($blib, 'bin')); plan tests => scalar @files; foreach my $file (@files) { unix_file_ok($file); } sub wanted { push @files, $File::Find::name if /\.p(l|m|od)$/; } sub unix_file_ok { my ($filename) = @_; local $/; open F, "< $filename" or die "Couldn't open '$filename' : $!\n"; binmode F; my $content = ; my $i; my @lines = grep { /\x0D\x0A$/sm } map { sprintf "%s: %s\x0A", $i++, $_ } split /\x0A/, $content; unless (is(scalar @lines, 0,"'$filename' contains no windows newlines")) { diag $_ for @lines; }; close F; }; DBIx-RunSQL-0.25/xt/meta-lint.t0000644000175000017500000000163014657430673015445 0ustar corioncorion#!perl -w # Stolen from ChrisDolan on use.perl.org # http://use.perl.org/comments.pl?sid=29264&cid=44309 use warnings; use strict; use File::Find; use Test::More tests => 4; use Parse::CPAN::Meta; use CPAN::Meta::Validator; use lib '.'; require './Makefile.PL'; # Loaded from Makefile.PL our %module = get_module_info(); my $module = $module{NAME}; (my $file = $module) =~ s!::!/!g; require "$file.pm"; my $version = sprintf '%0.2f', $module->VERSION; for my $meta_file ('META.yml', 'META.json') { my $meta = Parse::CPAN::Meta->load_file($meta_file); my $cmv = CPAN::Meta::Validator->new( $meta ); if(! ok $cmv->is_valid, "$meta_file is valid" ) { diag $_ for $cmv->errors; }; # Also check that the declared version matches the version in META.* is $meta->{version}, $version, "$meta_file version matches module version ($version)"; }; DBIx-RunSQL-0.25/xt/99-manifest.t0000644000175000017500000000203614657430673015621 0ustar corioncorionuse strict; use Test::More; # Check that MANIFEST and MANIFEST.skip are sane : use File::Find; use File::Spec; my @files = qw( MANIFEST MANIFEST.SKIP ); plan tests => scalar @files * 4 +1 # MANIFEST existence check +1 # MYMETA.* non-existence check ; for my $file (@files) { ok(-f $file, "$file exists"); open F, "<$file" or die "Couldn't open $file : $!"; my @lines = ; is_deeply([grep(/^$/, @lines)],[], "No empty lines in $file"); is_deeply([grep(/^\s+$/, @lines)],[], "No whitespace-only lines in $file"); is_deeply([grep(/^\s*\S\s+$/, @lines)],[],"No trailing whitespace on lines in $file"); if ($file eq 'MANIFEST') { chomp @lines; is_deeply([grep { s/\s.*//; ! -f } @lines], [], "All files in $file exist") or do { diag "$_ is mentioned in $file but doesn't exist on disk" for grep { ! -f } @lines }; # Exclude some files from shipping is_deeply([grep(/^MYMETA\.(yml|json)$/, @lines)],[],"We don't try to ship MYMETA.* $file"); }; close F; }; DBIx-RunSQL-0.25/xt/99-versions.t0000644000175000017500000000242214657430673015662 0ustar corioncorion#!perl -w # Stolen from ChrisDolan on use.perl.org # http://use.perl.org/comments.pl?sid=29264&cid=44309 use warnings; use strict; use File::Find; use Test::More; BEGIN { eval 'use File::Slurp; 1'; if ($@) { plan skip_all => "File::Slurp needed for testing"; exit 0; }; }; plan 'no_plan'; my $last_version = undef; sub check { return if (! m{blib/script/}xms && ! m{\.pm \z}xms); my $content = read_file($_); # only look at perl scripts, not sh scripts return if (m{blib/script/}xms && $content !~ m/\A \#![^\r\n]+?perl/xms); my @version_lines = $content =~ m/ ( [^\n]* \$VERSION \s* = [^=] [^\n]* ) /gxms; if (@version_lines == 0) { fail($_); } for my $line (@version_lines) { $line =~ s/^\s+//; $line =~ s/\s+$//; if (!defined $last_version) { $last_version = shift @version_lines; diag "Checking for $last_version"; pass($_); } else { is($line, $last_version, $_); } } } find({wanted => \&check, no_chdir => 1}, 'blib'); if (! defined $last_version) { fail('Failed to find any files with $VERSION'); } DBIx-RunSQL-0.25/LICENSE0000644000175000017500000002127514657430673013747 0ustar corioncorion The Artistic License 2.0 Copyright (c) 2000-2006, The Perl Foundation. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble This license establishes the terms under which a given free software Package may be copied, modified, distributed, and/or redistributed. The intent is that the Copyright Holder maintains some artistic control over the development of that Package while still keeping the Package available as open source and free software. You are always permitted to make arrangements wholly outside of this license directly with the Copyright Holder of a given Package. If the terms of this license do not permit the full use that you propose to make of the Package, you should contact the Copyright Holder and seek a different licensing arrangement. Definitions "Copyright Holder" means the individual(s) or organization(s) named in the copyright notice for the entire Package. "Contributor" means any party that has contributed code or other material to the Package, in accordance with the Copyright Holder's procedures. "You" and "your" means any person who would like to copy, distribute, or modify the Package. "Package" means the collection of files distributed by the Copyright Holder, and derivatives of that collection and/or of those files. A given Package may consist of either the Standard Version, or a Modified Version. "Distribute" means providing a copy of the Package or making it accessible to anyone else, or in the case of a company or organization, to others outside of your company or organization. "Distributor Fee" means any fee that you charge for Distributing this Package or providing support for this Package to another party. It does not mean licensing fees. "Standard Version" refers to the Package if it has not been modified, or has been modified only in ways explicitly requested by the Copyright Holder. "Modified Version" means the Package, if it has been changed, and such changes were not explicitly requested by the Copyright Holder. "Original License" means this Artistic License as Distributed with the Standard Version of the Package, in its current version or as it may be modified by The Perl Foundation in the future. "Source" form means the source code, documentation source, and configuration files for the Package. "Compiled" form means the compiled bytecode, object code, binary, or any other form resulting from mechanical transformation or translation of the Source form. Permission for Use and Modification Without Distribution (1) You are permitted to use the Standard Version and create and use Modified Versions for any purpose without restriction, provided that you do not Distribute the Modified Version. Permissions for Redistribution of the Standard Version (2) You may Distribute verbatim copies of the Source form of the Standard Version of this Package in any medium without restriction, either gratis or for a Distributor Fee, provided that you duplicate all of the original copyright notices and associated disclaimers. At your discretion, such verbatim copies may or may not include a Compiled form of the Package. (3) You may apply any bug fixes, portability changes, and other modifications made available from the Copyright Holder. The resulting Package will still be considered the Standard Version, and as such will be subject to the Original License. Distribution of Modified Versions of the Package as Source (4) You may Distribute your Modified Version as Source (either gratis or for a Distributor Fee, and with or without a Compiled form of the Modified Version) provided that you clearly document how it differs from the Standard Version, including, but not limited to, documenting any non-standard features, executables, or modules, and provided that you do at least ONE of the following: (a) make the Modified Version available to the Copyright Holder of the Standard Version, under the Original License, so that the Copyright Holder may include your modifications in the Standard Version. (b) ensure that installation of your Modified Version does not prevent the user installing or running the Standard Version. In addition, the Modified Version must bear a name that is different from the name of the Standard Version. (c) allow anyone who receives a copy of the Modified Version to make the Source form of the Modified Version available to others under (i) the Original License or (ii) a license that permits the licensee to freely copy, modify and redistribute the Modified Version using the same licensing terms that apply to the copy that the licensee received, and requires that the Source form of the Modified Version, and of any works derived from it, be made freely available in that license fees are prohibited but Distributor Fees are allowed. Distribution of Compiled Forms of the Standard Version or Modified Versions without the Source (5) You may Distribute Compiled forms of the Standard Version without the Source, provided that you include complete instructions on how to get the Source of the Standard Version. Such instructions must be valid at the time of your distribution. If these instructions, at any time while you are carrying out such distribution, become invalid, you must provide new instructions on demand or cease further distribution. If you provide valid instructions or cease distribution within thirty days after you become aware that the instructions are invalid, then you do not forfeit any of your rights under this license. (6) You may Distribute a Modified Version in Compiled form without the Source, provided that you comply with Section 4 with respect to the Source of the Modified Version. Aggregating or Linking the Package (7) You may aggregate the Package (either the Standard Version or Modified Version) with other packages and Distribute the resulting aggregation provided that you do not charge a licensing fee for the Package. Distributor Fees are permitted, and licensing fees for other components in the aggregation are permitted. The terms of this license apply to the use and Distribution of the Standard or Modified Versions as included in the aggregation. (8) You are permitted to link Modified and Standard Versions with other works, to embed the Package in a larger work of your own, or to build stand-alone binary or bytecode versions of applications that include the Package, and Distribute the result without restriction, provided the result does not expose a direct interface to the Package. Items That are Not Considered Part of a Modified Version (9) Works (including, but not limited to, modules and scripts) that merely extend or make use of the Package, do not, by themselves, cause the Package to be a Modified Version. In addition, such works are not considered parts of the Package itself, and are not subject to the terms of this license. General Provisions (10) Any use, modification, and distribution of the Standard or Modified Versions is governed by this Artistic License. By using, modifying or distributing the Package, you accept this license. Do not use, modify, or distribute the Package, if you do not accept this license. (11) If your Modified Version has been derived from a Modified Version made by someone other than you, you are nevertheless required to ensure that your Modified Version complies with the requirements of this license. (12) This license does not grant you the right to use any trademark, service mark, tradename, or logo of the Copyright Holder. (13) This license includes the non-exclusive, worldwide, free-of-charge patent license to make, have made, use, offer to sell, sell, import and otherwise transfer the Package with respect to any patent claims licensable by the Copyright Holder that are necessarily infringed by the Package. If you institute patent litigation (including a cross-claim or counterclaim) against any party alleging that the Package constitutes direct or contributory patent infringement, then this Artistic License to you shall terminate on the date that such litigation is filed. (14) Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.DBIx-RunSQL-0.25/MANIFEST.SKIP0000644000175000017500000000023714657430673014633 0ustar corioncorion.cvsignore$ ^.git/ ^.lwpcookies ^.releaserc ^blib/ ^DBIx-RunSQL-.* CVS/ ^pm_to_blib .tar.gz$ .old$ ^Makefile$ ^cvstest$ ^blibdirs$ .bak$ ^MYMETA.* ^.travis.yml