OLD | NEW |
1 /* | 1 /* |
2 ** 2006 June 10 | 2 ** 2006 June 10 |
3 ** | 3 ** |
4 ** The author disclaims copyright to this source code. In place of | 4 ** The author disclaims copyright to this source code. In place of |
5 ** a legal notice, here is a blessing: | 5 ** a legal notice, here is a blessing: |
6 ** | 6 ** |
7 ** May you do good and not evil. | 7 ** May you do good and not evil. |
8 ** May you find forgiveness for yourself and forgive others. | 8 ** May you find forgiveness for yourself and forgive others. |
9 ** May you share freely, never taking more than you give. | 9 ** May you share freely, never taking more than you give. |
10 ** | 10 ** |
11 ************************************************************************* | 11 ************************************************************************* |
12 ** This file contains code used to help implement virtual tables. | 12 ** This file contains code used to help implement virtual tables. |
13 ** | |
14 ** $Id: vtab.c,v 1.94 2009/08/08 18:01:08 drh Exp $ | |
15 */ | 13 */ |
16 #ifndef SQLITE_OMIT_VIRTUALTABLE | 14 #ifndef SQLITE_OMIT_VIRTUALTABLE |
17 #include "sqliteInt.h" | 15 #include "sqliteInt.h" |
18 | 16 |
19 /* | 17 /* |
20 ** The actual function that does the work of creating a new module. | 18 ** The actual function that does the work of creating a new module. |
21 ** This function implements the sqlite3_create_module() and | 19 ** This function implements the sqlite3_create_module() and |
22 ** sqlite3_create_module_v2() interfaces. | 20 ** sqlite3_create_module_v2() interfaces. |
23 */ | 21 */ |
24 static int createModule( | 22 static int createModule( |
(...skipping 18 matching lines...) Expand all Loading... |
43 pMod->pAux = pAux; | 41 pMod->pAux = pAux; |
44 pMod->xDestroy = xDestroy; | 42 pMod->xDestroy = xDestroy; |
45 pDel = (Module *)sqlite3HashInsert(&db->aModule, zCopy, nName, (void*)pMod); | 43 pDel = (Module *)sqlite3HashInsert(&db->aModule, zCopy, nName, (void*)pMod); |
46 if( pDel && pDel->xDestroy ){ | 44 if( pDel && pDel->xDestroy ){ |
47 pDel->xDestroy(pDel->pAux); | 45 pDel->xDestroy(pDel->pAux); |
48 } | 46 } |
49 sqlite3DbFree(db, pDel); | 47 sqlite3DbFree(db, pDel); |
50 if( pDel==pMod ){ | 48 if( pDel==pMod ){ |
51 db->mallocFailed = 1; | 49 db->mallocFailed = 1; |
52 } | 50 } |
53 sqlite3ResetInternalSchema(db, 0); | 51 sqlite3ResetInternalSchema(db, -1); |
54 }else if( xDestroy ){ | 52 }else if( xDestroy ){ |
55 xDestroy(pAux); | 53 xDestroy(pAux); |
56 } | 54 } |
57 rc = sqlite3ApiExit(db, SQLITE_OK); | 55 rc = sqlite3ApiExit(db, SQLITE_OK); |
58 sqlite3_mutex_leave(db->mutex); | 56 sqlite3_mutex_leave(db->mutex); |
59 return rc; | 57 return rc; |
60 } | 58 } |
61 | 59 |
62 | 60 |
63 /* | 61 /* |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
118 sqlite3 *db = pVTab->db; | 116 sqlite3 *db = pVTab->db; |
119 | 117 |
120 assert( db ); | 118 assert( db ); |
121 assert( pVTab->nRef>0 ); | 119 assert( pVTab->nRef>0 ); |
122 assert( sqlite3SafetyCheckOk(db) ); | 120 assert( sqlite3SafetyCheckOk(db) ); |
123 | 121 |
124 pVTab->nRef--; | 122 pVTab->nRef--; |
125 if( pVTab->nRef==0 ){ | 123 if( pVTab->nRef==0 ){ |
126 sqlite3_vtab *p = pVTab->pVtab; | 124 sqlite3_vtab *p = pVTab->pVtab; |
127 if( p ){ | 125 if( p ){ |
128 #ifdef SQLITE_DEBUG | 126 p->pModule->xDisconnect(p); |
129 if( pVTab->db->magic==SQLITE_MAGIC_BUSY ){ | |
130 (void)sqlite3SafetyOff(db); | |
131 p->pModule->xDisconnect(p); | |
132 (void)sqlite3SafetyOn(db); | |
133 } else | |
134 #endif | |
135 { | |
136 p->pModule->xDisconnect(p); | |
137 } | |
138 } | 127 } |
139 sqlite3DbFree(db, pVTab); | 128 sqlite3DbFree(db, pVTab); |
140 } | 129 } |
141 } | 130 } |
142 | 131 |
143 /* | 132 /* |
144 ** Table p is a virtual table. This function moves all elements in the | 133 ** Table p is a virtual table. This function moves all elements in the |
145 ** p->pVTable list to the sqlite3.pDisconnect lists of their associated | 134 ** p->pVTable list to the sqlite3.pDisconnect lists of their associated |
146 ** database connections to be disconnected at the next opportunity. | 135 ** database connections to be disconnected at the next opportunity. |
147 ** Except, if argument db is not NULL, then the entry associated with | 136 ** Except, if argument db is not NULL, then the entry associated with |
148 ** connection db is left in the p->pVTable list. | 137 ** connection db is left in the p->pVTable list. |
149 */ | 138 */ |
150 static VTable *vtabDisconnectAll(sqlite3 *db, Table *p){ | 139 static VTable *vtabDisconnectAll(sqlite3 *db, Table *p){ |
151 VTable *pRet = 0; | 140 VTable *pRet = 0; |
152 VTable *pVTable = p->pVTable; | 141 VTable *pVTable = p->pVTable; |
153 p->pVTable = 0; | 142 p->pVTable = 0; |
154 | 143 |
155 /* Assert that the mutex (if any) associated with the BtShared database | 144 /* Assert that the mutex (if any) associated with the BtShared database |
156 ** that contains table p is held by the caller. See header comments | 145 ** that contains table p is held by the caller. See header comments |
157 ** above function sqlite3VtabUnlockList() for an explanation of why | 146 ** above function sqlite3VtabUnlockList() for an explanation of why |
158 ** this makes it safe to access the sqlite3.pDisconnect list of any | 147 ** this makes it safe to access the sqlite3.pDisconnect list of any |
159 ** database connection that may have an entry in the p->pVTable list. */ | 148 ** database connection that may have an entry in the p->pVTable list. |
160 assert( db==0 || | 149 */ |
161 sqlite3BtreeHoldsMutex(db->aDb[sqlite3SchemaToIndex(db, p->pSchema)].pBt) | 150 assert( db==0 || sqlite3SchemaMutexHeld(db, 0, p->pSchema) ); |
162 ); | |
163 | 151 |
164 while( pVTable ){ | 152 while( pVTable ){ |
165 sqlite3 *db2 = pVTable->db; | 153 sqlite3 *db2 = pVTable->db; |
166 VTable *pNext = pVTable->pNext; | 154 VTable *pNext = pVTable->pNext; |
167 assert( db2 ); | 155 assert( db2 ); |
168 if( db2==db ){ | 156 if( db2==db ){ |
169 pRet = pVTable; | 157 pRet = pVTable; |
170 p->pVTable = pRet; | 158 p->pVTable = pRet; |
171 pRet->pNext = 0; | 159 pRet->pNext = 0; |
172 }else{ | 160 }else{ |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
225 ** | 213 ** |
226 ** Since it is a virtual-table, the Table structure contains a pointer | 214 ** Since it is a virtual-table, the Table structure contains a pointer |
227 ** to the head of a linked list of VTable structures. Each VTable | 215 ** to the head of a linked list of VTable structures. Each VTable |
228 ** structure is associated with a single sqlite3* user of the schema. | 216 ** structure is associated with a single sqlite3* user of the schema. |
229 ** The reference count of the VTable structure associated with database | 217 ** The reference count of the VTable structure associated with database |
230 ** connection db is decremented immediately (which may lead to the | 218 ** connection db is decremented immediately (which may lead to the |
231 ** structure being xDisconnected and free). Any other VTable structures | 219 ** structure being xDisconnected and free). Any other VTable structures |
232 ** in the list are moved to the sqlite3.pDisconnect list of the associated | 220 ** in the list are moved to the sqlite3.pDisconnect list of the associated |
233 ** database connection. | 221 ** database connection. |
234 */ | 222 */ |
235 void sqlite3VtabClear(Table *p){ | 223 void sqlite3VtabClear(sqlite3 *db, Table *p){ |
236 vtabDisconnectAll(0, p); | 224 if( !db || db->pnBytesFreed==0 ) vtabDisconnectAll(0, p); |
237 if( p->azModuleArg ){ | 225 if( p->azModuleArg ){ |
238 int i; | 226 int i; |
239 for(i=0; i<p->nModuleArg; i++){ | 227 for(i=0; i<p->nModuleArg; i++){ |
240 sqlite3DbFree(p->dbMem, p->azModuleArg[i]); | 228 sqlite3DbFree(db, p->azModuleArg[i]); |
241 } | 229 } |
242 sqlite3DbFree(p->dbMem, p->azModuleArg); | 230 sqlite3DbFree(db, p->azModuleArg); |
243 } | 231 } |
244 } | 232 } |
245 | 233 |
246 /* | 234 /* |
247 ** Add a new module argument to pTable->azModuleArg[]. | 235 ** Add a new module argument to pTable->azModuleArg[]. |
248 ** The string is not copied - the pointer is stored. The | 236 ** The string is not copied - the pointer is stored. The |
249 ** string will be freed automatically when the table is | 237 ** string will be freed automatically when the table is |
250 ** deleted. | 238 ** deleted. |
251 */ | 239 */ |
252 static void addModuleArgument(sqlite3 *db, Table *pTable, char *zArg){ | 240 static void addModuleArgument(sqlite3 *db, Table *pTable, char *zArg){ |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
375 pTab->zName, | 363 pTab->zName, |
376 pTab->zName, | 364 pTab->zName, |
377 zStmt, | 365 zStmt, |
378 pParse->regRowid | 366 pParse->regRowid |
379 ); | 367 ); |
380 sqlite3DbFree(db, zStmt); | 368 sqlite3DbFree(db, zStmt); |
381 v = sqlite3GetVdbe(pParse); | 369 v = sqlite3GetVdbe(pParse); |
382 sqlite3ChangeCookie(pParse, iDb); | 370 sqlite3ChangeCookie(pParse, iDb); |
383 | 371 |
384 sqlite3VdbeAddOp2(v, OP_Expire, 0, 0); | 372 sqlite3VdbeAddOp2(v, OP_Expire, 0, 0); |
385 zWhere = sqlite3MPrintf(db, "name='%q'", pTab->zName); | 373 zWhere = sqlite3MPrintf(db, "name='%q' AND type='table'", pTab->zName); |
386 sqlite3VdbeAddOp4(v, OP_ParseSchema, iDb, 1, 0, zWhere, P4_DYNAMIC); | 374 sqlite3VdbeAddOp4(v, OP_ParseSchema, iDb, 0, 0, zWhere, P4_DYNAMIC); |
387 sqlite3VdbeAddOp4(v, OP_VCreate, iDb, 0, 0, | 375 sqlite3VdbeAddOp4(v, OP_VCreate, iDb, 0, 0, |
388 pTab->zName, sqlite3Strlen30(pTab->zName) + 1); | 376 pTab->zName, sqlite3Strlen30(pTab->zName) + 1); |
389 } | 377 } |
390 | 378 |
391 /* If we are rereading the sqlite_master table create the in-memory | 379 /* If we are rereading the sqlite_master table create the in-memory |
392 ** record of the table. The xConnect() method is not called until | 380 ** record of the table. The xConnect() method is not called until |
393 ** the first time the virtual table is used in an SQL statement. This | 381 ** the first time the virtual table is used in an SQL statement. This |
394 ** allows a schema that contains virtual tables to be loaded before | 382 ** allows a schema that contains virtual tables to be loaded before |
395 ** the required virtual table implementations are registered. */ | 383 ** the required virtual table implementations are registered. */ |
396 else { | 384 else { |
397 Table *pOld; | 385 Table *pOld; |
398 Schema *pSchema = pTab->pSchema; | 386 Schema *pSchema = pTab->pSchema; |
399 const char *zName = pTab->zName; | 387 const char *zName = pTab->zName; |
400 int nName = sqlite3Strlen30(zName); | 388 int nName = sqlite3Strlen30(zName); |
| 389 assert( sqlite3SchemaMutexHeld(db, 0, pSchema) ); |
401 pOld = sqlite3HashInsert(&pSchema->tblHash, zName, nName, pTab); | 390 pOld = sqlite3HashInsert(&pSchema->tblHash, zName, nName, pTab); |
402 if( pOld ){ | 391 if( pOld ){ |
403 db->mallocFailed = 1; | 392 db->mallocFailed = 1; |
404 assert( pTab==pOld ); /* Malloc must have failed inside HashInsert() */ | 393 assert( pTab==pOld ); /* Malloc must have failed inside HashInsert() */ |
405 return; | 394 return; |
406 } | 395 } |
407 pSchema->db = pParse->db; | |
408 pParse->pNewTable = 0; | 396 pParse->pNewTable = 0; |
409 } | 397 } |
410 } | 398 } |
411 | 399 |
412 /* | 400 /* |
413 ** The parser calls this routine when it sees the first token | 401 ** The parser calls this routine when it sees the first token |
414 ** of an argument to the module name in a CREATE VIRTUAL TABLE statement. | 402 ** of an argument to the module name in a CREATE VIRTUAL TABLE statement. |
415 */ | 403 */ |
416 void sqlite3VtabArgInit(Parse *pParse){ | 404 void sqlite3VtabArgInit(Parse *pParse){ |
417 addArgumentToVtab(pParse); | 405 addArgumentToVtab(pParse); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
463 return SQLITE_NOMEM; | 451 return SQLITE_NOMEM; |
464 } | 452 } |
465 pVTable->db = db; | 453 pVTable->db = db; |
466 pVTable->pMod = pMod; | 454 pVTable->pMod = pMod; |
467 | 455 |
468 assert( !db->pVTab ); | 456 assert( !db->pVTab ); |
469 assert( xConstruct ); | 457 assert( xConstruct ); |
470 db->pVTab = pTab; | 458 db->pVTab = pTab; |
471 | 459 |
472 /* Invoke the virtual table constructor */ | 460 /* Invoke the virtual table constructor */ |
473 (void)sqlite3SafetyOff(db); | |
474 rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVTable->pVtab, &zErr); | 461 rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVTable->pVtab, &zErr); |
475 (void)sqlite3SafetyOn(db); | |
476 if( rc==SQLITE_NOMEM ) db->mallocFailed = 1; | 462 if( rc==SQLITE_NOMEM ) db->mallocFailed = 1; |
477 | 463 |
478 if( SQLITE_OK!=rc ){ | 464 if( SQLITE_OK!=rc ){ |
479 if( zErr==0 ){ | 465 if( zErr==0 ){ |
480 *pzErr = sqlite3MPrintf(db, "vtable constructor failed: %s", zModuleName); | 466 *pzErr = sqlite3MPrintf(db, "vtable constructor failed: %s", zModuleName); |
481 }else { | 467 }else { |
482 *pzErr = sqlite3MPrintf(db, "%s", zErr); | 468 *pzErr = sqlite3MPrintf(db, "%s", zErr); |
483 sqlite3DbFree(db, zErr); | 469 sqlite3_free(zErr); |
484 } | 470 } |
485 sqlite3DbFree(db, pVTable); | 471 sqlite3DbFree(db, pVTable); |
486 }else if( ALWAYS(pVTable->pVtab) ){ | 472 }else if( ALWAYS(pVTable->pVtab) ){ |
487 /* Justification of ALWAYS(): A correct vtab constructor must allocate | 473 /* Justification of ALWAYS(): A correct vtab constructor must allocate |
488 ** the sqlite3_vtab object if successful. */ | 474 ** the sqlite3_vtab object if successful. */ |
489 pVTable->pVtab->pModule = pMod->pModule; | 475 pVTable->pVtab->pModule = pMod->pModule; |
490 pVTable->nRef = 1; | 476 pVTable->nRef = 1; |
491 if( db->pVTab ){ | 477 if( db->pVTab ){ |
492 const char *zFormat = "vtable constructor did not declare schema: %s"; | 478 const char *zFormat = "vtable constructor did not declare schema: %s"; |
493 *pzErr = sqlite3MPrintf(db, zFormat, pTab->zName); | 479 *pzErr = sqlite3MPrintf(db, zFormat, pTab->zName); |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
653 | 639 |
654 int rc = SQLITE_OK; | 640 int rc = SQLITE_OK; |
655 Table *pTab; | 641 Table *pTab; |
656 char *zErr = 0; | 642 char *zErr = 0; |
657 | 643 |
658 sqlite3_mutex_enter(db->mutex); | 644 sqlite3_mutex_enter(db->mutex); |
659 pTab = db->pVTab; | 645 pTab = db->pVTab; |
660 if( !pTab ){ | 646 if( !pTab ){ |
661 sqlite3Error(db, SQLITE_MISUSE, 0); | 647 sqlite3Error(db, SQLITE_MISUSE, 0); |
662 sqlite3_mutex_leave(db->mutex); | 648 sqlite3_mutex_leave(db->mutex); |
663 return SQLITE_MISUSE; | 649 return SQLITE_MISUSE_BKPT; |
664 } | 650 } |
665 assert( (pTab->tabFlags & TF_Virtual)!=0 ); | 651 assert( (pTab->tabFlags & TF_Virtual)!=0 ); |
666 | 652 |
667 pParse = sqlite3StackAllocZero(db, sizeof(*pParse)); | 653 pParse = sqlite3StackAllocZero(db, sizeof(*pParse)); |
668 if( pParse==0 ){ | 654 if( pParse==0 ){ |
669 rc = SQLITE_NOMEM; | 655 rc = SQLITE_NOMEM; |
670 }else{ | 656 }else{ |
671 pParse->declareVtab = 1; | 657 pParse->declareVtab = 1; |
672 pParse->db = db; | 658 pParse->db = db; |
| 659 pParse->nQueryLoop = 1; |
673 | 660 |
674 if( | 661 if( SQLITE_OK==sqlite3RunParser(pParse, zCreateTable, &zErr) |
675 SQLITE_OK == sqlite3RunParser(pParse, zCreateTable, &zErr) && | 662 && pParse->pNewTable |
676 pParse->pNewTable && | 663 && !db->mallocFailed |
677 !pParse->pNewTable->pSelect && | 664 && !pParse->pNewTable->pSelect |
678 (pParse->pNewTable->tabFlags & TF_Virtual)==0 | 665 && (pParse->pNewTable->tabFlags & TF_Virtual)==0 |
679 ){ | 666 ){ |
680 if( !pTab->aCol ){ | 667 if( !pTab->aCol ){ |
681 pTab->aCol = pParse->pNewTable->aCol; | 668 pTab->aCol = pParse->pNewTable->aCol; |
682 pTab->nCol = pParse->pNewTable->nCol; | 669 pTab->nCol = pParse->pNewTable->nCol; |
683 pParse->pNewTable->nCol = 0; | 670 pParse->pNewTable->nCol = 0; |
684 pParse->pNewTable->aCol = 0; | 671 pParse->pNewTable->aCol = 0; |
685 } | 672 } |
686 db->pVTab = 0; | 673 db->pVTab = 0; |
687 } else { | 674 }else{ |
688 sqlite3Error(db, SQLITE_ERROR, zErr); | 675 sqlite3Error(db, SQLITE_ERROR, (zErr ? "%s" : 0), zErr); |
689 sqlite3DbFree(db, zErr); | 676 sqlite3DbFree(db, zErr); |
690 rc = SQLITE_ERROR; | 677 rc = SQLITE_ERROR; |
691 } | 678 } |
692 pParse->declareVtab = 0; | 679 pParse->declareVtab = 0; |
693 | 680 |
694 if( pParse->pVdbe ){ | 681 if( pParse->pVdbe ){ |
695 sqlite3VdbeFinalize(pParse->pVdbe); | 682 sqlite3VdbeFinalize(pParse->pVdbe); |
696 } | 683 } |
697 sqlite3DeleteTable(pParse->pNewTable); | 684 sqlite3DeleteTable(db, pParse->pNewTable); |
698 sqlite3StackFree(db, pParse); | 685 sqlite3StackFree(db, pParse); |
699 } | 686 } |
700 | 687 |
701 assert( (rc&0xff)==rc ); | 688 assert( (rc&0xff)==rc ); |
702 rc = sqlite3ApiExit(db, rc); | 689 rc = sqlite3ApiExit(db, rc); |
703 sqlite3_mutex_leave(db->mutex); | 690 sqlite3_mutex_leave(db->mutex); |
704 return rc; | 691 return rc; |
705 } | 692 } |
706 | 693 |
707 /* | 694 /* |
708 ** This function is invoked by the vdbe to call the xDestroy method | 695 ** This function is invoked by the vdbe to call the xDestroy method |
709 ** of the virtual table named zTab in database iDb. This occurs | 696 ** of the virtual table named zTab in database iDb. This occurs |
710 ** when a DROP TABLE is mentioned. | 697 ** when a DROP TABLE is mentioned. |
711 ** | 698 ** |
712 ** This call is a no-op if zTab is not a virtual table. | 699 ** This call is a no-op if zTab is not a virtual table. |
713 */ | 700 */ |
714 int sqlite3VtabCallDestroy(sqlite3 *db, int iDb, const char *zTab){ | 701 int sqlite3VtabCallDestroy(sqlite3 *db, int iDb, const char *zTab){ |
715 int rc = SQLITE_OK; | 702 int rc = SQLITE_OK; |
716 Table *pTab; | 703 Table *pTab; |
717 | 704 |
718 pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName); | 705 pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName); |
719 if( ALWAYS(pTab!=0 && pTab->pVTable!=0) ){ | 706 if( ALWAYS(pTab!=0 && pTab->pVTable!=0) ){ |
720 VTable *p = vtabDisconnectAll(db, pTab); | 707 VTable *p = vtabDisconnectAll(db, pTab); |
721 | 708 |
722 rc = sqlite3SafetyOff(db); | |
723 assert( rc==SQLITE_OK ); | 709 assert( rc==SQLITE_OK ); |
724 rc = p->pMod->pModule->xDestroy(p->pVtab); | 710 rc = p->pMod->pModule->xDestroy(p->pVtab); |
725 (void)sqlite3SafetyOn(db); | |
726 | 711 |
727 /* Remove the sqlite3_vtab* from the aVTrans[] array, if applicable */ | 712 /* Remove the sqlite3_vtab* from the aVTrans[] array, if applicable */ |
728 if( rc==SQLITE_OK ){ | 713 if( rc==SQLITE_OK ){ |
729 assert( pTab->pVTable==p && p->pNext==0 ); | 714 assert( pTab->pVTable==p && p->pNext==0 ); |
730 p->pVtab = 0; | 715 p->pVtab = 0; |
731 pTab->pVTable = 0; | 716 pTab->pVTable = 0; |
732 sqlite3VtabUnlock(p); | 717 sqlite3VtabUnlock(p); |
733 } | 718 } |
734 } | 719 } |
735 | 720 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
767 ** Invoke the xSync method of all virtual tables in the sqlite3.aVTrans | 752 ** Invoke the xSync method of all virtual tables in the sqlite3.aVTrans |
768 ** array. Return the error code for the first error that occurs, or | 753 ** array. Return the error code for the first error that occurs, or |
769 ** SQLITE_OK if all xSync operations are successful. | 754 ** SQLITE_OK if all xSync operations are successful. |
770 ** | 755 ** |
771 ** Set *pzErrmsg to point to a buffer that should be released using | 756 ** Set *pzErrmsg to point to a buffer that should be released using |
772 ** sqlite3DbFree() containing an error message, if one is available. | 757 ** sqlite3DbFree() containing an error message, if one is available. |
773 */ | 758 */ |
774 int sqlite3VtabSync(sqlite3 *db, char **pzErrmsg){ | 759 int sqlite3VtabSync(sqlite3 *db, char **pzErrmsg){ |
775 int i; | 760 int i; |
776 int rc = SQLITE_OK; | 761 int rc = SQLITE_OK; |
777 int rcsafety; | |
778 VTable **aVTrans = db->aVTrans; | 762 VTable **aVTrans = db->aVTrans; |
779 | 763 |
780 rc = sqlite3SafetyOff(db); | |
781 db->aVTrans = 0; | 764 db->aVTrans = 0; |
782 for(i=0; rc==SQLITE_OK && i<db->nVTrans; i++){ | 765 for(i=0; rc==SQLITE_OK && i<db->nVTrans; i++){ |
783 int (*x)(sqlite3_vtab *); | 766 int (*x)(sqlite3_vtab *); |
784 sqlite3_vtab *pVtab = aVTrans[i]->pVtab; | 767 sqlite3_vtab *pVtab = aVTrans[i]->pVtab; |
785 if( pVtab && (x = pVtab->pModule->xSync)!=0 ){ | 768 if( pVtab && (x = pVtab->pModule->xSync)!=0 ){ |
786 rc = x(pVtab); | 769 rc = x(pVtab); |
787 sqlite3DbFree(db, *pzErrmsg); | 770 sqlite3DbFree(db, *pzErrmsg); |
788 *pzErrmsg = pVtab->zErrMsg; | 771 *pzErrmsg = sqlite3DbStrDup(db, pVtab->zErrMsg); |
789 pVtab->zErrMsg = 0; | 772 sqlite3_free(pVtab->zErrMsg); |
790 } | 773 } |
791 } | 774 } |
792 db->aVTrans = aVTrans; | 775 db->aVTrans = aVTrans; |
793 rcsafety = sqlite3SafetyOn(db); | |
794 | |
795 if( rc==SQLITE_OK ){ | |
796 rc = rcsafety; | |
797 } | |
798 return rc; | 776 return rc; |
799 } | 777 } |
800 | 778 |
801 /* | 779 /* |
802 ** Invoke the xRollback method of all virtual tables in the | 780 ** Invoke the xRollback method of all virtual tables in the |
803 ** sqlite3.aVTrans array. Then clear the array itself. | 781 ** sqlite3.aVTrans array. Then clear the array itself. |
804 */ | 782 */ |
805 int sqlite3VtabRollback(sqlite3 *db){ | 783 int sqlite3VtabRollback(sqlite3 *db){ |
806 callFinaliser(db, offsetof(sqlite3_module,xRollback)); | 784 callFinaliser(db, offsetof(sqlite3_module,xRollback)); |
807 return SQLITE_OK; | 785 return SQLITE_OK; |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
953 apVtabLock = sqlite3_realloc(pToplevel->apVtabLock, n); | 931 apVtabLock = sqlite3_realloc(pToplevel->apVtabLock, n); |
954 if( apVtabLock ){ | 932 if( apVtabLock ){ |
955 pToplevel->apVtabLock = apVtabLock; | 933 pToplevel->apVtabLock = apVtabLock; |
956 pToplevel->apVtabLock[pToplevel->nVtabLock++] = pTab; | 934 pToplevel->apVtabLock[pToplevel->nVtabLock++] = pTab; |
957 }else{ | 935 }else{ |
958 pToplevel->db->mallocFailed = 1; | 936 pToplevel->db->mallocFailed = 1; |
959 } | 937 } |
960 } | 938 } |
961 | 939 |
962 #endif /* SQLITE_OMIT_VIRTUALTABLE */ | 940 #endif /* SQLITE_OMIT_VIRTUALTABLE */ |
OLD | NEW |