Author: turnstep
Date: Mon May 4 13:44:30 2009
New Revision: 12741
Modified:
DBD-Pg/trunk/quote.c
DBD-Pg/trunk/quote.h
DBD-Pg/trunk/t/12placeholders.t
DBD-Pg/trunk/types.c
Log:
Quick commit of work in progress to fix quoting problem.
Modified: DBD-Pg/trunk/quote.c
==============================================================================
--- DBD-Pg/trunk/quote.c (original)
+++ DBD-Pg/trunk/quote.c Mon May 4 13:44:30 2009
@@ -260,29 +260,75 @@
return result;
}
+char * quote_int(const char *string, STRLEN len, STRLEN *retlen, int estring)
+{
+ dTHX;
+ char * result;
+
+ New(0, result, len+1, char);
+ strcpy(result,string);
+ *retlen = len;
+ while (len > 0 && *string != '\0') {
+ len--;
+ if (isdigit(*string) || ' ' == *string || '+' == *string || '-'
== *string) {
+ *string++;
+ continue;
+ }
+ croak("Invalid integer");
+ }
-char * quote_integer(const char *value, STRLEN len, STRLEN *retlen, int
estring)
+ return result;
+}
+
+
+char * quote_float(const char *string, STRLEN len, STRLEN *retlen, int estring)
{
dTHX;
- char *result;
- STRLEN max_len=6;
- const int intval = *((const int*)value);
- len = 0;
-
- New(0, result, max_len, char);
-
- if (0 == intval)
- strncpy(result,"FALSE\0",6);
- else if (1 == intval)
- strncpy(result,"TRUE\0",5);
-
- *retlen = strlen(result);
- assert(*retlen+1 <= max_len);
+ char * result;
+ double val;
+
+ /*
+ We do minimal checking here, and let Postgres do the heavy lifting
+ Out job is to simply filter out bad characters
+ */
+
+ while (*string != '\0' && isspace((unsigned char) *string))
+ *string++;
+
+ errno = 0;
+ val = strtod(string, &result);
+
+ if (result == string || errno != 0) {
+ /* Allow exactly three strings, otherwise bail */
+ if (0 != strncasecmp(string, "NaN", 3)
+ && 0 != strncasecmp(string, "Infinity", 8)
+ && 0 != strncasecmp(string, "-Infinity", 9)
+ ) {
+ croak("Invalid number");
+ }
+ }
+
+ New(0, result, len+1, char);
+ strcpy(result,string);
+ *retlen = len;
return result;
}
+char * quote_name(const char *string, STRLEN len, STRLEN *retlen, int estring)
+{
+ dTHX;
+ char * result;
+
+ croak ("Not handled yet");
+
+ New(0, result, len+1, char);
+ strcpy(result,string);
+ *retlen = len;
+
+ return result;
+}
void dequote_char(const char *string, STRLEN *retlen, int estring)
Modified: DBD-Pg/trunk/quote.h
==============================================================================
--- DBD-Pg/trunk/quote.h (original)
+++ DBD-Pg/trunk/quote.h Mon May 4 13:44:30 2009
@@ -5,6 +5,9 @@
char * quote_sql_binary(char *string, STRLEN len, STRLEN *retlen, int estring);
char * quote_bool(const char *string, STRLEN len, STRLEN *retlen, int estring);
char * quote_integer(const char *string, STRLEN len, STRLEN *retlen, int
estring);
+char * quote_int(const char *string, STRLEN len, STRLEN *retlen, int estring);
+char * quote_float(const char *string, STRLEN len, STRLEN *retlen, int
estring);
+char * quote_name(const char *string, STRLEN len, STRLEN *retlen, int estring);
char * quote_geom(const char *string, STRLEN len, STRLEN *retlen, int estring);
char * quote_path(const char *string, STRLEN len, STRLEN *retlen, int estring);
char * quote_circle(const char *string, STRLEN len, STRLEN *retlen, int
estring);
Modified: DBD-Pg/trunk/t/12placeholders.t
==============================================================================
--- DBD-Pg/trunk/t/12placeholders.t (original)
+++ DBD-Pg/trunk/t/12placeholders.t Mon May 4 13:44:30 2009
@@ -7,6 +7,7 @@
use warnings;
use Test::More;
use lib 't','.';
+use DBI qw/:sql_types/;
require 'dbdpg_test_setup.pl';
select(($|=1,select(STDERR),$|=1)[1]);
@@ -308,6 +309,38 @@
is ($@, q{}, $t);
}
+my $val;
+$val = $dbh->quote('123', SQL_INTEGER);
+is ($val,123, 'GO?');
+
+eval {
+ $val = $dbh->quote('123abc', SQL_INTEGER);
+};
+like ($@, qr{Invalid integer}, 'Invalid integer fails to pass through');
+
+
+$val = $dbh->quote('123', SQL_INTEGER);
+is ($val,123, 'GO?');
+
+eval {
+ $val = $dbh->quote('123abc', SQL_FLOAT);
+};
+like ($@, qr{Invalid integer}, 'Invalid integer fails to pass through');
+
+exit;
+
+$dbh->rollback();
+## Test placeholerds plus binding
+$t='Bound placeholders enforce data types when not using server side prepares';
+$dbh->trace(0);
+$dbh->{pg_server_prepare} = 0;
+$sth = $dbh->prepare("SELECT (1+?+?)::integer");
+$sth->bind_param(1, 1, SQL_INTEGER);
+eval {
+ $sth->execute('10foo',20);
+};
+like ($@, qr{Invalid integer}, 'Invalid integer test 2');
+
## Begin custom type testing
$dbh->rollback();
Modified: DBD-Pg/trunk/types.c
==============================================================================
--- DBD-Pg/trunk/types.c (original)
+++ DBD-Pg/trunk/types.c Mon May 4 13:44:30 2009
@@ -94,14 +94,14 @@
{PG_CIRCLE ,"circle" ,1,',',"circle_out"
,quote_circle,dequote_string,{0},0},
{PG_CSTRING ,"cstring" ,1,',',"cstring_out"
,quote_string,dequote_string,{0},0},
{PG_DATE ,"date" ,1,',',"date_out"
,quote_string,dequote_string,{SQL_TYPE_DATE},0},
- {PG_FLOAT4 ,"float4" ,1,',',"float4out"
,null_quote ,null_dequote ,{0},2},
- {PG_FLOAT8 ,"float8" ,1,',',"float8out"
,null_quote ,null_dequote ,{SQL_FLOAT},2},
+ {PG_FLOAT4 ,"float4" ,1,',',"float4out"
,quote_float ,null_dequote ,{0},2},
+ {PG_FLOAT8 ,"float8" ,1,',',"float8out"
,quote_float ,null_dequote ,{SQL_FLOAT},2},
{PG_GTSVECTOR ,"gtsvector" ,1,',',"gtsvectorout"
,quote_string,dequote_string,{0},0},
{PG_INET ,"inet" ,1,',',"inet_out"
,quote_string,dequote_string,{0},0},
- {PG_INT2 ,"int2" ,1,',',"int2out"
,null_quote ,null_dequote ,{SQL_SMALLINT},1},
+ {PG_INT2 ,"int2" ,1,',',"int2out" ,quote_int
,null_dequote ,{SQL_SMALLINT},1},
{PG_INT2VECTOR ,"int2vector" ,1,',',"int2vectorout"
,quote_string,dequote_string,{0},0},
- {PG_INT4 ,"int4" ,1,',',"int4out"
,null_quote ,null_dequote ,{SQL_INTEGER},1},
- {PG_INT8 ,"int8" ,1,',',"int8out"
,null_quote ,null_dequote ,{SQL_BIGINT},0},
+ {PG_INT4 ,"int4" ,1,',',"int4out" ,quote_int
,null_dequote ,{SQL_INTEGER},1},
+ {PG_INT8 ,"int8" ,1,',',"int8out" ,quote_int
,null_dequote ,{SQL_BIGINT},0},
{PG_INTERNAL ,"internal" ,1,',',"internal_out"
,quote_string,dequote_string,{0},0},
{PG_INTERVAL ,"interval" ,1,',',"interval_out"
,quote_string,dequote_string,{0},0},
{PG_LANGUAGE_HANDLER ,"language_handler"
,1,',',"language_handler_out",quote_string,dequote_string,{0},0},
@@ -109,9 +109,9 @@
{PG_LSEG ,"lseg" ,1,',',"lseg_out"
,quote_geom ,dequote_string,{0},0},
{PG_MACADDR ,"macaddr" ,1,',',"macaddr_out"
,quote_string,dequote_string,{0},0},
{PG_MONEY ,"money" ,1,',',"cash_out"
,quote_string,dequote_string,{0},0},
- {PG_NAME ,"name" ,1,',',"nameout"
,null_quote ,null_dequote ,{SQL_VARCHAR},0},
- {PG_NUMERIC ,"numeric" ,1,',',"numeric_out"
,null_quote ,null_dequote ,{SQL_DECIMAL},2},
- {PG_OID ,"oid" ,1,',',"oidout"
,null_quote ,null_dequote ,{0},1},
+ {PG_NAME ,"name" ,1,',',"nameout"
,quote_name ,null_dequote ,{SQL_VARCHAR},0},
+ {PG_NUMERIC ,"numeric" ,1,',',"numeric_out"
,quote_float ,null_dequote ,{SQL_DECIMAL},2},
+ {PG_OID ,"oid" ,1,',',"oidout" ,quote_int
,null_dequote ,{0},1},
{PG_OIDVECTOR ,"oidvector" ,1,',',"oidvectorout"
,quote_string,dequote_string,{0},0},
{PG_OPAQUE ,"opaque" ,1,',',"opaque_out"
,quote_string,dequote_string,{0},0},
{PG_PATH ,"path" ,1,',',"path_out"
,quote_path ,dequote_string,{0},0},
@@ -303,16 +303,16 @@
{SQL_VARBINARY,"SQL_VARBINARY",1,',', "none", quote_bytea, dequote_bytea,
{PG_BYTEA}, 0},
{SQL_CHAR,"SQL_CHAR",1,',', "none", quote_string, dequote_char, {PG_CHAR}, 0},
{SQL_TYPE_DATE,"SQL_TYPE_DATE",1,',', "none", quote_string, dequote_string,
{PG_DATE}, 0},
- {SQL_FLOAT,"SQL_FLOAT",1,',', "none", null_quote, null_dequote, {PG_FLOAT8},
2},
- {SQL_DOUBLE,"SQL_DOUBLE",1,',', "none", null_quote, null_dequote,
{PG_FLOAT8}, 2},
- {SQL_NUMERIC,"SQL_NUMERIC",1,',', "none", null_quote, null_dequote,
{PG_FLOAT8}, 2},
- {SQL_REAL,"SQL_REAL",1,',', "none", null_quote, null_dequote, {PG_FLOAT8}, 2},
- {SQL_SMALLINT,"SQL_SMALLINT",1,',', "none", null_quote, null_dequote,
{PG_INT2}, 1},
- {SQL_TINYINT,"SQL_TINYINT",1,',', "none", null_quote, null_dequote,
{PG_INT2}, 1},
- {SQL_INTEGER,"SQL_INTEGER",1,',', "none", null_quote, null_dequote,
{PG_INT4}, 1},
- {SQL_BIGINT,"SQL_BIGINT",1,',', "none", null_quote, null_dequote, {PG_INT8},
0},
- {SQL_VARCHAR,"SQL_VARCHAR",1,',', "none", null_quote, null_dequote,
{PG_NAME}, 0},
- {SQL_DECIMAL,"SQL_DECIMAL",1,',', "none", null_quote, null_dequote,
{PG_NUMERIC}, 2},
+ {SQL_FLOAT,"SQL_FLOAT",1,',', "none", quote_float, null_dequote, {PG_FLOAT8},
2},
+ {SQL_DOUBLE,"SQL_DOUBLE",1,',', "none", quote_float, null_dequote,
{PG_FLOAT8}, 2},
+ {SQL_NUMERIC,"SQL_NUMERIC",1,',', "none", quote_float, null_dequote,
{PG_FLOAT8}, 2},
+ {SQL_REAL,"SQL_REAL",1,',', "none", quote_float, null_dequote, {PG_FLOAT8},
2},
+ {SQL_SMALLINT,"SQL_SMALLINT",1,',', "none", quote_int, null_dequote,
{PG_INT2}, 1},
+ {SQL_TINYINT,"SQL_TINYINT",1,',', "none", quote_int, null_dequote, {PG_INT2},
1},
+ {SQL_INTEGER,"SQL_INTEGER",1,',', "none", quote_int, null_dequote, {PG_INT4},
1},
+ {SQL_BIGINT,"SQL_BIGINT",1,',', "none", quote_int, null_dequote, {PG_INT8},
0},
+ {SQL_VARCHAR,"SQL_VARCHAR",1,',', "none", quote_name, null_dequote,
{PG_NAME}, 0},
+ {SQL_DECIMAL,"SQL_DECIMAL",1,',', "none", quote_float, null_dequote,
{PG_NUMERIC}, 2},
{SQL_LONGVARCHAR,"SQL_LONGVARCHAR",1,',', "none", quote_string,
dequote_string, {PG_TEXT}, 0},
{SQL_TYPE_TIME,"SQL_TYPE_TIME",1,',', "none", quote_string, dequote_string,
{PG_TIME}, 0},
{SQL_TIMESTAMP,"SQL_TIMESTAMP",1,',', "none", quote_string, dequote_string,
{PG_TIMESTAMP}, 0},
@@ -722,14 +722,14 @@
cid quote_string dequote_string 0 0 0
## Things that get no quoting at all (e.g. numbers)
-int2 null_quote null_dequote SQL_SMALLINT|SQL_TINYINT 1 1
-int4 null_quote null_dequote SQL_INTEGER 1 1
-int8 null_quote null_dequote SQL_BIGINT 1 0
-float4 null_quote null_dequote 0 1 2
-float8 null_quote null_dequote
SQL_FLOAT|SQL_DOUBLE|SQL_NUMERIC|SQL_REAL 1 2
-numeric null_quote null_dequote SQL_DECIMAL 1 2
-oid null_quote null_dequote 0 0 1
-name null_quote null_dequote SQL_VARCHAR 0 0 ## XXX
Wrong
+int2 quote_int null_dequote SQL_SMALLINT|SQL_TINYINT 1 1
+int4 quote_int null_dequote SQL_INTEGER 1 1
+int8 quote_int null_dequote SQL_BIGINT 1 0
+float4 quote_float null_dequote 0 1 2
+float8 quote_float null_dequote
SQL_FLOAT|SQL_DOUBLE|SQL_NUMERIC|SQL_REAL 1 2
+numeric quote_float null_dequote SQL_DECIMAL 1 2
+oid quote_int null_dequote 0 0 1
+name quote_name null_dequote SQL_VARCHAR 0 0 ## XXX
Wrong
## Boolean
bool quote_bool dequote_bool SQL_BOOLEAN 1 3