/ Check-in [97a9604d]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

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

Overview
Comment:Merge latest trunk changes into this branch.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | reuse-schema
Files: files | file ages | folders
SHA3-256: 97a9604d85cf5044e8109e533d4682b25bfe6a110f403ebd0fdef03880059f37
User & Date: dan 2019-03-04 07:25:38
Wiki:reuse-schema
Context
2019-03-20
16:03
Merge latest trunk changes into this branch. check-in: 4cd20ca6 user: dan tags: reuse-schema
2019-03-04
07:25
Merge latest trunk changes into this branch. check-in: 97a9604d user: dan tags: reuse-schema
07:15
Fix a problem preventing compilation with SQLITE_OMIT_UTF16. check-in: 906d1fd8 user: dan tags: trunk
2019-02-26
16:36
Update doc/shared_schema.md to describe the shell tool ".shared-schema" dot-command. check-in: 0ce2092a user: dan tags: reuse-schema
Changes
Hide Diffs Side-by-Side Diffs Show Whitespace Changes Patch

Changes to Makefile.in.

  1422   1422   	$(INSTALL) -d $(DESTDIR)$(includedir)
  1423   1423   	$(INSTALL) -m 0644 sqlite3.h $(DESTDIR)$(includedir)
  1424   1424   	$(INSTALL) -m 0644 $(TOP)/src/sqlite3ext.h $(DESTDIR)$(includedir)
  1425   1425   	$(INSTALL) -d $(DESTDIR)$(pkgconfigdir)
  1426   1426   	$(INSTALL) -m 0644 sqlite3.pc $(DESTDIR)$(pkgconfigdir)
  1427   1427   
  1428   1428   pkgIndex.tcl:
  1429         -	echo 'package ifneeded sqlite3 $(RELEASE) [list load $(TCLLIBDIR)/libtclsqlite3$(SHLIB_SUFFIX) sqlite3]' > $@
         1429  +	echo 'package ifneeded sqlite3 $(RELEASE) [list load [file join $$dir libtclsqlite3[info sharedlibextension]] sqlite3]' > $@
  1430   1430   tcl_install:	lib_install libtclsqlite3.la pkgIndex.tcl
  1431   1431   	$(INSTALL) -d $(DESTDIR)$(TCLLIBDIR)
  1432   1432   	$(LTINSTALL) libtclsqlite3.la $(DESTDIR)$(TCLLIBDIR)
  1433   1433   	rm -f $(DESTDIR)$(TCLLIBDIR)/libtclsqlite3.la $(DESTDIR)$(TCLLIBDIR)/libtclsqlite3.a
  1434   1434   	$(INSTALL) -m 0644 pkgIndex.tcl $(DESTDIR)$(TCLLIBDIR)
  1435   1435   
  1436   1436   clean:

Changes to ext/fts3/README.tokenizers.

    48     48     returned. If only one argument is passed, a pointer to the tokenizer
    49     49     implementation currently registered as <tokenizer-name> is returned,
    50     50     encoded as a blob. Or, if no such tokenizer exists, an SQL exception
    51     51     (error) is raised.
    52     52   
    53     53     SECURITY: If the fts3 extension is used in an environment where potentially
    54     54       malicious users may execute arbitrary SQL (i.e. gears), they should be
    55         -    prevented from invoking the fts3_tokenizer() function, possibly using the
    56         -    authorisation callback.
           55  +    prevented from invoking the fts3_tokenizer() function.  The
           56  +    fts3_tokenizer() function is disabled by default. It is only enabled
           57  +    by SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER. Do not enable it in
           58  +    security sensitive environments.
    57     59   
    58     60     See "Sample code" below for an example of calling the fts3_tokenizer()
    59     61     function from C code.
    60     62   
    61     63   3. ICU Library Tokenizers
    62     64   
    63     65     If this extension is compiled with the SQLITE_ENABLE_ICU pre-processor 

Changes to ext/fts3/fts3_snippet.c.

   425    425   
   426    426     for(i=0; i<pIter->nPhrase; i++){
   427    427       SnippetPhrase *pPhrase = &pIter->aPhrase[i];
   428    428       if( pPhrase->pTail ){
   429    429         char *pCsr = pPhrase->pTail;
   430    430         int iCsr = pPhrase->iTail;
   431    431   
   432         -      while( iCsr<(iStart+pIter->nSnippet) ){
          432  +      while( iCsr<(iStart+pIter->nSnippet) && iCsr>=iStart ){
   433    433           int j;
   434    434           u64 mPhrase = (u64)1 << i;
   435    435           u64 mPos = (u64)1 << (iCsr - iStart);
   436    436           assert( iCsr>=iStart && (iCsr - iStart)<=64 );
   437    437           assert( i>=0 && i<=64 );
   438    438           if( (mCover|mCovered)&mPhrase ){
   439    439             iScore++;

Changes to ext/fts3/fts3_tokenizer.c.

   102    102       if( !pPtr ){
   103    103         char *zErr = sqlite3_mprintf("unknown tokenizer: %s", zName);
   104    104         sqlite3_result_error(context, zErr, -1);
   105    105         sqlite3_free(zErr);
   106    106         return;
   107    107       }
   108    108     }
          109  +  if( fts3TokenizerEnabled(context) ){
   109    110     sqlite3_result_blob(context, (void *)&pPtr, sizeof(pPtr), SQLITE_TRANSIENT);
   110    111   }
          112  +}
   111    113   
   112    114   int sqlite3Fts3IsIdChar(char c){
   113    115     static const char isFtsIdChar[] = {
   114    116         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 0x */
   115    117         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 1x */
   116    118         0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 2x */
   117    119         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,  /* 3x */

Changes to ext/fts5/test/fts5aux.test.

   271    271   
   272    272   do_execsql_test 9.3 {
   273    273     SELECT rowid FROM t1('b:a AND b:b') ORDER BY rank;
   274    274   } {
   275    275     9 10
   276    276   }
   277    277   
          278  +#-------------------------------------------------------------------------
          279  +# Test that aux. functions may not be used in aggregate queries.
          280  +#
          281  +reset_db
          282  +do_execsql_test 10.0 {
          283  +  CREATE VIRTUAL TABLE t1 USING fts5(x, y, z);
          284  +  INSERT INTO t1 VALUES('a', 'one two', 1);
          285  +  INSERT INTO t1 VALUES('b', 'two three', 2);
          286  +  INSERT INTO t1 VALUES('c', 'three four', 1);
          287  +  INSERT INTO t1 VALUES('d', 'four five', 2);
          288  +  INSERT INTO t1 VALUES('e', 'five six', 1);
          289  +  INSERT INTO t1 VALUES('f', 'six seven', 2);
          290  +}
          291  +
          292  +proc firstcol {cmd} { $cmd xColumnText 0 }
          293  +sqlite3_fts5_create_function db firstcol firstcol
          294  +
          295  +do_execsql_test 10.1.1 {
          296  +  SELECT firstcol(t1) FROM t1
          297  +} {a b c d e f}
          298  +do_execsql_test 10.1.2 {
          299  +  SELECT group_concat(x, '.') FROM t1
          300  +} {a.b.c.d.e.f}
          301  +
          302  +do_catchsql_test 10.1.3 {
          303  +  SELECT group_concat(firstcol(t1), '.') FROM t1
          304  +} {1 {unable to use function firstcol in the requested context}}
   278    305   
          306  +do_catchsql_test 10.1.4 {
          307  +  SELECT group_concat(firstcol(t1), '.') FROM t1 GROUP BY rowid
          308  +} {1 {unable to use function firstcol in the requested context}}
   279    309   
   280    310   finish_test
          311  +

Changes to ext/misc/fileio.c.

   148    148     db = sqlite3_context_db_handle(ctx);
   149    149     mxBlob = sqlite3_limit(db, SQLITE_LIMIT_LENGTH, -1);
   150    150     if( nIn>mxBlob ){
   151    151       sqlite3_result_error_code(ctx, SQLITE_TOOBIG);
   152    152       fclose(in);
   153    153       return;
   154    154     }
   155         -  pBuf = sqlite3_malloc64( nIn );
          155  +  pBuf = sqlite3_malloc64( nIn ? nIn : 1 );
   156    156     if( pBuf==0 ){
   157    157       sqlite3_result_error_nomem(ctx);
   158    158       fclose(in);
   159    159       return;
   160    160     }
   161         -  if( 1==fread(pBuf, nIn, 1, in) ){
          161  +  if( nIn==fread(pBuf, 1, nIn, in) ){
   162    162       sqlite3_result_blob64(ctx, pBuf, nIn, sqlite3_free);
   163    163     }else{
   164    164       sqlite3_result_error_code(ctx, SQLITE_IOERR);
   165    165       sqlite3_free(pBuf);
   166    166     }
   167    167     fclose(in);
   168    168   }

Changes to ext/misc/fossildelta.c.

     6      6   **
     7      7   **    May you do good and not evil.
     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   ******************************************************************************
    12     12   **
    13         -** This SQLite extension implements the delta functions used by Fossil.
           13  +** This SQLite extension implements the delta functions used by the RBU
           14  +** extension. Three scalar functions and one table-valued function are
           15  +** implemented here:
           16  +**
           17  +**   delta_apply(X,D)     -- apply delta D to file X and return the result
           18  +**   delta_create(X,Y)    -- compute and return a delta that carries X into Y
           19  +**   delta_output_size(D) -- blob size in bytes output from applying delta D
           20  +**   delta_parse(D)       -- returns rows describing delta D
           21  +**
           22  +** The delta format is the Fossil delta format, described in a comment
           23  +** on the delete_create() function implementation below, and also at
           24  +**
           25  +**    https://www.fossil-scm.org/fossil/doc/trunk/www/delta_format.wiki
           26  +**
           27  +** This delta format is used by the RBU extension, which is the main
           28  +** reason that these routines are included in the extension library.
           29  +** RBU does not use this extension directly.  Rather, this extension is
           30  +** provided as a convenience to developers who want to analyze RBU files 
           31  +** that contain deltas.
    14     32   */
    15     33   #include <string.h>
    16     34   #include <assert.h>
    17     35   #include <stdlib.h>
    18     36   #include "sqlite3ext.h"
    19     37   SQLITE_EXTENSION_INIT1
    20     38   

Changes to ext/misc/percentile.c.

   104    104     int eType;
   105    105     double y;
   106    106     assert( argc==2 );
   107    107   
   108    108     /* Requirement 3:  P must be a number between 0 and 100 */
   109    109     eType = sqlite3_value_numeric_type(argv[1]);
   110    110     rPct = sqlite3_value_double(argv[1]);
   111         -  if( (eType!=SQLITE_INTEGER && eType!=SQLITE_FLOAT) ||
   112         -      ((rPct = sqlite3_value_double(argv[1]))<0.0 || rPct>100.0) ){
          111  +  if( (eType!=SQLITE_INTEGER && eType!=SQLITE_FLOAT)
          112  +   || rPct<0.0 || rPct>100.0 ){
   113    113       sqlite3_result_error(pCtx, "2nd argument to percentile() is not "
   114    114                            "a number between 0.0 and 100.0", -1);
   115    115       return;
   116    116     }
   117    117   
   118    118     /* Allocate the session context. */
   119    119     p = (Percentile*)sqlite3_aggregate_context(pCtx, sizeof(*p));

Changes to ext/session/sessionB.test.

   254    254   }
   255    255   
   256    256   # INSERT + DELETE 
   257    257   do_patchconcat_test 4.3.3 {
   258    258     INSERT INTO t2 VALUES('a', 'a', 'a', 'a');
   259    259   } {
   260    260     DELETE FROM t2 WHERE c = 'a';
   261         -} {
   262         -}
          261  +} {}
   263    262   
   264    263   # INSERT + UPDATE
   265    264   do_patchconcat_test 4.3.4 {
   266    265     INSERT INTO t2 VALUES('a', 'a', 'a', 'a');
   267    266   } {
   268    267     UPDATE t2 SET d = 'b' WHERE c='a';
   269    268   } {

Changes to src/btree.c.

  1417   1417     assert( pPage->nOverflow==0 );
  1418   1418     assert( sqlite3_mutex_held(pPage->pBt->mutex) );
  1419   1419     temp = 0;
  1420   1420     src = data = pPage->aData;
  1421   1421     hdr = pPage->hdrOffset;
  1422   1422     cellOffset = pPage->cellOffset;
  1423   1423     nCell = pPage->nCell;
  1424         -  assert( nCell==get2byte(&data[hdr+3]) );
         1424  +  assert( nCell==get2byte(&data[hdr+3]) || CORRUPT_DB );
  1425   1425     iCellFirst = cellOffset + 2*nCell;
  1426   1426     usableSize = pPage->pBt->usableSize;
  1427   1427   
  1428   1428     /* This block handles pages with two or fewer free blocks and nMaxFrag
  1429   1429     ** or fewer fragmented bytes. In this case it is faster to move the
  1430   1430     ** two (or one) blocks of cells using memmove() and add the required
  1431   1431     ** offsets to each pointer in the cell-pointer array than it is to 
................................................................................
  9612   9612   ** Check the integrity of the freelist or of an overflow page list.
  9613   9613   ** Verify that the number of pages on the list is N.
  9614   9614   */
  9615   9615   static void checkList(
  9616   9616     IntegrityCk *pCheck,  /* Integrity checking context */
  9617   9617     int isFreeList,       /* True for a freelist.  False for overflow page list */
  9618   9618     int iPage,            /* Page number for first page in the list */
  9619         -  int N                 /* Expected number of pages in the list */
         9619  +  u32 N                 /* Expected number of pages in the list */
  9620   9620   ){
  9621   9621     int i;
  9622         -  int expected = N;
         9622  +  u32 expected = N;
  9623   9623     int nErrAtStart = pCheck->nErr;
  9624   9624     while( iPage!=0 && pCheck->mxErr ){
  9625   9625       DbPage *pOvflPage;
  9626   9626       unsigned char *pOvflData;
  9627   9627       if( checkRef(pCheck, iPage) ) break;
  9628   9628       N--;
  9629   9629       if( sqlite3PagerGet(pCheck->pPager, (Pgno)iPage, &pOvflPage, 0) ){
................................................................................
  9874   9874         }
  9875   9875         maxKey = info.nKey;
  9876   9876         keyCanBeEqual = 0;     /* Only the first key on the page may ==maxKey */
  9877   9877       }
  9878   9878   
  9879   9879       /* Check the content overflow list */
  9880   9880       if( info.nPayload>info.nLocal ){
  9881         -      int nPage;       /* Number of pages on the overflow chain */
         9881  +      u32 nPage;       /* Number of pages on the overflow chain */
  9882   9882         Pgno pgnoOvfl;   /* First page of the overflow chain */
  9883   9883         assert( pc + info.nSize - 4 <= usableSize );
  9884   9884         nPage = (info.nPayload - info.nLocal + usableSize - 5)/(usableSize - 4);
  9885   9885         pgnoOvfl = get4byte(&pCell[info.nSize - 4]);
  9886   9886   #ifndef SQLITE_OMIT_AUTOVACUUM
  9887   9887         if( pBt->autoVacuum ){
  9888   9888           checkPtrmap(pCheck, pgnoOvfl, PTRMAP_OVERFLOW1, iPage);

Changes to src/func.c.

  1801   1801   ** Set the LIKEOPT flag on the 2-argument function with the given name.
  1802   1802   */
  1803   1803   static void setLikeOptFlag(sqlite3 *db, const char *zName, u8 flagVal){
  1804   1804     FuncDef *pDef;
  1805   1805     pDef = sqlite3FindFunction(db, zName, 2, SQLITE_UTF8, 0);
  1806   1806     if( ALWAYS(pDef) ){
  1807   1807       pDef->funcFlags |= flagVal;
         1808  +  }
         1809  +  pDef = sqlite3FindFunction(db, zName, 3, SQLITE_UTF8, 0);
         1810  +  if( pDef ){
         1811  +    pDef->funcFlags |= flagVal;
  1808   1812     }
  1809   1813   }
  1810   1814   
  1811   1815   /*
  1812   1816   ** Register the built-in LIKE and GLOB functions.  The caseSensitive
  1813   1817   ** parameter determines whether or not the LIKE operator is case
  1814   1818   ** sensitive.  GLOB is always case sensitive.

Changes to src/pager.c.

   833    833   **   * the database file is open,
   834    834   **   * there are no dirty pages in the cache, and
   835    835   **   * the desired page is not currently in the wal file.
   836    836   */
   837    837   int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno){
   838    838     if( pPager->fd->pMethods==0 ) return 0;
   839    839     if( sqlite3PCacheIsDirty(pPager->pPCache) ) return 0;
          840  +#ifdef SQLITE_HAS_CODEC
          841  +  if( pPager->xCodec!=0 ) return 0;
          842  +#endif
   840    843   #ifndef SQLITE_OMIT_WAL
   841    844     if( pPager->pWal ){
   842    845       u32 iRead = 0;
   843    846       int rc;
   844    847       rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iRead);
   845    848       return (rc==SQLITE_OK && iRead==0);
   846    849     }
................................................................................
  3782   3785       char *pNew = NULL;             /* New temp space */
  3783   3786       i64 nByte = 0;
  3784   3787   
  3785   3788       if( pPager->eState>PAGER_OPEN && isOpen(pPager->fd) ){
  3786   3789         rc = sqlite3OsFileSize(pPager->fd, &nByte);
  3787   3790       }
  3788   3791       if( rc==SQLITE_OK ){
  3789         -      pNew = (char *)sqlite3PageMalloc(pageSize);
  3790         -      if( !pNew ) rc = SQLITE_NOMEM_BKPT;
         3792  +      /* 8 bytes of zeroed overrun space is sufficient so that the b-tree
         3793  +      * cell header parser will never run off the end of the allocation */
         3794  +      pNew = (char *)sqlite3PageMalloc(pageSize+8);
         3795  +      if( !pNew ){
         3796  +        rc = SQLITE_NOMEM_BKPT;
         3797  +      }else{
         3798  +        memset(pNew+pageSize, 0, 8);
         3799  +      }
  3791   3800       }
  3792   3801   
  3793   3802       if( rc==SQLITE_OK ){
  3794   3803         pager_reset(pPager);
  3795   3804         rc = sqlite3PcacheSetPageSize(pPager->pPCache, pageSize);
  3796   3805       }
  3797   3806       if( rc==SQLITE_OK ){

Changes to src/select.c.

  5302   5302   
  5303   5303   /*
  5304   5304   ** Update the accumulator memory cells for an aggregate based on
  5305   5305   ** the current cursor position.
  5306   5306   **
  5307   5307   ** If regAcc is non-zero and there are no min() or max() aggregates
  5308   5308   ** in pAggInfo, then only populate the pAggInfo->nAccumulator accumulator
  5309         -** registers i register regAcc contains 0. The caller will take care
         5309  +** registers if register regAcc contains 0. The caller will take care
  5310   5310   ** of setting and clearing regAcc.
  5311   5311   */
  5312   5312   static void updateAccumulator(Parse *pParse, int regAcc, AggInfo *pAggInfo){
  5313   5313     Vdbe *v = pParse->pVdbe;
  5314   5314     int i;
  5315   5315     int regHit = 0;
  5316   5316     int addrHitTest = 0;

Changes to src/shell.c.in.

  2743   2743   #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
  2744   2744     sqlite3SelectTrace = savedSelectTrace;
  2745   2745   #endif
  2746   2746   #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
  2747   2747     sqlite3WhereTrace = savedWhereTrace;
  2748   2748   #endif
  2749   2749   }
         2750  +
         2751  +/* Name of the TEMP table that holds bind parameter values */
         2752  +#define BIND_PARAM_TABLE "$Parameters"
         2753  +
         2754  +/* Create the TEMP table used to store parameter bindings */
         2755  +static void bind_table_init(ShellState *p){
         2756  +  sqlite3_exec(p->db,
         2757  +    "CREATE TABLE IF NOT EXISTS temp.[" BIND_PARAM_TABLE "](\n"
         2758  +    "  key TEXT PRIMARY KEY,\n"
         2759  +    "  value ANY\n"
         2760  +    ") WITHOUT ROWID;",
         2761  +    0, 0, 0);
         2762  +}
         2763  +
         2764  +/*
         2765  +** Bind parameters on a prepared statement.
         2766  +**
         2767  +** Parameter bindings are taken from a TEMP table of the form:
         2768  +**
         2769  +**    CREATE TEMP TABLE "$Parameters"(key TEXT PRIMARY KEY, value)
         2770  +**    WITHOUT ROWID;
         2771  +**
         2772  +** No bindings occur if this table does not exist.  The special character '$'
         2773  +** is included in the table name to help prevent collisions with actual tables.
         2774  +** The table must be in the TEMP schema.
         2775  +*/
         2776  +static void bind_prepared_stmt(ShellState *pArg, sqlite3_stmt *pStmt){
         2777  +  int nVar;
         2778  +  int i;
         2779  +  int rc;
         2780  +  sqlite3_stmt *pQ = 0;
         2781  +
         2782  +  nVar = sqlite3_bind_parameter_count(pStmt);
         2783  +  if( nVar==0 ) return;  /* Nothing to do */
         2784  +  if( sqlite3_table_column_metadata(pArg->db, "TEMP", BIND_PARAM_TABLE,
         2785  +                                    "key", 0, 0, 0, 0, 0)!=SQLITE_OK ){
         2786  +    return; /* Parameter table does not exist */
         2787  +  }
         2788  +  rc = sqlite3_prepare_v2(pArg->db,
         2789  +          "SELECT value FROM temp.\"" BIND_PARAM_TABLE "\""
         2790  +          " WHERE key=?1", -1, &pQ, 0);
         2791  +  if( rc || pQ==0 ) return;
         2792  +  for(i=1; i<=nVar; i++){
         2793  +    char zNum[30];
         2794  +    const char *zVar = sqlite3_bind_parameter_name(pStmt, i);
         2795  +    if( zVar==0 ){
         2796  +      sqlite3_snprintf(sizeof(zNum),zNum,"?%d",i);
         2797  +      zVar = zNum;
         2798  +    }
         2799  +    sqlite3_bind_text(pQ, 1, zVar, -1, SQLITE_STATIC);
         2800  +    if( sqlite3_step(pQ)==SQLITE_ROW ){
         2801  +      sqlite3_bind_value(pStmt, i, sqlite3_column_value(pQ, 0));
         2802  +    }else{
         2803  +      sqlite3_bind_null(pStmt, i);
         2804  +    }
         2805  +    sqlite3_reset(pQ);
         2806  +  }
         2807  +  sqlite3_finalize(pQ);
         2808  +}
  2750   2809   
  2751   2810   /*
  2752   2811   ** Run a prepared statement
  2753   2812   */
  2754   2813   static void exec_prepared_stmt(
  2755   2814     ShellState *pArg,                                /* Pointer to ShellState */
  2756   2815     sqlite3_stmt *pStmt                              /* Statment to run */
................................................................................
  3388   3447           /* If the shell is currently in ".explain" mode, gather the extra
  3389   3448           ** data required to add indents to the output.*/
  3390   3449           if( pArg->cMode==MODE_Explain ){
  3391   3450             explain_data_prepare(pArg, pStmt);
  3392   3451           }
  3393   3452         }
  3394   3453   
         3454  +      bind_prepared_stmt(pArg, pStmt);
  3395   3455         exec_prepared_stmt(pArg, pStmt);
  3396   3456         explain_data_delete(pArg);
  3397   3457         eqp_render(pArg);
  3398   3458   
  3399   3459         /* print usage stats if stats on */
  3400   3460         if( pArg && pArg->statsOn ){
  3401   3461           display_stats(db, pArg, 0);
................................................................................
  3819   3879     "        --maxsize N     Maximum size for --hexdb or --deserialized database",
  3820   3880   #endif
  3821   3881     "        --new           Initialize FILE to an empty database",
  3822   3882     "        --readonly      Open FILE readonly",
  3823   3883     "        --zip           FILE is a ZIP archive",
  3824   3884     ".output ?FILE?           Send output to FILE or stdout if FILE is omitted",
  3825   3885     "     If FILE begins with '|' then open it as a pipe.",
         3886  +  ".parameter CMD ...       Manage SQL parameter bindings",
         3887  +  "   clear                   Erase all bindings",
         3888  +  "   init                    Initialize the TEMP table that holds bindings",
         3889  +  "   list                    List the current parameter bindings",
         3890  +  "   set PARAMETER VALUE     Given SQL parameter PARAMETER a value of VALUE",
         3891  +  "                           PARAMETER should start with '$', ':', '@', or '?'",
         3892  +  "   unset PARAMETER         Remove PARAMETER from the binding table",
  3826   3893     ".print STRING...         Print literal STRING",
  3827   3894   #ifndef SQLITE_OMIT_PROGRESS_CALLBACK
  3828   3895     ".progress N              Invoke progress handler after every N opcodes",
  3829   3896     "   --limit N                 Interrupt after N progress callbacks",
  3830   3897     "   --once                    Do no more than one progress interrupt",
  3831   3898     "   --quiet|-q                No output except at interrupts",
  3832   3899     "   --reset                   Reset the count for each input and interrupt",
................................................................................
  7288   7355           p->out = stdout;
  7289   7356           rc = 1;
  7290   7357         } else {
  7291   7358           sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
  7292   7359         }
  7293   7360       }
  7294   7361     }else
         7362  +
         7363  +  if( c=='p' && n>=3 && strncmp(azArg[0], "parameter", n)==0 ){
         7364  +    open_db(p,0);
         7365  +    if( nArg<=1 ) goto parameter_syntax_error;
         7366  +
         7367  +    /* .parameter clear
         7368  +    ** Clear all bind parameters by dropping the TEMP table that holds them.
         7369  +    */
         7370  +    if( nArg==2 && strcmp(azArg[1],"clear")==0 ){
         7371  +      sqlite3_exec(p->db, "DROP TABLE IF EXISTS temp.[" BIND_PARAM_TABLE "];",
         7372  +                   0, 0, 0);
         7373  +    }else
         7374  +
         7375  +    /* .parameter list
         7376  +    ** List all bind parameters.
         7377  +    */
         7378  +    if( nArg==2 && strcmp(azArg[1],"list")==0 ){
         7379  +      sqlite3_stmt *pStmt = 0;
         7380  +      int rx;
         7381  +      int len = 0;
         7382  +      rx = sqlite3_prepare_v2(p->db,
         7383  +             "SELECT max(length(key)) "
         7384  +             "FROM temp.[" BIND_PARAM_TABLE "];", -1, &pStmt, 0);
         7385  +      if( rx==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
         7386  +        len = sqlite3_column_int(pStmt, 0);
         7387  +        if( len>40 ) len = 40;
         7388  +      }
         7389  +      sqlite3_finalize(pStmt);
         7390  +      pStmt = 0;
         7391  +      if( len ){
         7392  +        rx = sqlite3_prepare_v2(p->db,
         7393  +             "SELECT key, quote(value) "
         7394  +             "FROM temp.[" BIND_PARAM_TABLE "];", -1, &pStmt, 0);
         7395  +        while( sqlite3_step(pStmt)==SQLITE_ROW ){
         7396  +          utf8_printf(p->out, "%-*s %s\n", len, sqlite3_column_text(pStmt,0),
         7397  +                      sqlite3_column_text(pStmt,1));
         7398  +        }
         7399  +        sqlite3_finalize(pStmt);
         7400  +      }
         7401  +    }else
         7402  +
         7403  +    /* .parameter init
         7404  +    ** Make sure the TEMP table used to hold bind parameters exists.
         7405  +    ** Create it if necessary.
         7406  +    */
         7407  +    if( nArg==2 && strcmp(azArg[1],"init")==0 ){
         7408  +      bind_table_init(p);
         7409  +    }else
         7410  +
         7411  +    /* .parameter set NAME VALUE
         7412  +    ** Set or reset a bind parameter.  NAME should be the full parameter
         7413  +    ** name exactly as it appears in the query.  (ex: $abc, @def).  The
         7414  +    ** VALUE can be in either SQL literal notation, or if not it will be
         7415  +    ** understood to be a text string.
         7416  +    */
         7417  +    if( nArg==4 && strcmp(azArg[1],"set")==0 ){
         7418  +      int rx;
         7419  +      char *zSql;
         7420  +      sqlite3_stmt *pStmt;
         7421  +      const char *zKey = azArg[2];
         7422  +      const char *zValue = azArg[3];
         7423  +      bind_table_init(p);
         7424  +      zSql = sqlite3_mprintf(
         7425  +                  "REPLACE INTO temp.[" BIND_PARAM_TABLE "](key,value)"
         7426  +                  "VALUES(%Q,%s);", zKey, zValue);
         7427  +      if( zSql==0 ) shell_out_of_memory();
         7428  +      pStmt = 0;
         7429  +      rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
         7430  +      sqlite3_free(zSql);
         7431  +      if( rx!=SQLITE_OK ){
         7432  +        sqlite3_finalize(pStmt);
         7433  +        pStmt = 0;
         7434  +        zSql = sqlite3_mprintf(
         7435  +                   "REPLACE INTO temp.[" BIND_PARAM_TABLE "](key,value)"
         7436  +                   "VALUES(%Q,%Q);", zKey, zValue);
         7437  +        if( zSql==0 ) shell_out_of_memory();
         7438  +        rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
         7439  +        sqlite3_free(zSql);
         7440  +        if( rx!=SQLITE_OK ){
         7441  +          utf8_printf(p->out, "Error: %s\n", sqlite3_errmsg(p->db));
         7442  +          sqlite3_finalize(pStmt);
         7443  +          pStmt = 0;
         7444  +          rc = 1;
         7445  +        }
         7446  +      }
         7447  +      sqlite3_step(pStmt);
         7448  +      sqlite3_finalize(pStmt);
         7449  +    }else
         7450  +
         7451  +    /* .parameter unset NAME
         7452  +    ** Remove the NAME binding from the parameter binding table, if it
         7453  +    ** exists.
         7454  +    */
         7455  +    if( nArg==3 && strcmp(azArg[1],"unset")==0 ){
         7456  +      char *zSql = sqlite3_mprintf(
         7457  +          "DELETE FROM temp.[" BIND_PARAM_TABLE "] WHERE key=%Q", azArg[2]);
         7458  +      if( zSql==0 ) shell_out_of_memory();
         7459  +      sqlite3_exec(p->db, zSql, 0, 0, 0);
         7460  +      sqlite3_free(zSql);
         7461  +    }else
         7462  +    /* If no command name matches, show a syntax error */
         7463  +    parameter_syntax_error:
         7464  +    showHelp(p->out, "parameter");
         7465  +  }else
  7295   7466   
  7296   7467     if( c=='p' && n>=3 && strncmp(azArg[0], "print", n)==0 ){
  7297   7468       int i;
  7298   7469       for(i=1; i<nArg; i++){
  7299   7470         if( i>1 ) raw_printf(p->out, " ");
  7300   7471         utf8_printf(p->out, "%s", azArg[i]);
  7301   7472       }

Changes to src/sqlite.h.in.

  2084   2084   ** The second parameter is a pointer to an integer into which
  2085   2085   ** is written 0 or 1 to indicate whether triggers are disabled or enabled
  2086   2086   ** following this call.  The second parameter may be a NULL pointer, in
  2087   2087   ** which case the trigger setting is not reported back. </dd>
  2088   2088   **
  2089   2089   ** [[SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER]]
  2090   2090   ** <dt>SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER</dt>
  2091         -** <dd> ^This option is used to enable or disable the two-argument
  2092         -** version of the [fts3_tokenizer()] function which is part of the
         2091  +** <dd> ^This option is used to enable or disable the
         2092  +** [fts3_tokenizer()] function which is part of the
  2093   2093   ** [FTS3] full-text search engine extension.
  2094   2094   ** There should be two additional arguments.
  2095   2095   ** The first argument is an integer which is 0 to disable fts3_tokenizer() or
  2096   2096   ** positive to enable fts3_tokenizer() or negative to leave the setting
  2097   2097   ** unchanged.
  2098   2098   ** The second parameter is a pointer to an integer into which
  2099   2099   ** is written 0 or 1 to indicate whether fts3_tokenizer is disabled or enabled

Changes to src/tclsqlite.c.

    89     89   
    90     90   /* Forward declaration */
    91     91   typedef struct SqliteDb SqliteDb;
    92     92   
    93     93   /*
    94     94   ** New SQL functions can be created as TCL scripts.  Each such function
    95     95   ** is described by an instance of the following structure.
           96  +**
           97  +** Variable eType may be set to SQLITE_INTEGER, SQLITE_FLOAT, SQLITE_TEXT,
           98  +** SQLITE_BLOB or SQLITE_NULL. If it is SQLITE_NULL, then the implementation
           99  +** attempts to determine the type of the result based on the Tcl object.
          100  +** If it is SQLITE_TEXT or SQLITE_BLOB, then a text (sqlite3_result_text())
          101  +** or blob (sqlite3_result_blob()) is returned. If it is SQLITE_INTEGER
          102  +** or SQLITE_FLOAT, then an attempt is made to return an integer or float
          103  +** value, falling back to float and then text if this is not possible.
    96    104   */
    97    105   typedef struct SqlFunc SqlFunc;
    98    106   struct SqlFunc {
    99    107     Tcl_Interp *interp;   /* The TCL interpret to execute the function */
   100    108     Tcl_Obj *pScript;     /* The Tcl_Obj representation of the script */
   101    109     SqliteDb *pDb;        /* Database connection that owns this function */
   102    110     int useEvalObjv;      /* True if it is safe to use Tcl_EvalObjv */
          111  +  int eType;            /* Type of value to return */
   103    112     char *zName;          /* Name of this function */
   104    113     SqlFunc *pNext;       /* Next function on the list of them all */
   105    114   };
   106    115   
   107    116   /*
   108    117   ** New collation sequences function can be created as TCL scripts.  Each such
   109    118   ** function is described by an instance of the following structure.
................................................................................
   146    155     Tcl_Interp *interp;        /* The interpreter used for this database */
   147    156     char *zBusy;               /* The busy callback routine */
   148    157     char *zCommit;             /* The commit hook callback routine */
   149    158     char *zTrace;              /* The trace callback routine */
   150    159     char *zTraceV2;            /* The trace_v2 callback routine */
   151    160     char *zProfile;            /* The profile callback routine */
   152    161     char *zProgress;           /* The progress callback routine */
          162  +  char *zBindFallback;       /* Callback to invoke on a binding miss */
   153    163     char *zAuth;               /* The authorization callback routine */
   154    164     int disableAuth;           /* Disable the authorizer if it exists */
   155    165     char *zNull;               /* Text to substitute for an SQL NULL value */
   156    166     SqlFunc *pFunc;            /* List of SQL functions */
   157    167     Tcl_Obj *pUpdateHook;      /* Update hook script (if any) */
   158    168     Tcl_Obj *pPreUpdateHook;   /* Pre-update hook script (if any) */
   159    169     Tcl_Obj *pRollbackHook;    /* Rollback hook script (if any) */
................................................................................
   536    546     }
   537    547     if( pDb->zTraceV2 ){
   538    548       Tcl_Free(pDb->zTraceV2);
   539    549     }
   540    550     if( pDb->zProfile ){
   541    551       Tcl_Free(pDb->zProfile);
   542    552     }
          553  +  if( pDb->zBindFallback ){
          554  +    Tcl_Free(pDb->zBindFallback);
          555  +  }
   543    556     if( pDb->zAuth ){
   544    557       Tcl_Free(pDb->zAuth);
   545    558     }
   546    559     if( pDb->zNull ){
   547    560       Tcl_Free(pDb->zNull);
   548    561     }
   549    562     if( pDb->pUpdateHook ){
................................................................................
   991   1004       sqlite3_result_error(context, Tcl_GetStringResult(p->interp), -1);
   992   1005     }else{
   993   1006       Tcl_Obj *pVar = Tcl_GetObjResult(p->interp);
   994   1007       int n;
   995   1008       u8 *data;
   996   1009       const char *zType = (pVar->typePtr ? pVar->typePtr->name : "");
   997   1010       char c = zType[0];
         1011  +    int eType = p->eType;
         1012  +
         1013  +    if( eType==SQLITE_NULL ){
   998   1014       if( c=='b' && strcmp(zType,"bytearray")==0 && pVar->bytes==0 ){
   999   1015         /* Only return a BLOB type if the Tcl variable is a bytearray and
  1000   1016         ** has no string representation. */
         1017  +        eType = SQLITE_BLOB;
         1018  +      }else if( (c=='b' && strcmp(zType,"boolean")==0)
         1019  +             || (c=='w' && strcmp(zType,"wideInt")==0)
         1020  +             || (c=='i' && strcmp(zType,"int")==0) 
         1021  +      ){
         1022  +        eType = SQLITE_INTEGER;
         1023  +      }else if( c=='d' && strcmp(zType,"double")==0 ){
         1024  +        eType = SQLITE_FLOAT;
         1025  +      }else{
         1026  +        eType = SQLITE_TEXT;
         1027  +      }
         1028  +    }
         1029  +
         1030  +    switch( eType ){
         1031  +      case SQLITE_BLOB: {
  1001   1032         data = Tcl_GetByteArrayFromObj(pVar, &n);
  1002   1033         sqlite3_result_blob(context, data, n, SQLITE_TRANSIENT);
  1003         -    }else if( c=='b' && strcmp(zType,"boolean")==0 ){
  1004         -      Tcl_GetIntFromObj(0, pVar, &n);
  1005         -      sqlite3_result_int(context, n);
  1006         -    }else if( c=='d' && strcmp(zType,"double")==0 ){
         1034  +        break;
         1035  +      }
         1036  +      case SQLITE_INTEGER: {
         1037  +        Tcl_WideInt v;
         1038  +        if( TCL_OK==Tcl_GetWideIntFromObj(0, pVar, &v) ){
         1039  +          sqlite3_result_int64(context, v);
         1040  +          break;
         1041  +        }
         1042  +        /* fall-through */
         1043  +      }
         1044  +      case SQLITE_FLOAT: {
  1007   1045         double r;
  1008         -      Tcl_GetDoubleFromObj(0, pVar, &r);
         1046  +        if( TCL_OK==Tcl_GetDoubleFromObj(0, pVar, &r) ){
  1009   1047         sqlite3_result_double(context, r);
  1010         -    }else if( (c=='w' && strcmp(zType,"wideInt")==0) ||
  1011         -          (c=='i' && strcmp(zType,"int")==0) ){
  1012         -      Tcl_WideInt v;
  1013         -      Tcl_GetWideIntFromObj(0, pVar, &v);
  1014         -      sqlite3_result_int64(context, v);
  1015         -    }else{
         1048  +          break;
         1049  +        }
         1050  +        /* fall-through */
         1051  +      }
         1052  +      default: {
  1016   1053         data = (unsigned char *)Tcl_GetStringFromObj(pVar, &n);
  1017   1054         sqlite3_result_text(context, (char *)data, n, SQLITE_TRANSIENT);
         1055  +        break;
  1018   1056       }
  1019   1057     }
         1058  +
         1059  +  }
  1020   1060   }
  1021   1061   
  1022   1062   #ifndef SQLITE_OMIT_AUTHORIZATION
  1023   1063   /*
  1024   1064   ** This is the authentication function.  It appends the authentication
  1025   1065   ** type code and the two arguments to zCmd[] then invokes the result
  1026   1066   ** on the interpreter.  The reply is examined to determine if the
................................................................................
  1261   1301     sqlite3_stmt *pStmt = 0;        /* Prepared statement object */
  1262   1302     SqlPreparedStmt *pPreStmt;      /* Pointer to cached statement */
  1263   1303     int nSql;                       /* Length of zSql in bytes */
  1264   1304     int nVar = 0;                   /* Number of variables in statement */
  1265   1305     int iParm = 0;                  /* Next free entry in apParm */
  1266   1306     char c;
  1267   1307     int i;
         1308  +  int needResultReset = 0;        /* Need to invoke Tcl_ResetResult() */
         1309  +  int rc = SQLITE_OK;             /* Value to return */
  1268   1310     Tcl_Interp *interp = pDb->interp;
  1269   1311   
  1270   1312     *ppPreStmt = 0;
  1271   1313   
  1272   1314     /* Trim spaces from the start of zSql and calculate the remaining length. */
  1273   1315     while( (c = zSql[0])==' ' || c=='\t' || c=='\r' || c=='\n' ){ zSql++; }
  1274   1316     nSql = strlen30(zSql);
................................................................................
  1348   1390     assert( 0==memcmp(pPreStmt->zSql, zSql, pPreStmt->nSql) );
  1349   1391   
  1350   1392     /* Bind values to parameters that begin with $ or : */
  1351   1393     for(i=1; i<=nVar; i++){
  1352   1394       const char *zVar = sqlite3_bind_parameter_name(pStmt, i);
  1353   1395       if( zVar!=0 && (zVar[0]=='$' || zVar[0]==':' || zVar[0]=='@') ){
  1354   1396         Tcl_Obj *pVar = Tcl_GetVar2Ex(interp, &zVar[1], 0, 0);
         1397  +      if( pVar==0 && pDb->zBindFallback!=0 ){
         1398  +        Tcl_Obj *pCmd;
         1399  +        int rx;
         1400  +        pCmd = Tcl_NewStringObj(pDb->zBindFallback, -1);
         1401  +        Tcl_IncrRefCount(pCmd);
         1402  +        Tcl_ListObjAppendElement(interp, pCmd, Tcl_NewStringObj(zVar,-1));
         1403  +        if( needResultReset ) Tcl_ResetResult(interp);
         1404  +        needResultReset = 1;
         1405  +        rx = Tcl_EvalObjEx(interp, pCmd, TCL_EVAL_DIRECT);
         1406  +        Tcl_DecrRefCount(pCmd);
         1407  +        if( rx==TCL_OK ){
         1408  +          pVar = Tcl_GetObjResult(interp);
         1409  +        }else if( rx==TCL_ERROR ){
         1410  +          rc = TCL_ERROR;
         1411  +          break;
         1412  +        }else{
         1413  +          pVar = 0;
         1414  +        }
         1415  +      }
  1355   1416         if( pVar ){
  1356   1417           int n;
  1357   1418           u8 *data;
  1358   1419           const char *zType = (pVar->typePtr ? pVar->typePtr->name : "");
  1359   1420           c = zType[0];
  1360   1421           if( zVar[0]=='@' ||
  1361   1422              (c=='b' && strcmp(zType,"bytearray")==0 && pVar->bytes==0) ){
................................................................................
  1383   1444             sqlite3_bind_text(pStmt, i, (char *)data, n, SQLITE_STATIC);
  1384   1445             Tcl_IncrRefCount(pVar);
  1385   1446             pPreStmt->apParm[iParm++] = pVar;
  1386   1447           }
  1387   1448         }else{
  1388   1449           sqlite3_bind_null(pStmt, i);
  1389   1450         }
         1451  +      if( needResultReset ) Tcl_ResetResult(pDb->interp);
  1390   1452       }
  1391   1453     }
  1392   1454     pPreStmt->nParm = iParm;
  1393   1455     *ppPreStmt = pPreStmt;
         1456  +  if( needResultReset && rc==TCL_OK ) Tcl_ResetResult(pDb->interp);
  1394   1457   
  1395         -  return TCL_OK;
         1458  +  return rc;
  1396   1459   }
  1397   1460   
  1398   1461   /*
  1399   1462   ** Release a statement reference obtained by calling dbPrepareAndBind().
  1400   1463   ** There should be exactly one call to this function for each call to
  1401   1464   ** dbPrepareAndBind().
  1402   1465   **
................................................................................
  1847   1910     int objc,
  1848   1911     Tcl_Obj *const*objv
  1849   1912   ){
  1850   1913     SqliteDb *pDb = (SqliteDb*)cd;
  1851   1914     int choice;
  1852   1915     int rc = TCL_OK;
  1853   1916     static const char *DB_strs[] = {
  1854         -    "authorizer",             "backup",                "busy",
  1855         -    "cache",                  "changes",               "close",
  1856         -    "collate",                "collation_needed",      "commit_hook",
  1857         -    "complete",               "copy",                  "deserialize",
  1858         -    "enable_load_extension",  "errorcode",             "eval",
  1859         -    "exists",                 "function",              "incrblob",
  1860         -    "interrupt",              "last_insert_rowid",     "nullvalue",
  1861         -    "onecolumn",              "preupdate",             "profile",
  1862         -    "progress",               "rekey",                 "restore",
  1863         -    "rollback_hook",          "serialize",             "status",
  1864         -    "timeout",                "total_changes",         "trace",
  1865         -    "trace_v2",               "transaction",           "unlock_notify",
  1866         -    "update_hook",            "version",               "wal_hook",
  1867         -    0                        
         1917  +    "authorizer",             "backup",                "bind_fallback",
         1918  +    "busy",                   "cache",                 "changes",
         1919  +    "close",                  "collate",               "collation_needed",
         1920  +    "commit_hook",            "complete",              "copy",
         1921  +    "deserialize",            "enable_load_extension", "errorcode",
         1922  +    "eval",                   "exists",                "function",
         1923  +    "incrblob",               "interrupt",             "last_insert_rowid",
         1924  +    "nullvalue",              "onecolumn",             "preupdate",
         1925  +    "profile",                "progress",              "rekey",
         1926  +    "restore",                "rollback_hook",         "serialize",
         1927  +    "status",                 "timeout",               "total_changes",
         1928  +    "trace",                  "trace_v2",              "transaction",
         1929  +    "unlock_notify",          "update_hook",           "version",
         1930  +    "wal_hook",               0                        
  1868   1931     };
  1869   1932     enum DB_enum {
  1870         -    DB_AUTHORIZER,            DB_BACKUP,               DB_BUSY,
  1871         -    DB_CACHE,                 DB_CHANGES,              DB_CLOSE,
  1872         -    DB_COLLATE,               DB_COLLATION_NEEDED,     DB_COMMIT_HOOK,
  1873         -    DB_COMPLETE,              DB_COPY,                 DB_DESERIALIZE,
  1874         -    DB_ENABLE_LOAD_EXTENSION, DB_ERRORCODE,            DB_EVAL,
  1875         -    DB_EXISTS,                DB_FUNCTION,             DB_INCRBLOB,
  1876         -    DB_INTERRUPT,             DB_LAST_INSERT_ROWID,    DB_NULLVALUE,
  1877         -    DB_ONECOLUMN,             DB_PREUPDATE,            DB_PROFILE,
  1878         -    DB_PROGRESS,              DB_REKEY,                DB_RESTORE,
  1879         -    DB_ROLLBACK_HOOK,         DB_SERIALIZE,            DB_STATUS,
  1880         -    DB_TIMEOUT,               DB_TOTAL_CHANGES,        DB_TRACE,
  1881         -    DB_TRACE_V2,              DB_TRANSACTION,          DB_UNLOCK_NOTIFY,
  1882         -    DB_UPDATE_HOOK,           DB_VERSION,              DB_WAL_HOOK
         1933  +    DB_AUTHORIZER,            DB_BACKUP,               DB_BIND_FALLBACK,
         1934  +    DB_BUSY,                  DB_CACHE,                DB_CHANGES,
         1935  +    DB_CLOSE,                 DB_COLLATE,              DB_COLLATION_NEEDED,
         1936  +    DB_COMMIT_HOOK,           DB_COMPLETE,             DB_COPY,
         1937  +    DB_DESERIALIZE,           DB_ENABLE_LOAD_EXTENSION,DB_ERRORCODE,
         1938  +    DB_EVAL,                  DB_EXISTS,               DB_FUNCTION,
         1939  +    DB_INCRBLOB,              DB_INTERRUPT,            DB_LAST_INSERT_ROWID,
         1940  +    DB_NULLVALUE,             DB_ONECOLUMN,            DB_PREUPDATE,
         1941  +    DB_PROFILE,               DB_PROGRESS,             DB_REKEY,
         1942  +    DB_RESTORE,               DB_ROLLBACK_HOOK,        DB_SERIALIZE,
         1943  +    DB_STATUS,                DB_TIMEOUT,              DB_TOTAL_CHANGES,
         1944  +    DB_TRACE,                 DB_TRACE_V2,             DB_TRANSACTION,
         1945  +    DB_UNLOCK_NOTIFY,         DB_UPDATE_HOOK,          DB_VERSION,
         1946  +    DB_WAL_HOOK             
  1883   1947     };
  1884   1948     /* don't leave trailing commas on DB_enum, it confuses the AIX xlc compiler */
  1885   1949   
  1886   1950     if( objc<2 ){
  1887   1951       Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ...");
  1888   1952       return TCL_ERROR;
  1889   1953     }
................................................................................
  1996   2060         Tcl_AppendResult(interp, "backup failed: ",
  1997   2061              sqlite3_errmsg(pDest), (char*)0);
  1998   2062         rc = TCL_ERROR;
  1999   2063       }
  2000   2064       sqlite3_close(pDest);
  2001   2065       break;
  2002   2066     }
         2067  +
         2068  +  /*    $db bind_fallback ?CALLBACK?
         2069  +  **
         2070  +  ** When resolving bind parameters in an SQL statement, if the parameter
         2071  +  ** cannot be associated with a TCL variable then invoke CALLBACK with a
         2072  +  ** single argument that is the name of the parameter and use the return
         2073  +  ** value of the CALLBACK as the binding.  If CALLBACK returns something
         2074  +  ** other than TCL_OK or TCL_ERROR then bind a NULL.
         2075  +  **
         2076  +  ** If CALLBACK is an empty string, then revert to the default behavior 
         2077  +  ** which is to set the binding to NULL.
         2078  +  **
         2079  +  ** If CALLBACK returns an error, that causes the statement execution to
         2080  +  ** abort.  Hence, to configure a connection so that it throws an error
         2081  +  ** on an attempt to bind an unknown variable, do something like this:
         2082  +  **
         2083  +  **     proc bind_error {name} {error "no such variable: $name"}
         2084  +  **     db bind_fallback bind_error
         2085  +  */
         2086  +  case DB_BIND_FALLBACK: {
         2087  +    if( objc>3 ){
         2088  +      Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK?");
         2089  +      return TCL_ERROR;
         2090  +    }else if( objc==2 ){
         2091  +      if( pDb->zBindFallback ){
         2092  +        Tcl_AppendResult(interp, pDb->zBindFallback, (char*)0);
         2093  +      }
         2094  +    }else{
         2095  +      char *zCallback;
         2096  +      int len;
         2097  +      if( pDb->zBindFallback ){
         2098  +        Tcl_Free(pDb->zBindFallback);
         2099  +      }
         2100  +      zCallback = Tcl_GetStringFromObj(objv[2], &len);
         2101  +      if( zCallback && len>0 ){
         2102  +        pDb->zBindFallback = Tcl_Alloc( len + 1 );
         2103  +        memcpy(pDb->zBindFallback, zCallback, len+1);
         2104  +      }else{
         2105  +        pDb->zBindFallback = 0;
         2106  +      }
         2107  +    }
         2108  +    break;
         2109  +  }
  2003   2110   
  2004   2111     /*    $db busy ?CALLBACK?
  2005   2112     **
  2006   2113     ** Invoke the given callback if an SQL statement attempts to open
  2007   2114     ** a locked database file.
  2008   2115     */
  2009   2116     case DB_BUSY: {
................................................................................
  2642   2749     case DB_FUNCTION: {
  2643   2750       int flags = SQLITE_UTF8;
  2644   2751       SqlFunc *pFunc;
  2645   2752       Tcl_Obj *pScript;
  2646   2753       char *zName;
  2647   2754       int nArg = -1;
  2648   2755       int i;
         2756  +    int eType = SQLITE_NULL;
  2649   2757       if( objc<4 ){
  2650   2758         Tcl_WrongNumArgs(interp, 2, objv, "NAME ?SWITCHES? SCRIPT");
  2651   2759         return TCL_ERROR;
  2652   2760       }
  2653   2761       for(i=3; i<(objc-1); i++){
  2654   2762         const char *z = Tcl_GetString(objv[i]);
  2655   2763         int n = strlen30(z);
  2656         -      if( n>2 && strncmp(z, "-argcount",n)==0 ){
         2764  +      if( n>1 && strncmp(z, "-argcount",n)==0 ){
  2657   2765           if( i==(objc-2) ){
  2658   2766             Tcl_AppendResult(interp, "option requires an argument: ", z,(char*)0);
  2659   2767             return TCL_ERROR;
  2660   2768           }
  2661   2769           if( Tcl_GetIntFromObj(interp, objv[i+1], &nArg) ) return TCL_ERROR;
  2662   2770           if( nArg<0 ){
  2663   2771             Tcl_AppendResult(interp, "number of arguments must be non-negative",
  2664   2772                              (char*)0);
  2665   2773             return TCL_ERROR;
  2666   2774           }
  2667   2775           i++;
  2668   2776         }else
  2669         -      if( n>2 && strncmp(z, "-deterministic",n)==0 ){
         2777  +      if( n>1 && strncmp(z, "-deterministic",n)==0 ){
  2670   2778           flags |= SQLITE_DETERMINISTIC;
         2779  +      }else
         2780  +      if( n>1 && strncmp(z, "-returntype", n)==0 ){
         2781  +        const char *azType[] = {"integer", "real", "text", "blob", "any", 0};
         2782  +        assert( SQLITE_INTEGER==1 && SQLITE_FLOAT==2 && SQLITE_TEXT==3 );
         2783  +        assert( SQLITE_BLOB==4 && SQLITE_NULL==5 );
         2784  +        if( i==(objc-2) ){
         2785  +          Tcl_AppendResult(interp, "option requires an argument: ", z,(char*)0);
         2786  +          return TCL_ERROR;
         2787  +        }
         2788  +        i++;
         2789  +        if( Tcl_GetIndexFromObj(interp, objv[i], azType, "type", 0, &eType) ){
         2790  +          return TCL_ERROR;
         2791  +        }
         2792  +        eType++;
  2671   2793         }else{
  2672   2794           Tcl_AppendResult(interp, "bad option \"", z,
  2673         -            "\": must be -argcount or -deterministic", (char*)0
         2795  +            "\": must be -argcount, -deterministic or -returntype", (char*)0
  2674   2796           );
  2675   2797           return TCL_ERROR;
  2676   2798         }
  2677   2799       }
  2678   2800   
  2679   2801       pScript = objv[objc-1];
  2680   2802       zName = Tcl_GetStringFromObj(objv[2], 0);
................................................................................
  2682   2804       if( pFunc==0 ) return TCL_ERROR;
  2683   2805       if( pFunc->pScript ){
  2684   2806         Tcl_DecrRefCount(pFunc->pScript);
  2685   2807       }
  2686   2808       pFunc->pScript = pScript;
  2687   2809       Tcl_IncrRefCount(pScript);
  2688   2810       pFunc->useEvalObjv = safeToUseEvalObjv(interp, pScript);
         2811  +    pFunc->eType = eType;
  2689   2812       rc = sqlite3_create_function(pDb->db, zName, nArg, flags,
  2690   2813           pFunc, tclSqlFunc, 0, 0);
  2691   2814       if( rc!=SQLITE_OK ){
  2692   2815         rc = TCL_ERROR;
  2693   2816         Tcl_SetResult(interp, (char *)sqlite3_errmsg(pDb->db), TCL_VOLATILE);
  2694   2817       }
  2695   2818       break;

Changes to src/tokenize.c.

   556    556     int nErr = 0;                   /* Number of errors encountered */
   557    557     void *pEngine;                  /* The LEMON-generated LALR(1) parser */
   558    558     int n = 0;                      /* Length of the next token token */
   559    559     int tokenType;                  /* type of the next token */
   560    560     int lastTokenParsed = -1;       /* type of the previous token */
   561    561     sqlite3 *db = pParse->db;       /* The database connection */
   562    562     int mxSqlLen;                   /* Max length of an SQL string */
   563         -  VVA_ONLY( u8 startedWithOom = db->mallocFailed );
   564    563   #ifdef sqlite3Parser_ENGINEALWAYSONSTACK
   565    564     yyParser sEngine;    /* Space to hold the Lemon-generated Parser object */
   566    565   #endif
          566  +  VVA_ONLY( u8 startedWithOom = db->mallocFailed );
   567    567   
   568    568     assert( zSql!=0 );
   569    569     mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
   570    570     if( db->nVdbeActive==0 ){
   571    571       db->u1.isInterrupted = 0;
   572    572     }
   573    573     pParse->rc = SQLITE_OK;

Changes to src/vdbeapi.c.

  1140   1140     db = p->db;
  1141   1141     assert( db!=0 );
  1142   1142     n = sqlite3_column_count(pStmt);
  1143   1143     if( N<n && N>=0 ){
  1144   1144       N += useType*n;
  1145   1145       sqlite3_mutex_enter(db->mutex);
  1146   1146       assert( db->mallocFailed==0 );
         1147  +#ifndef SQLITE_OMIT_UTF16
  1147   1148       if( useUtf16 ){
  1148   1149         ret = sqlite3_value_text16((sqlite3_value*)&p->aColName[N]);
  1149         -    }else{
         1150  +    }else
         1151  +#endif
         1152  +    {
  1150   1153         ret = sqlite3_value_text((sqlite3_value*)&p->aColName[N]);
  1151   1154       }
  1152   1155       /* A malloc may have failed inside of the _text() call. If this
  1153   1156       ** is the case, clear the mallocFailed flag and return NULL.
  1154   1157       */
  1155   1158       if( db->mallocFailed ){
  1156   1159         sqlite3OomClear(db);

Changes to src/wherecode.c.

  1154   1154       x.iIdxCol = iIdxCol;
  1155   1155       x.pIdxExpr = aColExpr->a[iIdxCol].pExpr;
  1156   1156       sqlite3WalkExpr(&w, pWInfo->pWhere);
  1157   1157       sqlite3WalkExprList(&w, pWInfo->pOrderBy);
  1158   1158       sqlite3WalkExprList(&w, pWInfo->pResultSet);
  1159   1159     }
  1160   1160   }
         1161  +
         1162  +/*
         1163  +** The pTruth expression is always tree because it is the WHERE clause
         1164  +** a partial index that is driving a query loop.  Look through all of the
         1165  +** WHERE clause terms on the query, and if any of those terms must be
         1166  +** true because pTruth is true, then mark those WHERE clause terms as
         1167  +** coded.
         1168  +*/
         1169  +static void whereApplyPartialIndexConstraints(
         1170  +  Expr *pTruth,
         1171  +  int iTabCur,
         1172  +  WhereClause *pWC
         1173  +){
         1174  +  int i;
         1175  +  WhereTerm *pTerm;
         1176  +  while( pTruth->op==TK_AND ){
         1177  +    whereApplyPartialIndexConstraints(pTruth->pLeft, iTabCur, pWC);
         1178  +    pTruth = pTruth->pRight;
         1179  +  }
         1180  +  for(i=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
         1181  +    Expr *pExpr;
         1182  +    if( pTerm->wtFlags & TERM_CODED ) continue;
         1183  +    pExpr = pTerm->pExpr;
         1184  +    if( sqlite3ExprCompare(0, pExpr, pTruth, iTabCur)==0 ){
         1185  +      pTerm->wtFlags |= TERM_CODED;
         1186  +    }
         1187  +  }
         1188  +}
  1161   1189   
  1162   1190   /*
  1163   1191   ** Generate code for the start of the iLevel-th loop in the WHERE clause
  1164   1192   ** implementation described by pWInfo.
  1165   1193   */
  1166   1194   Bitmask sqlite3WhereCodeOneLoopStart(
  1167   1195     Parse *pParse,       /* Parsing context */
................................................................................
  1763   1791       ** OR clause, since the transformation will become invalid once we
  1764   1792       ** move forward to the next index.
  1765   1793       ** https://sqlite.org/src/info/4e8e4857d32d401f
  1766   1794       */
  1767   1795       if( pLevel->iLeftJoin==0 && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0 ){
  1768   1796         whereIndexExprTrans(pIdx, iCur, iIdxCur, pWInfo);
  1769   1797       }
         1798  +
         1799  +    /* If a partial index is driving the loop, try to eliminate WHERE clause
         1800  +    ** terms from the query that must be true due to the WHERE clause of
         1801  +    ** the partial index
         1802  +    */
         1803  +    if( pIdx->pPartIdxWhere ){
         1804  +      whereApplyPartialIndexConstraints(pIdx->pPartIdxWhere, iCur, pWC);
         1805  +    }
  1770   1806   
  1771   1807       /* Record the instruction used to terminate the loop. */
  1772   1808       if( pLoop->wsFlags & WHERE_ONEROW ){
  1773   1809         pLevel->op = OP_Noop;
  1774   1810       }else if( bRev ){
  1775   1811         pLevel->op = OP_Prev;
  1776   1812       }else{

Changes to test/dbfuzz2.c.

   179    179     a = sqlite3_malloc64(nByte+1);
   180    180     if( a==0 ) return 1;
   181    181     memcpy(a, aData, nByte);
   182    182     sqlite3_deserialize(db, "main", a, nByte, nByte,
   183    183           SQLITE_DESERIALIZE_RESIZEABLE |
   184    184           SQLITE_DESERIALIZE_FREEONCLOSE);
   185    185     x = szMax;
          186  +#ifdef SQLITE_FCNTL_SIZE_LIMIT
   186    187     sqlite3_file_control(db, "main", SQLITE_FCNTL_SIZE_LIMIT, &x);
          188  +#endif
   187    189     if( bVdbeDebug ){
   188    190       sqlite3_exec(db, "PRAGMA vdbe_debug=ON", 0, 0, 0);
   189    191     }
   190    192     for(i=0; i<sizeof(azSql)/sizeof(azSql[0]); i++){
   191    193       if( eVerbosity>=1 ){
   192    194         printf("%s\n", azSql[i]);
   193    195         fflush(stdout);

Changes to test/fts3atoken.test.

   103    103   } {1 {unknown tokenizer: nosuchtokenizer}}
   104    104   
   105    105   #--------------------------------------------------------------------------
   106    106   # Test cases fts3atoken-3.* test the three built-in tokenizers with a
   107    107   # simple input string via the built-in test function. This is as much
   108    108   # to test the test function as the tokenizer implementations.
   109    109   #
          110  +sqlite3_db_config db SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1
   110    111   do_test fts3atoken-3.1 {
   111    112     execsql {
   112    113       SELECT fts3_tokenizer_test('simple', 'I don''t see how');
   113    114     }
   114    115   } {{0 i I 1 don don 2 t t 3 see see 4 how how}}
   115    116   do_test fts3atoken-3.2 {
   116    117     execsql {

Changes to test/fts3corrupt4.test.

  3472   3472   }]} {}
  3473   3473   
  3474   3474   breakpoint
  3475   3475   do_catchsql_test 21.1 {
  3476   3476     SELECT offsets(t1) FROM t1 WHERE t1 MATCH 'R*';
  3477   3477   } {1 {database disk image is malformed}}
  3478   3478   
         3479  +#-------------------------------------------------------------------------
         3480  +reset_db
         3481  +do_test 22.0 {
         3482  +  sqlite3 db {}
         3483  +  db deserialize [decode_hexdb {
         3484  +| size 28672 pagesize 4096 filename crash-b794c89d922ac9.db
         3485  +| page 1 offset 0
         3486  +|      0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00   SQLite format 3.
         3487  +|     16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 07   .....@  ........
         3488  +|     32: 00 00 00 02 00 00 00 01 00 00 00 07 00 00 00 00   ................
         3489  +|     96: 00 00 00 00 0d 0e b1 00 06 0d a4 00 0f 8d 0f 21   ...............!
         3490  +|    112: 0e b9 0d c8 0e 7e 0d a4 00 00 00 00 00 00 00 00   .....~..........
         3491  +|   3488: 00 00 00 00 22 07 06 17 11 11 01 31 74 61 62 6c   ...........1tabl
         3492  +|   3504: 65 74 32 74 32 07 43 52 45 41 54 45 20 54 41 42   et2t2.CREATE TAB
         3493  +|   3520: 4c 45 20 74 32 28 78 29 81 33 05 07 17 1f 1f 01   LE t2(x).3......
         3494  +|   3536: 82 35 74 61 61 6c 65 74 31 5f 73 65 67 64 69 72   .5taalet1_segdir
         3495  +|   3552: 74 31 5f 73 65 67 64 69 72 05 43 52 45 41 54 45   t1_segdir.CREATE
         3496  +|   3568: 20 54 41 42 4c 45 20 27 74 31 5f 73 65 67 64 69    TABLE 't1_segdi
         3497  +|   3584: 72 27 28 6c 65 76 65 6c 20 49 4e 54 45 47 45 52   r'(level INTEGER
         3498  +|   3600: 2c 69 64 78 20 49 4e 54 45 47 45 52 2c 73 74 61   ,idx INTEGER,sta
         3499  +|   3616: 72 74 5f 62 6c 6f 63 6b 20 49 4e 54 45 47 45 52   rt_block INTEGER
         3500  +|   3632: 2c 6c 65 61 76 65 73 5f 65 6e 64 5f 62 6c 6f 63   ,leaves_end_bloc
         3501  +|   3648: 6b 20 49 4e 54 45 47 45 52 2c 65 6e 64 5f 62 6c   k INTEGER,end_bl
         3502  +|   3664: 6f 63 6b 20 49 4e 54 45 47 45 52 2c 72 6f 6f 74   ock INTEGER,root
         3503  +|   3680: 20 42 4c 4f 42 2c 50 52 49 4d 41 52 59 20 4b 45    BLOB,PRIMARY KE
         3504  +|   3696: 59 28 6c 65 76 65 6c 2c 20 69 64 78 29 29 31 06   Y(level, idx))1.
         3505  +|   3712: 06 17 45 1f 01 00 69 6e 64 65 78 73 71 6c 69 74   ..E...indexsqlit
         3506  +|   3728: 65 5f 61 75 74 6f 69 6e 64 65 78 5f 74 31 5f 73   e_autoindex_t1_s
         3507  +|   3744: 65 67 64 69 72 5f 31 74 31 5f 73 65 67 64 69 72   egdir_1t1_segdir
         3508  +|   3760: 06 0f c7 00 08 00 00 00 00 66 04 07 17 23 23 01   .........f...##.
         3509  +|   3776: 81 13 74 61 62 6c 65 74 31 5f 73 65 67 6d 65 6e   ..tablet1_segmen
         3510  +|   3792: 74 73 74 31 5f 73 65 67 6d 65 6e 74 73 04 43 52   tst1_segments.CR
         3511  +|   3808: 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 73   EATE TABLE 't1_s
         3512  +|   3824: 65 67 6d 65 6e 74 73 27 28 62 6c 6f 63 6b 69 64   egments'(blockid
         3513  +|   3840: 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59    INTEGER PRIMARY
         3514  +|   3856: 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42 4c 4f 42    KEY, block BLOB
         3515  +|   3872: 29 6a 03 07 17 21 21 01 81 1f 74 61 62 6c 65 74   )j...!!...tablet
         3516  +|   3888: 31 5f 63 6f 6e 84 65 6e 74 74 31 5f 63 6f 6e 74   1_con.entt1_cont
         3517  +|   3904: 65 6e 74 03 43 52 45 41 54 45 20 54 41 42 4c 45   ent.CREATE TABLE
         3518  +|   3920: 20 27 74 31 5f 63 6f 6e 74 65 6e 74 27 28 64 6f    't1_content'(do
         3519  +|   3936: 63 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d   cid INTEGER PRIM
         3520  +|   3952: 41 52 59 20 4b 45 59 2c 20 27 63 30 61 27 2c 20   ARY KEY, 'c0a', 
         3521  +|   3968: 27 63 31 62 27 2c 20 27 63 32 63 27 29 38 02 06   'c1b', 'c2c')8..
         3522  +|   3984: 17 11 11 08 5f 74 61 62 6c 65 74 31 74 31 43 52   ...._tablet1t1CR
         3523  +|   4000: 45 41 54 45 20 56 49 52 54 55 41 4c 20 54 41 42   EATE VIRTUAL TAB
         3524  +|   4016: 4c 45 20 74 31 20 55 53 49 4e 47 20 66 74 73 33   LE t1 USING fts3
         3525  +|   4032: 28 61 2c 62 2c 63 29 00 00 00 00 00 00 00 00 00   (a,b,c).........
         3526  +| page 3 offset 8192
         3527  +|      0: 0d 00 00 00 25 0b 48 00 0f d8 0f af 0f 86 0f 74   ....%.H........t
         3528  +|     16: 0f 61 0f 4e 0f 2f 0f 0f 0e ef 0e d7 0e be 0e a5   .a.N./..........
         3529  +|     32: 0e 8d 0e 74 0e 5b 0e 40 0e 24 0e 08 0d ef 0d d5   ...t.[.@.$......
         3530  +|     48: 0d bb 0d a0 0d 84 0d 68 0d 4f 0d 35 0d 1b 0c fb   .......h.O.5....
         3531  +|     64: 0c da 0c b9 0c 99 0c 78 0c 57 0c 3e 0c 24 0c 0a   .......x.W.>.$..
         3532  +|     80: 0b 48 00 00 00 00 00 00 00 00 00 00 00 00 00 00   .H..............
         3533  +|   2880: 00 00 00 00 00 00 00 00 81 3f 25 06 00 82 7f 00   .........?%.....
         3534  +|   2896: 00 43 4f 4d 50 49 4c 45 52 3d 67 63 63 2d 35 2e   .COMPILER=gcc-5.
         3535  +|   2912: 34 2e 30 20 32 30 31 36 30 36 30 39 20 44 45 42   4.0 20160609 DEB
         3536  +|   2928: 55 47 20 45 4e 41 42 4c 45 20 44 42 53 54 41 54   UG ENABLE DBSTAT
         3537  +|   2944: 20 56 54 41 42 20 45 4e 41 42 4c 45 20 46 54 53    VTAB ENABLE FTS
         3538  +|   2960: 34 20 45 4e 41 42 4c 45 20 46 54 53 35 20 45 4e   4 ENABLE FTS5 EN
         3539  +|   2976: 41 42 4c 45 20 47 45 4f 50 4f 4c 59 20 45 4e 41   ABLE GEOPOLY ENA
         3540  +|   2992: 42 4c 45 20 4a 53 4f 4e 31 20 45 4e 41 42 4c 45   BLE JSON1 ENABLE
         3541  +|   3008: 20 4d 45 4d 53 49 53 35 20 45 4e 41 42 4c 45 20    MEMSIS5 ENABLE 
         3542  +|   3024: 52 54 52 45 45 20 4d 41 58 20 4d 45 4d 4f 52 59   RTREE MAX MEMORY
         3543  +|   3040: 3d 35 30 30 30 30 30 30 30 20 4f 4d 49 54 20 4c   =50000000 OMIT L
         3544  +|   3056: 4f 41 44 20 45 58 54 45 4e 53 49 4f 4e 20 54 48   OAD EXTENSION TH
         3545  +|   3072: 52 45 41 44 53 41 46 45 3d 30 18 24 05 00 26 0f   READSAFE=0.$..&.
         3546  +|   3088: 19 54 48 52 45 41 44 53 41 46 45 3d 30 58 42 49   .THREADSAFE=0XBI
         3547  +|   3104: 4e 41 52 59 18 23 05 00 25 0f 19 54 48 52 45 41   NARY.#..%..THREA
         3548  +|   3120: 44 53 41 46 45 3d 30 58 4e 4f 43 41 53 45 17 22   DSAFE=0XNOCASE..
         3549  +|   3136: 05 00 25 0f 17 54 48 52 45 41 44 53 41 46 45 3d   ..%..THREADSAFE=
         3550  +|   3152: 30 58 52 54 52 49 4d 1f 21 05 00 33 0f 19 4f 4d   0XRTRIM.!..3..OM
         3551  +|   3168: 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 49 4f   IT LOAD EXTENSIO
         3552  +|   3184: 4e 58 42 49 4e 41 52 59 1f 20 05 00 33 0f 19 4f   NXBINARY. ..3..O
         3553  +|   3200: 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 49   MIT LOAD EXTENSI
         3554  +|   3216: 4f 4e 58 4e 4f 43 41 53 45 1e 1f 05 00 33 0f 17   ONXNOCASE....3..
         3555  +|   3232: 4f 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53   OMIT LOAD EXTENS
         3556  +|   3248: 49 4f 4e 58 52 54 52 49 4d 1f 1e 05 00 33 0f 19   IONXRTRIM....3..
         3557  +|   3264: 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30 30   MAX MEMORY=50000
         3558  +|   3280: 30 30 30 58 42 49 4e 41 52 59 1f 1d 05 00 33 0f   000XBINARY....3.
         3559  +|   3296: 19 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30   .MAX MEMORY=5000
         3560  +|   3312: 30 30 30 30 58 4e 4f 43 41 53 45 1e 1c 05 00 33   0000XNOCASE....3
         3561  +|   3328: 0f 17 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30   ..MAX MEMORY=500
         3562  +|   3344: 30 30 30 30 30 58 52 54 52 49 4d 18 1b 05 00 25   00000XRTRIM....%
         3563  +|   3360: 0f 19 45 4e 41 42 4c 45 20 52 54 52 45 45 58 42   ..ENABLE RTREEXB
         3564  +|   3376: 49 4e 41 52 59 18 1a 05 00 25 0f 19 45 4e 41 42   INARY....%..ENAB
         3565  +|   3392: 4c 55 20 52 54 52 45 45 58 4e 4f 43 41 53 45 17   LU RTREEXNOCASE.
         3566  +|   3408: 19 05 00 25 0f 17 45 4e 41 42 4c 45 20 52 54 52   ...%..ENABLE RTR
         3567  +|   3424: 45 45 58 52 54 52 49 4d 1a 18 05 00 29 0f 19 45   EEXRTRIM....)..E
         3568  +|   3440: 4e 41 42 4c 45 20 4d 45 4d 53 59 53 35 58 42 49   NABLE MEMSYS5XBI
         3569  +|   3456: 4e 41 52 59 1a 17 05 00 29 0f 19 45 4e 41 42 4c   NARY....)..ENABL
         3570  +|   3472: 45 20 4d 45 4d 53 59 53 35 58 4e 4f 43 41 53 45   E MEMSYS5XNOCASE
         3571  +|   3488: 19 16 05 00 29 0f 17 45 4e 41 42 4c 45 20 4d 45   ....)..ENABLE ME
         3572  +|   3504: 4d 53 59 53 35 58 52 54 52 49 4d 18 15 05 00 25   MSYS5XRTRIM....%
         3573  +|   3520: 0f 19 45 4e 41 42 4c 45 20 4a 53 4f 4e 31 58 42   ..ENABLE JSON1XB
         3574  +|   3536: 49 4e 41 52 59 18 14 05 00 25 0f 19 45 4e 41 42   INARY....%..ENAB
         3575  +|   3552: 4c 45 20 4a 53 4f 4e 31 58 4e 4f 43 41 53 45 17   LE JSON1XNOCASE.
         3576  +|   3568: 13 05 00 25 0f 17 45 4e 41 42 4c 45 20 4a 53 4f   ...%..ENABLE JSO
         3577  +|   3584: 4e 31 58 52 54 52 49 4d 1a 12 05 00 29 0f 19 45   N1XRTRIM....)..E
         3578  +|   3600: 4e 41 42 4c 45 20 47 45 4f 50 4f 4c 59 58 42 49   NABLE GEOPOLYXBI
         3579  +|   3616: 4e 41 52 59 1a 11 05 00 29 0f 19 45 4e 41 42 4c   NARY....)..ENABL
         3580  +|   3632: 45 20 47 45 4f 50 4f 4c 59 58 4e 4f 43 41 53 45   E GEOPOLYXNOCASE
         3581  +|   3648: 19 10 05 00 29 0f 17 45 4e 41 42 4c 45 20 47 45   ....)..ENABLE GE
         3582  +|   3664: 4f 50 4f 4c 59 58 52 54 52 49 4d 17 0f 05 00 23   OPOLYXRTRIM....#
         3583  +|   3680: 0f 19 45 4e 41 42 4c 45 20 46 54 53 35 58 42 49   ..ENABLE FTS5XBI
         3584  +|   3696: 4e 41 52 59 17 0e 05 00 23 0f 19 45 4e 41 42 4c   NARY....#..ENABL
         3585  +|   3712: 45 20 46 54 53 35 58 4e 4f 43 41 53 45 16 0d 05   E FTS5XNOCASE...
         3586  +|   3728: 00 23 0f 17 45 4e 41 42 4c 45 20 46 54 53 35 58   .#..ENABLE FTS5X
         3587  +|   3744: 52 54 52 49 4d 17 0c 05 00 23 0f 19 45 4e 41 42   RTRIM....#..ENAB
         3588  +|   3760: 4c 45 19 46 54 53 34 58 42 49 4e 41 52 59 17 0b   LE.FTS4XBINARY..
         3589  +|   3776: 05 00 23 0f 19 45 4e 41 42 4e f5 20 46 54 53 34   ..#..ENABN. FTS4
         3590  +|   3792: 58 4e 4f 43 41 53 45 16 0a 05 00 23 0f 17 45 4e   XNOCASE....#..EN
         3591  +|   3808: 41 42 4c 45 20 46 54 53 34 58 52 54 52 49 4d 1e   ABLE FTS4XRTRIM.
         3592  +|   3824: 09 05 00 31 0f 19 45 4e 41 42 4c 45 20 44 42 53   ...1..ENABLE DBS
         3593  +|   3840: 54 41 54 20 56 54 41 42 58 42 49 4e 41 52 59 1e   TAT VTABXBINARY.
         3594  +|   3856: 08 05 00 31 0f 19 45 4e 41 42 4c 45 20 44 42 53   ...1..ENABLE DBS
         3595  +|   3872: 54 41 54 20 56 54 41 42 58 4e 4f 43 41 53 45 1d   TAT VTABXNOCASE.
         3596  +|   3888: 07 05 00 31 0f 17 45 4e 41 42 4c 45 20 44 41 53   ...1..ENABLE DAS
         3597  +|   3904: 54 41 54 20 56 54 41 42 58 52 54 52 49 4d 11 06   TAT VTABXRTRIM..
         3598  +|   3920: 05 00 17 0f 19 44 45 42 55 47 58 42 49 4e 41 52   .....DEBUGXBINAR
         3599  +|   3936: 59 11 05 05 00 17 0f 19 44 45 42 55 47 58 4e 4f   Y.......DEBUGXNO
         3600  +|   3952: 43 41 53 45 10 04 05 00 17 ab 17 44 45 42 55 47   CASE.......DEBUG
         3601  +|   3968: 48 52 54 52 49 4d 27 03 05 00 43 0f 19 43 4f 4d   HRTRIM'...C..COM
         3602  +|   3984: 50 49 4c 45 52 3d 67 63 63 2d 35 2e 34 2e 30 20   PILER=gcc-5.4.0 
         3603  +|   4000: 32 30 31 36 30 36 30 39 58 43 49 4e 41 52 59 27   20160609XCINARY'
         3604  +|   4016: 02 04 00 43 0f 19 43 4f 4d 50 49 4c 45 52 3d 67   ...C..COMPILER=g
         3605  +|   4032: 63 63 2d 35 2e 34 2e 30 20 32 30 31 36 30 36 30   cc-5.4.0 2016060
         3606  +|   4048: 39 58 4e 4f 43 41 53 45 26 01 05 00 43 0f 17 43   9XNOCASE&...C..C
         3607  +|   4064: 4f 4d 50 49 4c 45 52 3d 67 63 63 2d 35 2e 34 2e   OMPILER=gcc-5.4.
         3608  +|   4080: 30 20 32 30 31 36 30 36 30 39 58 52 54 52 49 4d   0 20160609XRTRIM
         3609  +| page 4 offset 12288
         3610  +|      0: 0d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
         3611  +| page 5 offset 16384
         3612  +|      0: 0d 00 00 00 02 0b a0 00 0c ad 0b a0 00 00 00 00   ................
         3613  +|   2976: 82 0a 02 08 08 09 08 08 17 84 06 30 20 32 35 33   ...........0 253
         3614  +|   2992: 00 01 30 04 25 06 1b 00 00 08 32 30 31 36 30 36   ..0.%.....201606
         3615  +|   3008: 30 39 03 25 07 00 00 01 34 03 25 05 00 00 01 35   09.%....4.%....5
         3616  +|   3024: 03 25 04 00 01 07 30 30 30 30 30 30 30 03 25 1a   .%....0000000.%.
         3617  +|   3040: 00 00 08 63 6f 6d 70 69 6c 65 72 03 25 02 00 00   ...compiler.%...
         3618  +|   3056: 06 64 62 73 74 61 74 03 25 0a 00 01 04 65 62 75   .dbstat.%....ebu
         3619  +|   3072: 67 03 25 08 00 00 06 65 6e 61 62 6c 65 09 25 09   g.%....enable.%.
         3620  +|   3088: 05 04 04 04 04 04 00 01 08 78 74 65 6e 73 69 6f   .........xtensio
         3621  +|   3104: 6e 03 25 1d 00 00 04 66 74 73 34 03 25 0d 00 03   n.%....fts4.%...
         3622  +|   3120: 01 35 03 25 0f 00 00 03 67 63 63 03 25 03 00 01   .5.%....gcc.%...
         3623  +|   3136: 06 65 6f 70 6f 6c 79 03 25 11 00 00 05 6a 73 6f   .eopoly.%....jso
         3624  +|   3152: 6e 31 03 25 13 00 00 04 6c 6f 61 64 03 25 1c 00   n1.%....load.%..
         3625  +|   3168: 00 03 6d 61 78 03 25 18 00 01 05 65 6d 6f 72 79   ..max.%....emory
         3626  +|   3184: 03 25 19 00 03 04 73 79 73 35 03 25 15 00 00 04   .%....sys5.%....
         3627  +|   3200: 6f 6d 69 74 03 25 1b 00 00 05 72 74 72 65 65 03   omit.%....rtree.
         3628  +|   3216: 25 17 00 00 0a 74 68 72 65 61 64 73 61 66 65 03   %....threadsafe.
         3629  +|   3232: 25 1e 00 00 04 76 74 61 62 03 25 0b 00 86 50 01   %....vtab.%...P.
         3630  +|   3248: 08 08 08 08 08 17 8d 12 30 20 38 33 35 00 01 30   ........0 835..0
         3631  +|   3264: 12 01 06 00 01 06 00 01 06 00 1f 03 00 01 03 00   ................
         3632  +|   3280: 01 03 00 00 08 32 30 31 36 30 36 30 39 09 01 07   .....20160609...
         3633  +|   3296: 00 01 07 00 01 07 00 00 01 34 09 01 05 00 01 05   .........4......
         3634  +|   3312: 00 01 05 00 00 01 35 09 01 04 00 01 04 00 01 04   ......5.........
         3635  +|   3328: 00 01 07 30 30 30 30 30 30 30 09 1c 04 00 01 04   ...0000000......
         3636  +|   3344: 00 01 04 00 00 06 62 69 6e 61 72 79 3c 03 01 02   ......binary<...
         3637  +|   3360: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
         3638  +|   3376: 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00   ................
         3639  +|   3392: 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03   ................
         3640  +|   3408: 01 02 02 00 03 01 02 02 00 00 08 63 6f 6d 70 69   ...........compi
         3641  +|   3424: 6c 65 72 09 01 02 00 01 02 00 01 02 00 00 06 64   ler............d
         3642  +|   3440: 62 73 74 61 74 09 07 03 00 01 03 00 01 03 00 01   bstat...........
         3643  +|   3456: 04 65 62 75 67 09 04 02 00 01 02 00 01 02 00 00   .ebug...........
         3644  +|   3472: 06 65 6e 61 62 6c 65 3f 07 02 00 01 02 00 01 02   .enable?........
         3645  +|   3488: 00 01 02 00 01 02 00 01 02 00 01 02 00 01 02 00   ................
         3646  +|   3504: 01 02 00 01 02 00 01 02 00 01 02 00 01 02 00 01   ................
         3647  +|   3520: 02 00 01 02 00 01 02 00 01 02 00 01 02 00 01 02   ................
         3648  +|   3536: 00 01 02 00 01 02 00 01 08 78 74 65 6e 73 69 6f   .........xtensio
         3649  +|   3552: 6e 09 1f 04 00 01 04 00 01 04 00 00 04 66 74 73   n............fts
         3650  +|   3568: 34 09 0a 03 d4 01 02 ff 01 03 00 03 01 35 09 0d   4............5..
         3651  +|   3584: 03 00 01 03 00 01 03 00 00 03 67 64 d3 09 01 03   ..........gd....
         3652  +|   3600: 00 01 03 00 01 03 00 01 06 65 6f 70 6f 6c 79 09   .........eopoly.
         3653  +|   3616: 10 03 00 01 03 00 01 03 00 00 05 6a 73 6f 6e 31   ...........json1
         3654  +|   3632: 19 13 03 00 01 03 00 01 03 00 00 04 6c 6f 61 64   ............load
         3655  +|   3648: 09 1f 03 00 01 03 00 01 03 00 00 03 6d 61 78 09   ............max.
         3656  +|   3664: 1c 02 00 01 02 00 01 02 00 01 05 65 6d 6f 72 79   ...........emory
         3657  +|   3680: 09 1c 03 00 01 03 00 01 03 00 03 04 73 79 73 35   ............sys5
         3658  +|   3696: 09 16 03 00 01 03 00 01 03 00 00 06 6e 6f 63 61   ............noca
         3659  +|   3712: 73 65 3c 02 01 02 02 00 03 01 02 02 00 03 01 02   se<.............
         3660  +|   3728: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
         3661  +|   3744: 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00   ................
         3662  +|   3760: 03 01 02 02 00 03 01 02 02 00 03 01 02 02 00 00   ................
         3663  +|   3776: 04 6f 6d 69 74 09 1f 02 00 01 12 00 01 02 00 00   .omit...........
         3664  +|   3792: 05 72 74 72 65 65 09 19 03 00 01 07 80 00 f3 00   .rtree..........
         3665  +|   3808: 03 02 69 6d 3c 01 01 02 02 00 03 01 02 02 00 03   ..im<...........
         3666  +|   3824: 01 02 02 00 03 01 02 02 00 03 01 02 02 00 03 01   ................
         3667  +|   3840: 02 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02   ................
         3668  +|   3856: 02 00 03 01 02 02 00 03 01 02 02 00 03 01 02 02   ................
         3669  +|   3872: 00 00 0a 74 68 72 65 61 64 73 61 66 65 09 22 02   ...threadsafe...
         3670  +|   3888: 00 01 02 00 01 02 00 00 04 76 74 61 62 09 07 04   .........vtab...
         3671  +|   3904: 00 01 04 00 01 04 00 00 01 78 b4 01 01 01 01 02   .........x......
         3672  +|   3920: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
         3673  +|   3936: 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01   ................
         3674  +|   3952: 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01   ................
         3675  +|   3968: 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01   ................
         3676  +|   3984: 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02   ................
         3677  +|   4000: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
         3678  +|   4016: 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01   ................
         3679  +|   4032: 01 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01   ................
         3680  +|   4048: 01 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01   ................
         3681  +|   4064: 02 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02   ................
         3682  +|   4080: 00 01 01 01 02 00 01 01 01 02 00 01 01 01 02 00   ................
         3683  +| page 6 offset 20480
         3684  +|      0: 0a 00 00 00 02 0f f5 00 0f fb 0f f5 00 00 00 00   ................
         3685  +|   4080: 00 00 00 00 00 05 04 08 09 01 02 04 04 08 08 09   ................
         3686  +| page 7 offset 24576
         3687  +|      0: 0d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
         3688  +|   4016: 00 00 00 00 00 00 00 00 0d 05 02 23 61 75 74 6f   ...........#auto
         3689  +|   4032: 6d 65 72 67 65 3d 35 0d 04 02 23 6d 65 72 67 65   merge=5...#merge
         3690  +|   4048: 3d 31 30 30 2c 38 11 03 02 2b 69 6e 74 65 67 72   =100,8...+integr
         3691  +|   4064: 69 74 79 2d 63 68 65 63 6b 09 02 02 1b 72 65 62   ity-check....reb
         3692  +| end crash-b794c89d922ac9.db
         3693  +}]} {}
         3694  +
         3695  +do_catchsql_test 22.1 {
         3696  +  SELECT snippet(t1,'', '', '--',-1,01)==0
         3697  +    FROM t1 WHERE a MATCH 'rtree OR json1rtree OR json1';
         3698  +} {0 {0 0 0 0 0 0 0}}
  3479   3699   
  3480   3700   finish_test
  3481   3701   

Changes to test/fts3expr4.test.

whitespace changes only

Changes to test/fuzzdata8.db.

cannot compute difference between binary files

Changes to test/like3.test.

   173    173   } {/abc}
   174    174   do_eqp_test like3-5.211 {
   175    175     SELECT x FROM t5b WHERE x GLOB '/a*';
   176    176   } {
   177    177     QUERY PLAN
   178    178     `--SEARCH TABLE t5b USING COVERING INDEX sqlite_autoindex_t5b_1 (x>? AND x<?)
   179    179   }
          180  +
          181  +# 2019-02-27
          182  +# Verify that the LIKE optimization works with an ESCAPE clause when
          183  +# using PRAGMA case_sensitive_like=ON.
          184  +#
          185  +do_execsql_test like3-6.100 {
          186  +  DROP TABLE IF EXISTS t1;
          187  +  CREATE TABLE t1(path TEXT COLLATE nocase PRIMARY KEY,a,b,c) WITHOUT ROWID;
          188  +}
          189  +do_eqp_test like3-6.110 {
          190  +  SELECT * FROM t1 WHERE path LIKE 'a%';
          191  +} {
          192  +  QUERY PLAN
          193  +  `--SEARCH TABLE t1 USING PRIMARY KEY (path>? AND path<?)
          194  +}
          195  +do_eqp_test like3-6.120 {
          196  +  SELECT * FROM t1 WHERE path LIKE 'a%' ESCAPE '_';
          197  +} {
          198  +  QUERY PLAN
          199  +  `--SEARCH TABLE t1 USING PRIMARY KEY (path>? AND path<?)
          200  +}
          201  +do_execsql_test like3-6.200 {
          202  +  DROP TABLE IF EXISTS t2;
          203  +  CREATE TABLE t2(path TEXT,x,y,z);
          204  +  CREATE INDEX t2path ON t2(path COLLATE nocase);
          205  +  CREATE INDEX t2path2 ON t2(path);
          206  +}
          207  +do_eqp_test like3-6.210 {
          208  +  SELECT * FROM t2 WHERE path LIKE 'a%';
          209  +} {
          210  +  QUERY PLAN
          211  +  `--SEARCH TABLE t2 USING INDEX t2path (path>? AND path<?)
          212  +}
          213  +do_eqp_test like3-6.220 {
          214  +  SELECT * FROM t2 WHERE path LIKE 'a%' ESCAPE '_';
          215  +} {
          216  +  QUERY PLAN
          217  +  `--SEARCH TABLE t2 USING INDEX t2path (path>? AND path<?)
          218  +}
          219  +db eval {PRAGMA case_sensitive_like=ON}
          220  +do_eqp_test like3-6.230 {
          221  +  SELECT * FROM t2 WHERE path LIKE 'a%';
          222  +} {
          223  +  QUERY PLAN
          224  +  `--SEARCH TABLE t2 USING INDEX t2path2 (path>? AND path<?)
          225  +}
          226  +do_eqp_test like3-6.240 {
          227  +  SELECT * FROM t2 WHERE path LIKE 'a%' ESCAPE '_';
          228  +} {
          229  +  QUERY PLAN
          230  +  `--SEARCH TABLE t2 USING INDEX t2path2 (path>? AND path<?)
          231  +}
   180    232   
   181    233   finish_test

Changes to test/scanstatus.test.

whitespace changes only

Changes to test/tclsqlite.test.

    17     17   #
    18     18   # $Id: tclsqlite.test,v 1.73 2009/03/16 13:19:36 danielk1977 Exp $
    19     19   
    20     20   catch {sqlite3}
    21     21   
    22     22   set testdir [file dirname $argv0]
    23     23   source $testdir/tester.tcl
           24  +set testprefix tcl
    24     25   
    25     26   # Check the error messages generated by tclsqlite
    26     27   #
    27     28   set r "sqlite_orig HANDLE ?FILENAME? ?-vfs VFSNAME? ?-readonly BOOLEAN? ?-create BOOLEAN? ?-nomutex BOOLEAN? ?-fullmutex BOOLEAN? ?-uri BOOLEAN? ?-shared-schema BOOLEAN?"
    28     29   if {[sqlite3 -has-codec]} {
    29     30     append r " ?-key CODECKEY?"
    30     31   }
................................................................................
    37     38     set v [catch {sqlite3} msg]
    38     39     regsub {really_sqlite3} $msg {sqlite3} msg
    39     40     lappend v $msg
    40     41   } [list 1 "wrong # args: should be \"$r\""]
    41     42   do_test tcl-1.2 {
    42     43     set v [catch {db bogus} msg]
    43     44     lappend v $msg
    44         -} {1 {bad option "bogus": must be authorizer, backup, busy, cache, changes, close, collate, collation_needed, commit_hook, complete, copy, deserialize, enable_load_extension, errorcode, eval, exists, function, incrblob, interrupt, last_insert_rowid, nullvalue, onecolumn, preupdate, profile, progress, rekey, restore, rollback_hook, serialize, status, timeout, total_changes, trace, trace_v2, transaction, unlock_notify, update_hook, version, or wal_hook}}
           45  +} {1 {bad option "bogus": must be authorizer, backup, bind_fallback, busy, cache, changes, close, collate, collation_needed, commit_hook, complete, copy, deserialize, enable_load_extension, errorcode, eval, exists, function, incrblob, interrupt, last_insert_rowid, nullvalue, onecolumn, preupdate, profile, progress, rekey, restore, rollback_hook, serialize, status, timeout, total_changes, trace, trace_v2, transaction, unlock_notify, update_hook, version, or wal_hook}}
    45     46   do_test tcl-1.2.1 {
    46     47     set v [catch {db cache bogus} msg]
    47     48     lappend v $msg
    48     49   } {1 {bad option "bogus": must be flush or size}}
    49     50   do_test tcl-1.2.2 {
    50     51     set v [catch {db cache} msg]
    51     52     lappend v $msg
................................................................................
   707    708     unset -nocomplain x
   708    709     db eval -withoutnulls {SELECT * FROM t1} x {
   709    710       lappend res $x(a) [array names x]
   710    711     }
   711    712     set res
   712    713   } {1 {a b *} 2 {a *} 3 {a b *}}
   713    714   
          715  +#-------------------------------------------------------------------------
          716  +# Test the -type option to [db function].
          717  +#
          718  +reset_db
          719  +proc add {a b} { return [expr $a + $b] }
          720  +proc ret {a} { return $a }
          721  +
          722  +db function add_i -returntype integer add 
          723  +db function add_r -ret        real    add
          724  +db function add_t -return     text    add 
          725  +db function add_b -returntype blob    add 
          726  +db function add_a -returntype any     add 
          727  +
          728  +db function ret_i -returntype int     ret 
          729  +db function ret_r -returntype real    ret
          730  +db function ret_t -returntype text    ret 
          731  +db function ret_b -returntype blob    ret 
          732  +db function ret_a -r          any     ret 
          733  +
          734  +do_execsql_test 17.0 {
          735  +  SELECT quote( add_i(2, 3) );
          736  +  SELECT quote( add_r(2, 3) ); 
          737  +  SELECT quote( add_t(2, 3) ); 
          738  +  SELECT quote( add_b(2, 3) ); 
          739  +  SELECT quote( add_a(2, 3) ); 
          740  +} {5 5.0 '5' X'35' 5}
          741  +
          742  +do_execsql_test 17.1 {
          743  +  SELECT quote( add_i(2.2, 3.3) );
          744  +  SELECT quote( add_r(2.2, 3.3) ); 
          745  +  SELECT quote( add_t(2.2, 3.3) ); 
          746  +  SELECT quote( add_b(2.2, 3.3) ); 
          747  +  SELECT quote( add_a(2.2, 3.3) ); 
          748  +} {5.5 5.5 '5.5' X'352E35' 5.5}
          749  +
          750  +do_execsql_test 17.2 {
          751  +  SELECT quote( ret_i(2.5) );
          752  +  SELECT quote( ret_r(2.5) ); 
          753  +  SELECT quote( ret_t(2.5) ); 
          754  +  SELECT quote( ret_b(2.5) ); 
          755  +  SELECT quote( ret_a(2.5) ); 
          756  +} {2.5 2.5 '2.5' X'322E35' 2.5}
          757  +
          758  +do_execsql_test 17.3 {
          759  +  SELECT quote( ret_i('2.5') );
          760  +  SELECT quote( ret_r('2.5') ); 
          761  +  SELECT quote( ret_t('2.5') ); 
          762  +  SELECT quote( ret_b('2.5') ); 
          763  +  SELECT quote( ret_a('2.5') ); 
          764  +} {2.5 2.5 '2.5' X'322E35' '2.5'}
          765  +
          766  +do_execsql_test 17.4 {
          767  +  SELECT quote( ret_i('abc') );
          768  +  SELECT quote( ret_r('abc') ); 
          769  +  SELECT quote( ret_t('abc') ); 
          770  +  SELECT quote( ret_b('abc') ); 
          771  +  SELECT quote( ret_a('abc') ); 
          772  +} {'abc' 'abc' 'abc' X'616263' 'abc'}
          773  +
          774  +do_execsql_test 17.5 {
          775  +  SELECT quote( ret_i(X'616263') );
          776  +  SELECT quote( ret_r(X'616263') ); 
          777  +  SELECT quote( ret_t(X'616263') ); 
          778  +  SELECT quote( ret_b(X'616263') ); 
          779  +  SELECT quote( ret_a(X'616263') ); 
          780  +} {'abc' 'abc' 'abc' X'616263' X'616263'}
          781  +
          782  +do_test 17.6.1 {
          783  +  list [catch { db function xyz -return object ret } msg] $msg
          784  +} {1 {bad type "object": must be integer, real, text, blob, or any}}
          785  +
          786  +do_test 17.6.2 {
          787  +  list [catch { db function xyz -return ret } msg] $msg
          788  +} {1 {option requires an argument: -return}}
   714    789   
          790  +do_test 17.6.3 {
          791  +  list [catch { db function xyz -n object ret } msg] $msg
          792  +} {1 {bad option "-n": must be -argcount, -deterministic or -returntype}}
   715    793   
   716         -
          794  +# 2019-02-28: The "bind_fallback" command.
          795  +#
          796  +do_test 18.100 {
          797  +  unset -nocomplain bindings abc def ghi jkl mno e01 e02
          798  +  set bindings(abc) [expr {1+2}]
          799  +  set bindings(def) {hello}
          800  +  set bindings(ghi) [expr {3.1415926*1.0}]
          801  +  proc bind_callback {nm} {
          802  +    global bindings
          803  +    set n2 [string range $nm 1 end]
          804  +    if {[info exists bindings($n2)]} {
          805  +      return $bindings($n2)
          806  +    }
          807  +    if {[string match e* $n2]} {
          808  +      error "no such variable: $nm"
          809  +    }
          810  +    return -code return {}
          811  +  }
          812  +  db bind_fallback bind_callback
          813  +  db eval {SELECT $abc, typeof($abc), $def, typeof($def), $ghi, typeof($ghi)}
          814  +} {3 integer hello text 3.1415926 real}
          815  +do_test 18.110 {
          816  +  db eval {SELECT quote(@def), typeof(@def)}
          817  +} {X'68656C6C6F' blob}
          818  +do_execsql_test 18.120 {
          819  +  SELECT typeof($mno);
          820  +} {null}
          821  +do_catchsql_test 18.130 {
          822  +  SELECT $e01;
          823  +} {1 {no such variable: $e01}}
          824  +do_test 18.140 {
          825  +  db bind_fallback
          826  +} {bind_callback}
          827  +do_test 18.200 {
          828  +  db bind_fallback {}
          829  +  db eval {SELECT $abc, typeof($abc), $def, typeof($def), $ghi, typeof($ghi)}
          830  +} {{} null {} null {} null}
          831  +do_test 18.300 {
          832  +  unset -nocomplain bindings
          833  +  proc bind_callback {nm} {lappend ::bindings $nm}
          834  +  db bind_fallback bind_callback
          835  +  db eval {SELECT $abc, @def, $ghi(123), :mno}
          836  +  set bindings
          837  +} {{$abc} @def {$ghi(123)} :mno}
          838  +do_test 18.900 {
          839  +  set rc [catch {db bind_fallback a b} msg]
          840  +  lappend rc $msg
          841  +} {1 {wrong # args: should be "db bind_fallback ?CALLBACK?"}}
          842  +do_test 18.910 {
          843  +  db bind_fallback bind_fallback_does_not_exist
          844  +} {}
          845  +do_catchsql_test 19.911 {
          846  +  SELECT $abc, typeof($abc), $def, typeof($def), $ghi, typeof($ghi);
          847  +} {1 {invalid command name "bind_fallback_does_not_exist"}}
          848  +db bind_fallback {}
   717    849   
   718    850   finish_test