Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Merge recent trunk changes, and especially the PRAGMA index_info enhancement which is needed on this branch. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | est_count_pragma |
Files: | files | file ages | folders |
SHA1: |
c3570e462a41586487c4ab3bd08129af |
User & Date: | drh 2016-10-25 17:28:49.402 |
Context
2016-10-25
| ||
18:28 | Enhance faststat1.c to deal better with WITHOUT ROWID tables. (check-in: 65444f2e35 user: drh tags: est_count_pragma) | |
17:28 | Merge recent trunk changes, and especially the PRAGMA index_info enhancement which is needed on this branch. (check-in: c3570e462a user: drh tags: est_count_pragma) | |
15:39 | Enhance the "PRAGMA index_info" and "PRAGMA index_xinfo" statements so that they work on WITHOUT ROWID tables and provide information about the underlying index btree that implements the WITHOUT ROWID table. (Leaf check-in: fe49fb0313 user: drh tags: index-info-on-table) | |
13:57 | First attempt at a utility program to compute sqlite_stat1 without doing a full table scan. (check-in: 7b83581a43 user: drh tags: est_count_pragma) | |
Changes
Changes to ext/session/session1.test.
︙ | ︙ | |||
565 566 567 568 569 570 571 572 573 | breakpoint do_changeset_test 10.1.2 S " {INSERT $tblname 0 X. {} {t uvw t abc}} {DELETE $tblname 0 X. {t xyz t def} {}} " do_test 10.1.4 { S delete } {} finish_test | > > > > > > > > > > > > | 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 | breakpoint do_changeset_test 10.1.2 S " {INSERT $tblname 0 X. {} {t uvw t abc}} {DELETE $tblname 0 X. {t xyz t def} {}} " do_test 10.1.4 { S delete } {} #------------------------------------------------------------------------- # Test the effect of updating a column from 0.0 to 0.0. # reset_db do_execsql_test 11.1 { CREATE TABLE t1(a INTEGER PRIMARY KEY, b REAL); INSERT INTO t1 VALUES(1, 0.0); } do_iterator_test 11.2 * { UPDATE t1 SET b = 0.0; } { } finish_test |
Changes to src/btree.c.
︙ | ︙ | |||
4860 4861 4862 4863 4864 4865 4866 | assert( pCur->skipNext!=SQLITE_OK ); return pCur->skipNext; } sqlite3BtreeClearCursor(pCur); } if( pCur->iPage>=0 ){ | | > | | > > | | 4860 4861 4862 4863 4864 4865 4866 4867 4868 4869 4870 4871 4872 4873 4874 4875 4876 4877 4878 4879 4880 4881 4882 4883 4884 4885 4886 4887 4888 4889 4890 | assert( pCur->skipNext!=SQLITE_OK ); return pCur->skipNext; } sqlite3BtreeClearCursor(pCur); } if( pCur->iPage>=0 ){ if( pCur->iPage ){ do{ assert( pCur->apPage[pCur->iPage]!=0 ); releasePageNotNull(pCur->apPage[pCur->iPage--]); }while( pCur->iPage); goto skip_init; } }else if( pCur->pgnoRoot==0 ){ pCur->eState = CURSOR_INVALID; return SQLITE_OK; }else{ assert( pCur->iPage==(-1) ); rc = getAndInitPage(pCur->pBtree->pBt, pCur->pgnoRoot, &pCur->apPage[0], 0, pCur->curPagerFlags); if( rc!=SQLITE_OK ){ pCur->eState = CURSOR_INVALID; return rc; } pCur->iPage = 0; pCur->curIntKey = pCur->apPage[0]->intKey; } pRoot = pCur->apPage[0]; assert( pRoot->pgno==pCur->pgnoRoot ); |
︙ | ︙ | |||
4896 4897 4898 4899 4900 4901 4902 4903 4904 4905 4906 4907 4908 4909 4910 4911 4912 4913 | ** in such a way that page pRoot is linked into a second b-tree table ** (or the freelist). */ assert( pRoot->intKey==1 || pRoot->intKey==0 ); if( pRoot->isInit==0 || (pCur->pKeyInfo==0)!=pRoot->intKey ){ return SQLITE_CORRUPT_BKPT; } pCur->aiIdx[0] = 0; pCur->info.nSize = 0; pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidNKey|BTCF_ValidOvfl); if( pRoot->nCell>0 ){ pCur->eState = CURSOR_VALID; }else if( !pRoot->leaf ){ Pgno subpage; if( pRoot->pgno!=1 ) return SQLITE_CORRUPT_BKPT; subpage = get4byte(&pRoot->aData[pRoot->hdrOffset+8]); pCur->eState = CURSOR_VALID; | > > | 4899 4900 4901 4902 4903 4904 4905 4906 4907 4908 4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 | ** in such a way that page pRoot is linked into a second b-tree table ** (or the freelist). */ assert( pRoot->intKey==1 || pRoot->intKey==0 ); if( pRoot->isInit==0 || (pCur->pKeyInfo==0)!=pRoot->intKey ){ return SQLITE_CORRUPT_BKPT; } skip_init: pCur->aiIdx[0] = 0; pCur->info.nSize = 0; pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidNKey|BTCF_ValidOvfl); pRoot = pCur->apPage[0]; if( pRoot->nCell>0 ){ pCur->eState = CURSOR_VALID; }else if( !pRoot->leaf ){ Pgno subpage; if( pRoot->pgno!=1 ) return SQLITE_CORRUPT_BKPT; subpage = get4byte(&pRoot->aData[pRoot->hdrOffset+8]); pCur->eState = CURSOR_VALID; |
︙ | ︙ |
Changes to src/pragma.c.
︙ | ︙ | |||
1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 | } break; case PragTyp_INDEX_INFO: if( zRight ){ Index *pIdx; Table *pTab; pIdx = sqlite3FindIndex(db, zRight, zDb); if( pIdx ){ static const char *azCol[] = { "seqno", "cid", "name", "desc", "coll", "key" }; int i; int mx; if( pPragma->iArg ){ | > > > > | 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 | } break; case PragTyp_INDEX_INFO: if( zRight ){ Index *pIdx; Table *pTab; pIdx = sqlite3FindIndex(db, zRight, zDb); if( pIdx==0 ){ pTab = sqlite3FindTable(db, zRight, zDb); if( pTab && !HasRowid(pTab) ) pIdx = sqlite3PrimaryKeyIndex(pTab); } if( pIdx ){ static const char *azCol[] = { "seqno", "cid", "name", "desc", "coll", "key" }; int i; int mx; if( pPragma->iArg ){ |
︙ | ︙ |
Changes to src/vdbeInt.h.
︙ | ︙ | |||
426 427 428 429 430 431 432 | u8 *aRecord; /* old.* database record */ KeyInfo keyinfo; UnpackedRecord *pUnpacked; /* Unpacked version of aRecord[] */ UnpackedRecord *pNewUnpacked; /* Unpacked version of new.* record */ int iNewReg; /* Register for new.* values */ i64 iKey1; /* First key value passed to hook */ i64 iKey2; /* Second key value passed to hook */ | < > | 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 | u8 *aRecord; /* old.* database record */ KeyInfo keyinfo; UnpackedRecord *pUnpacked; /* Unpacked version of aRecord[] */ UnpackedRecord *pNewUnpacked; /* Unpacked version of new.* record */ int iNewReg; /* Register for new.* values */ i64 iKey1; /* First key value passed to hook */ i64 iKey2; /* Second key value passed to hook */ Mem *aNew; /* Array of new.* values */ Table *pTab; /* Schema object being upated */ }; /* ** Function prototypes */ void sqlite3VdbeError(Vdbe*, const char *, ...); void sqlite3VdbeFreeCursor(Vdbe *, VdbeCursor*); |
︙ | ︙ |
Changes to src/vdbeapi.c.
︙ | ︙ | |||
1706 1707 1708 1709 1710 1711 1712 1713 | } p->aRecord = aRec; } if( iIdx>=p->pUnpacked->nField ){ *ppValue = (sqlite3_value *)columnNullValue(); }else{ *ppValue = &p->pUnpacked->aMem[iIdx]; | > | | > > > > | 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 | } p->aRecord = aRec; } if( iIdx>=p->pUnpacked->nField ){ *ppValue = (sqlite3_value *)columnNullValue(); }else{ Mem *pMem = *ppValue = &p->pUnpacked->aMem[iIdx]; *ppValue = &p->pUnpacked->aMem[iIdx]; if( iIdx==p->pTab->iPKey ){ sqlite3VdbeMemSetInt64(pMem, p->iKey1); }else if( p->pTab->aCol[iIdx].affinity==SQLITE_AFF_REAL ){ if( pMem->flags & MEM_Int ){ sqlite3VdbeMemRealify(pMem); } } } preupdate_old_out: sqlite3Error(db, rc); return sqlite3ApiExit(db, rc); } |
︙ | ︙ | |||
1785 1786 1787 1788 1789 1790 1791 | } p->pNewUnpacked = pUnpack; } if( iIdx>=pUnpack->nField ){ pMem = (sqlite3_value *)columnNullValue(); }else{ pMem = &pUnpack->aMem[iIdx]; | | | | 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 | } p->pNewUnpacked = pUnpack; } if( iIdx>=pUnpack->nField ){ pMem = (sqlite3_value *)columnNullValue(); }else{ pMem = &pUnpack->aMem[iIdx]; if( iIdx==p->pTab->iPKey ){ sqlite3VdbeMemSetInt64(pMem, p->iKey2); } } }else{ /* For an UPDATE, memory cell (p->iNewReg+1+iIdx) contains the required ** value. Make a copy of the cell contents and return a pointer to it. ** It is not safe to return a pointer to the memory cell itself as the ** caller may modify the value text encoding. */ assert( p->op==SQLITE_UPDATE ); if( !p->aNew ){ p->aNew = (Mem *)sqlite3DbMallocZero(db, sizeof(Mem) * p->pCsr->nField); if( !p->aNew ){ rc = SQLITE_NOMEM; goto preupdate_new_out; } } assert( iIdx>=0 && iIdx<p->pCsr->nField ); pMem = &p->aNew[iIdx]; if( pMem->flags==0 ){ if( iIdx==p->pTab->iPKey ){ sqlite3VdbeMemSetInt64(pMem, p->iKey2); }else{ rc = sqlite3VdbeMemCopy(pMem, &p->v->aMem[p->iNewReg+1+iIdx]); if( rc!=SQLITE_OK ) goto preupdate_new_out; } } } |
︙ | ︙ |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
4613 4614 4615 4616 4617 4618 4619 | preupdate.iNewReg = iReg; preupdate.keyinfo.db = db; preupdate.keyinfo.enc = ENC(db); preupdate.keyinfo.nField = pTab->nCol; preupdate.keyinfo.aSortOrder = (u8*)&fakeSortOrder; preupdate.iKey1 = iKey1; preupdate.iKey2 = iKey2; | | | 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 | preupdate.iNewReg = iReg; preupdate.keyinfo.db = db; preupdate.keyinfo.enc = ENC(db); preupdate.keyinfo.nField = pTab->nCol; preupdate.keyinfo.aSortOrder = (u8*)&fakeSortOrder; preupdate.iKey1 = iKey1; preupdate.iKey2 = iKey2; preupdate.pTab = pTab; db->pPreUpdate = &preupdate; db->xPreUpdateCallback(db->pPreUpdateArg, db, op, zDb, zTbl, iKey1, iKey2); db->pPreUpdate = 0; sqlite3DbFree(db, preupdate.aRecord); vdbeFreeUnpacked(db, preupdate.pUnpacked); vdbeFreeUnpacked(db, preupdate.pNewUnpacked); |
︙ | ︙ |
Changes to test/wal6.test.
︙ | ︙ | |||
229 230 231 232 233 234 235 236 237 238 | do_test 4.4.1 { catchsql { SELECT * FROM t1 } db2 } {0 {1 2}} do_test 4.4.2 { catchsql { SELECT * FROM t2 } db2 } {1 {database disk image is malformed}} finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 | do_test 4.4.1 { catchsql { SELECT * FROM t1 } db2 } {0 {1 2}} do_test 4.4.2 { catchsql { SELECT * FROM t2 } db2 } {1 {database disk image is malformed}} #------------------------------------------------------------------------- # Confirm that it is possible to get an SQLITE_BUSY_SNAPSHOT error from # "BEGIN EXCLUSIVE" if the connection already has an open read-transaction. # reset_db sqlite3 db2 test.db do_execsql_test 5.1 { PRAGMA journal_mode = wal; CREATE TABLE t1(x, y); INSERT INTO t1 VALUES(1, 2); INSERT INTO t1 VALUES(3, 4); } {wal} do_test 5.2 { set res [list] db eval { SELECT * FROM t1 } { if {$x==1} { db2 eval { INSERT INTO t1 VALUES(5, 6) } } if {$x==3} { set res [catchsql {BEGIN EXCLUSIVE}] lappend res [sqlite3_extended_errcode db] } } set res } {1 {database is locked} SQLITE_BUSY_SNAPSHOT} finish_test |
Changes to test/without_rowid1.test.
︙ | ︙ | |||
323 324 325 326 327 328 329 330 331 332 | } {1 {CHECK constraint failed: t70a}} do_catchsql_test 7.3 { CREATE TABLE t70b( a INT CHECK( rowid!=33 ), b TEXT PRIMARY KEY ) WITHOUT ROWID; } {1 {no such column: rowid}} finish_test | > > > > > > > > > > > > > > > > > > > | 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 | } {1 {CHECK constraint failed: t70a}} do_catchsql_test 7.3 { CREATE TABLE t70b( a INT CHECK( rowid!=33 ), b TEXT PRIMARY KEY ) WITHOUT ROWID; } {1 {no such column: rowid}} # The PRAGMA index_info and index_xinfo pragmas work on # WITHOUT ROWID tables too, but not on rowid tables. # do_execsql_test 8.1 { CREATE TABLE t80a(a TEXT, b INT, c BLOB, PRIMARY KEY(c,b)); PRAGMA index_info(t80a); } {} do_execsql_test 8.2 { PRAGMA index_xinfo(t80a); } {} do_execsql_test 8.3 { CREATE TABLE t80b(a TEXT, b INT, c BLOB, PRIMARY KEY(c,b)) WITHOUT ROWID; PRAGMA index_info(t80b); } {0 2 c 1 1 b} do_execsql_test 8.4 { PRAGMA index_xinfo(t80b); } {0 2 c 0 BINARY 1 1 1 b 0 BINARY 1 2 0 a 0 BINARY 0} finish_test |