diff --git a/dbdimp.c b/dbdimp.c index db3de2c..d6b93b9 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -116,6 +116,8 @@ static int sqlite_type_from_odbc_type(int type) { switch(type) { + case SQL_UNKNOWN_TYPE: + return SQLITE_NULL; case SQL_INTEGER: case SQL_SMALLINT: case SQL_TINYINT: @@ -710,8 +712,11 @@ sqlite_st_execute(SV *sth, imp_sth_t *imp_sth) * type column (see t/19_bindparam.t), at least when * we explicitly specify its type. However, we should * keep spaces when we just guess. + * + * see_if_its_a_number should be ignored if an explicit + * SQL type is set via bind_param(). */ - if (imp_dbh->see_if_its_a_number) { + if (sql_type == SQLITE_NULL && imp_dbh->see_if_its_a_number) { numtype = sqlite_is_number(aTHX_ data, SQLITE_NULL); } else if (sql_type == SQLITE_INTEGER || sql_type == SQLITE_FLOAT) { diff --git a/lib/DBD/SQLite.pm b/lib/DBD/SQLite.pm index e976855..3db3431 100644 --- a/lib/DBD/SQLite.pm +++ b/lib/DBD/SQLite.pm @@ -1149,6 +1149,20 @@ problems. Use this sparingly when you handle existing databases. If you handle databases created by other tools like native C command line tool, this attribute would help you. +As of 1.41_04, C works only for +bind values with no explicit type. + + my $dbh = DBI->connect('dbi:SQLite:foo', undef, undef, { + AutoCommit => 1, + RaiseError => 1, + sqlite_see_if_its_a_number => 1, + }); + my $sth = $dbh->prepare('INSERT INTO foo VALUES(?)'); + # '1.230' will be inserted as a text, instead of 1.23 as a number, + # even though sqlite_see_if_its_a_number is set. + $sth->bind_param(1, '1.230', SQL_VARCHAR); + $sth->execute; + =back =head2 Placeholders diff --git a/t/58_see_if_its_a_number_and_explicit_binding.t b/t/58_see_if_its_a_number_and_explicit_binding.t new file mode 100644 index 0000000..52bc55d --- /dev/null +++ b/t/58_see_if_its_a_number_and_explicit_binding.t @@ -0,0 +1,73 @@ +#!/usr/bin/perl + +use strict; +BEGIN { + $| = 1; + $^W = 1; +} + +use t::lib::Test qw/connect_ok/; +use Test::More; +use Test::NoWarnings; +use DBI qw(:sql_types); + +plan tests => 9; + +# The following is by mje++ +# http://pastebin.com/RkUwwVti + +my $test_value = "1234567.20"; + +sub my_is { + my ($dbh, $test) = @_; + + my ($x) = $dbh->selectrow_array(q/select b from test where a = ?/, undef, 1); + + is($x, "$test_value", $test); + $dbh->do(q/delete from test/); +} + +my $dbh = connect_ok(sqlite_see_if_its_a_number => 1); + +$dbh->do(q/create table test (a integer, b varchar(20))/); + +$dbh->do(q/insert into test values(?,?)/, undef, 1, $test_value); +SKIP: { + local $TODO = 'failing now'; + my_is($dbh, "do insert"); +}; + +my $sth = $dbh->prepare(q/insert into test values(?,?)/); +$sth->bind_param(1, 1, SQL_INTEGER); +$sth->bind_param(2, $test_value, SQL_CHAR); +$sth->execute; +my_is($dbh, "prepared insert with provided bound data and type SQL_CHAR"); + +$sth = $dbh->prepare(q/insert into test values(?,?)/); +$sth->bind_param(1, 1, SQL_INTEGER); +$sth->bind_param(2, $test_value, SQL_VARCHAR); +$sth->execute; +my_is($dbh, "prepared insert with provided bound data and type SQL_VARCHAR"); + +$sth = $dbh->prepare(q/insert into test values(?,?)/); +$sth->bind_param(1, undef, SQL_INTEGER); +$sth->bind_param(2, undef, SQL_CHAR); +$sth->execute(1, $test_value); +my_is($dbh, "prepared insert with sticky bound data and type SQL_CHAR"); + +$dbh->do(q/insert into test values(?,?)/, undef, 1, $test_value); +$sth = $dbh->prepare(q/update test set b = ? where a = ?/); +$sth->bind_param(1, undef, SQL_CHAR); +$sth->bind_param(2, undef, SQL_INTEGER); +$sth->execute($test_value, 1); +my_is($dbh, "update with sticky bound type char"); + +$dbh->{sqlite_see_if_its_a_number} = 0; +$dbh->do(q/insert into test values(?,?)/, undef, 1, $test_value); +my_is($dbh, "do insert see_if_its_a_number = 0"); + +$sth = $dbh->prepare(q/insert into test values(?,?)/); +$sth->bind_param(1, 1, SQL_INTEGER); +$sth->bind_param(2, $test_value, SQL_VARCHAR); +$sth->execute; +my_is($dbh, "prepared insert with provided bound data and type SQL_VARCHAR see_if_its_a_number=0");