Skip to content

Commit

Permalink
allow deep data structure interpolation in ysql
Browse files Browse the repository at this point in the history
'$.foo.bar' now gets the right thing out of a hash of hashes.

Fixes #70
  • Loading branch information
preaction committed Jan 1, 2015
1 parent 041da89 commit cade408
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 4 deletions.
8 changes: 7 additions & 1 deletion bin/ysql
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,17 @@ named placeholders, which begin with C<$.>. For example:
---
name: Stormy Waters
email: stormy@example.com
profile:
dept: Pilot
---
name: Debbie Dupree
email: debbie@example.com
profile:
dept: Wildlife
$ ysql write 'INSERT INTO person ( name, email ) VALUES ( $.name, $.email )' <input.yml
$ ysql write 'INSERT INTO person ( name, email, dept ) \
VALUES ( $.name, $.email, $.profile.dept )' \
< input.yml
=head1 ARGUMENTS
Expand Down
16 changes: 13 additions & 3 deletions lib/ETL/Yertl/Command/ysql.pm
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,29 @@ sub main {
elsif ( $command eq 'write' ) {
my $query = shift;

my @fields = $query =~ m/\$\.(\w+)/g;
$query =~ s/\$\.\w+/?/g;
my @fields = $query =~ m/\$(\.[.\w]+)/g;
$query =~ s/\$\.[\w.]+/?/g;

my $dbh = DBI->connect( $opt{dsn} );
my $sth = $dbh->prepare( $query );

my $in_fmt = ETL::Yertl::Format::yaml->new( input => \*STDIN );
for my $doc ( $in_fmt->read ) {
$sth->execute( map { $doc->{ $_ } } @fields );
$sth->execute( map { select_doc( $_, $doc ) } @fields );
}
}
}

sub select_doc {
my ( $select, $doc ) = @_;
$select =~ s/^[.]//; # select must start with .
my @parts = split /[.]/, $select;
for my $part ( @parts ) {
$doc = $doc->{ $part };
}
return $doc;
}

1;
__END__
26 changes: 26 additions & 0 deletions t/bin/ysql.t
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,32 @@ subtest 'write' => sub {
);
};

subtest 'interpolation' => sub {

subtest 'deep data structure' => sub {
my $tmp = tempfile;
my $dbi = DBI->connect( 'dbi:SQLite:dbname=' . $tmp );
$dbi->do( 'CREATE TABLE person ( id INT, name VARCHAR, email VARCHAR )' );
local *STDIN = $SHARE_DIR->child( 'command', 'ysql', 'deep.yml' )->openr;

my ( $stdout, $stderr, $exit ) = capture {
ysql->main( '--dsn', 'dbi:SQLite:dbname=' . $tmp, 'write',
'INSERT INTO person (id, name, email) VALUES ($.id, $.profile.name, $.email)',
);
};
is $exit, 0;
ok !$stderr, 'nothing on stderr' or diag $stderr;
ok !$stdout, 'nothing on stdout' or diag $stdout;

cmp_deeply
$dbi->selectall_arrayref( 'SELECT id,name,email FROM person' ),
bag(
[ 1, 'Hazel Murphy', 'hank@example.com' ],
[ 2, 'Quentin Quinn', 'quinn@example.com' ],
);
};
};

};


Expand Down
10 changes: 10 additions & 0 deletions t/share/command/ysql/deep.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
id: 1
profile:
name: Hazel Murphy
email: hank@example.com
---
id: 2
profile:
name: Quentin Quinn
email: quinn@example.com

0 comments on commit cade408

Please sign in to comment.