├── .exrc ├── .gear-rules ├── Makefile ├── pcre.c ├── readme.txt └── sqlite3-pcre.spec /.exrc: -------------------------------------------------------------------------------- 1 | set ts=8 sts=4 sw=4 noet 2 | -------------------------------------------------------------------------------- /.gear-rules: -------------------------------------------------------------------------------- 1 | tar: . 2 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | VERSION=0.1.1 2 | CC=cc 3 | INSTALL=install 4 | CFLAGS=$(shell pkg-config --cflags sqlite3 libpcre) -fPIC 5 | LIBS=$(shell pkg-config --libs libpcre) 6 | prefix=/usr 7 | 8 | .PHONY : install dist clean 9 | 10 | pcre.so : pcre.c 11 | ${CC} -shared -o $@ ${CFLAGS} -W -Werror pcre.c ${LIBS} -Wl,-z,defs 12 | 13 | install : pcre.so 14 | ${INSTALL} -pD -m755 pcre.so ${DESTDIR}${prefix}/lib/sqlite3/pcre.so 15 | 16 | dist : clean 17 | mkdir sqlite3-pcre-${VERSION} 18 | cp -f pcre.c Makefile readme.txt sqlite3-pcre-${VERSION} 19 | tar -czf sqlite3-pcre-${VERSION}.tar.gz sqlite3-pcre-${VERSION} 20 | 21 | clean : 22 | -rm -f pcre.so 23 | -------------------------------------------------------------------------------- /pcre.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Written by Alexey Tourbin . 3 | * 4 | * The author has dedicated the code to the public domain. Anyone is free 5 | * to copy, modify, publish, use, compile, sell, or distribute the original 6 | * code, either in source code form or as a compiled binary, for any purpose, 7 | * commercial or non-commercial, and by any means. 8 | */ 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | SQLITE_EXTENSION_INIT1 15 | 16 | typedef struct { 17 | char *s; 18 | pcre *p; 19 | pcre_extra *e; 20 | } cache_entry; 21 | 22 | #ifndef CACHE_SIZE 23 | #define CACHE_SIZE 16 24 | #endif 25 | 26 | static 27 | void regexp(sqlite3_context *ctx, int argc, sqlite3_value **argv) 28 | { 29 | const char *re, *str; 30 | pcre *p; 31 | pcre_extra *e; 32 | 33 | assert(argc == 2); 34 | 35 | re = (const char *) sqlite3_value_text(argv[0]); 36 | if (!re) { 37 | sqlite3_result_error(ctx, "no regexp", -1); 38 | return; 39 | } 40 | 41 | str = (const char *) sqlite3_value_text(argv[1]); 42 | if (!str) { 43 | sqlite3_result_error(ctx, "no string", -1); 44 | return; 45 | } 46 | 47 | /* simple LRU cache */ 48 | { 49 | int i; 50 | int found = 0; 51 | cache_entry *cache = sqlite3_user_data(ctx); 52 | 53 | assert(cache); 54 | 55 | for (i = 0; i < CACHE_SIZE && cache[i].s; i++) 56 | if (strcmp(re, cache[i].s) == 0) { 57 | found = 1; 58 | break; 59 | } 60 | if (found) { 61 | if (i > 0) { 62 | cache_entry c = cache[i]; 63 | memmove(cache + 1, cache, i * sizeof(cache_entry)); 64 | cache[0] = c; 65 | } 66 | } 67 | else { 68 | cache_entry c; 69 | const char *err; 70 | int pos; 71 | c.p = pcre_compile(re, 0, &err, &pos, NULL); 72 | if (!c.p) { 73 | char *e2 = sqlite3_mprintf("%s: %s (offset %d)", re, err, pos); 74 | sqlite3_result_error(ctx, e2, -1); 75 | sqlite3_free(e2); 76 | return; 77 | } 78 | c.e = pcre_study(c.p, 0, &err); 79 | c.s = strdup(re); 80 | if (!c.s) { 81 | sqlite3_result_error(ctx, "strdup: ENOMEM", -1); 82 | pcre_free(c.p); 83 | pcre_free(c.e); 84 | return; 85 | } 86 | i = CACHE_SIZE - 1; 87 | if (cache[i].s) { 88 | free(cache[i].s); 89 | assert(cache[i].p); 90 | pcre_free(cache[i].p); 91 | pcre_free(cache[i].e); 92 | } 93 | memmove(cache + 1, cache, i * sizeof(cache_entry)); 94 | cache[0] = c; 95 | } 96 | p = cache[0].p; 97 | e = cache[0].e; 98 | } 99 | 100 | { 101 | int rc; 102 | assert(p); 103 | rc = pcre_exec(p, e, str, strlen(str), 0, 0, NULL, 0); 104 | sqlite3_result_int(ctx, rc >= 0); 105 | return; 106 | } 107 | } 108 | 109 | int sqlite3_extension_init(sqlite3 *db, char **err, const sqlite3_api_routines *api) 110 | { 111 | SQLITE_EXTENSION_INIT2(api) 112 | cache_entry *cache = calloc(CACHE_SIZE, sizeof(cache_entry)); 113 | if (!cache) { 114 | *err = "calloc: ENOMEM"; 115 | return 1; 116 | } 117 | sqlite3_create_function(db, "REGEXP", 2, SQLITE_UTF8, cache, regexp, NULL, NULL); 118 | return 0; 119 | } 120 | -------------------------------------------------------------------------------- /readme.txt: -------------------------------------------------------------------------------- 1 | This is sqlite3-pcre, an extension for sqlite3 that uses libpcre to provide 2 | the REGEXP() function. 3 | 4 | The code was written by Alexey Tourbin and can be found at: 5 | 6 | http://git.altlinux.org/people/at/packages/?p=sqlite3-pcre.git 7 | 8 | -------------------------------------------------------------------------------- /sqlite3-pcre.spec: -------------------------------------------------------------------------------- 1 | Name: sqlite3-pcre 2 | Version: 0.1.1 3 | Release: 0 4 | 5 | Summary: Perl-compatible regular expression support for the SQLite 6 | License: Public Domain 7 | Group: Databases 8 | URL: http://git.altlinux.org/people/at/packages/?p=sqlite3-pcre.git 9 | 10 | Source: %name-%version.tar.gz 11 | 12 | Requires: libsqlite3 >= 3.3.8-alt2 13 | 14 | # Automatically added by buildreq on Thu Nov 02 2006 15 | BuildRequires: libpcre-devel libsqlite3-devel sqlite3 16 | 17 | #%if %{defined suse_version} 18 | #Requires: libsqlite3 >= 3.3.8 libpcre0 19 | #BuildRequires: pcre-devel sqlite3-devel sqlite3 20 | #%endif 21 | 22 | #%if %{defined fedora} || %{defined mdkversion} 23 | #Requires: libsqlite >= 3.3.8 libpcre0 24 | #BuildRequires: pcre-devel sqlite-devel sqlite 25 | #%endif 26 | 27 | %description 28 | This SQLite loadable extension enables the REGEXP operator, 29 | which is not implemented by default, to call PCRE routines 30 | for regular expression matching. 31 | 32 | %prep 33 | %setup -q 34 | 35 | %build 36 | make 37 | 38 | #check 39 | sqlite3 >out < 0.1-alt1 54 | - initial revision 55 | --------------------------------------------------------------------------------