Skip to content

Commit

Permalink
initial revision
Browse files Browse the repository at this point in the history
  • Loading branch information
svpv committed Nov 2, 2006
0 parents commit c9b9705
Show file tree
Hide file tree
Showing 4 changed files with 153 additions and 0 deletions.
1 change: 1 addition & 0 deletions .exrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
set ts=8 sts=4 sw=4 noet
1 change: 1 addition & 0 deletions .gear-rules
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
tar: .
108 changes: 108 additions & 0 deletions pcre.c
Original file line number Diff line number Diff line change
@@ -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;
}
43 changes: 43 additions & 0 deletions sqlite3-pcre.spec
Original file line number Diff line number Diff line change
@@ -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 <[email protected]> 0.1-alt1
- initial revision

0 comments on commit c9b9705

Please sign in to comment.