xref: /sqlite-3.40.0/ext/misc/prefixes.c (revision 4ead9634)
1*4ead9634Sdrh /*
2*4ead9634Sdrh ** 2018-04-19
3*4ead9634Sdrh **
4*4ead9634Sdrh ** The author disclaims copyright to this source code.  In place of
5*4ead9634Sdrh ** a legal notice, here is a blessing:
6*4ead9634Sdrh **
7*4ead9634Sdrh **    May you do good and not evil.
8*4ead9634Sdrh **    May you find forgiveness for yourself and forgive others.
9*4ead9634Sdrh **    May you share freely, never taking more than you give.
10*4ead9634Sdrh **
11*4ead9634Sdrh *************************************************************************
12*4ead9634Sdrh **
13*4ead9634Sdrh ** This file implements a table-valued function:
14*4ead9634Sdrh **
15*4ead9634Sdrh **      prefixes('abcdefg')
16*4ead9634Sdrh **
17*4ead9634Sdrh ** The function has a single (non-HIDDEN) column named prefix that takes
18*4ead9634Sdrh ** on all prefixes of the string in its argument, including an empty string
19*4ead9634Sdrh ** and the input string itself.  The order of prefixes is from longest
20*4ead9634Sdrh ** to shortest.
21*4ead9634Sdrh */
22*4ead9634Sdrh #if !defined(SQLITEINT_H)
23*4ead9634Sdrh #include "sqlite3ext.h"
24*4ead9634Sdrh #endif
25*4ead9634Sdrh SQLITE_EXTENSION_INIT1
26*4ead9634Sdrh #include <string.h>
27*4ead9634Sdrh #include <assert.h>
28*4ead9634Sdrh 
29*4ead9634Sdrh /* prefixes_vtab is a subclass of sqlite3_vtab which is
30*4ead9634Sdrh ** underlying representation of the virtual table
31*4ead9634Sdrh */
32*4ead9634Sdrh typedef struct prefixes_vtab prefixes_vtab;
33*4ead9634Sdrh struct prefixes_vtab {
34*4ead9634Sdrh   sqlite3_vtab base;  /* Base class - must be first */
35*4ead9634Sdrh   /* No additional fields are necessary */
36*4ead9634Sdrh };
37*4ead9634Sdrh 
38*4ead9634Sdrh /* prefixes_cursor is a subclass of sqlite3_vtab_cursor which will
39*4ead9634Sdrh ** serve as the underlying representation of a cursor that scans
40*4ead9634Sdrh ** over rows of the result
41*4ead9634Sdrh */
42*4ead9634Sdrh typedef struct prefixes_cursor prefixes_cursor;
43*4ead9634Sdrh struct prefixes_cursor {
44*4ead9634Sdrh   sqlite3_vtab_cursor base;  /* Base class - must be first */
45*4ead9634Sdrh   sqlite3_int64 iRowid;      /* The rowid */
46*4ead9634Sdrh   char *zStr;                /* Original string to be prefixed */
47*4ead9634Sdrh   int nStr;                  /* Length of the string in bytes */
48*4ead9634Sdrh };
49*4ead9634Sdrh 
50*4ead9634Sdrh /*
51*4ead9634Sdrh ** The prefixesConnect() method is invoked to create a new
52*4ead9634Sdrh ** template virtual table.
53*4ead9634Sdrh **
54*4ead9634Sdrh ** Think of this routine as the constructor for prefixes_vtab objects.
55*4ead9634Sdrh **
56*4ead9634Sdrh ** All this routine needs to do is:
57*4ead9634Sdrh **
58*4ead9634Sdrh **    (1) Allocate the prefixes_vtab object and initialize all fields.
59*4ead9634Sdrh **
60*4ead9634Sdrh **    (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
61*4ead9634Sdrh **        result set of queries against the virtual table will look like.
62*4ead9634Sdrh */
63*4ead9634Sdrh static int prefixesConnect(
64*4ead9634Sdrh   sqlite3 *db,
65*4ead9634Sdrh   void *pAux,
66*4ead9634Sdrh   int argc, const char *const*argv,
67*4ead9634Sdrh   sqlite3_vtab **ppVtab,
68*4ead9634Sdrh   char **pzErr
69*4ead9634Sdrh ){
70*4ead9634Sdrh   prefixes_vtab *pNew;
71*4ead9634Sdrh   int rc;
72*4ead9634Sdrh 
73*4ead9634Sdrh   rc = sqlite3_declare_vtab(db,
74*4ead9634Sdrh            "CREATE TABLE prefixes(prefix TEXT, original_string TEXT HIDDEN)"
75*4ead9634Sdrh        );
76*4ead9634Sdrh   if( rc==SQLITE_OK ){
77*4ead9634Sdrh     pNew = sqlite3_malloc( sizeof(*pNew) );
78*4ead9634Sdrh     *ppVtab = (sqlite3_vtab*)pNew;
79*4ead9634Sdrh     if( pNew==0 ) return SQLITE_NOMEM;
80*4ead9634Sdrh     memset(pNew, 0, sizeof(*pNew));
81*4ead9634Sdrh   }
82*4ead9634Sdrh   return rc;
83*4ead9634Sdrh }
84*4ead9634Sdrh 
85*4ead9634Sdrh /*
86*4ead9634Sdrh ** This method is the destructor for prefixes_vtab objects.
87*4ead9634Sdrh */
88*4ead9634Sdrh static int prefixesDisconnect(sqlite3_vtab *pVtab){
89*4ead9634Sdrh   prefixes_vtab *p = (prefixes_vtab*)pVtab;
90*4ead9634Sdrh   sqlite3_free(p);
91*4ead9634Sdrh   return SQLITE_OK;
92*4ead9634Sdrh }
93*4ead9634Sdrh 
94*4ead9634Sdrh /*
95*4ead9634Sdrh ** Constructor for a new prefixes_cursor object.
96*4ead9634Sdrh */
97*4ead9634Sdrh static int prefixesOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
98*4ead9634Sdrh   prefixes_cursor *pCur;
99*4ead9634Sdrh   pCur = sqlite3_malloc( sizeof(*pCur) );
100*4ead9634Sdrh   if( pCur==0 ) return SQLITE_NOMEM;
101*4ead9634Sdrh   memset(pCur, 0, sizeof(*pCur));
102*4ead9634Sdrh   *ppCursor = &pCur->base;
103*4ead9634Sdrh   return SQLITE_OK;
104*4ead9634Sdrh }
105*4ead9634Sdrh 
106*4ead9634Sdrh /*
107*4ead9634Sdrh ** Destructor for a prefixes_cursor.
108*4ead9634Sdrh */
109*4ead9634Sdrh static int prefixesClose(sqlite3_vtab_cursor *cur){
110*4ead9634Sdrh   prefixes_cursor *pCur = (prefixes_cursor*)cur;
111*4ead9634Sdrh   sqlite3_free(pCur->zStr);
112*4ead9634Sdrh   sqlite3_free(pCur);
113*4ead9634Sdrh   return SQLITE_OK;
114*4ead9634Sdrh }
115*4ead9634Sdrh 
116*4ead9634Sdrh 
117*4ead9634Sdrh /*
118*4ead9634Sdrh ** Advance a prefixes_cursor to its next row of output.
119*4ead9634Sdrh */
120*4ead9634Sdrh static int prefixesNext(sqlite3_vtab_cursor *cur){
121*4ead9634Sdrh   prefixes_cursor *pCur = (prefixes_cursor*)cur;
122*4ead9634Sdrh   pCur->iRowid++;
123*4ead9634Sdrh   return SQLITE_OK;
124*4ead9634Sdrh }
125*4ead9634Sdrh 
126*4ead9634Sdrh /*
127*4ead9634Sdrh ** Return values of columns for the row at which the prefixes_cursor
128*4ead9634Sdrh ** is currently pointing.
129*4ead9634Sdrh */
130*4ead9634Sdrh static int prefixesColumn(
131*4ead9634Sdrh   sqlite3_vtab_cursor *cur,   /* The cursor */
132*4ead9634Sdrh   sqlite3_context *ctx,       /* First argument to sqlite3_result_...() */
133*4ead9634Sdrh   int i                       /* Which column to return */
134*4ead9634Sdrh ){
135*4ead9634Sdrh   prefixes_cursor *pCur = (prefixes_cursor*)cur;
136*4ead9634Sdrh   switch( i ){
137*4ead9634Sdrh     case 0:
138*4ead9634Sdrh       sqlite3_result_text(ctx, pCur->zStr, pCur->nStr - (int)pCur->iRowid,
139*4ead9634Sdrh                           0);
140*4ead9634Sdrh       break;
141*4ead9634Sdrh     default:
142*4ead9634Sdrh       sqlite3_result_text(ctx, pCur->zStr, pCur->nStr, 0);
143*4ead9634Sdrh       break;
144*4ead9634Sdrh   }
145*4ead9634Sdrh   return SQLITE_OK;
146*4ead9634Sdrh }
147*4ead9634Sdrh 
148*4ead9634Sdrh /*
149*4ead9634Sdrh ** Return the rowid for the current row.  In this implementation, the
150*4ead9634Sdrh ** rowid is the same as the output value.
151*4ead9634Sdrh */
152*4ead9634Sdrh static int prefixesRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
153*4ead9634Sdrh   prefixes_cursor *pCur = (prefixes_cursor*)cur;
154*4ead9634Sdrh   *pRowid = pCur->iRowid;
155*4ead9634Sdrh   return SQLITE_OK;
156*4ead9634Sdrh }
157*4ead9634Sdrh 
158*4ead9634Sdrh /*
159*4ead9634Sdrh ** Return TRUE if the cursor has been moved off of the last
160*4ead9634Sdrh ** row of output.
161*4ead9634Sdrh */
162*4ead9634Sdrh static int prefixesEof(sqlite3_vtab_cursor *cur){
163*4ead9634Sdrh   prefixes_cursor *pCur = (prefixes_cursor*)cur;
164*4ead9634Sdrh   return pCur->iRowid>pCur->nStr;
165*4ead9634Sdrh }
166*4ead9634Sdrh 
167*4ead9634Sdrh /*
168*4ead9634Sdrh ** This method is called to "rewind" the prefixes_cursor object back
169*4ead9634Sdrh ** to the first row of output.  This method is always called at least
170*4ead9634Sdrh ** once prior to any call to prefixesColumn() or prefixesRowid() or
171*4ead9634Sdrh ** prefixesEof().
172*4ead9634Sdrh */
173*4ead9634Sdrh static int prefixesFilter(
174*4ead9634Sdrh   sqlite3_vtab_cursor *pVtabCursor,
175*4ead9634Sdrh   int idxNum, const char *idxStr,
176*4ead9634Sdrh   int argc, sqlite3_value **argv
177*4ead9634Sdrh ){
178*4ead9634Sdrh   prefixes_cursor *pCur = (prefixes_cursor *)pVtabCursor;
179*4ead9634Sdrh   sqlite3_free(pCur->zStr);
180*4ead9634Sdrh   if( argc>0 ){
181*4ead9634Sdrh     pCur->zStr = sqlite3_mprintf("%s", sqlite3_value_text(argv[0]));
182*4ead9634Sdrh     pCur->nStr = pCur->zStr ? (int)strlen(pCur->zStr) : 0;
183*4ead9634Sdrh   }else{
184*4ead9634Sdrh     pCur->zStr = 0;
185*4ead9634Sdrh     pCur->nStr = 0;
186*4ead9634Sdrh   }
187*4ead9634Sdrh   pCur->iRowid = 0;
188*4ead9634Sdrh   return SQLITE_OK;
189*4ead9634Sdrh }
190*4ead9634Sdrh 
191*4ead9634Sdrh /*
192*4ead9634Sdrh ** SQLite will invoke this method one or more times while planning a query
193*4ead9634Sdrh ** that uses the virtual table.  This routine needs to create
194*4ead9634Sdrh ** a query plan for each invocation and compute an estimated cost for that
195*4ead9634Sdrh ** plan.
196*4ead9634Sdrh */
197*4ead9634Sdrh static int prefixesBestIndex(
198*4ead9634Sdrh   sqlite3_vtab *tab,
199*4ead9634Sdrh   sqlite3_index_info *pIdxInfo
200*4ead9634Sdrh ){
201*4ead9634Sdrh   /* Search for a usable equality constraint against column 1
202*4ead9634Sdrh   ** (original_string) and use it if at all possible */
203*4ead9634Sdrh   int i;
204*4ead9634Sdrh   const struct sqlite3_index_constraint *p;
205*4ead9634Sdrh 
206*4ead9634Sdrh   for(i=0, p=pIdxInfo->aConstraint; i<pIdxInfo->nConstraint; i++, p++){
207*4ead9634Sdrh     if( p->iColumn!=1 ) continue;
208*4ead9634Sdrh     if( p->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
209*4ead9634Sdrh     if( !p->usable ) continue;
210*4ead9634Sdrh     pIdxInfo->aConstraintUsage[i].argvIndex = 1;
211*4ead9634Sdrh     pIdxInfo->aConstraintUsage[i].omit = 1;
212*4ead9634Sdrh     pIdxInfo->estimatedCost = (double)10;
213*4ead9634Sdrh     pIdxInfo->estimatedRows = 10;
214*4ead9634Sdrh     return SQLITE_OK;
215*4ead9634Sdrh   }
216*4ead9634Sdrh   pIdxInfo->estimatedCost = (double)1000000000;
217*4ead9634Sdrh   pIdxInfo->estimatedRows = 1000000000;
218*4ead9634Sdrh   return SQLITE_OK;
219*4ead9634Sdrh }
220*4ead9634Sdrh 
221*4ead9634Sdrh /*
222*4ead9634Sdrh ** This following structure defines all the methods for the
223*4ead9634Sdrh ** virtual table.
224*4ead9634Sdrh */
225*4ead9634Sdrh static sqlite3_module prefixesModule = {
226*4ead9634Sdrh   /* iVersion    */ 0,
227*4ead9634Sdrh   /* xCreate     */ 0,
228*4ead9634Sdrh   /* xConnect    */ prefixesConnect,
229*4ead9634Sdrh   /* xBestIndex  */ prefixesBestIndex,
230*4ead9634Sdrh   /* xDisconnect */ prefixesDisconnect,
231*4ead9634Sdrh   /* xDestroy    */ 0,
232*4ead9634Sdrh   /* xOpen       */ prefixesOpen,
233*4ead9634Sdrh   /* xClose      */ prefixesClose,
234*4ead9634Sdrh   /* xFilter     */ prefixesFilter,
235*4ead9634Sdrh   /* xNext       */ prefixesNext,
236*4ead9634Sdrh   /* xEof        */ prefixesEof,
237*4ead9634Sdrh   /* xColumn     */ prefixesColumn,
238*4ead9634Sdrh   /* xRowid      */ prefixesRowid,
239*4ead9634Sdrh   /* xUpdate     */ 0,
240*4ead9634Sdrh   /* xBegin      */ 0,
241*4ead9634Sdrh   /* xSync       */ 0,
242*4ead9634Sdrh   /* xCommit     */ 0,
243*4ead9634Sdrh   /* xRollback   */ 0,
244*4ead9634Sdrh   /* xFindMethod */ 0,
245*4ead9634Sdrh   /* xRename     */ 0,
246*4ead9634Sdrh   /* xSavepoint  */ 0,
247*4ead9634Sdrh   /* xRelease    */ 0,
248*4ead9634Sdrh   /* xRollbackTo */ 0,
249*4ead9634Sdrh   /* xShadowName */ 0
250*4ead9634Sdrh };
251*4ead9634Sdrh 
252*4ead9634Sdrh 
253*4ead9634Sdrh #ifdef _WIN32
254*4ead9634Sdrh __declspec(dllexport)
255*4ead9634Sdrh #endif
256*4ead9634Sdrh int sqlite3_prefixes_init(
257*4ead9634Sdrh   sqlite3 *db,
258*4ead9634Sdrh   char **pzErrMsg,
259*4ead9634Sdrh   const sqlite3_api_routines *pApi
260*4ead9634Sdrh ){
261*4ead9634Sdrh   int rc = SQLITE_OK;
262*4ead9634Sdrh   SQLITE_EXTENSION_INIT2(pApi);
263*4ead9634Sdrh   rc = sqlite3_create_module(db, "prefixes", &prefixesModule, 0);
264*4ead9634Sdrh   return rc;
265*4ead9634Sdrh }
266