Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Verify that the sqlite_sequence table exists and is in approximately the correct format prior to using it to process an autoincrement table. Fix for ticket [d8dc2b3a58cd5dc2918a1d4a]. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
e199e859ace4f8381c6380175206e7a2 |
User & Date: | drh 2018-05-23 16:50:21.007 |
Context
2018-05-23
| ||
17:53 | Remove a branch that is no longer used due to the fix to the sqlite_sequence schema problem, ticket [d8dc2b3a58cd5dc2918a1d4acbba4676a23ada4c] (check-in: 066742692a user: drh tags: trunk) | |
16:50 | Verify that the sqlite_sequence table exists and is in approximately the correct format prior to using it to process an autoincrement table. Fix for ticket [d8dc2b3a58cd5dc2918a1d4a]. (check-in: e199e859ac user: drh tags: trunk) | |
2018-05-18
| ||
17:58 | Add support for auxiliary columns to the rtree extension. (check-in: c6071ac99c user: drh tags: trunk) | |
Changes
Changes to src/insert.c.
︙ | ︙ | |||
222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 | */ static int autoIncBegin( Parse *pParse, /* Parsing context */ int iDb, /* Index of the database holding pTab */ Table *pTab /* The table we are writing to */ ){ int memId = 0; /* Register holding maximum rowid */ if( (pTab->tabFlags & TF_Autoincrement)!=0 && (pParse->db->mDbFlags & DBFLAG_Vacuum)==0 ){ Parse *pToplevel = sqlite3ParseToplevel(pParse); AutoincInfo *pInfo; pInfo = pToplevel->pAinc; while( pInfo && pInfo->pTab!=pTab ){ pInfo = pInfo->pNext; } if( pInfo==0 ){ pInfo = sqlite3DbMallocRawNN(pParse->db, sizeof(*pInfo)); if( pInfo==0 ) return 0; pInfo->pNext = pToplevel->pAinc; | > > > > > > > > > > > > > > > | 222 223 224 225 226 227 228 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 | */ static int autoIncBegin( Parse *pParse, /* Parsing context */ int iDb, /* Index of the database holding pTab */ Table *pTab /* The table we are writing to */ ){ int memId = 0; /* Register holding maximum rowid */ assert( pParse->db->aDb[iDb].pSchema!=0 ); if( (pTab->tabFlags & TF_Autoincrement)!=0 && (pParse->db->mDbFlags & DBFLAG_Vacuum)==0 ){ Parse *pToplevel = sqlite3ParseToplevel(pParse); AutoincInfo *pInfo; Table *pSeqTab = pParse->db->aDb[iDb].pSchema->pSeqTab; /* Verify that the sqlite_sequence table exists and is an ordinary ** rowid table with exactly two columns. ** Ticket d8dc2b3a58cd5dc2918a1d4acb 2018-05-23 */ if( pSeqTab==0 || !HasRowid(pSeqTab) || IsVirtual(pSeqTab) || pSeqTab->nCol!=2 ){ pParse->nErr++; pParse->rc = SQLITE_CORRUPT_SEQUENCE; return 0; } pInfo = pToplevel->pAinc; while( pInfo && pInfo->pTab!=pTab ){ pInfo = pInfo->pNext; } if( pInfo==0 ){ pInfo = sqlite3DbMallocRawNN(pParse->db, sizeof(*pInfo)); if( pInfo==0 ) return 0; pInfo->pNext = pToplevel->pAinc; |
︙ | ︙ |
Changes to src/sqlite.h.in.
︙ | ︙ | |||
507 508 509 510 511 512 513 514 515 516 517 518 519 520 | #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) #define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8)) #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8)) #define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8)) #define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8)) #define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8)) #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8)) #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8)) #define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8)) #define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8)) #define SQLITE_READONLY_DBMOVED (SQLITE_READONLY | (4<<8)) #define SQLITE_READONLY_CANTINIT (SQLITE_READONLY | (5<<8)) #define SQLITE_READONLY_DIRECTORY (SQLITE_READONLY | (6<<8)) #define SQLITE_ABORT_ROLLBACK (SQLITE_ABORT | (2<<8)) | > | 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 | #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) #define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8)) #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8)) #define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8)) #define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8)) #define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8)) #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8)) #define SQLITE_CORRUPT_SEQUENCE (SQLITE_CORRUPT | (2<<8)) #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8)) #define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8)) #define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8)) #define SQLITE_READONLY_DBMOVED (SQLITE_READONLY | (4<<8)) #define SQLITE_READONLY_CANTINIT (SQLITE_READONLY | (5<<8)) #define SQLITE_READONLY_DIRECTORY (SQLITE_READONLY | (6<<8)) #define SQLITE_ABORT_ROLLBACK (SQLITE_ABORT | (2<<8)) |
︙ | ︙ |
Changes to test/autoinc.test.
︙ | ︙ | |||
679 680 681 682 683 684 685 686 687 | # do_execsql_test autoinc-11.1 { CREATE TABLE t11(a INTEGER PRIMARY KEY AUTOINCREMENT,b UNIQUE); INSERT INTO t11(a,b) VALUES(2,3),(5,6),(4,3),(1,2) ON CONFLICT(b) DO UPDATE SET a=a+1000; SELECT seq FROM sqlite_sequence WHERE name='t11'; } {5} finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 | # do_execsql_test autoinc-11.1 { CREATE TABLE t11(a INTEGER PRIMARY KEY AUTOINCREMENT,b UNIQUE); INSERT INTO t11(a,b) VALUES(2,3),(5,6),(4,3),(1,2) ON CONFLICT(b) DO UPDATE SET a=a+1000; SELECT seq FROM sqlite_sequence WHERE name='t11'; } {5} # 2018-05-23 ticket d8dc2b3a58cd5dc2918a1d4acbba4676a23ada4c # Does not crash if the sqlite_sequence table schema is missing # or corrupt. # do_test autoinc-12.1 { db close forcedelete test.db sqlite3 db test.db db eval { CREATE TABLE fake_sequence(name TEXT PRIMARY KEY,seq) WITHOUT ROWID; PRAGMA writable_schema=on; UPDATE sqlite_master SET sql=replace(sql,'fake_','sqlite_'), name='sqlite_sequence', tbl_name='sqlite_sequence' WHERE name='fake_sequence'; } db close sqlite3 db test.db set res [catch {db eval { CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b TEXT); INSERT INTO t1(b) VALUES('one'); }} msg] lappend res $msg } {1 {database disk image is malformed}} do_test autoinc-12.2 { db close forcedelete test.db sqlite3 db test.db db eval { CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b TEXT); INSERT INTO t1(b) VALUES('one'); PRAGMA writable_schema=on; UPDATE sqlite_master SET sql=replace(sql,'sqlite_','x_'), name='x_sequence', tbl_name='x_sequence' WHERE name='sqlite_sequence'; } db close sqlite3 db test.db set res [catch {db eval { INSERT INTO t1(b) VALUES('two'); }} msg] lappend res $msg } {1 {database disk image is malformed}} do_test autoinc-12.3 { db close forcedelete test.db sqlite3 db test.db db eval { CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b TEXT); INSERT INTO t1(b) VALUES('one'); PRAGMA writable_schema=on; UPDATE sqlite_master SET sql='CREATE VIRTUAL TABLE sqlite_sequence USING sqlite_dbpage' WHERE name='sqlite_sequence'; } db close sqlite3 db test.db set res [catch {db eval { INSERT INTO t1(b) VALUES('two'); }} msg] lappend res $msg } {1 {database disk image is malformed}} do_test autoinc-12.4 { db close forcedelete test.db sqlite3 db test.db db eval { CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b TEXT); INSERT INTO t1(b) VALUES('one'); CREATE TABLE fake(name TEXT PRIMARY KEY,seq) WITHOUT ROWID; } set root1 [db one {SELECT rootpage FROM sqlite_master WHERE name='sqlite_sequence'}] set root2 [db one {SELECT rootpage FROM sqlite_master WHERE name='fake'}] db eval { PRAGMA writable_schema=on; UPDATE sqlite_master SET rootpage=$root2 WHERE name='sqlite_sequence'; UPDATE sqlite_master SET rootpage=$root1 WHERE name='fake'; } db close sqlite3 db test.db set res [catch {db eval { INSERT INTO t1(b) VALUES('two'); }} msg] lappend res $msg } {1 {database disk image is malformed}} breakpoint do_test autoinc-12.5 { db close forcedelete test.db sqlite3 db test.db db eval { CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b TEXT); INSERT INTO t1(b) VALUES('one'); PRAGMA writable_schema=on; UPDATE sqlite_master SET sql='CREATE TABLE sqlite_sequence(x)' WHERE name='sqlite_sequence'; } db close sqlite3 db test.db set res [catch {db eval { INSERT INTO t1(b) VALUES('two'); }} msg] lappend res $msg } {1 {database disk image is malformed}} do_test autoinc-12.6 { db close forcedelete test.db sqlite3 db test.db db eval { CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b TEXT); INSERT INTO t1(b) VALUES('one'); PRAGMA writable_schema=on; UPDATE sqlite_master SET sql='CREATE TABLE sqlite_sequence(x,y INTEGER PRIMARY KEY)' WHERE name='sqlite_sequence'; } db close sqlite3 db test.db set res [catch {db eval { INSERT INTO t1(b) VALUES('two'),('three'),('four'); INSERT INTO t1(b) VALUES('five'); PRAGMA integrity_check; }} msg] lappend res $msg } {0 ok} do_test autoinc-12.7 { db close forcedelete test.db sqlite3 db test.db db eval { CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b TEXT); INSERT INTO t1(b) VALUES('one'); PRAGMA writable_schema=on; UPDATE sqlite_master SET sql='CREATE TABLE sqlite_sequence(y INTEGER PRIMARY KEY,x)' WHERE name='sqlite_sequence'; } db close sqlite3 db test.db set res [catch {db eval { INSERT INTO t1(b) VALUES('two'),('three'),('four'); INSERT INTO t1(b) VALUES('five'); PRAGMA integrity_check; }} msg] lappend res $msg } {0 ok} finish_test |