/ Check-in [1e69f3ff]
Login

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

Overview
Comment:Add the sqlite3session_config() interface. For configuring global parameters belonging to the sessions module.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 1e69f3ff057b0be27a9e79842de2485f8299799f309e89bfa7597dd688e0975b
User & Date: dan 2018-10-26 17:05:00
Context
2018-10-27
00:47
Initial code for a fuzzing tool on database file that works with the -fsanitize=fuzzer option of clang. check-in: 90d12094 user: drh tags: trunk
2018-10-26
17:05
Add the sqlite3session_config() interface. For configuring global parameters belonging to the sessions module. check-in: 1e69f3ff user: dan tags: trunk
15:36
Prevent an == constraint specified using the table-valued-function argument syntax from being used to optimize any scan not related to the virtual table for which it was specified as an argument. check-in: 4d46685f user: dan tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to ext/session/session1.test.

   650    650     set CONFLICT_HANDLERS [list REPLACE REPLACE ABORT]
   651    651     execsql ROLLBACK
   652    652     execsql BEGIN
   653    653     catch { sqlite3changeset_apply_v2 -nosavepoint db $C xConflict } msg
   654    654     execsql { SELECT * FROM x1 }
   655    655   } {1 one 2 two 3 iii}
   656    656   execsql ROLLBACK
          657  +
          658  +do_test $tn.14.1 { sqlite3session_config strm_size -1 } 64
          659  +do_test $tn.14.2 { sqlite3session_config strm_size 65536 } 65536
          660  +do_test $tn.14.3 { sqlite3session_config strm_size 64 } 64
          661  +do_test $tn.14.4 { 
          662  +  list [catch {sqlite3session_config invalid 123} msg] $msg
          663  +} {1 SQLITE_MISUSE}
   657    664   
   658    665   }]
   659    666   }
   660    667   
   661    668   
   662    669   finish_test

Changes to ext/session/sqlite3session.c.

    21     21   # ifdef SQLITE_TEST
    22     22   #   define SESSIONS_STRM_CHUNK_SIZE 64
    23     23   # else
    24     24   #   define SESSIONS_STRM_CHUNK_SIZE 1024
    25     25   # endif
    26     26   #endif
    27     27   
           28  +static int sessions_strm_chunk_size = SESSIONS_STRM_CHUNK_SIZE;
           29  +
    28     30   typedef struct SessionHook SessionHook;
    29     31   struct SessionHook {
    30     32     void *pCtx;
    31     33     int (*xOld)(void*,int,sqlite3_value**);
    32     34     int (*xNew)(void*,int,sqlite3_value**);
    33     35     int (*xCount)(void*);
    34     36     int (*xDepth)(void*);
................................................................................
  2393   2395             }else if( p->op!=SQLITE_INSERT ){
  2394   2396               rc = sessionAppendDelete(&buf, bPatchset, p, nCol, abPK);
  2395   2397             }
  2396   2398             if( rc==SQLITE_OK ){
  2397   2399               rc = sqlite3_reset(pSel);
  2398   2400             }
  2399   2401   
  2400         -          /* If the buffer is now larger than SESSIONS_STRM_CHUNK_SIZE, pass
         2402  +          /* If the buffer is now larger than sessions_strm_chunk_size, pass
  2401   2403             ** its contents to the xOutput() callback. */
  2402   2404             if( xOutput 
  2403   2405              && rc==SQLITE_OK 
  2404   2406              && buf.nBuf>nNoop 
  2405         -           && buf.nBuf>SESSIONS_STRM_CHUNK_SIZE 
         2407  +           && buf.nBuf>sessions_strm_chunk_size 
  2406   2408             ){
  2407   2409               rc = xOutput(pOut, (void*)buf.aBuf, buf.nBuf);
  2408   2410               nNoop = -1;
  2409   2411               buf.nBuf = 0;
  2410   2412             }
  2411   2413   
  2412   2414           }
................................................................................
  2610   2612   }
  2611   2613   
  2612   2614   /*
  2613   2615   ** If the SessionInput object passed as the only argument is a streaming
  2614   2616   ** object and the buffer is full, discard some data to free up space.
  2615   2617   */
  2616   2618   static void sessionDiscardData(SessionInput *pIn){
  2617         -  if( pIn->xInput && pIn->iNext>=SESSIONS_STRM_CHUNK_SIZE ){
         2619  +  if( pIn->xInput && pIn->iNext>=sessions_strm_chunk_size ){
  2618   2620       int nMove = pIn->buf.nBuf - pIn->iNext;
  2619   2621       assert( nMove>=0 );
  2620   2622       if( nMove>0 ){
  2621   2623         memmove(pIn->buf.aBuf, &pIn->buf.aBuf[pIn->iNext], nMove);
  2622   2624       }
  2623   2625       pIn->buf.nBuf -= pIn->iNext;
  2624   2626       pIn->iNext = 0;
................................................................................
  2633   2635   **
  2634   2636   ** Return an SQLite error code if an error occurs, or SQLITE_OK otherwise.
  2635   2637   */
  2636   2638   static int sessionInputBuffer(SessionInput *pIn, int nByte){
  2637   2639     int rc = SQLITE_OK;
  2638   2640     if( pIn->xInput ){
  2639   2641       while( !pIn->bEof && (pIn->iNext+nByte)>=pIn->nData && rc==SQLITE_OK ){
  2640         -      int nNew = SESSIONS_STRM_CHUNK_SIZE;
         2642  +      int nNew = sessions_strm_chunk_size;
  2641   2643   
  2642   2644         if( pIn->bNoDiscard==0 ) sessionDiscardData(pIn);
  2643   2645         if( SQLITE_OK==sessionBufferGrow(&pIn->buf, nNew, &rc) ){
  2644   2646           rc = pIn->xInput(pIn->pIn, &pIn->buf.aBuf[pIn->buf.nBuf], &nNew);
  2645   2647           if( nNew==0 ){
  2646   2648             pIn->bEof = 1;
  2647   2649           }else{
................................................................................
  3358   3360   
  3359   3361         default:
  3360   3362           rc = SQLITE_CORRUPT_BKPT;
  3361   3363           goto finished_invert;
  3362   3364       }
  3363   3365   
  3364   3366       assert( rc==SQLITE_OK );
  3365         -    if( xOutput && sOut.nBuf>=SESSIONS_STRM_CHUNK_SIZE ){
         3367  +    if( xOutput && sOut.nBuf>=sessions_strm_chunk_size ){
  3366   3368         rc = xOutput(pOut, sOut.aBuf, sOut.nBuf);
  3367   3369         sOut.nBuf = 0;
  3368   3370         if( rc!=SQLITE_OK ) goto finished_invert;
  3369   3371       }
  3370   3372     }
  3371   3373   
  3372   3374     assert( rc==SQLITE_OK );
................................................................................
  4891   4893       sessionAppendTableHdr(&buf, pGrp->bPatch, pTab, &rc);
  4892   4894       for(i=0; i<pTab->nChange; i++){
  4893   4895         SessionChange *p;
  4894   4896         for(p=pTab->apChange[i]; p; p=p->pNext){
  4895   4897           sessionAppendByte(&buf, p->op, &rc);
  4896   4898           sessionAppendByte(&buf, p->bIndirect, &rc);
  4897   4899           sessionAppendBlob(&buf, p->aRecord, p->nRecord, &rc);
  4898         -        if( rc==SQLITE_OK && xOutput && buf.nBuf>=SESSIONS_STRM_CHUNK_SIZE ){
         4900  +        if( rc==SQLITE_OK && xOutput && buf.nBuf>=sessions_strm_chunk_size ){
  4899   4901             rc = xOutput(pOut, buf.aBuf, buf.nBuf);
  4900   4902             buf.nBuf = 0;
  4901   4903           }
  4902   4904         }
  4903   4905       }
  4904   4906     }
  4905   4907   
................................................................................
  5287   5289       }
  5288   5290   
  5289   5291       if( bDone==0 ){
  5290   5292         sessionAppendByte(&sOut, pIter->op, &rc);
  5291   5293         sessionAppendByte(&sOut, pIter->bIndirect, &rc);
  5292   5294         sessionAppendBlob(&sOut, aRec, nRec, &rc);
  5293   5295       }
  5294         -    if( rc==SQLITE_OK && xOutput && sOut.nBuf>SESSIONS_STRM_CHUNK_SIZE ){
         5296  +    if( rc==SQLITE_OK && xOutput && sOut.nBuf>sessions_strm_chunk_size ){
  5295   5297         rc = xOutput(pOut, sOut.aBuf, sOut.nBuf);
  5296   5298         sOut.nBuf = 0;
  5297   5299       }
  5298   5300       if( rc ) break;
  5299   5301     }
  5300   5302   
  5301   5303     if( rc!=SQLITE_OK ){
................................................................................
  5397   5399   */
  5398   5400   void sqlite3rebaser_delete(sqlite3_rebaser *p){
  5399   5401     if( p ){
  5400   5402       sessionDeleteTable(p->grp.pList);
  5401   5403       sqlite3_free(p);
  5402   5404     }
  5403   5405   }
         5406  +
         5407  +/* 
         5408  +** Global configuration
         5409  +*/
         5410  +int sqlite3session_config(int op, void *pArg){
         5411  +  int rc = SQLITE_OK;
         5412  +  switch( op ){
         5413  +    case SQLITE_SESSION_CONFIG_STRMSIZE: {
         5414  +      int *pInt = (int*)pArg;
         5415  +      if( *pInt>0 ){
         5416  +        sessions_strm_chunk_size = *pInt;
         5417  +      }
         5418  +      *pInt = sessions_strm_chunk_size;
         5419  +      break;
         5420  +    }
         5421  +    default:
         5422  +      rc = SQLITE_MISUSE;
         5423  +      break;
         5424  +  }
         5425  +  return rc;
         5426  +}
  5404   5427   
  5405   5428   #endif /* SQLITE_ENABLE_SESSION && SQLITE_ENABLE_PREUPDATE_HOOK */

Changes to ext/session/sqlite3session.h.

  1606   1606     sqlite3_rebaser *pRebaser,
  1607   1607     int (*xInput)(void *pIn, void *pData, int *pnData),
  1608   1608     void *pIn,
  1609   1609     int (*xOutput)(void *pOut, const void *pData, int nData),
  1610   1610     void *pOut
  1611   1611   );
  1612   1612   
         1613  +/*
         1614  +** CAPI3REF: Configure global parameters
         1615  +**
         1616  +** The sqlite3session_config() interface is used to make global configuration
         1617  +** changes to the sessions module in order to tune it to the specific needs 
         1618  +** of the application.
         1619  +**
         1620  +** The sqlite3session_config() interface is not threadsafe. If it is invoked
         1621  +** while any other thread is inside any other sessions method then the
         1622  +** results are undefined. Furthermore, if it is invoked after any sessions
         1623  +** related objects have been created, the results are also undefined. 
         1624  +**
         1625  +** The first argument to the sqlite3session_config() function must be one
         1626  +** of the SQLITE_SESSION_CONFIG_XXX constants defined below. The 
         1627  +** interpretation of the (void*) value passed as the second parameter and
         1628  +** the effect of calling this function depends on the value of the first
         1629  +** parameter.
         1630  +**
         1631  +** <dl>
         1632  +** <dt>SQLITE_SESSION_CONFIG_STRMSIZE<dd>
         1633  +**    By default, the sessions module streaming interfaces attempt to input
         1634  +**    and output data in approximately 1 KiB chunks. This operand may be used
         1635  +**    to set and query the value of this configuration setting. The pointer
         1636  +**    passed as the second argument must point to a value of type (int).
         1637  +**    If this value is greater than 0, it is used as the new streaming data
         1638  +**    chunk size for both input and output. Before returning, the (int) value
         1639  +**    pointed to by pArg is set to the final value of the streaming interface
         1640  +**    chunk size.
         1641  +** </dl>
         1642  +**
         1643  +** This function returns SQLITE_OK if successful, or an SQLite error code
         1644  +** otherwise.
         1645  +*/
         1646  +int sqlite3session_config(int op, void *pArg);
         1647  +
         1648  +/*
         1649  +** CAPI3REF: Values for sqlite3session_config().
         1650  +*/
         1651  +#define SQLITE_SESSION_CONFIG_STRMSIZE 1
  1613   1652   
  1614   1653   /*
  1615   1654   ** Make sure we can call this stuff from C++.
  1616   1655   */
  1617   1656   #ifdef __cplusplus
  1618   1657   }
  1619   1658   #endif
  1620   1659   
  1621   1660   #endif  /* !defined(__SQLITESESSION_H_) && defined(SQLITE_ENABLE_SESSION) */

Changes to ext/session/test_session.c.

  1234   1234   
  1235   1235     Tcl_CreateObjCommand(interp, Tcl_GetString(objv[1]), test_rebaser_cmd,
  1236   1236         (ClientData)pNew, test_rebaser_del
  1237   1237     );
  1238   1238     Tcl_SetObjResult(interp, objv[1]);
  1239   1239     return TCL_OK;
  1240   1240   }
         1241  +
         1242  +/*
         1243  +** tclcmd: sqlite3rebaser_configure OP VALUE
         1244  +*/
         1245  +static int SQLITE_TCLAPI test_sqlite3session_config(
         1246  +  void * clientData,
         1247  +  Tcl_Interp *interp,
         1248  +  int objc,
         1249  +  Tcl_Obj *CONST objv[]
         1250  +){
         1251  +  struct ConfigOpt {
         1252  +    const char *zSub;
         1253  +    int op;
         1254  +  } aSub[] = {
         1255  +    { "strm_size",    SQLITE_SESSION_CONFIG_STRMSIZE },
         1256  +    { "invalid",      0 },
         1257  +    { 0 }
         1258  +  };
         1259  +  int rc;
         1260  +  int iSub;
         1261  +  int iVal;
         1262  +
         1263  +  if( objc!=3 ){
         1264  +    Tcl_WrongNumArgs(interp, 1, objv, "OP VALUE");
         1265  +    return SQLITE_ERROR;
         1266  +  }
         1267  +  rc = Tcl_GetIndexFromObjStruct(interp, 
         1268  +      objv[1], aSub, sizeof(aSub[0]), "sub-command", 0, &iSub
         1269  +  );
         1270  +  if( rc!=TCL_OK ) return rc;
         1271  +  if( Tcl_GetIntFromObj(interp, objv[2], &iVal) ) return TCL_ERROR;
         1272  +
         1273  +  rc = sqlite3session_config(aSub[iSub].op, (void*)&iVal);
         1274  +  if( rc!=SQLITE_OK ){
         1275  +    return test_session_error(interp, rc, 0);
         1276  +  }
         1277  +  Tcl_SetObjResult(interp, Tcl_NewIntObj(iVal));
         1278  +  return TCL_OK;
         1279  +}
  1241   1280   
  1242   1281   int TestSession_Init(Tcl_Interp *interp){
  1243   1282     struct Cmd {
  1244   1283       const char *zCmd;
  1245   1284       Tcl_ObjCmdProc *xProc;
  1246   1285     } aCmd[] = {
  1247   1286       { "sqlite3session", test_sqlite3session },
................................................................................
  1250   1289       { "sqlite3changeset_concat", test_sqlite3changeset_concat },
  1251   1290       { "sqlite3changeset_apply", test_sqlite3changeset_apply },
  1252   1291       { "sqlite3changeset_apply_v2", test_sqlite3changeset_apply_v2 },
  1253   1292       { "sqlite3changeset_apply_replace_all", 
  1254   1293         test_sqlite3changeset_apply_replace_all },
  1255   1294       { "sql_exec_changeset", test_sql_exec_changeset },
  1256   1295       { "sqlite3rebaser_create", test_sqlite3rebaser_create },
         1296  +    { "sqlite3session_config", test_sqlite3session_config },
  1257   1297     };
  1258   1298     int i;
  1259   1299   
  1260   1300     for(i=0; i<sizeof(aCmd)/sizeof(struct Cmd); i++){
  1261   1301       struct Cmd *p = &aCmd[i];
  1262   1302       Tcl_CreateObjCommand(interp, p->zCmd, p->xProc, 0, 0);
  1263   1303     }
  1264   1304   
  1265   1305     return TCL_OK;
  1266   1306   }
  1267   1307   
  1268   1308   #endif /* SQLITE_TEST && SQLITE_SESSION && SQLITE_PREUPDATE_HOOK */