/ Check-in [04ef6783]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Initial implementation of a highly experimental interface for listing all keywords and symbolic names for an SQLite database connection.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | experimental-namelist
Files: files | file ages | folders
SHA3-256: 04ef6783a56d87ef7ddc8c58f899d2dd3f5d9c95ac435246e92a670c1eb861e9
User & Date: drh 2017-07-06 17:36:30
Context
2017-07-06
18:25
The sqlite3_namelist() routine now works for all name types. check-in: e41d6217 user: drh tags: experimental-namelist
17:36
Initial implementation of a highly experimental interface for listing all keywords and symbolic names for an SQLite database connection. check-in: 04ef6783 user: drh tags: experimental-namelist
16:33
Change the (machine-generated) keywordhash.h file to increase the scope of the tables used for keyword matching, so that the tables are accessible to functions other then keywordCode(). check-in: c5ed5ebd user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/sqlite.h.in.

8465
8466
8467
8468
8469
8470
8471










































8472
8473
8474
8475
8476
8477
8478
);
int sqlite3_preupdate_old(sqlite3 *, int, sqlite3_value **);
int sqlite3_preupdate_count(sqlite3 *);
int sqlite3_preupdate_depth(sqlite3 *);
int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **);
#endif











































/*
** CAPI3REF: Low-level system error code
**
** ^Attempt to return the underlying operating system error code or error
** number that caused the most recent I/O error or failure to open a file.
** The return value is OS-dependent.  For example, on unix systems, after
** [sqlite3_open_v2()] returns [SQLITE_CANTOPEN], this interface could be







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







8465
8466
8467
8468
8469
8470
8471
8472
8473
8474
8475
8476
8477
8478
8479
8480
8481
8482
8483
8484
8485
8486
8487
8488
8489
8490
8491
8492
8493
8494
8495
8496
8497
8498
8499
8500
8501
8502
8503
8504
8505
8506
8507
8508
8509
8510
8511
8512
8513
8514
8515
8516
8517
8518
8519
8520
);
int sqlite3_preupdate_old(sqlite3 *, int, sqlite3_value **);
int sqlite3_preupdate_count(sqlite3 *);
int sqlite3_preupdate_depth(sqlite3 *);
int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **);
#endif

/*
** CAPI3REF: List Of Symbolic Names
**
** ^The sqlite3_namelist(D,P,F) interface returns a list of symbolic names
** and keywords that might appear in valid SQL statements for [connection]
** D and that all begin with the prefix P.  ^The F parameter is a bitmask
** that determines the kinds of symbolic names and keywords that are found
** in the list.  ^Matching against the prefix P is performed using
** [sqlite3_strnicmp()] and is thus case insensitive for ASCII characters.
**
** ^The value returned by sqlite3_namelist() is stored in memory obtained
** from [sqlite3_malloc()] and must be released by the caller using
** [sqlite3_free()].  ^The sqlite3_namelist() interface returns NULL if a
** memory allocation error occurs.
**
** ^Elements of the list are in no particular order and may include duplicates.
** ^Each element is separated from the next by a single 0x00 byte.  ^The list
** is terminated by a single zero-length entry.
**
** This interface is intended to facilitate tab-completion for interactive
** interfaces for SQLite.
*/
char *sqlite3_namelist(sqlite3 *db, const char *zPrefix, int typeMask);

/*
** CAPI3REF: Symbolic Name Typemask Values
**
** ^These bitmask values are used to determine the kinds of symbolic names
** and keywords that are returned by [sqlite3_namelist()].  The third
** parameter to [sqlite3_namelist()] should be an OR-ed combination of
** one or more of the following value.
*/
#define SQLITE_NAMETYPE_KEYWORD    0x0001
#define SQLITE_NAMETYPE_SCHEMA     0x0002
#define SQLITE_NAMETYPE_TABLE      0x0004
#define SQLITE_NAMETYPE_INDEX      0x0008
#define SQLITE_NAMETYPE_TRIGGER    0x0010
#define SQLITE_NAMETYPE_FUNCTION   0x0020
#define SQLITE_NAMETYPE_MODULE     0x0040
#define SQLITE_NAMETYPE_COLLATION  0x0080
#define SQLITE_NAMETYPE_COLUMN     0x0100

/*
** CAPI3REF: Low-level system error code
**
** ^Attempt to return the underlying operating system error code or error
** number that caused the most recent I/O error or failure to open a file.
** The return value is OS-dependent.  For example, on unix systems, after
** [sqlite3_open_v2()] returns [SQLITE_CANTOPEN], this interface could be

Changes to src/tclsqlite.c.

1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
....
2660
2661
2662
2663
2664
2665
2666



























2667
2668
2669
2670
2671
2672
2673
  static const char *DB_strs[] = {
    "authorizer",         "backup",            "busy",
    "cache",              "changes",           "close",
    "collate",            "collation_needed",  "commit_hook",
    "complete",           "copy",              "enable_load_extension",
    "errorcode",          "eval",              "exists",
    "function",           "incrblob",          "interrupt",
    "last_insert_rowid",  "nullvalue",         "onecolumn",
    "preupdate",          "profile",           "progress",
    "rekey",              "restore",           "rollback_hook",
    "status",             "timeout",           "total_changes",
    "trace",              "trace_v2",          "transaction",
    "unlock_notify",      "update_hook",       "version",
    "wal_hook",
    0
  };
  enum DB_enum {
    DB_AUTHORIZER,        DB_BACKUP,           DB_BUSY,
    DB_CACHE,             DB_CHANGES,          DB_CLOSE,
    DB_COLLATE,           DB_COLLATION_NEEDED, DB_COMMIT_HOOK,
    DB_COMPLETE,          DB_COPY,             DB_ENABLE_LOAD_EXTENSION,
    DB_ERRORCODE,         DB_EVAL,             DB_EXISTS,
    DB_FUNCTION,          DB_INCRBLOB,         DB_INTERRUPT,
    DB_LAST_INSERT_ROWID, DB_NULLVALUE,        DB_ONECOLUMN,
    DB_PREUPDATE,         DB_PROFILE,          DB_PROGRESS,
    DB_REKEY,             DB_RESTORE,          DB_ROLLBACK_HOOK,
    DB_STATUS,            DB_TIMEOUT,          DB_TOTAL_CHANGES,
    DB_TRACE,             DB_TRACE_V2,         DB_TRANSACTION,
    DB_UNLOCK_NOTIFY,     DB_UPDATE_HOOK,      DB_VERSION,
    DB_WAL_HOOK,
  };
  /* don't leave trailing commas on DB_enum, it confuses the AIX xlc compiler */

  if( objc<2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ...");
    return TCL_ERROR;
  }
................................................................................
  ** Interrupt the execution of the inner-most SQL interpreter.  This
  ** causes the SQL statement to return an error of SQLITE_INTERRUPT.
  */
  case DB_INTERRUPT: {
    sqlite3_interrupt(pDb->db);
    break;
  }




























  /*
  **     $db nullvalue ?STRING?
  **
  ** Change text used when a NULL comes back from the database. If ?STRING?
  ** is not present, then the current string used for NULL is returned.
  ** If STRING is present, then STRING is returned.







|
|
|
|
|
|
|
<








|
|
|
|
|
|
|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859

1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
....
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
  static const char *DB_strs[] = {
    "authorizer",         "backup",            "busy",
    "cache",              "changes",           "close",
    "collate",            "collation_needed",  "commit_hook",
    "complete",           "copy",              "enable_load_extension",
    "errorcode",          "eval",              "exists",
    "function",           "incrblob",          "interrupt",
    "last_insert_rowid",  "namelist",          "nullvalue",
    "onecolumn",          "preupdate",         "profile",
    "progress",           "rekey",             "restore",
    "rollback_hook",      "status",            "timeout",
    "total_changes",      "trace",             "trace_v2",
    "transaction",        "unlock_notify",     "update_hook",
    "version",            "wal_hook",          0

  };
  enum DB_enum {
    DB_AUTHORIZER,        DB_BACKUP,           DB_BUSY,
    DB_CACHE,             DB_CHANGES,          DB_CLOSE,
    DB_COLLATE,           DB_COLLATION_NEEDED, DB_COMMIT_HOOK,
    DB_COMPLETE,          DB_COPY,             DB_ENABLE_LOAD_EXTENSION,
    DB_ERRORCODE,         DB_EVAL,             DB_EXISTS,
    DB_FUNCTION,          DB_INCRBLOB,         DB_INTERRUPT,
    DB_LAST_INSERT_ROWID, DB_NAMELIST,         DB_NULLVALUE,
    DB_ONECOLUMN,         DB_PREUPDATE,        DB_PROFILE,
    DB_PROGRESS,          DB_REKEY,            DB_RESTORE,
    DB_ROLLBACK_HOOK,     DB_STATUS,           DB_TIMEOUT,
    DB_TOTAL_CHANGES,     DB_TRACE,            DB_TRACE_V2,
    DB_TRANSACTION,       DB_UNLOCK_NOTIFY,    DB_UPDATE_HOOK,
    DB_VERSION,           DB_WAL_HOOK,         
  };
  /* don't leave trailing commas on DB_enum, it confuses the AIX xlc compiler */

  if( objc<2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ...");
    return TCL_ERROR;
  }
................................................................................
  ** Interrupt the execution of the inner-most SQL interpreter.  This
  ** causes the SQL statement to return an error of SQLITE_INTERRUPT.
  */
  case DB_INTERRUPT: {
    sqlite3_interrupt(pDb->db);
    break;
  }

  /*
  **     $db namelist PREFIX MASK
  */
  case DB_NAMELIST: {
    const char *zPrefix;
    int mask;
    char *zList;
    if( objc!=4 ){
      Tcl_WrongNumArgs(interp, 2, objv, "PREFIX MASK");
      return TCL_ERROR;
    }
    zPrefix = Tcl_GetString(objv[2]);
    if( Tcl_GetIntFromObj(interp, objv[3], &mask) ) return TCL_ERROR;
    zList = sqlite3_namelist(pDb->db, zPrefix, mask);
    if( zList ){
      Tcl_Obj *pList = Tcl_NewObj();
      int i, n;
      for(i=0; zList[i]; i += n+1){
        n = (int)strlen(&zList[i]);
        Tcl_ListObjAppendElement(interp, pList, Tcl_NewStringObj(&zList[i],-1));
      }
      sqlite3_free(zList);
      Tcl_SetObjResult(interp, pList);
    }
    break;
  }

  /*
  **     $db nullvalue ?STRING?
  **
  ** Change text used when a NULL comes back from the database. If ?STRING?
  ** is not present, then the current string used for NULL is returned.
  ** If STRING is present, then STRING is returned.

Changes to src/tokenize.c.

610
611
612
613
614
615
616

















































    Table *p = pParse->pZombieTab;
    pParse->pZombieTab = p->pNextZombie;
    sqlite3DeleteTable(db, p);
  }
  assert( nErr==0 || pParse->rc!=SQLITE_OK );
  return nErr;
}
























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
    Table *p = pParse->pZombieTab;
    pParse->pZombieTab = p->pNextZombie;
    sqlite3DeleteTable(db, p);
  }
  assert( nErr==0 || pParse->rc!=SQLITE_OK );
  return nErr;
}

/* An instance of the following object is used to accumulate a list
** of names for the sqlite3_namelist() interface
*/
struct NameAccum {
  StrAccum x;              /* Name list string stored here */
  const char *zPrefix;     /* All names must start with this prefix */
  int nPrefix;             /* Size of the prefix in bytes */
};

/*
** Examine zName to see if it belongs on the list (if it has a matching
** prefix) and add it to the list if it belongs.  nName is the length
** of the name in bytes, or -1 if zName is zero-terminated.
*/
static void addName(struct NameAccum *p, const char *zName, int nName){
  if( nName<0 ) nName = sqlite3Strlen30(zName);
  if( nName<p->nPrefix ) return;
  if( sqlite3StrNICmp(p->zPrefix, zName, p->nPrefix)!=0 ) return;
  sqlite3StrAccumAppend(&p->x, zName, nName);
  sqlite3StrAccumAppend(&p->x, "", 1);
}

/*
** Return a list of text words or identifiers that might appear in an
** SQL statement.  The typeMask parameter is a bitmask that determines
** specifically what kinds of names should be returned.  All names
** returned must begin with zPrefix.
**
** The returned list is from a single memory allocation.  The caller owns
** the allocation and should release it using sqlite3_free() when it has
** finished using the list.
**
** Each word is separated from the next by a single 0x00 byte.  The list
** is terminated by two 0x00 bytes in a row.
*/
char *sqlite3_namelist(sqlite3 *db, const char *zPrefix, int typeMask){
  struct NameAccum x;
  int i;
  x.zPrefix = zPrefix;
  x.nPrefix = sqlite3Strlen30(zPrefix);
  sqlite3StrAccumInit(&x.x, 0, 0, 0, 100000000);
  if( typeMask & SQLITE_NAMETYPE_KEYWORD ){
    for(i=0; i<ArraySize(aKWOffset); i++){
      addName(&x, zKWText + aKWOffset[i], aKWLen[i]);
    }
  }
  return sqlite3StrAccumFinish(&x.x);
}