Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Disallow writing to, creating or dropping virtual tables from within xSync() callbacks. (CVS 3339) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
e705d232324c71738b8b25713a134617 |
User & Date: | danielk1977 2006-07-26 16:22:15.000 |
Context
2006-07-28
| ||
20:16 | Report any error which occurs in closing the database at exit. Free a couple of strings which were leaking. (CVS 3340) (check-in: 47353f62ca user: adamd tags: trunk) | |
2006-07-26
| ||
16:22 | Disallow writing to, creating or dropping virtual tables from within xSync() callbacks. (CVS 3339) (check-in: e705d23232 user: danielk1977 tags: trunk) | |
14:57 | Fix an overzealous assert() in the UTF-16 to UTF-8 converter. (CVS 3338) (check-in: 096bd8212f user: drh tags: trunk) | |
Changes
Changes to src/build.c.
︙ | ︙ | |||
18 19 20 21 22 23 24 | ** CREATE INDEX ** DROP INDEX ** creating ID lists ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** | | | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | ** CREATE INDEX ** DROP INDEX ** creating ID lists ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** ** $Id: build.c,v 1.409 2006/07/26 16:22:15 danielk1977 Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** This routine is called when a new SQL statement is beginning to ** be parsed. Initialize the pParse structure as needed. |
︙ | ︙ | |||
842 843 844 845 846 847 848 849 850 851 852 853 854 855 | ** indices. Hence, the record number for the table must be allocated ** now. */ if( !db->init.busy && (v = sqlite3GetVdbe(pParse))!=0 ){ int lbl; int fileFormat; sqlite3BeginWriteOperation(pParse, 0, iDb); /* If the file format and encoding in the database have not been set, ** set them now. */ sqlite3VdbeAddOp(v, OP_ReadCookie, iDb, 1); /* file_format */ lbl = sqlite3VdbeMakeLabel(v); sqlite3VdbeAddOp(v, OP_If, 0, lbl); | > > > > > > | 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 | ** indices. Hence, the record number for the table must be allocated ** now. */ if( !db->init.busy && (v = sqlite3GetVdbe(pParse))!=0 ){ int lbl; int fileFormat; sqlite3BeginWriteOperation(pParse, 0, iDb); #ifndef SQLITE_OMIT_VIRTUALTABLE if( isVirtual ){ sqlite3VdbeAddOp(v, OP_VBegin, 0, 0); } #endif /* If the file format and encoding in the database have not been set, ** set them now. */ sqlite3VdbeAddOp(v, OP_ReadCookie, iDb, 1); /* file_format */ lbl = sqlite3VdbeMakeLabel(v); sqlite3VdbeAddOp(v, OP_If, 0, lbl); |
︙ | ︙ | |||
1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 | ** on disk. */ v = sqlite3GetVdbe(pParse); if( v ){ Trigger *pTrigger; Db *pDb = &db->aDb[iDb]; sqlite3BeginWriteOperation(pParse, 0, iDb); /* Drop all triggers associated with the table being dropped. Code ** is generated to remove entries from sqlite_master and/or ** sqlite_temp_master if required. */ pTrigger = pTab->pTrigger; while( pTrigger ){ | > > > > > > > > > | 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 | ** on disk. */ v = sqlite3GetVdbe(pParse); if( v ){ Trigger *pTrigger; Db *pDb = &db->aDb[iDb]; sqlite3BeginWriteOperation(pParse, 0, iDb); #ifndef SQLITE_OMIT_VIRTUALTABLE if( IsVirtual(pTab) ){ Vdbe *v = sqlite3GetVdbe(pParse); if( v ){ sqlite3VdbeAddOp(v, OP_VBegin, 0, 0); } } #endif /* Drop all triggers associated with the table being dropped. Code ** is generated to remove entries from sqlite_master and/or ** sqlite_temp_master if required. */ pTrigger = pTab->pTrigger; while( pTrigger ){ |
︙ | ︙ |
Changes to src/vtab.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2006 June 10 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains code used to help implement virtual tables. ** | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* ** 2006 June 10 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains code used to help implement virtual tables. ** ** $Id: vtab.c,v 1.29 2006/07/26 16:22:15 danielk1977 Exp $ */ #ifndef SQLITE_OMIT_VIRTUALTABLE #include "sqliteInt.h" /* ** External API function used to create a new virtual-table module. */ |
︙ | ︙ | |||
390 391 392 393 394 395 396 | *pzErr = sqlite3MPrintf("no such module: %s", zModule); rc = SQLITE_ERROR; }else{ rc = vtabCallConstructor(db, pTab, pMod, pMod->pModule->xCreate, pzErr); } if( rc==SQLITE_OK && pTab->pVtab ){ | | | 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 | *pzErr = sqlite3MPrintf("no such module: %s", zModule); rc = SQLITE_ERROR; }else{ rc = vtabCallConstructor(db, pTab, pMod, pMod->pModule->xCreate, pzErr); } if( rc==SQLITE_OK && pTab->pVtab ){ rc = addToVTrans(db, pTab->pVtab); } return rc; } /* ** This function is used to set the schema of a virtual table. It is only |
︙ | ︙ | |||
508 509 510 511 512 513 514 515 516 | ** sqlite3.aVTrans array. Return the error code for the first error ** that occurs, or SQLITE_OK if all xSync operations are successful. */ int sqlite3VtabSync(sqlite3 *db, int rc2){ int i; int rc = SQLITE_OK; int rcsafety; if( rc2!=SQLITE_OK ) return rc2; rc = sqlite3SafetyOff(db); | > > > | | > > | 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 | ** sqlite3.aVTrans array. Return the error code for the first error ** that occurs, or SQLITE_OK if all xSync operations are successful. */ int sqlite3VtabSync(sqlite3 *db, int rc2){ int i; int rc = SQLITE_OK; int rcsafety; sqlite3_vtab **aVTrans = db->aVTrans; if( rc2!=SQLITE_OK ) return rc2; rc = sqlite3SafetyOff(db); db->aVTrans = 0; for(i=0; rc==SQLITE_OK && i<db->nVTrans && aVTrans[i]; i++){ sqlite3_vtab *pVtab = aVTrans[i]; int (*x)(sqlite3_vtab *); x = pVtab->pModule->xSync; if( x ){ rc = x(pVtab); } } db->aVTrans = aVTrans; rcsafety = sqlite3SafetyOn(db); if( rc==SQLITE_OK ){ rc = rcsafety; } return rc; } /* |
︙ | ︙ | |||
553 554 555 556 557 558 559 | ** not currently open, invoke the xBegin method now. ** ** If the xBegin call is successful, place the sqlite3_vtab pointer ** in the sqlite3.aVTrans array. */ int sqlite3VtabBegin(sqlite3 *db, sqlite3_vtab *pVtab){ int rc = SQLITE_OK; | | > > > > > > > > > > > > > > > | 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 | ** not currently open, invoke the xBegin method now. ** ** If the xBegin call is successful, place the sqlite3_vtab pointer ** in the sqlite3.aVTrans array. */ int sqlite3VtabBegin(sqlite3 *db, sqlite3_vtab *pVtab){ int rc = SQLITE_OK; const sqlite3_module *pModule; /* Special case: If db->aVTrans is NULL and db->nVTrans is greater ** than zero, then this function is being called from within a ** virtual module xSync() callback. It is illegal to write to ** virtual module tables in this case, so return SQLITE_LOCKED. */ if( 0==db->aVTrans && db->nVTrans>0 ){ return SQLITE_LOCKED; } if( !pVtab ){ return SQLITE_OK; } pModule = pVtab->pModule; if( pModule->xBegin ){ int i; /* If pVtab is already in the aVTrans array, return early */ for(i=0; (i<db->nVTrans) && 0!=db->aVTrans[i]; i++){ if( db->aVTrans[i]==pVtab ){ return SQLITE_OK; } } |
︙ | ︙ |
Changes to test/vtab7.test.
︙ | ︙ | |||
8 9 10 11 12 13 14 | # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The focus # of this test is reading and writing to the database from within a # virtual table xSync() callback. # | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The focus # of this test is reading and writing to the database from within a # virtual table xSync() callback. # # $Id: vtab7.test,v 1.2 2006/07/26 16:22:16 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl ifcapable !vtab { finish_test return |
︙ | ︙ | |||
151 152 153 154 155 156 157 158 159 160 161 162 163 | # execsql { INSERT INTO log VALUES('hello') } # } # catchsql { # INSERT INTO abc2 VALUES(1, 2, 3); # } # } {1 {library routine called out of sequence}} trace remove variable ::echo_module write echo_module_trace unset -nocomplain ::callbacks finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 | # execsql { INSERT INTO log VALUES('hello') } # } # catchsql { # INSERT INTO abc2 VALUES(1, 2, 3); # } # } {1 {library routine called out of sequence}} # These tests, vtab7-4.*, test that an SQLITE_LOCKED error is returned # if an attempt to write to a virtual module table or create a new # virtual table from within an xSync() callback. do_test vtab7-4.1 { execsql { CREATE TABLE def(d, e, f); CREATE VIRTUAL TABLE def2 USING echo(def); } set ::callbacks(xSync,abc) { set ::error [catchsql { INSERT INTO def2 VALUES(1, 2, 3) }] } execsql { INSERT INTO abc2 VALUES(1, 2, 3); } set ::error } {1 {database table is locked}} do_test vtab7-4.2 { set ::callbacks(xSync,abc) { set ::error [catchsql { CREATE VIRTUAL TABLE def3 USING echo(def) }] } execsql { INSERT INTO abc2 VALUES(1, 2, 3); } set ::error } {1 {database table is locked}} do_test vtab7-4.3 { set ::callbacks(xSync,abc) { set ::error [catchsql { DROP TABLE def2 }] } execsql { INSERT INTO abc2 VALUES(1, 2, 3); SELECT name FROM sqlite_master ORDER BY name; } set ::error } {1 {database table is locked}} trace remove variable ::echo_module write echo_module_trace unset -nocomplain ::callbacks finish_test |