App-AltSQL/lib/App/AltSQL/Plugin/Dump.pm
package App::AltSQL::Plugin::Dump;
use Moose::Role;
use Moose::Util qw( apply_all_roles );
use App::AltSQL::Plugin::Dump::Format;
=head1 Name
Dump AltSQL Plugin
=head1 Synopsis
Usage:
.dump <file>.[csv|html|json|pl|pm|sql|xls|xml|yaml|yml] <query>;
=head1 Description
This plugin will allow you to dump out results from
a sql query into one of many data formats.
=head1 Examples
Given:
CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(32) NOT NULL,
PRIMARY KEY (`id`)
);
CSV:
.dump out.csv select * from users;
out.csv:
"id","name"
"1","Moo"
"2","Pie"
"3","Cow"
HTML:
.dump out.html select * from users;
out.html:
=begin html
<style>table{margin: 1em 1em 1em 2em;background: whitesmoke;border-collapse: collapse;}table th, table td{border: 1px gainsboro solid;padding: 0.2em;}table th{background: gainsboro;text-align: left;}</style><table><tr><th>id</th><th>name</th></tr><tr><td>1</td><td>Moo</td></tr><tr><td>2</td><td>Pie</td></tr><tr><td>3</td><td>Cow</td></tr></table>
=end html
JSON:
.dump out.json select * from users;
out.json:
[{"name":"Moo","id":"1"},{"name":"Pie","id":"2"},{"name":"Cow","id":"3"}]
PERL:
.dump out.[pl|pm] select * from users;
out.[pl|pm]:
$VAR1 = [
{
'id' => '1',
'name' => 'Moo'
},
{
'id' => '2',
'name' => 'Pie'
},
{
'id' => '3',
'name' => 'Cow'
},
];
SQL:
.dump out.sql select * from users;
out.sql:
INSERT INTO table (`id`,`name`) VALUES('1','Moo'),('2','Pie'),('3','Cow');
XLS:
.dump out.xls select * from users;
out.xls:
You just get a excel spreadsheet...
XML:
.dump out.xml select * from users;
out.xml:
<table>
<row>
<field name="id">1</field>
<field name="name">Moo</field>
</row>
<row>
<field name="id">2</field>
<field name="name">Pie</field>
</row>
<row>
<field name="id">3</field>
<field name="name">Cow</field>
</row>
</table>
YAML:
.dump out.[yaml|yml] select * from users;
out.[yaml|yml]:
---
- id: 1
name: Moo
- id: 2
name: Pie
- id: 3
name: Cow
=cut
around call_command => sub {
my ($orig, $self, @args) = @_;
my $option;
my ($command, $input) = @args[0..1];
if ($command ne 'dump') {
# Call next chained command
return $self->$orig(@args);
}
my (undef, $filename, $query) = split /\s+/, $input, 3;
if (!$filename || !$query) {
$self->log_error("Usage: .dump \$filename \$sql");
$self->log_error("Available formats: csv, xls, html, json, [pl|pm], sql, xml, [yml|yaml]");
return 1; # handled, won't run this as a query
}
my ($ext) = $filename =~ /\.([a-zA-Z-]+)$/;
my $format;
if ($ext =~ /^pl|pm$/i) { $format = 'perl'; }
elsif ($ext =~ /^yml|yaml$/i) { $format = 'yaml'; }
else { $format = lc $ext; }
my $formatter = App::AltSQL::Plugin::Dump::Format->new();
local $@;
eval {
apply_all_roles( $formatter, "App::AltSQL::Plugin::Dump::Format::$format" );
};
if ($@) {
$self->log_error("Sorry $format is not a supported format because:\n$@");
return 1;
}
my $sth = $self->model->execute_sql($query);
return 1 unless $sth; # handled; error occurred has has been reported to user
my @headers;
my %table_data;
if ( $sth->{NUM_OF_FIELDS} ) {
for my $i (0 .. $sth->{NUM_OF_FIELDS} - 1) {
push @{ $table_data{columns} }, { name => $sth->{NAME}[$i] };
}
}
$table_data{rows} = $sth->fetchall_arrayref() || [];
if ( @{ $table_data{rows} } ) {
my $data = $formatter->format(
table_data => \%table_data,
filename => $filename,
);
if ($data) {
open(FILE, '>', $filename);
print FILE $data;
close(FILE);
}
}
$self->log_info("Wrote ".($sth->{NUM_OF_FIELDS} || 0)." rows to file $filename");
return 1;
};
1;