mirror of
https://github.com/percona/percona-toolkit.git
synced 2025-09-20 02:44:58 +00:00
Fix for 1087319: Quoter::serialize_list() doesn't handle multiple NULL values
This commit is contained in:
@@ -161,16 +161,16 @@ sub serialize_list {
|
|||||||
# the same. undef/NULL is a valid boundary value, however...
|
# the same. undef/NULL is a valid boundary value, however...
|
||||||
return $args[0] if @args == 1 && !defined $args[0];
|
return $args[0] if @args == 1 && !defined $args[0];
|
||||||
|
|
||||||
# ... if there's an undef/NULL value and more than one value,
|
return join ',', map {
|
||||||
# then we have no easy way to serialize the values into a list.
|
my $c = $_;
|
||||||
# We can't convert undef to "NULL" because "NULL" is a valid
|
if ( defined($c) ) {
|
||||||
# value itself, and we can't make it "" because a blank string
|
$c =~ s/([^A-Za-z0-9])/\\$1/g;
|
||||||
# is also a valid value. In practice, a boundary value with
|
$c
|
||||||
# two NULL values should be rare.
|
}
|
||||||
die "Cannot serialize multiple values with undef/NULL"
|
else {
|
||||||
if grep { !defined $_ } @args;
|
'\\N'
|
||||||
|
}
|
||||||
return join ',', map { quotemeta } @args;
|
} @args;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub deserialize_list {
|
sub deserialize_list {
|
||||||
@@ -193,27 +193,16 @@ sub deserialize_list {
|
|||||||
# the entire string represents the single element, so grab that.
|
# the entire string represents the single element, so grab that.
|
||||||
push @escaped_parts, pos($string) ? substr( $string, pos($string) ) : $string;
|
push @escaped_parts, pos($string) ? substr( $string, pos($string) ) : $string;
|
||||||
|
|
||||||
# Undo the quotemeta().
|
# Undo the escaping.
|
||||||
my @unescaped_parts = map {
|
my @unescaped_parts = map {
|
||||||
my $part = $_;
|
my $part = $_;
|
||||||
# Here be weirdness. Unfortunately quotemeta() is broken, and exposes
|
if ($part eq '\\N') {
|
||||||
# the internal representation of scalars. Namely, the latin-1 range,
|
undef
|
||||||
# \128-\377 (\p{Latin1} in newer Perls) is all escaped in downgraded
|
}
|
||||||
# strings, but left alone in UTF-8 strings. Thus, this.
|
else {
|
||||||
|
$part =~ s/\\([^A-Za-z0-9])/$1/g;
|
||||||
# TODO: quotemeta() might change in 5.16 to mean
|
|
||||||
# qr/(?=\p{ASCII})\W|\p{Pattern_Syntax}/
|
|
||||||
# And also fix this whole weird behavior under
|
|
||||||
# use feature 'unicode_strings' -- If/once that's
|
|
||||||
# implemented, this will have to change.
|
|
||||||
my $char_class = utf8::is_utf8($part) # If it's a UTF-8 string,
|
|
||||||
? qr/(?=\p{ASCII})\W/ # We only care about non-word
|
|
||||||
# characters in the ASCII range
|
|
||||||
: qr/(?=\p{ASCII})\W|[\x{80}-\x{FF}]/; # Otherwise,
|
|
||||||
# same as above, but also
|
|
||||||
# unescape the latin-1 range.
|
|
||||||
$part =~ s/\\($char_class)/$1/g;
|
|
||||||
$part;
|
$part;
|
||||||
|
}
|
||||||
} @escaped_parts;
|
} @escaped_parts;
|
||||||
|
|
||||||
return @unescaped_parts;
|
return @unescaped_parts;
|
||||||
|
@@ -150,6 +150,12 @@ is(
|
|||||||
"Deserialize undef string",
|
"Deserialize undef string",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
is(
|
||||||
|
$q->serialize_list(undef, undef),
|
||||||
|
'\\N,\\N',
|
||||||
|
"Serialize two undefs",
|
||||||
|
);
|
||||||
|
|
||||||
my @serialize_tests = (
|
my @serialize_tests = (
|
||||||
[ 'a', 'b', ],
|
[ 'a', 'b', ],
|
||||||
[ 'a,', 'b', ],
|
[ 'a,', 'b', ],
|
||||||
@@ -169,6 +175,8 @@ my @serialize_tests = (
|
|||||||
[ '', '', '', ],
|
[ '', '', '', ],
|
||||||
[ '' ],
|
[ '' ],
|
||||||
[ undef ],
|
[ undef ],
|
||||||
|
[ undef, undef, '', undef ],
|
||||||
|
[ '\\N', '\\\\N', undef ],
|
||||||
);
|
);
|
||||||
|
|
||||||
use DSNParser;
|
use DSNParser;
|
||||||
@@ -200,13 +208,12 @@ SKIP: {
|
|||||||
# Bit of a hack, but we want to test both of Perl's internal encodings
|
# Bit of a hack, but we want to test both of Perl's internal encodings
|
||||||
# for correctness.
|
# for correctness.
|
||||||
local $dbh->{'mysql_enable_utf8'} = 1 if utf8::is_utf8($ser);
|
local $dbh->{'mysql_enable_utf8'} = 1 if utf8::is_utf8($ser);
|
||||||
|
|
||||||
$sth->execute($test_index, $ser);
|
$sth->execute($test_index, $ser);
|
||||||
$selsth->execute($test_index);
|
$selsth->execute($test_index);
|
||||||
|
|
||||||
my $flat_string = "["
|
my $flat_string = "["
|
||||||
. join( "][",
|
. join( "][",
|
||||||
map { defined($_) ? $_ : '' } @{$serialize_tests[$test_index]}
|
map { defined($_) ? $_ : '<undef>' } @{$serialize_tests[$test_index]}
|
||||||
)
|
)
|
||||||
. "]";
|
. "]";
|
||||||
$flat_string =~ s/\n/\\n/g;
|
$flat_string =~ s/\n/\\n/g;
|
||||||
|
Reference in New Issue
Block a user