mirror of
https://github.com/DBD-SQLite/DBD-SQLite
synced 2025-06-07 22:28:47 -04:00
sqlite_see_if_its_a_number attribute to enable sqlite_is_number check
This commit is contained in:
parent
16cd4fd520
commit
968ecf0063
5 changed files with 72 additions and 19 deletions
27
dbdimp.c
27
dbdimp.c
|
@ -240,6 +240,7 @@ sqlite_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *user, char *pa
|
|||
imp_dbh->handle_binary_nulls = FALSE;
|
||||
imp_dbh->allow_multiple_statements = FALSE;
|
||||
imp_dbh->use_immediate_transaction = FALSE;
|
||||
imp_dbh->see_if_its_a_number = FALSE;
|
||||
|
||||
sqlite3_busy_timeout(imp_dbh->db, SQL_TIMEOUT);
|
||||
|
||||
|
@ -439,6 +440,10 @@ sqlite_db_STORE_attrib(SV *dbh, imp_dbh_t *imp_dbh, SV *keysv, SV *valuesv)
|
|||
imp_dbh->use_immediate_transaction = !(! SvTRUE(valuesv));
|
||||
return TRUE;
|
||||
}
|
||||
if (strEQ(key, "sqlite_see_if_its_a_number")) {
|
||||
imp_dbh->see_if_its_a_number = !(! SvTRUE(valuesv));
|
||||
return TRUE;
|
||||
}
|
||||
if (strEQ(key, "sqlite_unicode")) {
|
||||
#if PERL_UNICODE_DOES_NOT_WORK_WELL
|
||||
sqlite_trace(dbh, imp_dbh, 3, form("Unicode support is disabled for this version of perl."));
|
||||
|
@ -477,6 +482,9 @@ sqlite_db_FETCH_attrib(SV *dbh, imp_dbh_t *imp_dbh, SV *keysv)
|
|||
if (strEQ(key, "sqlite_use_immediate_transaction")) {
|
||||
return sv_2mortal(newSViv(imp_dbh->use_immediate_transaction ? 1 : 0));
|
||||
}
|
||||
if (strEQ(key, "sqlite_see_if_its_a_number")) {
|
||||
return sv_2mortal(newSViv(imp_dbh->see_if_its_a_number ? 1 : 0));
|
||||
}
|
||||
if (strEQ(key, "sqlite_unicode")) {
|
||||
#if PERL_UNICODE_DOES_NOT_WORK_WELL
|
||||
sqlite_trace(dbh, imp_dbh, 3, "Unicode support is disabled for this version of perl.");
|
||||
|
@ -637,15 +645,17 @@ sqlite_st_execute(SV *sth, imp_sth_t *imp_sth)
|
|||
else {
|
||||
STRLEN len;
|
||||
const char *data;
|
||||
#if 0
|
||||
int numtype;
|
||||
#endif
|
||||
int numtype = 0;
|
||||
|
||||
if (imp_dbh->unicode) {
|
||||
sv_utf8_upgrade(value);
|
||||
}
|
||||
data = SvPV(value, len);
|
||||
#if 0
|
||||
numtype = sqlite_is_number(aTHX_ data);
|
||||
|
||||
if (imp_dbh->see_if_its_a_number) {
|
||||
numtype = sqlite_is_number(aTHX_ data);
|
||||
}
|
||||
|
||||
if (numtype == 1) {
|
||||
#if defined(USE_64_BIT_INT)
|
||||
rc = sqlite3_bind_int64(imp_sth->stmt, i+1, atoi(data));
|
||||
|
@ -657,11 +667,8 @@ sqlite_st_execute(SV *sth, imp_sth_t *imp_sth)
|
|||
rc = sqlite3_bind_double(imp_sth->stmt, i+1, atof(data));
|
||||
}
|
||||
else {
|
||||
#endif
|
||||
rc = sqlite3_bind_text(imp_sth->stmt, i+1, data, len, SQLITE_TRANSIENT);
|
||||
#if 0
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (value) {
|
||||
|
@ -816,7 +823,6 @@ sqlite_st_fetch(SV *sth, imp_sth_t *imp_sth)
|
|||
}
|
||||
switch(col_type) {
|
||||
case SQLITE_INTEGER:
|
||||
#if 1
|
||||
sqlite_trace(sth, imp_sth, 5, form("fetch column %d as integer", i));
|
||||
#if defined(USE_64_BIT_INT)
|
||||
sv_setiv(AvARRAY(av)[i], sqlite3_column_int64(imp_sth->stmt, i));
|
||||
|
@ -824,14 +830,11 @@ sqlite_st_fetch(SV *sth, imp_sth_t *imp_sth)
|
|||
sv_setnv(AvARRAY(av)[i], (double)sqlite3_column_int64(imp_sth->stmt, i));
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
case SQLITE_FLOAT:
|
||||
#if 1
|
||||
/* fetching as float may lose precision info in the perl world */
|
||||
sqlite_trace(sth, imp_sth, 5, form("fetch column %d as float", i));
|
||||
sv_setnv(AvARRAY(av)[i], sqlite3_column_double(imp_sth->stmt, i));
|
||||
break;
|
||||
#endif
|
||||
case SQLITE_TEXT:
|
||||
sqlite_trace(sth, imp_sth, 5, form("fetch column %d as text", i));
|
||||
val = (char*)sqlite3_column_text(imp_sth->stmt, i);
|
||||
|
|
1
dbdimp.h
1
dbdimp.h
|
@ -35,6 +35,7 @@ struct imp_dbh_st {
|
|||
SV *collation_needed_callback;
|
||||
bool allow_multiple_statements;
|
||||
bool use_immediate_transaction;
|
||||
bool see_if_its_a_number;
|
||||
};
|
||||
|
||||
/* Statement Handle */
|
||||
|
|
|
@ -752,7 +752,7 @@ like this while executing:
|
|||
|
||||
SELECT bar FROM foo GROUP BY bar HAVING count(*) > "5";
|
||||
|
||||
There are two workarounds for this.
|
||||
There are three workarounds for this.
|
||||
|
||||
=over 4
|
||||
|
||||
|
@ -778,6 +778,32 @@ This is somewhat weird, but works anyway.
|
|||
});
|
||||
$sth->execute(5);
|
||||
|
||||
=item Set C<sqlite_see_if_its_a_number> database handle attribute
|
||||
|
||||
As of version 1.32_02, you can use C<sqlite_see_if_its_a_number>
|
||||
to let DBD::SQLite to see if the bind values are numbers or not.
|
||||
|
||||
$dbh->{sqlite_see_if_its_a_number} = 1;
|
||||
my $sth = $dbh->prepare(q{
|
||||
SELECT bar FROM foo GROUP BY bar HAVING count(*) > ?;
|
||||
});
|
||||
$sth->execute(5);
|
||||
|
||||
You can set it to true when you connect to a database.
|
||||
|
||||
my $dbh = DBI->connect('dbi:SQLite:foo', undef, undef, {
|
||||
AutoCommit => 1,
|
||||
RaiseError => 1,
|
||||
sqlite_see_if_its_a_number => 1,
|
||||
});
|
||||
|
||||
This is the most straightforward solution, but as noted above,
|
||||
existing data in your databases created by DBD::SQLite have not
|
||||
always been stored as numbers, so this *might* cause other obscure
|
||||
problems. Use this sparingly when you handle existing databases.
|
||||
If you handle databases created by other tools like native C<sqlite3>
|
||||
command line tool, this attribute would help you.
|
||||
|
||||
=back
|
||||
|
||||
=head2 Placeholders
|
||||
|
@ -1033,6 +1059,12 @@ If you set this to true, DBD::SQLite tries to issue a C<begin
|
|||
immediate transaction> (instead of C<begin transaction>) when
|
||||
necessary. See above for details.
|
||||
|
||||
=item sqlite_see_if_its_a_number
|
||||
|
||||
If you set this to true, DBD::SQLite tries to see if the bind values
|
||||
are number or not, and does not quote if they are numbers. See above
|
||||
for details.
|
||||
|
||||
=back
|
||||
|
||||
=head2 Statement Handle Attributes
|
||||
|
|
|
@ -6,7 +6,7 @@ BEGIN {
|
|||
}
|
||||
|
||||
use t::lib::Test;
|
||||
use Test::More tests => 7;
|
||||
use Test::More tests => 8;
|
||||
use Test::NoWarnings;
|
||||
use DBI qw(:sql_types);
|
||||
|
||||
|
@ -51,6 +51,16 @@ $sth->execute;
|
|||
$ar = $sth->fetchall_arrayref;
|
||||
is( scalar(@$ar), 2, 'Got 2 results' );
|
||||
|
||||
# known workaround 3
|
||||
{
|
||||
local $dbh->{sqlite_see_if_its_a_number} = 1;
|
||||
my $sth = $dbh->selectall_arrayref(
|
||||
'SELECT bar FROM foo GROUP BY bar HAVING count(*) > ?',
|
||||
undef, 1
|
||||
);
|
||||
is( scalar(@$ar), 2, 'Got 2 results' );
|
||||
}
|
||||
|
||||
# and this is what should be tested
|
||||
#TODO: {
|
||||
local $TODO = 'This test is currently broken again. Wait for a better fix, or use known workarounds shown above';
|
||||
|
|
|
@ -7,7 +7,7 @@ BEGIN {
|
|||
}
|
||||
|
||||
use t::lib::Test;
|
||||
use Test::More tests => 17;
|
||||
use Test::More tests => 19;
|
||||
use Test::NoWarnings;
|
||||
use DBI qw(:sql_types);
|
||||
|
||||
|
@ -74,8 +74,15 @@ is( $sth->fetchrow_arrayref->[0], 1, "result of: $statement : [2]" );
|
|||
|
||||
# known workarounds 2: add "+0" to let sqlite convert the binded param into number
|
||||
|
||||
$statement =~ s/\?/\?\+0/;
|
||||
$sth = $dbh->prepare($statement);
|
||||
ok( $sth->execute(2), "execute: $statement : [2]" );
|
||||
is( $sth->fetchrow_arrayref->[0], 1, "result of: $statement : [2]" );
|
||||
(my $tweaked_statement = $statement) =~ s/\?/\?\+0/;
|
||||
$sth = $dbh->prepare($tweaked_statement);
|
||||
ok( $sth->execute(2), "execute: $tweaked_statement : [2]" );
|
||||
is( $sth->fetchrow_arrayref->[0], 1, "result of: $tweaked_statement : [2]" );
|
||||
|
||||
# workaround 3: use sqlite_see_if_its_a_number attribute
|
||||
{
|
||||
local $dbh->{sqlite_see_if_its_a_number} = 1;
|
||||
$sth = $dbh->prepare($statement);
|
||||
ok( $sth->execute(2), "execute: $statement : [2]" );
|
||||
is( $sth->fetchrow_arrayref->[0], 1, "result of: $statement : [2]" );
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue