Permalink
Please sign in to comment.
Showing
with
153 additions
and 0 deletions.
- +1 −0 .exrc
- +1 −0 .gear-rules
- +108 −0 pcre.c
- +43 −0 sqlite3-pcre.spec
1
.exrc
| @@ -0,0 +1 @@ | ||
| +set ts=8 sts=4 sw=4 noet |
| @@ -0,0 +1 @@ | ||
| +tar: . |
108
pcre.c
| @@ -0,0 +1,108 @@ | ||
| +#include <assert.h> | ||
| +#include <stdlib.h> | ||
| +#include <string.h> | ||
| +#include <pcre.h> | ||
| +#include <sqlite3ext.h> | ||
| +SQLITE_EXTENSION_INIT1 | ||
| + | ||
| +typedef struct { | ||
| + char *s; | ||
| + pcre *p; | ||
| + pcre_extra *e; | ||
| +} cache_entry; | ||
| + | ||
| +#define CACHE_SIZE 16 | ||
| + | ||
| +static | ||
| +void regexp(sqlite3_context *ctx, int argc, sqlite3_value **argv) | ||
| +{ | ||
| + const char *re, *str; | ||
| + pcre *p; | ||
| + pcre_extra *e; | ||
| + | ||
| + assert(argc == 2); | ||
| + | ||
| + re = (const char *) sqlite3_value_text(argv[0]); | ||
| + if (!re) { | ||
| + sqlite3_result_error(ctx, "no regexp", -1); | ||
| + return; | ||
| + } | ||
| + | ||
| + str = (const char *) sqlite3_value_text(argv[1]); | ||
| + if (!str) { | ||
| + sqlite3_result_error(ctx, "no string", -1); | ||
| + return; | ||
| + } | ||
| + | ||
| + /* simple LRU cache */ | ||
| + { | ||
| + int i; | ||
| + int found = 0; | ||
| + cache_entry *cache = sqlite3_user_data(ctx); | ||
| + | ||
| + assert(cache); | ||
| + | ||
| + for (i = 0; i < CACHE_SIZE && cache[i].s; i++) | ||
| + if (strcmp(re, cache[i].s) == 0) { | ||
| + found = 1; | ||
| + break; | ||
| + } | ||
| + if (found) { | ||
| + if (i > 0) { | ||
| + cache_entry c = cache[i]; | ||
| + memmove(cache + 1, cache, i * sizeof(cache_entry)); | ||
| + cache[0] = c; | ||
| + } | ||
| + } | ||
| + else { | ||
| + cache_entry c; | ||
| + const char *err; | ||
| + int pos; | ||
| + c.p = pcre_compile(re, 0, &err, &pos, NULL); | ||
| + if (!c.p) { | ||
| + char *e2 = sqlite3_mprintf("%s: %s (offset %d)", re, err, pos); | ||
| + sqlite3_result_error(ctx, e2, -1); | ||
| + sqlite3_free(e2); | ||
| + return; | ||
| + } | ||
| + c.e = pcre_study(c.p, 0, &err); | ||
| + c.s = strdup(re); | ||
| + if (!c.s) { | ||
| + sqlite3_result_error(ctx, "strdup: ENOMEM", -1); | ||
| + pcre_free(c.p); | ||
| + pcre_free(c.e); | ||
| + return; | ||
| + } | ||
| + if (cache[CACHE_SIZE-1].s) { | ||
| + free(cache[CACHE_SIZE-1].s); | ||
| + assert(cache[CACHE_SIZE-1].p); | ||
| + pcre_free(cache[CACHE_SIZE-1].p); | ||
| + pcre_free(cache[CACHE_SIZE-1].e); | ||
| + } | ||
| + memmove(cache + 1, cache, (CACHE_SIZE - 1) * sizeof(cache_entry)); | ||
| + cache[0] = c; | ||
| + } | ||
| + p = cache[0].p; | ||
| + e = cache[0].e; | ||
| + } | ||
| + | ||
| + { | ||
| + int rc; | ||
| + assert(p); | ||
| + rc = pcre_exec(p, e, str, strlen(str), 0, 0, NULL, 0); | ||
| + sqlite3_result_int(ctx, rc >= 0); | ||
| + return; | ||
| + } | ||
| +} | ||
| + | ||
| +int sqlite3_extension_init(sqlite3 *db, char **err, const sqlite3_api_routines *api) | ||
| +{ | ||
| + SQLITE_EXTENSION_INIT2(api) | ||
| + cache_entry *cache = calloc(CACHE_SIZE, sizeof(cache_entry)); | ||
| + if (!cache) { | ||
| + *err = "calloc: ENOMEM"; | ||
| + return 1; | ||
| + } | ||
| + sqlite3_create_function(db, "REGEXP", 2, SQLITE_UTF8, cache, regexp, NULL, NULL); | ||
| + return 0; | ||
| +} |
| @@ -0,0 +1,43 @@ | ||
| +Name: sqlite3-pcre | ||
| +Version: 0.1 | ||
| +Release: alt1 | ||
| + | ||
| +Summary: Perl-compatible regular expression support for the SQLite | ||
| +License: XXX (GPL or Public Domain) | ||
| +Group: Databases | ||
| + | ||
| +Source: %name-%version.tar | ||
| + | ||
| +# Automatically added by buildreq on Thu Nov 02 2006 | ||
| +BuildRequires: libpcre-devel libsqlite3-devel sqlite3 | ||
| + | ||
| +%description | ||
| +This SQLite loadable extensing enables the REGEXP operator, | ||
| +which is not implemented by default, to call PCRE routines | ||
| +for regular expression matching. | ||
| + | ||
| +%prep | ||
| +%setup -q | ||
| + | ||
| +%build | ||
| +cflags=`pkg-config --cflags sqlite3 libpcre` | ||
| +libs=`pkg-config --libs sqlite3 libpcre` | ||
| +gcc -shared -o pcre.so $cflags %optflags %optflags_shared -W -Werror pcre.c $libs -Wl,-z,defs | ||
| + | ||
| +#check | ||
| +sqlite3 >out <<EOF | ||
| +.load ./pcre.so | ||
| +SELECT "asdf" REGEXP "(?i)^A"; | ||
| +EOF | ||
| +grep 1 out | ||
| + | ||
| +%install | ||
| +install -pD -m755 pcre.so %buildroot%_libdir/sqlite3/pcre.so | ||
| + | ||
| +%files | ||
| +%dir %_libdir/sqlite3 | ||
| +%_libdir/sqlite3/pcre.so | ||
| + | ||
| +%changelog | ||
| +* Thu Nov 02 2006 Alexey Tourbin <at@altlinux.ru> 0.1-alt1 | ||
| +- initial revision |
0 comments on commit
c9b9705