OLD | NEW |
1 /* | 1 /* |
2 ** 2012 Jan 11 | 2 ** 2012 Jan 11 |
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 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
203 */ | 203 */ |
204 /* TODO(shess): It might be useful to allow DEFAULT in types to | 204 /* TODO(shess): It might be useful to allow DEFAULT in types to |
205 * specify what to do for NULL when an ALTER TABLE case comes up. | 205 * specify what to do for NULL when an ALTER TABLE case comes up. |
206 * Unfortunately, simply adding it to the exposed schema and using | 206 * Unfortunately, simply adding it to the exposed schema and using |
207 * sqlite3_result_null() does not cause the default to be generate. | 207 * sqlite3_result_null() does not cause the default to be generate. |
208 * Handling it ourselves seems hard, unfortunately. | 208 * Handling it ourselves seems hard, unfortunately. |
209 */ | 209 */ |
210 | 210 |
211 #include <assert.h> | 211 #include <assert.h> |
212 #include <ctype.h> | 212 #include <ctype.h> |
| 213 #include <stdint.h> |
213 #include <stdio.h> | 214 #include <stdio.h> |
| 215 #include <stdlib.h> |
214 #include <string.h> | 216 #include <string.h> |
215 | 217 |
216 /* Internal SQLite things that are used: | 218 #if defined(SQLITE_CORE) && !defined(SQLITE_CORE_NOT_REALLY) |
217 * u32, u64, i64 types. | 219 |
218 * Btree, Pager, and DbPage structs. | 220 /* Compiling as part of SQLite core, pull in internal APIs. */ |
219 * DbPage.pData, .pPager, and .pgno | |
220 * sqlite3 struct. | |
221 * sqlite3BtreePager() and sqlite3BtreeGetPageSize() | |
222 * sqlite3BtreeGetOptimalReserve() | |
223 * sqlite3PagerGet() and sqlite3PagerUnref() | |
224 * getVarint(). | |
225 */ | |
226 #include "sqliteInt.h" | 221 #include "sqliteInt.h" |
| 222 #define recoverGetVarint(p, v) sqlite3GetVarint(p, v) |
| 223 |
| 224 #else |
| 225 |
| 226 /* Compiling as a module outside of SQLite. Define local versions of some types |
| 227 ** and functions. These are copied and modestly adapted from SQLite source |
| 228 ** code. |
| 229 */ |
| 230 #include "sqlite3.h" |
| 231 |
| 232 /* Copied from SQLite internals. */ |
| 233 typedef uint8_t u8; |
| 234 typedef uint32_t u32; |
| 235 typedef uint64_t u64; |
| 236 typedef int64_t i64; |
| 237 |
| 238 /* |
| 239 ** A convenience macro that returns the number of elements in |
| 240 ** an array. |
| 241 */ |
| 242 #define ArraySize(X) ((int)(sizeof(X)/sizeof(X[0]))) |
| 243 |
| 244 /* |
| 245 ** Bitmasks used by sqlite3GetVarint(). These precomputed constants |
| 246 ** are defined here rather than simply putting the constant expressions |
| 247 ** inline in order to work around bugs in the RVT compiler. |
| 248 ** |
| 249 ** SLOT_2_0 A mask for (0x7f<<14) | 0x7f |
| 250 ** |
| 251 ** SLOT_4_2_0 A mask for (0x7f<<28) | SLOT_2_0 |
| 252 */ |
| 253 #define SLOT_2_0 0x001fc07f |
| 254 #define SLOT_4_2_0 0xf01fc07f |
| 255 |
| 256 /* |
| 257 ** Read a 64-bit variable-length integer from memory starting at p[0]. |
| 258 ** Return the number of bytes read. The value is stored in *v. |
| 259 */ |
| 260 static unsigned char recoverGetVarint(const unsigned char *p, u64 *v){ |
| 261 u32 a,b,s; |
| 262 |
| 263 a = *p; |
| 264 /* a: p0 (unmasked) */ |
| 265 if (!(a&0x80)) |
| 266 { |
| 267 *v = a; |
| 268 return 1; |
| 269 } |
| 270 |
| 271 p++; |
| 272 b = *p; |
| 273 /* b: p1 (unmasked) */ |
| 274 if (!(b&0x80)) |
| 275 { |
| 276 a &= 0x7f; |
| 277 a = a<<7; |
| 278 a |= b; |
| 279 *v = a; |
| 280 return 2; |
| 281 } |
| 282 |
| 283 /* Verify that constants are precomputed correctly */ |
| 284 assert( SLOT_2_0 == ((0x7f<<14) | (0x7f)) ); |
| 285 assert( SLOT_4_2_0 == ((0xfU<<28) | (0x7f<<14) | (0x7f)) ); |
| 286 |
| 287 p++; |
| 288 a = a<<14; |
| 289 a |= *p; |
| 290 /* a: p0<<14 | p2 (unmasked) */ |
| 291 if (!(a&0x80)) |
| 292 { |
| 293 a &= SLOT_2_0; |
| 294 b &= 0x7f; |
| 295 b = b<<7; |
| 296 a |= b; |
| 297 *v = a; |
| 298 return 3; |
| 299 } |
| 300 |
| 301 /* CSE1 from below */ |
| 302 a &= SLOT_2_0; |
| 303 p++; |
| 304 b = b<<14; |
| 305 b |= *p; |
| 306 /* b: p1<<14 | p3 (unmasked) */ |
| 307 if (!(b&0x80)) |
| 308 { |
| 309 b &= SLOT_2_0; |
| 310 /* moved CSE1 up */ |
| 311 /* a &= (0x7f<<14)|(0x7f); */ |
| 312 a = a<<7; |
| 313 a |= b; |
| 314 *v = a; |
| 315 return 4; |
| 316 } |
| 317 |
| 318 /* a: p0<<14 | p2 (masked) */ |
| 319 /* b: p1<<14 | p3 (unmasked) */ |
| 320 /* 1:save off p0<<21 | p1<<14 | p2<<7 | p3 (masked) */ |
| 321 /* moved CSE1 up */ |
| 322 /* a &= (0x7f<<14)|(0x7f); */ |
| 323 b &= SLOT_2_0; |
| 324 s = a; |
| 325 /* s: p0<<14 | p2 (masked) */ |
| 326 |
| 327 p++; |
| 328 a = a<<14; |
| 329 a |= *p; |
| 330 /* a: p0<<28 | p2<<14 | p4 (unmasked) */ |
| 331 if (!(a&0x80)) |
| 332 { |
| 333 /* we can skip these cause they were (effectively) done above |
| 334 ** while calculating s */ |
| 335 /* a &= (0x7f<<28)|(0x7f<<14)|(0x7f); */ |
| 336 /* b &= (0x7f<<14)|(0x7f); */ |
| 337 b = b<<7; |
| 338 a |= b; |
| 339 s = s>>18; |
| 340 *v = ((u64)s)<<32 | a; |
| 341 return 5; |
| 342 } |
| 343 |
| 344 /* 2:save off p0<<21 | p1<<14 | p2<<7 | p3 (masked) */ |
| 345 s = s<<7; |
| 346 s |= b; |
| 347 /* s: p0<<21 | p1<<14 | p2<<7 | p3 (masked) */ |
| 348 |
| 349 p++; |
| 350 b = b<<14; |
| 351 b |= *p; |
| 352 /* b: p1<<28 | p3<<14 | p5 (unmasked) */ |
| 353 if (!(b&0x80)) |
| 354 { |
| 355 /* we can skip this cause it was (effectively) done above in calc'ing s */ |
| 356 /* b &= (0x7f<<28)|(0x7f<<14)|(0x7f); */ |
| 357 a &= SLOT_2_0; |
| 358 a = a<<7; |
| 359 a |= b; |
| 360 s = s>>18; |
| 361 *v = ((u64)s)<<32 | a; |
| 362 return 6; |
| 363 } |
| 364 |
| 365 p++; |
| 366 a = a<<14; |
| 367 a |= *p; |
| 368 /* a: p2<<28 | p4<<14 | p6 (unmasked) */ |
| 369 if (!(a&0x80)) |
| 370 { |
| 371 a &= SLOT_4_2_0; |
| 372 b &= SLOT_2_0; |
| 373 b = b<<7; |
| 374 a |= b; |
| 375 s = s>>11; |
| 376 *v = ((u64)s)<<32 | a; |
| 377 return 7; |
| 378 } |
| 379 |
| 380 /* CSE2 from below */ |
| 381 a &= SLOT_2_0; |
| 382 p++; |
| 383 b = b<<14; |
| 384 b |= *p; |
| 385 /* b: p3<<28 | p5<<14 | p7 (unmasked) */ |
| 386 if (!(b&0x80)) |
| 387 { |
| 388 b &= SLOT_4_2_0; |
| 389 /* moved CSE2 up */ |
| 390 /* a &= (0x7f<<14)|(0x7f); */ |
| 391 a = a<<7; |
| 392 a |= b; |
| 393 s = s>>4; |
| 394 *v = ((u64)s)<<32 | a; |
| 395 return 8; |
| 396 } |
| 397 |
| 398 p++; |
| 399 a = a<<15; |
| 400 a |= *p; |
| 401 /* a: p4<<29 | p6<<15 | p8 (unmasked) */ |
| 402 |
| 403 /* moved CSE2 up */ |
| 404 /* a &= (0x7f<<29)|(0x7f<<15)|(0xff); */ |
| 405 b &= SLOT_2_0; |
| 406 b = b<<8; |
| 407 a |= b; |
| 408 |
| 409 s = s<<4; |
| 410 b = p[-4]; |
| 411 b &= 0x7f; |
| 412 b = b>>3; |
| 413 s |= b; |
| 414 |
| 415 *v = ((u64)s)<<32 | a; |
| 416 |
| 417 return 9; |
| 418 } |
| 419 #endif |
227 | 420 |
228 /* For debugging. */ | 421 /* For debugging. */ |
229 #if 0 | 422 #if 0 |
230 #define FNENTRY() fprintf(stderr, "In %s\n", __FUNCTION__) | 423 #define FNENTRY() fprintf(stderr, "In %s\n", __FUNCTION__) |
231 #else | 424 #else |
232 #define FNENTRY() | 425 #define FNENTRY() |
233 #endif | 426 #endif |
234 | 427 |
235 /* Generic constants and helper functions. */ | 428 /* Generic constants and helper functions. */ |
236 | 429 |
237 static const unsigned char kTableLeafPage = 0x0D; | 430 static const unsigned char kTableLeafPage = 0x0D; |
238 static const unsigned char kTableInteriorPage = 0x05; | 431 static const unsigned char kTableInteriorPage = 0x05; |
239 | 432 |
240 /* From section 1.2. */ | 433 /* From section 1.2. */ |
241 static const unsigned kiHeaderPageSizeOffset = 16; | 434 static const unsigned kiHeaderPageSizeOffset = 16; |
242 static const unsigned kiHeaderReservedSizeOffset = 20; | 435 static const unsigned kiHeaderReservedSizeOffset = 20; |
243 static const unsigned kiHeaderEncodingOffset = 56; | 436 static const unsigned kiHeaderEncodingOffset = 56; |
244 /* TODO(shess) |static const unsigned| fails creating the header in GetPager() | 437 static const unsigned knHeaderSize = 100; |
245 ** because |knHeaderSize| isn't |constexpr|. But this isn't C++, either. | |
246 */ | |
247 enum { knHeaderSize = 100}; | |
248 | 438 |
249 /* From section 1.5. */ | 439 /* From section 1.5. */ |
250 static const unsigned kiPageTypeOffset = 0; | 440 static const unsigned kiPageTypeOffset = 0; |
251 static const unsigned kiPageFreeBlockOffset = 1; | 441 /*static const unsigned kiPageFreeBlockOffset = 1;*/ |
252 static const unsigned kiPageCellCountOffset = 3; | 442 static const unsigned kiPageCellCountOffset = 3; |
253 static const unsigned kiPageCellContentOffset = 5; | 443 /*static const unsigned kiPageCellContentOffset = 5;*/ |
254 static const unsigned kiPageFragmentedBytesOffset = 7; | 444 /*static const unsigned kiPageFragmentedBytesOffset = 7;*/ |
255 static const unsigned knPageLeafHeaderBytes = 8; | 445 static const unsigned knPageLeafHeaderBytes = 8; |
256 /* Interior pages contain an additional field. */ | 446 /* Interior pages contain an additional field. */ |
257 static const unsigned kiPageRightChildOffset = 8; | 447 static const unsigned kiPageRightChildOffset = 8; |
258 static const unsigned kiPageInteriorHeaderBytes = 12; | 448 static const unsigned kiPageInteriorHeaderBytes = 12; |
259 | 449 |
260 /* Accepted types are specified by a mask. */ | 450 /* Accepted types are specified by a mask. */ |
261 #define MASK_ROWID (1<<0) | 451 #define MASK_ROWID (1<<0) |
262 #define MASK_INTEGER (1<<1) | 452 #define MASK_INTEGER (1<<1) |
263 #define MASK_FLOAT (1<<2) | 453 #define MASK_FLOAT (1<<2) |
264 #define MASK_TEXT (1<<3) | 454 #define MASK_TEXT (1<<3) |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
413 /* TODO(shess): SQLite by default allocates page metadata in a single allocation | 603 /* TODO(shess): SQLite by default allocates page metadata in a single allocation |
414 ** such that the page's data and metadata are contiguous, see pcache1AllocPage | 604 ** such that the page's data and metadata are contiguous, see pcache1AllocPage |
415 ** in pcache1.c. I believe this was intended to reduce malloc churn. It means | 605 ** in pcache1.c. I believe this was intended to reduce malloc churn. It means |
416 ** that Chromium's automated tooling would be unlikely to see page-buffer | 606 ** that Chromium's automated tooling would be unlikely to see page-buffer |
417 ** overruns. I believe that this code is safe, but for now replicate SQLite's | 607 ** overruns. I believe that this code is safe, but for now replicate SQLite's |
418 ** approach with kExcessSpace. | 608 ** approach with kExcessSpace. |
419 */ | 609 */ |
420 const int kExcessSpace = 128; | 610 const int kExcessSpace = 128; |
421 typedef struct RecoverPage RecoverPage; | 611 typedef struct RecoverPage RecoverPage; |
422 struct RecoverPage { | 612 struct RecoverPage { |
423 Pgno pgno; /* Page number for this page */ | 613 u32 pgno; /* Page number for this page */ |
424 void *pData; /* Page data for pgno */ | 614 void *pData; /* Page data for pgno */ |
425 RecoverPager *pPager; /* The pager this page is part of */ | 615 RecoverPager *pPager; /* The pager this page is part of */ |
426 }; | 616 }; |
427 | 617 |
428 static void pageDestroy(RecoverPage *pPage){ | 618 static void pageDestroy(RecoverPage *pPage){ |
429 sqlite3_free(pPage->pData); | 619 sqlite3_free(pPage->pData); |
430 memset(pPage, 0xA5, sizeof(*pPage)); | 620 memset(pPage, 0xA5, sizeof(*pPage)); |
431 sqlite3_free(pPage); | 621 sqlite3_free(pPage); |
432 } | 622 } |
433 | 623 |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
490 return PageData(pPage, knHeaderSize); | 680 return PageData(pPage, knHeaderSize); |
491 }else{ | 681 }else{ |
492 return PageData(pPage, 0); | 682 return PageData(pPage, 0); |
493 } | 683 } |
494 } | 684 } |
495 | 685 |
496 /* Helper to fetch the pager and page size for the named database. */ | 686 /* Helper to fetch the pager and page size for the named database. */ |
497 static int GetPager(sqlite3 *db, const char *zName, | 687 static int GetPager(sqlite3 *db, const char *zName, |
498 RecoverPager **ppPager, unsigned *pnPageSize, | 688 RecoverPager **ppPager, unsigned *pnPageSize, |
499 int *piEncoding){ | 689 int *piEncoding){ |
500 int rc, iEncoding; | 690 int i, rc, iEncoding; |
501 unsigned nPageSize, nReservedSize; | 691 unsigned nPageSize, nReservedSize; |
502 unsigned char header[knHeaderSize]; | 692 unsigned char header[knHeaderSize]; |
503 sqlite3_file *pFile = NULL; | 693 sqlite3_file *pFile = NULL; |
504 RecoverPager *pPager; | 694 RecoverPager *pPager; |
505 | 695 |
506 rc = sqlite3_file_control(db, zName, SQLITE_FCNTL_FILE_POINTER, &pFile); | 696 rc = sqlite3_file_control(db, zName, SQLITE_FCNTL_FILE_POINTER, &pFile); |
507 if( rc!=SQLITE_OK ) { | 697 if( rc!=SQLITE_OK ) { |
508 return rc; | 698 return rc; |
509 } else if( pFile==NULL ){ | 699 } else if( pFile==NULL ){ |
510 /* The documentation for sqlite3PagerFile() indicates it can return NULL if | 700 /* The documentation for sqlite3PagerFile() indicates it can return NULL if |
(...skipping 17 matching lines...) Expand all Loading... |
528 if( rc==SQLITE_IOERR_SHORT_READ ){ | 718 if( rc==SQLITE_IOERR_SHORT_READ ){ |
529 return SQLITE_CORRUPT; | 719 return SQLITE_CORRUPT; |
530 } | 720 } |
531 return rc; | 721 return rc; |
532 } | 722 } |
533 | 723 |
534 /* Page size must be a power of two between 512 and 32768 inclusive. */ | 724 /* Page size must be a power of two between 512 and 32768 inclusive. */ |
535 nPageSize = decodeUnsigned16(header + kiHeaderPageSizeOffset); | 725 nPageSize = decodeUnsigned16(header + kiHeaderPageSizeOffset); |
536 if( (nPageSize&(nPageSize-1)) || nPageSize>32768 || nPageSize<512 ){ | 726 if( (nPageSize&(nPageSize-1)) || nPageSize>32768 || nPageSize<512 ){ |
537 pFile->pMethods->xUnlock(pFile, SQLITE_LOCK_NONE); | 727 pFile->pMethods->xUnlock(pFile, SQLITE_LOCK_NONE); |
538 return rc; | 728 return SQLITE_CORRUPT; |
539 } | 729 } |
540 | 730 |
541 /* Space reserved a the end of the page for extensions. Usually 0. */ | 731 /* Space reserved a the end of the page for extensions. Usually 0. */ |
542 nReservedSize = header[kiHeaderReservedSizeOffset]; | 732 nReservedSize = header[kiHeaderReservedSizeOffset]; |
543 | 733 |
544 /* 1 for UTF-8, 2 for UTF-16le, 3 for UTF-16be. */ | 734 /* 1 for UTF-8, 2 for UTF-16le, 3 for UTF-16be. */ |
545 iEncoding = decodeUnsigned32(header + kiHeaderEncodingOffset); | 735 iEncoding = decodeUnsigned32(header + kiHeaderEncodingOffset); |
546 if( iEncoding==3 ){ | 736 if( iEncoding==3 ){ |
547 *piEncoding = SQLITE_UTF16BE; | 737 *piEncoding = SQLITE_UTF16BE; |
548 } else if( iEncoding==2 ){ | 738 } else if( iEncoding==2 ){ |
549 *piEncoding = SQLITE_UTF16LE; | 739 *piEncoding = SQLITE_UTF16LE; |
550 } else if( iEncoding==1 ){ | 740 } else if( iEncoding==1 ){ |
551 *piEncoding = SQLITE_UTF8; | 741 *piEncoding = SQLITE_UTF8; |
552 } else { | 742 } else { |
553 /* This case should not be possible. */ | 743 /* This case should not be possible. */ |
554 *piEncoding = SQLITE_UTF8; | 744 *piEncoding = SQLITE_UTF8; |
555 } | 745 } |
| 746 /*assert( iEncoding==1 || iEncoding==2 || iEncoding==3 );*/ |
556 | 747 |
557 rc = pagerCreate(pFile, nPageSize, &pPager); | 748 rc = pagerCreate(pFile, nPageSize, &pPager); |
558 if( rc!=SQLITE_OK ){ | 749 if( rc!=SQLITE_OK ){ |
559 pFile->pMethods->xUnlock(pFile, SQLITE_LOCK_NONE); | 750 pFile->pMethods->xUnlock(pFile, SQLITE_LOCK_NONE); |
560 return rc; | 751 return rc; |
561 } | 752 } |
562 | 753 |
563 *ppPager = pPager; | 754 *ppPager = pPager; |
564 *pnPageSize = nPageSize - nReservedSize; | 755 *pnPageSize = nPageSize - nReservedSize; |
565 *piEncoding = iEncoding; | 756 *piEncoding = iEncoding; |
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
828 | 1019 |
829 /* TODO(shess): Check for cell overlaps? Cells require 4 bytes plus | 1020 /* TODO(shess): Check for cell overlaps? Cells require 4 bytes plus |
830 * a varint. Check could be identical to leaf check (or even a | 1021 * a varint. Check could be identical to leaf check (or even a |
831 * shared helper testing for "Cells starting in this range"?). | 1022 * shared helper testing for "Cells starting in this range"?). |
832 */ | 1023 */ |
833 | 1024 |
834 /* If the offset is broken, return an invalid page number. */ | 1025 /* If the offset is broken, return an invalid page number. */ |
835 return 0; | 1026 return 0; |
836 } | 1027 } |
837 | 1028 |
| 1029 #if 0 |
838 static int interiorCursorEOF(RecoverInteriorCursor *pCursor){ | 1030 static int interiorCursorEOF(RecoverInteriorCursor *pCursor){ |
839 /* Find a parent with remaining children. EOF if none found. */ | 1031 /* Find a parent with remaining children. EOF if none found. */ |
840 while( pCursor && pCursor->iChild>=pCursor->nChildren ){ | 1032 while( pCursor && pCursor->iChild>=pCursor->nChildren ){ |
841 pCursor = pCursor->pParent; | 1033 pCursor = pCursor->pParent; |
842 } | 1034 } |
843 return pCursor==NULL; | 1035 return pCursor==NULL; |
844 } | 1036 } |
| 1037 #endif |
845 | 1038 |
846 /* Internal helper. Used to detect if iPage would cause a loop. */ | 1039 /* Internal helper. Used to detect if iPage would cause a loop. */ |
847 static int interiorCursorPageInUse(RecoverInteriorCursor *pCursor, | 1040 static int interiorCursorPageInUse(RecoverInteriorCursor *pCursor, |
848 unsigned iPage){ | 1041 unsigned iPage){ |
849 /* Find any parent using the indicated page. */ | 1042 /* Find any parent using the indicated page. */ |
850 while( pCursor && pCursor->pPage->pgno!=iPage ){ | 1043 while( pCursor && pCursor->pPage->pgno!=iPage ){ |
851 pCursor = pCursor->pParent; | 1044 pCursor = pCursor->pParent; |
852 } | 1045 } |
853 return pCursor!=NULL; | 1046 return pCursor!=NULL; |
854 } | 1047 } |
(...skipping 596 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1451 /* B-tree leaf cells lead with varint record size, varint rowid and | 1644 /* B-tree leaf cells lead with varint record size, varint rowid and |
1452 * varint header size. | 1645 * varint header size. |
1453 */ | 1646 */ |
1454 /* TODO(shess): The smallest page size is 512 bytes, which has an m | 1647 /* TODO(shess): The smallest page size is 512 bytes, which has an m |
1455 * of 39. Three varints need at most 27 bytes to encode. I think. | 1648 * of 39. Three varints need at most 27 bytes to encode. I think. |
1456 */ | 1649 */ |
1457 if( !checkVarints(pCell, nCellMaxBytes, 3) ){ | 1650 if( !checkVarints(pCell, nCellMaxBytes, 3) ){ |
1458 return ValidateError(); | 1651 return ValidateError(); |
1459 } | 1652 } |
1460 | 1653 |
1461 nRead = getVarint(pCell, &nRecordBytes); | 1654 nRead = recoverGetVarint(pCell, &nRecordBytes); |
1462 assert( iCellOffset+nRead<=pCursor->nPageSize ); | 1655 assert( iCellOffset+nRead<=pCursor->nPageSize ); |
1463 pCursor->nRecordBytes = nRecordBytes; | 1656 pCursor->nRecordBytes = nRecordBytes; |
1464 | 1657 |
1465 nRead += getVarint(pCell + nRead, &iRowid); | 1658 nRead += recoverGetVarint(pCell + nRead, &iRowid); |
1466 assert( iCellOffset+nRead<=pCursor->nPageSize ); | 1659 assert( iCellOffset+nRead<=pCursor->nPageSize ); |
1467 pCursor->iRowid = (i64)iRowid; | 1660 pCursor->iRowid = (i64)iRowid; |
1468 | 1661 |
1469 pCursor->iRecordOffset = iCellOffset + nRead; | 1662 pCursor->iRecordOffset = iCellOffset + nRead; |
1470 | 1663 |
1471 /* Start overflow setup here because nLocalRecordBytes is needed to | 1664 /* Start overflow setup here because nLocalRecordBytes is needed to |
1472 * check cell overlap. | 1665 * check cell overlap. |
1473 */ | 1666 */ |
1474 rc = overflowMaybeCreate(pCursor->pPage, pCursor->nPageSize, | 1667 rc = overflowMaybeCreate(pCursor->pPage, pCursor->nPageSize, |
1475 pCursor->iRecordOffset, pCursor->nRecordBytes, | 1668 pCursor->iRecordOffset, pCursor->nRecordBytes, |
1476 &pCursor->nLocalRecordBytes, | 1669 &pCursor->nLocalRecordBytes, |
1477 &pCursor->pOverflow); | 1670 &pCursor->pOverflow); |
1478 if( rc!=SQLITE_OK ){ | 1671 if( rc!=SQLITE_OK ){ |
1479 return ValidateError(); | 1672 return ValidateError(); |
1480 } | 1673 } |
1481 | 1674 |
1482 /* Check that no other cell starts within this cell. */ | 1675 /* Check that no other cell starts within this cell. */ |
1483 iEndOffset = pCursor->iRecordOffset + pCursor->nLocalRecordBytes; | 1676 iEndOffset = pCursor->iRecordOffset + pCursor->nLocalRecordBytes; |
1484 for( i=0; i<pCursor->nCells && pCellOffsets + i*2 + 2 <= pPageEnd; ++i ){ | 1677 for( i=0; i<pCursor->nCells && pCellOffsets + i*2 + 2 <= pPageEnd; ++i ){ |
1485 const unsigned iOtherOffset = decodeUnsigned16(pCellOffsets + i*2); | 1678 const unsigned iOtherOffset = decodeUnsigned16(pCellOffsets + i*2); |
1486 if( iOtherOffset>iCellOffset && iOtherOffset<iEndOffset ){ | 1679 if( iOtherOffset>iCellOffset && iOtherOffset<iEndOffset ){ |
1487 return ValidateError(); | 1680 return ValidateError(); |
1488 } | 1681 } |
1489 } | 1682 } |
1490 | 1683 |
1491 nRecordHeaderRead = getVarint(pCell + nRead, &nRecordHeaderBytes); | 1684 nRecordHeaderRead = recoverGetVarint(pCell + nRead, &nRecordHeaderBytes); |
1492 assert( nRecordHeaderBytes<=nRecordBytes ); | 1685 assert( nRecordHeaderBytes<=nRecordBytes ); |
1493 pCursor->nRecordHeaderBytes = nRecordHeaderBytes; | 1686 pCursor->nRecordHeaderBytes = nRecordHeaderBytes; |
1494 | 1687 |
1495 /* Large headers could overflow if pages are small. */ | 1688 /* Large headers could overflow if pages are small. */ |
1496 rc = overflowGetSegment(pCursor->pPage, | 1689 rc = overflowGetSegment(pCursor->pPage, |
1497 pCursor->iRecordOffset, pCursor->nLocalRecordBytes, | 1690 pCursor->iRecordOffset, pCursor->nLocalRecordBytes, |
1498 pCursor->pOverflow, 0, nRecordHeaderBytes, | 1691 pCursor->pOverflow, 0, nRecordHeaderBytes, |
1499 &pCursor->pRecordHeader, &pCursor->bFreeRecordHeader); | 1692 &pCursor->pRecordHeader, &pCursor->bFreeRecordHeader); |
1500 if( rc!=SQLITE_OK ){ | 1693 if( rc!=SQLITE_OK ){ |
1501 return ValidateError(); | 1694 return ValidateError(); |
1502 } | 1695 } |
1503 | 1696 |
1504 /* Tally up the column count and size of data. */ | 1697 /* Tally up the column count and size of data. */ |
1505 nRecordCols = 0; | 1698 nRecordCols = 0; |
1506 nRecordColBytes = 0; | 1699 nRecordColBytes = 0; |
1507 while( nRecordHeaderRead<nRecordHeaderBytes ){ | 1700 while( nRecordHeaderRead<nRecordHeaderBytes ){ |
1508 u64 iSerialType; /* Type descriptor for current column. */ | 1701 u64 iSerialType; /* Type descriptor for current column. */ |
1509 if( !checkVarint(pCursor->pRecordHeader + nRecordHeaderRead, | 1702 if( !checkVarint(pCursor->pRecordHeader + nRecordHeaderRead, |
1510 nRecordHeaderBytes - nRecordHeaderRead) ){ | 1703 nRecordHeaderBytes - nRecordHeaderRead) ){ |
1511 return ValidateError(); | 1704 return ValidateError(); |
1512 } | 1705 } |
1513 nRecordHeaderRead += getVarint(pCursor->pRecordHeader + nRecordHeaderRead, | 1706 nRecordHeaderRead += |
1514 &iSerialType); | 1707 recoverGetVarint(pCursor->pRecordHeader + nRecordHeaderRead, |
| 1708 &iSerialType); |
1515 if( iSerialType==10 || iSerialType==11 ){ | 1709 if( iSerialType==10 || iSerialType==11 ){ |
1516 return ValidateError(); | 1710 return ValidateError(); |
1517 } | 1711 } |
1518 nRecordColBytes += SerialTypeLength(iSerialType); | 1712 nRecordColBytes += SerialTypeLength(iSerialType); |
1519 nRecordCols++; | 1713 nRecordCols++; |
1520 } | 1714 } |
1521 pCursor->nRecordCols = nRecordCols; | 1715 pCursor->nRecordCols = nRecordCols; |
1522 | 1716 |
1523 /* Parsing the header used as many bytes as expected. */ | 1717 /* Parsing the header used as many bytes as expected. */ |
1524 if( nRecordHeaderRead!=nRecordHeaderBytes ){ | 1718 if( nRecordHeaderRead!=nRecordHeaderBytes ){ |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1570 | 1764 |
1571 /* Must be able to decode header size. */ | 1765 /* Must be able to decode header size. */ |
1572 pRecordHeader = pCursor->pRecordHeader; | 1766 pRecordHeader = pCursor->pRecordHeader; |
1573 if( !checkVarint(pRecordHeader, pCursor->nRecordHeaderBytes) ){ | 1767 if( !checkVarint(pRecordHeader, pCursor->nRecordHeaderBytes) ){ |
1574 return SQLITE_CORRUPT; | 1768 return SQLITE_CORRUPT; |
1575 } | 1769 } |
1576 | 1770 |
1577 /* Rather than caching the header size and how many bytes it took, | 1771 /* Rather than caching the header size and how many bytes it took, |
1578 * decode it every time. | 1772 * decode it every time. |
1579 */ | 1773 */ |
1580 nRead = getVarint(pRecordHeader, &nRecordHeaderBytes); | 1774 nRead = recoverGetVarint(pRecordHeader, &nRecordHeaderBytes); |
1581 assert( nRecordHeaderBytes==pCursor->nRecordHeaderBytes ); | 1775 assert( nRecordHeaderBytes==pCursor->nRecordHeaderBytes ); |
1582 | 1776 |
1583 /* Scan forward to the indicated column. Scans to _after_ column | 1777 /* Scan forward to the indicated column. Scans to _after_ column |
1584 * for later range checking. | 1778 * for later range checking. |
1585 */ | 1779 */ |
1586 /* TODO(shess): This could get expensive for very wide tables. An | 1780 /* TODO(shess): This could get expensive for very wide tables. An |
1587 * array of iSerialType could be built in leafCursorCellDecode(), but | 1781 * array of iSerialType could be built in leafCursorCellDecode(), but |
1588 * the number of columns is dynamic per row, so it would add memory | 1782 * the number of columns is dynamic per row, so it would add memory |
1589 * management complexity. Enough info to efficiently forward | 1783 * management complexity. Enough info to efficiently forward |
1590 * iterate could be kept, if all clients forward iterate | 1784 * iterate could be kept, if all clients forward iterate |
1591 * (recoverColumn() may not). | 1785 * (recoverColumn() may not). |
1592 */ | 1786 */ |
1593 iColEndOffset = 0; | 1787 iColEndOffset = 0; |
1594 nColsSkipped = 0; | 1788 nColsSkipped = 0; |
1595 while( nColsSkipped<=iCol && nRead<nRecordHeaderBytes ){ | 1789 while( nColsSkipped<=iCol && nRead<nRecordHeaderBytes ){ |
1596 if( !checkVarint(pRecordHeader + nRead, nRecordHeaderBytes - nRead) ){ | 1790 if( !checkVarint(pRecordHeader + nRead, nRecordHeaderBytes - nRead) ){ |
1597 return SQLITE_CORRUPT; | 1791 return SQLITE_CORRUPT; |
1598 } | 1792 } |
1599 nRead += getVarint(pRecordHeader + nRead, &iSerialType); | 1793 nRead += recoverGetVarint(pRecordHeader + nRead, &iSerialType); |
1600 iColEndOffset += SerialTypeLength(iSerialType); | 1794 iColEndOffset += SerialTypeLength(iSerialType); |
1601 nColsSkipped++; | 1795 nColsSkipped++; |
1602 } | 1796 } |
1603 | 1797 |
1604 /* Column's data extends past record's end. */ | 1798 /* Column's data extends past record's end. */ |
1605 if( nRecordHeaderBytes+iColEndOffset>pCursor->nRecordBytes ){ | 1799 if( nRecordHeaderBytes+iColEndOffset>pCursor->nRecordBytes ){ |
1606 return SQLITE_CORRUPT; | 1800 return SQLITE_CORRUPT; |
1607 } | 1801 } |
1608 | 1802 |
1609 *piColType = iSerialType; | 1803 *piColType = iSerialType; |
(...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1984 recoverRowid, /* xRowid - read data */ | 2178 recoverRowid, /* xRowid - read data */ |
1985 0, /* xUpdate - write data */ | 2179 0, /* xUpdate - write data */ |
1986 0, /* xBegin - begin transaction */ | 2180 0, /* xBegin - begin transaction */ |
1987 0, /* xSync - sync transaction */ | 2181 0, /* xSync - sync transaction */ |
1988 0, /* xCommit - commit transaction */ | 2182 0, /* xCommit - commit transaction */ |
1989 0, /* xRollback - rollback transaction */ | 2183 0, /* xRollback - rollback transaction */ |
1990 0, /* xFindFunction - function overloading */ | 2184 0, /* xFindFunction - function overloading */ |
1991 0, /* xRename - rename the table */ | 2185 0, /* xRename - rename the table */ |
1992 }; | 2186 }; |
1993 | 2187 |
1994 CHROMIUM_SQLITE_API | 2188 SQLITE_API |
1995 int recoverVtableInit(sqlite3 *db){ | 2189 int recoverVtableInit(sqlite3 *db){ |
1996 return sqlite3_create_module_v2(db, "recover", &recoverModule, NULL, 0); | 2190 return sqlite3_create_module_v2(db, "recover", &recoverModule, NULL, 0); |
1997 } | 2191 } |
1998 | 2192 |
1999 /* This section of code is for parsing the create input and | 2193 /* This section of code is for parsing the create input and |
2000 * initializing the module. | 2194 * initializing the module. |
2001 */ | 2195 */ |
2002 | 2196 |
2003 /* Find the next word in zText and place the endpoints in pzWord*. | 2197 /* Find the next word in zText and place the endpoints in pzWord*. |
2004 * Returns true if the word is non-empty. "Word" is defined as | 2198 * Returns true if the word is non-empty. "Word" is defined as |
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2222 if( !pRecover ){ | 2416 if( !pRecover ){ |
2223 return SQLITE_NOMEM; | 2417 return SQLITE_NOMEM; |
2224 } | 2418 } |
2225 memset(pRecover, 0, sizeof(*pRecover)); | 2419 memset(pRecover, 0, sizeof(*pRecover)); |
2226 pRecover->base.pModule = &recoverModule; | 2420 pRecover->base.pModule = &recoverModule; |
2227 pRecover->db = db; | 2421 pRecover->db = db; |
2228 | 2422 |
2229 /* Parse out db.table, assuming main if no dot. */ | 2423 /* Parse out db.table, assuming main if no dot. */ |
2230 zDot = strchr(argv[3], '.'); | 2424 zDot = strchr(argv[3], '.'); |
2231 if( !zDot ){ | 2425 if( !zDot ){ |
2232 pRecover->zDb = sqlite3_strdup(db->aDb[0].zName); | 2426 pRecover->zDb = sqlite3_strdup("main"); |
2233 pRecover->zTable = sqlite3_strdup(argv[3]); | 2427 pRecover->zTable = sqlite3_strdup(argv[3]); |
2234 }else if( zDot>argv[3] && zDot[1]!='\0' ){ | 2428 }else if( zDot>argv[3] && zDot[1]!='\0' ){ |
2235 pRecover->zDb = sqlite3_strndup(argv[3], zDot - argv[3]); | 2429 pRecover->zDb = sqlite3_strndup(argv[3], zDot - argv[3]); |
2236 pRecover->zTable = sqlite3_strdup(zDot + 1); | 2430 pRecover->zTable = sqlite3_strdup(zDot + 1); |
2237 }else{ | 2431 }else{ |
2238 /* ".table" or "db." not allowed. */ | 2432 /* ".table" or "db." not allowed. */ |
2239 *pzErr = sqlite3_mprintf("ill-formed table specifier"); | 2433 *pzErr = sqlite3_mprintf("ill-formed table specifier"); |
2240 recoverRelease(pRecover); | 2434 recoverRelease(pRecover); |
2241 return SQLITE_ERROR; | 2435 return SQLITE_ERROR; |
2242 } | 2436 } |
(...skipping 29 matching lines...) Expand all Loading... |
2272 rc = sqlite3_declare_vtab(db, zCreateSql); | 2466 rc = sqlite3_declare_vtab(db, zCreateSql); |
2273 sqlite3_free(zCreateSql); | 2467 sqlite3_free(zCreateSql); |
2274 if( rc!=SQLITE_OK ){ | 2468 if( rc!=SQLITE_OK ){ |
2275 recoverRelease(pRecover); | 2469 recoverRelease(pRecover); |
2276 return rc; | 2470 return rc; |
2277 } | 2471 } |
2278 | 2472 |
2279 *ppVtab = (sqlite3_vtab *)pRecover; | 2473 *ppVtab = (sqlite3_vtab *)pRecover; |
2280 return SQLITE_OK; | 2474 return SQLITE_OK; |
2281 } | 2475 } |
OLD | NEW |