From b38e57a23b4e4b5c3b5b115558e12950f393b323 Mon Sep 17 00:00:00 2001 From: Kenichi Ishigaki Date: Thu, 7 Jan 2016 19:47:10 +0900 Subject: [PATCH] LIKE/GLOB/REGEXP are also required to be implemented for SQLite 3.10.0 and above MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Petr Písař --- SQLite.xs | 18 ++++++++++++++++++ dbdimp.c | 8 ++++++++ lib/DBD/SQLite/VirtualTable/PerlData.pm | 24 +++++++++++++++++------- 3 files changed, 43 insertions(+), 7 deletions(-) diff --git a/SQLite.xs b/SQLite.xs index abe3524..bc6644b 100644 --- a/SQLite.xs +++ b/SQLite.xs @@ -363,5 +363,23 @@ sqlite_status(reset = 0) OUTPUT: RETVAL +#if SQLITE_VERSION_NUMBER >= 3010000 + +int +strglob(const char *zglob, const char *zstr) + CODE: + RETVAL = sqlite3_strglob(zglob, zstr); + OUTPUT: + RETVAL + +int +strlike(const char *zglob, const char *zstr, unsigned int esc = 0) + CODE: + RETVAL = sqlite3_strlike(zglob, zstr, esc); + OUTPUT: + RETVAL + +#endif + INCLUDE: constants.inc INCLUDE: SQLite.xsi diff --git a/dbdimp.c b/dbdimp.c index a4e426b..b441940 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -3129,6 +3129,14 @@ _constraint_op_to_string(unsigned char op) { return "<="; case SQLITE_INDEX_CONSTRAINT_MATCH: return "MATCH"; +#if SQLITE_VERSION_NUMBER >= 3010000 + case SQLITE_INDEX_CONSTRAINT_LIKE: + return "LIKE"; + case SQLITE_INDEX_CONSTRAINT_GLOB: + return "GLOB"; + case SQLITE_INDEX_CONSTRAINT_REGEXP: + return "REGEXP"; +#endif default: return "unknown"; } diff --git a/lib/DBD/SQLite/VirtualTable/PerlData.pm b/lib/DBD/SQLite/VirtualTable/PerlData.pm index 7bbcb0d..8151fe1 100644 --- a/lib/DBD/SQLite/VirtualTable/PerlData.pm +++ b/lib/DBD/SQLite/VirtualTable/PerlData.pm @@ -4,7 +4,8 @@ package DBD::SQLite::VirtualTable::PerlData; use strict; use warnings; use base 'DBD::SQLite::VirtualTable'; - +use DBD::SQLite; +use constant SQLITE_3010000 => $DBD::SQLite::sqlite_version_number >= 3010000 ? 1 : 0; # private data for translating comparison operators from Sqlite to Perl my $TXT = 0; @@ -17,6 +18,11 @@ my %SQLOP2PERLOP = ( '>' => [ 'gt', '>' ], '>=' => [ 'ge', '>=' ], 'MATCH' => [ '=~', '=~' ], + (SQLITE_3010000 ? ( + 'LIKE' => [ 'DBD::SQLite::strlike', 'DBD::SQLite::strlike' ], + 'GLOB' => [ 'DBD::SQLite::strglob', 'DBD::SQLite::strglob' ], + 'REGEXP'=> [ '=~', '=~' ], + ) : ()), ); #---------------------------------------------------------------------- @@ -95,12 +101,16 @@ sub BEST_INDEX { $optype = $self->{optypes}[$col]; } my $op = $SQLOP2PERLOP{$constraint->{op}}[$optype]; - push @conditions, - "(defined($member) && defined(\$vals[$ix]) && $member $op \$vals[$ix])"; - # Note : $vals[$ix] refers to an array of values passed to the - # FILTER method (see below); so the eval-ed perl code will be a - # closure on those values - + if (SQLITE_3010000 && $op =~ /str/) { + push @conditions, + "(defined($member) && defined(\$vals[$ix]) && !$op(\$vals[$ix], $member))"; + } else { + push @conditions, + "(defined($member) && defined(\$vals[$ix]) && $member $op \$vals[$ix])"; + } + # Note : $vals[$ix] refers to an array of values passed to the + # FILTER method (see below); so the eval-ed perl code will be a + # closure on those values # info passed back to the SQLite core -- see vtab.html in sqlite doc $constraint->{argvIndex} = $ix++; $constraint->{omit} = 1; -- 2.5.0