Permalink
Browse files

initial revision

  • Loading branch information...
0 parents commit c9b9705e576b63ccb12eed71e1218cfd74239f71 @svpv svpv committed Nov 1, 2006
Showing with 153 additions and 0 deletions.
  1. +1 −0 .exrc
  2. +1 −0 .gear-rules
  3. +108 −0 pcre.c
  4. +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

Please sign in to comment.