Author: turnstep
Date: Mon Jul 20 09:13:03 2009
New Revision: 13089
Modified:
DBD-Pg/trunk/Changes
DBD-Pg/trunk/quote.c
DBD-Pg/trunk/t/12placeholders.t
DBD-Pg/trunk/t/dbdpg_test_setup.pl
Log:
Fix up geometric type quoting, and make tests for same.
Per bug 41565
Modified: DBD-Pg/trunk/Changes
==============================================================================
--- DBD-Pg/trunk/Changes (original)
+++ DBD-Pg/trunk/Changes Mon Jul 20 09:13:03 2009
@@ -3,6 +3,7 @@
2.13.1_4
- Make quoting of int, floats, and names much safer. (CPAN bug #41565) [GSM]
+ - Make quoting of geometric types respect all valid chars (CPAN bug #41565)
[GSM]
- Return ints and bools-cast-to-number from the db as true Perlish numbers.
(CPAN bug #47619) [GSM]
- Fix backslash quoting of arrays (CPAN bug #46732) [GSM]
Modified: DBD-Pg/trunk/quote.c
==============================================================================
--- DBD-Pg/trunk/quote.c (original)
+++ DBD-Pg/trunk/quote.c Mon Jul 20 09:13:03 2009
@@ -100,17 +100,23 @@
}
+/* Quote a geometric constant. */
+/* Note: we only verify correct characters here, not for 100% valid input */
+/* Covers: points, lines, lsegs, boxes, polygons */
char * quote_geom(const char *string, STRLEN len, STRLEN *retlen, int estring)
{
dTHX;
char * result;
- const char *tmp;
+ const char *tmp;
len = 0; /* stops compiler warnings. Remove entirely someday */
tmp = string;
(*retlen) = 2;
+
while (*string != '\0') {
if (*string !=9 && *string != 32 && *string != '(' && *string
!= ')'
+ && *string != '-' && *string != '+' && *string != '.'
+ && *string != 'e' && *string != 'E'
&& *string != ',' && (*string < '0' || *string > '9'))
croak("Invalid input for geometric type");
(*retlen)++;
@@ -128,6 +134,7 @@
return result - (*retlen);
}
+/* Same as quote_geom, but also allows square brackets */
char * quote_path(const char *string, STRLEN len, STRLEN *retlen, int estring)
{
dTHX;
@@ -138,9 +145,11 @@
(*retlen) = 2;
while (*string != '\0') {
if (*string !=9 && *string != 32 && *string != '(' && *string
!= ')'
- && *string != ',' && *string != '[' && *string != ']'
- && (*string < '0' || *string > '9'))
- croak("Invalid input for geometric path type");
+ && *string != '-' && *string != '+' && *string != '.'
+ && *string != 'e' && *string != 'E'
+ && *string != '[' && *string != ']'
+ && *string != ',' && (*string < '0' || *string > '9'))
+ croak("Invalid input for path type");
(*retlen)++;
string++;
}
@@ -156,6 +165,7 @@
return result - (*retlen);
}
+/* Same as quote_geom, but also allows less than / greater than signs */
char * quote_circle(const char *string, STRLEN len, STRLEN *retlen, int
estring)
{
dTHX;
@@ -164,11 +174,14 @@
len = 0; /* stops compiler warnings. Remove entirely someday */
(*retlen) = 2;
+
while (*string != '\0') {
if (*string !=9 && *string != 32 && *string != '(' && *string
!= ')'
- && *string != ',' && *string != '<' && *string != '>'
- && (*string < '0' || *string > '9'))
- croak("Invalid input for geometric circle
type");
+ && *string != '-' && *string != '+' && *string != '.'
+ && *string != 'e' && *string != 'E'
+ && *string != '<' && *string != '>'
+ && *string != ',' && (*string < '0' || *string > '9'))
+ croak("Invalid input for circle type");
(*retlen)++;
string++;
}
Modified: DBD-Pg/trunk/t/12placeholders.t
==============================================================================
--- DBD-Pg/trunk/t/12placeholders.t (original)
+++ DBD-Pg/trunk/t/12placeholders.t Mon Jul 20 09:13:03 2009
@@ -17,7 +17,7 @@
if (! defined $dbh) {
plan skip_all => 'Connection to database failed, cannot continue
testing';
}
-plan tests => 129;
+plan tests => 213;
my $t='Connect to database for placeholder testing';
isnt ($dbh, undef, $t);
@@ -27,6 +27,8 @@
$dbh->do('SET escape_string_warning = false');
}
+my ($sth, $result, $SQL, $qresult);
+
# Make sure that quoting works properly.
$t='Quoting works properly';
my $E = $pgversion >= 80100 ? q{E} : q{};
@@ -350,17 +352,11 @@
}
$prefix = 'Invalid float value fails when quoting with SQL_FLOAT';
-## This is temporary to help track down a failing test
-use Data::Dumper;
for my $float ('3abc','123abc','','123e+04e+34','NaNum','-infinitee') {
$t = "$prefix (value=$float)";
$val = -1;
eval { $val = $dbh->quote($float, SQL_FLOAT); };
like ($@, qr{Invalid number}, $t);
- diag Dumper $@;
- my $foo = $@;
- $foo =~ s/(.)/"$1(".ord($1).")"/ge;
- diag $foo;
is ($val, -1, $t);
}
@@ -394,6 +390,279 @@
is($got, $expected, $t);
}
+## Test quoting of geometric types
+
+
+
+my @geotypes = qw/point line lseg box path polygon circle/;
+
+$dbh->do("SET search_path TO DEFAULT");
+eval { $dbh->do("DROP TABLE dbd_pg_test_geom"); }; $dbh->commit();
+
+$SQL = 'CREATE TABLE dbd_pg_test_geom (';
+for my $type (@geotypes) {
+ $SQL .= "x$type $type,";
+}
+$SQL =~ s/,$/)/;
+$dbh->do($SQL);
+$dbh->commit();
+
+my %typemap = (
+ point => PG_POINT,
+ line => PG_LINE,
+ lseg => PG_LSEG,
+ box => PG_BOX,
+ path => PG_PATH,
+ polygon => PG_POLYGON,
+ circle => PG_CIRCLE,
+);
+
+my $testdata = q{
+point datatype integers
+12,34
+'12,34'
+(12,34)
+
+point datatype floating point numbers
+1.34,667
+'1.34,667'
+(1.34,667)
+
+point datatype exponential numbers
+1e34,9E4
+'1e34,9E4'
+(1e+34,90000)
+
+point datatype plus and minus signs
+1e+34,-.45
+'1e+34,-.45'
+(1e+34,-0.45)
+
+point datatype invalid number
+123,abc
+ERROR: Invalid input for geometric type
+ERROR: any
+
+point datatype invalid format
+123
+'123'
+ERROR: any
+
+point datatype invalid format
+123,456,789
+'123,456,789'
+ERROR: any
+
+point datatype invalid format
+<(2,4),6>
+ERROR: Invalid input for geometric type
+ERROR: any
+
+point datatype invalid format
+[(1,2)]
+ERROR: Invalid input for geometric type
+ERROR: any
+
+line datatype integers
+12,34
+'12,34'
+ERROR: not yet implemented
+
+line datatype floating point numbers
+1.34,667
+'1.34,667'
+ERROR: not yet implemented
+
+line datatype exponential numbers
+1e34,9E4
+'1e34,9E4'
+ERROR: not yet implemented
+
+line datatype plus and minus signs
+1e+34,-.45
+'1e+34,-.45'
+ERROR: not yet implemented
+
+line datatype invalid number
+123,abc
+ERROR: Invalid input for geometric type
+ERROR: not yet implemented
+
+
+lseg datatype invalid format
+12,34
+'12,34'
+ERROR: any
+
+lseg datatype integers
+(12,34),(56,78)
+'(12,34),(56,78)'
+[(12,34),(56,78)]
+
+lseg datatype floating point and exponential numbers
+(1.2,3.4),(5e3,7E1)
+'(1.2,3.4),(5e3,7E1)'
+[(1.2,3.4),(5000,70)]
+
+
+box datatype invalid format
+12,34
+'12,34'
+ERROR: any
+
+box datatype integers
+(12,34),(56,78)
+'(12,34),(56,78)'
+(56,78),(12,34)
+
+box datatype floating point and exponential numbers
+(1.2,3.4),(5e3,7E1)
+'(1.2,3.4),(5e3,7E1)'
+(5000,70),(1.2,3.4)
+
+
+path datatype invalid format
+12,34
+'12,34'
+ERROR: any
+
+path datatype integers
+(12,34),(56,78)
+'(12,34),(56,78)'
+((12,34),(56,78))
+
+path datatype floating point and exponential numbers
+(1.2,3.4),(5e3,7E1)
+'(1.2,3.4),(5e3,7E1)'
+((1.2,3.4),(5000,70))
+
+path datatype alternate bracket format
+[(1.2,3.4),(5e3,7E1)]
+'[(1.2,3.4),(5e3,7E1)]'
+[(1.2,3.4),(5000,70)]
+
+path datatype many elements
+(1.2,3.4),(5,6),(7,8),(-9,10)
+'(1.2,3.4),(5,6),(7,8),(-9,10)'
+((1.2,3.4),(5,6),(7,8),(-9,10))
+
+path datatype fails with braces
+{(1,2),(3,4)}
+ERROR: Invalid input for path type
+ERROR: any
+
+
+polygon datatype invalid format
+12,34
+'12,34'
+ERROR: any
+
+polygon datatype integers
+(12,34),(56,78)
+'(12,34),(56,78)'
+((12,34),(56,78))
+
+polygon datatype floating point and exponential numbers
+(1.2,3.4),(5e3,7E1)
+'(1.2,3.4),(5e3,7E1)'
+((1.2,3.4),(5000,70))
+
+polygon datatype many elements
+(1.2,3.4),(5,6),(7,8),(-9,10)
+'(1.2,3.4),(5,6),(7,8),(-9,10)'
+((1.2,3.4),(5,6),(7,8),(-9,10))
+
+polygon datatype fails with brackets
+[(1,2),(3,4)]
+ERROR: Invalid input for geometric type
+ERROR: any
+
+
+
+circle datatype invalid format
+(12,34)
+'(12,34)'
+ERROR: any
+
+circle datatype integers
+<(12,34),5>
+'<(12,34),5>'
+<(12,34),5>
+
+circle datatype floating point and exponential numbers
+<(-1.2,2E2),3e3>
+'<(-1.2,2E2),3e3>'
+<(-1.2,200),3000>
+
+circle datatype fails with brackets
+[(1,2),(3,4)]
+ERROR: Invalid input for circle type
+ERROR: any
+
+};
+
+$testdata =~ s/^\s+//;
+my $curtype = '';
+for my $line (split /\n\n+/ => $testdata) {
+ my ($text,$input,$quoted,$rows) = split /\n/ => $line;
+ next if ! $text;
+ $t = "Geometric type test: $text";
+ (my $type) = ($text =~ m{(\w+)});
+ last if $type eq 'LAST';
+ if ($curtype ne $type) {
+ $curtype = $type;
+ eval { $dbh->do('DEALLOCATE geotest'); }; $dbh->commit();
+ $dbh->do(qq{PREPARE geotest($type) AS INSERT INTO
dbd_pg_test_geom(x$type) VALUES (\$1)});
+ $sth = $dbh->prepare(qq{INSERT INTO dbd_pg_test_geom(x$type)
VALUES (?)});
+ $sth->bind_param(1, '', {pg_type => $typemap{$type} });
+ }
+ $dbh->do('DELETE FROM dbd_pg_test_geom');
+ eval { $qresult = $dbh->quote($input, {pg_type => $typemap{$type}}); };
+ if ($@) {
+ if ($quoted !~ /ERROR: (.+)/) {
+ fail "$t error: $@";
+ }
+ else {
+ like ($@, qr{$1}, $t);
+ }
+ }
+ else {
+ is ($qresult, $quoted, $t);
+ }
+ $dbh->commit();
+
+ eval { $dbh->do("EXECUTE geotest('$input')"); };
+ if ($@) {
+ if ($rows !~ /ERROR: (.+)/) {
+ fail "$t error: $@";
+ }
+ else {
+ ## Do any error for now: i18n worries
+ pass $t;
+ }
+ }
+ $dbh->commit();
+
+ eval { $sth->execute($input); };
+ if ($@) {
+ if ($rows !~ /ERROR: (.+)/) {
+ fail $t;
+ }
+ else {
+ ## Do any error for now: i18n worries
+ pass $t;
+ }
+ }
+ $dbh->commit();
+
+ if ($rows !~ /ERROR/) {
+ $SQL = "SELECT x$type FROM dbd_pg_test_geom";
+ my $expected = [[$rows],[$rows]];
+ $result = $dbh->selectall_arrayref($SQL);
+ is_deeply($result, $expected, $t);
+ }
+}
+
## Begin custom type testing
$dbh->rollback();
Modified: DBD-Pg/trunk/t/dbdpg_test_setup.pl
==============================================================================
--- DBD-Pg/trunk/t/dbdpg_test_setup.pl (original)
+++ DBD-Pg/trunk/t/dbdpg_test_setup.pl Mon Jul 20 09:13:03 2009
@@ -25,6 +25,7 @@
'dbd_pg_test2',
'dbd_pg_test1',
'dbd_pg_test',
+ 'dbd_pg_test_geom',
);
my @sequences =