13265b564Sdrh /*
23265b564Sdrh ** 2017-07-10
33265b564Sdrh **
43265b564Sdrh ** The author disclaims copyright to this source code. In place of
53265b564Sdrh ** a legal notice, here is a blessing:
63265b564Sdrh **
73265b564Sdrh ** May you do good and not evil.
83265b564Sdrh ** May you find forgiveness for yourself and forgive others.
93265b564Sdrh ** May you share freely, never taking more than you give.
103265b564Sdrh **
113265b564Sdrh *************************************************************************
123265b564Sdrh **
133265b564Sdrh ** This file implements an eponymous virtual table that returns suggested
143265b564Sdrh ** completions for a partial SQL input.
153265b564Sdrh **
16f3c0009dSdrh ** Suggested usage:
17f3c0009dSdrh **
18f3c0009dSdrh ** SELECT DISTINCT candidate COLLATE nocase
19f3c0009dSdrh ** FROM completion($prefix,$wholeline)
20f3c0009dSdrh ** ORDER BY 1;
21f3c0009dSdrh **
22f3c0009dSdrh ** The two query parameters are optional. $prefix is the text of the
23f3c0009dSdrh ** current word being typed and that is to be completed. $wholeline is
24f3c0009dSdrh ** the complete input line, used for context.
25f3c0009dSdrh **
26f3c0009dSdrh ** The raw completion() table might return the same candidate multiple
27f3c0009dSdrh ** times, for example if the same column name is used to two or more
28f3c0009dSdrh ** tables. And the candidates are returned in an arbitrary order. Hence,
29f3c0009dSdrh ** the DISTINCT and ORDER BY are recommended.
30f3c0009dSdrh **
31f3c0009dSdrh ** This virtual table operates at the speed of human typing, and so there
32f3c0009dSdrh ** is no attempt to make it fast. Even a slow implementation will be much
33f3c0009dSdrh ** faster than any human can type.
34f3c0009dSdrh **
353265b564Sdrh */
363265b564Sdrh #include "sqlite3ext.h"
373265b564Sdrh SQLITE_EXTENSION_INIT1
383265b564Sdrh #include <assert.h>
393265b564Sdrh #include <string.h>
403265b564Sdrh #include <ctype.h>
413265b564Sdrh
423265b564Sdrh #ifndef SQLITE_OMIT_VIRTUALTABLE
433265b564Sdrh
443265b564Sdrh /* completion_vtab is a subclass of sqlite3_vtab which will
453265b564Sdrh ** serve as the underlying representation of a completion virtual table
463265b564Sdrh */
473265b564Sdrh typedef struct completion_vtab completion_vtab;
483265b564Sdrh struct completion_vtab {
493265b564Sdrh sqlite3_vtab base; /* Base class - must be first */
503265b564Sdrh sqlite3 *db; /* Database connection for this completion vtab */
513265b564Sdrh };
523265b564Sdrh
533265b564Sdrh /* completion_cursor is a subclass of sqlite3_vtab_cursor which will
543265b564Sdrh ** serve as the underlying representation of a cursor that scans
553265b564Sdrh ** over rows of the result
563265b564Sdrh */
573265b564Sdrh typedef struct completion_cursor completion_cursor;
583265b564Sdrh struct completion_cursor {
593265b564Sdrh sqlite3_vtab_cursor base; /* Base class - must be first */
603265b564Sdrh sqlite3 *db; /* Database connection for this cursor */
613265b564Sdrh int nPrefix, nLine; /* Number of bytes in zPrefix and zLine */
623265b564Sdrh char *zPrefix; /* The prefix for the word we want to complete */
633265b564Sdrh char *zLine; /* The whole that we want to complete */
643265b564Sdrh const char *zCurrentRow; /* Current output row */
65fc0ec3e5Sdrh int szRow; /* Length of the zCurrentRow string */
663265b564Sdrh sqlite3_stmt *pStmt; /* Current statement */
673265b564Sdrh sqlite3_int64 iRowid; /* The rowid */
683265b564Sdrh int ePhase; /* Current phase */
693265b564Sdrh int j; /* inter-phase counter */
703265b564Sdrh };
713265b564Sdrh
723265b564Sdrh /* Values for ePhase:
733265b564Sdrh */
74dc4dde6bSdrh #define COMPLETION_FIRST_PHASE 1
753265b564Sdrh #define COMPLETION_KEYWORDS 1
763265b564Sdrh #define COMPLETION_PRAGMAS 2
773265b564Sdrh #define COMPLETION_FUNCTIONS 3
783265b564Sdrh #define COMPLETION_COLLATIONS 4
793265b564Sdrh #define COMPLETION_INDEXES 5
803265b564Sdrh #define COMPLETION_TRIGGERS 6
813265b564Sdrh #define COMPLETION_DATABASES 7
828c1eba75Sdrh #define COMPLETION_TABLES 8 /* Also VIEWs and TRIGGERs */
83dc4dde6bSdrh #define COMPLETION_COLUMNS 9
84dc4dde6bSdrh #define COMPLETION_MODULES 10
85dc4dde6bSdrh #define COMPLETION_EOF 11
863265b564Sdrh
873265b564Sdrh /*
883265b564Sdrh ** The completionConnect() method is invoked to create a new
893265b564Sdrh ** completion_vtab that describes the completion virtual table.
903265b564Sdrh **
913265b564Sdrh ** Think of this routine as the constructor for completion_vtab objects.
923265b564Sdrh **
933265b564Sdrh ** All this routine needs to do is:
943265b564Sdrh **
953265b564Sdrh ** (1) Allocate the completion_vtab object and initialize all fields.
963265b564Sdrh **
973265b564Sdrh ** (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
983265b564Sdrh ** result set of queries against completion will look like.
993265b564Sdrh */
completionConnect(sqlite3 * db,void * pAux,int argc,const char * const * argv,sqlite3_vtab ** ppVtab,char ** pzErr)1003265b564Sdrh static int completionConnect(
1013265b564Sdrh sqlite3 *db,
1023265b564Sdrh void *pAux,
1033265b564Sdrh int argc, const char *const*argv,
1043265b564Sdrh sqlite3_vtab **ppVtab,
1053265b564Sdrh char **pzErr
1063265b564Sdrh ){
1073265b564Sdrh completion_vtab *pNew;
1083265b564Sdrh int rc;
1093265b564Sdrh
1108999798eSdrh (void)(pAux); /* Unused parameter */
1118999798eSdrh (void)(argc); /* Unused parameter */
1128999798eSdrh (void)(argv); /* Unused parameter */
1138999798eSdrh (void)(pzErr); /* Unused parameter */
1148999798eSdrh
1153265b564Sdrh /* Column numbers */
1163265b564Sdrh #define COMPLETION_COLUMN_CANDIDATE 0 /* Suggested completion of the input */
1173265b564Sdrh #define COMPLETION_COLUMN_PREFIX 1 /* Prefix of the word to be completed */
1183265b564Sdrh #define COMPLETION_COLUMN_WHOLELINE 2 /* Entire line seen so far */
119f3c0009dSdrh #define COMPLETION_COLUMN_PHASE 3 /* ePhase - used for debugging only */
1203265b564Sdrh
1212b1c2aadSdrh sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
1223265b564Sdrh rc = sqlite3_declare_vtab(db,
1233265b564Sdrh "CREATE TABLE x("
1243265b564Sdrh " candidate TEXT,"
1253265b564Sdrh " prefix TEXT HIDDEN,"
126f3c0009dSdrh " wholeline TEXT HIDDEN,"
127f3c0009dSdrh " phase INT HIDDEN" /* Used for debugging only */
1283265b564Sdrh ")");
1293265b564Sdrh if( rc==SQLITE_OK ){
1303265b564Sdrh pNew = sqlite3_malloc( sizeof(*pNew) );
1313265b564Sdrh *ppVtab = (sqlite3_vtab*)pNew;
1323265b564Sdrh if( pNew==0 ) return SQLITE_NOMEM;
1333265b564Sdrh memset(pNew, 0, sizeof(*pNew));
1343265b564Sdrh pNew->db = db;
1353265b564Sdrh }
1363265b564Sdrh return rc;
1373265b564Sdrh }
1383265b564Sdrh
1393265b564Sdrh /*
1403265b564Sdrh ** This method is the destructor for completion_cursor objects.
1413265b564Sdrh */
completionDisconnect(sqlite3_vtab * pVtab)1423265b564Sdrh static int completionDisconnect(sqlite3_vtab *pVtab){
1433265b564Sdrh sqlite3_free(pVtab);
1443265b564Sdrh return SQLITE_OK;
1453265b564Sdrh }
1463265b564Sdrh
1473265b564Sdrh /*
1483265b564Sdrh ** Constructor for a new completion_cursor object.
1493265b564Sdrh */
completionOpen(sqlite3_vtab * p,sqlite3_vtab_cursor ** ppCursor)1503265b564Sdrh static int completionOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
1513265b564Sdrh completion_cursor *pCur;
1523265b564Sdrh pCur = sqlite3_malloc( sizeof(*pCur) );
1533265b564Sdrh if( pCur==0 ) return SQLITE_NOMEM;
1543265b564Sdrh memset(pCur, 0, sizeof(*pCur));
1553265b564Sdrh pCur->db = ((completion_vtab*)p)->db;
1563265b564Sdrh *ppCursor = &pCur->base;
1573265b564Sdrh return SQLITE_OK;
1583265b564Sdrh }
1593265b564Sdrh
1603265b564Sdrh /*
1613265b564Sdrh ** Reset the completion_cursor.
1623265b564Sdrh */
completionCursorReset(completion_cursor * pCur)1633265b564Sdrh static void completionCursorReset(completion_cursor *pCur){
1643265b564Sdrh sqlite3_free(pCur->zPrefix); pCur->zPrefix = 0; pCur->nPrefix = 0;
1653265b564Sdrh sqlite3_free(pCur->zLine); pCur->zLine = 0; pCur->nLine = 0;
1663265b564Sdrh sqlite3_finalize(pCur->pStmt); pCur->pStmt = 0;
167dc4dde6bSdrh pCur->j = 0;
1683265b564Sdrh }
1693265b564Sdrh
1703265b564Sdrh /*
1713265b564Sdrh ** Destructor for a completion_cursor.
1723265b564Sdrh */
completionClose(sqlite3_vtab_cursor * cur)1733265b564Sdrh static int completionClose(sqlite3_vtab_cursor *cur){
1743265b564Sdrh completionCursorReset((completion_cursor*)cur);
1753265b564Sdrh sqlite3_free(cur);
1763265b564Sdrh return SQLITE_OK;
1773265b564Sdrh }
1783265b564Sdrh
1793265b564Sdrh /*
1803265b564Sdrh ** Advance a completion_cursor to its next row of output.
181f3c0009dSdrh **
182f3c0009dSdrh ** The ->ePhase, ->j, and ->pStmt fields of the completion_cursor object
183f3c0009dSdrh ** record the current state of the scan. This routine sets ->zCurrentRow
184f3c0009dSdrh ** to the current row of output and then returns. If no more rows remain,
185f3c0009dSdrh ** then ->ePhase is set to COMPLETION_EOF which will signal the virtual
186f3c0009dSdrh ** table that has reached the end of its scan.
187f3c0009dSdrh **
188f3c0009dSdrh ** The current implementation just lists potential identifiers and
189f3c0009dSdrh ** keywords and filters them by zPrefix. Future enhancements should
190f3c0009dSdrh ** take zLine into account to try to restrict the set of identifiers and
191f3c0009dSdrh ** keywords based on what would be legal at the current point of input.
1923265b564Sdrh */
completionNext(sqlite3_vtab_cursor * cur)1933265b564Sdrh static int completionNext(sqlite3_vtab_cursor *cur){
1943265b564Sdrh completion_cursor *pCur = (completion_cursor*)cur;
195dc4dde6bSdrh int eNextPhase = 0; /* Next phase to try if current phase reaches end */
196f3c0009dSdrh int iCol = -1; /* If >=0, step pCur->pStmt and use the i-th column */
1973265b564Sdrh pCur->iRowid++;
198dc4dde6bSdrh while( pCur->ePhase!=COMPLETION_EOF ){
199dc4dde6bSdrh switch( pCur->ePhase ){
200dc4dde6bSdrh case COMPLETION_KEYWORDS: {
201fc0ec3e5Sdrh if( pCur->j >= sqlite3_keyword_count() ){
202dc4dde6bSdrh pCur->zCurrentRow = 0;
203dc4dde6bSdrh pCur->ePhase = COMPLETION_DATABASES;
204dc4dde6bSdrh }else{
205fc0ec3e5Sdrh sqlite3_keyword_name(pCur->j++, &pCur->zCurrentRow, &pCur->szRow);
206dc4dde6bSdrh }
207dc4dde6bSdrh iCol = -1;
2083265b564Sdrh break;
2093265b564Sdrh }
210dc4dde6bSdrh case COMPLETION_DATABASES: {
211dc4dde6bSdrh if( pCur->pStmt==0 ){
212dc4dde6bSdrh sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1,
213dc4dde6bSdrh &pCur->pStmt, 0);
214dc4dde6bSdrh }
215dc4dde6bSdrh iCol = 1;
216dc4dde6bSdrh eNextPhase = COMPLETION_TABLES;
217dc4dde6bSdrh break;
218dc4dde6bSdrh }
219dc4dde6bSdrh case COMPLETION_TABLES: {
220dc4dde6bSdrh if( pCur->pStmt==0 ){
221dc4dde6bSdrh sqlite3_stmt *pS2;
222dc4dde6bSdrh char *zSql = 0;
223dc4dde6bSdrh const char *zSep = "";
224dc4dde6bSdrh sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1, &pS2, 0);
225dc4dde6bSdrh while( sqlite3_step(pS2)==SQLITE_ROW ){
226dc4dde6bSdrh const char *zDb = (const char*)sqlite3_column_text(pS2, 1);
227dc4dde6bSdrh zSql = sqlite3_mprintf(
228dc4dde6bSdrh "%z%s"
229*067b92baSdrh "SELECT name FROM \"%w\".sqlite_schema",
230dc4dde6bSdrh zSql, zSep, zDb
231dc4dde6bSdrh );
232dc4dde6bSdrh if( zSql==0 ) return SQLITE_NOMEM;
233dc4dde6bSdrh zSep = " UNION ";
234dc4dde6bSdrh }
235dc4dde6bSdrh sqlite3_finalize(pS2);
236dc4dde6bSdrh sqlite3_prepare_v2(pCur->db, zSql, -1, &pCur->pStmt, 0);
237dc4dde6bSdrh sqlite3_free(zSql);
238dc4dde6bSdrh }
239dc4dde6bSdrh iCol = 0;
240dc4dde6bSdrh eNextPhase = COMPLETION_COLUMNS;
241dc4dde6bSdrh break;
242dc4dde6bSdrh }
243dc4dde6bSdrh case COMPLETION_COLUMNS: {
244dc4dde6bSdrh if( pCur->pStmt==0 ){
245dc4dde6bSdrh sqlite3_stmt *pS2;
246dc4dde6bSdrh char *zSql = 0;
247dc4dde6bSdrh const char *zSep = "";
248dc4dde6bSdrh sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1, &pS2, 0);
249dc4dde6bSdrh while( sqlite3_step(pS2)==SQLITE_ROW ){
250dc4dde6bSdrh const char *zDb = (const char*)sqlite3_column_text(pS2, 1);
251dc4dde6bSdrh zSql = sqlite3_mprintf(
252dc4dde6bSdrh "%z%s"
253*067b92baSdrh "SELECT pti.name FROM \"%w\".sqlite_schema AS sm"
254dc4dde6bSdrh " JOIN pragma_table_info(sm.name,%Q) AS pti"
255dc4dde6bSdrh " WHERE sm.type='table'",
256dc4dde6bSdrh zSql, zSep, zDb, zDb
257dc4dde6bSdrh );
258dc4dde6bSdrh if( zSql==0 ) return SQLITE_NOMEM;
259dc4dde6bSdrh zSep = " UNION ";
260dc4dde6bSdrh }
261dc4dde6bSdrh sqlite3_finalize(pS2);
262dc4dde6bSdrh sqlite3_prepare_v2(pCur->db, zSql, -1, &pCur->pStmt, 0);
263dc4dde6bSdrh sqlite3_free(zSql);
264dc4dde6bSdrh }
265dc4dde6bSdrh iCol = 0;
266dc4dde6bSdrh eNextPhase = COMPLETION_EOF;
2673265b564Sdrh break;
2683265b564Sdrh }
2693265b564Sdrh }
270dc4dde6bSdrh if( iCol<0 ){
271dc4dde6bSdrh /* This case is when the phase presets zCurrentRow */
272dc4dde6bSdrh if( pCur->zCurrentRow==0 ) continue;
273dc4dde6bSdrh }else{
274dc4dde6bSdrh if( sqlite3_step(pCur->pStmt)==SQLITE_ROW ){
275dc4dde6bSdrh /* Extract the next row of content */
276dc4dde6bSdrh pCur->zCurrentRow = (const char*)sqlite3_column_text(pCur->pStmt, iCol);
277fc0ec3e5Sdrh pCur->szRow = sqlite3_column_bytes(pCur->pStmt, iCol);
278dc4dde6bSdrh }else{
279dc4dde6bSdrh /* When all rows are finished, advance to the next phase */
280dc4dde6bSdrh sqlite3_finalize(pCur->pStmt);
281dc4dde6bSdrh pCur->pStmt = 0;
282dc4dde6bSdrh pCur->ePhase = eNextPhase;
283dc4dde6bSdrh continue;
2843265b564Sdrh }
285dc4dde6bSdrh }
286dc4dde6bSdrh if( pCur->nPrefix==0 ) break;
287fc0ec3e5Sdrh if( pCur->nPrefix<=pCur->szRow
288fc0ec3e5Sdrh && sqlite3_strnicmp(pCur->zPrefix, pCur->zCurrentRow, pCur->nPrefix)==0
289fc0ec3e5Sdrh ){
290dc4dde6bSdrh break;
291dc4dde6bSdrh }
292dc4dde6bSdrh }
293dc4dde6bSdrh
2943265b564Sdrh return SQLITE_OK;
2953265b564Sdrh }
2963265b564Sdrh
2973265b564Sdrh /*
2983265b564Sdrh ** Return values of columns for the row at which the completion_cursor
2993265b564Sdrh ** is currently pointing.
3003265b564Sdrh */
completionColumn(sqlite3_vtab_cursor * cur,sqlite3_context * ctx,int i)3013265b564Sdrh static int completionColumn(
3023265b564Sdrh sqlite3_vtab_cursor *cur, /* The cursor */
3033265b564Sdrh sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
3043265b564Sdrh int i /* Which column to return */
3053265b564Sdrh ){
3063265b564Sdrh completion_cursor *pCur = (completion_cursor*)cur;
3073265b564Sdrh switch( i ){
3083265b564Sdrh case COMPLETION_COLUMN_CANDIDATE: {
309fc0ec3e5Sdrh sqlite3_result_text(ctx, pCur->zCurrentRow, pCur->szRow,SQLITE_TRANSIENT);
3103265b564Sdrh break;
3113265b564Sdrh }
3123265b564Sdrh case COMPLETION_COLUMN_PREFIX: {
3133265b564Sdrh sqlite3_result_text(ctx, pCur->zPrefix, -1, SQLITE_TRANSIENT);
3143265b564Sdrh break;
3153265b564Sdrh }
3163265b564Sdrh case COMPLETION_COLUMN_WHOLELINE: {
3173265b564Sdrh sqlite3_result_text(ctx, pCur->zLine, -1, SQLITE_TRANSIENT);
3183265b564Sdrh break;
3193265b564Sdrh }
320f3c0009dSdrh case COMPLETION_COLUMN_PHASE: {
321f3c0009dSdrh sqlite3_result_int(ctx, pCur->ePhase);
322f3c0009dSdrh break;
323f3c0009dSdrh }
3243265b564Sdrh }
3253265b564Sdrh return SQLITE_OK;
3263265b564Sdrh }
3273265b564Sdrh
3283265b564Sdrh /*
3293265b564Sdrh ** Return the rowid for the current row. In this implementation, the
3303265b564Sdrh ** rowid is the same as the output value.
3313265b564Sdrh */
completionRowid(sqlite3_vtab_cursor * cur,sqlite_int64 * pRowid)3323265b564Sdrh static int completionRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
3333265b564Sdrh completion_cursor *pCur = (completion_cursor*)cur;
3343265b564Sdrh *pRowid = pCur->iRowid;
3353265b564Sdrh return SQLITE_OK;
3363265b564Sdrh }
3373265b564Sdrh
3383265b564Sdrh /*
3393265b564Sdrh ** Return TRUE if the cursor has been moved off of the last
3403265b564Sdrh ** row of output.
3413265b564Sdrh */
completionEof(sqlite3_vtab_cursor * cur)3423265b564Sdrh static int completionEof(sqlite3_vtab_cursor *cur){
3433265b564Sdrh completion_cursor *pCur = (completion_cursor*)cur;
344dc4dde6bSdrh return pCur->ePhase >= COMPLETION_EOF;
3453265b564Sdrh }
3463265b564Sdrh
3473265b564Sdrh /*
3483265b564Sdrh ** This method is called to "rewind" the completion_cursor object back
3493265b564Sdrh ** to the first row of output. This method is always called at least
3503265b564Sdrh ** once prior to any call to completionColumn() or completionRowid() or
3513265b564Sdrh ** completionEof().
3523265b564Sdrh */
completionFilter(sqlite3_vtab_cursor * pVtabCursor,int idxNum,const char * idxStr,int argc,sqlite3_value ** argv)3533265b564Sdrh static int completionFilter(
3543265b564Sdrh sqlite3_vtab_cursor *pVtabCursor,
3553265b564Sdrh int idxNum, const char *idxStr,
3563265b564Sdrh int argc, sqlite3_value **argv
3573265b564Sdrh ){
3583265b564Sdrh completion_cursor *pCur = (completion_cursor *)pVtabCursor;
3593265b564Sdrh int iArg = 0;
3608999798eSdrh (void)(idxStr); /* Unused parameter */
3618999798eSdrh (void)(argc); /* Unused parameter */
3623265b564Sdrh completionCursorReset(pCur);
3633265b564Sdrh if( idxNum & 1 ){
3643265b564Sdrh pCur->nPrefix = sqlite3_value_bytes(argv[iArg]);
3653265b564Sdrh if( pCur->nPrefix>0 ){
3663265b564Sdrh pCur->zPrefix = sqlite3_mprintf("%s", sqlite3_value_text(argv[iArg]));
3673265b564Sdrh if( pCur->zPrefix==0 ) return SQLITE_NOMEM;
3683265b564Sdrh }
369c4ceea72Sdrh iArg = 1;
3703265b564Sdrh }
3713265b564Sdrh if( idxNum & 2 ){
3723265b564Sdrh pCur->nLine = sqlite3_value_bytes(argv[iArg]);
3733265b564Sdrh if( pCur->nLine>0 ){
3743265b564Sdrh pCur->zLine = sqlite3_mprintf("%s", sqlite3_value_text(argv[iArg]));
3753265b564Sdrh if( pCur->zLine==0 ) return SQLITE_NOMEM;
3763265b564Sdrh }
3773265b564Sdrh }
3783265b564Sdrh if( pCur->zLine!=0 && pCur->zPrefix==0 ){
3793265b564Sdrh int i = pCur->nLine;
3803265b564Sdrh while( i>0 && (isalnum(pCur->zLine[i-1]) || pCur->zLine[i-1]=='_') ){
3813265b564Sdrh i--;
3823265b564Sdrh }
3833265b564Sdrh pCur->nPrefix = pCur->nLine - i;
3843265b564Sdrh if( pCur->nPrefix>0 ){
3853265b564Sdrh pCur->zPrefix = sqlite3_mprintf("%.*s", pCur->nPrefix, pCur->zLine + i);
3863265b564Sdrh if( pCur->zPrefix==0 ) return SQLITE_NOMEM;
3873265b564Sdrh }
3883265b564Sdrh }
3893265b564Sdrh pCur->iRowid = 0;
3903265b564Sdrh pCur->ePhase = COMPLETION_FIRST_PHASE;
3913265b564Sdrh return completionNext(pVtabCursor);
3923265b564Sdrh }
3933265b564Sdrh
3943265b564Sdrh /*
3953265b564Sdrh ** SQLite will invoke this method one or more times while planning a query
3963265b564Sdrh ** that uses the completion virtual table. This routine needs to create
3973265b564Sdrh ** a query plan for each invocation and compute an estimated cost for that
3983265b564Sdrh ** plan.
3993265b564Sdrh **
4003265b564Sdrh ** There are two hidden parameters that act as arguments to the table-valued
4013265b564Sdrh ** function: "prefix" and "wholeline". Bit 0 of idxNum is set if "prefix"
4023265b564Sdrh ** is available and bit 1 is set if "wholeline" is available.
4033265b564Sdrh */
completionBestIndex(sqlite3_vtab * tab,sqlite3_index_info * pIdxInfo)4043265b564Sdrh static int completionBestIndex(
4053265b564Sdrh sqlite3_vtab *tab,
4063265b564Sdrh sqlite3_index_info *pIdxInfo
4073265b564Sdrh ){
4083265b564Sdrh int i; /* Loop over constraints */
4093265b564Sdrh int idxNum = 0; /* The query plan bitmask */
4103265b564Sdrh int prefixIdx = -1; /* Index of the start= constraint, or -1 if none */
4113265b564Sdrh int wholelineIdx = -1; /* Index of the stop= constraint, or -1 if none */
4123265b564Sdrh int nArg = 0; /* Number of arguments that completeFilter() expects */
4133265b564Sdrh const struct sqlite3_index_constraint *pConstraint;
4143265b564Sdrh
4158999798eSdrh (void)(tab); /* Unused parameter */
4163265b564Sdrh pConstraint = pIdxInfo->aConstraint;
4173265b564Sdrh for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
4183265b564Sdrh if( pConstraint->usable==0 ) continue;
4193265b564Sdrh if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
4203265b564Sdrh switch( pConstraint->iColumn ){
4213265b564Sdrh case COMPLETION_COLUMN_PREFIX:
4223265b564Sdrh prefixIdx = i;
4233265b564Sdrh idxNum |= 1;
4243265b564Sdrh break;
4253265b564Sdrh case COMPLETION_COLUMN_WHOLELINE:
4263265b564Sdrh wholelineIdx = i;
4273265b564Sdrh idxNum |= 2;
4283265b564Sdrh break;
4293265b564Sdrh }
4303265b564Sdrh }
4313265b564Sdrh if( prefixIdx>=0 ){
4323265b564Sdrh pIdxInfo->aConstraintUsage[prefixIdx].argvIndex = ++nArg;
4333265b564Sdrh pIdxInfo->aConstraintUsage[prefixIdx].omit = 1;
4343265b564Sdrh }
4353265b564Sdrh if( wholelineIdx>=0 ){
4363265b564Sdrh pIdxInfo->aConstraintUsage[wholelineIdx].argvIndex = ++nArg;
4373265b564Sdrh pIdxInfo->aConstraintUsage[wholelineIdx].omit = 1;
4383265b564Sdrh }
4393265b564Sdrh pIdxInfo->idxNum = idxNum;
4403265b564Sdrh pIdxInfo->estimatedCost = (double)5000 - 1000*nArg;
4413265b564Sdrh pIdxInfo->estimatedRows = 500 - 100*nArg;
4423265b564Sdrh return SQLITE_OK;
4433265b564Sdrh }
4443265b564Sdrh
4453265b564Sdrh /*
4463265b564Sdrh ** This following structure defines all the methods for the
4473265b564Sdrh ** completion virtual table.
4483265b564Sdrh */
4493265b564Sdrh static sqlite3_module completionModule = {
4503265b564Sdrh 0, /* iVersion */
4513265b564Sdrh 0, /* xCreate */
4523265b564Sdrh completionConnect, /* xConnect */
4533265b564Sdrh completionBestIndex, /* xBestIndex */
4543265b564Sdrh completionDisconnect, /* xDisconnect */
4553265b564Sdrh 0, /* xDestroy */
4563265b564Sdrh completionOpen, /* xOpen - open a cursor */
4573265b564Sdrh completionClose, /* xClose - close a cursor */
4583265b564Sdrh completionFilter, /* xFilter - configure scan constraints */
4593265b564Sdrh completionNext, /* xNext - advance a cursor */
4603265b564Sdrh completionEof, /* xEof - check for end of scan */
4613265b564Sdrh completionColumn, /* xColumn - read data */
4623265b564Sdrh completionRowid, /* xRowid - read data */
4633265b564Sdrh 0, /* xUpdate */
4643265b564Sdrh 0, /* xBegin */
4653265b564Sdrh 0, /* xSync */
4663265b564Sdrh 0, /* xCommit */
4673265b564Sdrh 0, /* xRollback */
4683265b564Sdrh 0, /* xFindMethod */
4693265b564Sdrh 0, /* xRename */
4708999798eSdrh 0, /* xSavepoint */
4718999798eSdrh 0, /* xRelease */
47284c501baSdrh 0, /* xRollbackTo */
47384c501baSdrh 0 /* xShadowName */
4743265b564Sdrh };
4753265b564Sdrh
4763265b564Sdrh #endif /* SQLITE_OMIT_VIRTUALTABLE */
4773265b564Sdrh
sqlite3CompletionVtabInit(sqlite3 * db)4783265b564Sdrh int sqlite3CompletionVtabInit(sqlite3 *db){
4793265b564Sdrh int rc = SQLITE_OK;
4803265b564Sdrh #ifndef SQLITE_OMIT_VIRTUALTABLE
4813265b564Sdrh rc = sqlite3_create_module(db, "completion", &completionModule, 0);
4823265b564Sdrh #endif
4833265b564Sdrh return rc;
4843265b564Sdrh }
4853265b564Sdrh
4863265b564Sdrh #ifdef _WIN32
4873265b564Sdrh __declspec(dllexport)
4883265b564Sdrh #endif
sqlite3_completion_init(sqlite3 * db,char ** pzErrMsg,const sqlite3_api_routines * pApi)4893265b564Sdrh int sqlite3_completion_init(
4903265b564Sdrh sqlite3 *db,
4913265b564Sdrh char **pzErrMsg,
4923265b564Sdrh const sqlite3_api_routines *pApi
4933265b564Sdrh ){
4943265b564Sdrh int rc = SQLITE_OK;
4953265b564Sdrh SQLITE_EXTENSION_INIT2(pApi);
4968999798eSdrh (void)(pzErrMsg); /* Unused parameter */
4973265b564Sdrh #ifndef SQLITE_OMIT_VIRTUALTABLE
4983265b564Sdrh rc = sqlite3CompletionVtabInit(db);
4993265b564Sdrh #endif
5003265b564Sdrh return rc;
5013265b564Sdrh }
502