SQLite

Check-in [7029111044]
Login

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

Overview
Comment:Change the sqlite3_namelist() interface to return a pointer to an array of pointers to strings, and to avoid duplicates.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | experimental-namelist
Files: files | file ages | folders
SHA3-256: 702911104424f03f6ebe3beb9090f73b52abe2e655537b8cd8a32e799718ed14
User & Date: drh 2017-07-06 18:52:36.337
Context
2017-07-06
19:26
Use the sqlite3_namelist() interface to implement simple tab-completion using linenoise. (check-in: 5cc7b0e2ca user: drh tags: experimental-namelist)
18:52
Change the sqlite3_namelist() interface to return a pointer to an array of pointers to strings, and to avoid duplicates. (check-in: 7029111044 user: drh tags: experimental-namelist)
18:25
The sqlite3_namelist() routine now works for all name types. (check-in: e41d62175b user: drh tags: experimental-namelist)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/hash.h.
87
88
89
90
91
92
93
94
95
96
#define sqliteHashData(E)   ((E)->data)
/* #define sqliteHashKey(E)    ((E)->pKey) // NOT USED */
/* #define sqliteHashKeysize(E) ((E)->nKey)  // NOT USED */

/*
** Number of entries in a hash table
*/
/* #define sqliteHashCount(H)  ((H)->count) // NOT USED */

#endif /* SQLITE_HASH_H */







|


87
88
89
90
91
92
93
94
95
96
#define sqliteHashData(E)   ((E)->data)
/* #define sqliteHashKey(E)    ((E)->pKey) // NOT USED */
/* #define sqliteHashKeysize(E) ((E)->nKey)  // NOT USED */

/*
** Number of entries in a hash table
*/
#define sqliteHashCount(H)  ((H)->count)

#endif /* SQLITE_HASH_H */
Changes to src/sqlite.h.in.
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
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







|





>
>






|
<
<




|







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
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,N) 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.
** ^If the pointer N is not NULL, then the number of matching names is
** stored in *N.
**
** ^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 unique but are in no particular order.


**
** This interface is intended to facilitate tab-completion for interactive
** interfaces for SQLite.
*/
char **sqlite3_namelist(sqlite3 *db, const char *zPrefix, int typeMask, int*);

/*
** 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
Changes to src/tclsqlite.c.
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

  /*
  **     $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?







|
>






|
|
|
<
|
<
|
>

>
|







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

  /*
  **     $db namelist PREFIX MASK
  */
  case DB_NAMELIST: {
    const char *zPrefix;
    int mask;
    char **azList;
    int nList, i;
    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;
    azList = sqlite3_namelist(pDb->db, zPrefix, mask, &nList);
    if( azList ){
      Tcl_Obj *pList = Tcl_NewListObj(nList, 0);

      for(i=0; azList[i]; i++){

        Tcl_ListObjAppendElement(interp, pList,
                                 Tcl_NewStringObj(azList[i],-1));
      }
      assert( i==nList );
      sqlite3_free(azList);
      Tcl_SetObjResult(interp, pList);
    }
    break;
  }

  /*
  **     $db nullvalue ?STRING?
Changes to src/tokenize.c.
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
666
  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;
  HashElem *j;


  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]);
    }
  }
  if( typeMask & SQLITE_NAMETYPE_FUNCTION ){
    for(i=0; i<SQLITE_FUNC_HASH_SZ; i++){







|










>
>



>
|
|















|
>
>
>
>
>

|

>
>


|







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
666
667
668
669
670
671
672
673
674
675
676
  return nErr;
}

/* An instance of the following object is used to accumulate a list
** of names for the sqlite3_namelist() interface
*/
struct NameAccum {
  Hash x;                  /* Hash table of all names */
  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){
  char *zCopy;
  char *zOld;
  if( nName<0 ) nName = sqlite3Strlen30(zName);
  if( nName<p->nPrefix ) return;
  if( sqlite3StrNICmp(p->zPrefix, zName, p->nPrefix)!=0 ) return;
  zCopy = sqlite3_mprintf("%.*s", nName, zName);
  zOld = sqlite3HashInsert(&p->x, zCopy, zCopy);
  sqlite3_free(zOld);  
}

/*
** 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,             /* Database from which to extract names */
  const char *zPrefix,     /* Only extract names matching this prefix */
  int typeMask,            /* Mask of the types of names to extract */
  int *pCount              /* Write the number of names here */
){
  struct NameAccum x;
  int i, n, nEntry;
  HashElem *j;
  char **azAns;
  char *zFree;
  x.zPrefix = zPrefix;
  x.nPrefix = sqlite3Strlen30(zPrefix);
  sqlite3HashInit(&x.x);
  if( typeMask & SQLITE_NAMETYPE_KEYWORD ){
    for(i=0; i<ArraySize(aKWOffset); i++){
      addName(&x, zKWText + aKWOffset[i], aKWLen[i]);
    }
  }
  if( typeMask & SQLITE_NAMETYPE_FUNCTION ){
    for(i=0; i<SQLITE_FUNC_HASH_SZ; i++){
720
721
722
723
724
725
726


727
























728
729
      if( typeMask & SQLITE_NAMETYPE_TRIGGER ){
        for(j=sqliteHashFirst(&pDb->pSchema->trigHash); j; j=sqliteHashNext(j)){
          Trigger *p = (Trigger*)sqliteHashData(j);
          addName(&x, p->zName, -1);
        }
      }
    }


  }
























  return sqlite3StrAccumFinish(&x.x);
}







>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|

730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
      if( typeMask & SQLITE_NAMETYPE_TRIGGER ){
        for(j=sqliteHashFirst(&pDb->pSchema->trigHash); j; j=sqliteHashNext(j)){
          Trigger *p = (Trigger*)sqliteHashData(j);
          addName(&x, p->zName, -1);
        }
      }
    }
    if( typeMask & SQLITE_NAMETYPE_COLUMN ){
      addName(&x, "rowid", -1);
    }
  }
  nEntry = sqliteHashCount(&x.x);
  if( pCount ) *pCount = nEntry;
  n = 0;
  for(j=sqliteHashFirst(&x.x); j; j=sqliteHashNext(j)){
    n += sqlite3Strlen30((const char*)sqliteHashData(j));
  }
  zFree = sqlite3_malloc( (nEntry+1)*sizeof(char*) + n + nEntry );
  if( zFree ){
    memset(zFree, 0, (nEntry+1)*sizeof(char*) + n + nEntry );
    azAns = (char**)zFree;
    zFree += (nEntry+1)*sizeof(char*);
    for(i=0, j=sqliteHashFirst(&x.x); j; i++, j=sqliteHashNext(j)){
      const char *zName = (const char*)sqliteHashData(j);
      azAns[i] = zFree;
      n = sqlite3Strlen30(zName);
      memcpy(zFree, zName, n+1);
      zFree += n+1;
    }
  }
  for(j=sqliteHashFirst(&x.x); j; j=sqliteHashNext(j)){
    sqlite3_free(sqliteHashData(j));
  }
  sqlite3HashClear(&x.x);
  return azAns;
}