Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Transactions commit on the last sqlite3_step(), not on sqlite3_finalize(). This allows the sqlite3_step() to return SQLITE_BUSY if the commit is blocked by a lock. Ticket #885. (CVS 1928) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
d1b29156558f1c576002cdb2544dffaa |
User & Date: | drh 2004-09-02 14:57:08.000 |
Context
2004-09-02
| ||
15:14 | Fix a problem with EXPLAIN on pragmas that return single integer values. Ticket #886 (CVS 1929) (check-in: 8ce3d730b0 user: drh tags: trunk) | |
14:57 | Transactions commit on the last sqlite3_step(), not on sqlite3_finalize(). This allows the sqlite3_step() to return SQLITE_BUSY if the commit is blocked by a lock. Ticket #885. (CVS 1928) (check-in: d1b2915655 user: drh tags: trunk) | |
2004-09-01
| ||
16:12 | Work around a bug in the Borland C++ compiler. Ticket #881. (CVS 1927) (check-in: 18af6ba580 user: drh tags: trunk) | |
Changes
Changes to src/main.c.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** ** $Id: main.c,v 1.257 2004/09/02 14:57:08 drh Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> /* ** The following constant value is used by the SQLITE_BIGENDIAN and |
︙ | ︙ | |||
517 518 519 520 521 522 523 | for(i=0; i<db->nDb; i++){ if( db->aDb[i].pBt ){ sqlite3BtreeRollback(db->aDb[i].pBt); db->aDb[i].inTrans = 0; } } sqlite3ResetInternalSchema(db, 0); | < | 517 518 519 520 521 522 523 524 525 526 527 528 529 530 | for(i=0; i<db->nDb; i++){ if( db->aDb[i].pBt ){ sqlite3BtreeRollback(db->aDb[i].pBt); db->aDb[i].inTrans = 0; } } sqlite3ResetInternalSchema(db, 0); } /* ** Return a static string that describes the kind of error specified in the ** argument. */ const char *sqlite3ErrStr(int rc){ |
︙ | ︙ | |||
983 984 985 986 987 988 989 | sqlite3RunParser(&sParse, zSql, &zErrMsg); if( db->xTrace && !db->init.busy ){ /* Trace only the statment that was compiled. ** Make a copy of that part of the SQL string since zSQL is const ** and we must pass a zero terminated string to the trace function ** The copy is unnecessary if the tail pointer is pointing at the | | | 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 | sqlite3RunParser(&sParse, zSql, &zErrMsg); if( db->xTrace && !db->init.busy ){ /* Trace only the statment that was compiled. ** Make a copy of that part of the SQL string since zSQL is const ** and we must pass a zero terminated string to the trace function ** The copy is unnecessary if the tail pointer is pointing at the ** beginning or end of the SQL string. */ if( sParse.zTail && sParse.zTail!=zSql && *sParse.zTail ){ char *tmpSql = sqliteStrNDup(zSql, sParse.zTail - zSql); if( tmpSql ){ db->xTrace(db->pTraceArg, tmpSql); sqliteFree(tmpSql); }else{ |
︙ | ︙ |
Changes to src/pager.c.
︙ | ︙ | |||
14 15 16 17 18 19 20 | ** The pager is used to access a database disk file. It implements ** atomic commit and rollback through the use of a journal file that ** is separate from the database file. The pager also implements file ** locking to prevent two processes from writing the same database ** file simultaneously, or one process from reading the database while ** another is writing. ** | | | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | ** The pager is used to access a database disk file. It implements ** atomic commit and rollback through the use of a journal file that ** is separate from the database file. The pager also implements file ** locking to prevent two processes from writing the same database ** file simultaneously, or one process from reading the database while ** another is writing. ** ** @(#) $Id: pager.c,v 1.162 2004/09/02 14:57:08 drh Exp $ */ #include "os.h" /* Must be first to enable large file support */ #include "sqliteInt.h" #include "pager.h" #include <assert.h> #include <string.h> |
︙ | ︙ | |||
2794 2795 2796 2797 2798 2799 2800 | rc = pager_unwritelock(pPager); pPager->dbSize = -1; return rc; /* Jump here if anything goes wrong during the commit process. */ commit_abort: | | < < < | 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 | rc = pager_unwritelock(pPager); pPager->dbSize = -1; return rc; /* Jump here if anything goes wrong during the commit process. */ commit_abort: sqlite3pager_rollback(pPager); return rc; } /* ** Rollback all changes. The database falls back to PAGER_SHARED mode. ** All in-memory cache pages revert to their original data contents. ** The journal is deleted. |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
39 40 41 42 43 44 45 | ** ** Various scripts scan this source file in order to generate HTML ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** | | | 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | ** ** Various scripts scan this source file in order to generate HTML ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** ** $Id: vdbe.c,v 1.413 2004/09/02 14:57:09 drh Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> #include "vdbeInt.h" /* |
︙ | ︙ | |||
617 618 619 620 621 622 623 | } /* Opcode: Halt P1 P2 * ** ** Exit immediately. All open cursors, Lists, Sorts, etc are closed ** automatically. ** | | | | | | | < < | > | > > > | < | | > > > | 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 | } /* Opcode: Halt P1 P2 * ** ** Exit immediately. All open cursors, Lists, Sorts, etc are closed ** automatically. ** ** P1 is the result code returned by sqlite3_exec(), sqlite3_reset(), ** or sqlite3_finalize(). For a normal halt, this should be SQLITE_OK (0). ** For errors, it can be some other value. If P1!=0 then P2 will determine ** whether or not to rollback the current transaction. Do not rollback ** if P2==OE_Fail. Do the rollback if P2==OE_Rollback. If P2==OE_Abort, ** then back out all changes that have occurred during this execution of the ** VDBE, but do not rollback the transaction. ** ** There is an implied "Halt 0 0 0" instruction inserted at the very end of ** every program. So a jump past the last instruction of the program ** is the same as executing Halt. */ case OP_Halt: { p->pTos = pTos; p->rc = pOp->p1; p->pc = pc; p->errorAction = pOp->p2; if( pOp->p3 ){ sqlite3SetString(&p->zErrMsg, pOp->p3, (char*)0); } rc = sqlite3VdbeHalt(p); if( rc==SQLITE_BUSY ){ p->rc = SQLITE_BUSY; return SQLITE_BUSY; }else if( rc!=SQLITE_OK ){ p->rc = rc; } return p->rc ? SQLITE_ERROR : SQLITE_DONE; } /* Opcode: Integer P1 * P3 ** ** The integer value P1 is pushed onto the stack. If P3 is not zero ** then it is assumed to be a string representation of the same integer. ** If P1 is zero and P3 is not zero, then the value is derived from P3. |
︙ | ︙ | |||
2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 | } /* Opcode: AutoCommit P1 P2 * ** ** Set the database auto-commit flag to P1 (1 or 0). If P2 is true, roll ** back any currently active btree transactions. If there are any active ** VMs (apart from this one), then the COMMIT or ROLLBACK statement fails. */ case OP_AutoCommit: { u8 i = pOp->p1; u8 rollback = pOp->p2; assert( i==1 || i==0 ); assert( i==1 || rollback==0 ); | > > | < > > > > > > > > | 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 | } /* Opcode: AutoCommit P1 P2 * ** ** Set the database auto-commit flag to P1 (1 or 0). If P2 is true, roll ** back any currently active btree transactions. If there are any active ** VMs (apart from this one), then the COMMIT or ROLLBACK statement fails. ** ** This instruction causes the VM to halt. */ case OP_AutoCommit: { u8 i = pOp->p1; u8 rollback = pOp->p2; assert( i==1 || i==0 ); assert( i==1 || rollback==0 ); assert( db->activeVdbeCnt>0 ); /* At least this one VM is active */ if( db->activeVdbeCnt>1 && i && !db->autoCommit ){ /* If this instruction implements a COMMIT or ROLLBACK, other VMs are ** still running, and a transaction is active, return an error indicating ** that the other VMs must complete first. */ sqlite3SetString(&p->zErrMsg, "cannot ", rollback?"rollback":"commit", " transaction - SQL statements in progress", 0); rc = SQLITE_ERROR; }else if( i!=db->autoCommit ){ db->autoCommit = i; if( pOp->p2 ){ assert( i==1 ); sqlite3RollbackAll(db); }else if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){ p->pTos = pTos; p->pc = pc; db->autoCommit = 1-i; p->rc = SQLITE_BUSY; return SQLITE_BUSY; } return SQLITE_DONE; }else{ sqlite3SetString(&p->zErrMsg, (!i)?"cannot start a transaction within a transaction":( (rollback)?"cannot rollback - no transaction is active": "cannot commit - no transaction is active"), 0); rc = SQLITE_ERROR; |
︙ | ︙ | |||
4447 4448 4449 4450 4451 4452 4453 | vdbe_halt: if( rc ){ p->rc = rc; rc = SQLITE_ERROR; }else{ rc = SQLITE_DONE; } | | | 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 | vdbe_halt: if( rc ){ p->rc = rc; rc = SQLITE_ERROR; }else{ rc = SQLITE_DONE; } sqlite3VdbeHalt(p); p->pTos = pTos; return rc; /* Jump to here if a malloc() fails. It's hard to get a malloc() ** to fail on a modern VM computer, so this code is untested. */ no_mem: |
︙ | ︙ |
Changes to src/vdbeInt.h.
︙ | ︙ | |||
334 335 336 337 338 339 340 | int returnDepth; /* Next unused element in returnStack[] */ int nResColumn; /* Number of columns in one row of the result set */ char **azResColumn; /* Values for one row of result */ int popStack; /* Pop the stack this much on entry to VdbeExec() */ char *zErrMsg; /* Error message written here */ u8 resOnStack; /* True if there are result values on the stack */ u8 explain; /* True if EXPLAIN present on SQL command */ | < | 334 335 336 337 338 339 340 341 342 343 344 345 346 347 | int returnDepth; /* Next unused element in returnStack[] */ int nResColumn; /* Number of columns in one row of the result set */ char **azResColumn; /* Values for one row of result */ int popStack; /* Pop the stack this much on entry to VdbeExec() */ char *zErrMsg; /* Error message written here */ u8 resOnStack; /* True if there are result values on the stack */ u8 explain; /* True if EXPLAIN present on SQL command */ u8 changeCntOn; /* True to update the change-counter */ u8 aborted; /* True if ROLLBACK in another VM causes an abort */ int nChange; /* Number of db changes made since last reset */ }; /* ** The following are allowed values for Vdbe.magic |
︙ | ︙ | |||
375 376 377 378 379 380 381 382 383 384 385 386 387 388 | int sqlite3VdbeIdxKeyCompare(Cursor*, int , const unsigned char*, int*); int sqlite3VdbeIdxRowid(BtCursor *, i64 *); int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*); int sqlite3VdbeRecordCompare(void*,int,const void*,int, const void*); int sqlite3VdbeIdxRowidLen(int,const u8*); int sqlite3VdbeExec(Vdbe*); int sqlite3VdbeList(Vdbe*); int sqlite3VdbeChangeEncoding(Mem *, int); int sqlite3VdbeMemCopy(Mem*, const Mem*); void sqlite3VdbeMemShallowCopy(Mem*, const Mem*, int); int sqlite3VdbeMemMove(Mem*, Mem*); int sqlite3VdbeMemNulTerminate(Mem*); int sqlite3VdbeMemSetStr(Mem*, const char*, int, u8, void(*)(void*)); void sqlite3VdbeMemSetInt64(Mem*, i64); | > | 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 | int sqlite3VdbeIdxKeyCompare(Cursor*, int , const unsigned char*, int*); int sqlite3VdbeIdxRowid(BtCursor *, i64 *); int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*); int sqlite3VdbeRecordCompare(void*,int,const void*,int, const void*); int sqlite3VdbeIdxRowidLen(int,const u8*); int sqlite3VdbeExec(Vdbe*); int sqlite3VdbeList(Vdbe*); int sqlite3VdbeHalt(Vdbe*); int sqlite3VdbeChangeEncoding(Mem *, int); int sqlite3VdbeMemCopy(Mem*, const Mem*); void sqlite3VdbeMemShallowCopy(Mem*, const Mem*, int); int sqlite3VdbeMemMove(Mem*, Mem*); int sqlite3VdbeMemNulTerminate(Mem*); int sqlite3VdbeMemSetStr(Mem*, const char*, int, u8, void(*)(void*)); void sqlite3VdbeMemSetInt64(Mem*, i64); |
︙ | ︙ |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
539 540 541 542 543 544 545 546 547 548 549 550 551 552 | } /* ** Prepare a virtual machine for execution. This involves things such ** as allocating stack space and initializing the program counter. ** After the VDBE has be prepped, it can be executed by one or more ** calls to sqlite3VdbeExec(). */ void sqlite3VdbeMakeReady( Vdbe *p, /* The VDBE */ int nVar, /* Number of '?' see in the SQL statement */ int nMem, /* Number of memory cells to allocate */ int nCursor, /* Number of cursors to allocate */ int isExplain /* True if the EXPLAIN keywords is present */ | > > > | 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 | } /* ** Prepare a virtual machine for execution. This involves things such ** as allocating stack space and initializing the program counter. ** After the VDBE has be prepped, it can be executed by one or more ** calls to sqlite3VdbeExec(). ** ** This is the only way to move a VDBE from VDBE_MAGIC_INIT to ** VDBE_MAGIC_RUN. */ void sqlite3VdbeMakeReady( Vdbe *p, /* The VDBE */ int nVar, /* Number of '?' see in the SQL statement */ int nMem, /* Number of memory cells to allocate */ int nCursor, /* Number of cursors to allocate */ int isExplain /* True if the EXPLAIN keywords is present */ |
︙ | ︙ | |||
934 935 936 937 938 939 940 | needXcommit = 1; if( i!=1 ) nTrans++; } } /* If there are any write-transactions at all, invoke the commit hook */ if( needXcommit && db->xCommitCallback ){ | > > | > > | 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 | needXcommit = 1; if( i!=1 ) nTrans++; } } /* If there are any write-transactions at all, invoke the commit hook */ if( needXcommit && db->xCommitCallback ){ int rc; sqlite3SafetyOff(db); rc = db->xCommitCallback(db->pCommitArg); sqlite3SafetyOn(db); if( rc ){ return SQLITE_CONSTRAINT; } } /* The simple case - no more than one database file (not counting the ** TEMP database) has a transaction active. There is no need for the ** master-journal. |
︙ | ︙ | |||
1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 | } } /* ** This routine checks that the sqlite3.activeVdbeCnt count variable ** matches the number of vdbe's in the list sqlite3.pVdbe that are ** currently active. An assertion fails if the two counts do not match. ** ** This is a no-op if NDEBUG is defined. */ #ifndef NDEBUG static void checkActiveVdbeCnt(sqlite *db){ Vdbe *p; int cnt = 0; | > > < | < | | > | > | > > > | | | > | < < < < < < < < < < | < < < < < | < | | < | < < < < < < | < < > | < < | 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 | } } /* ** This routine checks that the sqlite3.activeVdbeCnt count variable ** matches the number of vdbe's in the list sqlite3.pVdbe that are ** currently active. An assertion fails if the two counts do not match. ** This is an internal self-check only - it is not an essential processing ** step. ** ** This is a no-op if NDEBUG is defined. */ #ifndef NDEBUG static void checkActiveVdbeCnt(sqlite *db){ Vdbe *p; int cnt = 0; p = db->pVdbe; while( p ){ if( p->magic==VDBE_MAGIC_RUN && p->pc>=0 ){ cnt++; } p = p->pNext; } assert( cnt==db->activeVdbeCnt ); } #else #define checkActiveVdbeCnt(x) #endif /* ** This routine is called the when a VDBE tries to halt. If the VDBE ** has made changes and is in autocommit mode, then commit those ** changes. If a rollback is needed, then do the rollback. ** ** This routine is the only way to move the state of a VM from ** SQLITE_MAGIC_RUN to SQLITE_MAGIC_HALT. ** ** Return an error code. If the commit could not complete because of ** lock contention, return SQLITE_BUSY. If SQLITE_BUSY is returned, it ** means the close did not happen and needs to be repeated. */ int sqlite3VdbeHalt(Vdbe *p){ sqlite *db = p->db; int i; int (*xFunc)(Btree *pBt) = 0; /* Function to call on each btree backend */ if( p->magic!=VDBE_MAGIC_RUN ){ /* Already halted. Nothing to do. */ assert( p->magic==VDBE_MAGIC_HALT ); return SQLITE_OK; } closeAllCursors(p); checkActiveVdbeCnt(db); if( db->autoCommit && db->activeVdbeCnt==1 ){ if( p->rc==SQLITE_OK || p->errorAction==OE_Fail ){ /* The auto-commit flag is true, there are no other active queries ** using this handle and the vdbe program was successful or hit an ** 'OR FAIL' constraint. This means a commit is required. */ int rc = vdbeCommit(db); if( rc==SQLITE_BUSY ){ return SQLITE_BUSY; }else if( rc!=SQLITE_OK ){ p->rc = rc; xFunc = sqlite3BtreeRollback; } }else{ xFunc = sqlite3BtreeRollback; } }else{ if( p->rc==SQLITE_OK || p->errorAction==OE_Fail ){ xFunc = sqlite3BtreeCommitStmt; }else if( p->errorAction==OE_Abort ){ xFunc = sqlite3BtreeRollbackStmt; }else{ xFunc = sqlite3BtreeRollback; db->autoCommit = 1; abortOtherActiveVdbes(p); } } /* If xFunc is not NULL, then it is one of sqlite3BtreeRollback, ** sqlite3BtreeRollbackStmt or sqlite3BtreeCommitStmt. Call it once on ** each backend. If an error occurs and the return code is still ** SQLITE_OK, set the return code to the new error value. */ for(i=0; xFunc && i<db->nDb; i++){ |
︙ | ︙ | |||
1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 | sqlite3VdbeSetChanges(db, p->nChange); }else{ sqlite3VdbeSetChanges(db, 0); } p->nChange = 0; } if( p->rc!=SQLITE_OK ){ sqlite3RollbackInternalChanges(db); }else if( db->flags & SQLITE_InternChanges ){ sqlite3CommitInternalChanges(db); } | > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 | sqlite3VdbeSetChanges(db, p->nChange); }else{ sqlite3VdbeSetChanges(db, 0); } p->nChange = 0; } /* Rollback or commit any schema changes that occurred. */ if( p->rc!=SQLITE_OK ){ sqlite3RollbackInternalChanges(db); }else if( db->flags & SQLITE_InternChanges ){ sqlite3CommitInternalChanges(db); } /* We have successfully halted and closed the VM. Record this fact. */ if( p->pc>=0 ){ db->activeVdbeCnt--; } p->magic = VDBE_MAGIC_HALT; checkActiveVdbeCnt(db); return SQLITE_OK; } /* ** Clean up a VDBE after execution but do not delete the VDBE just yet. ** Write any error messages into *pzErrMsg. Return the result code. ** ** After this routine is run, the VDBE should be ready to be executed ** again. ** ** To look at it another way, this routine resets the state of the ** virtual machine from VDBE_MAGIC_RUN or VDBE_MAGIC_HALT back to ** VDBE_MAGIC_INIT. */ int sqlite3VdbeReset(Vdbe *p){ if( p->magic!=VDBE_MAGIC_RUN && p->magic!=VDBE_MAGIC_HALT ){ sqlite3Error(p->db, SQLITE_MISUSE, 0 ,0); return SQLITE_MISUSE; } /* If the VM did not run to completion or if it encountered an ** error, then it might not have been halted properly. So halt ** it now. */ sqlite3VdbeHalt(p); /* Transfer the error code and error message from the VDBE into the ** main database structure. */ if( p->zErrMsg ){ sqlite3Error(p->db, p->rc, "%s", p->zErrMsg, 0); sqliteFree(p->zErrMsg); p->zErrMsg = 0; }else if( p->rc ){ sqlite3Error(p->db, p->rc, 0); }else{ sqlite3Error(p->db, SQLITE_OK, 0); } /* Reclaim all memory used by the VDBE */ Cleanup(p); /* Save profiling information from this VDBE run. */ assert( p->pTos<&p->aStack[p->pc<0?0:p->pc] || sqlite3_malloc_failed==1 ); #ifdef VDBE_PROFILE { FILE *out = fopen("vdbe_profile.out", "a"); if( out ){ int i; fprintf(out, "---- "); |
︙ | ︙ | |||
1275 1276 1277 1278 1279 1280 1281 | } } #endif p->magic = VDBE_MAGIC_INIT; p->aborted = 0; return p->rc; } | | | 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 | } } #endif p->magic = VDBE_MAGIC_INIT; p->aborted = 0; return p->rc; } /* ** Clean up and delete a VDBE after execution. Return an integer which is ** the result code. Write any error message text into *pzErrMsg. */ int sqlite3VdbeFinalize(Vdbe *p){ int rc = SQLITE_OK; sqlite *db = p->db; |
︙ | ︙ |
Changes to test/attach2.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 script is testing the ATTACH and DETACH commands # and related functionality. # | | | 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 script is testing the ATTACH and DETACH commands # and related functionality. # # $Id: attach2.test,v 1.26 2004/09/02 14:57:09 drh Exp $ # set testdir [file dirname $argv0] source $testdir/tester.tcl # Ticket #354 |
︙ | ︙ | |||
259 260 261 262 263 264 265 | INSERT INTO t1 VALUES(1, 2) } } {1 {database is locked}} lock_status 4.9.1 db {main shared temp closed file2 shared} lock_status 4.9.2 db2 {main reserved temp closed file2 reserved} | < < | 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 | INSERT INTO t1 VALUES(1, 2) } } {1 {database is locked}} lock_status 4.9.1 db {main shared temp closed file2 shared} lock_status 4.9.2 db2 {main reserved temp closed file2 reserved} do_test attach2-4.10 { # We cannot commit db2 while db is holding a read-lock catchsql {COMMIT} db2 } {1 {database is locked}} lock_status 4.10.1 db {main shared temp closed file2 shared} lock_status 4.10.2 db2 {main pending temp closed file2 reserved} set sqlite_os_trace 0 do_test attach2-4.11 { # db is able to commit. catchsql {COMMIT} } {0 {}} lock_status 4.11.1 db {main unlocked temp closed file2 unlocked} lock_status 4.11.2 db2 {main pending temp closed file2 reserved} |
︙ | ︙ |
Changes to test/capi2.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 2003 January 29 # # 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 implements regression tests for SQLite library. The # focus of this script testing the callback-free C/C++ API. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # 2003 January 29 # # 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 implements regression tests for SQLite library. The # focus of this script testing the callback-free C/C++ API. # # $Id: capi2.test,v 1.19 2004/09/02 14:57:09 drh Exp $ # set testdir [file dirname $argv0] source $testdir/tester.tcl # Return the text values from the current row pointed at by STMT as a list. proc get_row_values {STMT} { |
︙ | ︙ | |||
199 200 201 202 203 204 205 | [sqlite3_column_count $VM] \ [get_row_values $VM] \ [get_column_names $VM] } {SQLITE_DONE 0 {} {}} # Update for v3 - the change has not actually happened until the query is # finalized. Is this going to cause trouble for anyone? Lee Nelson maybe? | > | | > | | 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 | [sqlite3_column_count $VM] \ [get_row_values $VM] \ [get_column_names $VM] } {SQLITE_DONE 0 {} {}} # Update for v3 - the change has not actually happened until the query is # finalized. Is this going to cause trouble for anyone? Lee Nelson maybe? # (Later:) The change now happens just before SQLITE_DONE is returned. do_test capi2-3.10b {db changes} {1} do_test capi2-3.11 { sqlite3_finalize $VM } {SQLITE_OK} do_test capi2-3.11b {db changes} {1} do_test capi2-3.12 { sqlite3_finalize $VM } {SQLITE_MISUSE} do_test capi2-3.13 { set VM [sqlite3_prepare $DB {INSERT INTO t1 VALUES(1,3,4)} -1 TAIL] list [sqlite3_step $VM] \ [sqlite3_column_count $VM] \ [get_row_values $VM] \ [get_column_names $VM] } {SQLITE_ERROR 0 {} {}} # Update for v3: Preparing a statement does not affect the change counter. # (Test result changes from 0 to 1). (Later:) change counter updates occur # when sqlite3_step returns, not at finalize time. do_test capi2-3.13b {db changes} {0} do_test capi2-3.14 { list [sqlite3_finalize $VM] [sqlite3_errmsg $DB] } {SQLITE_CONSTRAINT {column a is not unique}} do_test capi2-3.15 { set VM [sqlite3_prepare $DB {CREATE TABLE t2(a NOT NULL, b)} -1 TAIL] set TAIL |
︙ | ︙ |
Changes to test/capi3.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 2003 January 29 # # 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 implements regression tests for SQLite library. The # focus of this script testing the callback-free C/C++ API. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # 2003 January 29 # # 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 implements regression tests for SQLite library. The # focus of this script testing the callback-free C/C++ API. # # $Id: capi3.test,v 1.21 2004/09/02 14:57:09 drh Exp $ # set testdir [file dirname $argv0] source $testdir/tester.tcl # Return the UTF-16 representation of the supplied UTF-8 string $str. # If $nt is true, append two 0x00 bytes as a nul terminator. |
︙ | ︙ | |||
532 533 534 535 536 537 538 | set data [binary format c6a5 {6 23 0 0 0 0} table] } btree_insert $::bc 5 $data btree_close_cursor $::bc btree_commit $::bt btree_close $::bt | | | 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 | set data [binary format c6a5 {6 23 0 0 0 0} table] } btree_insert $::bc 5 $data btree_close_cursor $::bc btree_commit $::bt btree_close $::bt } {}; do_test capi3-8.5 { db close sqlite3 db test.db catchsql { SELECT * FROM sqlite_master; } } {1 {malformed database schema}} |
︙ | ︙ |
Added test/capi3b.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | # 2004 September 2 # # 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 implements regression tests for SQLite library. The # focus of this script testing the callback-free C/C++ API and in # particular the behavior of sqlite3_step() when trying to commit # with lock contention. # # $Id: capi3b.test,v 1.1 2004/09/02 14:57:09 drh Exp $ # set testdir [file dirname $argv0] source $testdir/tester.tcl db close set DB [sqlite3 db test.db] set DB2 [sqlite3 db2 test.db] # Create some data in the database # do_test capi3b-1.1 { execsql { CREATE TABLE t1(x); INSERT INTO t1 VALUES(1); INSERT INTO t1 VALUES(2); SELECT * FROM t1 } } {1 2} # Make sure the second database connection can see the data # do_test capi3b-1.2 { execsql { SELECT * FROM t1 } db2 } {1 2} # First database connection acquires a shared lock # do_test capi3b-1.3 { execsql { BEGIN; SELECT * FROM t1; } } {1 2} # Second database connection tries to write. The sqlite3_step() # function returns SQLITE_BUSY because it cannot commit. # do_test capi3b-1.4 { set VM [sqlite3_prepare $DB2 {INSERT INTO t1 VALUES(3)} -1 TAIL] sqlite3_step $VM } SQLITE_BUSY # The sqlite3_step call can be repeated multiple times. # do_test capi3b-1.5.1 { sqlite3_step $VM } SQLITE_BUSY do_test capi3b-1.5.2 { sqlite3_step $VM } SQLITE_BUSY # The first connection closes its transaction. This allows the second # connections sqlite3_step to succeed. # do_test capi3b-1.6 { execsql COMMIT sqlite3_step $VM } SQLITE_DONE do_test capi3b-1.7 { sqlite3_finalize $VM } SQLITE_OK do_test capi3b-1.8 { execsql {SELECT * FROM t1} db2 } {1 2 3} do_test capi3b-1.9 { execsql {SELECT * FROM t1} } {1 2 3} catch {db2 close} finish_test |
Changes to test/quick.test.
1 2 3 4 5 6 7 8 9 10 11 12 | # 2001 September 15 # # 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 runs all tests. # | | > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | # 2001 September 15 # # 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 runs all tests. # # $Id: quick.test,v 1.30 2004/09/02 14:57:09 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl rename finish_test really_finish_test proc finish_test {} {} set ISQUICK 1 set EXCLUDE { all.test btree2.test btree3.test btree4.test btree5.test btree6.test corrupt.test crash.test malloc.test memleak.test misuse.test quick.test utf16.test |
︙ | ︙ |