From 277338c6e5d4a1f404b718202a48894df116542f Mon Sep 17 00:00:00 2001 From: Sergey Poznyakoff Date: Wed, 1 Apr 2015 22:01:50 +0300 Subject: nsdbimport: use prepare/execute approach * nsdbimport/nsdbimport (parse_opts): New function. (readconfig): Special parsing for *-query statements. The values is a reference to array of 2 elements: the template (with placeholders) and an array for creating parameters (governor). (replvar): Third argument is a reference to governor. (query_expand): Remove. (sql_query): Use prepare_cached/execute. In debug mode, perform parameter substitution in a printable copy of the template. --- nsdbimport/nsdbimport | 86 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 55 insertions(+), 31 deletions(-) diff --git a/nsdbimport/nsdbimport b/nsdbimport/nsdbimport index 7c72f71..8b8fcca 100755 --- a/nsdbimport/nsdbimport +++ b/nsdbimport/nsdbimport @@ -71,6 +71,22 @@ END { my %config; +sub parse_opts { + my $opt = shift; + + if (defined($opt)) { + my %option; + foreach my $x (split /,/, $opt) { + if ($x =~ /([?+\.@-])(.*)/) { + $option{$1} = $2; + } + } + return \%option; + } + + return undef; +} + sub readconfig { my ($file, $kw) = @_; open(my $fd, "<", $file) @@ -102,10 +118,21 @@ sub readconfig { ++$err; next; } - $config{$k} = $v; + + if ($k =~ /.*-query$/) { + my @params; + + $v =~ s/\$\{([\w_-]+)(?::(.+?))?\}/push @params, { var => $1, opt => parse_opts($2) }; '?'/gex; + $v =~ s/'\?'/?/g; + $v =~ s/"\?"/?/g; + $config{$k} = [ $v, \@params ]; + } else { + $config{$k} = $v; + } } close $fd; exit(EX_CONFIG) if $err; + abend(EX_CONFIG, "rr-query is not defined in $file") unless defined($config{'rr-query'}); } @@ -155,53 +182,52 @@ my $rx_rr = array_to_regexp(@rrtypes); # ################### sub replvar { my ($rec, $var, $opt) = @_; - my %option; - if (defined($opt)) { - foreach my $x (split /,/, $opt) { - if ($x =~ /([?+\.@-])(.*)/) { - $option{$1} = $2; - } - } - } my $val = $rec->{$var} || ''; if ($val eq '') { - if (defined($option{'-'})) { - $val = $option{'-'}; - } elsif (defined($option{'?'})) { - my $text = $option{'?'} || "$var not defined"; + if (defined($opt->{'-'})) { + $val = $opt->{'-'}; + } elsif (defined($opt->{'?'})) { + my $text = $opt->{'?'} || "$var not defined"; error($text, prefix => $rec->{locus}); } - } elsif (defined($option{'+'})) { - $val = $option{'+'}; + } elsif (defined($opt->{'+'})) { + $val = $opt->{'+'}; } if ($val ne '') { - if ($val eq '@' and defined($option{'@'})) { - $val = $option{'@'} || $rec->{origin}; + if ($val eq '@' and defined($opt->{'@'})) { + $val = $opt->{'@'} || $rec->{origin}; $val .= '.' unless $val =~ /\.$/; - } elsif (defined($option{'.'}) and $val !~ /\.$/) { - $val .= '.' . ($option{'.'} || $rec->{origin}); + } elsif (defined($opt->{'.'}) and $val !~ /\.$/) { + $val .= '.' . ($opt->{'.'} || $rec->{origin}); $val .= '.' unless $val =~ /\.$/; } } return $val; } -sub query_expand { - my ($q, $rec) = @_; - $q =~ s/\$\{([\w_-]+)(?::(.+?))?\}/replvar($rec, $1, $2)/gex; - debug(2, "$rec->{locus}: $q"); - return $q; -} - sub sql_query { my ($tmpl, $rec) = @_; - my $q = query_expand($tmpl, $rec); + + my $sth = $dbd->prepare_cached($tmpl->[0]); + my @params; + foreach my $p (@{$tmpl->[1]}) { + push @params, replvar($rec, $p->{var}, $p->{opt}); + } + + if ($debug >= 2) { + my $printable = $tmpl->[0]; + foreach my $p (@params) { + $printable =~ s/\?/\'$p\'/; + } + error("$printable", prefix => 'DEBUG'); + } + unless ($dry_run) { - $dbd->do($q) - or abend(EX_UNAVAILABLE, $dbd->errstr."\nFailed query: $q"); + $sth->execute(@params) + or abend(EX_UNAVAILABLE, $dbd->errstr); } ++$record_count; } @@ -895,8 +921,6 @@ Exited due to errors in configuration file. Only MySQL is supported and tested. -Need to ensure proper quoting of SQL query arguments. - =head1 SEE ALSO B(1), B(8), B(5). -- cgit v1.2.1