OLD | NEW |
1 /* | 1 /* |
2 ** 2007 May 1 | 2 ** 2007 May 1 |
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 ** |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
57 | 57 |
58 /* Set the value of the SQL statements only variable to integer iRow. | 58 /* Set the value of the SQL statements only variable to integer iRow. |
59 ** This is done directly instead of using sqlite3_bind_int64() to avoid | 59 ** This is done directly instead of using sqlite3_bind_int64() to avoid |
60 ** triggering asserts related to mutexes. | 60 ** triggering asserts related to mutexes. |
61 */ | 61 */ |
62 assert( v->aVar[0].flags&MEM_Int ); | 62 assert( v->aVar[0].flags&MEM_Int ); |
63 v->aVar[0].u.i = iRow; | 63 v->aVar[0].u.i = iRow; |
64 | 64 |
65 rc = sqlite3_step(p->pStmt); | 65 rc = sqlite3_step(p->pStmt); |
66 if( rc==SQLITE_ROW ){ | 66 if( rc==SQLITE_ROW ){ |
67 u32 type = v->apCsr[0]->aType[p->iCol]; | 67 VdbeCursor *pC = v->apCsr[0]; |
| 68 u32 type = pC->aType[p->iCol]; |
68 if( type<12 ){ | 69 if( type<12 ){ |
69 zErr = sqlite3MPrintf(p->db, "cannot open value of type %s", | 70 zErr = sqlite3MPrintf(p->db, "cannot open value of type %s", |
70 type==0?"null": type==7?"real": "integer" | 71 type==0?"null": type==7?"real": "integer" |
71 ); | 72 ); |
72 rc = SQLITE_ERROR; | 73 rc = SQLITE_ERROR; |
73 sqlite3_finalize(p->pStmt); | 74 sqlite3_finalize(p->pStmt); |
74 p->pStmt = 0; | 75 p->pStmt = 0; |
75 }else{ | 76 }else{ |
76 p->iOffset = v->apCsr[0]->aOffset[p->iCol]; | 77 p->iOffset = pC->aType[p->iCol + pC->nField]; |
77 p->nByte = sqlite3VdbeSerialTypeLen(type); | 78 p->nByte = sqlite3VdbeSerialTypeLen(type); |
78 p->pCsr = v->apCsr[0]->pCursor; | 79 p->pCsr = pC->pCursor; |
79 sqlite3BtreeEnterCursor(p->pCsr); | 80 sqlite3BtreeIncrblobCursor(p->pCsr); |
80 sqlite3BtreeCacheOverflow(p->pCsr); | |
81 sqlite3BtreeLeaveCursor(p->pCsr); | |
82 } | 81 } |
83 } | 82 } |
84 | 83 |
85 if( rc==SQLITE_ROW ){ | 84 if( rc==SQLITE_ROW ){ |
86 rc = SQLITE_OK; | 85 rc = SQLITE_OK; |
87 }else if( p->pStmt ){ | 86 }else if( p->pStmt ){ |
88 rc = sqlite3_finalize(p->pStmt); | 87 rc = sqlite3_finalize(p->pStmt); |
89 p->pStmt = 0; | 88 p->pStmt = 0; |
90 if( rc==SQLITE_OK ){ | 89 if( rc==SQLITE_OK ){ |
91 zErr = sqlite3MPrintf(p->db, "no such rowid: %lld", iRow); | 90 zErr = sqlite3MPrintf(p->db, "no such rowid: %lld", iRow); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
125 ** | 124 ** |
126 ** After seeking the cursor, the vdbe executes an OP_ResultRow. | 125 ** After seeking the cursor, the vdbe executes an OP_ResultRow. |
127 ** Code external to the Vdbe then "borrows" the b-tree cursor and | 126 ** Code external to the Vdbe then "borrows" the b-tree cursor and |
128 ** uses it to implement the blob_read(), blob_write() and | 127 ** uses it to implement the blob_read(), blob_write() and |
129 ** blob_bytes() functions. | 128 ** blob_bytes() functions. |
130 ** | 129 ** |
131 ** The sqlite3_blob_close() function finalizes the vdbe program, | 130 ** The sqlite3_blob_close() function finalizes the vdbe program, |
132 ** which closes the b-tree cursor and (possibly) commits the | 131 ** which closes the b-tree cursor and (possibly) commits the |
133 ** transaction. | 132 ** transaction. |
134 */ | 133 */ |
| 134 static const int iLn = VDBE_OFFSET_LINENO(4); |
135 static const VdbeOpList openBlob[] = { | 135 static const VdbeOpList openBlob[] = { |
136 {OP_Transaction, 0, 0, 0}, /* 0: Start a transaction */ | 136 /* {OP_Transaction, 0, 0, 0}, // 0: Inserted separately */ |
137 {OP_VerifyCookie, 0, 0, 0}, /* 1: Check the schema cookie */ | 137 {OP_TableLock, 0, 0, 0}, /* 1: Acquire a read or write lock */ |
138 {OP_TableLock, 0, 0, 0}, /* 2: Acquire a read or write lock */ | |
139 | |
140 /* One of the following two instructions is replaced by an OP_Noop. */ | 138 /* One of the following two instructions is replaced by an OP_Noop. */ |
141 {OP_OpenRead, 0, 0, 0}, /* 3: Open cursor 0 for reading */ | 139 {OP_OpenRead, 0, 0, 0}, /* 2: Open cursor 0 for reading */ |
142 {OP_OpenWrite, 0, 0, 0}, /* 4: Open cursor 0 for read/write */ | 140 {OP_OpenWrite, 0, 0, 0}, /* 3: Open cursor 0 for read/write */ |
143 | 141 {OP_Variable, 1, 1, 1}, /* 4: Push the rowid to the stack */ |
144 {OP_Variable, 1, 1, 1}, /* 5: Push the rowid to the stack */ | 142 {OP_NotExists, 0, 10, 1}, /* 5: Seek the cursor */ |
145 {OP_NotExists, 0, 10, 1}, /* 6: Seek the cursor */ | 143 {OP_Column, 0, 0, 1}, /* 6 */ |
146 {OP_Column, 0, 0, 1}, /* 7 */ | 144 {OP_ResultRow, 1, 0, 0}, /* 7 */ |
147 {OP_ResultRow, 1, 0, 0}, /* 8 */ | 145 {OP_Goto, 0, 4, 0}, /* 8 */ |
148 {OP_Goto, 0, 5, 0}, /* 9 */ | 146 {OP_Close, 0, 0, 0}, /* 9 */ |
149 {OP_Close, 0, 0, 0}, /* 10 */ | 147 {OP_Halt, 0, 0, 0}, /* 10 */ |
150 {OP_Halt, 0, 0, 0}, /* 11 */ | |
151 }; | 148 }; |
152 | 149 |
153 int rc = SQLITE_OK; | 150 int rc = SQLITE_OK; |
154 char *zErr = 0; | 151 char *zErr = 0; |
155 Table *pTab; | 152 Table *pTab; |
156 Parse *pParse = 0; | 153 Parse *pParse = 0; |
157 Incrblob *pBlob = 0; | 154 Incrblob *pBlob = 0; |
158 | 155 |
159 flags = !!flags; /* flags = (flags ? 1 : 0); */ | 156 flags = !!flags; /* flags = (flags ? 1 : 0); */ |
160 *ppBlob = 0; | 157 *ppBlob = 0; |
(...skipping 10 matching lines...) Expand all Loading... |
171 pParse->db = db; | 168 pParse->db = db; |
172 sqlite3DbFree(db, zErr); | 169 sqlite3DbFree(db, zErr); |
173 zErr = 0; | 170 zErr = 0; |
174 | 171 |
175 sqlite3BtreeEnterAll(db); | 172 sqlite3BtreeEnterAll(db); |
176 pTab = sqlite3LocateTable(pParse, 0, zTable, zDb); | 173 pTab = sqlite3LocateTable(pParse, 0, zTable, zDb); |
177 if( pTab && IsVirtual(pTab) ){ | 174 if( pTab && IsVirtual(pTab) ){ |
178 pTab = 0; | 175 pTab = 0; |
179 sqlite3ErrorMsg(pParse, "cannot open virtual table: %s", zTable); | 176 sqlite3ErrorMsg(pParse, "cannot open virtual table: %s", zTable); |
180 } | 177 } |
| 178 if( pTab && !HasRowid(pTab) ){ |
| 179 pTab = 0; |
| 180 sqlite3ErrorMsg(pParse, "cannot open table without rowid: %s", zTable); |
| 181 } |
181 #ifndef SQLITE_OMIT_VIEW | 182 #ifndef SQLITE_OMIT_VIEW |
182 if( pTab && pTab->pSelect ){ | 183 if( pTab && pTab->pSelect ){ |
183 pTab = 0; | 184 pTab = 0; |
184 sqlite3ErrorMsg(pParse, "cannot open view: %s", zTable); | 185 sqlite3ErrorMsg(pParse, "cannot open view: %s", zTable); |
185 } | 186 } |
186 #endif | 187 #endif |
187 if( !pTab ){ | 188 if( !pTab ){ |
188 if( pParse->zErrMsg ){ | 189 if( pParse->zErrMsg ){ |
189 sqlite3DbFree(db, zErr); | 190 sqlite3DbFree(db, zErr); |
190 zErr = pParse->zErrMsg; | 191 zErr = pParse->zErrMsg; |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
228 for(j=0; j<pFKey->nCol; j++){ | 229 for(j=0; j<pFKey->nCol; j++){ |
229 if( pFKey->aCol[j].iFrom==iCol ){ | 230 if( pFKey->aCol[j].iFrom==iCol ){ |
230 zFault = "foreign key"; | 231 zFault = "foreign key"; |
231 } | 232 } |
232 } | 233 } |
233 } | 234 } |
234 } | 235 } |
235 #endif | 236 #endif |
236 for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ | 237 for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ |
237 int j; | 238 int j; |
238 for(j=0; j<pIdx->nColumn; j++){ | 239 for(j=0; j<pIdx->nKeyCol; j++){ |
239 if( pIdx->aiColumn[j]==iCol ){ | 240 if( pIdx->aiColumn[j]==iCol ){ |
240 zFault = "indexed"; | 241 zFault = "indexed"; |
241 } | 242 } |
242 } | 243 } |
243 } | 244 } |
244 if( zFault ){ | 245 if( zFault ){ |
245 sqlite3DbFree(db, zErr); | 246 sqlite3DbFree(db, zErr); |
246 zErr = sqlite3MPrintf(db, "cannot open %s column for writing", zFault); | 247 zErr = sqlite3MPrintf(db, "cannot open %s column for writing", zFault); |
247 rc = SQLITE_ERROR; | 248 rc = SQLITE_ERROR; |
248 sqlite3BtreeLeaveAll(db); | 249 sqlite3BtreeLeaveAll(db); |
249 goto blob_open_out; | 250 goto blob_open_out; |
250 } | 251 } |
251 } | 252 } |
252 | 253 |
253 pBlob->pStmt = (sqlite3_stmt *)sqlite3VdbeCreate(db); | 254 pBlob->pStmt = (sqlite3_stmt *)sqlite3VdbeCreate(pParse); |
254 assert( pBlob->pStmt || db->mallocFailed ); | 255 assert( pBlob->pStmt || db->mallocFailed ); |
255 if( pBlob->pStmt ){ | 256 if( pBlob->pStmt ){ |
256 Vdbe *v = (Vdbe *)pBlob->pStmt; | 257 Vdbe *v = (Vdbe *)pBlob->pStmt; |
257 int iDb = sqlite3SchemaToIndex(db, pTab->pSchema); | 258 int iDb = sqlite3SchemaToIndex(db, pTab->pSchema); |
258 | 259 |
259 sqlite3VdbeAddOpList(v, sizeof(openBlob)/sizeof(VdbeOpList), openBlob); | |
260 | 260 |
261 | 261 sqlite3VdbeAddOp4Int(v, OP_Transaction, iDb, flags, |
262 /* Configure the OP_Transaction */ | 262 pTab->pSchema->schema_cookie, |
263 sqlite3VdbeChangeP1(v, 0, iDb); | 263 pTab->pSchema->iGeneration); |
264 sqlite3VdbeChangeP2(v, 0, flags); | 264 sqlite3VdbeChangeP5(v, 1); |
265 | 265 sqlite3VdbeAddOpList(v, ArraySize(openBlob), openBlob, iLn); |
266 /* Configure the OP_VerifyCookie */ | |
267 sqlite3VdbeChangeP1(v, 1, iDb); | |
268 sqlite3VdbeChangeP2(v, 1, pTab->pSchema->schema_cookie); | |
269 sqlite3VdbeChangeP3(v, 1, pTab->pSchema->iGeneration); | |
270 | 266 |
271 /* Make sure a mutex is held on the table to be accessed */ | 267 /* Make sure a mutex is held on the table to be accessed */ |
272 sqlite3VdbeUsesBtree(v, iDb); | 268 sqlite3VdbeUsesBtree(v, iDb); |
273 | 269 |
274 /* Configure the OP_TableLock instruction */ | 270 /* Configure the OP_TableLock instruction */ |
275 #ifdef SQLITE_OMIT_SHARED_CACHE | 271 #ifdef SQLITE_OMIT_SHARED_CACHE |
276 sqlite3VdbeChangeToNoop(v, 2, 1); | 272 sqlite3VdbeChangeToNoop(v, 1); |
277 #else | 273 #else |
278 sqlite3VdbeChangeP1(v, 2, iDb); | 274 sqlite3VdbeChangeP1(v, 1, iDb); |
279 sqlite3VdbeChangeP2(v, 2, pTab->tnum); | 275 sqlite3VdbeChangeP2(v, 1, pTab->tnum); |
280 sqlite3VdbeChangeP3(v, 2, flags); | 276 sqlite3VdbeChangeP3(v, 1, flags); |
281 sqlite3VdbeChangeP4(v, 2, pTab->zName, P4_TRANSIENT); | 277 sqlite3VdbeChangeP4(v, 1, pTab->zName, P4_TRANSIENT); |
282 #endif | 278 #endif |
283 | 279 |
284 /* Remove either the OP_OpenWrite or OpenRead. Set the P2 | 280 /* Remove either the OP_OpenWrite or OpenRead. Set the P2 |
285 ** parameter of the other to pTab->tnum. */ | 281 ** parameter of the other to pTab->tnum. */ |
286 sqlite3VdbeChangeToNoop(v, 4 - flags, 1); | 282 sqlite3VdbeChangeToNoop(v, 3 - flags); |
287 sqlite3VdbeChangeP2(v, 3 + flags, pTab->tnum); | 283 sqlite3VdbeChangeP2(v, 2 + flags, pTab->tnum); |
288 sqlite3VdbeChangeP3(v, 3 + flags, iDb); | 284 sqlite3VdbeChangeP3(v, 2 + flags, iDb); |
289 | 285 |
290 /* Configure the number of columns. Configure the cursor to | 286 /* Configure the number of columns. Configure the cursor to |
291 ** think that the table has one more column than it really | 287 ** think that the table has one more column than it really |
292 ** does. An OP_Column to retrieve this imaginary column will | 288 ** does. An OP_Column to retrieve this imaginary column will |
293 ** always return an SQL NULL. This is useful because it means | 289 ** always return an SQL NULL. This is useful because it means |
294 ** we can invoke OP_Column to fill in the vdbe cursors type | 290 ** we can invoke OP_Column to fill in the vdbe cursors type |
295 ** and offset cache without causing any IO. | 291 ** and offset cache without causing any IO. |
296 */ | 292 */ |
297 sqlite3VdbeChangeP4(v, 3+flags, SQLITE_INT_TO_PTR(pTab->nCol+1),P4_INT32); | 293 sqlite3VdbeChangeP4(v, 2+flags, SQLITE_INT_TO_PTR(pTab->nCol+1),P4_INT32); |
298 sqlite3VdbeChangeP2(v, 7, pTab->nCol); | 294 sqlite3VdbeChangeP2(v, 6, pTab->nCol); |
299 if( !db->mallocFailed ){ | 295 if( !db->mallocFailed ){ |
300 sqlite3VdbeMakeReady(v, 1, 1, 1, 0, 0, 0); | 296 pParse->nVar = 1; |
| 297 pParse->nMem = 1; |
| 298 pParse->nTab = 1; |
| 299 sqlite3VdbeMakeReady(v, pParse); |
301 } | 300 } |
302 } | 301 } |
303 | 302 |
304 pBlob->flags = flags; | 303 pBlob->flags = flags; |
305 pBlob->iCol = iCol; | 304 pBlob->iCol = iCol; |
306 pBlob->db = db; | 305 pBlob->db = db; |
307 sqlite3BtreeLeaveAll(db); | 306 sqlite3BtreeLeaveAll(db); |
308 if( db->mallocFailed ){ | 307 if( db->mallocFailed ){ |
309 goto blob_open_out; | 308 goto blob_open_out; |
310 } | 309 } |
311 sqlite3_bind_int64(pBlob->pStmt, 1, iRow); | 310 sqlite3_bind_int64(pBlob->pStmt, 1, iRow); |
312 rc = blobSeekToRow(pBlob, iRow, &zErr); | 311 rc = blobSeekToRow(pBlob, iRow, &zErr); |
313 } while( (++nAttempt)<5 && rc==SQLITE_SCHEMA ); | 312 } while( (++nAttempt)<SQLITE_MAX_SCHEMA_RETRY && rc==SQLITE_SCHEMA ); |
314 | 313 |
315 blob_open_out: | 314 blob_open_out: |
316 if( rc==SQLITE_OK && db->mallocFailed==0 ){ | 315 if( rc==SQLITE_OK && db->mallocFailed==0 ){ |
317 *ppBlob = (sqlite3_blob *)pBlob; | 316 *ppBlob = (sqlite3_blob *)pBlob; |
318 }else{ | 317 }else{ |
319 if( pBlob && pBlob->pStmt ) sqlite3VdbeFinalize((Vdbe *)pBlob->pStmt); | 318 if( pBlob && pBlob->pStmt ) sqlite3VdbeFinalize((Vdbe *)pBlob->pStmt); |
320 sqlite3DbFree(db, pBlob); | 319 sqlite3DbFree(db, pBlob); |
321 } | 320 } |
322 sqlite3Error(db, rc, (zErr ? "%s" : 0), zErr); | 321 sqlite3ErrorWithMsg(db, rc, (zErr ? "%s" : 0), zErr); |
323 sqlite3DbFree(db, zErr); | 322 sqlite3DbFree(db, zErr); |
| 323 sqlite3ParserReset(pParse); |
324 sqlite3StackFree(db, pParse); | 324 sqlite3StackFree(db, pParse); |
325 rc = sqlite3ApiExit(db, rc); | 325 rc = sqlite3ApiExit(db, rc); |
326 sqlite3_mutex_leave(db->mutex); | 326 sqlite3_mutex_leave(db->mutex); |
327 return rc; | 327 return rc; |
328 } | 328 } |
329 | 329 |
330 /* | 330 /* |
331 ** Close a blob handle that was previously created using | 331 ** Close a blob handle that was previously created using |
332 ** sqlite3_blob_open(). | 332 ** sqlite3_blob_open(). |
333 */ | 333 */ |
(...skipping 30 matching lines...) Expand all Loading... |
364 sqlite3 *db; | 364 sqlite3 *db; |
365 | 365 |
366 if( p==0 ) return SQLITE_MISUSE_BKPT; | 366 if( p==0 ) return SQLITE_MISUSE_BKPT; |
367 db = p->db; | 367 db = p->db; |
368 sqlite3_mutex_enter(db->mutex); | 368 sqlite3_mutex_enter(db->mutex); |
369 v = (Vdbe*)p->pStmt; | 369 v = (Vdbe*)p->pStmt; |
370 | 370 |
371 if( n<0 || iOffset<0 || (iOffset+n)>p->nByte ){ | 371 if( n<0 || iOffset<0 || (iOffset+n)>p->nByte ){ |
372 /* Request is out of range. Return a transient error. */ | 372 /* Request is out of range. Return a transient error. */ |
373 rc = SQLITE_ERROR; | 373 rc = SQLITE_ERROR; |
374 sqlite3Error(db, SQLITE_ERROR, 0); | 374 sqlite3Error(db, SQLITE_ERROR); |
375 }else if( v==0 ){ | 375 }else if( v==0 ){ |
376 /* If there is no statement handle, then the blob-handle has | 376 /* If there is no statement handle, then the blob-handle has |
377 ** already been invalidated. Return SQLITE_ABORT in this case. | 377 ** already been invalidated. Return SQLITE_ABORT in this case. |
378 */ | 378 */ |
379 rc = SQLITE_ABORT; | 379 rc = SQLITE_ABORT; |
380 }else{ | 380 }else{ |
381 /* Call either BtreeData() or BtreePutData(). If SQLITE_ABORT is | 381 /* Call either BtreeData() or BtreePutData(). If SQLITE_ABORT is |
382 ** returned, clean-up the statement handle. | 382 ** returned, clean-up the statement handle. |
383 */ | 383 */ |
384 assert( db == v->db ); | 384 assert( db == v->db ); |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
444 | 444 |
445 if( p->pStmt==0 ){ | 445 if( p->pStmt==0 ){ |
446 /* If there is no statement handle, then the blob-handle has | 446 /* If there is no statement handle, then the blob-handle has |
447 ** already been invalidated. Return SQLITE_ABORT in this case. | 447 ** already been invalidated. Return SQLITE_ABORT in this case. |
448 */ | 448 */ |
449 rc = SQLITE_ABORT; | 449 rc = SQLITE_ABORT; |
450 }else{ | 450 }else{ |
451 char *zErr; | 451 char *zErr; |
452 rc = blobSeekToRow(p, iRow, &zErr); | 452 rc = blobSeekToRow(p, iRow, &zErr); |
453 if( rc!=SQLITE_OK ){ | 453 if( rc!=SQLITE_OK ){ |
454 sqlite3Error(db, rc, (zErr ? "%s" : 0), zErr); | 454 sqlite3ErrorWithMsg(db, rc, (zErr ? "%s" : 0), zErr); |
455 sqlite3DbFree(db, zErr); | 455 sqlite3DbFree(db, zErr); |
456 } | 456 } |
457 assert( rc!=SQLITE_SCHEMA ); | 457 assert( rc!=SQLITE_SCHEMA ); |
458 } | 458 } |
459 | 459 |
460 rc = sqlite3ApiExit(db, rc); | 460 rc = sqlite3ApiExit(db, rc); |
461 assert( rc==SQLITE_OK || p->pStmt==0 ); | 461 assert( rc==SQLITE_OK || p->pStmt==0 ); |
462 sqlite3_mutex_leave(db->mutex); | 462 sqlite3_mutex_leave(db->mutex); |
463 return rc; | 463 return rc; |
464 } | 464 } |
465 | 465 |
466 #endif /* #ifndef SQLITE_OMIT_INCRBLOB */ | 466 #endif /* #ifndef SQLITE_OMIT_INCRBLOB */ |
OLD | NEW |