/ Check-in [a393bbb9]
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:Fix corner cases in the WITHOUT ROWID virtual table logic.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | without-rowid-vtab
Files: files | file ages | folders
SHA1: a393bbb972660c1ffcdda923d0f3564ecfcd2f0a
User & Date: drh 2016-06-02 16:22:53
Context
2016-06-02
17:44
Add the data= parameter to the CSV virtual table extension. check-in: 76919104 user: drh tags: without-rowid-vtab
16:22
Fix corner cases in the WITHOUT ROWID virtual table logic. check-in: a393bbb9 user: drh tags: without-rowid-vtab
2016-05-31
21:18
An experimental branch with code that allows virtual tables to be declared as WITHOUT ROWID tables. This might be useful for virtual tables that model external data sources that do not have a convenient way of computing a unique rowid. The current check-in almost works, but there are still serious issues. check-in: 49638f18 user: drh tags: without-rowid-vtab
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/build.c.

   603    603                            db->lookaside.nOut : 0 );
   604    604   
   605    605     /* Delete all indices associated with this table. */
   606    606     for(pIndex = pTable->pIndex; pIndex; pIndex=pNext){
   607    607       pNext = pIndex->pNext;
   608    608       assert( pIndex->pSchema==pTable->pSchema
   609    609            || (IsVirtual(pTable) && pIndex->idxType!=SQLITE_IDXTYPE_APPDEF) );
   610         -    if( pIndex->idxType==SQLITE_IDXTYPE_APPDEF
   611         -     && (!db || db->pnBytesFreed==0)
   612         -    ){
          610  +    if( (db==0 || db->pnBytesFreed==0) && !IsVirtual(pTable) ){
   613    611         char *zName = pIndex->zName; 
   614    612         TESTONLY ( Index *pOld = ) sqlite3HashInsert(
   615    613            &pIndex->pSchema->idxHash, zName, 0
   616    614         );
   617    615         assert( db==0 || sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) );
   618    616         assert( pOld==pIndex || pOld==0 );
   619    617       }
................................................................................
  1714   1712       pList = sqlite3ExprListAppend(pParse, 0, 
  1715   1713                     sqlite3ExprAlloc(db, TK_ID, &ipkToken, 0));
  1716   1714       if( pList==0 ) return;
  1717   1715       pList->a[0].sortOrder = pParse->iPkSortOrder;
  1718   1716       assert( pParse->pNewTable==pTab );
  1719   1717       sqlite3CreateIndex(pParse, 0, 0, 0, pList, pTab->keyConf, 0, 0, 0, 0,
  1720   1718                          SQLITE_IDXTYPE_PRIMARYKEY);
         1719  +    if( db->mallocFailed ) return;
  1721   1720       pPk = sqlite3PrimaryKeyIndex(pTab);
  1722   1721       pTab->iPKey = -1;
  1723   1722     }else{
  1724   1723       pPk = sqlite3PrimaryKeyIndex(pTab);
  1725   1724   
  1726   1725       /* Bypass the creation of the PRIMARY KEY btree and the sqlite_master
  1727   1726       ** table entry. This is only required if currently generating VDBE
................................................................................
  3274   3273               sqlite3ErrorMsg(pParse, 
  3275   3274                   "conflicting ON CONFLICT clauses specified", 0);
  3276   3275             }
  3277   3276             if( pIdx->onError==OE_Default ){
  3278   3277               pIdx->onError = pIndex->onError;
  3279   3278             }
  3280   3279           }
         3280  +        if( idxType==SQLITE_IDXTYPE_PRIMARYKEY ) pIdx->idxType = idxType;
  3281   3281           goto exit_create_index;
  3282   3282         }
  3283   3283       }
  3284   3284     }
  3285   3285   
  3286   3286     /* Link the new Index structure to its table and to the other
  3287   3287     ** in-memory database structures. 
  3288   3288     */
  3289   3289     assert( pParse->nErr==0 );
  3290         -  if( db->init.busy ){
         3290  +  if( db->init.busy && !IN_DECLARE_VTAB ){
  3291   3291       Index *p;
  3292   3292       assert( sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) );
  3293   3293       p = sqlite3HashInsert(&pIndex->pSchema->idxHash, 
  3294   3294                             pIndex->zName, pIndex);
  3295   3295       if( p ){
  3296   3296         assert( p==pIndex );  /* Malloc must have failed */
  3297   3297         sqlite3OomFault(db);

Changes to src/vtab.c.

   751    751        && pParse->pNewTable
   752    752        && !db->mallocFailed
   753    753        && !pParse->pNewTable->pSelect
   754    754        && (pParse->pNewTable->tabFlags & TF_Virtual)==0
   755    755       ){
   756    756         if( !pTab->aCol ){
   757    757           Table *pNew = pParse->pNewTable;
          758  +        Index *pIdx;
   758    759           pTab->aCol = pNew->aCol;
   759    760           pTab->nCol = pNew->nCol;
   760    761           pTab->tabFlags |= pNew->tabFlags & TF_WithoutRowid;
   761         -        pTab->pIndex = pNew->pIndex;
   762    762           pNew->nCol = 0;
   763    763           pNew->aCol = 0;
   764         -        pNew->pIndex = 0;
          764  +        assert( pTab->pIndex==0 );
          765  +        pIdx = pNew->pIndex;
          766  +        if( pIdx ){
          767  +          assert( pIdx->pNext==0 );
          768  +          pTab->pIndex = pIdx;
          769  +          pNew->pIndex = 0;
          770  +          pIdx->pTable = pTab;
          771  +        }
   765    772         }
   766    773         pCtx->bDeclared = 1;
   767    774       }else{
   768    775         sqlite3ErrorWithMsg(db, SQLITE_ERROR, (zErr ? "%s" : 0), zErr);
   769    776         sqlite3DbFree(db, zErr);
   770    777         rc = SQLITE_ERROR;
   771    778       }