SQLite4
Check-in [ff68adaca1]
Not logged in

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

Overview
Comment:Remove the sqlite4_get_table() API.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: ff68adaca1a45b382aad6ddf020909c6841faba6
User & Date: drh 2012-04-23 12:47:08
Context
2012-04-23
14:11
Add an xMkKey callback to the built-in collation sequence "nocase". Fix a bug in encoding text values with collation sequences into database keys. check-in: 6c9adc9acc user: dan tags: trunk
12:47
Remove the sqlite4_get_table() API. check-in: ff68adaca1 user: drh tags: trunk
12:07
Allow multiple NULL values in a UNIQUE index. check-in: 4dbb499c39 user: dan tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to main.mk.

58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
...
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
         fts3_write.o func.o global.o hash.o \
         icu.o insert.o kvlsm.o kvmem.o legacy.o \
         main.o malloc.o math.o mem0.o mem1.o mem2.o mem3.o mem5.o \
         mutex.o mutex_noop.o mutex_os2.o mutex_unix.o mutex_w32.o \
         opcodes.o os.o os_os2.o os_unix.o os_win.o \
         parse.o pragma.o prepare.o printf.o \
         random.o resolve.o rowset.o rtree.o select.o status.o storage.o \
         table.o tokenize.o trigger.o \
         update.o util.o varint.o \
         vdbe.o vdbeapi.o vdbeaux.o vdbecodec.o vdbecursor.o \
         vdbemem.o vdbesort.o vdbetrace.o \
         walker.o where.o utf.o vtab.o



................................................................................
  $(TOP)/src/shell.c \
  $(TOP)/src/sqlite.h.in \
  $(TOP)/src/sqliteInt.h \
  $(TOP)/src/sqliteLimit.h \
  $(TOP)/src/status.c \
  $(TOP)/src/storage.c \
  $(TOP)/src/storage.h \
  $(TOP)/src/table.c \
  $(TOP)/src/tclsqlite.c \
  $(TOP)/src/tokenize.c \
  $(TOP)/src/trigger.c \
  $(TOP)/src/utf.c \
  $(TOP)/src/update.c \
  $(TOP)/src/util.c \
  $(TOP)/src/varint.c \







|







 







<







58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
...
127
128
129
130
131
132
133

134
135
136
137
138
139
140
         fts3_write.o func.o global.o hash.o \
         icu.o insert.o kvlsm.o kvmem.o legacy.o \
         main.o malloc.o math.o mem0.o mem1.o mem2.o mem3.o mem5.o \
         mutex.o mutex_noop.o mutex_os2.o mutex_unix.o mutex_w32.o \
         opcodes.o os.o os_os2.o os_unix.o os_win.o \
         parse.o pragma.o prepare.o printf.o \
         random.o resolve.o rowset.o rtree.o select.o status.o storage.o \
         tokenize.o trigger.o \
         update.o util.o varint.o \
         vdbe.o vdbeapi.o vdbeaux.o vdbecodec.o vdbecursor.o \
         vdbemem.o vdbesort.o vdbetrace.o \
         walker.o where.o utf.o vtab.o



................................................................................
  $(TOP)/src/shell.c \
  $(TOP)/src/sqlite.h.in \
  $(TOP)/src/sqliteInt.h \
  $(TOP)/src/sqliteLimit.h \
  $(TOP)/src/status.c \
  $(TOP)/src/storage.c \
  $(TOP)/src/storage.h \

  $(TOP)/src/tclsqlite.c \
  $(TOP)/src/tokenize.c \
  $(TOP)/src/trigger.c \
  $(TOP)/src/utf.c \
  $(TOP)/src/update.c \
  $(TOP)/src/util.c \
  $(TOP)/src/varint.c \

Changes to src/shell.c.

2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088


























2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107

2108
2109
2110
2111
2112
2113
2114
2115
  }else

  if( c=='s' && strncmp(azArg[0], "stats", n)==0 && nArg>1 && nArg<3 ){
    p->statsOn = booleanValue(azArg[1]);
  }else

  if( c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0 && nArg<3 ){
    char **azResult;
    int nRow;
    char *zErrMsg;
    open_db(p);
    if( nArg==1 ){
      rc = sqlite4_get_table(p->db,
        "SELECT name FROM sqlite_master "
        "WHERE type IN ('table','view') AND name NOT LIKE 'sqlite_%' "
        "UNION ALL "
        "SELECT name FROM sqlite_temp_master "
        "WHERE type IN ('table','view') "
        "ORDER BY 1",
        &azResult, &nRow, 0, &zErrMsg
      );
    }else{
      zShellStatic = azArg[1];
      rc = sqlite4_get_table(p->db,
        "SELECT name FROM sqlite_master "
        "WHERE type IN ('table','view') AND name LIKE shellstatic() "
        "UNION ALL "
        "SELECT name FROM sqlite_temp_master "
        "WHERE type IN ('table','view') AND name LIKE shellstatic() "
        "ORDER BY 1",
        &azResult, &nRow, 0, &zErrMsg
      );
      zShellStatic = 0;
    }
    if( zErrMsg ){
      fprintf(stderr,"Error: %s\n", zErrMsg);
      sqlite4_free(zErrMsg);
      rc = 1;
    }else if( rc != SQLITE_OK ){
      fprintf(stderr,"Error: querying sqlite_master and sqlite_temp_master\n");
      rc = 1;
    }else{


























      int len, maxlen = 0;
      int i, j;
      int nPrintCol, nPrintRow;
      for(i=1; i<=nRow; i++){
        if( azResult[i]==0 ) continue;
        len = strlen30(azResult[i]);
        if( len>maxlen ) maxlen = len;
      }
      nPrintCol = 80/(maxlen+2);
      if( nPrintCol<1 ) nPrintCol = 1;
      nPrintRow = (nRow + nPrintCol - 1)/nPrintCol;
      for(i=0; i<nPrintRow; i++){
        for(j=i+1; j<=nRow; j+=nPrintRow){
          char *zSp = j<=nPrintRow ? "" : "  ";
          printf("%s%-*s", zSp, maxlen, azResult[j] ? azResult[j] : "");
        }
        printf("\n");
      }
    }

    sqlite4_free_table(azResult);
  }else

  if( c=='t' && n>=8 && strncmp(azArg[0], "testctrl", n)==0 && nArg>=2 ){
    static const struct {
       const char *zCtrlName;   /* Name of a test-control option */
       int ctrlCode;            /* Integer code for that option */
    } aCtrl[] = {







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



|
<







|
|





>
|







2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118

2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
  }else

  if( c=='s' && strncmp(azArg[0], "stats", n)==0 && nArg>1 && nArg<3 ){
    p->statsOn = booleanValue(azArg[1]);
  }else

  if( c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0 && nArg<3 ){
    sqlite4_stmt *pStmt;
    char **azResult;
    int nRow, nAlloc;
    char *zSql = 0;
    int ii;
    open_db(p);
    rc = sqlite4_prepare(p->db, "PRAGMA database_list", -1, &pStmt, 0);
    if( rc ) return rc;
    zSql = sqlite4_mprintf(
        "SELECT name FROM sqlite_master"
        " WHERE type IN ('table','view')"
        "   AND name NOT LIKE 'sqlite_%%'"
        "   AND name LIKE ?1");
    while( sqlite4_step(pStmt)==SQLITE_ROW ){
      const char *zDbName = (const char*)sqlite4_column_text(pStmt, 1);
      if( zDbName==0 || strcmp(zDbName,"main")==0 ) continue;
      if( strcmp(zDbName,"temp")==0 ){
        zSql = sqlite4_mprintf(
                 "%z UNION ALL "
                 "SELECT 'temp.' || name FROM sqlite_temp_master"
                 " WHERE type IN ('table','view')"
                 "   AND name NOT LIKE 'sqlite_%%'"
                 "   AND name LIKE ?1", zSql);
      }else{
        zSql = sqlite4_mprintf(
                 "%z UNION ALL "
                 "SELECT '%q.' || name FROM \"%w\".sqlite_master"
                 " WHERE type IN ('table','view')"
                 "   AND name NOT LIKE 'sqlite_%%'"
                 "   AND name LIKE ?1", zSql, zDbName, zDbName);
      }
    }
    sqlite4_finalize(pStmt);
    zSql = sqlite4_mprintf("%z ORDER BY 1", zSql);
    rc = sqlite4_prepare(p->db, zSql, -1, &pStmt, 0);
    sqlite4_free(zSql);
    if( rc ) return rc;
    nRow = nAlloc = 0;
    azResult = 0;
    if( nArg>1 ){
      sqlite4_bind_text(pStmt, 1, azArg[1], -1, SQLITE_TRANSIENT);
    }else{
      sqlite4_bind_text(pStmt, 1, "%", -1, SQLITE_STATIC);
    }
    while( sqlite4_step(pStmt)==SQLITE_ROW ){
      if( nRow>=nAlloc ){
        char **azNew;
        int n = nAlloc*2 + 10;
        azNew = sqlite4_realloc(azResult, sizeof(azResult[0])*n);
        if( azNew==0 ){
          fprintf(stderr, "Error: out of memory\n");
          break;
        }
        nAlloc = n;
        azResult = azNew;
      }
      azResult[nRow] = sqlite4_mprintf("%s", sqlite4_column_text(pStmt, 0));
      if( azResult[nRow] ) nRow++;
    }
    sqlite4_finalize(pStmt);        
    if( nRow>0 ){
      int len, maxlen = 0;
      int i, j;
      int nPrintCol, nPrintRow;
      for(i=0; i<nRow; i++){

        len = strlen30(azResult[i]);
        if( len>maxlen ) maxlen = len;
      }
      nPrintCol = 80/(maxlen+2);
      if( nPrintCol<1 ) nPrintCol = 1;
      nPrintRow = (nRow + nPrintCol - 1)/nPrintCol;
      for(i=0; i<nPrintRow; i++){
        for(j=i; j<nRow; j+=nPrintRow){
          char *zSp = j<nPrintRow ? "" : "  ";
          printf("%s%-*s", zSp, maxlen, azResult[j] ? azResult[j] : "");
        }
        printf("\n");
      }
    }
    for(ii=0; ii<nRow; ii++) sqlite4_free(azResult[ii]);
    sqlite4_free(azResult);
  }else

  if( c=='t' && n>=8 && strncmp(azArg[0], "testctrl", n)==0 && nArg>=2 ){
    static const struct {
       const char *zCtrlName;   /* Name of a test-control option */
       int ctrlCode;            /* Integer code for that option */
    } aCtrl[] = {

Changes to src/sqlite.h.in.

1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
....
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
**
** The input to [sqlite4_complete16()] must be a zero-terminated
** UTF-16 string in native byte order.
*/
int sqlite4_complete(const char *sql);
int sqlite4_complete16(const void *sql);

/*
** CAPI3REF: Convenience Routines For Running Queries
**
** This is a legacy interface that is preserved for backwards compatibility.
** Use of this interface is not recommended.
**
** Definition: A <b>result table</b> is memory data structure created by the
** [sqlite4_get_table()] interface.  A result table records the
** complete query results from one or more queries.
**
** The table conceptually has a number of rows and columns.  But
** these numbers are not part of the result table itself.  These
** numbers are obtained separately.  Let N be the number of rows
** and M be the number of columns.
**
** A result table is an array of pointers to zero-terminated UTF-8 strings.
** There are (N+1)*M elements in the array.  The first M pointers point
** to zero-terminated strings that  contain the names of the columns.
** The remaining entries all point to query results.  NULL values result
** in NULL pointers.  All other values are in their UTF-8 zero-terminated
** string representation as returned by [sqlite4_column_text()].
**
** A result table might consist of one or more memory allocations.
** It is not safe to pass a result table directly to [sqlite4_free()].
** A result table should be deallocated using [sqlite4_free_table()].
**
** ^(As an example of the result table format, suppose a query result
** is as follows:
**
** <blockquote><pre>
**        Name        | Age
**        -----------------------
**        Alice       | 43
**        Bob         | 28
**        Cindy       | 21
** </pre></blockquote>
**
** There are two column (M==2) and three rows (N==3).  Thus the
** result table has 8 entries.  Suppose the result table is stored
** in an array names azResult.  Then azResult holds this content:
**
** <blockquote><pre>
**        azResult&#91;0] = "Name";
**        azResult&#91;1] = "Age";
**        azResult&#91;2] = "Alice";
**        azResult&#91;3] = "43";
**        azResult&#91;4] = "Bob";
**        azResult&#91;5] = "28";
**        azResult&#91;6] = "Cindy";
**        azResult&#91;7] = "21";
** </pre></blockquote>)^
**
** ^The sqlite4_get_table() function evaluates one or more
** semicolon-separated SQL statements in the zero-terminated UTF-8
** string of its 2nd parameter and returns a result table to the
** pointer given in its 3rd parameter.
**
** After the application has finished with the result from sqlite4_get_table(),
** it must pass the result table pointer to sqlite4_free_table() in order to
** release the memory that was malloced.  Because of the way the
** [sqlite4_malloc()] happens within sqlite4_get_table(), the calling
** function must not try to call [sqlite4_free()] directly.  Only
** [sqlite4_free_table()] is able to release the memory properly and safely.
**
** The sqlite4_get_table() interface is implemented as a wrapper around
** [sqlite4_exec()].  The sqlite4_get_table() routine does not have access
** to any internal data structures of SQLite.  It uses only the public
** interface defined here.  As a consequence, errors that occur in the
** wrapper layer outside of the internal [sqlite4_exec()] call are not
** reflected in subsequent calls to [sqlite4_errcode()] or
** [sqlite4_errmsg()].
*/
int sqlite4_get_table(
  sqlite4 *db,          /* An open database */
  const char *zSql,     /* SQL to be evaluated */
  char ***pazResult,    /* Results of the query */
  int *pnRow,           /* Number of result rows written here */
  int *pnColumn,        /* Number of result columns written here */
  char **pzErrmsg       /* Error msg written here */
);
void sqlite4_free_table(char **result);

/*
** CAPI3REF: Formatted String Printing Functions
**
** These routines are work-alikes of the "printf()" family of functions
** from the standard C library.
**
................................................................................
   void(*xProfile)(void*,const char*,sqlite4_uint64), void*);

/*
** CAPI3REF: Query Progress Callbacks
**
** ^The sqlite4_progress_handler(D,N,X,P) interface causes the callback
** function X to be invoked periodically during long running calls to
** [sqlite4_exec()], [sqlite4_step()] and [sqlite4_get_table()] for
** database connection D.  An example use for this
** interface is to keep a GUI updated during a large query.
**
** ^The parameter P is passed through as the only parameter to the 
** callback function X.  ^The parameter N is the number of 
** [virtual machine instructions] that are evaluated between successive
** invocations of the callback X.







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







|







1708
1709
1710
1711
1712
1713
1714

















































































1715
1716
1717
1718
1719
1720
1721
....
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
**
** The input to [sqlite4_complete16()] must be a zero-terminated
** UTF-16 string in native byte order.
*/
int sqlite4_complete(const char *sql);
int sqlite4_complete16(const void *sql);



















































































/*
** CAPI3REF: Formatted String Printing Functions
**
** These routines are work-alikes of the "printf()" family of functions
** from the standard C library.
**
................................................................................
   void(*xProfile)(void*,const char*,sqlite4_uint64), void*);

/*
** CAPI3REF: Query Progress Callbacks
**
** ^The sqlite4_progress_handler(D,N,X,P) interface causes the callback
** function X to be invoked periodically during long running calls to
** [sqlite4_exec()] and [sqlite4_step()] for
** database connection D.  An example use for this
** interface is to keep a GUI updated during a large query.
**
** ^The parameter P is passed through as the only parameter to the 
** callback function X.  ^The parameter N is the number of 
** [virtual machine instructions] that are evaluated between successive
** invocations of the callback X.

Changes to src/test1.c.

563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
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
....
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
  if( n>sizeof(zStr) ) n = sizeof(zStr);
  sqlite4_snprintf(sizeof(zStr), zStr, "abcdefghijklmnopqrstuvwxyz");
  sqlite4_snprintf(n, zStr, zFormat, a1);
  Tcl_AppendResult(interp, zStr, 0);
  return TCL_OK;
}

#ifndef SQLITE_OMIT_GET_TABLE

/*
** Usage:  sqlite4_get_table_printf  DB  FORMAT  STRING  ?--no-counts?
**
** Invoke the sqlite4_get_table_printf() interface using the open database
** DB.  The SQL is the string FORMAT.  The format string should contain
** one %s or %q.  STRING is the value inserted into %s or %q.
*/
static int test_get_table_printf(
  void *NotUsed,
  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  int argc,              /* Number of arguments */
  char **argv            /* Text of each argument */
){
  sqlite4 *db;
  Tcl_DString str;
  int rc;
  char *zErr = 0;
  int nRow, nCol;
  char **aResult;
  int i;
  char zBuf[30];
  char *zSql;
  int resCount = -1;
  if( argc==5 ){
    if( Tcl_GetInt(interp, argv[4], &resCount) ) return TCL_ERROR;
  }
  if( argc!=4 && argc!=5 ){
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 
       " DB FORMAT STRING ?COUNT?", 0);
    return TCL_ERROR;
  }
  if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
  Tcl_DStringInit(&str);
  zSql = sqlite4_mprintf(argv[2],argv[3]);
  if( argc==5 ){
    rc = sqlite4_get_table(db, zSql, &aResult, 0, 0, &zErr);
  }else{
    rc = sqlite4_get_table(db, zSql, &aResult, &nRow, &nCol, &zErr);
    resCount = (nRow+1)*nCol;
  }
  sqlite4_free(zSql);
  sprintf(zBuf, "%d", rc);
  Tcl_AppendElement(interp, zBuf);
  if( rc==SQLITE_OK ){
    if( argc==4 ){
      sprintf(zBuf, "%d", nRow);
      Tcl_AppendElement(interp, zBuf);
      sprintf(zBuf, "%d", nCol);
      Tcl_AppendElement(interp, zBuf);
    }
    for(i=0; i<resCount; i++){
      Tcl_AppendElement(interp, aResult[i] ? aResult[i] : "NULL");
    }
  }else{
    Tcl_AppendElement(interp, zErr);
  }
  sqlite4_free_table(aResult);
  if( zErr ) sqlite4_free(zErr);
  if( sqlite4TestErrCode(interp, db, rc) ) return TCL_ERROR;
  return TCL_OK;
}

#endif /* SQLITE_OMIT_GET_TABLE */


/*
** Usage:  sqlite4_last_insert_rowid DB
**
** Returns the integer ROWID of the most recent insert.
*/
................................................................................
     { "sqlite4_mprintf_n_test",        (Tcl_CmdProc*)test_mprintf_n        },
     { "sqlite4_snprintf_int",          (Tcl_CmdProc*)test_snprintf_int     },
     { "sqlite4_last_insert_rowid",     (Tcl_CmdProc*)test_last_rowid       },
     { "sqlite4_exec_printf",           (Tcl_CmdProc*)test_exec_printf      },
     { "sqlite4_exec_hex",              (Tcl_CmdProc*)test_exec_hex         },
     { "sqlite4_exec",                  (Tcl_CmdProc*)test_exec             },
     { "sqlite4_exec_nr",               (Tcl_CmdProc*)test_exec_nr          },
#ifndef SQLITE_OMIT_GET_TABLE
     { "sqlite4_get_table_printf",      (Tcl_CmdProc*)test_get_table_printf },
#endif
     { "sqlite4_close",                 (Tcl_CmdProc*)sqlite_test_close     },
     { "sqlite4_create_function",       (Tcl_CmdProc*)test_create_function  },
     { "sqlite4_create_aggregate",      (Tcl_CmdProc*)test_create_aggregate },
     { "sqlite_register_test_function", (Tcl_CmdProc*)test_register_func    },
     { "sqlite_abort",                  (Tcl_CmdProc*)sqlite_abort          },
     { "sqlite_bind",                   (Tcl_CmdProc*)test_bind             },
     { "breakpoint",                    (Tcl_CmdProc*)test_breakpoint       },







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







<
<
<







563
564
565
566
567
568
569

































































570
571
572
573
574
575
576
....
4848
4849
4850
4851
4852
4853
4854



4855
4856
4857
4858
4859
4860
4861
  if( n>sizeof(zStr) ) n = sizeof(zStr);
  sqlite4_snprintf(sizeof(zStr), zStr, "abcdefghijklmnopqrstuvwxyz");
  sqlite4_snprintf(n, zStr, zFormat, a1);
  Tcl_AppendResult(interp, zStr, 0);
  return TCL_OK;
}




































































/*
** Usage:  sqlite4_last_insert_rowid DB
**
** Returns the integer ROWID of the most recent insert.
*/
................................................................................
     { "sqlite4_mprintf_n_test",        (Tcl_CmdProc*)test_mprintf_n        },
     { "sqlite4_snprintf_int",          (Tcl_CmdProc*)test_snprintf_int     },
     { "sqlite4_last_insert_rowid",     (Tcl_CmdProc*)test_last_rowid       },
     { "sqlite4_exec_printf",           (Tcl_CmdProc*)test_exec_printf      },
     { "sqlite4_exec_hex",              (Tcl_CmdProc*)test_exec_hex         },
     { "sqlite4_exec",                  (Tcl_CmdProc*)test_exec             },
     { "sqlite4_exec_nr",               (Tcl_CmdProc*)test_exec_nr          },



     { "sqlite4_close",                 (Tcl_CmdProc*)sqlite_test_close     },
     { "sqlite4_create_function",       (Tcl_CmdProc*)test_create_function  },
     { "sqlite4_create_aggregate",      (Tcl_CmdProc*)test_create_aggregate },
     { "sqlite_register_test_function", (Tcl_CmdProc*)test_register_func    },
     { "sqlite_abort",                  (Tcl_CmdProc*)sqlite_abort          },
     { "sqlite_bind",                   (Tcl_CmdProc*)test_bind             },
     { "breakpoint",                    (Tcl_CmdProc*)test_breakpoint       },