modernc.org/cc@v1.0.1/v2/testdata/_sqlite/ext/misc/completion.c (about)

     1  /*
     2  ** 2017-07-10
     3  **
     4  ** The author disclaims copyright to this source code.  In place of
     5  ** a legal notice, here is a blessing:
     6  **
     7  **    May you do good and not evil.
     8  **    May you find forgiveness for yourself and forgive others.
     9  **    May you share freely, never taking more than you give.
    10  **
    11  *************************************************************************
    12  **
    13  ** This file implements an eponymous virtual table that returns suggested
    14  ** completions for a partial SQL input.
    15  **
    16  ** Suggested usage:
    17  **
    18  **     SELECT DISTINCT candidate COLLATE nocase
    19  **       FROM completion($prefix,$wholeline)
    20  **      ORDER BY 1;
    21  **
    22  ** The two query parameters are optional.  $prefix is the text of the
    23  ** current word being typed and that is to be completed.  $wholeline is
    24  ** the complete input line, used for context.
    25  **
    26  ** The raw completion() table might return the same candidate multiple
    27  ** times, for example if the same column name is used to two or more
    28  ** tables.  And the candidates are returned in an arbitrary order.  Hence,
    29  ** the DISTINCT and ORDER BY are recommended.
    30  **
    31  ** This virtual table operates at the speed of human typing, and so there
    32  ** is no attempt to make it fast.  Even a slow implementation will be much
    33  ** faster than any human can type.
    34  **
    35  */
    36  #include "sqlite3ext.h"
    37  SQLITE_EXTENSION_INIT1
    38  #include <assert.h>
    39  #include <string.h>
    40  #include <ctype.h>
    41  
    42  #ifndef SQLITE_OMIT_VIRTUALTABLE
    43  
    44  /* completion_vtab is a subclass of sqlite3_vtab which will
    45  ** serve as the underlying representation of a completion virtual table
    46  */
    47  typedef struct completion_vtab completion_vtab;
    48  struct completion_vtab {
    49    sqlite3_vtab base;  /* Base class - must be first */
    50    sqlite3 *db;        /* Database connection for this completion vtab */
    51  };
    52  
    53  /* completion_cursor is a subclass of sqlite3_vtab_cursor which will
    54  ** serve as the underlying representation of a cursor that scans
    55  ** over rows of the result
    56  */
    57  typedef struct completion_cursor completion_cursor;
    58  struct completion_cursor {
    59    sqlite3_vtab_cursor base;  /* Base class - must be first */
    60    sqlite3 *db;               /* Database connection for this cursor */
    61    int nPrefix, nLine;        /* Number of bytes in zPrefix and zLine */
    62    char *zPrefix;             /* The prefix for the word we want to complete */
    63    char *zLine;               /* The whole that we want to complete */
    64    const char *zCurrentRow;   /* Current output row */
    65    sqlite3_stmt *pStmt;       /* Current statement */
    66    sqlite3_int64 iRowid;      /* The rowid */
    67    int ePhase;                /* Current phase */
    68    int j;                     /* inter-phase counter */
    69  };
    70  
    71  /* Values for ePhase:
    72  */
    73  #define COMPLETION_FIRST_PHASE   1
    74  #define COMPLETION_KEYWORDS      1
    75  #define COMPLETION_PRAGMAS       2
    76  #define COMPLETION_FUNCTIONS     3
    77  #define COMPLETION_COLLATIONS    4
    78  #define COMPLETION_INDEXES       5
    79  #define COMPLETION_TRIGGERS      6
    80  #define COMPLETION_DATABASES     7
    81  #define COMPLETION_TABLES        8
    82  #define COMPLETION_COLUMNS       9
    83  #define COMPLETION_MODULES       10
    84  #define COMPLETION_EOF           11
    85  
    86  /*
    87  ** The completionConnect() method is invoked to create a new
    88  ** completion_vtab that describes the completion virtual table.
    89  **
    90  ** Think of this routine as the constructor for completion_vtab objects.
    91  **
    92  ** All this routine needs to do is:
    93  **
    94  **    (1) Allocate the completion_vtab object and initialize all fields.
    95  **
    96  **    (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
    97  **        result set of queries against completion will look like.
    98  */
    99  static int completionConnect(
   100    sqlite3 *db,
   101    void *pAux,
   102    int argc, const char *const*argv,
   103    sqlite3_vtab **ppVtab,
   104    char **pzErr
   105  ){
   106    completion_vtab *pNew;
   107    int rc;
   108  
   109    (void)(pAux);    /* Unused parameter */
   110    (void)(argc);    /* Unused parameter */
   111    (void)(argv);    /* Unused parameter */
   112    (void)(pzErr);   /* Unused parameter */
   113  
   114  /* Column numbers */
   115  #define COMPLETION_COLUMN_CANDIDATE 0  /* Suggested completion of the input */
   116  #define COMPLETION_COLUMN_PREFIX    1  /* Prefix of the word to be completed */
   117  #define COMPLETION_COLUMN_WHOLELINE 2  /* Entire line seen so far */
   118  #define COMPLETION_COLUMN_PHASE     3  /* ePhase - used for debugging only */
   119  
   120    rc = sqlite3_declare_vtab(db,
   121        "CREATE TABLE x("
   122        "  candidate TEXT,"
   123        "  prefix TEXT HIDDEN,"
   124        "  wholeline TEXT HIDDEN,"
   125        "  phase INT HIDDEN"        /* Used for debugging only */
   126        ")");
   127    if( rc==SQLITE_OK ){
   128      pNew = sqlite3_malloc( sizeof(*pNew) );
   129      *ppVtab = (sqlite3_vtab*)pNew;
   130      if( pNew==0 ) return SQLITE_NOMEM;
   131      memset(pNew, 0, sizeof(*pNew));
   132      pNew->db = db;
   133    }
   134    return rc;
   135  }
   136  
   137  /*
   138  ** This method is the destructor for completion_cursor objects.
   139  */
   140  static int completionDisconnect(sqlite3_vtab *pVtab){
   141    sqlite3_free(pVtab);
   142    return SQLITE_OK;
   143  }
   144  
   145  /*
   146  ** Constructor for a new completion_cursor object.
   147  */
   148  static int completionOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
   149    completion_cursor *pCur;
   150    pCur = sqlite3_malloc( sizeof(*pCur) );
   151    if( pCur==0 ) return SQLITE_NOMEM;
   152    memset(pCur, 0, sizeof(*pCur));
   153    pCur->db = ((completion_vtab*)p)->db;
   154    *ppCursor = &pCur->base;
   155    return SQLITE_OK;
   156  }
   157  
   158  /*
   159  ** Reset the completion_cursor.
   160  */
   161  static void completionCursorReset(completion_cursor *pCur){
   162    sqlite3_free(pCur->zPrefix);   pCur->zPrefix = 0;  pCur->nPrefix = 0;
   163    sqlite3_free(pCur->zLine);     pCur->zLine = 0;    pCur->nLine = 0;
   164    sqlite3_finalize(pCur->pStmt); pCur->pStmt = 0;
   165    pCur->j = 0;
   166  }
   167  
   168  /*
   169  ** Destructor for a completion_cursor.
   170  */
   171  static int completionClose(sqlite3_vtab_cursor *cur){
   172    completionCursorReset((completion_cursor*)cur);
   173    sqlite3_free(cur);
   174    return SQLITE_OK;
   175  }
   176  
   177  /*
   178  ** All SQL keywords understood by SQLite
   179  */
   180  static const char *completionKwrds[] = {
   181    "ABORT", "ACTION", "ADD", "AFTER", "ALL", "ALTER", "ANALYZE", "AND", "AS",
   182    "ASC", "ATTACH", "AUTOINCREMENT", "BEFORE", "BEGIN", "BETWEEN", "BY",
   183    "CASCADE", "CASE", "CAST", "CHECK", "COLLATE", "COLUMN", "COMMIT",
   184    "CONFLICT", "CONSTRAINT", "CREATE", "CROSS", "CURRENT_DATE",
   185    "CURRENT_TIME", "CURRENT_TIMESTAMP", "DATABASE", "DEFAULT", "DEFERRABLE",
   186    "DEFERRED", "DELETE", "DESC", "DETACH", "DISTINCT", "DROP", "EACH",
   187    "ELSE", "END", "ESCAPE", "EXCEPT", "EXCLUSIVE", "EXISTS", "EXPLAIN",
   188    "FAIL", "FOR", "FOREIGN", "FROM", "FULL", "GLOB", "GROUP", "HAVING", "IF",
   189    "IGNORE", "IMMEDIATE", "IN", "INDEX", "INDEXED", "INITIALLY", "INNER",
   190    "INSERT", "INSTEAD", "INTERSECT", "INTO", "IS", "ISNULL", "JOIN", "KEY",
   191    "LEFT", "LIKE", "LIMIT", "MATCH", "NATURAL", "NO", "NOT", "NOTNULL",
   192    "NULL", "OF", "OFFSET", "ON", "OR", "ORDER", "OUTER", "PLAN", "PRAGMA",
   193    "PRIMARY", "QUERY", "RAISE", "RECURSIVE", "REFERENCES", "REGEXP",
   194    "REINDEX", "RELEASE", "RENAME", "REPLACE", "RESTRICT", "RIGHT",
   195    "ROLLBACK", "ROW", "SAVEPOINT", "SELECT", "SET", "TABLE", "TEMP",
   196    "TEMPORARY", "THEN", "TO", "TRANSACTION", "TRIGGER", "UNION", "UNIQUE",
   197    "UPDATE", "USING", "VACUUM", "VALUES", "VIEW", "VIRTUAL", "WHEN", "WHERE",
   198    "WITH", "WITHOUT",
   199  };
   200  #define completionKwCount \
   201     (int)(sizeof(completionKwrds)/sizeof(completionKwrds[0]))
   202  
   203  /*
   204  ** Advance a completion_cursor to its next row of output.
   205  **
   206  ** The ->ePhase, ->j, and ->pStmt fields of the completion_cursor object
   207  ** record the current state of the scan.  This routine sets ->zCurrentRow
   208  ** to the current row of output and then returns.  If no more rows remain,
   209  ** then ->ePhase is set to COMPLETION_EOF which will signal the virtual
   210  ** table that has reached the end of its scan.
   211  **
   212  ** The current implementation just lists potential identifiers and
   213  ** keywords and filters them by zPrefix.  Future enhancements should
   214  ** take zLine into account to try to restrict the set of identifiers and
   215  ** keywords based on what would be legal at the current point of input.
   216  */
   217  static int completionNext(sqlite3_vtab_cursor *cur){
   218    completion_cursor *pCur = (completion_cursor*)cur;
   219    int eNextPhase = 0;  /* Next phase to try if current phase reaches end */
   220    int iCol = -1;       /* If >=0, step pCur->pStmt and use the i-th column */
   221    pCur->iRowid++;
   222    while( pCur->ePhase!=COMPLETION_EOF ){
   223      switch( pCur->ePhase ){
   224        case COMPLETION_KEYWORDS: {
   225          if( pCur->j >= completionKwCount ){
   226            pCur->zCurrentRow = 0;
   227            pCur->ePhase = COMPLETION_DATABASES;
   228          }else{
   229            pCur->zCurrentRow = completionKwrds[pCur->j++];
   230          }
   231          iCol = -1;
   232          break;
   233        }
   234        case COMPLETION_DATABASES: {
   235          if( pCur->pStmt==0 ){
   236            sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1,
   237                               &pCur->pStmt, 0);
   238          }
   239          iCol = 1;
   240          eNextPhase = COMPLETION_TABLES;
   241          break;
   242        }
   243        case COMPLETION_TABLES: {
   244          if( pCur->pStmt==0 ){
   245            sqlite3_stmt *pS2;
   246            char *zSql = 0;
   247            const char *zSep = "";
   248            sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1, &pS2, 0);
   249            while( sqlite3_step(pS2)==SQLITE_ROW ){
   250              const char *zDb = (const char*)sqlite3_column_text(pS2, 1);
   251              zSql = sqlite3_mprintf(
   252                 "%z%s"
   253                 "SELECT name FROM \"%w\".sqlite_master"
   254                 " WHERE type='table'",
   255                 zSql, zSep, zDb
   256              );
   257              if( zSql==0 ) return SQLITE_NOMEM;
   258              zSep = " UNION ";
   259            }
   260            sqlite3_finalize(pS2);
   261            sqlite3_prepare_v2(pCur->db, zSql, -1, &pCur->pStmt, 0);
   262            sqlite3_free(zSql);
   263          }
   264          iCol = 0;
   265          eNextPhase = COMPLETION_COLUMNS;
   266          break;
   267        }
   268        case COMPLETION_COLUMNS: {
   269          if( pCur->pStmt==0 ){
   270            sqlite3_stmt *pS2;
   271            char *zSql = 0;
   272            const char *zSep = "";
   273            sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1, &pS2, 0);
   274            while( sqlite3_step(pS2)==SQLITE_ROW ){
   275              const char *zDb = (const char*)sqlite3_column_text(pS2, 1);
   276              zSql = sqlite3_mprintf(
   277                 "%z%s"
   278                 "SELECT pti.name FROM \"%w\".sqlite_master AS sm"
   279                         " JOIN pragma_table_info(sm.name,%Q) AS pti"
   280                 " WHERE sm.type='table'",
   281                 zSql, zSep, zDb, zDb
   282              );
   283              if( zSql==0 ) return SQLITE_NOMEM;
   284              zSep = " UNION ";
   285            }
   286            sqlite3_finalize(pS2);
   287            sqlite3_prepare_v2(pCur->db, zSql, -1, &pCur->pStmt, 0);
   288            sqlite3_free(zSql);
   289          }
   290          iCol = 0;
   291          eNextPhase = COMPLETION_EOF;
   292          break;
   293        }
   294      }
   295      if( iCol<0 ){
   296        /* This case is when the phase presets zCurrentRow */
   297        if( pCur->zCurrentRow==0 ) continue;
   298      }else{
   299        if( sqlite3_step(pCur->pStmt)==SQLITE_ROW ){
   300          /* Extract the next row of content */
   301          pCur->zCurrentRow = (const char*)sqlite3_column_text(pCur->pStmt, iCol);
   302        }else{
   303          /* When all rows are finished, advance to the next phase */
   304          sqlite3_finalize(pCur->pStmt);
   305          pCur->pStmt = 0;
   306          pCur->ePhase = eNextPhase;
   307          continue;
   308        }
   309      }
   310      if( pCur->nPrefix==0 ) break;
   311      if( sqlite3_strnicmp(pCur->zPrefix, pCur->zCurrentRow, pCur->nPrefix)==0 ){
   312        break;
   313      }
   314    }
   315  
   316    return SQLITE_OK;
   317  }
   318  
   319  /*
   320  ** Return values of columns for the row at which the completion_cursor
   321  ** is currently pointing.
   322  */
   323  static int completionColumn(
   324    sqlite3_vtab_cursor *cur,   /* The cursor */
   325    sqlite3_context *ctx,       /* First argument to sqlite3_result_...() */
   326    int i                       /* Which column to return */
   327  ){
   328    completion_cursor *pCur = (completion_cursor*)cur;
   329    switch( i ){
   330      case COMPLETION_COLUMN_CANDIDATE: {
   331        sqlite3_result_text(ctx, pCur->zCurrentRow, -1, SQLITE_TRANSIENT);
   332        break;
   333      }
   334      case COMPLETION_COLUMN_PREFIX: {
   335        sqlite3_result_text(ctx, pCur->zPrefix, -1, SQLITE_TRANSIENT);
   336        break;
   337      }
   338      case COMPLETION_COLUMN_WHOLELINE: {
   339        sqlite3_result_text(ctx, pCur->zLine, -1, SQLITE_TRANSIENT);
   340        break;
   341      }
   342      case COMPLETION_COLUMN_PHASE: {
   343        sqlite3_result_int(ctx, pCur->ePhase);
   344        break;
   345      }
   346    }
   347    return SQLITE_OK;
   348  }
   349  
   350  /*
   351  ** Return the rowid for the current row.  In this implementation, the
   352  ** rowid is the same as the output value.
   353  */
   354  static int completionRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
   355    completion_cursor *pCur = (completion_cursor*)cur;
   356    *pRowid = pCur->iRowid;
   357    return SQLITE_OK;
   358  }
   359  
   360  /*
   361  ** Return TRUE if the cursor has been moved off of the last
   362  ** row of output.
   363  */
   364  static int completionEof(sqlite3_vtab_cursor *cur){
   365    completion_cursor *pCur = (completion_cursor*)cur;
   366    return pCur->ePhase >= COMPLETION_EOF;
   367  }
   368  
   369  /*
   370  ** This method is called to "rewind" the completion_cursor object back
   371  ** to the first row of output.  This method is always called at least
   372  ** once prior to any call to completionColumn() or completionRowid() or 
   373  ** completionEof().
   374  */
   375  static int completionFilter(
   376    sqlite3_vtab_cursor *pVtabCursor, 
   377    int idxNum, const char *idxStr,
   378    int argc, sqlite3_value **argv
   379  ){
   380    completion_cursor *pCur = (completion_cursor *)pVtabCursor;
   381    int iArg = 0;
   382    (void)(idxStr);   /* Unused parameter */
   383    (void)(argc);     /* Unused parameter */
   384    completionCursorReset(pCur);
   385    if( idxNum & 1 ){
   386      pCur->nPrefix = sqlite3_value_bytes(argv[iArg]);
   387      if( pCur->nPrefix>0 ){
   388        pCur->zPrefix = sqlite3_mprintf("%s", sqlite3_value_text(argv[iArg]));
   389        if( pCur->zPrefix==0 ) return SQLITE_NOMEM;
   390      }
   391      iArg++;
   392    }
   393    if( idxNum & 2 ){
   394      pCur->nLine = sqlite3_value_bytes(argv[iArg]);
   395      if( pCur->nLine>0 ){
   396        pCur->zLine = sqlite3_mprintf("%s", sqlite3_value_text(argv[iArg]));
   397        if( pCur->zLine==0 ) return SQLITE_NOMEM;
   398      }
   399      iArg++;
   400    }
   401    if( pCur->zLine!=0 && pCur->zPrefix==0 ){
   402      int i = pCur->nLine;
   403      while( i>0 && (isalnum(pCur->zLine[i-1]) || pCur->zLine[i-1]=='_') ){
   404        i--;
   405      }
   406      pCur->nPrefix = pCur->nLine - i;
   407      if( pCur->nPrefix>0 ){
   408        pCur->zPrefix = sqlite3_mprintf("%.*s", pCur->nPrefix, pCur->zLine + i);
   409        if( pCur->zPrefix==0 ) return SQLITE_NOMEM;
   410      }
   411    }
   412    pCur->iRowid = 0;
   413    pCur->ePhase = COMPLETION_FIRST_PHASE;
   414    return completionNext(pVtabCursor);
   415  }
   416  
   417  /*
   418  ** SQLite will invoke this method one or more times while planning a query
   419  ** that uses the completion virtual table.  This routine needs to create
   420  ** a query plan for each invocation and compute an estimated cost for that
   421  ** plan.
   422  **
   423  ** There are two hidden parameters that act as arguments to the table-valued
   424  ** function:  "prefix" and "wholeline".  Bit 0 of idxNum is set if "prefix"
   425  ** is available and bit 1 is set if "wholeline" is available.
   426  */
   427  static int completionBestIndex(
   428    sqlite3_vtab *tab,
   429    sqlite3_index_info *pIdxInfo
   430  ){
   431    int i;                 /* Loop over constraints */
   432    int idxNum = 0;        /* The query plan bitmask */
   433    int prefixIdx = -1;    /* Index of the start= constraint, or -1 if none */
   434    int wholelineIdx = -1; /* Index of the stop= constraint, or -1 if none */
   435    int nArg = 0;          /* Number of arguments that completeFilter() expects */
   436    const struct sqlite3_index_constraint *pConstraint;
   437  
   438    (void)(tab);    /* Unused parameter */
   439    pConstraint = pIdxInfo->aConstraint;
   440    for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
   441      if( pConstraint->usable==0 ) continue;
   442      if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
   443      switch( pConstraint->iColumn ){
   444        case COMPLETION_COLUMN_PREFIX:
   445          prefixIdx = i;
   446          idxNum |= 1;
   447          break;
   448        case COMPLETION_COLUMN_WHOLELINE:
   449          wholelineIdx = i;
   450          idxNum |= 2;
   451          break;
   452      }
   453    }
   454    if( prefixIdx>=0 ){
   455      pIdxInfo->aConstraintUsage[prefixIdx].argvIndex = ++nArg;
   456      pIdxInfo->aConstraintUsage[prefixIdx].omit = 1;
   457    }
   458    if( wholelineIdx>=0 ){
   459      pIdxInfo->aConstraintUsage[wholelineIdx].argvIndex = ++nArg;
   460      pIdxInfo->aConstraintUsage[wholelineIdx].omit = 1;
   461    }
   462    pIdxInfo->idxNum = idxNum;
   463    pIdxInfo->estimatedCost = (double)5000 - 1000*nArg;
   464    pIdxInfo->estimatedRows = 500 - 100*nArg;
   465    return SQLITE_OK;
   466  }
   467  
   468  /*
   469  ** This following structure defines all the methods for the 
   470  ** completion virtual table.
   471  */
   472  static sqlite3_module completionModule = {
   473    0,                         /* iVersion */
   474    0,                         /* xCreate */
   475    completionConnect,         /* xConnect */
   476    completionBestIndex,       /* xBestIndex */
   477    completionDisconnect,      /* xDisconnect */
   478    0,                         /* xDestroy */
   479    completionOpen,            /* xOpen - open a cursor */
   480    completionClose,           /* xClose - close a cursor */
   481    completionFilter,          /* xFilter - configure scan constraints */
   482    completionNext,            /* xNext - advance a cursor */
   483    completionEof,             /* xEof - check for end of scan */
   484    completionColumn,          /* xColumn - read data */
   485    completionRowid,           /* xRowid - read data */
   486    0,                         /* xUpdate */
   487    0,                         /* xBegin */
   488    0,                         /* xSync */
   489    0,                         /* xCommit */
   490    0,                         /* xRollback */
   491    0,                         /* xFindMethod */
   492    0,                         /* xRename */
   493    0,                         /* xSavepoint */
   494    0,                         /* xRelease */
   495    0                          /* xRollbackTo */
   496  };
   497  
   498  #endif /* SQLITE_OMIT_VIRTUALTABLE */
   499  
   500  int sqlite3CompletionVtabInit(sqlite3 *db){
   501    int rc = SQLITE_OK;
   502  #ifndef SQLITE_OMIT_VIRTUALTABLE
   503    rc = sqlite3_create_module(db, "completion", &completionModule, 0);
   504  #endif
   505    return rc;
   506  }
   507  
   508  #ifdef _WIN32
   509  __declspec(dllexport)
   510  #endif
   511  int sqlite3_completion_init(
   512    sqlite3 *db, 
   513    char **pzErrMsg, 
   514    const sqlite3_api_routines *pApi
   515  ){
   516    int rc = SQLITE_OK;
   517    SQLITE_EXTENSION_INIT2(pApi);
   518    (void)(pzErrMsg);  /* Unused parameter */
   519  #ifndef SQLITE_OMIT_VIRTUALTABLE
   520    rc = sqlite3CompletionVtabInit(db);
   521  #endif
   522    return rc;
   523  }