| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | #if !defined(SQLITE_CORE) || !defined(SQLITE_OMIT_VIRTUALTABLE) |
| | #if !defined(SQLITEINT_H) |
| | #include "sqlite3ext.h" |
| | #endif |
| | SQLITE_EXTENSION_INIT1 |
| | #include <string.h> |
| | #include <assert.h> |
| |
|
| | |
| | |
| | |
| | typedef struct prefixes_vtab prefixes_vtab; |
| | struct prefixes_vtab { |
| | sqlite3_vtab base; |
| | |
| | }; |
| |
|
| | |
| | |
| | |
| | |
| | typedef struct prefixes_cursor prefixes_cursor; |
| | struct prefixes_cursor { |
| | sqlite3_vtab_cursor base; |
| | sqlite3_int64 iRowid; |
| | char *zStr; |
| | int nStr; |
| | }; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | static int prefixesConnect( |
| | sqlite3 *db, |
| | void *pAux, |
| | int argc, const char *const*argv, |
| | sqlite3_vtab **ppVtab, |
| | char **pzErr |
| | ){ |
| | prefixes_vtab *pNew; |
| | int rc; |
| |
|
| | rc = sqlite3_declare_vtab(db, |
| | "CREATE TABLE prefixes(prefix TEXT, original_string TEXT HIDDEN)" |
| | ); |
| | if( rc==SQLITE_OK ){ |
| | pNew = sqlite3_malloc( sizeof(*pNew) ); |
| | *ppVtab = (sqlite3_vtab*)pNew; |
| | if( pNew==0 ) return SQLITE_NOMEM; |
| | memset(pNew, 0, sizeof(*pNew)); |
| | sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS); |
| | } |
| | return rc; |
| | } |
| |
|
| | |
| | |
| | |
| | static int prefixesDisconnect(sqlite3_vtab *pVtab){ |
| | prefixes_vtab *p = (prefixes_vtab*)pVtab; |
| | sqlite3_free(p); |
| | return SQLITE_OK; |
| | } |
| |
|
| | |
| | |
| | |
| | static int prefixesOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ |
| | prefixes_cursor *pCur; |
| | pCur = sqlite3_malloc( sizeof(*pCur) ); |
| | if( pCur==0 ) return SQLITE_NOMEM; |
| | memset(pCur, 0, sizeof(*pCur)); |
| | *ppCursor = &pCur->base; |
| | return SQLITE_OK; |
| | } |
| |
|
| | |
| | |
| | |
| | static int prefixesClose(sqlite3_vtab_cursor *cur){ |
| | prefixes_cursor *pCur = (prefixes_cursor*)cur; |
| | sqlite3_free(pCur->zStr); |
| | sqlite3_free(pCur); |
| | return SQLITE_OK; |
| | } |
| |
|
| |
|
| | |
| | |
| | |
| | static int prefixesNext(sqlite3_vtab_cursor *cur){ |
| | prefixes_cursor *pCur = (prefixes_cursor*)cur; |
| | pCur->iRowid++; |
| | return SQLITE_OK; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | static int prefixesColumn( |
| | sqlite3_vtab_cursor *cur, |
| | sqlite3_context *ctx, |
| | int i |
| | ){ |
| | prefixes_cursor *pCur = (prefixes_cursor*)cur; |
| | switch( i ){ |
| | case 0: |
| | sqlite3_result_text(ctx, pCur->zStr, pCur->nStr - (int)pCur->iRowid, |
| | 0); |
| | break; |
| | default: |
| | sqlite3_result_text(ctx, pCur->zStr, pCur->nStr, 0); |
| | break; |
| | } |
| | return SQLITE_OK; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | static int prefixesRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ |
| | prefixes_cursor *pCur = (prefixes_cursor*)cur; |
| | *pRowid = pCur->iRowid; |
| | return SQLITE_OK; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | static int prefixesEof(sqlite3_vtab_cursor *cur){ |
| | prefixes_cursor *pCur = (prefixes_cursor*)cur; |
| | return pCur->iRowid>pCur->nStr; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | static int prefixesFilter( |
| | sqlite3_vtab_cursor *pVtabCursor, |
| | int idxNum, const char *idxStr, |
| | int argc, sqlite3_value **argv |
| | ){ |
| | prefixes_cursor *pCur = (prefixes_cursor *)pVtabCursor; |
| | sqlite3_free(pCur->zStr); |
| | if( argc>0 ){ |
| | pCur->zStr = sqlite3_mprintf("%s", sqlite3_value_text(argv[0])); |
| | pCur->nStr = pCur->zStr ? (int)strlen(pCur->zStr) : 0; |
| | }else{ |
| | pCur->zStr = 0; |
| | pCur->nStr = 0; |
| | } |
| | pCur->iRowid = 0; |
| | return SQLITE_OK; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | static int prefixesBestIndex( |
| | sqlite3_vtab *tab, |
| | sqlite3_index_info *pIdxInfo |
| | ){ |
| | |
| | |
| | int i; |
| | const struct sqlite3_index_constraint *p; |
| |
|
| | for(i=0, p=pIdxInfo->aConstraint; i<pIdxInfo->nConstraint; i++, p++){ |
| | if( p->iColumn!=1 ) continue; |
| | if( p->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue; |
| | if( !p->usable ) continue; |
| | pIdxInfo->aConstraintUsage[i].argvIndex = 1; |
| | pIdxInfo->aConstraintUsage[i].omit = 1; |
| | pIdxInfo->estimatedCost = (double)10; |
| | pIdxInfo->estimatedRows = 10; |
| | return SQLITE_OK; |
| | } |
| | pIdxInfo->estimatedCost = (double)1000000000; |
| | pIdxInfo->estimatedRows = 1000000000; |
| | return SQLITE_OK; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | static sqlite3_module prefixesModule = { |
| | 0, |
| | 0, |
| | prefixesConnect, |
| | prefixesBestIndex, |
| | prefixesDisconnect, |
| | 0, |
| | prefixesOpen, |
| | prefixesClose, |
| | prefixesFilter, |
| | prefixesNext, |
| | prefixesEof, |
| | prefixesColumn, |
| | prefixesRowid, |
| | 0, |
| | 0, |
| | 0, |
| | 0, |
| | 0, |
| | 0, |
| | 0, |
| | 0, |
| | 0, |
| | 0, |
| | 0, |
| | 0 |
| | }; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | #define PREFIX_SKIP_UTF8(zIn) { \ |
| | if( (*(zIn++))>=0xc0 ){ \ |
| | while( (*zIn & 0xc0)==0x80 ){ zIn++; } \ |
| | } \ |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | static void prefixLengthFunc( |
| | sqlite3_context *ctx, |
| | int nVal, |
| | sqlite3_value **apVal |
| | ){ |
| | int nByte; |
| | int nRet = 0; |
| | const unsigned char *zL = sqlite3_value_text(apVal[0]); |
| | const unsigned char *zR = sqlite3_value_text(apVal[1]); |
| | int nL = sqlite3_value_bytes(apVal[0]); |
| | int nR = sqlite3_value_bytes(apVal[1]); |
| | int i; |
| |
|
| | nByte = (nL > nR ? nL : nR); |
| | for(i=0; i<nByte; i++){ |
| | if( zL[i]!=zR[i] ) break; |
| | if( (zL[i] & 0xC0)!=0x80 ) nRet++; |
| | } |
| |
|
| | if( (zL[i] & 0xC0)==0x80 ) nRet--; |
| | sqlite3_result_int(ctx, nRet); |
| | } |
| |
|
| | #ifdef _WIN32 |
| | __declspec(dllexport) |
| | #endif |
| | int sqlite3_prefixes_init( |
| | sqlite3 *db, |
| | char **pzErrMsg, |
| | const sqlite3_api_routines *pApi |
| | ){ |
| | int rc = SQLITE_OK; |
| | SQLITE_EXTENSION_INIT2(pApi); |
| | rc = sqlite3_create_module(db, "prefixes", &prefixesModule, 0); |
| | if( rc==SQLITE_OK ){ |
| | rc = sqlite3_create_function( |
| | db, "prefix_length", 2, SQLITE_UTF8, 0, prefixLengthFunc, 0, 0 |
| | ); |
| | } |
| | return rc; |
| | } |
| | #endif |
| |
|