From 802e8d154826613a35d1d6addf64bd35811240b2 Mon Sep 17 00:00:00 2001 From: Kenichi Ishigaki Date: Sun, 16 Oct 2011 07:27:24 +0000 Subject: [PATCH] applied a patch from Yuriy Kaminskiy --- Changes | 6 ++++ dbdimp.c | 16 +++++------ t/48_bind_param_is_sticky.t | 48 +++++++++++++++++++++++++++++++ t/rt_71311_bind_col_and_unicode.t | 1 + 4 files changed, 62 insertions(+), 9 deletions(-) create mode 100644 t/48_bind_param_is_sticky.t diff --git a/Changes b/Changes index d2663e1..6566569 100644 --- a/Changes +++ b/Changes @@ -5,9 +5,15 @@ Changes for Perl extension DBD-SQLite - Resolved #67581: bind_param SQL_INTEGER numifies value; Now DBD::SQLite croaks if you explicitly specify datatype (with bind_param) and datatype mismatch happens (ISHIGAKI) + - Datatype set in the bind_param(_array) becomes sticky now + (as per DBI spec). This potentially affects code depending on + current undocumented and broken behavior. (Yuriy Kaminskiy) - Resolved #71311: binding output columns as SQL_BLOB returns nothing (ISHIGAKI) + - Bsymbolic flag was not portable enough and was not silently + ignored under MacOSX. Needs to check harder to see if the + linker supports the option. (ISHIGAKI) 1.34_01 Thu 22 Sep 2011 - Updated to SQLite 3.7.8 (ISHIGAKI) diff --git a/dbdimp.c b/dbdimp.c index 49fedd9..c7f2ad1 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -641,11 +641,11 @@ sqlite_st_execute(SV *sth, imp_sth_t *imp_sth) } for (i = 0; i < num_params; i++) { - SV *value = av_shift(imp_sth->params); - SV *sql_type_sv = av_shift(imp_sth->params); - int sql_type = sqlite_type_from_odbc_type(SvIV(sql_type_sv)); + SV **pvalue = av_fetch(imp_sth->params, 2*i, 0); + SV **sql_type_sv = av_fetch(imp_sth->params, 2*i+1, 0); + SV *value = pvalue ? *pvalue : &PL_sv_undef; + int sql_type = sqlite_type_from_odbc_type(sql_type_sv ? SvIV(*sql_type_sv) : SQL_UNKNOWN_TYPE); - sqlite_trace(sth, imp_sth, 4, form("params left in 0x%p: %ld", imp_sth->params, 1+av_len(imp_sth->params))); sqlite_trace(sth, imp_sth, 4, form("bind %d type %d as %s", i, sql_type, SvPV_nolen_undef_ok(value))); if (!SvOK(value)) { @@ -701,10 +701,6 @@ sqlite_st_execute(SV *sth, imp_sth_t *imp_sth) } } - if (value) { - SvREFCNT_dec(value); - } - SvREFCNT_dec(sql_type_sv); if (rc != SQLITE_OK) { sqlite_error(sth, rc, sqlite3_errmsg(imp_dbh->db)); return -4; /* -> undef in SQLite.xsi */ @@ -1158,7 +1154,9 @@ sqlite_bind_ph(SV *sth, imp_sth_t *imp_sth, pos = 2 * (SvIV(param) - 1); sqlite_trace(sth, imp_sth, 3, form("bind into 0x%p: %"IVdf" => %s (%"IVdf") pos %d", imp_sth->params, SvIV(param), SvPV_nolen_undef_ok(value), sql_type, pos)); av_store(imp_sth->params, pos, SvREFCNT_inc(value)); - av_store(imp_sth->params, pos+1, newSViv(sql_type)); + if (sql_type) { + av_store(imp_sth->params, pos+1, newSViv(sql_type)); + } return TRUE; } diff --git a/t/48_bind_param_is_sticky.t b/t/48_bind_param_is_sticky.t new file mode 100644 index 0000000..504dd74 --- /dev/null +++ b/t/48_bind_param_is_sticky.t @@ -0,0 +1,48 @@ +#!/usr/bin/perl + +# Check data type assignment in bind_param is sticky + +use strict; +BEGIN { + $| = 1; + $^W = 1; +} + +use t::lib::Test qw/connect_ok/; +use DBI qw(:sql_types); +use Test::More; +use Test::NoWarnings; + +plan tests => 10 + 1; + +my $dbh = connect_ok( + RaiseError => 1, + PrintError => 0, + AutoCommit => 0, +); +$dbh->do("CREATE TABLE Blah ( id INTEGER, val BLOB )"); +$dbh->commit; +my $sth; +ok($sth = $dbh->prepare("INSERT INTO Blah VALUES (?, ?)"), "prepare"); +$sth->bind_param(1, 1); +$sth->bind_param(2, 'foo', SQL_BLOB); +$sth->execute; +$sth->execute(2, 'bar'); +sub verify_types() { + my $rows = $dbh->selectall_arrayref("SELECT typeof(val) FROM Blah ORDER BY id"); + ok($rows, "selectall_arrayref returned data"); + ok(@{$rows} == 2, "... with expected number of rows"); + ok($rows->[0]->[0] eq 'blob', "$rows->[0]->[0] eq blob"); + ok($rows->[1]->[0] eq 'blob', "$rows->[1]->[0] eq blob"); +} +verify_types(); +$dbh->commit; +$dbh->do("DELETE FROM Blah"); +$sth->bind_param_array(1, [1, 2]); +$sth->bind_param_array(2, [qw/FOO BAR/], SQL_BLOB); +$sth->execute_array({}); +verify_types(); +$dbh->commit; + +$dbh->disconnect; +undef($dbh); diff --git a/t/rt_71311_bind_col_and_unicode.t b/t/rt_71311_bind_col_and_unicode.t index d85ac1e..3c60f78 100644 --- a/t/rt_71311_bind_col_and_unicode.t +++ b/t/rt_71311_bind_col_and_unicode.t @@ -37,6 +37,7 @@ my $str = "\x{20ac}"; $sth->bind_param(2, $blob, {TYPE => SQL_BLOB}); $sth->execute; + $sth->bind_param(2, undef, SQL_VARCHAR); $sth->execute(4, $str); $sth->bind_param(1, 5);;