diff --git a/MANIFEST b/MANIFEST index f2a4c42..9b30654 100644 --- a/MANIFEST +++ b/MANIFEST @@ -89,6 +89,7 @@ t/60_readonly.t t/61_strlike.t t/62_regexp_multibyte_char_class.t t/63_param_values.t +t/64_limit.t t/cookbook_variance.t t/lib/SQLiteTest.pm t/rt_106151_outermost_savepoint.t diff --git a/SQLite.xs b/SQLite.xs index 5b51aef..2712ac6 100644 --- a/SQLite.xs +++ b/SQLite.xs @@ -318,6 +318,19 @@ create_module(dbh, name, perl_class) OUTPUT: RETVAL +static int +limit(dbh, id, new_value = -1) + SV *dbh + int id + int new_value + ALIAS: + DBD::SQLite::db::sqlite_limit = 1 + CODE: + { + RETVAL = sqlite_db_limit(aTHX_ dbh, id, new_value); + } + OUTPUT: + RETVAL MODULE = DBD::SQLite PACKAGE = DBD::SQLite::st diff --git a/dbdimp.c b/dbdimp.c index 4ef2805..219a597 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -2652,6 +2652,13 @@ sqlite_db_backup_to_file(pTHX_ SV *dbh, char *filename) #endif } +int +sqlite_db_limit(pTHX_ SV *dbh, int id, int new_value) +{ + D_imp_dbh(dbh); + return sqlite3_limit(imp_dbh->db, id, new_value); +} + #include "dbdimp_tokenizer.inc" #include "dbdimp_virtual_table.inc" diff --git a/dbdimp.h b/dbdimp.h index 880bf37..b86f1c0 100644 --- a/dbdimp.h +++ b/dbdimp.h @@ -131,6 +131,7 @@ int sqlite_db_register_fts3_perl_tokenizer(pTHX_ SV *dbh); HV* _sqlite_status(int reset); HV* _sqlite_st_status(pTHX_ SV *sth, int reset); int sqlite_db_create_module(pTHX_ SV *dbh, const char *name, const char *perl_class); +int sqlite_db_limit(pTHX_ SV *dbh, int id, int new_value); int sqlite_db_do_sv(SV *dbh, imp_dbh_t *imp_dbh, SV *sv_statement); void init_cxt(); diff --git a/lib/DBD/SQLite.pm b/lib/DBD/SQLite.pm index 5641557..19e4294 100644 --- a/lib/DBD/SQLite.pm +++ b/lib/DBD/SQLite.pm @@ -57,6 +57,7 @@ sub driver { DBD::SQLite::db->install_method('sqlite_db_status', { O => 0x0004 }); DBD::SQLite::st->install_method('sqlite_st_status', { O => 0x0004 }); DBD::SQLite::db->install_method('sqlite_create_module'); + DBD::SQLite::db->install_method('sqlite_limit'); $methods_are_installed++; } @@ -2266,6 +2267,13 @@ registered before creating a new virtual table using the module and before using a preexisting virtual table for the module. Virtual tables are explained in L. +=head2 $dbh->sqlite_limit( $category_id, $new_value ) + +Sets a new run-time limit for the category, and returns the current limit. +If the new value is a negative number (or omitted), the limit is unchanged +and just returns the current limit. Category ids (SQLITE_LIMIT_LENGTH, +SQLITE_LIMIT_VARIABLE_NUMBER, etc) can be imported from DBD::SQLite::Constants. + =head1 DRIVER FUNCTIONS =head2 DBD::SQLite::compile_options() diff --git a/t/64_limit.t b/t/64_limit.t new file mode 100644 index 0000000..3a74935 --- /dev/null +++ b/t/64_limit.t @@ -0,0 +1,30 @@ +#!/usr/bin/perl + +use strict; +BEGIN { + $| = 1; + $^W = 1; +} + +use lib "t/lib"; +use SQLiteTest qw/connect_ok @CALL_FUNCS/; +use Test::More; +use DBD::SQLite::Constants qw/SQLITE_LIMIT_VARIABLE_NUMBER/; + +plan tests => 14; + +for my $func (@CALL_FUNCS) { + my $dbh = connect_ok(PrintError => 0, RaiseError => 1); + my $current_limit = $dbh->$func(SQLITE_LIMIT_VARIABLE_NUMBER, 'limit'); + ok $current_limit, "current limit: $current_limit"; + + $current_limit = $dbh->$func(SQLITE_LIMIT_VARIABLE_NUMBER, -1, 'limit'); + ok $current_limit, "current limit: $current_limit"; + + ok $dbh->do('create table foo (id, text)'); + ok $dbh->do('insert into foo values(?, ?)', undef, 1, 'OK'); + + ok $dbh->$func(SQLITE_LIMIT_VARIABLE_NUMBER, 1, 'limit'); + eval { $dbh->do('insert into foo values(?, ?)', undef, 2, 'NOT OK') }; + like $@ => qr/too many SQL variables/, "should raise error because of the variable limit"; +}