Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | merge trunk |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | cleanX |
Files: | files | file ages | folders |
SHA1: |
0ab66b742c58672d9d44c81a94614dee |
User & Date: | jan.nijtmans 2015-08-21 09:15:50.745 |
Context
2015-09-04
| ||
11:45 | merge trunk ... (check-in: 45cbbad4 user: jan.nijtmans tags: cleanX) | |
2015-08-21
| ||
09:15 | merge trunk ... (check-in: 0ab66b74 user: jan.nijtmans tags: cleanX) | |
2015-08-18
| ||
13:28 | Update the built-in SQLite to version 3.8.11.1 ... (check-in: 7842b8ab user: jan.nijtmans tags: trunk) | |
2015-07-14
| ||
09:55 | merge trunk ... (check-in: 3ddf95e3 user: jan.nijtmans tags: cleanX) | |
Changes
Added .fossil-settings/clean-glob.
> > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | *.a *.lib *.manifest *.o *.obj *.pdb *.res Makefile bld/* wbld/* win/*.c win/*.h win/*.exe win/headers win/linkopts autoconfig.h config.log |
Changes to .fossil-settings/ignore-glob.
1 2 | compat/openssl* compat/tcl* | < < < < < < < < < < < < < < < < < | 1 2 3 4 5 | compat/openssl* compat/tcl* fossil fossil.exe win/fossil.exe |
Changes to src/blob.c.
︙ | ︙ | |||
269 270 271 272 273 274 275 276 277 278 279 280 281 282 | pBlob->xRealloc = blobReallocStatic; } /* ** Append text or data to the end of a blob. */ void blob_append(Blob *pBlob, const char *aData, int nData){ blob_is_init(pBlob); if( nData<0 ) nData = strlen(aData); if( nData==0 ) return; if( pBlob->nUsed + nData >= pBlob->nAlloc ){ pBlob->xRealloc(pBlob, pBlob->nUsed + nData + pBlob->nAlloc + 100); if( pBlob->nUsed + nData >= pBlob->nAlloc ){ blob_panic(); | > | 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 | pBlob->xRealloc = blobReallocStatic; } /* ** Append text or data to the end of a blob. */ void blob_append(Blob *pBlob, const char *aData, int nData){ assert( aData!=0 || nData==0 ); blob_is_init(pBlob); if( nData<0 ) nData = strlen(aData); if( nData==0 ) return; if( pBlob->nUsed + nData >= pBlob->nAlloc ){ pBlob->xRealloc(pBlob, pBlob->nUsed + nData + pBlob->nAlloc + 100); if( pBlob->nUsed + nData >= pBlob->nAlloc ){ blob_panic(); |
︙ | ︙ |
Changes to src/cgi.c.
︙ | ︙ | |||
1048 1049 1050 1051 1052 1053 1054 | } } /* If no match is found and the name begins with an upper-case ** letter, then check to see if there is an environment variable ** with the given name. */ | | | 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 | } } /* If no match is found and the name begins with an upper-case ** letter, then check to see if there is an environment variable ** with the given name. */ if( zName && fossil_isupper(zName[0]) ){ const char *zValue = fossil_getenv(zName); if( zValue ){ cgi_set_parameter_nocopy(zName, zValue, 0); CGIDEBUG(("env-match [%s] = [%s]\n", zName, zValue)); return zValue; } } |
︙ | ︙ |
Changes to src/checkin.c.
︙ | ︙ | |||
640 641 642 643 644 645 646 | ** specified by the --clean option. No file that matches glob patterns ** specified by --ignore or --keep will ever be deleted. The default ** values for --clean, --ignore, and --keep are determined by the ** (versionable) clean-glob, ignore-glob, and keep-glob settings. ** Files and subdirectories whose names begin with "." are automatically ** ignored unless the --dotfiles option is used. ** | | | | | | 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 | ** specified by the --clean option. No file that matches glob patterns ** specified by --ignore or --keep will ever be deleted. The default ** values for --clean, --ignore, and --keep are determined by the ** (versionable) clean-glob, ignore-glob, and keep-glob settings. ** Files and subdirectories whose names begin with "." are automatically ** ignored unless the --dotfiles option is used. ** ** The --verily option ignores the keep-glob and ignore-glob settings ** and turns on --dotfiles, and --emptydirs. Use the --verily ** option when you really want to clean up everything. Extreme care ** should be exercised when using the --verily option. ** ** Options: ** --allckouts Check for empty directories within any checkouts ** that may be nested within the current one. This ** option should be used with great care because the ** empty-dirs setting (and other applicable settings) ** belonging to the other repositories, if any, will |
︙ | ︙ | |||
670 671 672 673 674 675 676 | ** argument. Matching files, if any, are removed ** prior to checking for any empty directories; ** therefore, directories that contain only files ** that were removed will be removed as well. ** -f|--force Remove files without prompting. ** -x|--verily WARNING: Removes everything that is not a managed ** file or the repository itself. This option | | | > | | 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 | ** argument. Matching files, if any, are removed ** prior to checking for any empty directories; ** therefore, directories that contain only files ** that were removed will be removed as well. ** -f|--force Remove files without prompting. ** -x|--verily WARNING: Removes everything that is not a managed ** file or the repository itself. This option ** implies the --emptydirs, --dotfiles, and ** --disable-undo options. Furthermore, it completely ** disregards the keep-glob and ignore-glob settings. ** However, it does honor the --ignore and --keep ** options. ** --clean <CSG> WARNING: Never prompt to delete any files matching ** this comma separated list of glob patterns. Also, ** deletions of any files matching this pattern list ** cannot be undone. ** --ignore <CSG> Ignore files matching patterns from the ** comma separated list of glob patterns. |
︙ | ︙ | |||
729 730 731 732 733 734 735 736 737 738 739 740 741 | verboseFlag = find_option("verbose","v",0)!=0; zKeepFlag = find_option("keep",0,1); zCleanFlag = find_option("clean",0,1); db_must_be_within_tree(); if( find_option("verily","x",0)!=0 ){ verilyFlag = 1; emptyDirsFlag = 1; scanFlags |= SCAN_ALL; zCleanFlag = 0; } if( zIgnoreFlag==0 ){ zIgnoreFlag = db_get("ignore-glob", 0); } | > | | 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 | verboseFlag = find_option("verbose","v",0)!=0; zKeepFlag = find_option("keep",0,1); zCleanFlag = find_option("clean",0,1); db_must_be_within_tree(); if( find_option("verily","x",0)!=0 ){ verilyFlag = 1; emptyDirsFlag = 1; disableUndo = 1; scanFlags |= SCAN_ALL; zCleanFlag = 0; } if( zIgnoreFlag==0 ){ zIgnoreFlag = db_get("ignore-glob", 0); } if( zKeepFlag==0 && !verilyFlag ){ zKeepFlag = db_get("keep-glob", 0); } if( zCleanFlag==0 && !verilyFlag ){ zCleanFlag = db_get("clean-glob", 0); } if( db_get_boolean("dotfiles", 0) ) scanFlags |= SCAN_ALL; verify_all_options(); |
︙ | ︙ | |||
767 768 769 770 771 772 773 | if( file_tree_name(g.zRepositoryName, &repo, 0, 0) ){ db_multi_exec("DELETE FROM sfile WHERE x=%B", &repo); } db_multi_exec("DELETE FROM sfile WHERE x IN (SELECT pathname FROM vfile)"); while( db_step(&q)==SQLITE_ROW ){ const char *zName = db_column_text(&q, 0); if( glob_match(pKeep, zName+nRoot) ){ | | | 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 | if( file_tree_name(g.zRepositoryName, &repo, 0, 0) ){ db_multi_exec("DELETE FROM sfile WHERE x=%B", &repo); } db_multi_exec("DELETE FROM sfile WHERE x IN (SELECT pathname FROM vfile)"); while( db_step(&q)==SQLITE_ROW ){ const char *zName = db_column_text(&q, 0); if( glob_match(pKeep, zName+nRoot) ){ if( verboseFlag ){ fossil_print("KEPT file \"%s\" not removed (due to --keep" " or \"keep-glob\")\n", zName+nRoot); } continue; } if( !dryRunFlag && !glob_match(pClean, zName+nRoot) && !(verilyFlag && glob_match(pIgnore, zName+nRoot)) ){ |
︙ | ︙ | |||
831 832 833 834 835 836 837 | " WHERE x NOT IN (%s) AND y = 0" " ORDER BY 1 DESC", g.zLocalRoot, fossil_all_reserved_names(0) ); while( db_step(&q)==SQLITE_ROW ){ const char *zName = db_column_text(&q, 0); if( glob_match(pKeep, zName+nRoot) ){ | | | 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 | " WHERE x NOT IN (%s) AND y = 0" " ORDER BY 1 DESC", g.zLocalRoot, fossil_all_reserved_names(0) ); while( db_step(&q)==SQLITE_ROW ){ const char *zName = db_column_text(&q, 0); if( glob_match(pKeep, zName+nRoot) ){ if( verboseFlag ){ fossil_print("KEPT directory \"%s\" not removed (due to --keep" " or \"keep-glob\")\n", zName+nRoot); } continue; } if( !allDirFlag && !dryRunFlag && !glob_match(pClean, zName+nRoot) && !(verilyFlag && glob_match(pIgnore, zName+nRoot)) ){ |
︙ | ︙ |
Changes to src/db.c.
︙ | ︙ | |||
1972 1973 1974 1975 1976 1977 1978 | ){ /* There's a versioned setting, and a non-versioned setting. Tell ** the user about the conflict */ fossil_warning( "setting %s has both versioned and non-versioned values: using " "versioned value from file .fossil-settings/%s (to silence this " "warning, either create an empty file named " | | > | | 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 | ){ /* There's a versioned setting, and a non-versioned setting. Tell ** the user about the conflict */ fossil_warning( "setting %s has both versioned and non-versioned values: using " "versioned value from file .fossil-settings/%s (to silence this " "warning, either create an empty file named " ".fossil-settings/%s.no-warn in the check-out root, " "or delete the non-versioned setting " "with \"fossil unset %s\")", zName, zName, zName, zName ); } /* Prefer the versioned setting */ return ( zVersionedSetting!=0 ) ? zVersionedSetting : zNonVersionedSetting; } |
︙ | ︙ | |||
2460 2461 2462 2463 2464 2465 2466 | ** %fossil unset PROPERTY ?OPTIONS? ** ** The "settings" command with no arguments lists all properties and their ** values. With just a property name it shows the value of that property. ** With a value argument it changes the property for the current repository. ** ** Settings marked as versionable are overridden by the contents of the | | | 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 | ** %fossil unset PROPERTY ?OPTIONS? ** ** The "settings" command with no arguments lists all properties and their ** values. With just a property name it shows the value of that property. ** With a value argument it changes the property for the current repository. ** ** Settings marked as versionable are overridden by the contents of the ** file named .fossil-settings/PROPERTY in the check-out root, if that ** file exists. ** ** The "unset" command clears a property setting. ** ** ** access-log If enabled, record successful and failed login attempts ** in the "accesslog" table. Default: off |
︙ | ︙ |
Changes to src/delta.c.
︙ | ︙ | |||
587 588 589 590 591 592 593 594 595 596 597 598 599 600 | #endif if( total!=limit ){ /* ERROR: generated size does not match predicted size */ return -1; } return total; } default: { /* ERROR: unknown delta operator */ return -1; } } } /* ERROR: unterminated delta */ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 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 659 660 661 | #endif if( total!=limit ){ /* ERROR: generated size does not match predicted size */ return -1; } return total; } default: { /* ERROR: unknown delta operator */ return -1; } } } /* ERROR: unterminated delta */ return -1; } /* ** Analyze a delta. Figure out the total number of bytes copied from ** source to target, and the total number of bytes inserted by the delta, ** and return both numbers. */ int delta_analyze( const char *zDelta, /* Delta to apply to the pattern */ int lenDelta, /* Length of the delta */ int *pnCopy, /* OUT: Number of bytes copied */ int *pnInsert /* OUT: Number of bytes inserted */ ){ unsigned int nInsert = 0; unsigned int nCopy = 0; (void)getInt(&zDelta, &lenDelta); if( *zDelta!='\n' ){ /* ERROR: size integer not terminated by "\n" */ return -1; } zDelta++; lenDelta--; while( *zDelta && lenDelta>0 ){ unsigned int cnt, ofst; cnt = getInt(&zDelta, &lenDelta); switch( zDelta[0] ){ case '@': { zDelta++; lenDelta--; ofst = getInt(&zDelta, &lenDelta); if( lenDelta>0 && zDelta[0]!=',' ){ /* ERROR: copy command not terminated by ',' */ return -1; } zDelta++; lenDelta--; nCopy += cnt; break; } case ':': { zDelta++; lenDelta--; nInsert += cnt; if( cnt>lenDelta ){ /* ERROR: insert count exceeds size of delta */ return -1; } zDelta += cnt; lenDelta -= cnt; break; } case ';': { *pnCopy = nCopy; *pnInsert = nInsert; return 0; } default: { /* ERROR: unknown delta operator */ return -1; } } } /* ERROR: unterminated delta */ |
︙ | ︙ |
Changes to src/deltacmd.c.
︙ | ︙ | |||
41 42 43 44 45 46 47 | blob_resize(pDelta, len); return 0; } /* ** COMMAND: test-delta-create ** | > > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | blob_resize(pDelta, len); return 0; } /* ** COMMAND: test-delta-create ** ** Usage: %fossil test-delta-create FILE1 FILE2 DELTA ** ** Create and output a delta that carries FILE1 into FILE2. ** Store the result in DELTA. */ void delta_create_cmd(void){ Blob orig, target, delta; if( g.argc!=5 ){ usage("ORIGIN TARGET DELTA"); } if( blob_read_from_file(&orig, g.argv[2])<0 ){ fossil_fatal("cannot read %s\n", g.argv[2]); } if( blob_read_from_file(&target, g.argv[3])<0 ){ fossil_fatal("cannot read %s\n", g.argv[3]); } blob_delta_create(&orig, &target, &delta); if( blob_write_to_file(&delta, g.argv[4])<blob_size(&delta) ){ fossil_fatal("cannot write %s\n", g.argv[4]); } blob_reset(&orig); blob_reset(&target); blob_reset(&delta); } /* ** COMMAND: test-delta-analyze ** ** Usage: %fossil test-delta-analyze FILE1 FILE2 ** ** Create and a delta that carries FILE1 into FILE2. Print the ** number bytes copied and the number of bytes inserted. */ void delta_analyze_cmd(void){ Blob orig, target, delta; int nCopy = 0; int nInsert = 0; int sz1, sz2; if( g.argc!=4 ){ usage("ORIGIN TARGET"); } if( blob_read_from_file(&orig, g.argv[2])<0 ){ fossil_fatal("cannot read %s\n", g.argv[2]); } if( blob_read_from_file(&target, g.argv[3])<0 ){ fossil_fatal("cannot read %s\n", g.argv[3]); } blob_delta_create(&orig, &target, &delta); delta_analyze(blob_buffer(&delta), blob_size(&delta), &nCopy, &nInsert); sz1 = blob_size(&orig); sz2 = blob_size(&target); blob_reset(&orig); blob_reset(&target); blob_reset(&delta); fossil_print("original size: %8d\n", sz1); fossil_print("bytes copied: %8d (%.1f%% of target)\n", nCopy, (100.0*nCopy)/sz2); fossil_print("bytes inserted: %8d (%.1f%% of target)\n", nInsert, (100.0*nInsert)/sz2); fossil_print("final size: %8d\n", sz2); } /* ** Apply the delta in pDelta to the original file pOriginal to generate ** the target file pTarget. The pTarget blob is initialized by this ** routine. ** ** It works ok for pTarget and pOriginal to be the same blob. |
︙ | ︙ | |||
100 101 102 103 104 105 106 | *pTarget = out; return len; } /* ** COMMAND: test-delta-apply ** | | > | > > > | 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 | *pTarget = out; return len; } /* ** COMMAND: test-delta-apply ** ** Usage: %fossil test-delta-apply FILE1 DELTA ** ** Apply DELTA to FILE1 and output the result. */ void delta_apply_cmd(void){ Blob orig, target, delta; if( g.argc!=5 ){ usage("ORIGIN DELTA TARGET"); } if( blob_read_from_file(&orig, g.argv[2])<0 ){ fossil_fatal("cannot read %s\n", g.argv[2]); } if( blob_read_from_file(&delta, g.argv[3])<0 ){ fossil_fatal("cannot read %s\n", g.argv[3]); } blob_delta_apply(&orig, &delta, &target); if( blob_write_to_file(&target, g.argv[4])<blob_size(&target) ){ fossil_fatal("cannot write %s\n", g.argv[4]); } blob_reset(&orig); blob_reset(&target); blob_reset(&delta); } /* ** COMMAND: test-delta ** ** Usage: %fossil test-delta FILE1 FILE2 ** ** Read two files named on the command-line. Create and apply deltas ** going in both directions. Verify that the original files are ** correctly recovered. */ void cmd_test_delta(void){ Blob f1, f2; /* Original file content */ |
︙ | ︙ |
Changes to src/doc.c.
︙ | ︙ | |||
521 522 523 524 525 526 527 | ** The "ckout" CHECKIN is intended for development - to provide a mechanism ** for looking at what a file will look like using the /doc webpage after ** it gets checked in. ** ** The file extension is used to decide how to render the file. ** ** If FILE ends in "/" then names "FILE/index.html", "FILE/index.wiki", | | | 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 | ** The "ckout" CHECKIN is intended for development - to provide a mechanism ** for looking at what a file will look like using the /doc webpage after ** it gets checked in. ** ** The file extension is used to decide how to render the file. ** ** If FILE ends in "/" then names "FILE/index.html", "FILE/index.wiki", ** and "FILE/index.md" are tried in that order. If none of those are found, ** then FILE is completely replaced by "404.md" and tried. If that is ** not found, then a default 404 screen is generated. */ void doc_page(void){ const char *zName; /* Argument to the /doc page */ const char *zOrigName = "?"; /* Original document name */ const char *zMime; /* Document MIME type */ |
︙ | ︙ | |||
545 546 547 548 549 550 551 | }; login_check_credentials(); if( !g.perm.Read ){ login_needed(g.anon.Read); return; } blob_init(&title, 0, 0); db_begin_transaction(); while( rid==0 && (++nMiss)<=ArraySize(azSuffix) ){ | > | | | 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 | }; login_check_credentials(); if( !g.perm.Read ){ login_needed(g.anon.Read); return; } blob_init(&title, 0, 0); db_begin_transaction(); while( rid==0 && (++nMiss)<=ArraySize(azSuffix) ){ zName = P("name"); if( zName==0 || zName[0]==0 ) zName = "tip/index.wiki"; for(i=0; zName[i] && zName[i]!='/'; i++){} zCheckin = mprintf("%.*s", i, zName); if( fossil_strcmp(zCheckin,"ckout")==0 && g.localOpen==0 ){ zCheckin = "tip"; } if( nMiss==ArraySize(azSuffix) ){ zName = "404.md"; }else if( zName[i]==0 ){ assert( nMiss>=0 && nMiss<ArraySize(azSuffix) ); zName = azSuffix[nMiss]; |
︙ | ︙ |
Changes to src/foci.c.
︙ | ︙ | |||
165 166 167 168 169 170 171 | int idxNum, const char *idxStr, int argc, sqlite3_value **argv ){ FociCursor *pCur = (FociCursor *)pCursor; manifest_destroy(pCur->pMan); if( idxNum ){ pCur->pMan = manifest_get(sqlite3_value_int(argv[0]), CFTYPE_MANIFEST, 0); | | | | > < > | 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 | int idxNum, const char *idxStr, int argc, sqlite3_value **argv ){ FociCursor *pCur = (FociCursor *)pCursor; manifest_destroy(pCur->pMan); if( idxNum ){ pCur->pMan = manifest_get(sqlite3_value_int(argv[0]), CFTYPE_MANIFEST, 0); if( pCur->pMan ){ manifest_file_rewind(pCur->pMan); pCur->pFile = manifest_file_next(pCur->pMan, 0); } }else{ pCur->pMan = 0; } pCur->iFile = 0; return SQLITE_OK; } static int fociColumn( sqlite3_vtab_cursor *pCursor, sqlite3_context *ctx, int i |
︙ | ︙ |
Changes to src/info.c.
︙ | ︙ | |||
1884 1885 1886 1887 1888 1889 1890 | if( (objType & (OBJTYPE_WIKI|OBJTYPE_TICKET))!=0 ){ style_submenu_element("Parsed", "Parsed", "%R/info/%s", zUuid); } if( descOnly ){ style_submenu_element("Content", "Content", "%R/artifact/%s", zUuid); }else{ style_submenu_element("Line Numbers", "Line Numbers", | | | 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 | if( (objType & (OBJTYPE_WIKI|OBJTYPE_TICKET))!=0 ){ style_submenu_element("Parsed", "Parsed", "%R/info/%s", zUuid); } if( descOnly ){ style_submenu_element("Content", "Content", "%R/artifact/%s", zUuid); }else{ style_submenu_element("Line Numbers", "Line Numbers", "%R/artifact/%s%s",zUuid, ((zLn&&*zLn) ? "" : "?txt=1&ln=0")); @ <hr /> content_get(rid, &content); if( renderAsWiki ){ wiki_render_by_mimetype(&content, zMime); }else if( renderAsHtml ){ @ <iframe src="%R/raw/%T(blob_str(&downloadName))?name=%s(zUuid)" |
︙ | ︙ | |||
2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 | } return 0; } while( fossil_isspace(zB[0]) ) zB++; while( fossil_isspace(zA[0]) ) zA++; return zA[0]==0 && zB[0]==0; } /* ** WEBPAGE: ci_edit ** URL: /ci_edit?r=RID&c=NEWCOMMENT&u=NEWUSER ** ** Present a dialog for updating properties of a check-in. ** | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 | } return 0; } while( fossil_isspace(zB[0]) ) zB++; while( fossil_isspace(zA[0]) ) zA++; return zA[0]==0 && zB[0]==0; } /* ** The following methods operate on the newtags temporary table ** that is used to collect various changes to be added to a control ** artifact for a check-in edit. */ static void init_newtags(void){ db_multi_exec("CREATE TEMP TABLE newtags(tag UNIQUE, prefix, value)"); } static void change_special( const char *zName, /* Name of the special tag */ const char *zOp, /* Operation prefix (e.g. +,-,*) */ const char *zValue /* Value of the tag */ ){ db_multi_exec("REPLACE INTO newtags VALUES(%Q,'%q',%Q)", zName, zOp, zValue); } static void change_sym_tag(const char *zTag, const char *zOp){ db_multi_exec("REPLACE INTO newtags VALUES('sym-%q',%Q,NULL)", zTag, zOp); } static void cancel_special(const char *zTag){ change_special(zTag,"-",0); } static void add_color(const char *zNewColor, int fPropagateColor){ change_special("bgcolor",fPropagateColor ? "*" : "+", zNewColor); } static void cancel_color(void){ change_special("bgcolor","-",0); } static void add_comment(const char *zNewComment){ change_special("comment","+",zNewComment); } static void add_date(const char *zNewDate){ change_special("date","+",zNewDate); } static void add_user(const char *zNewUser){ change_special("user","+",zNewUser); } static void add_tag(const char *zNewTag){ change_sym_tag(zNewTag,"+"); } static void cancel_tag(int rid, const char *zCancelTag){ if( db_exists("SELECT 1 FROM tagxref, tag" " WHERE tagxref.rid=%d AND tagtype>0" " AND tagxref.tagid=tag.tagid AND tagname='sym-%q'", rid, zCancelTag) ) change_sym_tag(zCancelTag,"-"); } static void hide_branch(void){ change_special("hidden","*",0); } static void close_leaf(int rid){ change_special("closed",is_a_leaf(rid)?"+":"*",0); } static void change_branch(int rid, const char *zNewBranch){ db_multi_exec( "REPLACE INTO newtags " " SELECT tagname, '-', NULL FROM tagxref, tag" " WHERE tagxref.rid=%d AND tagtype==2" " AND tagname GLOB 'sym-*'" " AND tag.tagid=tagxref.tagid", rid ); change_special("branch","*",zNewBranch); change_sym_tag(zNewBranch,"*"); } /* ** The apply_newtags method is called after all newtags have been added ** and the control artifact is completed and then written to the DB. */ static void apply_newtags(Blob *ctrl, int rid, const char *zUuid){ Stmt q; int nChng = 0; db_prepare(&q, "SELECT tag, prefix, value FROM newtags" " ORDER BY prefix || tag"); while( db_step(&q)==SQLITE_ROW ){ const char *zTag = db_column_text(&q, 0); const char *zPrefix = db_column_text(&q, 1); const char *zValue = db_column_text(&q, 2); nChng++; if( zValue ){ blob_appendf(ctrl, "T %s%F %s %F\n", zPrefix, zTag, zUuid, zValue); }else{ blob_appendf(ctrl, "T %s%F %s\n", zPrefix, zTag, zUuid); } } db_finalize(&q); if( nChng>0 ){ int nrid; Blob cksum; blob_appendf(ctrl, "U %F\n", login_name()); md5sum_blob(ctrl, &cksum); blob_appendf(ctrl, "Z %b\n", &cksum); db_begin_transaction(); g.markPrivate = content_is_private(rid); nrid = content_put(ctrl); manifest_crosslink(nrid, ctrl, MC_PERMIT_HOOKS); assert( blob_is_reset(ctrl) ); db_end_transaction(0); } } /* ** This method checks that the date can be parsed. ** Returns 1 if datetime() can validate, 0 otherwise. */ int is_datetime(const char* zDate){ return db_int(0, "SELECT datetime(%Q) NOT NULL", zDate); } /* ** WEBPAGE: ci_edit ** URL: /ci_edit?r=RID&c=NEWCOMMENT&u=NEWUSER ** ** Present a dialog for updating properties of a check-in. ** |
︙ | ︙ | |||
2352 2353 2354 2355 2356 2357 2358 | zNewBrFlag = P("newbr") ? " checked" : ""; zNewBranch = PDT("brname",""); zCloseFlag = P("close") ? " checked" : ""; zHideFlag = P("hide") ? " checked" : ""; if( P("apply") ){ Blob ctrl; char *zNow; | < | < < | < < < < < | < < | < < < | < < < | < < | < | < | < < | < < < | < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < | 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 | zNewBrFlag = P("newbr") ? " checked" : ""; zNewBranch = PDT("brname",""); zCloseFlag = P("close") ? " checked" : ""; zHideFlag = P("hide") ? " checked" : ""; if( P("apply") ){ Blob ctrl; char *zNow; login_verify_csrf_secret(); blob_zero(&ctrl); zNow = date_in_standard_format(zChngTime ? zChngTime : "now"); blob_appendf(&ctrl, "D %s\n", zNow); init_newtags(); if( zNewColor[0] && (fPropagateColor!=fNewPropagateColor || fossil_strcmp(zColor,zNewColor)!=0) ) add_color(zNewColor,fNewPropagateColor); if( zNewColor[0]==0 && zColor[0]!=0 ) cancel_color(); if( comment_compare(zComment,zNewComment)==0 ) add_comment(zNewComment); if( fossil_strcmp(zDate,zNewDate)!=0 ) add_date(zNewDate); if( fossil_strcmp(zUser,zNewUser)!=0 ) add_user(zNewUser); db_prepare(&q, "SELECT tag.tagid, tagname FROM tagxref, tag" " WHERE tagxref.rid=%d AND tagtype>0 AND tagxref.tagid=tag.tagid", rid ); while( db_step(&q)==SQLITE_ROW ){ int tagid = db_column_int(&q, 0); const char *zTag = db_column_text(&q, 1); char zLabel[30]; sqlite3_snprintf(sizeof(zLabel), zLabel, "c%d", tagid); if( P(zLabel) ) cancel_special(zTag); } db_finalize(&q); if( zHideFlag[0] ) hide_branch(); if( zCloseFlag[0] ) close_leaf(rid); if( zNewTagFlag[0] && zNewTag[0] ) add_tag(zNewTag); if( zNewBrFlag[0] && zNewBranch[0] ) change_branch(rid,zNewBranch); apply_newtags(&ctrl, rid, zUuid); cgi_redirectf("ci?name=%s", zUuid); } blob_zero(&comment); blob_append(&comment, zNewComment, -1); zUuid[10] = 0; style_header("Edit Check-in [%s]", zUuid); /* |
︙ | ︙ | |||
2650 2651 2652 2653 2654 2655 2656 | @ <input type="submit" name="apply" value="Apply Changes" /> @ <input type="submit" name="cancel" value="Cancel" /> @ </td></tr> @ </table> @ </div></form> style_footer(); } | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 | @ <input type="submit" name="apply" value="Apply Changes" /> @ <input type="submit" name="cancel" value="Cancel" /> @ </td></tr> @ </table> @ </div></form> style_footer(); } /* ** Prepare an ammended commit comment. Let the user modify it using the ** editor specified in the global_config table or either ** the VISUAL or EDITOR environment variable. ** ** Store the final commit comment in pComment. pComment is assumed ** to be uninitialized - any prior content is overwritten. ** ** Use zInit to initialize the check-in comment so that the user does ** not have to retype. */ static void prepare_amend_comment( Blob *pComment, const char *zInit, const char *zUuid ){ Blob prompt; #if defined(_WIN32) || defined(__CYGWIN__) int bomSize; const unsigned char *bom = get_utf8_bom(&bomSize); blob_init(&prompt, (const char *) bom, bomSize); if( zInit && zInit[0]){ blob_append(&prompt, zInit, -1); } #else blob_init(&prompt, zInit, -1); #endif blob_append(&prompt, "\n# Enter a new comment for check-in ", -1); if( zUuid && zUuid[0] ){ blob_append(&prompt, zUuid, -1); } blob_append(&prompt, ".\n# Lines beginning with a # are ignored.\n", -1); prompt_for_user_comment(pComment, &prompt); blob_reset(&prompt); } #define AMEND_USAGE_STMT "UUID OPTION ?OPTION ...?" /* ** COMMAND: amend ** ** Usage: %fossil amend UUID OPTION ?OPTION ...? ** ** Amend the tags on check-in UUID to change how it displays in the timeline. ** ** Options: ** ** --author USER Make USER the author for check-in ** -m|--comment COMMENT Make COMMENT the check-in comment ** -M|--message-file FILE Read the amended comment from FILE ** --edit-comment Launch editor to revise comment ** --date DATE Make DATE the check-in time ** --bgcolor COLOR Apply COLOR to this check-in ** --branchcolor COLOR Apply and propagate COLOR to the branch ** --tag TAG Add new TAG to this check-in ** --cancel TAG Cancel TAG from this check-in ** --branch NAME Make this check-in the start of branch NAME ** --hide Hide branch starting from this check-in ** --close Mark this "leaf" as closed */ void ci_amend_cmd(void){ int rid; const char *zComment; /* Current comment on the check-in */ const char *zNewComment; /* Revised check-in comment */ const char *zComFile; /* Filename from which to read comment */ const char *zUser; /* Current user for the check-in */ const char *zNewUser; /* Revised user */ const char *zDate; /* Current date of the check-in */ const char *zNewDate; /* Revised check-in date */ const char *zColor; const char *zNewColor; const char *zNewBrColor; const char *zNewBranch; const char **pzNewTags = 0; const char **pzCancelTags = 0; int fClose; /* True if leaf should be closed */ int fHide; /* True if branch should be hidden */ int fPropagateColor; /* True if color propagates before amend */ int fNewPropagateColor = 0; /* True if color propagates after amend */ int fHasHidden = 0; /* True if hidden tag already set */ int fHasClosed = 0; /* True if closed tag already set */ int fEditComment; /* True if editor to be used for comment */ const char *zChngTime; /* The change time on the control artifact */ const char *zUuid; Blob ctrl; Blob comment; char *zNow; int nTags, nCancels; int i; Stmt q; if( g.argc==3 ) usage(AMEND_USAGE_STMT); fEditComment = find_option("edit-comment",0,0)!=0; zNewComment = find_option("comment","m",1); zComFile = find_option("message-file","M",1); zNewBranch = find_option("branch",0,1); zNewColor = find_option("bgcolor",0,1); zNewBrColor = find_option("branchcolor",0,1); if( zNewBrColor ){ zNewColor = zNewBrColor; fNewPropagateColor = 1; } zNewDate = find_option("date",0,1); zNewUser = find_option("author",0,1); pzNewTags = find_repeatable_option("tag",0,&nTags); pzCancelTags = find_repeatable_option("cancel",0,&nCancels); fClose = find_option("close",0,0)!=0; fHide = find_option("hide",0,0)!=0; zChngTime = find_option("chngtime",0,1); db_find_and_open_repository(0,0); user_select(); verify_all_options(); if( g.argc<3 || g.argc>=4 ) usage(AMEND_USAGE_STMT); rid = name_to_typed_rid(g.argv[2], "ci"); if( rid==0 && !is_a_version(rid) ) fossil_fatal("no such check-in"); zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); if( zUuid==0 ) fossil_fatal("Unable to find UUID"); zComment = db_text(0, "SELECT coalesce(ecomment,comment)" " FROM event WHERE objid=%d", rid); zUser = db_text(0, "SELECT coalesce(euser,user)" " FROM event WHERE objid=%d", rid); zDate = db_text(0, "SELECT datetime(mtime)" " FROM event WHERE objid=%d", rid); zColor = db_text("", "SELECT bgcolor" " FROM event WHERE objid=%d", rid); fPropagateColor = db_int(0, "SELECT tagtype FROM tagxref" " WHERE rid=%d AND tagid=%d", rid, TAG_BGCOLOR)==2; fNewPropagateColor = zNewColor && zNewColor[0] ? fNewPropagateColor : fPropagateColor; db_prepare(&q, "SELECT tag.tagid FROM tagxref, tag" " WHERE tagxref.rid=%d AND tagtype>0 AND tagxref.tagid=tag.tagid", rid ); while( db_step(&q)==SQLITE_ROW ){ int tagid = db_column_int(&q, 0); if( tagid == TAG_CLOSED ){ fHasClosed = 1; }else if( tagid==TAG_HIDDEN ){ fHasHidden = 1; }else{ continue; } } db_finalize(&q); blob_zero(&ctrl); zNow = date_in_standard_format(zChngTime && zChngTime[0] ? zChngTime : "now"); blob_appendf(&ctrl, "D %s\n", zNow); init_newtags(); if( zNewColor && zNewColor[0] && (fPropagateColor!=fNewPropagateColor || fossil_strcmp(zColor,zNewColor)!=0) ){ add_color( mprintf("%s%s", (zNewColor[0]!='#' && validate16(zNewColor,strlen(zNewColor)) && (strlen(zNewColor)==6 || strlen(zNewColor)==3)) ? "#" : "", zNewColor ), fNewPropagateColor ); } if( (zNewColor!=0 && zNewColor[0]==0) && (zColor && zColor[0] ) ){ cancel_color(); } if( fEditComment ){ prepare_amend_comment(&comment, zComment, zUuid); zNewComment = blob_str(&comment); }else if( zComFile ){ blob_zero(&comment); blob_read_from_file(&comment, zComFile); blob_to_utf8_no_bom(&comment, 1); zNewComment = blob_str(&comment); } if( zNewComment && zNewComment[0] && comment_compare(zComment,zNewComment)==0 ) add_comment(zNewComment); if( zNewDate && zNewDate[0] && fossil_strcmp(zDate,zNewDate)!=0 ){ if( is_datetime(zNewDate) ){ add_date(zNewDate); }else{ fossil_fatal("Unsupported date format, use YYYY-MM-DD HH:MM:SS"); } } if( zNewUser && zNewUser[0] && fossil_strcmp(zUser,zNewUser)!=0 ){ add_user(zNewUser); } if( pzNewTags!=0 ){ for(i=0; i<nTags; i++){ if( pzNewTags[i] && pzNewTags[i][0] ) add_tag(pzNewTags[i]); } fossil_free(pzNewTags); } if( pzCancelTags!=0 ){ for(i=0; i<nCancels; i++){ if( pzCancelTags[i] && pzCancelTags[i][0] ) cancel_tag(rid,pzCancelTags[i]); } fossil_free(pzCancelTags); } if( fHide && !fHasHidden ) hide_branch(); if( fClose && !fHasClosed ) close_leaf(rid); if( zNewBranch && zNewBranch[0] ) change_branch(rid,zNewBranch); apply_newtags(&ctrl, rid, zUuid); show_common_info(rid, "uuid:", 1, 0); } |
Changes to src/linenoise.c.
︙ | ︙ | |||
174 175 176 177 178 179 180 | static void linenoiseAtExit(void); int linenoiseHistoryAdd(const char *line); static void refreshLine(struct linenoiseState *l); /* Debugging macro. */ #if 0 FILE *lndebug_fp = NULL; | | | | | 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 | static void linenoiseAtExit(void); int linenoiseHistoryAdd(const char *line); static void refreshLine(struct linenoiseState *l); /* Debugging macro. */ #if 0 FILE *lndebug_fp = NULL; #define lndebug(fmt, arg1) \ do { \ if (lndebug_fp == NULL) { \ lndebug_fp = fopen("/tmp/lndebug.txt","a"); \ fprintf(lndebug_fp, \ "[%d %d %d] p: %d, rows: %d, rpos: %d, max: %d, oldmax: %d\n", \ (int)l->len,(int)l->pos,(int)l->oldpos,plen,rows,rpos, \ (int)l->maxrows,old_rows); \ } \ fprintf(lndebug_fp, ", " fmt, arg1); \ fflush(lndebug_fp); \ } while (0) #else #define lndebug(fmt, arg1) #endif /* ======================= Low level terminal handling ====================== */ /* Set if to use or not the multi line mode. */ void linenoiseSetMultiLine(int ml) { mlmode = ml; |
︙ | ︙ | |||
524 525 526 527 528 529 530 | lndebug("go down %d", old_rows-rpos); snprintf(seq,64,"\x1b[%dB", old_rows-rpos); abAppend(&ab,seq,strlen(seq)); } /* Now for every row clear it, go up. */ for (j = 0; j < old_rows-1; j++) { | | | | | 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 | lndebug("go down %d", old_rows-rpos); snprintf(seq,64,"\x1b[%dB", old_rows-rpos); abAppend(&ab,seq,strlen(seq)); } /* Now for every row clear it, go up. */ for (j = 0; j < old_rows-1; j++) { lndebug("clear+up", 0); snprintf(seq,64,"\r\x1b[0K\x1b[1A"); abAppend(&ab,seq,strlen(seq)); } /* Clean the top line. */ lndebug("clear", 0); snprintf(seq,64,"\r\x1b[0K"); abAppend(&ab,seq,strlen(seq)); /* Write the prompt and the current buffer content */ abAppend(&ab,l->prompt,strlen(l->prompt)); abAppend(&ab,l->buf,l->len); /* If we are at the very end of the screen with our prompt, we need to * emit a newline and move the prompt to the first column. */ if (l->pos && l->pos == l->len && (l->pos+plen) % l->cols == 0) { lndebug("<newline>", 0); abAppend(&ab,"\n",1); snprintf(seq,64,"\r"); abAppend(&ab,seq,strlen(seq)); rows++; if (rows > (int)l->maxrows) l->maxrows = rows; } |
︙ | ︙ | |||
572 573 574 575 576 577 578 | lndebug("set col %d", 1+col); if (col) snprintf(seq,64,"\r\x1b[%dC", col); else snprintf(seq,64,"\r"); abAppend(&ab,seq,strlen(seq)); | | | 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 | lndebug("set col %d", 1+col); if (col) snprintf(seq,64,"\r\x1b[%dC", col); else snprintf(seq,64,"\r"); abAppend(&ab,seq,strlen(seq)); lndebug("\n", 0); l->oldpos = l->pos; if (write(fd,ab.b,ab.len) == -1) {} /* Can't recover from write error. */ abFree(&ab); } /* Calls the two low level functions refreshSingleLine() or |
︙ | ︙ |
Changes to src/main.c.
︙ | ︙ | |||
874 875 876 877 878 879 880 881 882 883 884 885 886 887 | zReturn = g.argv[i+hasArg]; remove_from_argv(i, 1+hasArg); break; } } return zReturn; } /* ** Look for a repository command-line option. If present, [re-]cache it in ** the global state and return the new pointer, freeing any previous value. ** If absent and there is no cached value, return NULL. */ const char *find_repository_option(){ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 | zReturn = g.argv[i+hasArg]; remove_from_argv(i, 1+hasArg); break; } } return zReturn; } /* ** Look for multiple occurrences of a command-line option with the ** corresponding argument. ** ** Return a malloc allocated array of pointers to the arguments. ** ** pnUsedArgs is used to store the number of matched arguments. ** ** Caller is responsible to free allocated memory. */ const char **find_repeatable_option( const char *zLong, const char *zShort, int *pnUsedArgs ){ const char *zOption; const char **pzArgs = 0; int nAllocArgs = 0; int nUsedArgs = 0; while( (zOption = find_option(zLong, zShort, 1))!=0 ){ if( pzArgs==0 && nAllocArgs==0 ){ nAllocArgs = 1; pzArgs = fossil_malloc( nAllocArgs*sizeof(pzArgs[0]) ); }else if( nAllocArgs<=nUsedArgs ){ nAllocArgs = nAllocArgs*2; pzArgs = fossil_realloc( pzArgs, nAllocArgs*sizeof(pzArgs[0]) ); } pzArgs[nUsedArgs++] = zOption; } *pnUsedArgs = nUsedArgs; return pzArgs; } /* ** Look for a repository command-line option. If present, [re-]cache it in ** the global state and return the new pointer, freeing any previous value. ** If absent and there is no cached value, return NULL. */ const char *find_repository_option(){ |
︙ | ︙ |
Changes to src/merge.c.
︙ | ︙ | |||
590 591 592 593 594 595 596 | }else{ fossil_print("MERGE %s\n", zName); } if( islinkv || islinkm /* || file_wd_islink(zFullPath) */ ){ fossil_print("***** Cannot merge symlink %s\n", zName); nConflict++; }else{ | | | 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 | }else{ fossil_print("MERGE %s\n", zName); } if( islinkv || islinkm /* || file_wd_islink(zFullPath) */ ){ fossil_print("***** Cannot merge symlink %s\n", zName); nConflict++; }else{ if( !dryRunFlag ) undo_save(zName); zFullPath = mprintf("%s/%s", g.zLocalRoot, zName); content_get(ridp, &p); content_get(ridm, &m); if( isBinary ){ rc = -1; blob_zero(&r); }else{ |
︙ | ︙ | |||
641 642 643 644 645 646 647 | int chnged = db_column_int(&q, 2); /* Delete the file idv */ fossil_print("DELETE %s\n", zName); if( chnged ){ fossil_warning("WARNING: local edits lost for %s\n", zName); nConflict++; } | | | 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 | int chnged = db_column_int(&q, 2); /* Delete the file idv */ fossil_print("DELETE %s\n", zName); if( chnged ){ fossil_warning("WARNING: local edits lost for %s\n", zName); nConflict++; } if( !dryRunFlag ) undo_save(zName); db_multi_exec( "UPDATE vfile SET deleted=1 WHERE id=%d", idv ); if( !dryRunFlag ){ char *zFullPath = mprintf("%s%s", g.zLocalRoot, zName); file_delete(zFullPath); free(zFullPath); |
︙ | ︙ | |||
667 668 669 670 671 672 673 | " WHERE idv>0 AND idp>0 AND idm>0 AND fnp=fn AND fnm!=fnp" ); while( db_step(&q)==SQLITE_ROW ){ int idv = db_column_int(&q, 0); const char *zOldName = db_column_text(&q, 1); const char *zNewName = db_column_text(&q, 2); fossil_print("RENAME %s -> %s\n", zOldName, zNewName); | | | | 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 | " WHERE idv>0 AND idp>0 AND idm>0 AND fnp=fn AND fnm!=fnp" ); while( db_step(&q)==SQLITE_ROW ){ int idv = db_column_int(&q, 0); const char *zOldName = db_column_text(&q, 1); const char *zNewName = db_column_text(&q, 2); fossil_print("RENAME %s -> %s\n", zOldName, zNewName); if( !dryRunFlag ) undo_save(zOldName); if( !dryRunFlag ) undo_save(zNewName); db_multi_exec( "UPDATE vfile SET pathname=%Q, origname=coalesce(origname,pathname)" " WHERE id=%d AND vid=%d", zNewName, idv, vid ); if( !dryRunFlag ){ char *zFullOldPath = mprintf("%s%s", g.zLocalRoot, zOldName); char *zFullNewPath = mprintf("%s%s", g.zLocalRoot, zNewName); |
︙ | ︙ | |||
724 725 726 727 728 729 730 | }else if( backoutFlag ){ db_multi_exec("INSERT OR IGNORE INTO vmerge(id,merge) VALUES(-2,%d)",pid); }else if( integrateFlag ){ db_multi_exec("INSERT OR IGNORE INTO vmerge(id,merge) VALUES(-4,%d)",mid); }else{ db_multi_exec("INSERT OR IGNORE INTO vmerge(id,merge) VALUES(0,%d)", mid); } | | | 724 725 726 727 728 729 730 731 732 733 | }else if( backoutFlag ){ db_multi_exec("INSERT OR IGNORE INTO vmerge(id,merge) VALUES(-2,%d)",pid); }else if( integrateFlag ){ db_multi_exec("INSERT OR IGNORE INTO vmerge(id,merge) VALUES(-4,%d)",mid); }else{ db_multi_exec("INSERT OR IGNORE INTO vmerge(id,merge) VALUES(0,%d)", mid); } if( !dryRunFlag ) undo_finish(); db_end_transaction(dryRunFlag); } |
Changes to src/setup.c.
︙ | ︙ | |||
1470 1471 1472 1473 1474 1475 1476 | (char*)pSet->def, hasVersionableValue); @<br /> } } @ </td></tr></table> @ </div></form> @ <p>Settings marked with (v) are 'versionable' and will be overridden | | > | 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 | (char*)pSet->def, hasVersionableValue); @<br /> } } @ </td></tr></table> @ </div></form> @ <p>Settings marked with (v) are 'versionable' and will be overridden @ by the contents of files named <tt>.fossil-settings/PROPERTY</tt> @ in the check-out root. @ If such a file is present, the corresponding field above is not @ editable.</p><hr /><p> @ These settings work in the same way, as the <kbd>set</kbd> @ commandline:<br /> @ </p><pre>%s(zHelp_setting_cmd)</pre> db_end_transaction(0); style_footer(); |
︙ | ︙ |
Changes to src/shell.c.
︙ | ︙ | |||
1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 | iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_SORT, bReset); fprintf(pArg->out, "Sort Operations: %d\n", iCur); iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX,bReset); fprintf(pArg->out, "Autoindex Inserts: %d\n", iCur); iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset); fprintf(pArg->out, "Virtual Machine Steps: %d\n", iCur); } return 0; } /* ** Display scan stats. */ | > > | 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 | iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_SORT, bReset); fprintf(pArg->out, "Sort Operations: %d\n", iCur); iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX,bReset); fprintf(pArg->out, "Autoindex Inserts: %d\n", iCur); iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset); fprintf(pArg->out, "Virtual Machine Steps: %d\n", iCur); } /* Do not remove this machine readable comment: extra-stats-output-here */ return 0; } /* ** Display scan stats. */ |
︙ | ︙ |
Changes to src/sqlite3.c.
1 2 | /****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite | | | 1 2 3 4 5 6 7 8 9 10 | /****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite ** version 3.8.11.1. By combining all the individual C code files into this ** single large file, the entire code can be compiled as a single translation ** unit. This allows many compilers to do optimizations that would not be ** possible if the files were compiled separately. Performance improvements ** of 5% or more are commonly seen when SQLite is compiled as a single ** translation unit. ** ** This file is all you need to compile SQLite. To use SQLite in other |
︙ | ︙ | |||
321 322 323 324 325 326 327 | ** string contains the date and time of the check-in (UTC) and an SHA1 ** hash of the entire source tree. ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ | | | | 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 | ** string contains the date and time of the check-in (UTC) and an SHA1 ** hash of the entire source tree. ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.8.11.1" #define SQLITE_VERSION_NUMBER 3008011 #define SQLITE_SOURCE_ID "2015-07-29 20:00:57 cf538e2783e468bbc25e7cb2a9ee64d3e0e80b2f" /* ** CAPI3REF: Run-Time Library Version Numbers ** KEYWORDS: sqlite3_version, sqlite3_sourceid ** ** These interfaces provide the same information as the [SQLITE_VERSION], ** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros |
︙ | ︙ | |||
1177 1178 1179 1180 1181 1182 1183 | ** circumstances in order to fix a problem with priority inversion. ** Applications should <em>not</em> use this file-control. ** ** <li>[[SQLITE_FCNTL_ZIPVFS]] ** The [SQLITE_FCNTL_ZIPVFS] opcode is implemented by zipvfs only. All other ** VFS should return SQLITE_NOTFOUND for this opcode. ** | | | | | 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 | ** circumstances in order to fix a problem with priority inversion. ** Applications should <em>not</em> use this file-control. ** ** <li>[[SQLITE_FCNTL_ZIPVFS]] ** The [SQLITE_FCNTL_ZIPVFS] opcode is implemented by zipvfs only. All other ** VFS should return SQLITE_NOTFOUND for this opcode. ** ** <li>[[SQLITE_FCNTL_RBU]] ** The [SQLITE_FCNTL_RBU] opcode is implemented by the special VFS used by ** the RBU extension only. All other VFS should return SQLITE_NOTFOUND for ** this opcode. ** </ul> */ #define SQLITE_FCNTL_LOCKSTATE 1 #define SQLITE_FCNTL_GET_LOCKPROXYFILE 2 #define SQLITE_FCNTL_SET_LOCKPROXYFILE 3 #define SQLITE_FCNTL_LAST_ERRNO 4 |
︙ | ︙ | |||
1207 1208 1209 1210 1211 1212 1213 | #define SQLITE_FCNTL_TRACE 19 #define SQLITE_FCNTL_HAS_MOVED 20 #define SQLITE_FCNTL_SYNC 21 #define SQLITE_FCNTL_COMMIT_PHASETWO 22 #define SQLITE_FCNTL_WIN32_SET_HANDLE 23 #define SQLITE_FCNTL_WAL_BLOCK 24 #define SQLITE_FCNTL_ZIPVFS 25 | | | 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 | #define SQLITE_FCNTL_TRACE 19 #define SQLITE_FCNTL_HAS_MOVED 20 #define SQLITE_FCNTL_SYNC 21 #define SQLITE_FCNTL_COMMIT_PHASETWO 22 #define SQLITE_FCNTL_WIN32_SET_HANDLE 23 #define SQLITE_FCNTL_WAL_BLOCK 24 #define SQLITE_FCNTL_ZIPVFS 25 #define SQLITE_FCNTL_RBU 26 /* deprecated names */ #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE #define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO |
︙ | ︙ | |||
3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 | SQLITE_API int SQLITE_STDCALL sqlite3_bind_null(sqlite3_stmt*, int); SQLITE_API int SQLITE_STDCALL sqlite3_bind_text(sqlite3_stmt*,int,const char*,int,void(*)(void*)); SQLITE_API int SQLITE_STDCALL sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*)); SQLITE_API int SQLITE_STDCALL sqlite3_bind_text64(sqlite3_stmt*, int, const char*, sqlite3_uint64, void(*)(void*), unsigned char encoding); SQLITE_API int SQLITE_STDCALL sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); SQLITE_API int SQLITE_STDCALL sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); /* ** CAPI3REF: Number Of SQL Parameters ** METHOD: sqlite3_stmt ** ** ^This routine can be used to find the number of [SQL parameters] ** in a [prepared statement]. SQL parameters are tokens of the | > | 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 | SQLITE_API int SQLITE_STDCALL sqlite3_bind_null(sqlite3_stmt*, int); SQLITE_API int SQLITE_STDCALL sqlite3_bind_text(sqlite3_stmt*,int,const char*,int,void(*)(void*)); SQLITE_API int SQLITE_STDCALL sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*)); SQLITE_API int SQLITE_STDCALL sqlite3_bind_text64(sqlite3_stmt*, int, const char*, sqlite3_uint64, void(*)(void*), unsigned char encoding); SQLITE_API int SQLITE_STDCALL sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); SQLITE_API int SQLITE_STDCALL sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); SQLITE_API int SQLITE_STDCALL sqlite3_bind_zeroblob64(sqlite3_stmt*, int, sqlite3_uint64); /* ** CAPI3REF: Number Of SQL Parameters ** METHOD: sqlite3_stmt ** ** ^This routine can be used to find the number of [SQL parameters] ** in a [prepared statement]. SQL parameters are tokens of the |
︙ | ︙ | |||
4744 4745 4746 4747 4748 4749 4750 | ** Refer to the [SQL parameter] documentation for additional information. ** ** ^The sqlite3_result_blob() interface sets the result from ** an application-defined function to be the BLOB whose content is pointed ** to by the second parameter and which is N bytes long where N is the ** third parameter. ** | | | | | 4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 | ** Refer to the [SQL parameter] documentation for additional information. ** ** ^The sqlite3_result_blob() interface sets the result from ** an application-defined function to be the BLOB whose content is pointed ** to by the second parameter and which is N bytes long where N is the ** third parameter. ** ** ^The sqlite3_result_zeroblob(C,N) and sqlite3_result_zeroblob64(C,N) ** interfaces set the result of the application-defined function to be ** a BLOB containing all zero bytes and N bytes in size. ** ** ^The sqlite3_result_double() interface sets the result from ** an application-defined function to be a floating point value specified ** by its 2nd argument. ** ** ^The sqlite3_result_error() and sqlite3_result_error16() functions ** cause the implemented SQL function to throw an exception. |
︙ | ︙ | |||
4861 4862 4863 4864 4865 4866 4867 4868 4869 4870 4871 4872 4873 4874 | SQLITE_API void SQLITE_STDCALL sqlite3_result_text64(sqlite3_context*, const char*,sqlite3_uint64, void(*)(void*), unsigned char encoding); SQLITE_API void SQLITE_STDCALL sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*)); SQLITE_API void SQLITE_STDCALL sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*)); SQLITE_API void SQLITE_STDCALL sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*)); SQLITE_API void SQLITE_STDCALL sqlite3_result_value(sqlite3_context*, sqlite3_value*); SQLITE_API void SQLITE_STDCALL sqlite3_result_zeroblob(sqlite3_context*, int n); /* ** CAPI3REF: Define New Collating Sequences ** METHOD: sqlite3 ** ** ^These functions add, remove, or modify a [collation] associated ** with the [database connection] specified as the first argument. | > | 4862 4863 4864 4865 4866 4867 4868 4869 4870 4871 4872 4873 4874 4875 4876 | SQLITE_API void SQLITE_STDCALL sqlite3_result_text64(sqlite3_context*, const char*,sqlite3_uint64, void(*)(void*), unsigned char encoding); SQLITE_API void SQLITE_STDCALL sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*)); SQLITE_API void SQLITE_STDCALL sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*)); SQLITE_API void SQLITE_STDCALL sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*)); SQLITE_API void SQLITE_STDCALL sqlite3_result_value(sqlite3_context*, sqlite3_value*); SQLITE_API void SQLITE_STDCALL sqlite3_result_zeroblob(sqlite3_context*, int n); SQLITE_API int SQLITE_STDCALL sqlite3_result_zeroblob64(sqlite3_context*, sqlite3_uint64 n); /* ** CAPI3REF: Define New Collating Sequences ** METHOD: sqlite3 ** ** ^These functions add, remove, or modify a [collation] associated ** with the [database connection] specified as the first argument. |
︙ | ︙ | |||
8360 8361 8362 8363 8364 8365 8366 | #endif /* ** Make sure that the compiler intrinsics we desire are enabled when ** compiling with an appropriate version of MSVC. */ #if defined(_MSC_VER) && _MSC_VER>=1300 | > | | | > > > | 8362 8363 8364 8365 8366 8367 8368 8369 8370 8371 8372 8373 8374 8375 8376 8377 8378 8379 8380 8381 8382 | #endif /* ** Make sure that the compiler intrinsics we desire are enabled when ** compiling with an appropriate version of MSVC. */ #if defined(_MSC_VER) && _MSC_VER>=1300 # if !defined(_WIN32_WCE) # include <intrin.h> # pragma intrinsic(_byteswap_ushort) # pragma intrinsic(_byteswap_ulong) # else # include <cmnintrin.h> # endif #endif /* ** The SQLITE_THREADSAFE macro must be defined as 0, 1, or 2. ** 0 means mutexes are permanently disable and the library is never ** threadsafe. 1 means the library is serialized which is the highest ** level of threadsafety. 2 means the library is multithreaded - multiple |
︙ | ︙ | |||
9187 9188 9189 9190 9191 9192 9193 | # define SQLITE_MAX_MMAP_SIZE 0 # endif #endif #ifndef SQLITE_MAX_MMAP_SIZE # if defined(__linux__) \ || defined(_WIN32) \ || (defined(__APPLE__) && defined(__MACH__)) \ | | > > | 9193 9194 9195 9196 9197 9198 9199 9200 9201 9202 9203 9204 9205 9206 9207 9208 9209 | # define SQLITE_MAX_MMAP_SIZE 0 # endif #endif #ifndef SQLITE_MAX_MMAP_SIZE # if defined(__linux__) \ || defined(_WIN32) \ || (defined(__APPLE__) && defined(__MACH__)) \ || defined(__sun) \ || defined(__FreeBSD__) \ || defined(__DragonFly__) # define SQLITE_MAX_MMAP_SIZE 0x7fff0000 /* 2147418112 */ # else # define SQLITE_MAX_MMAP_SIZE 0 # endif # define SQLITE_MAX_MMAP_SIZE_xc 1 /* exclude from ctime.c */ #endif |
︙ | ︙ | |||
13881 13882 13883 13884 13885 13886 13887 13888 13889 13890 13891 13892 13893 13894 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** ** This file contains definitions of global variables and constants. */ /* An array to map all upper-case characters into their corresponding ** lower-case character. ** ** SQLite only considers US-ASCII (or EBCDIC) characters. We do not ** handle case conversions for the UTF character set since the tables ** involved are nearly as big or bigger than SQLite itself. | > | 13889 13890 13891 13892 13893 13894 13895 13896 13897 13898 13899 13900 13901 13902 13903 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** ** This file contains definitions of global variables and constants. */ /* #include "sqliteInt.h" */ /* An array to map all upper-case characters into their corresponding ** lower-case character. ** ** SQLite only considers US-ASCII (or EBCDIC) characters. We do not ** handle case conversions for the UTF character set since the tables ** involved are nearly as big or bigger than SQLite itself. |
︙ | ︙ | |||
14120 14121 14122 14123 14124 14125 14126 14127 14128 14129 14130 14131 14132 14133 | ** Changing the pending byte during operation will result in undefined ** and incorrect behavior. */ #ifndef SQLITE_OMIT_WSD SQLITE_PRIVATE int sqlite3PendingByte = 0x40000000; #endif /* ** Properties of opcodes. The OPFLG_INITIALIZER macro is ** created by mkopcodeh.awk during compilation. Data is obtained ** from the comments following the "case OP_xxxx:" statements in ** the vdbe.c file. */ SQLITE_PRIVATE const unsigned char sqlite3OpcodeProperty[] = OPFLG_INITIALIZER; | > | 14129 14130 14131 14132 14133 14134 14135 14136 14137 14138 14139 14140 14141 14142 14143 | ** Changing the pending byte during operation will result in undefined ** and incorrect behavior. */ #ifndef SQLITE_OMIT_WSD SQLITE_PRIVATE int sqlite3PendingByte = 0x40000000; #endif /* #include "opcodes.h" */ /* ** Properties of opcodes. The OPFLG_INITIALIZER macro is ** created by mkopcodeh.awk during compilation. Data is obtained ** from the comments following the "case OP_xxxx:" statements in ** the vdbe.c file. */ SQLITE_PRIVATE const unsigned char sqlite3OpcodeProperty[] = OPFLG_INITIALIZER; |
︙ | ︙ | |||
14148 14149 14150 14151 14152 14153 14154 14155 14156 14157 14158 14159 14160 14161 | ** ** This file implements routines used to report what compile-time options ** SQLite was built with. */ #ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS /* ** An array of names of all compile-time options. This array should ** be sorted A-Z. ** ** This array looks large, but in a typical installation actually uses ** only a handful of compile-time options, so most times this array is usually | > | 14158 14159 14160 14161 14162 14163 14164 14165 14166 14167 14168 14169 14170 14171 14172 | ** ** This file implements routines used to report what compile-time options ** SQLite was built with. */ #ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS /* #include "sqliteInt.h" */ /* ** An array of names of all compile-time options. This array should ** be sorted A-Z. ** ** This array looks large, but in a typical installation actually uses ** only a handful of compile-time options, so most times this array is usually |
︙ | ︙ | |||
14577 14578 14579 14580 14581 14582 14583 14584 14585 14586 14587 14588 14589 14590 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** ** This module implements the sqlite3_status() interface and related ** functionality. */ /************** Include vdbeInt.h in the middle of status.c ******************/ /************** Begin file vdbeInt.h *****************************************/ /* ** 2003 September 6 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: | > | 14588 14589 14590 14591 14592 14593 14594 14595 14596 14597 14598 14599 14600 14601 14602 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** ** This module implements the sqlite3_status() interface and related ** functionality. */ /* #include "sqliteInt.h" */ /************** Include vdbeInt.h in the middle of status.c ******************/ /************** Begin file vdbeInt.h *****************************************/ /* ** 2003 September 6 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: |
︙ | ︙ | |||
15460 15461 15462 15463 15464 15465 15466 15467 15468 15469 15470 15471 15472 15473 | ** ** Jean Meeus ** Astronomical Algorithms, 2nd Edition, 1998 ** ISBM 0-943396-61-1 ** Willmann-Bell, Inc ** Richmond, Virginia (USA) */ /* #include <stdlib.h> */ /* #include <assert.h> */ #include <time.h> #ifndef SQLITE_OMIT_DATETIME_FUNCS | > | 15472 15473 15474 15475 15476 15477 15478 15479 15480 15481 15482 15483 15484 15485 15486 | ** ** Jean Meeus ** Astronomical Algorithms, 2nd Edition, 1998 ** ISBM 0-943396-61-1 ** Willmann-Bell, Inc ** Richmond, Virginia (USA) */ /* #include "sqliteInt.h" */ /* #include <stdlib.h> */ /* #include <assert.h> */ #include <time.h> #ifndef SQLITE_OMIT_DATETIME_FUNCS |
︙ | ︙ | |||
15771 15772 15773 15774 15775 15776 15777 | p->D = 1; }else{ Z = (int)((p->iJD + 43200000)/86400000); A = (int)((Z - 1867216.25)/36524.25); A = Z + 1 + A - (A/4); B = A + 1524; C = (int)((B - 122.1)/365.25); | | | 15784 15785 15786 15787 15788 15789 15790 15791 15792 15793 15794 15795 15796 15797 15798 | p->D = 1; }else{ Z = (int)((p->iJD + 43200000)/86400000); A = (int)((Z - 1867216.25)/36524.25); A = Z + 1 + A - (A/4); B = A + 1524; C = (int)((B - 122.1)/365.25); D = (36525*(C&32767))/100; E = (int)((B-D)/30.6001); X1 = (int)(30.6001*E); p->D = B - D - X1; p->M = E<14 ? E-1 : E-13; p->Y = p->M>2 ? C - 4716 : C - 4715; } p->validYMD = 1; |
︙ | ︙ | |||
16572 16573 16574 16575 16576 16577 16578 16579 16580 16581 16582 16583 16584 16585 | ** ****************************************************************************** ** ** This file contains OS interface code that is common to all ** architectures. */ #define _SQLITE_OS_C_ 1 #undef _SQLITE_OS_C_ /* ** The default SQLite sqlite3_vfs implementations do not allocate ** memory (actually, os_unix.c allocates a small amount of memory ** from within OsOpen()), but some third-party implementations may. ** So we test the effects of a malloc() failing and the sqlite3OsXXX() | > | 16585 16586 16587 16588 16589 16590 16591 16592 16593 16594 16595 16596 16597 16598 16599 | ** ****************************************************************************** ** ** This file contains OS interface code that is common to all ** architectures. */ #define _SQLITE_OS_C_ 1 /* #include "sqliteInt.h" */ #undef _SQLITE_OS_C_ /* ** The default SQLite sqlite3_vfs implementations do not allocate ** memory (actually, os_unix.c allocates a small amount of memory ** from within OsOpen()), but some third-party implementations may. ** So we test the effects of a malloc() failing and the sqlite3OsXXX() |
︙ | ︙ | |||
16978 16979 16980 16981 16982 16983 16984 16985 16986 16987 16988 16989 16990 16991 | ** SQLITE_NOMEM) to the user. However, sometimes a fault is not necessarily ** fatal. For example, if a malloc fails while resizing a hash table, this ** is completely recoverable simply by not carrying out the resize. The ** hash table will continue to function normally. So a malloc failure ** during a hash table resize is a benign fault. */ #ifndef SQLITE_OMIT_BUILTIN_TEST /* ** Global variables. */ typedef struct BenignMallocHooks BenignMallocHooks; | > | 16992 16993 16994 16995 16996 16997 16998 16999 17000 17001 17002 17003 17004 17005 17006 | ** SQLITE_NOMEM) to the user. However, sometimes a fault is not necessarily ** fatal. For example, if a malloc fails while resizing a hash table, this ** is completely recoverable simply by not carrying out the resize. The ** hash table will continue to function normally. So a malloc failure ** during a hash table resize is a benign fault. */ /* #include "sqliteInt.h" */ #ifndef SQLITE_OMIT_BUILTIN_TEST /* ** Global variables. */ typedef struct BenignMallocHooks BenignMallocHooks; |
︙ | ︙ | |||
17059 17060 17061 17062 17063 17064 17065 17066 17067 17068 17069 17070 17071 17072 | ** ** This file contains a no-op memory allocation drivers for use when ** SQLITE_ZERO_MALLOC is defined. The allocation drivers implemented ** here always fail. SQLite will not operate with these drivers. These ** are merely placeholders. Real drivers must be substituted using ** sqlite3_config() before SQLite will operate. */ /* ** This version of the memory allocator is the default. It is ** used when no other memory allocator is specified using compile-time ** macros. */ #ifdef SQLITE_ZERO_MALLOC | > | 17074 17075 17076 17077 17078 17079 17080 17081 17082 17083 17084 17085 17086 17087 17088 | ** ** This file contains a no-op memory allocation drivers for use when ** SQLITE_ZERO_MALLOC is defined. The allocation drivers implemented ** here always fail. SQLite will not operate with these drivers. These ** are merely placeholders. Real drivers must be substituted using ** sqlite3_config() before SQLite will operate. */ /* #include "sqliteInt.h" */ /* ** This version of the memory allocator is the default. It is ** used when no other memory allocator is specified using compile-time ** macros. */ #ifdef SQLITE_ZERO_MALLOC |
︙ | ︙ | |||
17145 17146 17147 17148 17149 17150 17151 17152 17153 17154 17155 17156 17157 17158 | ** building on older macs. ** ** SQLITE_WITHOUT_MSIZE Set this symbol to disable the use of ** _msize() on windows systems. This might ** be necessary when compiling for Delphi, ** for example. */ /* ** This version of the memory allocator is the default. It is ** used when no other memory allocator is specified using compile-time ** macros. */ #ifdef SQLITE_SYSTEM_MALLOC | > | 17161 17162 17163 17164 17165 17166 17167 17168 17169 17170 17171 17172 17173 17174 17175 | ** building on older macs. ** ** SQLITE_WITHOUT_MSIZE Set this symbol to disable the use of ** _msize() on windows systems. This might ** be necessary when compiling for Delphi, ** for example. */ /* #include "sqliteInt.h" */ /* ** This version of the memory allocator is the default. It is ** used when no other memory allocator is specified using compile-time ** macros. */ #ifdef SQLITE_SYSTEM_MALLOC |
︙ | ︙ | |||
17420 17421 17422 17423 17424 17425 17426 17427 17428 17429 17430 17431 17432 17433 | ** to obtain the memory it needs while adding lots of additional debugging ** information to each allocation in order to help detect and fix memory ** leaks and memory usage errors. ** ** This file contains implementations of the low-level memory allocation ** routines specified in the sqlite3_mem_methods object. */ /* ** This version of the memory allocator is used only if the ** SQLITE_MEMDEBUG macro is defined */ #ifdef SQLITE_MEMDEBUG | > | 17437 17438 17439 17440 17441 17442 17443 17444 17445 17446 17447 17448 17449 17450 17451 | ** to obtain the memory it needs while adding lots of additional debugging ** information to each allocation in order to help detect and fix memory ** leaks and memory usage errors. ** ** This file contains implementations of the low-level memory allocation ** routines specified in the sqlite3_mem_methods object. */ /* #include "sqliteInt.h" */ /* ** This version of the memory allocator is used only if the ** SQLITE_MEMDEBUG macro is defined */ #ifdef SQLITE_MEMDEBUG |
︙ | ︙ | |||
17954 17955 17956 17957 17958 17959 17960 17961 17962 17963 17964 17965 17966 17967 | ** implementations. Once sqlite3_initialize() has been called, ** the amount of memory available to SQLite is fixed and cannot ** be changed. ** ** This version of the memory allocation subsystem is included ** in the build only if SQLITE_ENABLE_MEMSYS3 is defined. */ /* ** This version of the memory allocator is only built into the library ** SQLITE_ENABLE_MEMSYS3 is defined. Defining this symbol does not ** mean that the library will use a memory-pool by default, just that ** it is available. The mempool allocator is activated by calling ** sqlite3_config(). | > | 17972 17973 17974 17975 17976 17977 17978 17979 17980 17981 17982 17983 17984 17985 17986 | ** implementations. Once sqlite3_initialize() has been called, ** the amount of memory available to SQLite is fixed and cannot ** be changed. ** ** This version of the memory allocation subsystem is included ** in the build only if SQLITE_ENABLE_MEMSYS3 is defined. */ /* #include "sqliteInt.h" */ /* ** This version of the memory allocator is only built into the library ** SQLITE_ENABLE_MEMSYS3 is defined. Defining this symbol does not ** mean that the library will use a memory-pool by default, just that ** it is available. The mempool allocator is activated by calling ** sqlite3_config(). |
︙ | ︙ | |||
18668 18669 18670 18671 18672 18673 18674 18675 18676 18677 18678 18679 18680 18681 | ** fragmentation as long as the following constraint holds: ** ** N >= M*(1 + log2(n)/2) - n + 1 ** ** The sqlite3_status() logic tracks the maximum values of n and M so ** that an application can, at any time, verify this constraint. */ /* ** This version of the memory allocator is used only when ** SQLITE_ENABLE_MEMSYS5 is defined. */ #ifdef SQLITE_ENABLE_MEMSYS5 | > | 18687 18688 18689 18690 18691 18692 18693 18694 18695 18696 18697 18698 18699 18700 18701 | ** fragmentation as long as the following constraint holds: ** ** N >= M*(1 + log2(n)/2) - n + 1 ** ** The sqlite3_status() logic tracks the maximum values of n and M so ** that an application can, at any time, verify this constraint. */ /* #include "sqliteInt.h" */ /* ** This version of the memory allocator is used only when ** SQLITE_ENABLE_MEMSYS5 is defined. */ #ifdef SQLITE_ENABLE_MEMSYS5 |
︙ | ︙ | |||
19211 19212 19213 19214 19215 19216 19217 19218 19219 19220 19221 19222 19223 19224 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains the C functions that implement mutexes. ** ** This file contains code that is common across all mutex implementations. */ #if defined(SQLITE_DEBUG) && !defined(SQLITE_MUTEX_OMIT) /* ** For debugging purposes, record when the mutex subsystem is initialized ** and uninitialized so that we can assert() if there is an attempt to ** allocate a mutex while the system is uninitialized. */ | > | 19231 19232 19233 19234 19235 19236 19237 19238 19239 19240 19241 19242 19243 19244 19245 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains the C functions that implement mutexes. ** ** This file contains code that is common across all mutex implementations. */ /* #include "sqliteInt.h" */ #if defined(SQLITE_DEBUG) && !defined(SQLITE_MUTEX_OMIT) /* ** For debugging purposes, record when the mutex subsystem is initialized ** and uninitialized so that we can assert() if there is an attempt to ** allocate a mutex while the system is uninitialized. */ |
︙ | ︙ | |||
19384 19385 19386 19387 19388 19389 19390 19391 19392 19393 19394 19395 19396 19397 | ** ** interface. ** ** If compiled with SQLITE_DEBUG, then additional logic is inserted ** that does error checking on mutexes to make sure they are being ** called correctly. */ #ifndef SQLITE_MUTEX_OMIT #ifndef SQLITE_DEBUG /* ** Stub routines for all mutex methods. ** | > | 19405 19406 19407 19408 19409 19410 19411 19412 19413 19414 19415 19416 19417 19418 19419 | ** ** interface. ** ** If compiled with SQLITE_DEBUG, then additional logic is inserted ** that does error checking on mutexes to make sure they are being ** called correctly. */ /* #include "sqliteInt.h" */ #ifndef SQLITE_MUTEX_OMIT #ifndef SQLITE_DEBUG /* ** Stub routines for all mutex methods. ** |
︙ | ︙ | |||
19587 19588 19589 19590 19591 19592 19593 19594 19595 19596 19597 19598 19599 19600 | ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains the C functions that implement mutexes for pthreads */ /* ** The code in this file is only used if we are compiling threadsafe ** under unix with pthreads. ** ** Note that this implementation requires a version of pthreads that ** supports recursive mutexes. | > | 19609 19610 19611 19612 19613 19614 19615 19616 19617 19618 19619 19620 19621 19622 19623 | ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains the C functions that implement mutexes for pthreads */ /* #include "sqliteInt.h" */ /* ** The code in this file is only used if we are compiling threadsafe ** under unix with pthreads. ** ** Note that this implementation requires a version of pthreads that ** supports recursive mutexes. |
︙ | ︙ | |||
19961 19962 19963 19964 19965 19966 19967 19968 19969 19970 19971 19972 19973 19974 | ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains the C functions that implement mutexes for Win32. */ #if SQLITE_OS_WIN /* ** Include code that is common to all os_*.c files */ /************** Include os_common.h in the middle of mutex_w32.c *************/ /************** Begin file os_common.h ***************************************/ | > | 19984 19985 19986 19987 19988 19989 19990 19991 19992 19993 19994 19995 19996 19997 19998 | ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains the C functions that implement mutexes for Win32. */ /* #include "sqliteInt.h" */ #if SQLITE_OS_WIN /* ** Include code that is common to all os_*.c files */ /************** Include os_common.h in the middle of mutex_w32.c *************/ /************** Begin file os_common.h ***************************************/ |
︙ | ︙ | |||
20636 20637 20638 20639 20640 20641 20642 20643 20644 20645 20646 20647 20648 20649 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** ** Memory allocation functions used throughout sqlite. */ /* #include <stdarg.h> */ /* ** Attempt to release up to n bytes of non-essential memory currently ** held by SQLite. An example of non-essential memory is memory used to ** cache database pages that are not currently in use. */ | > | 20660 20661 20662 20663 20664 20665 20666 20667 20668 20669 20670 20671 20672 20673 20674 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** ** Memory allocation functions used throughout sqlite. */ /* #include "sqliteInt.h" */ /* #include <stdarg.h> */ /* ** Attempt to release up to n bytes of non-essential memory currently ** held by SQLite. An example of non-essential memory is memory used to ** cache database pages that are not currently in use. */ |
︙ | ︙ | |||
21447 21448 21449 21450 21451 21452 21453 21454 21455 21456 21457 21458 21459 21460 | ************************************************************************** ** ** This file contains code for a set of "printf"-like routines. These ** routines format strings much like the printf() from the standard C ** library, though the implementation here has enhancements to support ** SQLite. */ /* ** Conversion types fall into various categories as defined by the ** following enumeration. */ #define etRADIX 1 /* Integer types. %d, %x, %o, and so forth */ #define etFLOAT 2 /* Floating point. %f */ | > | 21472 21473 21474 21475 21476 21477 21478 21479 21480 21481 21482 21483 21484 21485 21486 | ************************************************************************** ** ** This file contains code for a set of "printf"-like routines. These ** routines format strings much like the printf() from the standard C ** library, though the implementation here has enhancements to support ** SQLite. */ /* #include "sqliteInt.h" */ /* ** Conversion types fall into various categories as defined by the ** following enumeration. */ #define etRADIX 1 /* Integer types. %d, %x, %o, and so forth */ #define etFLOAT 2 /* Floating point. %f */ |
︙ | ︙ | |||
22449 22450 22451 22452 22453 22454 22455 22456 22457 22458 22459 22460 22461 22462 | ** This is the routine that actually formats the sqlite3_log() message. ** We house it in a separate routine from sqlite3_log() to avoid using ** stack space on small-stack systems when logging is disabled. ** ** sqlite3_log() must render into a static buffer. It cannot dynamically ** allocate memory because it might be called while the memory allocator ** mutex is held. */ static void renderLogMsg(int iErrCode, const char *zFormat, va_list ap){ StrAccum acc; /* String accumulator */ char zMsg[SQLITE_PRINT_BUF_SIZE*3]; /* Complete log message */ sqlite3StrAccumInit(&acc, 0, zMsg, sizeof(zMsg), 0); sqlite3VXPrintf(&acc, 0, zFormat, ap); | > > > > > | 22475 22476 22477 22478 22479 22480 22481 22482 22483 22484 22485 22486 22487 22488 22489 22490 22491 22492 22493 | ** This is the routine that actually formats the sqlite3_log() message. ** We house it in a separate routine from sqlite3_log() to avoid using ** stack space on small-stack systems when logging is disabled. ** ** sqlite3_log() must render into a static buffer. It cannot dynamically ** allocate memory because it might be called while the memory allocator ** mutex is held. ** ** sqlite3VXPrintf() might ask for *temporary* memory allocations for ** certain format characters (%q) or for very large precisions or widths. ** Care must be taken that any sqlite3_log() calls that occur while the ** memory mutex is held do not use these mechanisms. */ static void renderLogMsg(int iErrCode, const char *zFormat, va_list ap){ StrAccum acc; /* String accumulator */ char zMsg[SQLITE_PRINT_BUF_SIZE*3]; /* Complete log message */ sqlite3StrAccumInit(&acc, 0, zMsg, sizeof(zMsg), 0); sqlite3VXPrintf(&acc, 0, zFormat, ap); |
︙ | ︙ | |||
22524 22525 22526 22527 22528 22529 22530 22531 22532 22533 22534 22535 22536 22537 | ** This file contains C code to implement the TreeView debugging routines. ** These routines print a parse tree to standard output for debugging and ** analysis. ** ** The interfaces in this file is only available when compiling ** with SQLITE_DEBUG. */ #ifdef SQLITE_DEBUG /* ** Add a new subitem to the tree. The moreToFollow flag indicates that this ** is not the last item in the tree. */ static TreeView *sqlite3TreeViewPush(TreeView *p, u8 moreToFollow){ | > | 22555 22556 22557 22558 22559 22560 22561 22562 22563 22564 22565 22566 22567 22568 22569 | ** This file contains C code to implement the TreeView debugging routines. ** These routines print a parse tree to standard output for debugging and ** analysis. ** ** The interfaces in this file is only available when compiling ** with SQLITE_DEBUG. */ /* #include "sqliteInt.h" */ #ifdef SQLITE_DEBUG /* ** Add a new subitem to the tree. The moreToFollow flag indicates that this ** is not the last item in the tree. */ static TreeView *sqlite3TreeViewPush(TreeView *p, u8 moreToFollow){ |
︙ | ︙ | |||
22955 22956 22957 22958 22959 22960 22961 22962 22963 22964 22965 22966 22967 22968 | ************************************************************************* ** This file contains code to implement a pseudo-random number ** generator (PRNG) for SQLite. ** ** Random numbers are used by some of the database backends in order ** to generate random integer keys for tables or random filenames. */ /* All threads share a single random number generator. ** This structure is the current state of the generator. */ static SQLITE_WSD struct sqlite3PrngType { unsigned char isInit; /* True if initialized */ | > | 22987 22988 22989 22990 22991 22992 22993 22994 22995 22996 22997 22998 22999 23000 23001 | ************************************************************************* ** This file contains code to implement a pseudo-random number ** generator (PRNG) for SQLite. ** ** Random numbers are used by some of the database backends in order ** to generate random integer keys for tables or random filenames. */ /* #include "sqliteInt.h" */ /* All threads share a single random number generator. ** This structure is the current state of the generator. */ static SQLITE_WSD struct sqlite3PrngType { unsigned char isInit; /* True if initialized */ |
︙ | ︙ | |||
23101 23102 23103 23104 23105 23106 23107 23108 23109 23110 23111 23112 23113 23114 23115 | ** "thread" is done by the main thread at either the sqlite3ThreadCreate() ** or sqlite3ThreadJoin() call. This is, in fact, what happens in ** single threaded systems. Nothing in SQLite requires multiple threads. ** This interface exists so that applications that want to take advantage ** of multiple cores can do so, while also allowing applications to stay ** single-threaded if desired. */ #if SQLITE_OS_WIN #endif #if SQLITE_MAX_WORKER_THREADS>0 /********************************* Unix Pthreads ****************************/ #if SQLITE_OS_UNIX && defined(SQLITE_MUTEX_PTHREADS) && SQLITE_THREADSAFE>0 | > > | 23134 23135 23136 23137 23138 23139 23140 23141 23142 23143 23144 23145 23146 23147 23148 23149 23150 | ** "thread" is done by the main thread at either the sqlite3ThreadCreate() ** or sqlite3ThreadJoin() call. This is, in fact, what happens in ** single threaded systems. Nothing in SQLite requires multiple threads. ** This interface exists so that applications that want to take advantage ** of multiple cores can do so, while also allowing applications to stay ** single-threaded if desired. */ /* #include "sqliteInt.h" */ #if SQLITE_OS_WIN /* # include "os_win.h" */ #endif #if SQLITE_MAX_WORKER_THREADS>0 /********************************* Unix Pthreads ****************************/ #if SQLITE_OS_UNIX && defined(SQLITE_MUTEX_PTHREADS) && SQLITE_THREADSAFE>0 |
︙ | ︙ | |||
23375 23376 23377 23378 23379 23380 23381 23382 23383 23384 23385 23386 23387 23388 23389 | ** ** ** BOM or Byte Order Mark: ** 0xff 0xfe little-endian utf-16 follows ** 0xfe 0xff big-endian utf-16 follows ** */ /* #include <assert.h> */ #ifndef SQLITE_AMALGAMATION /* ** The following constant value is used by the SQLITE_BIGENDIAN and ** SQLITE_LITTLEENDIAN macros. */ SQLITE_PRIVATE const int sqlite3one = 1; | > > | 23410 23411 23412 23413 23414 23415 23416 23417 23418 23419 23420 23421 23422 23423 23424 23425 23426 | ** ** ** BOM or Byte Order Mark: ** 0xff 0xfe little-endian utf-16 follows ** 0xfe 0xff big-endian utf-16 follows ** */ /* #include "sqliteInt.h" */ /* #include <assert.h> */ /* #include "vdbeInt.h" */ #ifndef SQLITE_AMALGAMATION /* ** The following constant value is used by the SQLITE_BIGENDIAN and ** SQLITE_LITTLEENDIAN macros. */ SQLITE_PRIVATE const int sqlite3one = 1; |
︙ | ︙ | |||
23888 23889 23890 23891 23892 23893 23894 23895 23896 23897 23898 23899 23900 23901 | ************************************************************************* ** Utility functions used throughout sqlite. ** ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** */ /* #include <stdarg.h> */ #if HAVE_ISNAN || SQLITE_HAVE_ISNAN # include <math.h> #endif /* ** Routine needed to support the testcase() macro. | > | 23925 23926 23927 23928 23929 23930 23931 23932 23933 23934 23935 23936 23937 23938 23939 | ************************************************************************* ** Utility functions used throughout sqlite. ** ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** */ /* #include "sqliteInt.h" */ /* #include <stdarg.h> */ #if HAVE_ISNAN || SQLITE_HAVE_ISNAN # include <math.h> #endif /* ** Routine needed to support the testcase() macro. |
︙ | ︙ | |||
25284 25285 25286 25287 25288 25289 25290 25291 25292 25293 25294 25295 25296 25297 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This is the implementation of generic hash-tables ** used in SQLite. */ /* #include <assert.h> */ /* Turn bulk memory into a hash table object by initializing the ** fields of the Hash structure. ** ** "pNew" is a pointer to the hash table that is to be initialized. */ | > | 25322 25323 25324 25325 25326 25327 25328 25329 25330 25331 25332 25333 25334 25335 25336 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This is the implementation of generic hash-tables ** used in SQLite. */ /* #include "sqliteInt.h" */ /* #include <assert.h> */ /* Turn bulk memory into a hash table object by initializing the ** fields of the Hash structure. ** ** "pNew" is a pointer to the hash table that is to be initialized. */ |
︙ | ︙ | |||
25761 25762 25763 25764 25765 25766 25767 25768 25769 25770 25771 25772 25773 25774 | ** * Definitions of sqlite3_io_methods objects for all locking ** methods plus "finder" functions for each locking method. ** * sqlite3_vfs method implementations. ** * Locking primitives for the proxy uber-locking-method. (MacOSX only) ** * Definitions of sqlite3_vfs objects for all locking methods ** plus implementations of sqlite3_os_init() and sqlite3_os_end(). */ #if SQLITE_OS_UNIX /* This file is used on unix only */ /* ** There are various methods for file locking used for concurrency ** control: ** ** 1. POSIX locking (the default), | > | 25800 25801 25802 25803 25804 25805 25806 25807 25808 25809 25810 25811 25812 25813 25814 | ** * Definitions of sqlite3_io_methods objects for all locking ** methods plus "finder" functions for each locking method. ** * sqlite3_vfs method implementations. ** * Locking primitives for the proxy uber-locking-method. (MacOSX only) ** * Definitions of sqlite3_vfs objects for all locking methods ** plus implementations of sqlite3_os_init() and sqlite3_os_end(). */ /* #include "sqliteInt.h" */ #if SQLITE_OS_UNIX /* This file is used on unix only */ /* ** There are various methods for file locking used for concurrency ** control: ** ** 1. POSIX locking (the default), |
︙ | ︙ | |||
33495 33496 33497 33498 33499 33500 33501 33502 33503 33504 33505 33506 33507 33508 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ****************************************************************************** ** ** This file contains code that is specific to Windows. */ #if SQLITE_OS_WIN /* This file is used for Windows only */ /* ** Include code that is common to all os_*.c files */ /************** Include os_common.h in the middle of os_win.c ****************/ /************** Begin file os_common.h ***************************************/ | > | 33535 33536 33537 33538 33539 33540 33541 33542 33543 33544 33545 33546 33547 33548 33549 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ****************************************************************************** ** ** This file contains code that is specific to Windows. */ /* #include "sqliteInt.h" */ #if SQLITE_OS_WIN /* This file is used for Windows only */ /* ** Include code that is common to all os_*.c files */ /************** Include os_common.h in the middle of os_win.c ****************/ /************** Begin file os_common.h ***************************************/ |
︙ | ︙ | |||
33703 33704 33705 33706 33707 33708 33709 33710 33711 33712 33713 33714 33715 33716 | /************** End of os_common.h *******************************************/ /************** Continuing where we left off in os_win.c *********************/ /* ** Include the header file for the Windows VFS. */ /* ** Compiling and using WAL mode requires several APIs that are only ** available in Windows platforms based on the NT kernel. */ #if !SQLITE_OS_WINNT && !defined(SQLITE_OMIT_WAL) # error "WAL mode requires support from the Windows NT kernel, compile\ | > | 33744 33745 33746 33747 33748 33749 33750 33751 33752 33753 33754 33755 33756 33757 33758 | /************** End of os_common.h *******************************************/ /************** Continuing where we left off in os_win.c *********************/ /* ** Include the header file for the Windows VFS. */ /* #include "os_win.h" */ /* ** Compiling and using WAL mode requires several APIs that are only ** available in Windows platforms based on the NT kernel. */ #if !SQLITE_OS_WINNT && !defined(SQLITE_OMIT_WAL) # error "WAL mode requires support from the Windows NT kernel, compile\ |
︙ | ︙ | |||
39356 39357 39358 39359 39360 39361 39362 39363 39364 39365 39366 39367 39368 39369 | ** Clear operations are exceedingly rare. There are usually between ** 5 and 500 set operations per Bitvec object, though the number of sets can ** sometimes grow into tens of thousands or larger. The size of the ** Bitvec object is the number of pages in the database file at the ** start of a transaction, and is thus usually less than a few thousand, ** but can be as large as 2 billion for a really big database. */ /* Size of the Bitvec structure in bytes. */ #define BITVEC_SZ 512 /* Round the union size down to the nearest pointer boundary, since that's how ** it will be aligned within the Bitvec struct. */ #define BITVEC_USIZE (((BITVEC_SZ-(3*sizeof(u32)))/sizeof(Bitvec*))*sizeof(Bitvec*)) | > | 39398 39399 39400 39401 39402 39403 39404 39405 39406 39407 39408 39409 39410 39411 39412 | ** Clear operations are exceedingly rare. There are usually between ** 5 and 500 set operations per Bitvec object, though the number of sets can ** sometimes grow into tens of thousands or larger. The size of the ** Bitvec object is the number of pages in the database file at the ** start of a transaction, and is thus usually less than a few thousand, ** but can be as large as 2 billion for a really big database. */ /* #include "sqliteInt.h" */ /* Size of the Bitvec structure in bytes. */ #define BITVEC_SZ 512 /* Round the union size down to the nearest pointer boundary, since that's how ** it will be aligned within the Bitvec struct. */ #define BITVEC_USIZE (((BITVEC_SZ-(3*sizeof(u32)))/sizeof(Bitvec*))*sizeof(Bitvec*)) |
︙ | ︙ | |||
39745 39746 39747 39748 39749 39750 39751 39752 39753 39754 39755 39756 39757 39758 | ** 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 that page cache. */ /* ** A complete page cache is an instance of this structure. */ struct PCache { PgHdr *pDirty, *pDirtyTail; /* List of dirty pages in LRU order */ PgHdr *pSynced; /* Last synced page in dirty page list */ | > | 39788 39789 39790 39791 39792 39793 39794 39795 39796 39797 39798 39799 39800 39801 39802 | ** 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 that page cache. */ /* #include "sqliteInt.h" */ /* ** A complete page cache is an instance of this structure. */ struct PCache { PgHdr *pDirty, *pDirtyTail; /* List of dirty pages in LRU order */ PgHdr *pSynced; /* Last synced page in dirty page list */ |
︙ | ︙ | |||
40486 40487 40488 40489 40490 40491 40492 40493 40494 40495 40496 40497 40498 40499 | ** (3) is exhausted, subsequent allocations fail over to the general-purpose ** memory allocator (1). ** ** Earlier versions of SQLite used only methods (1) and (2). But experiments ** show that method (3) with N==100 provides about a 5% performance boost for ** common workloads. */ typedef struct PCache1 PCache1; typedef struct PgHdr1 PgHdr1; typedef struct PgFreeslot PgFreeslot; typedef struct PGroup PGroup; /* Each page cache (or PCache) belongs to a PGroup. A PGroup is a set | > | 40530 40531 40532 40533 40534 40535 40536 40537 40538 40539 40540 40541 40542 40543 40544 | ** (3) is exhausted, subsequent allocations fail over to the general-purpose ** memory allocator (1). ** ** Earlier versions of SQLite used only methods (1) and (2). But experiments ** show that method (3) with N==100 provides about a 5% performance boost for ** common workloads. */ /* #include "sqliteInt.h" */ typedef struct PCache1 PCache1; typedef struct PgHdr1 PgHdr1; typedef struct PgFreeslot PgFreeslot; typedef struct PGroup PGroup; /* Each page cache (or PCache) belongs to a PGroup. A PGroup is a set |
︙ | ︙ | |||
40596 40597 40598 40599 40600 40601 40602 40603 40604 40605 40606 40607 40608 40609 | /* Variables related to SQLITE_CONFIG_PAGECACHE settings. The ** szSlot, nSlot, pStart, pEnd, nReserve, and isInit values are all ** fixed at sqlite3_initialize() time and do not require mutex protection. ** The nFreeSlot and pFree values do require mutex protection. */ int isInit; /* True if initialized */ int separateCache; /* Use a new PGroup for each PCache */ int szSlot; /* Size of each free slot */ int nSlot; /* The number of pcache slots */ int nReserve; /* Try to keep nFreeSlot above this */ void *pStart, *pEnd; /* Bounds of global page cache memory */ /* Above requires no mutex. Use mutex below for variable that follow. */ sqlite3_mutex *mutex; /* Mutex for accessing the following: */ PgFreeslot *pFree; /* Free page blocks */ | > | 40641 40642 40643 40644 40645 40646 40647 40648 40649 40650 40651 40652 40653 40654 40655 | /* Variables related to SQLITE_CONFIG_PAGECACHE settings. The ** szSlot, nSlot, pStart, pEnd, nReserve, and isInit values are all ** fixed at sqlite3_initialize() time and do not require mutex protection. ** The nFreeSlot and pFree values do require mutex protection. */ int isInit; /* True if initialized */ int separateCache; /* Use a new PGroup for each PCache */ int nInitPage; /* Initial bulk allocation size */ int szSlot; /* Size of each free slot */ int nSlot; /* The number of pcache slots */ int nReserve; /* Try to keep nFreeSlot above this */ void *pStart, *pEnd; /* Bounds of global page cache memory */ /* Above requires no mutex. Use mutex below for variable that follow. */ sqlite3_mutex *mutex; /* Mutex for accessing the following: */ PgFreeslot *pFree; /* Free page blocks */ |
︙ | ︙ | |||
40663 40664 40665 40666 40667 40668 40669 40670 40671 40672 40673 40674 40675 40676 | p->pNext = pcache1.pFree; pcache1.pFree = p; pBuf = (void*)&((char*)pBuf)[sz]; } pcache1.pEnd = pBuf; } } /* ** Malloc function used within this file to allocate space from the buffer ** configured using sqlite3_config(SQLITE_CONFIG_PAGECACHE) option. If no ** such buffer exists or there is no space left in it, this function falls ** back to sqlite3Malloc(). ** | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 40709 40710 40711 40712 40713 40714 40715 40716 40717 40718 40719 40720 40721 40722 40723 40724 40725 40726 40727 40728 40729 40730 40731 40732 40733 40734 40735 40736 40737 40738 40739 40740 40741 40742 40743 40744 40745 40746 40747 40748 40749 40750 40751 40752 40753 40754 40755 40756 40757 40758 40759 | p->pNext = pcache1.pFree; pcache1.pFree = p; pBuf = (void*)&((char*)pBuf)[sz]; } pcache1.pEnd = pBuf; } } /* ** Try to initialize the pCache->pFree and pCache->pBulk fields. Return ** true if pCache->pFree ends up containing one or more free pages. */ static int pcache1InitBulk(PCache1 *pCache){ i64 szBulk; char *zBulk; if( pcache1.nInitPage==0 ) return 0; /* Do not bother with a bulk allocation if the cache size very small */ if( pCache->nMax<3 ) return 0; sqlite3BeginBenignMalloc(); if( pcache1.nInitPage>0 ){ szBulk = pCache->szAlloc * (i64)pcache1.nInitPage; }else{ szBulk = -1024 * (i64)pcache1.nInitPage; } if( szBulk > pCache->szAlloc*(i64)pCache->nMax ){ szBulk = pCache->szAlloc*pCache->nMax; } zBulk = pCache->pBulk = sqlite3Malloc( szBulk ); sqlite3EndBenignMalloc(); if( zBulk ){ int nBulk = sqlite3MallocSize(zBulk)/pCache->szAlloc; int i; for(i=0; i<nBulk; i++){ PgHdr1 *pX = (PgHdr1*)&zBulk[pCache->szPage]; pX->page.pBuf = zBulk; pX->page.pExtra = &pX[1]; pX->isBulkLocal = 1; pX->pNext = pCache->pFree; pCache->pFree = pX; zBulk += pCache->szAlloc; } } return pCache->pFree!=0; } /* ** Malloc function used within this file to allocate space from the buffer ** configured using sqlite3_config(SQLITE_CONFIG_PAGECACHE) option. If no ** such buffer exists or there is no space left in it, this function falls ** back to sqlite3Malloc(). ** |
︙ | ︙ | |||
40764 40765 40766 40767 40768 40769 40770 | ** Allocate a new page object initially associated with cache pCache. */ static PgHdr1 *pcache1AllocPage(PCache1 *pCache){ PgHdr1 *p = 0; void *pPg; assert( sqlite3_mutex_held(pCache->pGroup->mutex) ); | | | 40847 40848 40849 40850 40851 40852 40853 40854 40855 40856 40857 40858 40859 40860 40861 | ** Allocate a new page object initially associated with cache pCache. */ static PgHdr1 *pcache1AllocPage(PCache1 *pCache){ PgHdr1 *p = 0; void *pPg; assert( sqlite3_mutex_held(pCache->pGroup->mutex) ); if( pCache->pFree || (pCache->nPage==0 && pcache1InitBulk(pCache)) ){ p = pCache->pFree; pCache->pFree = p->pNext; p->pNext = 0; }else{ #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT /* The group mutex must be released before pcache1Alloc() is called. This ** is because it might call sqlite3_release_memory(), which assumes that |
︙ | ︙ | |||
40968 40969 40970 40971 40972 40973 40974 | if( freeFlag ) pcache1FreePage(pPage); } /* ** If there are currently more than nMaxPage pages allocated, try ** to recycle pages to reduce the number allocated to nMaxPage. */ | | > > > > > | 41051 41052 41053 41054 41055 41056 41057 41058 41059 41060 41061 41062 41063 41064 41065 41066 41067 41068 41069 41070 41071 41072 41073 41074 41075 41076 41077 | if( freeFlag ) pcache1FreePage(pPage); } /* ** If there are currently more than nMaxPage pages allocated, try ** to recycle pages to reduce the number allocated to nMaxPage. */ static void pcache1EnforceMaxPage(PCache1 *pCache){ PGroup *pGroup = pCache->pGroup; assert( sqlite3_mutex_held(pGroup->mutex) ); while( pGroup->nCurrentPage>pGroup->nMaxPage && pGroup->pLruTail ){ PgHdr1 *p = pGroup->pLruTail; assert( p->pCache->pGroup==pGroup ); assert( p->isPinned==0 ); pcache1PinPage(p); pcache1RemoveFromHash(p, 1); } if( pCache->nPage==0 && pCache->pBulk ){ sqlite3_free(pCache->pBulk); pCache->pBulk = pCache->pFree = 0; } } /* ** Discard all pages from cache pCache with a page number (key value) ** greater than or equal to iLimit. Any pinned pages that meet this ** criteria are unpinned before they are discarded. |
︙ | ︙ | |||
41052 41053 41054 41055 41056 41057 41058 41059 41060 41061 41062 41063 41064 41065 | #if SQLITE_THREADSAFE if( sqlite3GlobalConfig.bCoreMutex ){ pcache1.grp.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU); pcache1.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_PMEM); } #endif pcache1.grp.mxPinned = 10; pcache1.isInit = 1; return SQLITE_OK; } /* ** Implementation of the sqlite3_pcache.xShutdown method. | > > > > > > > > | 41140 41141 41142 41143 41144 41145 41146 41147 41148 41149 41150 41151 41152 41153 41154 41155 41156 41157 41158 41159 41160 41161 | #if SQLITE_THREADSAFE if( sqlite3GlobalConfig.bCoreMutex ){ pcache1.grp.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU); pcache1.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_PMEM); } #endif if( pcache1.separateCache && sqlite3GlobalConfig.nPage!=0 && sqlite3GlobalConfig.pPage==0 ){ pcache1.nInitPage = sqlite3GlobalConfig.nPage; }else{ pcache1.nInitPage = 0; } pcache1.grp.mxPinned = 10; pcache1.isInit = 1; return SQLITE_OK; } /* ** Implementation of the sqlite3_pcache.xShutdown method. |
︙ | ︙ | |||
41106 41107 41108 41109 41110 41111 41112 | pcache1ResizeHash(pCache); if( bPurgeable ){ pCache->nMin = 10; pGroup->nMinPage += pCache->nMin; pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage; } pcache1LeaveMutex(pGroup); | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 41202 41203 41204 41205 41206 41207 41208 41209 41210 41211 41212 41213 41214 41215 | pcache1ResizeHash(pCache); if( bPurgeable ){ pCache->nMin = 10; pGroup->nMinPage += pCache->nMin; pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage; } pcache1LeaveMutex(pGroup); if( pCache->nHash==0 ){ pcache1Destroy((sqlite3_pcache*)pCache); pCache = 0; } } return (sqlite3_pcache *)pCache; } |
︙ | ︙ | |||
41158 41159 41160 41161 41162 41163 41164 | if( pCache->bPurgeable ){ PGroup *pGroup = pCache->pGroup; pcache1EnterMutex(pGroup); pGroup->nMaxPage += (nMax - pCache->nMax); pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage; pCache->nMax = nMax; pCache->n90pct = pCache->nMax*9/10; | | | | 41224 41225 41226 41227 41228 41229 41230 41231 41232 41233 41234 41235 41236 41237 41238 41239 41240 41241 41242 41243 41244 41245 41246 41247 41248 41249 41250 41251 41252 41253 41254 41255 41256 | if( pCache->bPurgeable ){ PGroup *pGroup = pCache->pGroup; pcache1EnterMutex(pGroup); pGroup->nMaxPage += (nMax - pCache->nMax); pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage; pCache->nMax = nMax; pCache->n90pct = pCache->nMax*9/10; pcache1EnforceMaxPage(pCache); pcache1LeaveMutex(pGroup); } } /* ** Implementation of the sqlite3_pcache.xShrink method. ** ** Free up as much memory as possible. */ static void pcache1Shrink(sqlite3_pcache *p){ PCache1 *pCache = (PCache1*)p; if( pCache->bPurgeable ){ PGroup *pGroup = pCache->pGroup; int savedMaxPage; pcache1EnterMutex(pGroup); savedMaxPage = pGroup->nMaxPage; pGroup->nMaxPage = 0; pcache1EnforceMaxPage(pCache); pGroup->nMaxPage = savedMaxPage; pcache1LeaveMutex(pGroup); } } /* ** Implementation of the sqlite3_pcache.xPagecount method. |
︙ | ︙ | |||
41513 41514 41515 41516 41517 41518 41519 | pcache1EnterMutex(pGroup); pcache1TruncateUnsafe(pCache, 0); assert( pGroup->nMaxPage >= pCache->nMax ); pGroup->nMaxPage -= pCache->nMax; assert( pGroup->nMinPage >= pCache->nMin ); pGroup->nMinPage -= pCache->nMin; pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage; | | | 41579 41580 41581 41582 41583 41584 41585 41586 41587 41588 41589 41590 41591 41592 41593 | pcache1EnterMutex(pGroup); pcache1TruncateUnsafe(pCache, 0); assert( pGroup->nMaxPage >= pCache->nMax ); pGroup->nMaxPage -= pCache->nMax; assert( pGroup->nMinPage >= pCache->nMin ); pGroup->nMinPage -= pCache->nMin; pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage; pcache1EnforceMaxPage(pCache); pcache1LeaveMutex(pGroup); sqlite3_free(pCache->pBulk); sqlite3_free(pCache->apHash); sqlite3_free(pCache); } /* |
︙ | ︙ | |||
41677 41678 41679 41680 41681 41682 41683 41684 41685 41686 41687 41688 41689 41690 | ** The cost of a TEST using the same batch number is O(logN). The cost ** of the first SMALLEST is O(NlogN). Second and subsequent SMALLEST ** primitives are constant time. The cost of DESTROY is O(N). ** ** There is an added cost of O(N) when switching between TEST and ** SMALLEST primitives. */ /* ** Target size for allocation chunks. */ #define ROWSET_ALLOCATION_SIZE 1024 | > | 41743 41744 41745 41746 41747 41748 41749 41750 41751 41752 41753 41754 41755 41756 41757 | ** The cost of a TEST using the same batch number is O(logN). The cost ** of the first SMALLEST is O(NlogN). Second and subsequent SMALLEST ** primitives are constant time. The cost of DESTROY is O(N). ** ** There is an added cost of O(N) when switching between TEST and ** SMALLEST primitives. */ /* #include "sqliteInt.h" */ /* ** Target size for allocation chunks. */ #define ROWSET_ALLOCATION_SIZE 1024 |
︙ | ︙ | |||
42146 42147 42148 42149 42150 42151 42152 42153 42154 42155 42156 42157 42158 42159 | ** 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. */ #ifndef SQLITE_OMIT_DISKIO /************** Include wal.h in the middle of pager.c ***********************/ /************** Begin file wal.h *********************************************/ /* ** 2010 February 1 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: | > | 42213 42214 42215 42216 42217 42218 42219 42220 42221 42222 42223 42224 42225 42226 42227 | ** 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. */ #ifndef SQLITE_OMIT_DISKIO /* #include "sqliteInt.h" */ /************** Include wal.h in the middle of pager.c ***********************/ /************** Begin file wal.h *********************************************/ /* ** 2010 February 1 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: |
︙ | ︙ | |||
42167 42168 42169 42170 42171 42172 42173 42174 42175 42176 42177 42178 42179 42180 | ** system. Refer to the comments below and the header comment attached to ** the implementation of each function in log.c for further details. */ #ifndef _WAL_H_ #define _WAL_H_ /* Additional values that can be added to the sync_flags argument of ** sqlite3WalFrames(): */ #define WAL_SYNC_TRANSACTIONS 0x20 /* Sync at the end of each transaction */ #define SQLITE_SYNC_MASK 0x13 /* Mask off the SQLITE_SYNC_* values */ | > | 42235 42236 42237 42238 42239 42240 42241 42242 42243 42244 42245 42246 42247 42248 42249 | ** system. Refer to the comments below and the header comment attached to ** the implementation of each function in log.c for further details. */ #ifndef _WAL_H_ #define _WAL_H_ /* #include "sqliteInt.h" */ /* Additional values that can be added to the sync_flags argument of ** sqlite3WalFrames(): */ #define WAL_SYNC_TRANSACTIONS 0x20 /* Sync at the end of each transaction */ #define SQLITE_SYNC_MASK 0x13 /* Mask off the SQLITE_SYNC_* values */ |
︙ | ︙ | |||
49781 49782 49783 49784 49785 49786 49787 49788 49789 49790 49791 49792 49793 49794 | ** ** When a rollback occurs, the value of K is decreased. Hash table entries ** that correspond to frames greater than the new K value are removed ** from the hash table at this point. */ #ifndef SQLITE_OMIT_WAL /* ** Trace output macros */ #if defined(SQLITE_TEST) && defined(SQLITE_DEBUG) SQLITE_PRIVATE int sqlite3WalTrace = 0; # define WALTRACE(X) if(sqlite3WalTrace) sqlite3DebugPrintf X | > | 49850 49851 49852 49853 49854 49855 49856 49857 49858 49859 49860 49861 49862 49863 49864 | ** ** When a rollback occurs, the value of K is decreased. Hash table entries ** that correspond to frames greater than the new K value are removed ** from the hash table at this point. */ #ifndef SQLITE_OMIT_WAL /* #include "wal.h" */ /* ** Trace output macros */ #if defined(SQLITE_TEST) && defined(SQLITE_DEBUG) SQLITE_PRIVATE int sqlite3WalTrace = 0; # define WALTRACE(X) if(sqlite3WalTrace) sqlite3DebugPrintf X |
︙ | ︙ | |||
50186 50187 50188 50189 50190 50191 50192 | volatile WalIndexHdr *aHdr = walIndexHdr(pWal); const int nCksum = offsetof(WalIndexHdr, aCksum); assert( pWal->writeLock ); pWal->hdr.isInit = 1; pWal->hdr.iVersion = WALINDEX_MAX_VERSION; walChecksumBytes(1, (u8*)&pWal->hdr, nCksum, 0, pWal->hdr.aCksum); | | | | 50256 50257 50258 50259 50260 50261 50262 50263 50264 50265 50266 50267 50268 50269 50270 50271 50272 | volatile WalIndexHdr *aHdr = walIndexHdr(pWal); const int nCksum = offsetof(WalIndexHdr, aCksum); assert( pWal->writeLock ); pWal->hdr.isInit = 1; pWal->hdr.iVersion = WALINDEX_MAX_VERSION; walChecksumBytes(1, (u8*)&pWal->hdr, nCksum, 0, pWal->hdr.aCksum); memcpy((void*)&aHdr[1], (const void*)&pWal->hdr, sizeof(WalIndexHdr)); walShmBarrier(pWal); memcpy((void*)&aHdr[0], (const void*)&pWal->hdr, sizeof(WalIndexHdr)); } /* ** This function encodes a single frame header and writes it to a buffer ** supplied by the caller. A frame-header is made up of a series of ** 4-byte big-endian integers, as follows: ** |
︙ | ︙ | |||
50490 50491 50492 50493 50494 50495 50496 | memset((void *)&aPgno[iLimit+1], 0, nByte); #ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT /* Verify that the every entry in the mapping region is still reachable ** via the hash table even after the cleanup. */ if( iLimit ){ | | | | | | | 50560 50561 50562 50563 50564 50565 50566 50567 50568 50569 50570 50571 50572 50573 50574 50575 50576 50577 50578 50579 50580 | memset((void *)&aPgno[iLimit+1], 0, nByte); #ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT /* Verify that the every entry in the mapping region is still reachable ** via the hash table even after the cleanup. */ if( iLimit ){ int j; /* Loop counter */ int iKey; /* Hash key */ for(j=1; j<=iLimit; j++){ for(iKey=walHash(aPgno[j]); aHash[iKey]; iKey=walNextHash(iKey)){ if( aHash[iKey]==j ) break; } assert( aHash[iKey]==j ); } } #endif /* SQLITE_ENABLE_EXPENSIVE_ASSERT */ } /* |
︙ | ︙ | |||
50998 50999 51000 51001 51002 51003 51004 | ht_slot *aList; /* Pointer to sub-list content */ }; const int nList = *pnList; /* Size of input list */ int nMerge = 0; /* Number of elements in list aMerge */ ht_slot *aMerge = 0; /* List to be merged */ int iList; /* Index into input list */ | | | > > | > > | 51068 51069 51070 51071 51072 51073 51074 51075 51076 51077 51078 51079 51080 51081 51082 51083 51084 51085 51086 51087 51088 51089 51090 51091 51092 51093 51094 51095 51096 51097 51098 51099 51100 51101 51102 51103 51104 51105 51106 51107 51108 | ht_slot *aList; /* Pointer to sub-list content */ }; const int nList = *pnList; /* Size of input list */ int nMerge = 0; /* Number of elements in list aMerge */ ht_slot *aMerge = 0; /* List to be merged */ int iList; /* Index into input list */ u32 iSub = 0; /* Index into aSub array */ struct Sublist aSub[13]; /* Array of sub-lists */ memset(aSub, 0, sizeof(aSub)); assert( nList<=HASHTABLE_NPAGE && nList>0 ); assert( HASHTABLE_NPAGE==(1<<(ArraySize(aSub)-1)) ); for(iList=0; iList<nList; iList++){ nMerge = 1; aMerge = &aList[iList]; for(iSub=0; iList & (1<<iSub); iSub++){ struct Sublist *p; assert( iSub<ArraySize(aSub) ); p = &aSub[iSub]; assert( p->aList && p->nList<=(1<<iSub) ); assert( p->aList==&aList[iList&~((2<<iSub)-1)] ); walMerge(aContent, p->aList, p->nList, &aMerge, &nMerge, aBuffer); } aSub[iSub].aList = aMerge; aSub[iSub].nList = nMerge; } for(iSub++; iSub<ArraySize(aSub); iSub++){ if( nList & (1<<iSub) ){ struct Sublist *p; assert( iSub<ArraySize(aSub) ); p = &aSub[iSub]; assert( p->nList<=(1<<iSub) ); assert( p->aList==&aList[nList&~((2<<iSub)-1)] ); walMerge(aContent, p->aList, p->nList, &aMerge, &nMerge, aBuffer); } } assert( aMerge==aList ); *pnList = nMerge; |
︙ | ︙ | |||
52931 52932 52933 52934 52935 52936 52937 52938 52939 52940 52941 52942 52943 52944 | ** unspecified. A trunk page looks like this: ** ** SIZE DESCRIPTION ** 4 Page number of next trunk page ** 4 Number of leaf pointers on this page ** * zero or more pages numbers of leaves */ /* The following value is the maximum cell size assuming a maximum page ** size give above. */ #define MX_CELL_SIZE(pBt) ((int)(pBt->pageSize-8)) | > | 53005 53006 53007 53008 53009 53010 53011 53012 53013 53014 53015 53016 53017 53018 53019 | ** unspecified. A trunk page looks like this: ** ** SIZE DESCRIPTION ** 4 Page number of next trunk page ** 4 Number of leaf pointers on this page ** * zero or more pages numbers of leaves */ /* #include "sqliteInt.h" */ /* The following value is the maximum cell size assuming a maximum page ** size give above. */ #define MX_CELL_SIZE(pBt) ((int)(pBt->pageSize-8)) |
︙ | ︙ | |||
53728 53729 53730 53731 53732 53733 53734 53735 53736 53737 53738 53739 53740 53741 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file implements an external (disk-based) database using BTrees. ** See the header comment on "btreeInt.h" for additional information. ** Including a description of file format and an overview of operation. */ /* ** The header string that appears at the beginning of every ** SQLite database. */ static const char zMagicHeader[] = SQLITE_FILE_HEADER; | > | 53803 53804 53805 53806 53807 53808 53809 53810 53811 53812 53813 53814 53815 53816 53817 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file implements an external (disk-based) database using BTrees. ** See the header comment on "btreeInt.h" for additional information. ** Including a description of file format and an overview of operation. */ /* #include "btreeInt.h" */ /* ** The header string that appears at the beginning of every ** SQLite database. */ static const char zMagicHeader[] = SQLITE_FILE_HEADER; |
︙ | ︙ | |||
62673 62674 62675 62676 62677 62678 62679 | u32 usableSize; /* Usable size of the page */ u32 contentOffset; /* Offset to the start of the cell content area */ u32 *heap = 0; /* Min-heap used for checking cell coverage */ u32 x, prev = 0; /* Next and previous entry on the min-heap */ const char *saved_zPfx = pCheck->zPfx; int saved_v1 = pCheck->v1; int saved_v2 = pCheck->v2; | | | 62749 62750 62751 62752 62753 62754 62755 62756 62757 62758 62759 62760 62761 62762 62763 | u32 usableSize; /* Usable size of the page */ u32 contentOffset; /* Offset to the start of the cell content area */ u32 *heap = 0; /* Min-heap used for checking cell coverage */ u32 x, prev = 0; /* Next and previous entry on the min-heap */ const char *saved_zPfx = pCheck->zPfx; int saved_v1 = pCheck->v1; int saved_v2 = pCheck->v2; u8 savedIsInit = 0; /* Check that the page exists */ pBt = pCheck->pBt; usableSize = pBt->usableSize; if( iPage==0 ) return 0; if( checkRef(pCheck, iPage) ) return 0; |
︙ | ︙ | |||
63309 63310 63311 63312 63313 63314 63315 63316 63317 63318 63319 63320 63321 63322 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains the implementation of the sqlite3_backup_XXX() ** API functions and the related features. */ /* ** Structure allocated for each backup operation. */ struct sqlite3_backup { sqlite3* pDestDb; /* Destination database handle */ Btree *pDest; /* Destination b-tree file */ | > > | 63385 63386 63387 63388 63389 63390 63391 63392 63393 63394 63395 63396 63397 63398 63399 63400 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains the implementation of the sqlite3_backup_XXX() ** API functions and the related features. */ /* #include "sqliteInt.h" */ /* #include "btreeInt.h" */ /* ** Structure allocated for each backup operation. */ struct sqlite3_backup { sqlite3* pDestDb; /* Destination database handle */ Btree *pDest; /* Destination b-tree file */ |
︙ | ︙ | |||
64107 64108 64109 64110 64111 64112 64113 64114 64115 64116 64117 64118 64119 64120 | ************************************************************************* ** ** This file contains code use to manipulate "Mem" structure. A "Mem" ** stores a single value in the VDBE. Mem is an opaque structure visible ** only within the VDBE. Interface routines refer to a Mem using the ** name sqlite_value */ #ifdef SQLITE_DEBUG /* ** Check invariants on a Mem object. ** ** This routine is intended for use inside of assert() statements, like ** this: assert( sqlite3VdbeCheckMemInvariants(pMem) ); | > > | 64185 64186 64187 64188 64189 64190 64191 64192 64193 64194 64195 64196 64197 64198 64199 64200 | ************************************************************************* ** ** This file contains code use to manipulate "Mem" structure. A "Mem" ** stores a single value in the VDBE. Mem is an opaque structure visible ** only within the VDBE. Interface routines refer to a Mem using the ** name sqlite_value */ /* #include "sqliteInt.h" */ /* #include "vdbeInt.h" */ #ifdef SQLITE_DEBUG /* ** Check invariants on a Mem object. ** ** This routine is intended for use inside of assert() statements, like ** this: assert( sqlite3VdbeCheckMemInvariants(pMem) ); |
︙ | ︙ | |||
65824 65825 65826 65827 65828 65829 65830 65831 65832 65833 65834 65835 65836 65837 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains code used for creating, destroying, and populating ** a VDBE (or an "sqlite3_stmt" as it is known to the outside world.) */ /* ** Create a new virtual database engine. */ SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(Parse *pParse){ sqlite3 *db = pParse->db; Vdbe *p; | > > | 65904 65905 65906 65907 65908 65909 65910 65911 65912 65913 65914 65915 65916 65917 65918 65919 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains code used for creating, destroying, and populating ** a VDBE (or an "sqlite3_stmt" as it is known to the outside world.) */ /* #include "sqliteInt.h" */ /* #include "vdbeInt.h" */ /* ** Create a new virtual database engine. */ SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(Parse *pParse){ sqlite3 *db = pParse->db; Vdbe *p; |
︙ | ︙ | |||
70072 70073 70074 70075 70076 70077 70078 70079 70080 70081 70082 70083 70084 70085 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** ** This file contains code use to implement APIs that are part of the ** VDBE. */ #ifndef SQLITE_OMIT_DEPRECATED /* ** Return TRUE (non-zero) of the statement supplied as an argument needs ** to be recompiled. A statement needs to be recompiled whenever the ** execution environment changes in a way that would alter the program ** that sqlite3_prepare() generates. For example, if new functions or | > > | 70154 70155 70156 70157 70158 70159 70160 70161 70162 70163 70164 70165 70166 70167 70168 70169 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** ** This file contains code use to implement APIs that are part of the ** VDBE. */ /* #include "sqliteInt.h" */ /* #include "vdbeInt.h" */ #ifndef SQLITE_OMIT_DEPRECATED /* ** Return TRUE (non-zero) of the statement supplied as an argument needs ** to be recompiled. A statement needs to be recompiled whenever the ** execution environment changes in a way that would alter the program ** that sqlite3_prepare() generates. For example, if new functions or |
︙ | ︙ | |||
70110 70111 70112 70113 70114 70115 70116 70117 70118 70119 70120 70121 70122 70123 70124 70125 70126 70127 70128 70129 70130 70131 70132 70133 70134 70135 70136 70137 70138 70139 70140 70141 70142 70143 | sqlite3_log(SQLITE_MISUSE, "API called with NULL prepared statement"); return 1; }else{ return vdbeSafety(p); } } /* ** The following routine destroys a virtual machine that is created by ** the sqlite3_compile() routine. The integer returned is an SQLITE_ ** success/failure code that describes the result of executing the virtual ** machine. ** ** This routine sets the error code and string returned by ** sqlite3_errcode(), sqlite3_errmsg() and sqlite3_errmsg16(). */ SQLITE_API int SQLITE_STDCALL sqlite3_finalize(sqlite3_stmt *pStmt){ int rc; if( pStmt==0 ){ /* IMPLEMENTATION-OF: R-57228-12904 Invoking sqlite3_finalize() on a NULL ** pointer is a harmless no-op. */ rc = SQLITE_OK; }else{ Vdbe *v = (Vdbe*)pStmt; sqlite3 *db = v->db; if( vdbeSafety(v) ) return SQLITE_MISUSE_BKPT; sqlite3_mutex_enter(db->mutex); rc = sqlite3VdbeFinalize(v); rc = sqlite3ApiExit(db, rc); sqlite3LeaveMutexAndCloseZombie(db); } return rc; } | > > > > > > > > > > > > > > > > > > > > > > > > > > | 70194 70195 70196 70197 70198 70199 70200 70201 70202 70203 70204 70205 70206 70207 70208 70209 70210 70211 70212 70213 70214 70215 70216 70217 70218 70219 70220 70221 70222 70223 70224 70225 70226 70227 70228 70229 70230 70231 70232 70233 70234 70235 70236 70237 70238 70239 70240 70241 70242 70243 70244 70245 70246 70247 70248 70249 70250 70251 70252 70253 | sqlite3_log(SQLITE_MISUSE, "API called with NULL prepared statement"); return 1; }else{ return vdbeSafety(p); } } #ifndef SQLITE_OMIT_TRACE /* ** Invoke the profile callback. This routine is only called if we already ** know that the profile callback is defined and needs to be invoked. */ static SQLITE_NOINLINE void invokeProfileCallback(sqlite3 *db, Vdbe *p){ sqlite3_int64 iNow; assert( p->startTime>0 ); assert( db->xProfile!=0 ); assert( db->init.busy==0 ); assert( p->zSql!=0 ); sqlite3OsCurrentTimeInt64(db->pVfs, &iNow); db->xProfile(db->pProfileArg, p->zSql, (iNow - p->startTime)*1000000); p->startTime = 0; } /* ** The checkProfileCallback(DB,P) macro checks to see if a profile callback ** is needed, and it invokes the callback if it is needed. */ # define checkProfileCallback(DB,P) \ if( ((P)->startTime)>0 ){ invokeProfileCallback(DB,P); } #else # define checkProfileCallback(DB,P) /*no-op*/ #endif /* ** The following routine destroys a virtual machine that is created by ** the sqlite3_compile() routine. The integer returned is an SQLITE_ ** success/failure code that describes the result of executing the virtual ** machine. ** ** This routine sets the error code and string returned by ** sqlite3_errcode(), sqlite3_errmsg() and sqlite3_errmsg16(). */ SQLITE_API int SQLITE_STDCALL sqlite3_finalize(sqlite3_stmt *pStmt){ int rc; if( pStmt==0 ){ /* IMPLEMENTATION-OF: R-57228-12904 Invoking sqlite3_finalize() on a NULL ** pointer is a harmless no-op. */ rc = SQLITE_OK; }else{ Vdbe *v = (Vdbe*)pStmt; sqlite3 *db = v->db; if( vdbeSafety(v) ) return SQLITE_MISUSE_BKPT; sqlite3_mutex_enter(db->mutex); checkProfileCallback(db, v); rc = sqlite3VdbeFinalize(v); rc = sqlite3ApiExit(db, rc); sqlite3LeaveMutexAndCloseZombie(db); } return rc; } |
︙ | ︙ | |||
70151 70152 70153 70154 70155 70156 70157 | */ SQLITE_API int SQLITE_STDCALL sqlite3_reset(sqlite3_stmt *pStmt){ int rc; if( pStmt==0 ){ rc = SQLITE_OK; }else{ Vdbe *v = (Vdbe*)pStmt; | > | > | | | | 70261 70262 70263 70264 70265 70266 70267 70268 70269 70270 70271 70272 70273 70274 70275 70276 70277 70278 70279 70280 70281 70282 | */ SQLITE_API int SQLITE_STDCALL sqlite3_reset(sqlite3_stmt *pStmt){ int rc; if( pStmt==0 ){ rc = SQLITE_OK; }else{ Vdbe *v = (Vdbe*)pStmt; sqlite3 *db = v->db; sqlite3_mutex_enter(db->mutex); checkProfileCallback(db, v); rc = sqlite3VdbeReset(v); sqlite3VdbeRewind(v); assert( (rc & (db->errMask))==rc ); rc = sqlite3ApiExit(db, rc); sqlite3_mutex_leave(db->mutex); } return rc; } /* ** Set all the parameters in the compiled SQL statement to NULL. */ |
︙ | ︙ | |||
70191 70192 70193 70194 70195 70196 70197 | /**************************** sqlite3_value_ ******************************* ** The following routines extract information from a Mem or sqlite3_value ** structure. */ SQLITE_API const void *SQLITE_STDCALL sqlite3_value_blob(sqlite3_value *pVal){ Mem *p = (Mem*)pVal; if( p->flags & (MEM_Blob|MEM_Str) ){ | | > > > | 70303 70304 70305 70306 70307 70308 70309 70310 70311 70312 70313 70314 70315 70316 70317 70318 70319 70320 | /**************************** sqlite3_value_ ******************************* ** The following routines extract information from a Mem or sqlite3_value ** structure. */ SQLITE_API const void *SQLITE_STDCALL sqlite3_value_blob(sqlite3_value *pVal){ Mem *p = (Mem*)pVal; if( p->flags & (MEM_Blob|MEM_Str) ){ if( sqlite3VdbeMemExpandBlob(p)!=SQLITE_OK ){ assert( p->flags==MEM_Null && p->z==0 ); return 0; } p->flags |= MEM_Blob; return p->n ? p->z : 0; }else{ return sqlite3_value_text(pVal); } } SQLITE_API int SQLITE_STDCALL sqlite3_value_bytes(sqlite3_value *pVal){ |
︙ | ︙ | |||
70452 70453 70454 70455 70456 70457 70458 70459 70460 70461 70462 70463 70464 70465 | SQLITE_API void SQLITE_STDCALL sqlite3_result_value(sqlite3_context *pCtx, sqlite3_value *pValue){ assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); sqlite3VdbeMemCopy(pCtx->pOut, pValue); } SQLITE_API void SQLITE_STDCALL sqlite3_result_zeroblob(sqlite3_context *pCtx, int n){ assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); sqlite3VdbeMemSetZeroBlob(pCtx->pOut, n); } SQLITE_API void SQLITE_STDCALL sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){ pCtx->isError = errCode; pCtx->fErrorOrAux = 1; #ifdef SQLITE_DEBUG if( pCtx->pVdbe ) pCtx->pVdbe->rcApp = errCode; #endif | > > > > > > > > > | 70567 70568 70569 70570 70571 70572 70573 70574 70575 70576 70577 70578 70579 70580 70581 70582 70583 70584 70585 70586 70587 70588 70589 | SQLITE_API void SQLITE_STDCALL sqlite3_result_value(sqlite3_context *pCtx, sqlite3_value *pValue){ assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); sqlite3VdbeMemCopy(pCtx->pOut, pValue); } SQLITE_API void SQLITE_STDCALL sqlite3_result_zeroblob(sqlite3_context *pCtx, int n){ assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); sqlite3VdbeMemSetZeroBlob(pCtx->pOut, n); } SQLITE_API int SQLITE_STDCALL sqlite3_result_zeroblob64(sqlite3_context *pCtx, u64 n){ Mem *pOut = pCtx->pOut; assert( sqlite3_mutex_held(pOut->db->mutex) ); if( n>(u64)pOut->db->aLimit[SQLITE_LIMIT_LENGTH] ){ return SQLITE_TOOBIG; } sqlite3VdbeMemSetZeroBlob(pCtx->pOut, (int)n); return SQLITE_OK; } SQLITE_API void SQLITE_STDCALL sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){ pCtx->isError = errCode; pCtx->fErrorOrAux = 1; #ifdef SQLITE_DEBUG if( pCtx->pVdbe ) pCtx->pVdbe->rcApp = errCode; #endif |
︙ | ︙ | |||
70506 70507 70508 70509 70510 70511 70512 70513 70514 70515 70516 70517 70518 70519 | rc = db->xWalCallback(db->pWalArg, db, db->aDb[i].zName, nEntry); } } } #endif return rc; } /* ** Execute the statement pStmt, either until a row of data is ready, the ** statement is completely executed or an error occurs. ** ** This routine implements the bulk of the logic behind the sqlite_step() ** API. The only thing omitted is the automatic recompile if a | > | 70630 70631 70632 70633 70634 70635 70636 70637 70638 70639 70640 70641 70642 70643 70644 | rc = db->xWalCallback(db->pWalArg, db, db->aDb[i].zName, nEntry); } } } #endif return rc; } /* ** Execute the statement pStmt, either until a row of data is ready, the ** statement is completely executed or an error occurs. ** ** This routine implements the bulk of the logic behind the sqlite_step() ** API. The only thing omitted is the automatic recompile if a |
︙ | ︙ | |||
70575 70576 70577 70578 70579 70580 70581 | } assert( db->nVdbeWrite>0 || db->autoCommit==0 || (db->nDeferredCons==0 && db->nDeferredImmCons==0) ); #ifndef SQLITE_OMIT_TRACE | | > > | 70700 70701 70702 70703 70704 70705 70706 70707 70708 70709 70710 70711 70712 70713 70714 70715 70716 70717 | } assert( db->nVdbeWrite>0 || db->autoCommit==0 || (db->nDeferredCons==0 && db->nDeferredImmCons==0) ); #ifndef SQLITE_OMIT_TRACE if( db->xProfile && !db->init.busy && p->zSql ){ sqlite3OsCurrentTimeInt64(db->pVfs, &p->startTime); }else{ assert( p->startTime==0 ); } #endif db->nVdbeActive++; if( p->readOnly==0 ) db->nVdbeWrite++; if( p->bIsReader ) db->nVdbeRead++; p->pc = 0; |
︙ | ︙ | |||
70600 70601 70602 70603 70604 70605 70606 | { db->nVdbeExec++; rc = sqlite3VdbeExec(p); db->nVdbeExec--; } #ifndef SQLITE_OMIT_TRACE | | < | < < < < | 70727 70728 70729 70730 70731 70732 70733 70734 70735 70736 70737 70738 70739 70740 70741 70742 | { db->nVdbeExec++; rc = sqlite3VdbeExec(p); db->nVdbeExec--; } #ifndef SQLITE_OMIT_TRACE /* If the statement completed successfully, invoke the profile callback */ if( rc!=SQLITE_ROW ) checkProfileCallback(db, p); #endif if( rc==SQLITE_DONE ){ assert( p->rc==SQLITE_OK ); p->rc = doWalCallbacks(db); if( p->rc!=SQLITE_OK ){ rc = SQLITE_ERROR; |
︙ | ︙ | |||
71434 71435 71436 71437 71438 71439 71440 71441 71442 71443 71444 71445 71446 71447 | rc = vdbeUnbind(p, i); if( rc==SQLITE_OK ){ sqlite3VdbeMemSetZeroBlob(&p->aVar[i-1], n); sqlite3_mutex_leave(p->db->mutex); } return rc; } /* ** Return the number of wildcards that can be potentially bound to. ** This routine is added to support DBD::SQLite. */ SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_count(sqlite3_stmt *pStmt){ Vdbe *p = (Vdbe*)pStmt; | > > > > > > > > > > > > > > | 71556 71557 71558 71559 71560 71561 71562 71563 71564 71565 71566 71567 71568 71569 71570 71571 71572 71573 71574 71575 71576 71577 71578 71579 71580 71581 71582 71583 | rc = vdbeUnbind(p, i); if( rc==SQLITE_OK ){ sqlite3VdbeMemSetZeroBlob(&p->aVar[i-1], n); sqlite3_mutex_leave(p->db->mutex); } return rc; } SQLITE_API int SQLITE_STDCALL sqlite3_bind_zeroblob64(sqlite3_stmt *pStmt, int i, sqlite3_uint64 n){ int rc; Vdbe *p = (Vdbe *)pStmt; sqlite3_mutex_enter(p->db->mutex); if( n>(u64)p->db->aLimit[SQLITE_LIMIT_LENGTH] ){ rc = SQLITE_TOOBIG; }else{ assert( (n & 0x7FFFFFFF)==n ); rc = sqlite3_bind_zeroblob(pStmt, i, n); } rc = sqlite3ApiExit(p->db, rc); sqlite3_mutex_leave(p->db->mutex); return rc; } /* ** Return the number of wildcards that can be potentially bound to. ** This routine is added to support DBD::SQLite. */ SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_count(sqlite3_stmt *pStmt){ Vdbe *p = (Vdbe*)pStmt; |
︙ | ︙ | |||
71683 71684 71685 71686 71687 71688 71689 71690 71691 71692 71693 71694 71695 71696 | ************************************************************************* ** ** This file contains code used to insert the values of host parameters ** (aka "wildcards") into the SQL text output by sqlite3_trace(). ** ** The Vdbe parse-tree explainer is also found here. */ #ifndef SQLITE_OMIT_TRACE /* ** zSql is a zero-terminated string of UTF-8 SQL text. Return the number of ** bytes in this text up to but excluding the first character in ** a host parameter. If the text contains no host parameters, return | > > | 71819 71820 71821 71822 71823 71824 71825 71826 71827 71828 71829 71830 71831 71832 71833 71834 | ************************************************************************* ** ** This file contains code used to insert the values of host parameters ** (aka "wildcards") into the SQL text output by sqlite3_trace(). ** ** The Vdbe parse-tree explainer is also found here. */ /* #include "sqliteInt.h" */ /* #include "vdbeInt.h" */ #ifndef SQLITE_OMIT_TRACE /* ** zSql is a zero-terminated string of UTF-8 SQL text. Return the number of ** bytes in this text up to but excluding the first character in ** a host parameter. If the text contains no host parameters, return |
︙ | ︙ | |||
71875 71876 71877 71878 71879 71880 71881 71882 71883 71884 71885 71886 71887 71888 | ** ** 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. */ /* ** Invoke this macro on memory cells just prior to changing the ** value of the cell. This macro verifies that shallow copies are ** not misused. A shallow copy of a string or blob just copies a ** pointer to the string or blob, not the content. If the original ** is changed while the copy is still in use, the string or blob might | > > | 72013 72014 72015 72016 72017 72018 72019 72020 72021 72022 72023 72024 72025 72026 72027 72028 | ** ** 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. */ /* #include "sqliteInt.h" */ /* #include "vdbeInt.h" */ /* ** Invoke this macro on memory cells just prior to changing the ** value of the cell. This macro verifies that shallow copies are ** not misused. A shallow copy of a string or blob just copies a ** pointer to the string or blob, not the content. If the original ** is changed while the copy is still in use, the string or blob might |
︙ | ︙ | |||
74646 74647 74648 74649 74650 74651 74652 | pRec = pLast; do{ assert( memIsValid(pRec) ); pRec->uTemp = serial_type = sqlite3VdbeSerialType(pRec, file_format); len = sqlite3VdbeSerialTypeLen(serial_type); if( pRec->flags & MEM_Zero ){ if( nData ){ | | | 74786 74787 74788 74789 74790 74791 74792 74793 74794 74795 74796 74797 74798 74799 74800 | pRec = pLast; do{ assert( memIsValid(pRec) ); pRec->uTemp = serial_type = sqlite3VdbeSerialType(pRec, file_format); len = sqlite3VdbeSerialTypeLen(serial_type); if( pRec->flags & MEM_Zero ){ if( nData ){ if( sqlite3VdbeMemExpandBlob(pRec) ) goto no_mem; }else{ nZero += pRec->u.nZero; len -= pRec->u.nZero; } } nData += len; testcase( serial_type==127 ); |
︙ | ︙ | |||
78633 78634 78635 78636 78637 78638 78639 78640 78641 78642 78643 78644 78645 78646 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** ** This file contains code used to implement incremental BLOB I/O. */ #ifndef SQLITE_OMIT_INCRBLOB /* ** Valid sqlite3_blob* handles point to Incrblob structures. */ typedef struct Incrblob Incrblob; | > > | 78773 78774 78775 78776 78777 78778 78779 78780 78781 78782 78783 78784 78785 78786 78787 78788 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** ** This file contains code used to implement incremental BLOB I/O. */ /* #include "sqliteInt.h" */ /* #include "vdbeInt.h" */ #ifndef SQLITE_OMIT_INCRBLOB /* ** Valid sqlite3_blob* handles point to Incrblob structures. */ typedef struct Incrblob Incrblob; |
︙ | ︙ | |||
79231 79232 79233 79234 79235 79236 79237 79238 79239 79240 79241 79242 79243 79244 | ** If running in multi-threaded mode and there are more than ** SORTER_MAX_MERGE_COUNT PMAs on disk when Rewind() is called, then more ** than one background thread may be created. Specifically, there may be ** one background thread for each temporary file on disk, and one background ** thread to merge the output of each of the others to a single PMA for ** the main thread to read from. */ /* ** If SQLITE_DEBUG_SORTER_THREADS is defined, this module outputs various ** messages to stderr that may be helpful in understanding the performance ** characteristics of the sorter in multi-threaded mode. */ #if 0 | > > | 79373 79374 79375 79376 79377 79378 79379 79380 79381 79382 79383 79384 79385 79386 79387 79388 | ** If running in multi-threaded mode and there are more than ** SORTER_MAX_MERGE_COUNT PMAs on disk when Rewind() is called, then more ** than one background thread may be created. Specifically, there may be ** one background thread for each temporary file on disk, and one background ** thread to merge the output of each of the others to a single PMA for ** the main thread to read from. */ /* #include "sqliteInt.h" */ /* #include "vdbeInt.h" */ /* ** If SQLITE_DEBUG_SORTER_THREADS is defined, this module outputs various ** messages to stderr that may be helpful in understanding the performance ** characteristics of the sorter in multi-threaded mode. */ #if 0 |
︙ | ︙ | |||
81847 81848 81849 81850 81851 81852 81853 81854 81855 81856 81857 81858 81859 81860 | ** on disk is not created or populated until either: ** ** 1) The in-memory representation grows too large for the allocated ** buffer, or ** 2) The sqlite3JournalCreate() function is called. */ #ifdef SQLITE_ENABLE_ATOMIC_WRITE /* ** A JournalFile object is a subclass of sqlite3_file used by ** as an open file handle for journal files. */ struct JournalFile { | > | 81991 81992 81993 81994 81995 81996 81997 81998 81999 82000 82001 82002 82003 82004 82005 | ** on disk is not created or populated until either: ** ** 1) The in-memory representation grows too large for the allocated ** buffer, or ** 2) The sqlite3JournalCreate() function is called. */ #ifdef SQLITE_ENABLE_ATOMIC_WRITE /* #include "sqliteInt.h" */ /* ** A JournalFile object is a subclass of sqlite3_file used by ** as an open file handle for journal files. */ struct JournalFile { |
︙ | ︙ | |||
82094 82095 82096 82097 82098 82099 82100 82101 82102 82103 82104 82105 82106 82107 | ** ************************************************************************* ** ** This file contains code use to implement an in-memory rollback journal. ** The in-memory rollback journal is used to journal transactions for ** ":memory:" databases and when the journal_mode=MEMORY pragma is used. */ /* Forward references to internal structures */ typedef struct MemJournal MemJournal; typedef struct FilePoint FilePoint; typedef struct FileChunk FileChunk; /* Space to hold the rollback journal is allocated in increments of | > | 82239 82240 82241 82242 82243 82244 82245 82246 82247 82248 82249 82250 82251 82252 82253 | ** ************************************************************************* ** ** This file contains code use to implement an in-memory rollback journal. ** The in-memory rollback journal is used to journal transactions for ** ":memory:" databases and when the journal_mode=MEMORY pragma is used. */ /* #include "sqliteInt.h" */ /* Forward references to internal structures */ typedef struct MemJournal MemJournal; typedef struct FilePoint FilePoint; typedef struct FileChunk FileChunk; /* Space to hold the rollback journal is allocated in increments of |
︙ | ︙ | |||
82349 82350 82351 82352 82353 82354 82355 82356 82357 82358 82359 82360 82361 82362 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains routines used for walking the parser tree for ** an SQL statement. */ /* #include <stdlib.h> */ /* #include <string.h> */ /* ** Walk an expression tree. Invoke the callback once for each node ** of the expression, while descending. (In other words, the callback | > | 82495 82496 82497 82498 82499 82500 82501 82502 82503 82504 82505 82506 82507 82508 82509 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains routines used for walking the parser tree for ** an SQL statement. */ /* #include "sqliteInt.h" */ /* #include <stdlib.h> */ /* #include <string.h> */ /* ** Walk an expression tree. Invoke the callback once for each node ** of the expression, while descending. (In other words, the callback |
︙ | ︙ | |||
82507 82508 82509 82510 82511 82512 82513 82514 82515 82516 82517 82518 82519 82520 | ** ************************************************************************* ** ** This file contains routines used for walking the parser tree and ** resolve all identifiers by associating them with a particular ** table and column. */ /* #include <stdlib.h> */ /* #include <string.h> */ /* ** Walk the expression tree pExpr and increase the aggregate function ** depth (the Expr.op2 field) by N on every TK_AGG_FUNCTION node. ** This needs to occur when copying a TK_AGG_FUNCTION node from an | > | 82654 82655 82656 82657 82658 82659 82660 82661 82662 82663 82664 82665 82666 82667 82668 | ** ************************************************************************* ** ** This file contains routines used for walking the parser tree and ** resolve all identifiers by associating them with a particular ** table and column. */ /* #include "sqliteInt.h" */ /* #include <stdlib.h> */ /* #include <string.h> */ /* ** Walk the expression tree pExpr and increase the aggregate function ** depth (the Expr.op2 field) by N on every TK_AGG_FUNCTION node. ** This needs to occur when copying a TK_AGG_FUNCTION node from an |
︙ | ︙ | |||
84019 84020 84021 84022 84023 84024 84025 84026 84027 84028 84029 84030 84031 84032 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. */ /* ** Return the 'affinity' of the expression pExpr if any. ** ** If pExpr is a column, a reference to a column via an 'AS' alias, ** or a sub-select with a column as the return value, then the ** affinity of that column is returned. Otherwise, 0x00 is returned, | > | 84167 84168 84169 84170 84171 84172 84173 84174 84175 84176 84177 84178 84179 84180 84181 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. */ /* #include "sqliteInt.h" */ /* ** Return the 'affinity' of the expression pExpr if any. ** ** If pExpr is a column, a reference to a column via an 'AS' alias, ** or a sub-select with a column as the return value, then the ** affinity of that column is returned. Otherwise, 0x00 is returned, |
︙ | ︙ | |||
88181 88182 88183 88184 88185 88186 88187 88188 88189 88190 88191 88192 88193 88194 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that used to generate VDBE code ** that implements the ALTER TABLE command. */ /* ** The code in this file only exists if we are not omitting the ** ALTER TABLE logic from the build. */ #ifndef SQLITE_OMIT_ALTERTABLE | > | 88330 88331 88332 88333 88334 88335 88336 88337 88338 88339 88340 88341 88342 88343 88344 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that used to generate VDBE code ** that implements the ALTER TABLE command. */ /* #include "sqliteInt.h" */ /* ** The code in this file only exists if we are not omitting the ** ALTER TABLE logic from the build. */ #ifndef SQLITE_OMIT_ALTERTABLE |
︙ | ︙ | |||
89143 89144 89145 89146 89147 89148 89149 89150 89151 89152 89153 89154 89155 89156 | ** column contains the actual value of the left-most column instead ** of a blob encoding of the complete index key as is found in ** sqlite_stat4.sample. The nEq, nLt, and nDLt entries of sqlite_stat3 ** all contain just a single integer which is the same as the first ** integer in the equivalent columns in sqlite_stat4. */ #ifndef SQLITE_OMIT_ANALYZE #if defined(SQLITE_ENABLE_STAT4) # define IsStat4 1 # define IsStat3 0 #elif defined(SQLITE_ENABLE_STAT3) # define IsStat4 0 # define IsStat3 1 | > | 89293 89294 89295 89296 89297 89298 89299 89300 89301 89302 89303 89304 89305 89306 89307 | ** column contains the actual value of the left-most column instead ** of a blob encoding of the complete index key as is found in ** sqlite_stat4.sample. The nEq, nLt, and nDLt entries of sqlite_stat3 ** all contain just a single integer which is the same as the first ** integer in the equivalent columns in sqlite_stat4. */ #ifndef SQLITE_OMIT_ANALYZE /* #include "sqliteInt.h" */ #if defined(SQLITE_ENABLE_STAT4) # define IsStat4 1 # define IsStat3 0 #elif defined(SQLITE_ENABLE_STAT3) # define IsStat4 0 # define IsStat3 1 |
︙ | ︙ | |||
90908 90909 90910 90911 90912 90913 90914 90915 90916 90917 90918 90919 90920 90921 | ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains code used to implement the ATTACH and DETACH commands. */ #ifndef SQLITE_OMIT_ATTACH /* ** Resolve an expression that was part of an ATTACH or DETACH statement. This ** is slightly different from resolving a normal SQL expression, because simple ** identifiers are treated as strings, not possible column names or aliases. ** | > | 91059 91060 91061 91062 91063 91064 91065 91066 91067 91068 91069 91070 91071 91072 91073 | ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains code used to implement the ATTACH and DETACH commands. */ /* #include "sqliteInt.h" */ #ifndef SQLITE_OMIT_ATTACH /* ** Resolve an expression that was part of an ATTACH or DETACH statement. This ** is slightly different from resolving a normal SQL expression, because simple ** identifiers are treated as strings, not possible column names or aliases. ** |
︙ | ︙ | |||
91497 91498 91499 91500 91501 91502 91503 91504 91505 91506 91507 91508 91509 91510 | ** ************************************************************************* ** This file contains code used to implement the sqlite3_set_authorizer() ** API. This facility is an optional feature of the library. Embedded ** systems that do not need this facility may omit it by recompiling ** the library with -DSQLITE_OMIT_AUTHORIZATION=1 */ /* ** All of the code in this file may be omitted by defining a single ** macro. */ #ifndef SQLITE_OMIT_AUTHORIZATION | > | 91649 91650 91651 91652 91653 91654 91655 91656 91657 91658 91659 91660 91661 91662 91663 | ** ************************************************************************* ** This file contains code used to implement the sqlite3_set_authorizer() ** API. This facility is an optional feature of the library. Embedded ** systems that do not need this facility may omit it by recompiling ** the library with -DSQLITE_OMIT_AUTHORIZATION=1 */ /* #include "sqliteInt.h" */ /* ** All of the code in this file may be omitted by defining a single ** macro. */ #ifndef SQLITE_OMIT_AUTHORIZATION |
︙ | ︙ | |||
91767 91768 91769 91770 91771 91772 91773 91774 91775 91776 91777 91778 91779 91780 | ** CREATE INDEX ** DROP INDEX ** creating ID lists ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK */ /* ** This routine is called when a new SQL statement is beginning to ** be parsed. Initialize the pParse structure as needed. */ SQLITE_PRIVATE void sqlite3BeginParse(Parse *pParse, int explainFlag){ pParse->explain = (u8)explainFlag; | > | 91920 91921 91922 91923 91924 91925 91926 91927 91928 91929 91930 91931 91932 91933 91934 | ** CREATE INDEX ** DROP INDEX ** creating ID lists ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK */ /* #include "sqliteInt.h" */ /* ** This routine is called when a new SQL statement is beginning to ** be parsed. Initialize the pParse structure as needed. */ SQLITE_PRIVATE void sqlite3BeginParse(Parse *pParse, int explainFlag){ pParse->explain = (u8)explainFlag; |
︙ | ︙ | |||
96087 96088 96089 96090 96091 96092 96093 96094 96095 96096 96097 96098 96099 96100 | ** ************************************************************************* ** ** This file contains functions used to access the internal hash tables ** of user defined functions and collation sequences. */ /* ** Invoke the 'collation needed' callback to request a collation sequence ** in the encoding enc of name zName, length nName. */ static void callCollNeeded(sqlite3 *db, int enc, const char *zName){ assert( !db->xCollNeeded || !db->xCollNeeded16 ); | > | 96241 96242 96243 96244 96245 96246 96247 96248 96249 96250 96251 96252 96253 96254 96255 | ** ************************************************************************* ** ** This file contains functions used to access the internal hash tables ** of user defined functions and collation sequences. */ /* #include "sqliteInt.h" */ /* ** Invoke the 'collation needed' callback to request a collation sequence ** in the encoding enc of name zName, length nName. */ static void callCollNeeded(sqlite3 *db, int enc, const char *zName){ assert( !db->xCollNeeded || !db->xCollNeeded16 ); |
︙ | ︙ | |||
96564 96565 96566 96567 96568 96569 96570 96571 96572 96573 96574 96575 96576 96577 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** in order to generate code for DELETE FROM statements. */ /* ** While a SrcList can in general represent multiple tables and subqueries ** (as in the FROM clause of a SELECT statement) in this case it contains ** the name of a single table, as one might find in an INSERT, DELETE, ** or UPDATE statement. Look up that table in the symbol table and ** return a pointer. Set an error message and return NULL if the table | > | 96719 96720 96721 96722 96723 96724 96725 96726 96727 96728 96729 96730 96731 96732 96733 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** in order to generate code for DELETE FROM statements. */ /* #include "sqliteInt.h" */ /* ** While a SrcList can in general represent multiple tables and subqueries ** (as in the FROM clause of a SELECT statement) in this case it contains ** the name of a single table, as one might find in an INSERT, DELETE, ** or UPDATE statement. Look up that table in the symbol table and ** return a pointer. Set an error message and return NULL if the table |
︙ | ︙ | |||
97406 97407 97408 97409 97410 97411 97412 97413 97414 97415 97416 97417 97418 97419 97420 97421 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains the C-language implementations for many of the SQL ** functions of SQLite. (Some function, and in particular the date and ** time functions, are implemented separately.) */ /* #include <stdlib.h> */ /* #include <assert.h> */ /* ** Return the collating function associated with a function. */ static CollSeq *sqlite3GetFuncCollSeq(sqlite3_context *context){ VdbeOp *pOp; assert( context->pVdbe!=0 ); | > > | 97562 97563 97564 97565 97566 97567 97568 97569 97570 97571 97572 97573 97574 97575 97576 97577 97578 97579 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains the C-language implementations for many of the SQL ** functions of SQLite. (Some function, and in particular the date and ** time functions, are implemented separately.) */ /* #include "sqliteInt.h" */ /* #include <stdlib.h> */ /* #include <assert.h> */ /* #include "vdbeInt.h" */ /* ** Return the collating function associated with a function. */ static CollSeq *sqlite3GetFuncCollSeq(sqlite3_context *context){ VdbeOp *pOp; assert( context->pVdbe!=0 ); |
︙ | ︙ | |||
98513 98514 98515 98516 98517 98518 98519 | */ static void zeroblobFunc( sqlite3_context *context, int argc, sqlite3_value **argv ){ i64 n; | | | | | | < < | 98671 98672 98673 98674 98675 98676 98677 98678 98679 98680 98681 98682 98683 98684 98685 98686 98687 98688 98689 98690 98691 98692 | */ static void zeroblobFunc( sqlite3_context *context, int argc, sqlite3_value **argv ){ i64 n; int rc; assert( argc==1 ); UNUSED_PARAMETER(argc); n = sqlite3_value_int64(argv[0]); if( n<0 ) n = 0; rc = sqlite3_result_zeroblob64(context, n); /* IMP: R-00293-64994 */ if( rc ){ sqlite3_result_error_code(context, rc); } } /* ** The replace() function. Three arguments are all strings: call ** them A, B, and C. The result is also a string which is derived ** from A by replacing every occurrence of B with C. The match |
︙ | ︙ | |||
99203 99204 99205 99206 99207 99208 99209 99210 99211 99212 99213 99214 99215 99216 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains code used by the compiler to add foreign key ** support to compiled SQL statements. */ #ifndef SQLITE_OMIT_FOREIGN_KEY #ifndef SQLITE_OMIT_TRIGGER /* ** Deferred and Immediate FKs ** -------------------------- | > | 99359 99360 99361 99362 99363 99364 99365 99366 99367 99368 99369 99370 99371 99372 99373 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains code used by the compiler to add foreign key ** support to compiled SQL statements. */ /* #include "sqliteInt.h" */ #ifndef SQLITE_OMIT_FOREIGN_KEY #ifndef SQLITE_OMIT_TRIGGER /* ** Deferred and Immediate FKs ** -------------------------- |
︙ | ︙ | |||
100607 100608 100609 100610 100611 100612 100613 100614 100615 100616 100617 100618 100619 100620 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle INSERT statements in SQLite. */ /* ** Generate code that will ** ** (1) acquire a lock for table pTab then ** (2) open pTab as cursor iCur. ** | > | 100764 100765 100766 100767 100768 100769 100770 100771 100772 100773 100774 100775 100776 100777 100778 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle INSERT statements in SQLite. */ /* #include "sqliteInt.h" */ /* ** Generate code that will ** ** (1) acquire a lock for table pTab then ** (2) open pTab as cursor iCur. ** |
︙ | ︙ | |||
102590 102591 102592 102593 102594 102595 102596 | sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0); sqlite3VdbeAddOp2(v, OP_Close, iDest, 0); }else{ sqlite3TableLock(pParse, iDbDest, pDest->tnum, 1, pDest->zName); sqlite3TableLock(pParse, iDbSrc, pSrc->tnum, 0, pSrc->zName); } for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){ | | | 102748 102749 102750 102751 102752 102753 102754 102755 102756 102757 102758 102759 102760 102761 102762 | sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0); sqlite3VdbeAddOp2(v, OP_Close, iDest, 0); }else{ sqlite3TableLock(pParse, iDbDest, pDest->tnum, 1, pDest->zName); sqlite3TableLock(pParse, iDbSrc, pSrc->tnum, 0, pSrc->zName); } for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){ u8 idxInsFlags = 0; for(pSrcIdx=pSrc->pIndex; ALWAYS(pSrcIdx); pSrcIdx=pSrcIdx->pNext){ if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break; } assert( pSrcIdx ); sqlite3VdbeAddOp3(v, OP_OpenRead, iSrc, pSrcIdx->tnum, iDbSrc); sqlite3VdbeSetP4KeyInfo(pParse, pSrcIdx); VdbeComment((v, "%s", pSrcIdx->zName)); |
︙ | ︙ | |||
102625 102626 102627 102628 102629 102630 102631 | ** sorted order. */ for(i=0; i<pSrcIdx->nColumn; i++){ char *zColl = pSrcIdx->azColl[i]; assert( zColl!=0 ); if( sqlite3_stricmp("BINARY", zColl) ) break; } if( i==pSrcIdx->nColumn ){ | | > > > | | 102783 102784 102785 102786 102787 102788 102789 102790 102791 102792 102793 102794 102795 102796 102797 102798 102799 102800 102801 102802 102803 102804 102805 | ** sorted order. */ for(i=0; i<pSrcIdx->nColumn; i++){ char *zColl = pSrcIdx->azColl[i]; assert( zColl!=0 ); if( sqlite3_stricmp("BINARY", zColl) ) break; } if( i==pSrcIdx->nColumn ){ idxInsFlags = OPFLAG_USESEEKRESULT; sqlite3VdbeAddOp3(v, OP_Last, iDest, 0, -1); } } if( !HasRowid(pSrc) && pDestIdx->idxType==2 ){ idxInsFlags |= OPFLAG_NCHANGE; } sqlite3VdbeAddOp3(v, OP_IdxInsert, iDest, regData, 1); sqlite3VdbeChangeP5(v, idxInsFlags); sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1); VdbeCoverage(v); sqlite3VdbeJumpHere(v, addr1); sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0); sqlite3VdbeAddOp2(v, OP_Close, iDest, 0); } if( emptySrcTest ) sqlite3VdbeJumpHere(v, emptySrcTest); sqlite3ReleaseTempReg(pParse, regRowid); |
︙ | ︙ | |||
102669 102670 102671 102672 102673 102674 102675 102676 102677 102678 102679 102680 102681 102682 | ************************************************************************* ** 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. */ /* ** Execute SQL code. Return one of the SQLITE_ success/failure ** codes. Also write an error message into memory obtained from ** malloc() and make *pzErrMsg point to that message. ** ** If the SQL is a query, then for each row in the query result | > | 102830 102831 102832 102833 102834 102835 102836 102837 102838 102839 102840 102841 102842 102843 102844 | ************************************************************************* ** 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. */ /* #include "sqliteInt.h" */ /* ** Execute SQL code. Return one of the SQLITE_ success/failure ** codes. Also write an error message into memory obtained from ** malloc() and make *pzErrMsg point to that message. ** ** If the SQL is a query, then for each row in the query result |
︙ | ︙ | |||
102837 102838 102839 102840 102841 102842 102843 102844 102845 102846 102847 102848 102849 102850 | ** shared libraries that want to be imported as extensions into ** an SQLite instance. Shared libraries that intend to be loaded ** as extensions by SQLite should #include this file instead of ** sqlite3.h. */ #ifndef _SQLITE3EXT_H_ #define _SQLITE3EXT_H_ typedef struct sqlite3_api_routines sqlite3_api_routines; /* ** The following structure holds pointers to all of the SQLite API ** routines. ** | > | 102999 103000 103001 103002 103003 103004 103005 103006 103007 103008 103009 103010 103011 103012 103013 | ** shared libraries that want to be imported as extensions into ** an SQLite instance. Shared libraries that intend to be loaded ** as extensions by SQLite should #include this file instead of ** sqlite3.h. */ #ifndef _SQLITE3EXT_H_ #define _SQLITE3EXT_H_ /* #include "sqlite3.h" */ typedef struct sqlite3_api_routines sqlite3_api_routines; /* ** The following structure holds pointers to all of the SQLite API ** routines. ** |
︙ | ︙ | |||
103089 103090 103091 103092 103093 103094 103095 103096 103097 103098 103099 103100 103101 103102 | void(*)(void*)); void (*result_text64)(sqlite3_context*,const char*,sqlite3_uint64, void(*)(void*), unsigned char); int (*strglob)(const char*,const char*); /* Version 3.8.11 and later */ sqlite3_value *(*value_dup)(const sqlite3_value*); void (*value_free)(sqlite3_value*); }; /* ** The following macros redefine the API routines so that they are ** redirected through the global sqlite3_api structure. ** ** This header file is also used by the loadext.c source file | > > | 103252 103253 103254 103255 103256 103257 103258 103259 103260 103261 103262 103263 103264 103265 103266 103267 | void(*)(void*)); void (*result_text64)(sqlite3_context*,const char*,sqlite3_uint64, void(*)(void*), unsigned char); int (*strglob)(const char*,const char*); /* Version 3.8.11 and later */ sqlite3_value *(*value_dup)(const sqlite3_value*); void (*value_free)(sqlite3_value*); int (*result_zeroblob64)(sqlite3_context*,sqlite3_uint64); int (*bind_zeroblob64)(sqlite3_stmt*, int, sqlite3_uint64); }; /* ** The following macros redefine the API routines so that they are ** redirected through the global sqlite3_api structure. ** ** This header file is also used by the loadext.c source file |
︙ | ︙ | |||
103322 103323 103324 103325 103326 103327 103328 103329 103330 103331 103332 103333 103334 103335 | #define sqlite3_reset_auto_extension sqlite3_api->reset_auto_extension #define sqlite3_result_blob64 sqlite3_api->result_blob64 #define sqlite3_result_text64 sqlite3_api->result_text64 #define sqlite3_strglob sqlite3_api->strglob /* Version 3.8.11 and later */ #define sqlite3_value_dup sqlite3_api->value_dup #define sqlite3_value_free sqlite3_api->value_free #endif /* SQLITE_CORE */ #ifndef SQLITE_CORE /* This case when the file really is being compiled as a loadable ** extension */ # define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api=0; # define SQLITE_EXTENSION_INIT2(v) sqlite3_api=v; | > > | 103487 103488 103489 103490 103491 103492 103493 103494 103495 103496 103497 103498 103499 103500 103501 103502 | #define sqlite3_reset_auto_extension sqlite3_api->reset_auto_extension #define sqlite3_result_blob64 sqlite3_api->result_blob64 #define sqlite3_result_text64 sqlite3_api->result_text64 #define sqlite3_strglob sqlite3_api->strglob /* Version 3.8.11 and later */ #define sqlite3_value_dup sqlite3_api->value_dup #define sqlite3_value_free sqlite3_api->value_free #define sqlite3_result_zeroblob64 sqlite3_api->result_zeroblob64 #define sqlite3_bind_zeroblob64 sqlite3_api->bind_zeroblob64 #endif /* SQLITE_CORE */ #ifndef SQLITE_CORE /* This case when the file really is being compiled as a loadable ** extension */ # define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api=0; # define SQLITE_EXTENSION_INIT2(v) sqlite3_api=v; |
︙ | ︙ | |||
103343 103344 103345 103346 103347 103348 103349 103350 103351 103352 103353 103354 103355 103356 | # define SQLITE_EXTENSION_INIT3 /*no-op*/ #endif #endif /* _SQLITE3EXT_H_ */ /************** End of sqlite3ext.h ******************************************/ /************** Continuing where we left off in loadext.c ********************/ /* #include <string.h> */ #ifndef SQLITE_OMIT_LOAD_EXTENSION /* ** Some API routines are omitted when various features are ** excluded from a build of SQLite. Substitute a NULL pointer | > | 103510 103511 103512 103513 103514 103515 103516 103517 103518 103519 103520 103521 103522 103523 103524 | # define SQLITE_EXTENSION_INIT3 /*no-op*/ #endif #endif /* _SQLITE3EXT_H_ */ /************** End of sqlite3ext.h ******************************************/ /************** Continuing where we left off in loadext.c ********************/ /* #include "sqliteInt.h" */ /* #include <string.h> */ #ifndef SQLITE_OMIT_LOAD_EXTENSION /* ** Some API routines are omitted when various features are ** excluded from a build of SQLite. Substitute a NULL pointer |
︙ | ︙ | |||
103730 103731 103732 103733 103734 103735 103736 | sqlite3_realloc64, sqlite3_reset_auto_extension, sqlite3_result_blob64, sqlite3_result_text64, sqlite3_strglob, /* Version 3.8.11 and later */ (sqlite3_value*(*)(const sqlite3_value*))sqlite3_value_dup, | | > > | 103898 103899 103900 103901 103902 103903 103904 103905 103906 103907 103908 103909 103910 103911 103912 103913 103914 | sqlite3_realloc64, sqlite3_reset_auto_extension, sqlite3_result_blob64, sqlite3_result_text64, sqlite3_strglob, /* Version 3.8.11 and later */ (sqlite3_value*(*)(const sqlite3_value*))sqlite3_value_dup, sqlite3_value_free, sqlite3_result_zeroblob64, sqlite3_bind_zeroblob64 }; /* ** Attempt to load an SQLite extension library contained in the file ** zFile. The entry point is zProc. zProc may be 0 in which case a ** default entry point name (sqlite3_extension_init) is used. Use ** of the default name is recommended. |
︙ | ︙ | |||
104112 104113 104114 104115 104116 104117 104118 104119 104120 104121 104122 104123 104124 104125 | ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains code used to implement the PRAGMA command. */ #if !defined(SQLITE_ENABLE_LOCKING_STYLE) # if defined(__APPLE__) # define SQLITE_ENABLE_LOCKING_STYLE 1 # else # define SQLITE_ENABLE_LOCKING_STYLE 0 # endif | > | 104282 104283 104284 104285 104286 104287 104288 104289 104290 104291 104292 104293 104294 104295 104296 | ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains code used to implement the PRAGMA command. */ /* #include "sqliteInt.h" */ #if !defined(SQLITE_ENABLE_LOCKING_STYLE) # if defined(__APPLE__) # define SQLITE_ENABLE_LOCKING_STYLE 1 # else # define SQLITE_ENABLE_LOCKING_STYLE 0 # endif |
︙ | ︙ | |||
104218 104219 104220 104221 104222 104223 104224 | { /* zName: */ "busy_timeout", /* ePragTyp: */ PragTyp_BUSY_TIMEOUT, /* ePragFlag: */ 0, /* iArg: */ 0 }, #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) { /* zName: */ "cache_size", /* ePragTyp: */ PragTyp_CACHE_SIZE, | | | 104389 104390 104391 104392 104393 104394 104395 104396 104397 104398 104399 104400 104401 104402 104403 | { /* zName: */ "busy_timeout", /* ePragTyp: */ PragTyp_BUSY_TIMEOUT, /* ePragFlag: */ 0, /* iArg: */ 0 }, #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) { /* zName: */ "cache_size", /* ePragTyp: */ PragTyp_CACHE_SIZE, /* ePragFlag: */ 0, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) { /* zName: */ "cache_spill", /* ePragTyp: */ PragTyp_FLAG, /* ePragFlag: */ 0, /* iArg: */ SQLITE_CacheSpill }, |
︙ | ︙ | |||
105288 105289 105290 105291 105292 105293 105294 105295 105296 105297 105298 105299 105300 105301 105302 105303 105304 105305 105306 | ** number of pages in the cache. If N is negative, then the ** number of pages is adjusted so that the cache uses -N kibibytes ** of memory. */ case PragTyp_CACHE_SIZE: { assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); if( !zRight ){ returnSingleInt(pParse, "cache_size", pDb->pSchema->cache_size); }else{ int size = sqlite3Atoi(zRight); pDb->pSchema->cache_size = size; sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size); } break; } /* ** PRAGMA [database.]mmap_size(N) ** | > > | 105459 105460 105461 105462 105463 105464 105465 105466 105467 105468 105469 105470 105471 105472 105473 105474 105475 105476 105477 105478 105479 | ** number of pages in the cache. If N is negative, then the ** number of pages is adjusted so that the cache uses -N kibibytes ** of memory. */ case PragTyp_CACHE_SIZE: { assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); if( !zRight ){ if( sqlite3ReadSchema(pParse) ) goto pragma_out; returnSingleInt(pParse, "cache_size", pDb->pSchema->cache_size); }else{ int size = sqlite3Atoi(zRight); pDb->pSchema->cache_size = size; sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size); if( sqlite3ReadSchema(pParse) ) goto pragma_out; } break; } /* ** PRAGMA [database.]mmap_size(N) ** |
︙ | ︙ | |||
106563 106564 106565 106566 106567 106568 106569 106570 106571 106572 106573 106574 106575 106576 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains the implementation of the sqlite3_prepare() ** interface, and routines that contribute to loading the database schema ** from disk. */ /* ** Fill the InitData structure with an error message that indicates ** that the database is corrupt. */ static void corruptSchema( InitData *pData, /* Initialization context */ | > | 106736 106737 106738 106739 106740 106741 106742 106743 106744 106745 106746 106747 106748 106749 106750 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains the implementation of the sqlite3_prepare() ** interface, and routines that contribute to loading the database schema ** from disk. */ /* #include "sqliteInt.h" */ /* ** Fill the InitData structure with an error message that indicates ** that the database is corrupt. */ static void corruptSchema( InitData *pData, /* Initialization context */ |
︙ | ︙ | |||
107457 107458 107459 107460 107461 107462 107463 107464 107465 107466 107467 107468 107469 107470 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. */ /* ** Trace output macros */ #if SELECTTRACE_ENABLED /***/ int sqlite3SelectTrace = 0; # define SELECTTRACE(K,P,S,X) \ | > | 107631 107632 107633 107634 107635 107636 107637 107638 107639 107640 107641 107642 107643 107644 107645 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. */ /* #include "sqliteInt.h" */ /* ** Trace output macros */ #if SELECTTRACE_ENABLED /***/ int sqlite3SelectTrace = 0; # define SELECTTRACE(K,P,S,X) \ |
︙ | ︙ | |||
108526 108527 108528 108529 108530 108531 108532 | pInfo->aColl[i-iStart] = pColl; pInfo->aSortOrder[i-iStart] = pItem->sortOrder; } } return pInfo; } | < < | 108701 108702 108703 108704 108705 108706 108707 108708 108709 108710 108711 108712 108713 108714 108715 108716 108717 108718 108719 108720 108721 108722 108723 108724 108725 108726 108727 | pInfo->aColl[i-iStart] = pColl; pInfo->aSortOrder[i-iStart] = pItem->sortOrder; } } return pInfo; } /* ** Name of the connection operator, used for error messages. */ static const char *selectOpName(int id){ char *z; switch( id ){ case TK_ALL: z = "UNION ALL"; break; case TK_INTERSECT: z = "INTERSECT"; break; case TK_EXCEPT: z = "EXCEPT"; break; default: z = "UNION"; break; } return z; } #ifndef SQLITE_OMIT_EXPLAIN /* ** Unless an "EXPLAIN QUERY PLAN" command is being processed, this function ** is a no-op. Otherwise, it adds a single row of output to the EQP result, ** where the caption is of the form: ** |
︙ | ︙ | |||
109543 109544 109545 109546 109547 109548 109549 | /* Forward references */ static int multiSelectOrderBy( Parse *pParse, /* Parsing context */ Select *p, /* The right-most of SELECTs to be coded */ SelectDest *pDest /* What to do with query results */ ); | < < < < < < < < < < < < < | 109716 109717 109718 109719 109720 109721 109722 109723 109724 109725 109726 109727 109728 109729 | /* Forward references */ static int multiSelectOrderBy( Parse *pParse, /* Parsing context */ Select *p, /* The right-most of SELECTs to be coded */ SelectDest *pDest /* What to do with query results */ ); /* ** Handle the special case of a compound-select that originates from a ** VALUES clause. By handling this as a special case, we avoid deep ** recursion, and thus do not need to enforce the SQLITE_LIMIT_COMPOUND_SELECT ** on a VALUES clause. ** ** Because the Select object originates from a VALUES clause: |
︙ | ︙ | |||
109981 109982 109983 109984 109985 109986 109987 109988 109989 109990 109991 109992 109993 109994 | multi_select_end: pDest->iSdst = dest.iSdst; pDest->nSdst = dest.nSdst; sqlite3SelectDelete(db, pDelete); return rc; } #endif /* SQLITE_OMIT_COMPOUND_SELECT */ /* ** Code an output subroutine for a coroutine implementation of a ** SELECT statment. ** ** The data to be output is contained in pIn->iSdst. There are ** pIn->nSdst columns to be output. pDest is where the output should | > > > > > > > > > > > > > | 110141 110142 110143 110144 110145 110146 110147 110148 110149 110150 110151 110152 110153 110154 110155 110156 110157 110158 110159 110160 110161 110162 110163 110164 110165 110166 110167 | multi_select_end: pDest->iSdst = dest.iSdst; pDest->nSdst = dest.nSdst; sqlite3SelectDelete(db, pDelete); return rc; } #endif /* SQLITE_OMIT_COMPOUND_SELECT */ /* ** Error message for when two or more terms of a compound select have different ** size result sets. */ SQLITE_PRIVATE void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p){ if( p->selFlags & SF_Values ){ sqlite3ErrorMsg(pParse, "all VALUES must have the same number of terms"); }else{ sqlite3ErrorMsg(pParse, "SELECTs to the left and right of %s" " do not have the same number of result columns", selectOpName(p->op)); } } /* ** Code an output subroutine for a coroutine implementation of a ** SELECT statment. ** ** The data to be output is contained in pIn->iSdst. There are ** pIn->nSdst columns to be output. pDest is where the output should |
︙ | ︙ | |||
113075 113076 113077 113078 113079 113080 113081 113082 113083 113084 113085 113086 113087 113088 | ** This file contains the sqlite3_get_table() and sqlite3_free_table() ** interface routines. These are just wrappers around the main ** interface routine of sqlite3_exec(). ** ** These routines are in a separate files so that they will not be linked ** if they are not used. */ /* #include <stdlib.h> */ /* #include <string.h> */ #ifndef SQLITE_OMIT_GET_TABLE /* ** This structure is used to pass data from sqlite3_get_table() through | > | 113248 113249 113250 113251 113252 113253 113254 113255 113256 113257 113258 113259 113260 113261 113262 | ** This file contains the sqlite3_get_table() and sqlite3_free_table() ** interface routines. These are just wrappers around the main ** interface routine of sqlite3_exec(). ** ** These routines are in a separate files so that they will not be linked ** if they are not used. */ /* #include "sqliteInt.h" */ /* #include <stdlib.h> */ /* #include <string.h> */ #ifndef SQLITE_OMIT_GET_TABLE /* ** This structure is used to pass data from sqlite3_get_table() through |
︙ | ︙ | |||
113271 113272 113273 113274 113275 113276 113277 113278 113279 113280 113281 113282 113283 113284 | ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains the implementation for TRIGGERs */ #ifndef SQLITE_OMIT_TRIGGER /* ** Delete a linked list of TriggerStep structures. */ SQLITE_PRIVATE void sqlite3DeleteTriggerStep(sqlite3 *db, TriggerStep *pTriggerStep){ while( pTriggerStep ){ | > | 113445 113446 113447 113448 113449 113450 113451 113452 113453 113454 113455 113456 113457 113458 113459 | ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains the implementation for TRIGGERs */ /* #include "sqliteInt.h" */ #ifndef SQLITE_OMIT_TRIGGER /* ** Delete a linked list of TriggerStep structures. */ SQLITE_PRIVATE void sqlite3DeleteTriggerStep(sqlite3 *db, TriggerStep *pTriggerStep){ while( pTriggerStep ){ |
︙ | ︙ | |||
114394 114395 114396 114397 114398 114399 114400 114401 114402 114403 114404 114405 114406 114407 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle UPDATE statements. */ #ifndef SQLITE_OMIT_VIRTUALTABLE /* Forward declaration */ static void updateVirtualTable( Parse *pParse, /* The parsing context */ SrcList *pSrc, /* The virtual table to be modified */ Table *pTab, /* The virtual table */ | > | 114569 114570 114571 114572 114573 114574 114575 114576 114577 114578 114579 114580 114581 114582 114583 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle UPDATE statements. */ /* #include "sqliteInt.h" */ #ifndef SQLITE_OMIT_VIRTUALTABLE /* Forward declaration */ static void updateVirtualTable( Parse *pParse, /* The parsing context */ SrcList *pSrc, /* The virtual table to be modified */ Table *pTab, /* The virtual table */ |
︙ | ︙ | |||
115170 115171 115172 115173 115174 115175 115176 115177 115178 115179 115180 115181 115182 115183 | ** ************************************************************************* ** This file contains code used to implement the VACUUM command. ** ** Most of the code in this file may be omitted by defining the ** SQLITE_OMIT_VACUUM macro. */ #if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH) /* ** Finalize a prepared statement. If there was an error, store the ** text of the error message in *pzErrMsg. Return the result code. */ static int vacuumFinalize(sqlite3 *db, sqlite3_stmt *pStmt, char **pzErrMsg){ | > > | 115346 115347 115348 115349 115350 115351 115352 115353 115354 115355 115356 115357 115358 115359 115360 115361 | ** ************************************************************************* ** This file contains code used to implement the VACUUM command. ** ** Most of the code in this file may be omitted by defining the ** SQLITE_OMIT_VACUUM macro. */ /* #include "sqliteInt.h" */ /* #include "vdbeInt.h" */ #if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH) /* ** Finalize a prepared statement. If there was an error, store the ** text of the error message in *pzErrMsg. Return the result code. */ static int vacuumFinalize(sqlite3 *db, sqlite3_stmt *pStmt, char **pzErrMsg){ |
︙ | ︙ | |||
115542 115543 115544 115545 115546 115547 115548 115549 115550 115551 115552 115553 115554 115555 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains code used to help implement virtual tables. */ #ifndef SQLITE_OMIT_VIRTUALTABLE /* ** Before a virtual table xCreate() or xConnect() method is invoked, the ** sqlite3.pVtabCtx member variable is set to point to an instance of ** this struct allocated on the stack. It is used by the implementation of ** the sqlite3_declare_vtab() and sqlite3_vtab_config() APIs, both of which ** are invoked only from within xCreate and xConnect methods. | > | 115720 115721 115722 115723 115724 115725 115726 115727 115728 115729 115730 115731 115732 115733 115734 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains code used to help implement virtual tables. */ #ifndef SQLITE_OMIT_VIRTUALTABLE /* #include "sqliteInt.h" */ /* ** Before a virtual table xCreate() or xConnect() method is invoked, the ** sqlite3.pVtabCtx member variable is set to point to an instance of ** this struct allocated on the stack. It is used by the implementation of ** the sqlite3_declare_vtab() and sqlite3_vtab_config() APIs, both of which ** are invoked only from within xCreate and xConnect methods. |
︙ | ︙ | |||
116700 116701 116702 116703 116704 116705 116706 116707 116708 116709 116710 116711 116712 116713 | ** the WHERE clause of SQL statements. ** ** This file was split off from where.c on 2015-06-06 in order to reduce the ** size of where.c and make it easier to edit. This file contains the routines ** that actually generate the bulk of the WHERE loop code. The original where.c ** file retains the code that does query planning and analysis. */ /************** Include whereInt.h in the middle of wherecode.c **************/ /************** Begin file whereInt.h ****************************************/ /* ** 2013-11-12 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: | > | 116879 116880 116881 116882 116883 116884 116885 116886 116887 116888 116889 116890 116891 116892 116893 | ** the WHERE clause of SQL statements. ** ** This file was split off from where.c on 2015-06-06 in order to reduce the ** size of where.c and make it easier to edit. This file contains the routines ** that actually generate the bulk of the WHERE loop code. The original where.c ** file retains the code that does query planning and analysis. */ /* #include "sqliteInt.h" */ /************** Include whereInt.h in the middle of wherecode.c **************/ /************** Begin file whereInt.h ****************************************/ /* ** 2013-11-12 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: |
︙ | ︙ | |||
118511 118512 118513 118514 118515 118516 118517 | int nPk = pPk->nKeyCol; int iPk; /* Read the PK into an array of temp registers. */ r = sqlite3GetTempRange(pParse, nPk); for(iPk=0; iPk<nPk; iPk++){ int iCol = pPk->aiColumn[iPk]; | > | > > > | 118691 118692 118693 118694 118695 118696 118697 118698 118699 118700 118701 118702 118703 118704 118705 118706 118707 118708 118709 | int nPk = pPk->nKeyCol; int iPk; /* Read the PK into an array of temp registers. */ r = sqlite3GetTempRange(pParse, nPk); for(iPk=0; iPk<nPk; iPk++){ int iCol = pPk->aiColumn[iPk]; int rx; rx = sqlite3ExprCodeGetColumn(pParse, pTab, iCol, iCur,r+iPk,0); if( rx!=r+iPk ){ sqlite3VdbeAddOp2(v, OP_SCopy, rx, r+iPk); } } /* Check if the temp table already contains this key. If so, ** the row has already been included in the result set and ** can be ignored (by jumping past the Gosub below). Otherwise, ** insert the key into the temp table and proceed with processing ** the row. |
︙ | ︙ | |||
118735 118736 118737 118738 118739 118740 118741 118742 118743 118744 118745 118746 118747 118748 | ** This module contains C code that generates VDBE code used to process ** the WHERE clause of SQL statements. ** ** This file was originally part of where.c but was split out to improve ** readability and editabiliity. This file contains utility routines for ** analyzing Expr objects in the WHERE clause. */ /* Forward declarations */ static void exprAnalyze(SrcList*, WhereClause*, int); /* ** Deallocate all memory associated with a WhereOrInfo object. */ | > > | 118919 118920 118921 118922 118923 118924 118925 118926 118927 118928 118929 118930 118931 118932 118933 118934 | ** This module contains C code that generates VDBE code used to process ** the WHERE clause of SQL statements. ** ** This file was originally part of where.c but was split out to improve ** readability and editabiliity. This file contains utility routines for ** analyzing Expr objects in the WHERE clause. */ /* #include "sqliteInt.h" */ /* #include "whereInt.h" */ /* Forward declarations */ static void exprAnalyze(SrcList*, WhereClause*, int); /* ** Deallocate all memory associated with a WhereOrInfo object. */ |
︙ | ︙ | |||
119985 119986 119987 119988 119989 119990 119991 119992 119993 119994 119995 119996 119997 119998 | ** This module contains C code that generates VDBE code used to process ** the WHERE clause of SQL statements. This module is responsible for ** generating the code that loops through a table looking for applicable ** rows. Indices are selected and used to speed the search when doing ** so is applicable. Because this module is responsible for selecting ** indices, you might also think of this module as the "query optimizer". */ /* Forward declaration of methods */ static int whereLoopResize(sqlite3*, WhereLoop*, int); /* Test variable that can be set to enable WHERE tracing */ #if defined(SQLITE_TEST) || defined(SQLITE_DEBUG) /***/ int sqlite3WhereTrace = 0; | > > | 120171 120172 120173 120174 120175 120176 120177 120178 120179 120180 120181 120182 120183 120184 120185 120186 | ** This module contains C code that generates VDBE code used to process ** the WHERE clause of SQL statements. This module is responsible for ** generating the code that loops through a table looking for applicable ** rows. Indices are selected and used to speed the search when doing ** so is applicable. Because this module is responsible for selecting ** indices, you might also think of this module as the "query optimizer". */ /* #include "sqliteInt.h" */ /* #include "whereInt.h" */ /* Forward declaration of methods */ static int whereLoopResize(sqlite3*, WhereLoop*, int); /* Test variable that can be set to enable WHERE tracing */ #if defined(SQLITE_TEST) || defined(SQLITE_DEBUG) /***/ int sqlite3WhereTrace = 0; |
︙ | ︙ | |||
124484 124485 124486 124487 124488 124489 124490 124491 124492 124493 124494 124495 124496 124497 | ** LALR(1) grammar but which are always false in the ** specific grammar used by SQLite. */ /* First off, code is included that follows the "include" declaration ** in the input grammar file. */ /* #include <stdio.h> */ /* ** Disable all error recovery processing in the parser push-down ** automaton. */ #define YYNOERRORRECOVERY 1 | > | 124672 124673 124674 124675 124676 124677 124678 124679 124680 124681 124682 124683 124684 124685 124686 | ** LALR(1) grammar but which are always false in the ** specific grammar used by SQLite. */ /* First off, code is included that follows the "include" declaration ** in the input grammar file. */ /* #include <stdio.h> */ /* #include "sqliteInt.h" */ /* ** Disable all error recovery processing in the parser push-down ** automaton. */ #define YYNOERRORRECOVERY 1 |
︙ | ︙ | |||
128069 128070 128071 128072 128073 128074 128075 128076 128077 128078 128079 128080 128081 128082 | ************************************************************************* ** An tokenizer for SQL ** ** This file contains C code that splits an SQL input string up into ** individual tokens and sends those tokens one-by-one over to the ** parser for analysis. */ /* #include <stdlib.h> */ /* ** The charMap() macro maps alphabetic characters into their ** lower-case ASCII equivalent. On ASCII machines, this is just ** an upper-to-lower case map. On EBCDIC machines we also need ** to adjust the encoding. Only alphabetic characters and underscores | > | 128258 128259 128260 128261 128262 128263 128264 128265 128266 128267 128268 128269 128270 128271 128272 | ************************************************************************* ** An tokenizer for SQL ** ** This file contains C code that splits an SQL input string up into ** individual tokens and sends those tokens one-by-one over to the ** parser for analysis. */ /* #include "sqliteInt.h" */ /* #include <stdlib.h> */ /* ** The charMap() macro maps alphabetic characters into their ** lower-case ASCII equivalent. On ASCII machines, this is just ** an upper-to-lower case map. On EBCDIC machines we also need ** to adjust the encoding. Only alphabetic characters and underscores |
︙ | ︙ | |||
128878 128879 128880 128881 128882 128883 128884 128885 128886 128887 128888 128889 128890 128891 | ** An tokenizer for SQL ** ** This file contains C code that implements the sqlite3_complete() API. ** This code used to be part of the tokenizer.c source file. But by ** separating it out, the code will be automatically omitted from ** static links that do not use it. */ #ifndef SQLITE_OMIT_COMPLETE /* ** This is defined in tokenize.c. We just have to import the definition. */ #ifndef SQLITE_AMALGAMATION #ifdef SQLITE_ASCII | > | 129068 129069 129070 129071 129072 129073 129074 129075 129076 129077 129078 129079 129080 129081 129082 | ** An tokenizer for SQL ** ** This file contains C code that implements the sqlite3_complete() API. ** This code used to be part of the tokenizer.c source file. But by ** separating it out, the code will be automatically omitted from ** static links that do not use it. */ /* #include "sqliteInt.h" */ #ifndef SQLITE_OMIT_COMPLETE /* ** This is defined in tokenize.c. We just have to import the definition. */ #ifndef SQLITE_AMALGAMATION #ifdef SQLITE_ASCII |
︙ | ︙ | |||
129168 129169 129170 129171 129172 129173 129174 129175 129176 129177 129178 129179 129180 129181 129182 129183 129184 129185 129186 129187 129188 129189 129190 129191 129192 129193 129194 129195 129196 129197 129198 129199 129200 | ** ************************************************************************* ** 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. */ #ifdef SQLITE_ENABLE_FTS3 /************** Include fts3.h in the middle of main.c ***********************/ /************** Begin file fts3.h ********************************************/ /* ** 2006 Oct 10 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ****************************************************************************** ** ** This header file is used by programs that want to link against the ** FTS3 library. All it does is declare the sqlite3Fts3Init() interface. */ #if 0 extern "C" { #endif /* __cplusplus */ SQLITE_PRIVATE int sqlite3Fts3Init(sqlite3 *db); | > > | 129359 129360 129361 129362 129363 129364 129365 129366 129367 129368 129369 129370 129371 129372 129373 129374 129375 129376 129377 129378 129379 129380 129381 129382 129383 129384 129385 129386 129387 129388 129389 129390 129391 129392 129393 | ** ************************************************************************* ** 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. */ /* #include "sqliteInt.h" */ #ifdef SQLITE_ENABLE_FTS3 /************** Include fts3.h in the middle of main.c ***********************/ /************** Begin file fts3.h ********************************************/ /* ** 2006 Oct 10 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ****************************************************************************** ** ** This header file is used by programs that want to link against the ** FTS3 library. All it does is declare the sqlite3Fts3Init() interface. */ /* #include "sqlite3.h" */ #if 0 extern "C" { #endif /* __cplusplus */ SQLITE_PRIVATE int sqlite3Fts3Init(sqlite3 *db); |
︙ | ︙ | |||
129219 129220 129221 129222 129223 129224 129225 129226 129227 129228 129229 129230 129231 129232 | ** May you share freely, never taking more than you give. ** ****************************************************************************** ** ** This header file is used by programs that want to link against the ** RTREE library. All it does is declare the sqlite3RtreeInit() interface. */ #if 0 extern "C" { #endif /* __cplusplus */ SQLITE_PRIVATE int sqlite3RtreeInit(sqlite3 *db); | > | 129412 129413 129414 129415 129416 129417 129418 129419 129420 129421 129422 129423 129424 129425 129426 | ** May you share freely, never taking more than you give. ** ****************************************************************************** ** ** This header file is used by programs that want to link against the ** RTREE library. All it does is declare the sqlite3RtreeInit() interface. */ /* #include "sqlite3.h" */ #if 0 extern "C" { #endif /* __cplusplus */ SQLITE_PRIVATE int sqlite3RtreeInit(sqlite3 *db); |
︙ | ︙ | |||
129251 129252 129253 129254 129255 129256 129257 129258 129259 129260 129261 129262 129263 129264 | ** May you share freely, never taking more than you give. ** ****************************************************************************** ** ** This header file is used by programs that want to link against the ** ICU extension. All it does is declare the sqlite3IcuInit() interface. */ #if 0 extern "C" { #endif /* __cplusplus */ SQLITE_PRIVATE int sqlite3IcuInit(sqlite3 *db); | > | 129445 129446 129447 129448 129449 129450 129451 129452 129453 129454 129455 129456 129457 129458 129459 | ** May you share freely, never taking more than you give. ** ****************************************************************************** ** ** This header file is used by programs that want to link against the ** ICU extension. All it does is declare the sqlite3IcuInit() interface. */ /* #include "sqlite3.h" */ #if 0 extern "C" { #endif /* __cplusplus */ SQLITE_PRIVATE int sqlite3IcuInit(sqlite3 *db); |
︙ | ︙ | |||
129883 129884 129885 129886 129887 129888 129889 129890 129891 129892 129893 129894 129895 129896 | ** The sz parameter is the number of bytes in each lookaside slot. ** The cnt parameter is the number of slots. If pStart is NULL the ** space for the lookaside memory is obtained from sqlite3_malloc(). ** If pStart is not NULL then it is sz*cnt bytes of memory to use for ** the lookaside memory. */ static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){ void *pStart; if( db->lookaside.nOut ){ return SQLITE_BUSY; } /* Free any existing lookaside buffer for this handle before ** allocating a new one so we don't have to have space for ** both at the same time. | > | 130078 130079 130080 130081 130082 130083 130084 130085 130086 130087 130088 130089 130090 130091 130092 | ** The sz parameter is the number of bytes in each lookaside slot. ** The cnt parameter is the number of slots. If pStart is NULL the ** space for the lookaside memory is obtained from sqlite3_malloc(). ** If pStart is not NULL then it is sz*cnt bytes of memory to use for ** the lookaside memory. */ static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){ #ifndef SQLITE_OMIT_LOOKASIDE void *pStart; if( db->lookaside.nOut ){ return SQLITE_BUSY; } /* Free any existing lookaside buffer for this handle before ** allocating a new one so we don't have to have space for ** both at the same time. |
︙ | ︙ | |||
129933 129934 129935 129936 129937 129938 129939 129940 129941 129942 129943 129944 129945 129946 | db->lookaside.bMalloced = pBuf==0 ?1:0; }else{ db->lookaside.pStart = db; db->lookaside.pEnd = db; db->lookaside.bEnabled = 0; db->lookaside.bMalloced = 0; } return SQLITE_OK; } /* ** Return the mutex associated with a database connection. */ SQLITE_API sqlite3_mutex *SQLITE_STDCALL sqlite3_db_mutex(sqlite3 *db){ | > | 130129 130130 130131 130132 130133 130134 130135 130136 130137 130138 130139 130140 130141 130142 130143 | db->lookaside.bMalloced = pBuf==0 ?1:0; }else{ db->lookaside.pStart = db; db->lookaside.pEnd = db; db->lookaside.bEnabled = 0; db->lookaside.bMalloced = 0; } #endif /* SQLITE_OMIT_LOOKASIDE */ return SQLITE_OK; } /* ** Return the mutex associated with a database connection. */ SQLITE_API sqlite3_mutex *SQLITE_STDCALL sqlite3_db_mutex(sqlite3 *db){ |
︙ | ︙ | |||
133043 133044 133045 133046 133047 133048 133049 133050 133051 133052 133053 133054 133055 133056 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** ** This file contains the implementation of the sqlite3_unlock_notify() ** API method and its associated functionality. */ /* Omit this entire file if SQLITE_ENABLE_UNLOCK_NOTIFY is not defined. */ #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY /* ** Public interfaces: ** | > > | 133240 133241 133242 133243 133244 133245 133246 133247 133248 133249 133250 133251 133252 133253 133254 133255 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** ** This file contains the implementation of the sqlite3_unlock_notify() ** API method and its associated functionality. */ /* #include "sqliteInt.h" */ /* #include "btreeInt.h" */ /* Omit this entire file if SQLITE_ENABLE_UNLOCK_NOTIFY is not defined. */ #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY /* ** Public interfaces: ** |
︙ | ︙ | |||
133686 133687 133688 133689 133690 133691 133692 133693 133694 133695 133696 133697 133698 133699 133700 133701 133702 | # define SQLITE_ENABLE_FTS3 #endif #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) /* If not building as part of the core, include sqlite3ext.h. */ #ifndef SQLITE_CORE SQLITE_EXTENSION_INIT3 #endif /************** Include fts3_tokenizer.h in the middle of fts3Int.h **********/ /************** Begin file fts3_tokenizer.h **********************************/ /* ** 2006 July 10 ** ** The author disclaims copyright to this source code. ** | > > | 133885 133886 133887 133888 133889 133890 133891 133892 133893 133894 133895 133896 133897 133898 133899 133900 133901 133902 133903 | # define SQLITE_ENABLE_FTS3 #endif #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) /* If not building as part of the core, include sqlite3ext.h. */ #ifndef SQLITE_CORE /* # include "sqlite3ext.h" */ SQLITE_EXTENSION_INIT3 #endif /* #include "sqlite3.h" */ /************** Include fts3_tokenizer.h in the middle of fts3Int.h **********/ /************** Begin file fts3_tokenizer.h **********************************/ /* ** 2006 July 10 ** ** The author disclaims copyright to this source code. ** |
︙ | ︙ | |||
133717 133718 133719 133720 133721 133722 133723 133724 133725 133726 133727 133728 133729 133730 | #ifndef _FTS3_TOKENIZER_H_ #define _FTS3_TOKENIZER_H_ /* TODO(shess) Only used for SQLITE_OK and SQLITE_DONE at this time. ** If tokenizers are to be allowed to call sqlite3_*() functions, then ** we will need a way to register the API consistently. */ /* ** Structures used by the tokenizer interface. When a new tokenizer ** implementation is registered, the caller provides a pointer to ** an sqlite3_tokenizer_module containing pointers to the callback ** functions that make up an implementation. ** | > | 133918 133919 133920 133921 133922 133923 133924 133925 133926 133927 133928 133929 133930 133931 133932 | #ifndef _FTS3_TOKENIZER_H_ #define _FTS3_TOKENIZER_H_ /* TODO(shess) Only used for SQLITE_OK and SQLITE_DONE at this time. ** If tokenizers are to be allowed to call sqlite3_*() functions, then ** we will need a way to register the API consistently. */ /* #include "sqlite3.h" */ /* ** Structures used by the tokenizer interface. When a new tokenizer ** implementation is registered, the caller provides a pointer to ** an sqlite3_tokenizer_module containing pointers to the callback ** functions that make up an implementation. ** |
︙ | ︙ | |||
134557 134558 134559 134560 134561 134562 134563 134564 134565 134566 134567 134568 134569 134570 134571 | /* #include <assert.h> */ /* #include <stdlib.h> */ /* #include <stddef.h> */ /* #include <stdio.h> */ /* #include <string.h> */ /* #include <stdarg.h> */ #ifndef SQLITE_CORE SQLITE_EXTENSION_INIT1 #endif static int fts3EvalNext(Fts3Cursor *pCsr); static int fts3EvalStart(Fts3Cursor *pCsr); static int fts3TermSegReaderCursor( Fts3Cursor *, const char *, int, int, Fts3MultiSegReader **); | > > | 134759 134760 134761 134762 134763 134764 134765 134766 134767 134768 134769 134770 134771 134772 134773 134774 134775 | /* #include <assert.h> */ /* #include <stdlib.h> */ /* #include <stddef.h> */ /* #include <stdio.h> */ /* #include <string.h> */ /* #include <stdarg.h> */ /* #include "fts3.h" */ #ifndef SQLITE_CORE /* # include "sqlite3ext.h" */ SQLITE_EXTENSION_INIT1 #endif static int fts3EvalNext(Fts3Cursor *pCsr); static int fts3EvalStart(Fts3Cursor *pCsr); static int fts3TermSegReaderCursor( Fts3Cursor *, const char *, int, int, Fts3MultiSegReader **); |
︙ | ︙ | |||
138484 138485 138486 138487 138488 138489 138490 | ** scanned in forward order, and the phrase consists of ** MAX_INCR_PHRASE_TOKENS or fewer tokens, none of which are are "^first" ** tokens or prefix tokens that cannot use a prefix-index. */ int bHaveIncr = 0; int bIncrOk = (bOptOk && pCsr->bDesc==pTab->bDescIdx && p->nToken<=MAX_INCR_PHRASE_TOKENS && p->nToken>0 | < | 138688 138689 138690 138691 138692 138693 138694 138695 138696 138697 138698 138699 138700 138701 | ** scanned in forward order, and the phrase consists of ** MAX_INCR_PHRASE_TOKENS or fewer tokens, none of which are are "^first" ** tokens or prefix tokens that cannot use a prefix-index. */ int bHaveIncr = 0; int bIncrOk = (bOptOk && pCsr->bDesc==pTab->bDescIdx && p->nToken<=MAX_INCR_PHRASE_TOKENS && p->nToken>0 #ifdef SQLITE_TEST && pTab->bNoIncrDoclist==0 #endif ); for(i=0; bIncrOk==1 && i<p->nToken; i++){ Fts3PhraseToken *pToken = &p->aToken[i]; if( pToken->bFirst || (pToken->pSegcsr!=0 && !pToken->pSegcsr->bLookup) ){ |
︙ | ︙ | |||
138604 138605 138606 138607 138608 138609 138610 138611 138612 138613 138614 138615 138616 138617 | assert( !p || (p>=aDoclist && p<=&aDoclist[nDoclist]) ); if( p==0 ){ p = aDoclist; p += sqlite3Fts3GetVarint(p, piDocid); }else{ fts3PoslistCopy(0, &p); if( p>=&aDoclist[nDoclist] ){ *pbEof = 1; }else{ sqlite3_int64 iVar; p += sqlite3Fts3GetVarint(p, &iVar); *piDocid += ((bDescIdx ? -1 : 1) * iVar); } | > | 138807 138808 138809 138810 138811 138812 138813 138814 138815 138816 138817 138818 138819 138820 138821 | assert( !p || (p>=aDoclist && p<=&aDoclist[nDoclist]) ); if( p==0 ){ p = aDoclist; p += sqlite3Fts3GetVarint(p, piDocid); }else{ fts3PoslistCopy(0, &p); while( p<&aDoclist[nDoclist] && *p==0 ) p++; if( p>=&aDoclist[nDoclist] ){ *pbEof = 1; }else{ sqlite3_int64 iVar; p += sqlite3Fts3GetVarint(p, &iVar); *piDocid += ((bDescIdx ? -1 : 1) * iVar); } |
︙ | ︙ | |||
140010 140011 140012 140013 140014 140015 140016 | iDocid = pExpr->iDocid; pIter = pPhrase->doclist.pList; if( iDocid!=pCsr->iPrevId || pExpr->bEof ){ int rc = SQLITE_OK; int bDescDoclist = pTab->bDescIdx; /* For DOCID_CMP macro */ int bOr = 0; | < > | 140214 140215 140216 140217 140218 140219 140220 140221 140222 140223 140224 140225 140226 140227 140228 140229 140230 140231 | iDocid = pExpr->iDocid; pIter = pPhrase->doclist.pList; if( iDocid!=pCsr->iPrevId || pExpr->bEof ){ int rc = SQLITE_OK; int bDescDoclist = pTab->bDescIdx; /* For DOCID_CMP macro */ int bOr = 0; u8 bTreeEof = 0; Fts3Expr *p; /* Used to iterate from pExpr to root */ Fts3Expr *pNear; /* Most senior NEAR ancestor (or pExpr) */ int bMatch; /* Check if this phrase descends from an OR expression node. If not, ** return NULL. Otherwise, the entry that corresponds to docid ** pCsr->iPrevId may lie earlier in the doclist buffer. Or, if the ** tree that the node is part of has been marked as EOF, but the node ** itself is not EOF, then it may point to an earlier entry. */ pNear = pExpr; |
︙ | ︙ | |||
140047 140048 140049 140050 140051 140052 140053 | if( bTreeEof ){ while( rc==SQLITE_OK && !pNear->bEof ){ fts3EvalNextRow(pCsr, pNear, &rc); } } if( rc!=SQLITE_OK ) return rc; | > > > > > > > > > > | | | | | | | | | | | | | | | | | | | | | | | > | > > > > | > | 140251 140252 140253 140254 140255 140256 140257 140258 140259 140260 140261 140262 140263 140264 140265 140266 140267 140268 140269 140270 140271 140272 140273 140274 140275 140276 140277 140278 140279 140280 140281 140282 140283 140284 140285 140286 140287 140288 140289 140290 140291 140292 140293 140294 140295 140296 140297 140298 140299 140300 140301 140302 140303 140304 140305 | if( bTreeEof ){ while( rc==SQLITE_OK && !pNear->bEof ){ fts3EvalNextRow(pCsr, pNear, &rc); } } if( rc!=SQLITE_OK ) return rc; bMatch = 1; for(p=pNear; p; p=p->pLeft){ u8 bEof = 0; Fts3Expr *pTest = p; Fts3Phrase *pPh; assert( pTest->eType==FTSQUERY_NEAR || pTest->eType==FTSQUERY_PHRASE ); if( pTest->eType==FTSQUERY_NEAR ) pTest = pTest->pRight; assert( pTest->eType==FTSQUERY_PHRASE ); pPh = pTest->pPhrase; pIter = pPh->pOrPoslist; iDocid = pPh->iOrDocid; if( pCsr->bDesc==bDescDoclist ){ bEof = !pPh->doclist.nAll || (pIter >= (pPh->doclist.aAll + pPh->doclist.nAll)); while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)<0 ) && bEof==0 ){ sqlite3Fts3DoclistNext( bDescDoclist, pPh->doclist.aAll, pPh->doclist.nAll, &pIter, &iDocid, &bEof ); } }else{ bEof = !pPh->doclist.nAll || (pIter && pIter<=pPh->doclist.aAll); while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)>0 ) && bEof==0 ){ int dummy; sqlite3Fts3DoclistPrev( bDescDoclist, pPh->doclist.aAll, pPh->doclist.nAll, &pIter, &iDocid, &dummy, &bEof ); } } pPh->pOrPoslist = pIter; pPh->iOrDocid = iDocid; if( bEof || iDocid!=pCsr->iPrevId ) bMatch = 0; } if( bMatch ){ pIter = pPhrase->pOrPoslist; }else{ pIter = 0; } } if( pIter==0 ) return SQLITE_OK; if( *pIter==0x01 ){ pIter++; pIter += fts3GetVarint32(pIter, &iThis); }else{ |
︙ | ︙ | |||
140159 140160 140161 140162 140163 140164 140165 140166 140167 140168 140169 140170 140171 140172 | ** 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. ** ****************************************************************************** ** */ #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) /* #include <string.h> */ /* #include <assert.h> */ typedef struct Fts3auxTable Fts3auxTable; typedef struct Fts3auxCursor Fts3auxCursor; | > | 140379 140380 140381 140382 140383 140384 140385 140386 140387 140388 140389 140390 140391 140392 140393 | ** 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. ** ****************************************************************************** ** */ /* #include "fts3Int.h" */ #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) /* #include <string.h> */ /* #include <assert.h> */ typedef struct Fts3auxTable Fts3auxTable; typedef struct Fts3auxCursor Fts3auxCursor; |
︙ | ︙ | |||
140715 140716 140717 140718 140719 140720 140721 140722 140723 140724 140725 140726 140727 140728 | ****************************************************************************** ** ** This module contains code that implements a parser for fts3 query strings ** (the right-hand argument to the MATCH operator). Because the supported ** syntax is relatively simple, the whole tokenizer/parser system is ** hand-coded. */ #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) /* ** By default, this module parses the legacy syntax that has been ** traditionally used by fts3. Or, if SQLITE_ENABLE_FTS3_PARENTHESIS ** is defined, then it uses the new syntax. The differences between ** the new and the old syntaxes are: | > | 140936 140937 140938 140939 140940 140941 140942 140943 140944 140945 140946 140947 140948 140949 140950 | ****************************************************************************** ** ** This module contains code that implements a parser for fts3 query strings ** (the right-hand argument to the MATCH operator). Because the supported ** syntax is relatively simple, the whole tokenizer/parser system is ** hand-coded. */ /* #include "fts3Int.h" */ #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) /* ** By default, this module parses the legacy syntax that has been ** traditionally used by fts3. Or, if SQLITE_ENABLE_FTS3_PARENTHESIS ** is defined, then it uses the new syntax. The differences between ** the new and the old syntaxes are: |
︙ | ︙ | |||
142008 142009 142010 142011 142012 142013 142014 142015 142016 142017 142018 142019 142020 142021 142022 142023 142024 142025 142026 142027 | ** ** * The FTS3 module is being built as an extension ** (in which case SQLITE_CORE is not defined), or ** ** * The FTS3 module is being built into the core of ** SQLite (in which case SQLITE_ENABLE_FTS3 is defined). */ #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) /* #include <assert.h> */ /* #include <stdlib.h> */ /* #include <string.h> */ /* ** Malloc and Free functions */ static void *fts3HashMalloc(int n){ void *p = sqlite3_malloc(n); if( p ){ | > > | 142230 142231 142232 142233 142234 142235 142236 142237 142238 142239 142240 142241 142242 142243 142244 142245 142246 142247 142248 142249 142250 142251 | ** ** * The FTS3 module is being built as an extension ** (in which case SQLITE_CORE is not defined), or ** ** * The FTS3 module is being built into the core of ** SQLite (in which case SQLITE_ENABLE_FTS3 is defined). */ /* #include "fts3Int.h" */ #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) /* #include <assert.h> */ /* #include <stdlib.h> */ /* #include <string.h> */ /* #include "fts3_hash.h" */ /* ** Malloc and Free functions */ static void *fts3HashMalloc(int n){ void *p = sqlite3_malloc(n); if( p ){ |
︙ | ︙ | |||
142391 142392 142393 142394 142395 142396 142397 142398 142399 142400 142401 142402 142403 142404 142405 142406 142407 142408 142409 142410 142411 | ** ** * The FTS3 module is being built as an extension ** (in which case SQLITE_CORE is not defined), or ** ** * The FTS3 module is being built into the core of ** SQLite (in which case SQLITE_ENABLE_FTS3 is defined). */ #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) /* #include <assert.h> */ /* #include <stdlib.h> */ /* #include <stdio.h> */ /* #include <string.h> */ /* ** Class derived from sqlite3_tokenizer */ typedef struct porter_tokenizer { sqlite3_tokenizer base; /* Base class */ } porter_tokenizer; | > > | 142615 142616 142617 142618 142619 142620 142621 142622 142623 142624 142625 142626 142627 142628 142629 142630 142631 142632 142633 142634 142635 142636 142637 | ** ** * The FTS3 module is being built as an extension ** (in which case SQLITE_CORE is not defined), or ** ** * The FTS3 module is being built into the core of ** SQLite (in which case SQLITE_ENABLE_FTS3 is defined). */ /* #include "fts3Int.h" */ #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) /* #include <assert.h> */ /* #include <stdlib.h> */ /* #include <stdio.h> */ /* #include <string.h> */ /* #include "fts3_tokenizer.h" */ /* ** Class derived from sqlite3_tokenizer */ typedef struct porter_tokenizer { sqlite3_tokenizer base; /* Base class */ } porter_tokenizer; |
︙ | ︙ | |||
143055 143056 143057 143058 143059 143060 143061 143062 143063 143064 143065 143066 143067 143068 | ** ** * The FTS3 module is being built as an extension ** (in which case SQLITE_CORE is not defined), or ** ** * The FTS3 module is being built into the core of ** SQLite (in which case SQLITE_ENABLE_FTS3 is defined). */ #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) /* #include <assert.h> */ /* #include <string.h> */ /* ** Implementation of the SQL scalar function for accessing the underlying | > | 143281 143282 143283 143284 143285 143286 143287 143288 143289 143290 143291 143292 143293 143294 143295 | ** ** * The FTS3 module is being built as an extension ** (in which case SQLITE_CORE is not defined), or ** ** * The FTS3 module is being built into the core of ** SQLite (in which case SQLITE_ENABLE_FTS3 is defined). */ /* #include "fts3Int.h" */ #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) /* #include <assert.h> */ /* #include <string.h> */ /* ** Implementation of the SQL scalar function for accessing the underlying |
︙ | ︙ | |||
143550 143551 143552 143553 143554 143555 143556 143557 143558 143559 143560 143561 143562 143563 143564 143565 143566 143567 143568 143569 143570 | ** ** * The FTS3 module is being built as an extension ** (in which case SQLITE_CORE is not defined), or ** ** * The FTS3 module is being built into the core of ** SQLite (in which case SQLITE_ENABLE_FTS3 is defined). */ #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) /* #include <assert.h> */ /* #include <stdlib.h> */ /* #include <stdio.h> */ /* #include <string.h> */ typedef struct simple_tokenizer { sqlite3_tokenizer base; char delim[128]; /* flag ASCII delimiters */ } simple_tokenizer; typedef struct simple_tokenizer_cursor { | > > | 143777 143778 143779 143780 143781 143782 143783 143784 143785 143786 143787 143788 143789 143790 143791 143792 143793 143794 143795 143796 143797 143798 143799 | ** ** * The FTS3 module is being built as an extension ** (in which case SQLITE_CORE is not defined), or ** ** * The FTS3 module is being built into the core of ** SQLite (in which case SQLITE_ENABLE_FTS3 is defined). */ /* #include "fts3Int.h" */ #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) /* #include <assert.h> */ /* #include <stdlib.h> */ /* #include <stdio.h> */ /* #include <string.h> */ /* #include "fts3_tokenizer.h" */ typedef struct simple_tokenizer { sqlite3_tokenizer base; char delim[128]; /* flag ASCII delimiters */ } simple_tokenizer; typedef struct simple_tokenizer_cursor { |
︙ | ︙ | |||
143801 143802 143803 143804 143805 143806 143807 143808 143809 143810 143811 143812 143813 143814 | ** token: A token from the input. ** start: Byte offset of the token within the input <string>. ** end: Byte offset of the byte immediately following the end of the ** token within the input string. ** pos: Token offset of token within input. ** */ #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) /* #include <string.h> */ /* #include <assert.h> */ typedef struct Fts3tokTable Fts3tokTable; typedef struct Fts3tokCursor Fts3tokCursor; | > | 144030 144031 144032 144033 144034 144035 144036 144037 144038 144039 144040 144041 144042 144043 144044 | ** token: A token from the input. ** start: Byte offset of the token within the input <string>. ** end: Byte offset of the byte immediately following the end of the ** token within the input string. ** pos: Token offset of token within input. ** */ /* #include "fts3Int.h" */ #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) /* #include <string.h> */ /* #include <assert.h> */ typedef struct Fts3tokTable Fts3tokTable; typedef struct Fts3tokCursor Fts3tokCursor; |
︙ | ︙ | |||
144236 144237 144238 144239 144240 144241 144242 144243 144244 144245 144246 144247 144248 144249 | ** This file is part of the SQLite FTS3 extension module. Specifically, ** this file contains code to insert, update and delete rows from FTS3 ** tables. It also contains code to merge FTS3 b-tree segments. Some ** of the sub-routines used to merge segments are also used by the query ** code in fts3.c. */ #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) /* #include <string.h> */ /* #include <assert.h> */ /* #include <stdlib.h> */ | > | 144466 144467 144468 144469 144470 144471 144472 144473 144474 144475 144476 144477 144478 144479 144480 | ** This file is part of the SQLite FTS3 extension module. Specifically, ** this file contains code to insert, update and delete rows from FTS3 ** tables. It also contains code to merge FTS3 b-tree segments. Some ** of the sub-routines used to merge segments are also used by the query ** code in fts3.c. */ /* #include "fts3Int.h" */ #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) /* #include <string.h> */ /* #include <assert.h> */ /* #include <stdlib.h> */ |
︙ | ︙ | |||
149896 149897 149898 149899 149900 149901 149902 149903 149904 149905 149906 149907 149908 149909 | ** 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. ** ****************************************************************************** */ #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) /* #include <string.h> */ /* #include <assert.h> */ /* ** Characters that may appear in the second argument to matchinfo(). | > | 150127 150128 150129 150130 150131 150132 150133 150134 150135 150136 150137 150138 150139 150140 150141 | ** 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. ** ****************************************************************************** */ /* #include "fts3Int.h" */ #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) /* #include <string.h> */ /* #include <assert.h> */ /* ** Characters that may appear in the second argument to matchinfo(). |
︙ | ︙ | |||
151608 151609 151610 151611 151612 151613 151614 151615 151616 151617 151618 151619 151620 151621 151622 151623 151624 151625 151626 151627 151628 | ****************************************************************************** ** ** Implementation of the "unicode" full-text-search tokenizer. */ #ifndef SQLITE_DISABLE_FTS3_UNICODE #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) /* #include <assert.h> */ /* #include <stdlib.h> */ /* #include <stdio.h> */ /* #include <string.h> */ /* ** The following two macros - READ_UTF8 and WRITE_UTF8 - have been copied ** from the sqlite3 source file utf.c. If this file is compiled as part ** of the amalgamation, they are not required. */ #ifndef SQLITE_AMALGAMATION | > > | 151840 151841 151842 151843 151844 151845 151846 151847 151848 151849 151850 151851 151852 151853 151854 151855 151856 151857 151858 151859 151860 151861 151862 | ****************************************************************************** ** ** Implementation of the "unicode" full-text-search tokenizer. */ #ifndef SQLITE_DISABLE_FTS3_UNICODE /* #include "fts3Int.h" */ #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) /* #include <assert.h> */ /* #include <stdlib.h> */ /* #include <stdio.h> */ /* #include <string.h> */ /* #include "fts3_tokenizer.h" */ /* ** The following two macros - READ_UTF8 and WRITE_UTF8 - have been copied ** from the sqlite3 source file utf.c. If this file is compiled as part ** of the amalgamation, they are not required. */ #ifndef SQLITE_AMALGAMATION |
︙ | ︙ | |||
152410 152411 152412 152413 152414 152415 152416 152417 152418 152419 152420 152421 152422 152423 152424 152425 | ** of a record. For internal nodes it is the node number of a ** child page. */ #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_RTREE) #ifndef SQLITE_CORE SQLITE_EXTENSION_INIT1 #else #endif /* #include <string.h> */ /* #include <assert.h> */ /* #include <stdio.h> */ #ifndef SQLITE_AMALGAMATION | > > | 152644 152645 152646 152647 152648 152649 152650 152651 152652 152653 152654 152655 152656 152657 152658 152659 152660 152661 | ** of a record. For internal nodes it is the node number of a ** child page. */ #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_RTREE) #ifndef SQLITE_CORE /* #include "sqlite3ext.h" */ SQLITE_EXTENSION_INIT1 #else /* #include "sqlite3.h" */ #endif /* #include <string.h> */ /* #include <assert.h> */ /* #include <stdio.h> */ #ifndef SQLITE_AMALGAMATION |
︙ | ︙ | |||
155907 155908 155909 155910 155911 155912 155913 155914 155915 155916 155917 155918 155919 155920 155921 155922 | #include <unicode/uregex.h> #include <unicode/ustring.h> #include <unicode/ucol.h> /* #include <assert.h> */ #ifndef SQLITE_CORE SQLITE_EXTENSION_INIT1 #else #endif /* ** Maximum length (in bytes) of the pattern in a LIKE or GLOB ** operator. */ #ifndef SQLITE_MAX_LIKE_PATTERN_LENGTH | > > | 156143 156144 156145 156146 156147 156148 156149 156150 156151 156152 156153 156154 156155 156156 156157 156158 156159 156160 | #include <unicode/uregex.h> #include <unicode/ustring.h> #include <unicode/ucol.h> /* #include <assert.h> */ #ifndef SQLITE_CORE /* #include "sqlite3ext.h" */ SQLITE_EXTENSION_INIT1 #else /* #include "sqlite3.h" */ #endif /* ** Maximum length (in bytes) of the pattern in a LIKE or GLOB ** operator. */ #ifndef SQLITE_MAX_LIKE_PATTERN_LENGTH |
︙ | ︙ | |||
156384 156385 156386 156387 156388 156389 156390 156391 156392 156393 156394 156395 156396 156397 156398 156399 156400 156401 156402 | ** 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 a tokenizer for fts3 based on the ICU library. */ #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) #ifdef SQLITE_ENABLE_ICU /* #include <assert.h> */ /* #include <string.h> */ #include <unicode/ubrk.h> /* #include <unicode/ucol.h> */ /* #include <unicode/ustring.h> */ #include <unicode/utf16.h> typedef struct IcuTokenizer IcuTokenizer; | > > | 156622 156623 156624 156625 156626 156627 156628 156629 156630 156631 156632 156633 156634 156635 156636 156637 156638 156639 156640 156641 156642 | ** 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 a tokenizer for fts3 based on the ICU library. */ /* #include "fts3Int.h" */ #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) #ifdef SQLITE_ENABLE_ICU /* #include <assert.h> */ /* #include <string.h> */ /* #include "fts3_tokenizer.h" */ #include <unicode/ubrk.h> /* #include <unicode/ucol.h> */ /* #include <unicode/ustring.h> */ #include <unicode/utf16.h> typedef struct IcuTokenizer IcuTokenizer; |
︙ | ︙ | |||
156633 156634 156635 156636 156637 156638 156639 | *ppModule = &icuTokenizerModule; } #endif /* defined(SQLITE_ENABLE_ICU) */ #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ /************** End of fts3_icu.c ********************************************/ | | | | | | | | | | | | | | | | | | | > > | > > | | | | | 156873 156874 156875 156876 156877 156878 156879 156880 156881 156882 156883 156884 156885 156886 156887 156888 156889 156890 156891 156892 156893 156894 156895 156896 156897 156898 156899 156900 156901 156902 156903 156904 156905 156906 156907 156908 156909 156910 156911 156912 156913 156914 156915 156916 156917 156918 156919 156920 156921 156922 156923 156924 156925 156926 156927 156928 156929 156930 156931 156932 156933 156934 156935 156936 156937 156938 156939 156940 156941 156942 156943 156944 156945 156946 156947 156948 156949 156950 156951 156952 156953 156954 156955 156956 156957 156958 156959 156960 156961 156962 156963 156964 156965 156966 156967 156968 156969 156970 156971 156972 156973 156974 156975 156976 156977 156978 156979 156980 156981 156982 156983 156984 156985 156986 156987 156988 156989 156990 156991 156992 156993 156994 156995 | *ppModule = &icuTokenizerModule; } #endif /* defined(SQLITE_ENABLE_ICU) */ #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ /************** End of fts3_icu.c ********************************************/ /************** Begin file sqlite3rbu.c **************************************/ /* ** 2014 August 30 ** ** 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. ** ************************************************************************* ** ** ** OVERVIEW ** ** The RBU extension requires that the RBU update be packaged as an ** SQLite database. The tables it expects to find are described in ** sqlite3rbu.h. Essentially, for each table xyz in the target database ** that the user wishes to write to, a corresponding data_xyz table is ** created in the RBU database and populated with one row for each row to ** update, insert or delete from the target table. ** ** The update proceeds in three stages: ** ** 1) The database is updated. The modified database pages are written ** to a *-oal file. A *-oal file is just like a *-wal file, except ** that it is named "<database>-oal" instead of "<database>-wal". ** Because regular SQLite clients do not look for file named ** "<database>-oal", they go on using the original database in ** rollback mode while the *-oal file is being generated. ** ** During this stage RBU does not update the database by writing ** directly to the target tables. Instead it creates "imposter" ** tables using the SQLITE_TESTCTRL_IMPOSTER interface that it uses ** to update each b-tree individually. All updates required by each ** b-tree are completed before moving on to the next, and all ** updates are done in sorted key order. ** ** 2) The "<database>-oal" file is moved to the equivalent "<database>-wal" ** location using a call to rename(2). Before doing this the RBU ** module takes an EXCLUSIVE lock on the database file, ensuring ** that there are no other active readers. ** ** Once the EXCLUSIVE lock is released, any other database readers ** detect the new *-wal file and read the database in wal mode. At ** this point they see the new version of the database - including ** the updates made as part of the RBU update. ** ** 3) The new *-wal file is checkpointed. This proceeds in the same way ** as a regular database checkpoint, except that a single frame is ** checkpointed each time sqlite3rbu_step() is called. If the RBU ** handle is closed before the entire *-wal file is checkpointed, ** the checkpoint progress is saved in the RBU database and the ** checkpoint can be resumed by another RBU client at some point in ** the future. ** ** POTENTIAL PROBLEMS ** ** The rename() call might not be portable. And RBU is not currently ** syncing the directory after renaming the file. ** ** When state is saved, any commit to the *-oal file and the commit to ** the RBU update database are not atomic. So if the power fails at the ** wrong moment they might get out of sync. As the main database will be ** committed before the RBU update database this will likely either just ** pass unnoticed, or result in SQLITE_CONSTRAINT errors (due to UNIQUE ** constraint violations). ** ** If some client does modify the target database mid RBU update, or some ** other error occurs, the RBU extension will keep throwing errors. It's ** not really clear how to get out of this state. The system could just ** by delete the RBU update database and *-oal file and have the device ** download the update again and start over. ** ** At present, for an UPDATE, both the new.* and old.* records are ** collected in the rbu_xyz table. And for both UPDATEs and DELETEs all ** fields are collected. This means we're probably writing a lot more ** data to disk when saving the state of an ongoing update to the RBU ** update database than is strictly necessary. ** */ /* #include <assert.h> */ /* #include <string.h> */ /* #include <stdio.h> */ #if !defined(_WIN32) /* # include <unistd.h> */ #endif /* #include "sqlite3.h" */ #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_RBU) /************** Include sqlite3rbu.h in the middle of sqlite3rbu.c ***********/ /************** Begin file sqlite3rbu.h **************************************/ /* ** 2014 August 30 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** ** This file contains the public interface for the RBU extension. */ /* ** SUMMARY ** ** Writing a transaction containing a large number of operations on ** b-tree indexes that are collectively larger than the available cache |
︙ | ︙ | |||
156774 156775 156776 156777 156778 156779 156780 | ** guarantee that a single update process will run for long enough to apply ** the entire update, for example because the update is being applied on a ** mobile device that is frequently rebooted. Even after the writer process ** has committed one or more sub-transactions, other database clients continue ** to read from the original database snapshot. In other words, partially ** applied transactions are not visible to other clients. ** | | | | | 157018 157019 157020 157021 157022 157023 157024 157025 157026 157027 157028 157029 157030 157031 157032 157033 157034 157035 157036 157037 157038 157039 | ** guarantee that a single update process will run for long enough to apply ** the entire update, for example because the update is being applied on a ** mobile device that is frequently rebooted. Even after the writer process ** has committed one or more sub-transactions, other database clients continue ** to read from the original database snapshot. In other words, partially ** applied transactions are not visible to other clients. ** ** "RBU" stands for "Resumable Bulk Update". As in a large database update ** transmitted via a wireless network to a mobile device. A transaction ** applied using this extension is hence refered to as an "RBU update". ** ** ** LIMITATIONS ** ** An "RBU update" transaction is subject to the following limitations: ** ** * The transaction must consist of INSERT, UPDATE and DELETE operations ** only. ** ** * INSERT statements may not use any default values. ** ** * UPDATE and DELETE statements must identify their target rows by |
︙ | ︙ | |||
156806 156807 156808 156809 156810 156811 156812 | ** * CHECK constraints are not enforced. ** ** * No constraint handling mode except for "OR ROLLBACK" is supported. ** ** ** PREPARATION ** | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 157050 157051 157052 157053 157054 157055 157056 157057 157058 157059 157060 157061 157062 157063 157064 157065 157066 157067 157068 157069 157070 157071 157072 157073 157074 157075 157076 157077 157078 157079 157080 157081 157082 157083 157084 157085 157086 157087 157088 157089 157090 157091 157092 157093 157094 157095 157096 157097 157098 157099 157100 157101 157102 157103 157104 157105 157106 157107 157108 157109 157110 157111 157112 157113 157114 157115 157116 157117 157118 157119 157120 157121 157122 157123 157124 157125 157126 157127 157128 157129 157130 157131 157132 157133 157134 157135 157136 157137 157138 157139 157140 157141 157142 157143 157144 157145 157146 157147 157148 157149 157150 157151 157152 157153 157154 157155 157156 157157 157158 157159 157160 157161 157162 157163 157164 157165 157166 157167 157168 157169 157170 157171 157172 157173 157174 157175 157176 157177 157178 157179 157180 157181 157182 157183 157184 157185 157186 157187 157188 157189 157190 157191 157192 157193 157194 157195 157196 157197 157198 157199 157200 157201 157202 157203 157204 157205 157206 157207 157208 157209 157210 157211 157212 157213 157214 157215 157216 157217 157218 157219 157220 157221 157222 157223 157224 157225 157226 157227 157228 157229 157230 157231 157232 157233 157234 157235 157236 157237 157238 157239 157240 157241 157242 157243 157244 157245 157246 157247 157248 157249 157250 157251 157252 157253 157254 157255 157256 157257 157258 157259 157260 157261 157262 157263 157264 157265 157266 157267 157268 157269 157270 157271 157272 157273 157274 157275 157276 157277 157278 157279 157280 157281 157282 157283 157284 157285 157286 157287 157288 157289 157290 157291 157292 157293 157294 157295 157296 157297 157298 157299 157300 157301 157302 157303 157304 157305 157306 157307 157308 157309 157310 157311 157312 157313 157314 157315 157316 157317 157318 157319 157320 157321 157322 157323 157324 157325 157326 157327 157328 157329 157330 157331 157332 157333 157334 157335 157336 157337 157338 157339 157340 157341 157342 157343 157344 157345 157346 157347 157348 157349 157350 157351 157352 157353 157354 157355 157356 157357 157358 157359 157360 157361 157362 157363 157364 157365 157366 157367 157368 157369 157370 157371 157372 157373 157374 157375 157376 157377 157378 157379 157380 157381 157382 157383 157384 157385 157386 157387 157388 157389 157390 157391 157392 157393 157394 157395 157396 157397 157398 157399 157400 157401 157402 157403 157404 157405 157406 157407 157408 157409 157410 157411 157412 157413 157414 157415 157416 157417 157418 157419 157420 157421 157422 157423 157424 157425 157426 157427 157428 157429 157430 157431 157432 157433 157434 157435 157436 157437 157438 157439 157440 157441 157442 157443 157444 157445 157446 157447 157448 157449 157450 157451 157452 157453 157454 157455 157456 157457 157458 157459 157460 157461 157462 157463 157464 157465 157466 157467 157468 157469 157470 157471 157472 157473 157474 157475 157476 157477 157478 157479 157480 157481 157482 157483 157484 157485 157486 157487 157488 157489 157490 157491 157492 157493 157494 157495 157496 157497 157498 157499 157500 157501 157502 157503 157504 157505 157506 157507 157508 157509 157510 157511 157512 157513 157514 157515 157516 157517 157518 157519 157520 157521 157522 157523 157524 157525 157526 157527 157528 157529 157530 157531 157532 157533 157534 157535 157536 157537 157538 157539 157540 157541 157542 157543 157544 157545 157546 157547 157548 157549 157550 157551 157552 157553 157554 157555 157556 157557 157558 157559 157560 157561 157562 157563 157564 157565 157566 157567 157568 157569 157570 157571 157572 157573 157574 157575 157576 157577 157578 157579 157580 157581 157582 157583 157584 157585 157586 157587 157588 157589 157590 157591 157592 157593 157594 157595 157596 157597 157598 157599 157600 157601 157602 157603 157604 157605 157606 157607 157608 157609 157610 157611 157612 157613 157614 157615 157616 157617 157618 157619 157620 157621 157622 157623 157624 157625 157626 157627 157628 157629 157630 157631 157632 157633 157634 157635 157636 157637 157638 157639 157640 157641 157642 157643 157644 157645 157646 157647 157648 157649 157650 157651 157652 157653 157654 157655 157656 157657 157658 157659 157660 157661 157662 157663 157664 157665 157666 157667 157668 | ** * CHECK constraints are not enforced. ** ** * No constraint handling mode except for "OR ROLLBACK" is supported. ** ** ** PREPARATION ** ** An "RBU update" is stored as a separate SQLite database. A database ** containing an RBU update is an "RBU database". For each table in the ** target database to be updated, the RBU database should contain a table ** named "data_<target name>" containing the same set of columns as the ** target table, and one more - "rbu_control". The data_% table should ** have no PRIMARY KEY or UNIQUE constraints, but each column should have ** the same type as the corresponding column in the target database. ** The "rbu_control" column should have no type at all. For example, if ** the target database contains: ** ** CREATE TABLE t1(a INTEGER PRIMARY KEY, b TEXT, c UNIQUE); ** ** Then the RBU database should contain: ** ** CREATE TABLE data_t1(a INTEGER, b TEXT, c, rbu_control); ** ** The order of the columns in the data_% table does not matter. ** ** If the target database table is a virtual table or a table that has no ** PRIMARY KEY declaration, the data_% table must also contain a column ** named "rbu_rowid". This column is mapped to the tables implicit primary ** key column - "rowid". Virtual tables for which the "rowid" column does ** not function like a primary key value cannot be updated using RBU. For ** example, if the target db contains either of the following: ** ** CREATE VIRTUAL TABLE x1 USING fts3(a, b); ** CREATE TABLE x1(a, b) ** ** then the RBU database should contain: ** ** CREATE TABLE data_x1(a, b, rbu_rowid, rbu_control); ** ** All non-hidden columns (i.e. all columns matched by "SELECT *") of the ** target table must be present in the input table. For virtual tables, ** hidden columns are optional - they are updated by RBU if present in ** the input table, or not otherwise. For example, to write to an fts4 ** table with a hidden languageid column such as: ** ** CREATE VIRTUAL TABLE ft1 USING fts4(a, b, languageid='langid'); ** ** Either of the following input table schemas may be used: ** ** CREATE TABLE data_ft1(a, b, langid, rbu_rowid, rbu_control); ** CREATE TABLE data_ft1(a, b, rbu_rowid, rbu_control); ** ** For each row to INSERT into the target database as part of the RBU ** update, the corresponding data_% table should contain a single record ** with the "rbu_control" column set to contain integer value 0. The ** other columns should be set to the values that make up the new record ** to insert. ** ** If the target database table has an INTEGER PRIMARY KEY, it is not ** possible to insert a NULL value into the IPK column. Attempting to ** do so results in an SQLITE_MISMATCH error. ** ** For each row to DELETE from the target database as part of the RBU ** update, the corresponding data_% table should contain a single record ** with the "rbu_control" column set to contain integer value 1. The ** real primary key values of the row to delete should be stored in the ** corresponding columns of the data_% table. The values stored in the ** other columns are not used. ** ** For each row to UPDATE from the target database as part of the RBU ** update, the corresponding data_% table should contain a single record ** with the "rbu_control" column set to contain a value of type text. ** The real primary key values identifying the row to update should be ** stored in the corresponding columns of the data_% table row, as should ** the new values of all columns being update. The text value in the ** "rbu_control" column must contain the same number of characters as ** there are columns in the target database table, and must consist entirely ** of 'x' and '.' characters (or in some special cases 'd' - see below). For ** each column that is being updated, the corresponding character is set to ** 'x'. For those that remain as they are, the corresponding character of the ** rbu_control value should be set to '.'. For example, given the tables ** above, the update statement: ** ** UPDATE t1 SET c = 'usa' WHERE a = 4; ** ** is represented by the data_t1 row created by: ** ** INSERT INTO data_t1(a, b, c, rbu_control) VALUES(4, NULL, 'usa', '..x'); ** ** Instead of an 'x' character, characters of the rbu_control value specified ** for UPDATEs may also be set to 'd'. In this case, instead of updating the ** target table with the value stored in the corresponding data_% column, the ** user-defined SQL function "rbu_delta()" is invoked and the result stored in ** the target table column. rbu_delta() is invoked with two arguments - the ** original value currently stored in the target table column and the ** value specified in the data_xxx table. ** ** For example, this row: ** ** INSERT INTO data_t1(a, b, c, rbu_control) VALUES(4, NULL, 'usa', '..d'); ** ** is similar to an UPDATE statement such as: ** ** UPDATE t1 SET c = rbu_delta(c, 'usa') WHERE a = 4; ** ** If the target database table is a virtual table or a table with no PRIMARY ** KEY, the rbu_control value should not include a character corresponding ** to the rbu_rowid value. For example, this: ** ** INSERT INTO data_ft1(a, b, rbu_rowid, rbu_control) ** VALUES(NULL, 'usa', 12, '.x'); ** ** causes a result similar to: ** ** UPDATE ft1 SET b = 'usa' WHERE rowid = 12; ** ** The data_xxx tables themselves should have no PRIMARY KEY declarations. ** However, RBU is more efficient if reading the rows in from each data_xxx ** table in "rowid" order is roughly the same as reading them sorted by ** the PRIMARY KEY of the corresponding target database table. In other ** words, rows should be sorted using the destination table PRIMARY KEY ** fields before they are inserted into the data_xxx tables. ** ** USAGE ** ** The API declared below allows an application to apply an RBU update ** stored on disk to an existing target database. Essentially, the ** application: ** ** 1) Opens an RBU handle using the sqlite3rbu_open() function. ** ** 2) Registers any required virtual table modules with the database ** handle returned by sqlite3rbu_db(). Also, if required, register ** the rbu_delta() implementation. ** ** 3) Calls the sqlite3rbu_step() function one or more times on ** the new handle. Each call to sqlite3rbu_step() performs a single ** b-tree operation, so thousands of calls may be required to apply ** a complete update. ** ** 4) Calls sqlite3rbu_close() to close the RBU update handle. If ** sqlite3rbu_step() has been called enough times to completely ** apply the update to the target database, then the RBU database ** is marked as fully applied. Otherwise, the state of the RBU ** update application is saved in the RBU database for later ** resumption. ** ** See comments below for more detail on APIs. ** ** If an update is only partially applied to the target database by the ** time sqlite3rbu_close() is called, various state information is saved ** within the RBU database. This allows subsequent processes to automatically ** resume the RBU update from where it left off. ** ** To remove all RBU extension state information, returning an RBU database ** to its original contents, it is sufficient to drop all tables that begin ** with the prefix "rbu_" ** ** DATABASE LOCKING ** ** An RBU update may not be applied to a database in WAL mode. Attempting ** to do so is an error (SQLITE_ERROR). ** ** While an RBU handle is open, a SHARED lock may be held on the target ** database file. This means it is possible for other clients to read the ** database, but not to write it. ** ** If an RBU update is started and then suspended before it is completed, ** then an external client writes to the database, then attempting to resume ** the suspended RBU update is also an error (SQLITE_BUSY). */ #ifndef _SQLITE3RBU_H #define _SQLITE3RBU_H /* #include "sqlite3.h" ** Required for error code definitions ** */ typedef struct sqlite3rbu sqlite3rbu; /* ** Open an RBU handle. ** ** Argument zTarget is the path to the target database. Argument zRbu is ** the path to the RBU database. Each call to this function must be matched ** by a call to sqlite3rbu_close(). When opening the databases, RBU passes ** the SQLITE_CONFIG_URI flag to sqlite3_open_v2(). So if either zTarget ** or zRbu begin with "file:", it will be interpreted as an SQLite ** database URI, not a regular file name. ** ** If the zState argument is passed a NULL value, the RBU extension stores ** the current state of the update (how many rows have been updated, which ** indexes are yet to be updated etc.) within the RBU database itself. This ** can be convenient, as it means that the RBU application does not need to ** organize removing a separate state file after the update is concluded. ** Or, if zState is non-NULL, it must be a path to a database file in which ** the RBU extension can store the state of the update. ** ** When resuming an RBU update, the zState argument must be passed the same ** value as when the RBU update was started. ** ** Once the RBU update is finished, the RBU extension does not ** automatically remove any zState database file, even if it created it. ** ** By default, RBU uses the default VFS to access the files on disk. To ** use a VFS other than the default, an SQLite "file:" URI containing a ** "vfs=..." option may be passed as the zTarget option. ** ** IMPORTANT NOTE FOR ZIPVFS USERS: The RBU extension works with all of ** SQLite's built-in VFSs, including the multiplexor VFS. However it does ** not work out of the box with zipvfs. Refer to the comment describing ** the zipvfs_create_vfs() API below for details on using RBU with zipvfs. */ SQLITE_API sqlite3rbu *SQLITE_STDCALL sqlite3rbu_open( const char *zTarget, const char *zRbu, const char *zState ); /* ** Internally, each RBU connection uses a separate SQLite database ** connection to access the target and rbu update databases. This ** API allows the application direct access to these database handles. ** ** The first argument passed to this function must be a valid, open, RBU ** handle. The second argument should be passed zero to access the target ** database handle, or non-zero to access the rbu update database handle. ** Accessing the underlying database handles may be useful in the ** following scenarios: ** ** * If any target tables are virtual tables, it may be necessary to ** call sqlite3_create_module() on the target database handle to ** register the required virtual table implementations. ** ** * If the data_xxx tables in the RBU source database are virtual ** tables, the application may need to call sqlite3_create_module() on ** the rbu update db handle to any required virtual table ** implementations. ** ** * If the application uses the "rbu_delta()" feature described above, ** it must use sqlite3_create_function() or similar to register the ** rbu_delta() implementation with the target database handle. ** ** If an error has occurred, either while opening or stepping the RBU object, ** this function may return NULL. The error code and message may be collected ** when sqlite3rbu_close() is called. */ SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3rbu_db(sqlite3rbu*, int bRbu); /* ** Do some work towards applying the RBU update to the target db. ** ** Return SQLITE_DONE if the update has been completely applied, or ** SQLITE_OK if no error occurs but there remains work to do to apply ** the RBU update. If an error does occur, some other error code is ** returned. ** ** Once a call to sqlite3rbu_step() has returned a value other than ** SQLITE_OK, all subsequent calls on the same RBU handle are no-ops ** that immediately return the same value. */ SQLITE_API int SQLITE_STDCALL sqlite3rbu_step(sqlite3rbu *pRbu); /* ** Close an RBU handle. ** ** If the RBU update has been completely applied, mark the RBU database ** as fully applied. Otherwise, assuming no error has occurred, save the ** current state of the RBU update appliation to the RBU database. ** ** If an error has already occurred as part of an sqlite3rbu_step() ** or sqlite3rbu_open() call, or if one occurs within this function, an ** SQLite error code is returned. Additionally, *pzErrmsg may be set to ** point to a buffer containing a utf-8 formatted English language error ** message. It is the responsibility of the caller to eventually free any ** such buffer using sqlite3_free(). ** ** Otherwise, if no error occurs, this function returns SQLITE_OK if the ** update has been partially applied, or SQLITE_DONE if it has been ** completely applied. */ SQLITE_API int SQLITE_STDCALL sqlite3rbu_close(sqlite3rbu *pRbu, char **pzErrmsg); /* ** Return the total number of key-value operations (inserts, deletes or ** updates) that have been performed on the target database since the ** current RBU update was started. */ SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3rbu_progress(sqlite3rbu *pRbu); /* ** Create an RBU VFS named zName that accesses the underlying file-system ** via existing VFS zParent. Or, if the zParent parameter is passed NULL, ** then the new RBU VFS uses the default system VFS to access the file-system. ** The new object is registered as a non-default VFS with SQLite before ** returning. ** ** Part of the RBU implementation uses a custom VFS object. Usually, this ** object is created and deleted automatically by RBU. ** ** The exception is for applications that also use zipvfs. In this case, ** the custom VFS must be explicitly created by the user before the RBU ** handle is opened. The RBU VFS should be installed so that the zipvfs ** VFS uses the RBU VFS, which in turn uses any other VFS layers in use ** (for example multiplexor) to access the file-system. For example, ** to assemble an RBU enabled VFS stack that uses both zipvfs and ** multiplexor (error checking omitted): ** ** // Create a VFS named "multiplex" (not the default). ** sqlite3_multiplex_initialize(0, 0); ** ** // Create an rbu VFS named "rbu" that uses multiplexor. If the ** // second argument were replaced with NULL, the "rbu" VFS would ** // access the file-system via the system default VFS, bypassing the ** // multiplexor. ** sqlite3rbu_create_vfs("rbu", "multiplex"); ** ** // Create a zipvfs VFS named "zipvfs" that uses rbu. ** zipvfs_create_vfs_v3("zipvfs", "rbu", 0, xCompressorAlgorithmDetector); ** ** // Make zipvfs the default VFS. ** sqlite3_vfs_register(sqlite3_vfs_find("zipvfs"), 1); ** ** Because the default VFS created above includes a RBU functionality, it ** may be used by RBU clients. Attempting to use RBU with a zipvfs VFS stack ** that does not include the RBU layer results in an error. ** ** The overhead of adding the "rbu" VFS to the system is negligible for ** non-RBU users. There is no harm in an application accessing the ** file-system via "rbu" all the time, even if it only uses RBU functionality ** occasionally. */ SQLITE_API int SQLITE_STDCALL sqlite3rbu_create_vfs(const char *zName, const char *zParent); /* ** Deregister and destroy an RBU vfs created by an earlier call to ** sqlite3rbu_create_vfs(). ** ** VFS objects are not reference counted. If a VFS object is destroyed ** before all database handles that use it have been closed, the results ** are undefined. */ SQLITE_API void SQLITE_STDCALL sqlite3rbu_destroy_vfs(const char *zName); #endif /* _SQLITE3RBU_H */ /************** End of sqlite3rbu.h ******************************************/ /************** Continuing where we left off in sqlite3rbu.c *****************/ /* Maximum number of prepared UPDATE statements held by this module */ #define SQLITE_RBU_UPDATE_CACHESIZE 16 /* ** Swap two objects of type TYPE. */ #if !defined(SQLITE_AMALGAMATION) # define SWAP(TYPE,A,B) {TYPE t=A; A=B; B=t;} #endif /* ** The rbu_state table is used to save the state of a partially applied ** update so that it can be resumed later. The table consists of integer ** keys mapped to values as follows: ** ** RBU_STATE_STAGE: ** May be set to integer values 1, 2, 4 or 5. As follows: ** 1: the *-rbu file is currently under construction. ** 2: the *-rbu file has been constructed, but not yet moved ** to the *-wal path. ** 4: the checkpoint is underway. ** 5: the rbu update has been checkpointed. ** ** RBU_STATE_TBL: ** Only valid if STAGE==1. The target database name of the table ** currently being written. ** ** RBU_STATE_IDX: ** Only valid if STAGE==1. The target database name of the index ** currently being written, or NULL if the main table is currently being ** updated. ** ** RBU_STATE_ROW: ** Only valid if STAGE==1. Number of rows already processed for the current ** table/index. ** ** RBU_STATE_PROGRESS: ** Trbul number of sqlite3rbu_step() calls made so far as part of this ** rbu update. ** ** RBU_STATE_CKPT: ** Valid if STAGE==4. The 64-bit checksum associated with the wal-index ** header created by recovering the *-wal file. This is used to detect ** cases when another client appends frames to the *-wal file in the ** middle of an incremental checkpoint (an incremental checkpoint cannot ** be continued if this happens). ** ** RBU_STATE_COOKIE: ** Valid if STAGE==1. The current change-counter cookie value in the ** target db file. ** ** RBU_STATE_OALSZ: ** Valid if STAGE==1. The size in bytes of the *-oal file. */ #define RBU_STATE_STAGE 1 #define RBU_STATE_TBL 2 #define RBU_STATE_IDX 3 #define RBU_STATE_ROW 4 #define RBU_STATE_PROGRESS 5 #define RBU_STATE_CKPT 6 #define RBU_STATE_COOKIE 7 #define RBU_STATE_OALSZ 8 #define RBU_STAGE_OAL 1 #define RBU_STAGE_MOVE 2 #define RBU_STAGE_CAPTURE 3 #define RBU_STAGE_CKPT 4 #define RBU_STAGE_DONE 5 #define RBU_CREATE_STATE \ "CREATE TABLE IF NOT EXISTS %s.rbu_state(k INTEGER PRIMARY KEY, v)" typedef struct RbuFrame RbuFrame; typedef struct RbuObjIter RbuObjIter; typedef struct RbuState RbuState; typedef struct rbu_vfs rbu_vfs; typedef struct rbu_file rbu_file; typedef struct RbuUpdateStmt RbuUpdateStmt; #if !defined(SQLITE_AMALGAMATION) typedef unsigned int u32; typedef unsigned char u8; typedef sqlite3_int64 i64; #endif /* ** These values must match the values defined in wal.c for the equivalent ** locks. These are not magic numbers as they are part of the SQLite file ** format. */ #define WAL_LOCK_WRITE 0 #define WAL_LOCK_CKPT 1 #define WAL_LOCK_READ0 3 /* ** A structure to store values read from the rbu_state table in memory. */ struct RbuState { int eStage; char *zTbl; char *zIdx; i64 iWalCksum; int nRow; i64 nProgress; u32 iCookie; i64 iOalSz; }; struct RbuUpdateStmt { char *zMask; /* Copy of update mask used with pUpdate */ sqlite3_stmt *pUpdate; /* Last update statement (or NULL) */ RbuUpdateStmt *pNext; }; /* ** An iterator of this type is used to iterate through all objects in ** the target database that require updating. For each such table, the ** iterator visits, in order: ** ** * the table itself, ** * each index of the table (zero or more points to visit), and ** * a special "cleanup table" state. ** ** abIndexed: ** If the table has no indexes on it, abIndexed is set to NULL. Otherwise, ** it points to an array of flags nTblCol elements in size. The flag is ** set for each column that is either a part of the PK or a part of an ** index. Or clear otherwise. ** */ struct RbuObjIter { sqlite3_stmt *pTblIter; /* Iterate through tables */ sqlite3_stmt *pIdxIter; /* Index iterator */ int nTblCol; /* Size of azTblCol[] array */ char **azTblCol; /* Array of unquoted target column names */ char **azTblType; /* Array of target column types */ int *aiSrcOrder; /* src table col -> target table col */ u8 *abTblPk; /* Array of flags, set on target PK columns */ u8 *abNotNull; /* Array of flags, set on NOT NULL columns */ u8 *abIndexed; /* Array of flags, set on indexed & PK cols */ int eType; /* Table type - an RBU_PK_XXX value */ /* Output variables. zTbl==0 implies EOF. */ int bCleanup; /* True in "cleanup" state */ const char *zTbl; /* Name of target db table */ const char *zIdx; /* Name of target db index (or null) */ int iTnum; /* Root page of current object */ int iPkTnum; /* If eType==EXTERNAL, root of PK index */ int bUnique; /* Current index is unique */ /* Statements created by rbuObjIterPrepareAll() */ int nCol; /* Number of columns in current object */ sqlite3_stmt *pSelect; /* Source data */ sqlite3_stmt *pInsert; /* Statement for INSERT operations */ sqlite3_stmt *pDelete; /* Statement for DELETE ops */ sqlite3_stmt *pTmpInsert; /* Insert into rbu_tmp_$zTbl */ /* Last UPDATE used (for PK b-tree updates only), or NULL. */ RbuUpdateStmt *pRbuUpdate; }; /* ** Values for RbuObjIter.eType ** ** 0: Table does not exist (error) ** 1: Table has an implicit rowid. ** 2: Table has an explicit IPK column. ** 3: Table has an external PK index. ** 4: Table is WITHOUT ROWID. ** 5: Table is a virtual table. */ #define RBU_PK_NOTABLE 0 #define RBU_PK_NONE 1 #define RBU_PK_IPK 2 #define RBU_PK_EXTERNAL 3 #define RBU_PK_WITHOUT_ROWID 4 #define RBU_PK_VTAB 5 /* ** Within the RBU_STAGE_OAL stage, each call to sqlite3rbu_step() performs ** one of the following operations. */ #define RBU_INSERT 1 /* Insert on a main table b-tree */ #define RBU_DELETE 2 /* Delete a row from a main table b-tree */ #define RBU_IDX_DELETE 3 /* Delete a row from an aux. index b-tree */ #define RBU_IDX_INSERT 4 /* Insert on an aux. index b-tree */ #define RBU_UPDATE 5 /* Update a row in a main table b-tree */ /* ** A single step of an incremental checkpoint - frame iWalFrame of the wal ** file should be copied to page iDbPage of the database file. */ struct RbuFrame { u32 iDbPage; u32 iWalFrame; }; /* ** RBU handle. */ struct sqlite3rbu { int eStage; /* Value of RBU_STATE_STAGE field */ sqlite3 *dbMain; /* target database handle */ sqlite3 *dbRbu; /* rbu database handle */ char *zTarget; /* Path to target db */ char *zRbu; /* Path to rbu db */ char *zState; /* Path to state db (or NULL if zRbu) */ char zStateDb[5]; /* Db name for state ("stat" or "main") */ int rc; /* Value returned by last rbu_step() call */ char *zErrmsg; /* Error message if rc!=SQLITE_OK */ int nStep; /* Rows processed for current object */ int nProgress; /* Rows processed for all objects */ RbuObjIter objiter; /* Iterator for skipping through tbl/idx */ const char *zVfsName; /* Name of automatically created rbu vfs */ rbu_file *pTargetFd; /* File handle open on target db */ i64 iOalSz; /* The following state variables are used as part of the incremental ** checkpoint stage (eStage==RBU_STAGE_CKPT). See comments surrounding ** function rbuSetupCheckpoint() for details. */ u32 iMaxFrame; /* Largest iWalFrame value in aFrame[] */ u32 mLock; int nFrame; /* Entries in aFrame[] array */ int nFrameAlloc; /* Allocated size of aFrame[] array */ RbuFrame *aFrame; int pgsz; u8 *aBuf; i64 iWalCksum; }; /* ** An rbu VFS is implemented using an instance of this structure. */ struct rbu_vfs { sqlite3_vfs base; /* rbu VFS shim methods */ sqlite3_vfs *pRealVfs; /* Underlying VFS */ sqlite3_mutex *mutex; /* Mutex to protect pMain */ rbu_file *pMain; /* Linked list of main db files */ }; /* ** Each file opened by an rbu VFS is represented by an instance of ** the following structure. */ struct rbu_file { sqlite3_file base; /* sqlite3_file methods */ sqlite3_file *pReal; /* Underlying file handle */ rbu_vfs *pRbuVfs; /* Pointer to the rbu_vfs object */ sqlite3rbu *pRbu; /* Pointer to rbu object (rbu target only) */ int openFlags; /* Flags this file was opened with */ u32 iCookie; /* Cookie value for main db files */ u8 iWriteVer; /* "write-version" value for main db files */ int nShm; /* Number of entries in apShm[] array */ char **apShm; /* Array of mmap'd *-shm regions */ char *zDel; /* Delete this when closing file */ const char *zWal; /* Wal filename for this main db file */ rbu_file *pWalFd; /* Wal file descriptor for this main db */ rbu_file *pMainNext; /* Next MAIN_DB file */ }; /* ** Prepare the SQL statement in buffer zSql against database handle db. ** If successful, set *ppStmt to point to the new statement and return ** SQLITE_OK. |
︙ | ︙ | |||
157488 157489 157490 157491 157492 157493 157494 | rc = prepareAndCollectError(db, ppStmt, pzErrmsg, zSql); sqlite3_free(zSql); } return rc; } /* | | | | | | | | | | | | | | | | | | | | | | 157732 157733 157734 157735 157736 157737 157738 157739 157740 157741 157742 157743 157744 157745 157746 157747 157748 157749 157750 157751 157752 157753 157754 157755 157756 157757 157758 157759 157760 157761 157762 157763 157764 157765 157766 157767 157768 157769 157770 157771 157772 157773 157774 157775 157776 157777 157778 157779 157780 157781 157782 157783 157784 157785 157786 157787 157788 157789 157790 157791 157792 157793 157794 157795 157796 157797 157798 157799 157800 157801 157802 157803 157804 157805 157806 157807 157808 157809 157810 157811 157812 157813 157814 157815 157816 157817 157818 157819 157820 157821 157822 157823 157824 157825 157826 157827 157828 157829 157830 | rc = prepareAndCollectError(db, ppStmt, pzErrmsg, zSql); sqlite3_free(zSql); } return rc; } /* ** Free the RbuObjIter.azTblCol[] and RbuObjIter.abTblPk[] arrays allocated ** by an earlier call to rbuObjIterCacheTableInfo(). */ static void rbuObjIterFreeCols(RbuObjIter *pIter){ int i; for(i=0; i<pIter->nTblCol; i++){ sqlite3_free(pIter->azTblCol[i]); sqlite3_free(pIter->azTblType[i]); } sqlite3_free(pIter->azTblCol); pIter->azTblCol = 0; pIter->azTblType = 0; pIter->aiSrcOrder = 0; pIter->abTblPk = 0; pIter->abNotNull = 0; pIter->nTblCol = 0; pIter->eType = 0; /* Invalid value */ } /* ** Finalize all statements and free all allocations that are specific to ** the current object (table/index pair). */ static void rbuObjIterClearStatements(RbuObjIter *pIter){ RbuUpdateStmt *pUp; sqlite3_finalize(pIter->pSelect); sqlite3_finalize(pIter->pInsert); sqlite3_finalize(pIter->pDelete); sqlite3_finalize(pIter->pTmpInsert); pUp = pIter->pRbuUpdate; while( pUp ){ RbuUpdateStmt *pTmp = pUp->pNext; sqlite3_finalize(pUp->pUpdate); sqlite3_free(pUp); pUp = pTmp; } pIter->pSelect = 0; pIter->pInsert = 0; pIter->pDelete = 0; pIter->pRbuUpdate = 0; pIter->pTmpInsert = 0; pIter->nCol = 0; } /* ** Clean up any resources allocated as part of the iterator object passed ** as the only argument. */ static void rbuObjIterFinalize(RbuObjIter *pIter){ rbuObjIterClearStatements(pIter); sqlite3_finalize(pIter->pTblIter); sqlite3_finalize(pIter->pIdxIter); rbuObjIterFreeCols(pIter); memset(pIter, 0, sizeof(RbuObjIter)); } /* ** Advance the iterator to the next position. ** ** If no error occurs, SQLITE_OK is returned and the iterator is left ** pointing to the next entry. Otherwise, an error code and message is ** left in the RBU handle passed as the first argument. A copy of the ** error code is returned. */ static int rbuObjIterNext(sqlite3rbu *p, RbuObjIter *pIter){ int rc = p->rc; if( rc==SQLITE_OK ){ /* Free any SQLite statements used while processing the previous object */ rbuObjIterClearStatements(pIter); if( pIter->zIdx==0 ){ rc = sqlite3_exec(p->dbMain, "DROP TRIGGER IF EXISTS temp.rbu_insert_tr;" "DROP TRIGGER IF EXISTS temp.rbu_update1_tr;" "DROP TRIGGER IF EXISTS temp.rbu_update2_tr;" "DROP TRIGGER IF EXISTS temp.rbu_delete_tr;" , 0, 0, &p->zErrmsg ); } if( rc==SQLITE_OK ){ if( pIter->bCleanup ){ rbuObjIterFreeCols(pIter); pIter->bCleanup = 0; rc = sqlite3_step(pIter->pTblIter); if( rc!=SQLITE_ROW ){ rc = resetAndCollectError(pIter->pTblIter, &p->zErrmsg); pIter->zTbl = 0; }else{ pIter->zTbl = (const char*)sqlite3_column_text(pIter->pTblIter, 0); |
︙ | ︙ | |||
157605 157606 157607 157608 157609 157610 157611 | } } } } } if( rc!=SQLITE_OK ){ | | | | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 157849 157850 157851 157852 157853 157854 157855 157856 157857 157858 157859 157860 157861 157862 157863 157864 157865 157866 157867 157868 157869 157870 157871 157872 157873 157874 157875 157876 157877 157878 157879 157880 157881 157882 157883 157884 157885 157886 157887 157888 157889 157890 157891 157892 157893 157894 157895 157896 157897 157898 157899 157900 157901 157902 157903 157904 157905 157906 157907 157908 157909 157910 157911 157912 157913 157914 157915 157916 157917 157918 157919 157920 157921 157922 157923 157924 157925 157926 157927 157928 157929 157930 157931 157932 157933 157934 157935 157936 157937 157938 157939 157940 157941 157942 157943 157944 157945 157946 157947 157948 157949 157950 157951 157952 157953 157954 157955 157956 157957 157958 157959 157960 157961 157962 157963 157964 157965 157966 157967 157968 157969 157970 157971 157972 157973 157974 157975 157976 157977 157978 157979 157980 157981 157982 157983 157984 157985 157986 157987 157988 157989 157990 157991 157992 157993 157994 157995 157996 157997 157998 157999 158000 158001 158002 158003 158004 158005 158006 158007 158008 158009 158010 158011 158012 158013 158014 158015 158016 158017 158018 158019 158020 158021 158022 158023 158024 158025 158026 158027 158028 158029 158030 158031 158032 158033 158034 158035 158036 158037 158038 158039 158040 158041 158042 158043 158044 158045 158046 158047 158048 158049 158050 158051 158052 158053 158054 158055 158056 158057 158058 158059 158060 158061 158062 158063 158064 158065 158066 158067 158068 158069 158070 158071 158072 158073 158074 158075 158076 158077 158078 158079 158080 158081 158082 158083 158084 158085 158086 158087 158088 158089 158090 158091 158092 158093 158094 158095 158096 158097 158098 158099 158100 158101 158102 158103 158104 158105 158106 158107 158108 158109 158110 158111 158112 158113 158114 158115 158116 158117 158118 158119 158120 158121 158122 158123 158124 158125 158126 158127 158128 158129 158130 158131 158132 158133 158134 158135 158136 158137 158138 158139 158140 158141 158142 158143 158144 158145 158146 158147 158148 158149 158150 158151 158152 158153 158154 158155 158156 158157 158158 158159 158160 158161 | } } } } } if( rc!=SQLITE_OK ){ rbuObjIterFinalize(pIter); p->rc = rc; } return rc; } /* ** Initialize the iterator structure passed as the second argument. ** ** If no error occurs, SQLITE_OK is returned and the iterator is left ** pointing to the first entry. Otherwise, an error code and message is ** left in the RBU handle passed as the first argument. A copy of the ** error code is returned. */ static int rbuObjIterFirst(sqlite3rbu *p, RbuObjIter *pIter){ int rc; memset(pIter, 0, sizeof(RbuObjIter)); rc = prepareAndCollectError(p->dbRbu, &pIter->pTblIter, &p->zErrmsg, "SELECT substr(name, 6) FROM sqlite_master " "WHERE type IN ('table', 'view') AND name LIKE 'data_%'" ); if( rc==SQLITE_OK ){ rc = prepareAndCollectError(p->dbMain, &pIter->pIdxIter, &p->zErrmsg, "SELECT name, rootpage, sql IS NULL OR substr(8, 6)=='UNIQUE' " " FROM main.sqlite_master " " WHERE type='index' AND tbl_name = ?" ); } pIter->bCleanup = 1; p->rc = rc; return rbuObjIterNext(p, pIter); } /* ** This is a wrapper around "sqlite3_mprintf(zFmt, ...)". If an OOM occurs, ** an error code is stored in the RBU handle passed as the first argument. ** ** If an error has already occurred (p->rc is already set to something other ** than SQLITE_OK), then this function returns NULL without modifying the ** stored error code. In this case it still calls sqlite3_free() on any ** printf() parameters associated with %z conversions. */ static char *rbuMPrintf(sqlite3rbu *p, const char *zFmt, ...){ char *zSql = 0; va_list ap; va_start(ap, zFmt); zSql = sqlite3_vmprintf(zFmt, ap); if( p->rc==SQLITE_OK ){ if( zSql==0 ) p->rc = SQLITE_NOMEM; }else{ sqlite3_free(zSql); zSql = 0; } va_end(ap); return zSql; } /* ** Argument zFmt is a sqlite3_mprintf() style format string. The trailing ** arguments are the usual subsitution values. This function performs ** the printf() style substitutions and executes the result as an SQL ** statement on the RBU handles database. ** ** If an error occurs, an error code and error message is stored in the ** RBU handle. If an error has already occurred when this function is ** called, it is a no-op. */ static int rbuMPrintfExec(sqlite3rbu *p, sqlite3 *db, const char *zFmt, ...){ va_list ap; char *zSql; va_start(ap, zFmt); zSql = sqlite3_vmprintf(zFmt, ap); if( p->rc==SQLITE_OK ){ if( zSql==0 ){ p->rc = SQLITE_NOMEM; }else{ p->rc = sqlite3_exec(db, zSql, 0, 0, &p->zErrmsg); } } sqlite3_free(zSql); va_end(ap); return p->rc; } /* ** Attempt to allocate and return a pointer to a zeroed block of nByte ** bytes. ** ** If an error (i.e. an OOM condition) occurs, return NULL and leave an ** error code in the rbu handle passed as the first argument. Or, if an ** error has already occurred when this function is called, return NULL ** immediately without attempting the allocation or modifying the stored ** error code. */ static void *rbuMalloc(sqlite3rbu *p, int nByte){ void *pRet = 0; if( p->rc==SQLITE_OK ){ assert( nByte>0 ); pRet = sqlite3_malloc(nByte); if( pRet==0 ){ p->rc = SQLITE_NOMEM; }else{ memset(pRet, 0, nByte); } } return pRet; } /* ** Allocate and zero the pIter->azTblCol[] and abTblPk[] arrays so that ** there is room for at least nCol elements. If an OOM occurs, store an ** error code in the RBU handle passed as the first argument. */ static void rbuAllocateIterArrays(sqlite3rbu *p, RbuObjIter *pIter, int nCol){ int nByte = (2*sizeof(char*) + sizeof(int) + 3*sizeof(u8)) * nCol; char **azNew; azNew = (char**)rbuMalloc(p, nByte); if( azNew ){ pIter->azTblCol = azNew; pIter->azTblType = &azNew[nCol]; pIter->aiSrcOrder = (int*)&pIter->azTblType[nCol]; pIter->abTblPk = (u8*)&pIter->aiSrcOrder[nCol]; pIter->abNotNull = (u8*)&pIter->abTblPk[nCol]; pIter->abIndexed = (u8*)&pIter->abNotNull[nCol]; } } /* ** The first argument must be a nul-terminated string. This function ** returns a copy of the string in memory obtained from sqlite3_malloc(). ** It is the responsibility of the caller to eventually free this memory ** using sqlite3_free(). ** ** If an OOM condition is encountered when attempting to allocate memory, ** output variable (*pRc) is set to SQLITE_NOMEM before returning. Otherwise, ** if the allocation succeeds, (*pRc) is left unchanged. */ static char *rbuStrndup(const char *zStr, int *pRc){ char *zRet = 0; assert( *pRc==SQLITE_OK ); if( zStr ){ int nCopy = strlen(zStr) + 1; zRet = (char*)sqlite3_malloc(nCopy); if( zRet ){ memcpy(zRet, zStr, nCopy); }else{ *pRc = SQLITE_NOMEM; } } return zRet; } /* ** Finalize the statement passed as the second argument. ** ** If the sqlite3_finalize() call indicates that an error occurs, and the ** rbu handle error code is not already set, set the error code and error ** message accordingly. */ static void rbuFinalize(sqlite3rbu *p, sqlite3_stmt *pStmt){ sqlite3 *db = sqlite3_db_handle(pStmt); int rc = sqlite3_finalize(pStmt); if( p->rc==SQLITE_OK && rc!=SQLITE_OK ){ p->rc = rc; p->zErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(db)); } } /* Determine the type of a table. ** ** peType is of type (int*), a pointer to an output parameter of type ** (int). This call sets the output parameter as follows, depending ** on the type of the table specified by parameters dbName and zTbl. ** ** RBU_PK_NOTABLE: No such table. ** RBU_PK_NONE: Table has an implicit rowid. ** RBU_PK_IPK: Table has an explicit IPK column. ** RBU_PK_EXTERNAL: Table has an external PK index. ** RBU_PK_WITHOUT_ROWID: Table is WITHOUT ROWID. ** RBU_PK_VTAB: Table is a virtual table. ** ** Argument *piPk is also of type (int*), and also points to an output ** parameter. Unless the table has an external primary key index ** (i.e. unless *peType is set to 3), then *piPk is set to zero. Or, ** if the table does have an external primary key index, then *piPk ** is set to the root page number of the primary key index before ** returning. ** ** ALGORITHM: ** ** if( no entry exists in sqlite_master ){ ** return RBU_PK_NOTABLE ** }else if( sql for the entry starts with "CREATE VIRTUAL" ){ ** return RBU_PK_VTAB ** }else if( "PRAGMA index_list()" for the table contains a "pk" index ){ ** if( the index that is the pk exists in sqlite_master ){ ** *piPK = rootpage of that index. ** return RBU_PK_EXTERNAL ** }else{ ** return RBU_PK_WITHOUT_ROWID ** } ** }else if( "PRAGMA table_info()" lists one or more "pk" columns ){ ** return RBU_PK_IPK ** }else{ ** return RBU_PK_NONE ** } */ static void rbuTableType( sqlite3rbu *p, const char *zTab, int *peType, int *piTnum, int *piPk ){ /* ** 0) SELECT count(*) FROM sqlite_master where name=%Q AND IsVirtual(%Q) ** 1) PRAGMA index_list = ? ** 2) SELECT count(*) FROM sqlite_master where name=%Q ** 3) PRAGMA table_info = ? */ sqlite3_stmt *aStmt[4] = {0, 0, 0, 0}; *peType = RBU_PK_NOTABLE; *piPk = 0; assert( p->rc==SQLITE_OK ); p->rc = prepareFreeAndCollectError(p->dbMain, &aStmt[0], &p->zErrmsg, sqlite3_mprintf( "SELECT (sql LIKE 'create virtual%%'), rootpage" " FROM sqlite_master" " WHERE name=%Q", zTab )); if( p->rc!=SQLITE_OK || sqlite3_step(aStmt[0])!=SQLITE_ROW ){ /* Either an error, or no such table. */ goto rbuTableType_end; } if( sqlite3_column_int(aStmt[0], 0) ){ *peType = RBU_PK_VTAB; /* virtual table */ goto rbuTableType_end; } *piTnum = sqlite3_column_int(aStmt[0], 1); p->rc = prepareFreeAndCollectError(p->dbMain, &aStmt[1], &p->zErrmsg, sqlite3_mprintf("PRAGMA index_list=%Q",zTab) ); if( p->rc ) goto rbuTableType_end; while( sqlite3_step(aStmt[1])==SQLITE_ROW ){ const u8 *zOrig = sqlite3_column_text(aStmt[1], 3); const u8 *zIdx = sqlite3_column_text(aStmt[1], 1); if( zOrig && zIdx && zOrig[0]=='p' ){ p->rc = prepareFreeAndCollectError(p->dbMain, &aStmt[2], &p->zErrmsg, sqlite3_mprintf( "SELECT rootpage FROM sqlite_master WHERE name = %Q", zIdx )); if( p->rc==SQLITE_OK ){ if( sqlite3_step(aStmt[2])==SQLITE_ROW ){ *piPk = sqlite3_column_int(aStmt[2], 0); *peType = RBU_PK_EXTERNAL; }else{ *peType = RBU_PK_WITHOUT_ROWID; } } goto rbuTableType_end; } } p->rc = prepareFreeAndCollectError(p->dbMain, &aStmt[3], &p->zErrmsg, sqlite3_mprintf("PRAGMA table_info=%Q",zTab) ); if( p->rc==SQLITE_OK ){ while( sqlite3_step(aStmt[3])==SQLITE_ROW ){ if( sqlite3_column_int(aStmt[3],5)>0 ){ *peType = RBU_PK_IPK; /* explicit IPK column */ goto rbuTableType_end; } } *peType = RBU_PK_NONE; } rbuTableType_end: { int i; for(i=0; i<sizeof(aStmt)/sizeof(aStmt[0]); i++){ rbuFinalize(p, aStmt[i]); } } } /* ** This is a helper function for rbuObjIterCacheTableInfo(). It populates ** the pIter->abIndexed[] array. */ static void rbuObjIterCacheIndexedCols(sqlite3rbu *p, RbuObjIter *pIter){ sqlite3_stmt *pList = 0; int bIndex = 0; if( p->rc==SQLITE_OK ){ memcpy(pIter->abIndexed, pIter->abTblPk, sizeof(u8)*pIter->nTblCol); p->rc = prepareFreeAndCollectError(p->dbMain, &pList, &p->zErrmsg, sqlite3_mprintf("PRAGMA main.index_list = %Q", pIter->zTbl) |
︙ | ︙ | |||
157924 157925 157926 157927 157928 157929 157930 | p->rc = prepareFreeAndCollectError(p->dbMain, &pXInfo, &p->zErrmsg, sqlite3_mprintf("PRAGMA main.index_xinfo = %Q", zIdx) ); while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXInfo) ){ int iCid = sqlite3_column_int(pXInfo, 1); if( iCid>=0 ) pIter->abIndexed[iCid] = 1; } | | | | | | | | | | | | | | | | | | | | | | 158169 158170 158171 158172 158173 158174 158175 158176 158177 158178 158179 158180 158181 158182 158183 158184 158185 158186 158187 158188 158189 158190 158191 158192 158193 158194 158195 158196 158197 158198 158199 158200 158201 158202 158203 158204 158205 158206 158207 158208 158209 158210 158211 158212 158213 158214 158215 158216 158217 158218 158219 158220 158221 158222 158223 158224 158225 158226 158227 158228 158229 158230 158231 158232 158233 158234 158235 158236 158237 158238 158239 158240 158241 158242 158243 158244 158245 158246 158247 158248 158249 158250 158251 158252 158253 158254 158255 | p->rc = prepareFreeAndCollectError(p->dbMain, &pXInfo, &p->zErrmsg, sqlite3_mprintf("PRAGMA main.index_xinfo = %Q", zIdx) ); while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXInfo) ){ int iCid = sqlite3_column_int(pXInfo, 1); if( iCid>=0 ) pIter->abIndexed[iCid] = 1; } rbuFinalize(p, pXInfo); bIndex = 1; } rbuFinalize(p, pList); if( bIndex==0 ) pIter->abIndexed = 0; } /* ** If they are not already populated, populate the pIter->azTblCol[], ** pIter->abTblPk[], pIter->nTblCol and pIter->bRowid variables according to ** the table (not index) that the iterator currently points to. ** ** Return SQLITE_OK if successful, or an SQLite error code otherwise. If ** an error does occur, an error code and error message are also left in ** the RBU handle. */ static int rbuObjIterCacheTableInfo(sqlite3rbu *p, RbuObjIter *pIter){ if( pIter->azTblCol==0 ){ sqlite3_stmt *pStmt = 0; int nCol = 0; int i; /* for() loop iterator variable */ int bRbuRowid = 0; /* If input table has column "rbu_rowid" */ int iOrder = 0; int iTnum = 0; /* Figure out the type of table this step will deal with. */ assert( pIter->eType==0 ); rbuTableType(p, pIter->zTbl, &pIter->eType, &iTnum, &pIter->iPkTnum); if( p->rc==SQLITE_OK && pIter->eType==RBU_PK_NOTABLE ){ p->rc = SQLITE_ERROR; p->zErrmsg = sqlite3_mprintf("no such table: %s", pIter->zTbl); } if( p->rc ) return p->rc; if( pIter->zIdx==0 ) pIter->iTnum = iTnum; assert( pIter->eType==RBU_PK_NONE || pIter->eType==RBU_PK_IPK || pIter->eType==RBU_PK_EXTERNAL || pIter->eType==RBU_PK_WITHOUT_ROWID || pIter->eType==RBU_PK_VTAB ); /* Populate the azTblCol[] and nTblCol variables based on the columns ** of the input table. Ignore any input table columns that begin with ** "rbu_". */ p->rc = prepareFreeAndCollectError(p->dbRbu, &pStmt, &p->zErrmsg, sqlite3_mprintf("SELECT * FROM 'data_%q'", pIter->zTbl) ); if( p->rc==SQLITE_OK ){ nCol = sqlite3_column_count(pStmt); rbuAllocateIterArrays(p, pIter, nCol); } for(i=0; p->rc==SQLITE_OK && i<nCol; i++){ const char *zName = (const char*)sqlite3_column_name(pStmt, i); if( sqlite3_strnicmp("rbu_", zName, 4) ){ char *zCopy = rbuStrndup(zName, &p->rc); pIter->aiSrcOrder[pIter->nTblCol] = pIter->nTblCol; pIter->azTblCol[pIter->nTblCol++] = zCopy; } else if( 0==sqlite3_stricmp("rbu_rowid", zName) ){ bRbuRowid = 1; } } sqlite3_finalize(pStmt); pStmt = 0; if( p->rc==SQLITE_OK && bRbuRowid!=(pIter->eType==RBU_PK_VTAB || pIter->eType==RBU_PK_NONE) ){ p->rc = SQLITE_ERROR; p->zErrmsg = sqlite3_mprintf( "table data_%q %s rbu_rowid column", pIter->zTbl, (bRbuRowid ? "may not have" : "requires") ); } /* Check that all non-HIDDEN columns in the destination table are also ** present in the input table. Populate the abTblPk[], azTblType[] and ** aiTblOrder[] arrays at the same time. */ if( p->rc==SQLITE_OK ){ |
︙ | ︙ | |||
158029 158030 158031 158032 158033 158034 158035 | const char *zType = (const char*)sqlite3_column_text(pStmt, 2); if( i!=iOrder ){ SWAP(int, pIter->aiSrcOrder[i], pIter->aiSrcOrder[iOrder]); SWAP(char*, pIter->azTblCol[i], pIter->azTblCol[iOrder]); } | | | | | | | | | | | | | | | 158274 158275 158276 158277 158278 158279 158280 158281 158282 158283 158284 158285 158286 158287 158288 158289 158290 158291 158292 158293 158294 158295 158296 158297 158298 158299 158300 158301 158302 158303 158304 158305 158306 158307 158308 158309 158310 158311 158312 158313 158314 158315 158316 158317 158318 158319 158320 158321 158322 158323 158324 158325 158326 158327 158328 158329 158330 158331 158332 158333 158334 158335 158336 158337 158338 158339 158340 158341 158342 158343 158344 158345 158346 158347 158348 158349 158350 158351 158352 158353 | const char *zType = (const char*)sqlite3_column_text(pStmt, 2); if( i!=iOrder ){ SWAP(int, pIter->aiSrcOrder[i], pIter->aiSrcOrder[iOrder]); SWAP(char*, pIter->azTblCol[i], pIter->azTblCol[iOrder]); } pIter->azTblType[iOrder] = rbuStrndup(zType, &p->rc); pIter->abTblPk[iOrder] = (iPk!=0); pIter->abNotNull[iOrder] = (u8)bNotNull || (iPk!=0); iOrder++; } } rbuFinalize(p, pStmt); rbuObjIterCacheIndexedCols(p, pIter); assert( pIter->eType!=RBU_PK_VTAB || pIter->abIndexed==0 ); } return p->rc; } /* ** This function constructs and returns a pointer to a nul-terminated ** string containing some SQL clause or list based on one or more of the ** column names currently stored in the pIter->azTblCol[] array. */ static char *rbuObjIterGetCollist( sqlite3rbu *p, /* RBU object */ RbuObjIter *pIter /* Object iterator for column names */ ){ char *zList = 0; const char *zSep = ""; int i; for(i=0; i<pIter->nTblCol; i++){ const char *z = pIter->azTblCol[i]; zList = rbuMPrintf(p, "%z%s\"%w\"", zList, zSep, z); zSep = ", "; } return zList; } /* ** This function is used to create a SELECT list (the list of SQL ** expressions that follows a SELECT keyword) for a SELECT statement ** used to read from an data_xxx or rbu_tmp_xxx table while updating the ** index object currently indicated by the iterator object passed as the ** second argument. A "PRAGMA index_xinfo = <idxname>" statement is used ** to obtain the required information. ** ** If the index is of the following form: ** ** CREATE INDEX i1 ON t1(c, b COLLATE nocase); ** ** and "t1" is a table with an explicit INTEGER PRIMARY KEY column ** "ipk", the returned string is: ** ** "`c` COLLATE 'BINARY', `b` COLLATE 'NOCASE', `ipk` COLLATE 'BINARY'" ** ** As well as the returned string, three other malloc'd strings are ** returned via output parameters. As follows: ** ** pzImposterCols: ... ** pzImposterPk: ... ** pzWhere: ... */ static char *rbuObjIterGetIndexCols( sqlite3rbu *p, /* RBU object */ RbuObjIter *pIter, /* Object iterator for column names */ char **pzImposterCols, /* OUT: Columns for imposter table */ char **pzImposterPk, /* OUT: Imposter PK clause */ char **pzWhere, /* OUT: WHERE clause */ int *pnBind /* OUT: Trbul number of columns */ ){ int rc = p->rc; /* Error code */ int rc2; /* sqlite3_finalize() return code */ char *zRet = 0; /* String to return */ char *zImpCols = 0; /* String to return via *pzImposterCols */ char *zImpPK = 0; /* String to return via *pzImposterPK */ char *zWhere = 0; /* String to return via *pzWhere */ |
︙ | ︙ | |||
158123 158124 158125 158126 158127 158128 158129 | int bDesc = sqlite3_column_int(pXInfo, 3); const char *zCollate = (const char*)sqlite3_column_text(pXInfo, 4); const char *zCol; const char *zType; if( iCid<0 ){ /* An integer primary key. If the table has an explicit IPK, use | | | | | | | | 158368 158369 158370 158371 158372 158373 158374 158375 158376 158377 158378 158379 158380 158381 158382 158383 158384 158385 158386 158387 158388 158389 158390 158391 158392 158393 158394 158395 158396 158397 158398 158399 158400 158401 158402 158403 158404 158405 158406 158407 158408 | int bDesc = sqlite3_column_int(pXInfo, 3); const char *zCollate = (const char*)sqlite3_column_text(pXInfo, 4); const char *zCol; const char *zType; if( iCid<0 ){ /* An integer primary key. If the table has an explicit IPK, use ** its name. Otherwise, use "rbu_rowid". */ if( pIter->eType==RBU_PK_IPK ){ int i; for(i=0; pIter->abTblPk[i]==0; i++); assert( i<pIter->nTblCol ); zCol = pIter->azTblCol[i]; }else{ zCol = "rbu_rowid"; } zType = "INTEGER"; }else{ zCol = pIter->azTblCol[iCid]; zType = pIter->azTblType[iCid]; } zRet = sqlite3_mprintf("%z%s\"%w\" COLLATE %Q", zRet, zCom, zCol, zCollate); if( pIter->bUnique==0 || sqlite3_column_int(pXInfo, 5) ){ const char *zOrder = (bDesc ? " DESC" : ""); zImpPK = sqlite3_mprintf("%z%s\"rbu_imp_%d%w\"%s", zImpPK, zCom, nBind, zCol, zOrder ); } zImpCols = sqlite3_mprintf("%z%s\"rbu_imp_%d%w\" %s COLLATE %Q", zImpCols, zCom, nBind, zCol, zType, zCollate ); zWhere = sqlite3_mprintf( "%z%s\"rbu_imp_%d%w\" IS ?", zWhere, zAnd, nBind, zCol ); if( zRet==0 || zImpPK==0 || zImpCols==0 || zWhere==0 ) rc = SQLITE_NOMEM; zCom = ", "; zAnd = " AND "; nBind++; } |
︙ | ︙ | |||
158187 158188 158189 158190 158191 158192 158193 | ** Assuming the current table columns are "a", "b" and "c", and the zObj ** paramter is passed "old", return a string of the form: ** ** "old.a, old.b, old.b" ** ** With the column names escaped. ** | | | | | | 158432 158433 158434 158435 158436 158437 158438 158439 158440 158441 158442 158443 158444 158445 158446 158447 158448 158449 158450 158451 | ** Assuming the current table columns are "a", "b" and "c", and the zObj ** paramter is passed "old", return a string of the form: ** ** "old.a, old.b, old.b" ** ** With the column names escaped. ** ** For tables with implicit rowids - RBU_PK_EXTERNAL and RBU_PK_NONE, append ** the text ", old._rowid_" to the returned value. */ static char *rbuObjIterGetOldlist( sqlite3rbu *p, RbuObjIter *pIter, const char *zObj ){ char *zList = 0; if( p->rc==SQLITE_OK && pIter->abIndexed ){ const char *zS = ""; int i; for(i=0; i<pIter->nTblCol; i++){ |
︙ | ︙ | |||
158214 158215 158216 158217 158218 158219 158220 | if( zList==0 ){ p->rc = SQLITE_NOMEM; break; } } /* For a table with implicit rowids, append "old._rowid_" to the list. */ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 158459 158460 158461 158462 158463 158464 158465 158466 158467 158468 158469 158470 158471 158472 158473 158474 158475 158476 158477 158478 158479 158480 158481 158482 158483 158484 158485 158486 158487 158488 158489 158490 158491 158492 158493 158494 158495 158496 158497 158498 158499 158500 158501 158502 158503 158504 158505 158506 158507 158508 158509 158510 158511 158512 158513 158514 158515 158516 158517 158518 158519 158520 158521 158522 158523 158524 158525 158526 158527 158528 158529 158530 158531 158532 158533 158534 158535 158536 158537 158538 158539 158540 158541 158542 158543 158544 158545 158546 158547 158548 158549 158550 158551 158552 158553 158554 158555 158556 158557 158558 158559 158560 158561 158562 158563 158564 158565 158566 158567 158568 158569 158570 158571 158572 158573 158574 158575 158576 158577 158578 158579 158580 158581 158582 158583 158584 158585 158586 158587 158588 158589 158590 158591 158592 158593 158594 158595 158596 158597 158598 158599 158600 158601 158602 158603 158604 158605 158606 158607 158608 158609 158610 158611 158612 158613 158614 158615 158616 158617 158618 158619 158620 158621 158622 158623 158624 158625 158626 158627 158628 158629 | if( zList==0 ){ p->rc = SQLITE_NOMEM; break; } } /* For a table with implicit rowids, append "old._rowid_" to the list. */ if( pIter->eType==RBU_PK_EXTERNAL || pIter->eType==RBU_PK_NONE ){ zList = rbuMPrintf(p, "%z, %s._rowid_", zList, zObj); } } return zList; } /* ** Return an expression that can be used in a WHERE clause to match the ** primary key of the current table. For example, if the table is: ** ** CREATE TABLE t1(a, b, c, PRIMARY KEY(b, c)); ** ** Return the string: ** ** "b = ?1 AND c = ?2" */ static char *rbuObjIterGetWhere( sqlite3rbu *p, RbuObjIter *pIter ){ char *zList = 0; if( pIter->eType==RBU_PK_VTAB || pIter->eType==RBU_PK_NONE ){ zList = rbuMPrintf(p, "_rowid_ = ?%d", pIter->nTblCol+1); }else if( pIter->eType==RBU_PK_EXTERNAL ){ const char *zSep = ""; int i; for(i=0; i<pIter->nTblCol; i++){ if( pIter->abTblPk[i] ){ zList = rbuMPrintf(p, "%z%sc%d=?%d", zList, zSep, i, i+1); zSep = " AND "; } } zList = rbuMPrintf(p, "_rowid_ = (SELECT id FROM rbu_imposter2 WHERE %z)", zList ); }else{ const char *zSep = ""; int i; for(i=0; i<pIter->nTblCol; i++){ if( pIter->abTblPk[i] ){ const char *zCol = pIter->azTblCol[i]; zList = rbuMPrintf(p, "%z%s\"%w\"=?%d", zList, zSep, zCol, i+1); zSep = " AND "; } } } return zList; } /* ** The SELECT statement iterating through the keys for the current object ** (p->objiter.pSelect) currently points to a valid row. However, there ** is something wrong with the rbu_control value in the rbu_control value ** stored in the (p->nCol+1)'th column. Set the error code and error message ** of the RBU handle to something reflecting this. */ static void rbuBadControlError(sqlite3rbu *p){ p->rc = SQLITE_ERROR; p->zErrmsg = sqlite3_mprintf("invalid rbu_control value"); } /* ** Return a nul-terminated string containing the comma separated list of ** assignments that should be included following the "SET" keyword of ** an UPDATE statement used to update the table object that the iterator ** passed as the second argument currently points to if the rbu_control ** column of the data_xxx table entry is set to zMask. ** ** The memory for the returned string is obtained from sqlite3_malloc(). ** It is the responsibility of the caller to eventually free it using ** sqlite3_free(). ** ** If an OOM error is encountered when allocating space for the new ** string, an error code is left in the rbu handle passed as the first ** argument and NULL is returned. Or, if an error has already occurred ** when this function is called, NULL is returned immediately, without ** attempting the allocation or modifying the stored error code. */ static char *rbuObjIterGetSetlist( sqlite3rbu *p, RbuObjIter *pIter, const char *zMask ){ char *zList = 0; if( p->rc==SQLITE_OK ){ int i; if( strlen(zMask)!=pIter->nTblCol ){ rbuBadControlError(p); }else{ const char *zSep = ""; for(i=0; i<pIter->nTblCol; i++){ char c = zMask[pIter->aiSrcOrder[i]]; if( c=='x' ){ zList = rbuMPrintf(p, "%z%s\"%w\"=?%d", zList, zSep, pIter->azTblCol[i], i+1 ); zSep = ", "; } if( c=='d' ){ zList = rbuMPrintf(p, "%z%s\"%w\"=rbu_delta(\"%w\", ?%d)", zList, zSep, pIter->azTblCol[i], pIter->azTblCol[i], i+1 ); zSep = ", "; } } } } return zList; } /* ** Return a nul-terminated string consisting of nByte comma separated ** "?" expressions. For example, if nByte is 3, return a pointer to ** a buffer containing the string "?,?,?". ** ** The memory for the returned string is obtained from sqlite3_malloc(). ** It is the responsibility of the caller to eventually free it using ** sqlite3_free(). ** ** If an OOM error is encountered when allocating space for the new ** string, an error code is left in the rbu handle passed as the first ** argument and NULL is returned. Or, if an error has already occurred ** when this function is called, NULL is returned immediately, without ** attempting the allocation or modifying the stored error code. */ static char *rbuObjIterGetBindlist(sqlite3rbu *p, int nBind){ char *zRet = 0; int nByte = nBind*2 + 1; zRet = (char*)rbuMalloc(p, nByte); if( zRet ){ int i; for(i=0; i<nBind; i++){ zRet[i*2] = '?'; zRet[i*2+1] = (i+1==nBind) ? '\0' : ','; } } return zRet; } /* ** The iterator currently points to a table (not index) of type ** RBU_PK_WITHOUT_ROWID. This function creates the PRIMARY KEY ** declaration for the corresponding imposter table. For example, ** if the iterator points to a table created as: ** ** CREATE TABLE t1(a, b, c, PRIMARY KEY(b, a DESC)) WITHOUT ROWID ** ** this function returns: ** ** PRIMARY KEY("b", "a" DESC) */ static char *rbuWithoutRowidPK(sqlite3rbu *p, RbuObjIter *pIter){ char *z = 0; assert( pIter->zIdx==0 ); if( p->rc==SQLITE_OK ){ const char *zSep = "PRIMARY KEY("; sqlite3_stmt *pXList = 0; /* PRAGMA index_list = (pIter->zTbl) */ sqlite3_stmt *pXInfo = 0; /* PRAGMA index_xinfo = <pk-index> */ |
︙ | ︙ | |||
158393 158394 158395 158396 158397 158398 158399 | p->rc = prepareFreeAndCollectError(p->dbMain, &pXInfo, &p->zErrmsg, sqlite3_mprintf("PRAGMA main.index_xinfo = %Q", zIdx) ); } break; } } | | | | | | | | | | 158638 158639 158640 158641 158642 158643 158644 158645 158646 158647 158648 158649 158650 158651 158652 158653 158654 158655 158656 158657 158658 158659 158660 158661 158662 158663 158664 158665 158666 158667 158668 158669 158670 158671 158672 158673 158674 158675 158676 158677 158678 158679 158680 158681 158682 158683 158684 158685 158686 158687 158688 158689 | p->rc = prepareFreeAndCollectError(p->dbMain, &pXInfo, &p->zErrmsg, sqlite3_mprintf("PRAGMA main.index_xinfo = %Q", zIdx) ); } break; } } rbuFinalize(p, pXList); while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXInfo) ){ if( sqlite3_column_int(pXInfo, 5) ){ /* int iCid = sqlite3_column_int(pXInfo, 0); */ const char *zCol = (const char*)sqlite3_column_text(pXInfo, 2); const char *zDesc = sqlite3_column_int(pXInfo, 3) ? " DESC" : ""; z = rbuMPrintf(p, "%z%s\"%w\"%s", z, zSep, zCol, zDesc); zSep = ", "; } } z = rbuMPrintf(p, "%z)", z); rbuFinalize(p, pXInfo); } return z; } /* ** This function creates the second imposter table used when writing to ** a table b-tree where the table has an external primary key. If the ** iterator passed as the second argument does not currently point to ** a table (not index) with an external primary key, this function is a ** no-op. ** ** Assuming the iterator does point to a table with an external PK, this ** function creates a WITHOUT ROWID imposter table named "rbu_imposter2" ** used to access that PK index. For example, if the target table is ** declared as follows: ** ** CREATE TABLE t1(a, b TEXT, c REAL, PRIMARY KEY(b, c)); ** ** then the imposter table schema is: ** ** CREATE TABLE rbu_imposter2(c1 TEXT, c2 REAL, id INTEGER) WITHOUT ROWID; ** */ static void rbuCreateImposterTable2(sqlite3rbu *p, RbuObjIter *pIter){ if( p->rc==SQLITE_OK && pIter->eType==RBU_PK_EXTERNAL ){ int tnum = pIter->iPkTnum; /* Root page of PK index */ sqlite3_stmt *pQuery = 0; /* SELECT name ... WHERE rootpage = $tnum */ const char *zIdx = 0; /* Name of PK index */ sqlite3_stmt *pXInfo = 0; /* PRAGMA main.index_xinfo = $zIdx */ const char *zComma = ""; char *zCols = 0; /* Used to build up list of table cols */ char *zPk = 0; /* Used to build up table PK declaration */ |
︙ | ︙ | |||
158456 158457 158458 158459 158460 158461 158462 | } } if( zIdx ){ p->rc = prepareFreeAndCollectError(p->dbMain, &pXInfo, &p->zErrmsg, sqlite3_mprintf("PRAGMA main.index_xinfo = %Q", zIdx) ); } | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 158701 158702 158703 158704 158705 158706 158707 158708 158709 158710 158711 158712 158713 158714 158715 158716 158717 158718 158719 158720 158721 158722 158723 158724 158725 158726 158727 158728 158729 158730 158731 158732 158733 158734 158735 158736 158737 158738 158739 158740 158741 158742 158743 158744 158745 158746 158747 158748 158749 158750 158751 158752 158753 158754 158755 158756 158757 158758 158759 158760 158761 158762 158763 158764 158765 158766 158767 158768 158769 158770 158771 158772 158773 158774 158775 158776 158777 158778 158779 158780 158781 158782 158783 158784 158785 158786 158787 158788 158789 158790 158791 158792 158793 158794 158795 158796 158797 158798 158799 158800 158801 158802 158803 158804 158805 158806 158807 158808 158809 158810 158811 158812 158813 158814 158815 158816 158817 158818 158819 158820 158821 158822 158823 158824 158825 158826 158827 158828 158829 158830 158831 158832 158833 158834 158835 158836 158837 158838 158839 158840 158841 | } } if( zIdx ){ p->rc = prepareFreeAndCollectError(p->dbMain, &pXInfo, &p->zErrmsg, sqlite3_mprintf("PRAGMA main.index_xinfo = %Q", zIdx) ); } rbuFinalize(p, pQuery); while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXInfo) ){ int bKey = sqlite3_column_int(pXInfo, 5); if( bKey ){ int iCid = sqlite3_column_int(pXInfo, 1); int bDesc = sqlite3_column_int(pXInfo, 3); const char *zCollate = (const char*)sqlite3_column_text(pXInfo, 4); zCols = rbuMPrintf(p, "%z%sc%d %s COLLATE %s", zCols, zComma, iCid, pIter->azTblType[iCid], zCollate ); zPk = rbuMPrintf(p, "%z%sc%d%s", zPk, zComma, iCid, bDesc?" DESC":""); zComma = ", "; } } zCols = rbuMPrintf(p, "%z, id INTEGER", zCols); rbuFinalize(p, pXInfo); sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 1, tnum); rbuMPrintfExec(p, p->dbMain, "CREATE TABLE rbu_imposter2(%z, PRIMARY KEY(%z)) WITHOUT ROWID", zCols, zPk ); sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 0, 0); } } /* ** If an error has already occurred when this function is called, it ** immediately returns zero (without doing any work). Or, if an error ** occurs during the execution of this function, it sets the error code ** in the sqlite3rbu object indicated by the first argument and returns ** zero. ** ** The iterator passed as the second argument is guaranteed to point to ** a table (not an index) when this function is called. This function ** attempts to create any imposter table required to write to the main ** table b-tree of the table before returning. Non-zero is returned if ** an imposter table are created, or zero otherwise. ** ** An imposter table is required in all cases except RBU_PK_VTAB. Only ** virtual tables are written to directly. The imposter table has the ** same schema as the actual target table (less any UNIQUE constraints). ** More precisely, the "same schema" means the same columns, types, ** collation sequences. For tables that do not have an external PRIMARY ** KEY, it also means the same PRIMARY KEY declaration. */ static void rbuCreateImposterTable(sqlite3rbu *p, RbuObjIter *pIter){ if( p->rc==SQLITE_OK && pIter->eType!=RBU_PK_VTAB ){ int tnum = pIter->iTnum; const char *zComma = ""; char *zSql = 0; int iCol; sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 0, 1); for(iCol=0; p->rc==SQLITE_OK && iCol<pIter->nTblCol; iCol++){ const char *zPk = ""; const char *zCol = pIter->azTblCol[iCol]; const char *zColl = 0; p->rc = sqlite3_table_column_metadata( p->dbMain, "main", pIter->zTbl, zCol, 0, &zColl, 0, 0, 0 ); if( pIter->eType==RBU_PK_IPK && pIter->abTblPk[iCol] ){ /* If the target table column is an "INTEGER PRIMARY KEY", add ** "PRIMARY KEY" to the imposter table column declaration. */ zPk = "PRIMARY KEY "; } zSql = rbuMPrintf(p, "%z%s\"%w\" %s %sCOLLATE %s%s", zSql, zComma, zCol, pIter->azTblType[iCol], zPk, zColl, (pIter->abNotNull[iCol] ? " NOT NULL" : "") ); zComma = ", "; } if( pIter->eType==RBU_PK_WITHOUT_ROWID ){ char *zPk = rbuWithoutRowidPK(p, pIter); if( zPk ){ zSql = rbuMPrintf(p, "%z, %z", zSql, zPk); } } sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 1, tnum); rbuMPrintfExec(p, p->dbMain, "CREATE TABLE \"rbu_imp_%w\"(%z)%s", pIter->zTbl, zSql, (pIter->eType==RBU_PK_WITHOUT_ROWID ? " WITHOUT ROWID" : "") ); sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 0, 0); } } /* ** Prepare a statement used to insert rows into the "rbu_tmp_xxx" table. ** Specifically a statement of the form: ** ** INSERT INTO rbu_tmp_xxx VALUES(?, ?, ? ...); ** ** The number of bound variables is equal to the number of columns in ** the target table, plus one (for the rbu_control column), plus one more ** (for the rbu_rowid column) if the target table is an implicit IPK or ** virtual table. */ static void rbuObjIterPrepareTmpInsert( sqlite3rbu *p, RbuObjIter *pIter, const char *zCollist, const char *zRbuRowid ){ int bRbuRowid = (pIter->eType==RBU_PK_EXTERNAL || pIter->eType==RBU_PK_NONE); char *zBind = rbuObjIterGetBindlist(p, pIter->nTblCol + 1 + bRbuRowid); if( zBind ){ assert( pIter->pTmpInsert==0 ); p->rc = prepareFreeAndCollectError( p->dbRbu, &pIter->pTmpInsert, &p->zErrmsg, sqlite3_mprintf( "INSERT INTO %s.'rbu_tmp_%q'(rbu_control,%s%s) VALUES(%z)", p->zStateDb, pIter->zTbl, zCollist, zRbuRowid, zBind )); } } static void rbuTmpInsertFunc( sqlite3_context *pCtx, int nVal, sqlite3_value **apVal ){ sqlite3rbu *p = sqlite3_user_data(pCtx); int rc = SQLITE_OK; int i; for(i=0; rc==SQLITE_OK && i<nVal; i++){ rc = sqlite3_bind_value(p->objiter.pTmpInsert, i+1, apVal[i]); } if( rc==SQLITE_OK ){ |
︙ | ︙ | |||
158604 158605 158606 158607 158608 158609 158610 | } /* ** Ensure that the SQLite statement handles required to update the ** target database object currently indicated by the iterator passed ** as the second argument are available. */ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 158849 158850 158851 158852 158853 158854 158855 158856 158857 158858 158859 158860 158861 158862 158863 158864 158865 158866 158867 158868 158869 158870 158871 158872 158873 158874 158875 158876 158877 158878 158879 158880 158881 158882 158883 158884 158885 158886 158887 158888 158889 158890 158891 158892 158893 158894 158895 158896 158897 158898 158899 158900 158901 158902 158903 158904 158905 158906 158907 158908 158909 158910 158911 158912 158913 158914 158915 158916 158917 158918 158919 158920 158921 158922 158923 158924 158925 158926 158927 158928 158929 158930 158931 158932 158933 158934 158935 158936 158937 158938 158939 158940 158941 158942 158943 158944 158945 158946 158947 158948 158949 158950 158951 158952 158953 158954 158955 158956 158957 158958 158959 158960 158961 158962 158963 158964 158965 158966 158967 158968 158969 158970 158971 158972 158973 158974 158975 158976 158977 158978 158979 158980 158981 158982 158983 158984 158985 158986 158987 158988 158989 158990 158991 158992 158993 158994 158995 158996 158997 158998 158999 159000 159001 159002 159003 159004 159005 159006 159007 159008 159009 159010 159011 159012 159013 159014 159015 159016 159017 159018 159019 159020 159021 159022 159023 159024 159025 159026 159027 159028 159029 159030 159031 159032 159033 159034 159035 159036 159037 159038 159039 159040 159041 159042 159043 159044 159045 159046 159047 159048 159049 159050 159051 159052 159053 159054 159055 159056 159057 159058 159059 159060 159061 159062 159063 159064 159065 159066 159067 159068 159069 159070 159071 159072 159073 159074 159075 159076 159077 159078 159079 159080 159081 159082 159083 159084 159085 159086 159087 159088 159089 159090 159091 159092 159093 159094 159095 159096 159097 159098 159099 159100 159101 159102 159103 159104 159105 159106 159107 159108 159109 159110 159111 159112 159113 159114 159115 159116 159117 159118 159119 159120 159121 159122 159123 159124 159125 159126 159127 159128 159129 159130 159131 159132 159133 159134 159135 159136 159137 159138 159139 159140 159141 159142 159143 159144 159145 159146 159147 159148 159149 159150 159151 159152 159153 159154 159155 159156 159157 159158 159159 159160 159161 159162 159163 159164 159165 159166 159167 159168 159169 159170 159171 159172 159173 159174 159175 159176 159177 159178 159179 159180 159181 159182 159183 159184 159185 159186 159187 159188 | } /* ** Ensure that the SQLite statement handles required to update the ** target database object currently indicated by the iterator passed ** as the second argument are available. */ static int rbuObjIterPrepareAll( sqlite3rbu *p, RbuObjIter *pIter, int nOffset /* Add "LIMIT -1 OFFSET $nOffset" to SELECT */ ){ assert( pIter->bCleanup==0 ); if( pIter->pSelect==0 && rbuObjIterCacheTableInfo(p, pIter)==SQLITE_OK ){ const int tnum = pIter->iTnum; char *zCollist = 0; /* List of indexed columns */ char **pz = &p->zErrmsg; const char *zIdx = pIter->zIdx; char *zLimit = 0; if( nOffset ){ zLimit = sqlite3_mprintf(" LIMIT -1 OFFSET %d", nOffset); if( !zLimit ) p->rc = SQLITE_NOMEM; } if( zIdx ){ const char *zTbl = pIter->zTbl; char *zImposterCols = 0; /* Columns for imposter table */ char *zImposterPK = 0; /* Primary key declaration for imposter */ char *zWhere = 0; /* WHERE clause on PK columns */ char *zBind = 0; int nBind = 0; assert( pIter->eType!=RBU_PK_VTAB ); zCollist = rbuObjIterGetIndexCols( p, pIter, &zImposterCols, &zImposterPK, &zWhere, &nBind ); zBind = rbuObjIterGetBindlist(p, nBind); /* Create the imposter table used to write to this index. */ sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 0, 1); sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 1,tnum); rbuMPrintfExec(p, p->dbMain, "CREATE TABLE \"rbu_imp_%w\"( %s, PRIMARY KEY( %s ) ) WITHOUT ROWID", zTbl, zImposterCols, zImposterPK ); sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 0, 0); /* Create the statement to insert index entries */ pIter->nCol = nBind; if( p->rc==SQLITE_OK ){ p->rc = prepareFreeAndCollectError( p->dbMain, &pIter->pInsert, &p->zErrmsg, sqlite3_mprintf("INSERT INTO \"rbu_imp_%w\" VALUES(%s)", zTbl, zBind) ); } /* And to delete index entries */ if( p->rc==SQLITE_OK ){ p->rc = prepareFreeAndCollectError( p->dbMain, &pIter->pDelete, &p->zErrmsg, sqlite3_mprintf("DELETE FROM \"rbu_imp_%w\" WHERE %s", zTbl, zWhere) ); } /* Create the SELECT statement to read keys in sorted order */ if( p->rc==SQLITE_OK ){ char *zSql; if( pIter->eType==RBU_PK_EXTERNAL || pIter->eType==RBU_PK_NONE ){ zSql = sqlite3_mprintf( "SELECT %s, rbu_control FROM %s.'rbu_tmp_%q' ORDER BY %s%s", zCollist, p->zStateDb, pIter->zTbl, zCollist, zLimit ); }else{ zSql = sqlite3_mprintf( "SELECT %s, rbu_control FROM 'data_%q' " "WHERE typeof(rbu_control)='integer' AND rbu_control!=1 " "UNION ALL " "SELECT %s, rbu_control FROM %s.'rbu_tmp_%q' " "ORDER BY %s%s", zCollist, pIter->zTbl, zCollist, p->zStateDb, pIter->zTbl, zCollist, zLimit ); } p->rc = prepareFreeAndCollectError(p->dbRbu, &pIter->pSelect, pz, zSql); } sqlite3_free(zImposterCols); sqlite3_free(zImposterPK); sqlite3_free(zWhere); sqlite3_free(zBind); }else{ int bRbuRowid = (pIter->eType==RBU_PK_VTAB || pIter->eType==RBU_PK_NONE); const char *zTbl = pIter->zTbl; /* Table this step applies to */ const char *zWrite; /* Imposter table name */ char *zBindings = rbuObjIterGetBindlist(p, pIter->nTblCol + bRbuRowid); char *zWhere = rbuObjIterGetWhere(p, pIter); char *zOldlist = rbuObjIterGetOldlist(p, pIter, "old"); char *zNewlist = rbuObjIterGetOldlist(p, pIter, "new"); zCollist = rbuObjIterGetCollist(p, pIter); pIter->nCol = pIter->nTblCol; /* Create the SELECT statement to read keys from data_xxx */ if( p->rc==SQLITE_OK ){ p->rc = prepareFreeAndCollectError(p->dbRbu, &pIter->pSelect, pz, sqlite3_mprintf( "SELECT %s, rbu_control%s FROM 'data_%q'%s", zCollist, (bRbuRowid ? ", rbu_rowid" : ""), zTbl, zLimit ) ); } /* Create the imposter table or tables (if required). */ rbuCreateImposterTable(p, pIter); rbuCreateImposterTable2(p, pIter); zWrite = (pIter->eType==RBU_PK_VTAB ? "" : "rbu_imp_"); /* Create the INSERT statement to write to the target PK b-tree */ if( p->rc==SQLITE_OK ){ p->rc = prepareFreeAndCollectError(p->dbMain, &pIter->pInsert, pz, sqlite3_mprintf( "INSERT INTO \"%s%w\"(%s%s) VALUES(%s)", zWrite, zTbl, zCollist, (bRbuRowid ? ", _rowid_" : ""), zBindings ) ); } /* Create the DELETE statement to write to the target PK b-tree */ if( p->rc==SQLITE_OK ){ p->rc = prepareFreeAndCollectError(p->dbMain, &pIter->pDelete, pz, sqlite3_mprintf( "DELETE FROM \"%s%w\" WHERE %s", zWrite, zTbl, zWhere ) ); } if( pIter->abIndexed ){ const char *zRbuRowid = ""; if( pIter->eType==RBU_PK_EXTERNAL || pIter->eType==RBU_PK_NONE ){ zRbuRowid = ", rbu_rowid"; } /* Create the rbu_tmp_xxx table and the triggers to populate it. */ rbuMPrintfExec(p, p->dbRbu, "CREATE TABLE IF NOT EXISTS %s.'rbu_tmp_%q' AS " "SELECT *%s FROM 'data_%q' WHERE 0;" , p->zStateDb , zTbl, (pIter->eType==RBU_PK_EXTERNAL ? ", 0 AS rbu_rowid" : "") , zTbl ); rbuMPrintfExec(p, p->dbMain, "CREATE TEMP TRIGGER rbu_delete_tr BEFORE DELETE ON \"%s%w\" " "BEGIN " " SELECT rbu_tmp_insert(2, %s);" "END;" "CREATE TEMP TRIGGER rbu_update1_tr BEFORE UPDATE ON \"%s%w\" " "BEGIN " " SELECT rbu_tmp_insert(2, %s);" "END;" "CREATE TEMP TRIGGER rbu_update2_tr AFTER UPDATE ON \"%s%w\" " "BEGIN " " SELECT rbu_tmp_insert(3, %s);" "END;", zWrite, zTbl, zOldlist, zWrite, zTbl, zOldlist, zWrite, zTbl, zNewlist ); if( pIter->eType==RBU_PK_EXTERNAL || pIter->eType==RBU_PK_NONE ){ rbuMPrintfExec(p, p->dbMain, "CREATE TEMP TRIGGER rbu_insert_tr AFTER INSERT ON \"%s%w\" " "BEGIN " " SELECT rbu_tmp_insert(0, %s);" "END;", zWrite, zTbl, zNewlist ); } rbuObjIterPrepareTmpInsert(p, pIter, zCollist, zRbuRowid); } sqlite3_free(zWhere); sqlite3_free(zOldlist); sqlite3_free(zNewlist); sqlite3_free(zBindings); } sqlite3_free(zCollist); sqlite3_free(zLimit); } return p->rc; } /* ** Set output variable *ppStmt to point to an UPDATE statement that may ** be used to update the imposter table for the main table b-tree of the ** table object that pIter currently points to, assuming that the ** rbu_control column of the data_xyz table contains zMask. ** ** If the zMask string does not specify any columns to update, then this ** is not an error. Output variable *ppStmt is set to NULL in this case. */ static int rbuGetUpdateStmt( sqlite3rbu *p, /* RBU handle */ RbuObjIter *pIter, /* Object iterator */ const char *zMask, /* rbu_control value ('x.x.') */ sqlite3_stmt **ppStmt /* OUT: UPDATE statement handle */ ){ RbuUpdateStmt **pp; RbuUpdateStmt *pUp = 0; int nUp = 0; /* In case an error occurs */ *ppStmt = 0; /* Search for an existing statement. If one is found, shift it to the front ** of the LRU queue and return immediately. Otherwise, leave nUp pointing ** to the number of statements currently in the cache and pUp to the ** last object in the list. */ for(pp=&pIter->pRbuUpdate; *pp; pp=&((*pp)->pNext)){ pUp = *pp; if( strcmp(pUp->zMask, zMask)==0 ){ *pp = pUp->pNext; pUp->pNext = pIter->pRbuUpdate; pIter->pRbuUpdate = pUp; *ppStmt = pUp->pUpdate; return SQLITE_OK; } nUp++; } assert( pUp==0 || pUp->pNext==0 ); if( nUp>=SQLITE_RBU_UPDATE_CACHESIZE ){ for(pp=&pIter->pRbuUpdate; *pp!=pUp; pp=&((*pp)->pNext)); *pp = 0; sqlite3_finalize(pUp->pUpdate); pUp->pUpdate = 0; }else{ pUp = (RbuUpdateStmt*)rbuMalloc(p, sizeof(RbuUpdateStmt)+pIter->nTblCol+1); } if( pUp ){ char *zWhere = rbuObjIterGetWhere(p, pIter); char *zSet = rbuObjIterGetSetlist(p, pIter, zMask); char *zUpdate = 0; pUp->zMask = (char*)&pUp[1]; memcpy(pUp->zMask, zMask, pIter->nTblCol); pUp->pNext = pIter->pRbuUpdate; pIter->pRbuUpdate = pUp; if( zSet ){ const char *zPrefix = ""; if( pIter->eType!=RBU_PK_VTAB ) zPrefix = "rbu_imp_"; zUpdate = sqlite3_mprintf("UPDATE \"%s%w\" SET %s WHERE %s", zPrefix, pIter->zTbl, zSet, zWhere ); p->rc = prepareFreeAndCollectError( p->dbMain, &pUp->pUpdate, &p->zErrmsg, zUpdate ); *ppStmt = pUp->pUpdate; } sqlite3_free(zWhere); sqlite3_free(zSet); } return p->rc; } static sqlite3 *rbuOpenDbhandle(sqlite3rbu *p, const char *zName){ sqlite3 *db = 0; if( p->rc==SQLITE_OK ){ const int flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_URI; p->rc = sqlite3_open_v2(zName, &db, flags, p->zVfsName); if( p->rc ){ p->zErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(db)); sqlite3_close(db); db = 0; } } return db; } /* ** Open the database handle and attach the RBU database as "rbu". If an ** error occurs, leave an error code and message in the RBU handle. */ static void rbuOpenDatabase(sqlite3rbu *p){ assert( p->rc==SQLITE_OK ); assert( p->dbMain==0 && p->dbRbu==0 ); p->eStage = 0; p->dbMain = rbuOpenDbhandle(p, p->zTarget); p->dbRbu = rbuOpenDbhandle(p, p->zRbu); /* If using separate RBU and state databases, attach the state database to ** the RBU db handle now. */ if( p->zState ){ rbuMPrintfExec(p, p->dbRbu, "ATTACH %Q AS stat", p->zState); memcpy(p->zStateDb, "stat", 4); }else{ memcpy(p->zStateDb, "main", 4); } if( p->rc==SQLITE_OK ){ p->rc = sqlite3_create_function(p->dbMain, "rbu_tmp_insert", -1, SQLITE_UTF8, (void*)p, rbuTmpInsertFunc, 0, 0 ); } if( p->rc==SQLITE_OK ){ p->rc = sqlite3_file_control(p->dbMain, "main", SQLITE_FCNTL_RBU, (void*)p); } rbuMPrintfExec(p, p->dbMain, "SELECT * FROM sqlite_master"); /* Mark the database file just opened as an RBU target database. If ** this call returns SQLITE_NOTFOUND, then the RBU vfs is not in use. ** This is an error. */ if( p->rc==SQLITE_OK ){ p->rc = sqlite3_file_control(p->dbMain, "main", SQLITE_FCNTL_RBU, (void*)p); } if( p->rc==SQLITE_NOTFOUND ){ p->rc = SQLITE_ERROR; p->zErrmsg = sqlite3_mprintf("rbu vfs not found"); } } /* ** This routine is a copy of the sqlite3FileSuffix3() routine from the core. ** It is a no-op unless SQLITE_ENABLE_8_3_NAMES is defined. ** |
︙ | ︙ | |||
158953 158954 158955 158956 158957 158958 158959 | ** Examples: ** ** test.db-journal => test.nal ** test.db-wal => test.wal ** test.db-shm => test.shm ** test.db-mj7f3319fa => test.9fa */ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 159198 159199 159200 159201 159202 159203 159204 159205 159206 159207 159208 159209 159210 159211 159212 159213 159214 159215 159216 159217 159218 159219 159220 159221 159222 159223 159224 159225 159226 159227 159228 159229 159230 159231 159232 159233 159234 159235 159236 159237 159238 159239 159240 159241 159242 159243 159244 159245 159246 159247 159248 159249 159250 159251 159252 159253 159254 159255 159256 159257 159258 159259 159260 159261 159262 159263 159264 159265 159266 159267 159268 159269 159270 159271 159272 159273 159274 159275 159276 159277 159278 159279 159280 159281 159282 159283 159284 159285 159286 159287 159288 159289 159290 159291 159292 159293 159294 159295 159296 159297 159298 159299 159300 159301 159302 159303 159304 159305 159306 159307 159308 159309 159310 159311 159312 159313 159314 159315 159316 159317 159318 159319 159320 159321 159322 159323 159324 159325 159326 159327 159328 159329 159330 159331 159332 159333 159334 159335 159336 159337 159338 159339 159340 159341 159342 159343 159344 159345 159346 159347 159348 159349 159350 159351 159352 159353 159354 159355 159356 159357 159358 159359 159360 159361 159362 159363 159364 159365 159366 159367 159368 159369 159370 159371 159372 159373 159374 159375 159376 159377 159378 159379 159380 159381 159382 159383 159384 159385 159386 159387 159388 159389 159390 159391 159392 159393 159394 159395 159396 159397 159398 159399 159400 159401 159402 159403 159404 159405 159406 159407 159408 159409 159410 159411 159412 159413 159414 159415 159416 159417 159418 159419 159420 159421 159422 159423 159424 159425 159426 159427 159428 159429 159430 159431 159432 159433 159434 159435 159436 159437 159438 159439 159440 159441 159442 159443 159444 159445 159446 159447 159448 159449 159450 159451 159452 159453 159454 159455 159456 159457 159458 159459 159460 159461 159462 159463 159464 159465 159466 159467 159468 159469 159470 159471 159472 159473 159474 159475 159476 159477 159478 159479 159480 159481 159482 159483 159484 159485 159486 159487 159488 159489 159490 159491 159492 159493 159494 159495 159496 159497 159498 159499 159500 159501 159502 159503 159504 159505 159506 159507 159508 159509 159510 159511 159512 159513 159514 159515 159516 159517 159518 159519 159520 159521 159522 159523 159524 159525 159526 159527 159528 159529 159530 159531 159532 159533 159534 159535 159536 159537 159538 159539 159540 159541 159542 159543 159544 159545 159546 159547 159548 159549 159550 159551 159552 159553 159554 159555 159556 159557 159558 159559 159560 159561 159562 159563 159564 159565 159566 159567 159568 159569 159570 159571 159572 159573 159574 159575 159576 159577 159578 159579 159580 159581 159582 159583 159584 159585 159586 159587 159588 159589 159590 159591 159592 159593 159594 159595 159596 159597 159598 159599 159600 159601 159602 159603 159604 159605 159606 159607 159608 159609 159610 159611 159612 159613 159614 159615 159616 159617 159618 159619 159620 159621 159622 159623 159624 159625 159626 159627 159628 159629 159630 159631 159632 159633 159634 159635 159636 159637 159638 159639 159640 159641 159642 159643 159644 159645 159646 159647 159648 159649 159650 159651 159652 159653 159654 159655 159656 159657 159658 159659 159660 159661 159662 159663 159664 159665 159666 159667 159668 159669 159670 159671 159672 159673 159674 159675 159676 159677 159678 159679 159680 159681 159682 159683 159684 159685 159686 159687 159688 159689 159690 159691 159692 159693 159694 159695 159696 159697 159698 159699 159700 159701 159702 159703 159704 159705 159706 159707 159708 159709 159710 159711 159712 159713 159714 159715 159716 159717 159718 159719 159720 159721 159722 159723 159724 159725 159726 159727 159728 159729 159730 159731 159732 159733 159734 159735 159736 159737 159738 159739 159740 159741 159742 159743 159744 159745 159746 159747 159748 159749 159750 159751 159752 159753 159754 159755 159756 159757 159758 159759 159760 159761 159762 159763 159764 159765 159766 159767 159768 159769 159770 159771 159772 159773 159774 159775 159776 159777 159778 159779 159780 159781 159782 159783 159784 159785 159786 159787 159788 159789 159790 159791 159792 159793 159794 159795 159796 159797 159798 159799 159800 159801 159802 159803 159804 159805 159806 159807 159808 159809 159810 159811 159812 159813 159814 159815 159816 159817 159818 159819 159820 159821 159822 159823 159824 159825 159826 159827 159828 159829 159830 159831 159832 159833 159834 159835 159836 159837 159838 159839 159840 159841 159842 159843 159844 159845 159846 159847 159848 159849 159850 159851 159852 159853 159854 159855 159856 159857 159858 159859 159860 159861 159862 159863 159864 159865 159866 159867 159868 159869 159870 159871 159872 159873 159874 159875 159876 159877 159878 159879 159880 159881 159882 159883 159884 159885 159886 159887 159888 159889 159890 159891 159892 159893 159894 159895 159896 159897 159898 159899 159900 159901 159902 159903 159904 159905 159906 159907 159908 159909 159910 159911 159912 159913 159914 159915 159916 159917 159918 159919 159920 159921 159922 159923 159924 159925 159926 159927 159928 159929 159930 159931 159932 159933 159934 159935 159936 159937 159938 159939 159940 159941 159942 159943 159944 159945 159946 159947 159948 159949 159950 159951 159952 159953 159954 159955 159956 159957 159958 159959 159960 159961 159962 159963 159964 159965 159966 159967 159968 159969 159970 159971 159972 159973 159974 159975 159976 159977 159978 159979 159980 159981 159982 159983 159984 159985 159986 159987 159988 159989 159990 159991 159992 159993 159994 159995 159996 159997 159998 159999 160000 160001 160002 160003 160004 160005 160006 160007 160008 160009 160010 160011 160012 160013 160014 160015 160016 160017 160018 160019 160020 160021 160022 160023 160024 160025 160026 160027 160028 160029 160030 160031 160032 160033 160034 160035 160036 160037 160038 160039 160040 160041 160042 160043 160044 160045 160046 160047 160048 160049 160050 160051 160052 160053 160054 160055 160056 160057 160058 160059 160060 160061 160062 160063 160064 160065 160066 160067 160068 160069 160070 160071 160072 160073 160074 160075 160076 160077 160078 160079 160080 160081 160082 160083 160084 160085 160086 160087 160088 160089 160090 160091 160092 160093 160094 160095 160096 160097 160098 160099 160100 160101 160102 160103 160104 160105 160106 160107 160108 160109 160110 160111 160112 160113 160114 160115 160116 160117 160118 160119 160120 160121 160122 160123 160124 160125 160126 160127 160128 160129 160130 160131 160132 160133 160134 160135 160136 160137 160138 160139 160140 160141 160142 160143 160144 160145 160146 160147 160148 160149 160150 160151 160152 160153 160154 160155 160156 160157 160158 160159 160160 160161 160162 160163 160164 160165 160166 160167 160168 160169 160170 160171 160172 160173 160174 160175 160176 160177 160178 160179 160180 160181 160182 160183 160184 160185 160186 160187 160188 160189 160190 160191 160192 160193 160194 160195 160196 160197 160198 160199 160200 160201 160202 160203 160204 160205 160206 160207 160208 160209 160210 160211 160212 160213 160214 160215 160216 160217 160218 160219 160220 160221 160222 160223 160224 160225 160226 160227 160228 160229 160230 160231 160232 160233 160234 160235 160236 160237 160238 160239 160240 160241 160242 160243 160244 160245 160246 160247 160248 160249 160250 160251 160252 160253 160254 160255 160256 160257 160258 160259 160260 160261 160262 160263 160264 160265 160266 160267 160268 160269 160270 160271 160272 160273 160274 160275 160276 160277 160278 160279 160280 160281 160282 160283 160284 160285 160286 160287 160288 160289 160290 160291 160292 160293 160294 160295 160296 160297 160298 160299 160300 160301 160302 160303 160304 160305 160306 160307 160308 160309 160310 160311 160312 160313 160314 160315 160316 160317 160318 160319 160320 160321 160322 160323 160324 160325 160326 160327 160328 160329 160330 160331 160332 160333 160334 160335 160336 160337 160338 160339 160340 160341 160342 160343 160344 160345 160346 160347 160348 160349 160350 160351 160352 160353 160354 160355 160356 160357 160358 160359 160360 160361 160362 160363 160364 160365 160366 160367 160368 160369 160370 160371 160372 160373 160374 160375 160376 160377 160378 160379 160380 160381 160382 160383 160384 160385 160386 160387 160388 160389 160390 160391 160392 160393 160394 160395 160396 160397 160398 160399 160400 160401 160402 160403 160404 160405 160406 160407 160408 160409 160410 160411 160412 160413 160414 160415 160416 160417 160418 160419 160420 160421 160422 160423 160424 160425 160426 160427 160428 160429 160430 160431 160432 160433 160434 160435 160436 160437 160438 160439 160440 160441 160442 160443 160444 160445 160446 160447 160448 160449 160450 160451 160452 160453 160454 160455 160456 160457 160458 160459 160460 160461 160462 160463 160464 160465 160466 160467 160468 160469 160470 160471 160472 160473 160474 160475 160476 160477 160478 160479 160480 160481 160482 160483 160484 160485 160486 160487 160488 160489 160490 160491 160492 160493 160494 160495 160496 160497 160498 160499 160500 160501 160502 160503 160504 160505 160506 160507 160508 160509 160510 160511 160512 160513 160514 160515 160516 160517 160518 160519 160520 160521 160522 160523 160524 160525 160526 160527 160528 160529 160530 160531 160532 160533 160534 160535 160536 160537 160538 160539 160540 160541 160542 160543 160544 160545 160546 160547 160548 160549 160550 | ** Examples: ** ** test.db-journal => test.nal ** test.db-wal => test.wal ** test.db-shm => test.shm ** test.db-mj7f3319fa => test.9fa */ static void rbuFileSuffix3(const char *zBase, char *z){ #ifdef SQLITE_ENABLE_8_3_NAMES #if SQLITE_ENABLE_8_3_NAMES<2 if( sqlite3_uri_boolean(zBase, "8_3_names", 0) ) #endif { int i, sz; sz = sqlite3Strlen30(z); for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){} if( z[i]=='.' && ALWAYS(sz>i+4) ) memmove(&z[i+1], &z[sz-3], 4); } #endif } /* ** Return the current wal-index header checksum for the target database ** as a 64-bit integer. ** ** The checksum is store in the first page of xShmMap memory as an 8-byte ** blob starting at byte offset 40. */ static i64 rbuShmChecksum(sqlite3rbu *p){ i64 iRet = 0; if( p->rc==SQLITE_OK ){ sqlite3_file *pDb = p->pTargetFd->pReal; u32 volatile *ptr; p->rc = pDb->pMethods->xShmMap(pDb, 0, 32*1024, 0, (void volatile**)&ptr); if( p->rc==SQLITE_OK ){ iRet = ((i64)ptr[10] << 32) + ptr[11]; } } return iRet; } /* ** This function is called as part of initializing or reinitializing an ** incremental checkpoint. ** ** It populates the sqlite3rbu.aFrame[] array with the set of ** (wal frame -> db page) copy operations required to checkpoint the ** current wal file, and obtains the set of shm locks required to safely ** perform the copy operations directly on the file-system. ** ** If argument pState is not NULL, then the incremental checkpoint is ** being resumed. In this case, if the checksum of the wal-index-header ** following recovery is not the same as the checksum saved in the RbuState ** object, then the rbu handle is set to DONE state. This occurs if some ** other client appends a transaction to the wal file in the middle of ** an incremental checkpoint. */ static void rbuSetupCheckpoint(sqlite3rbu *p, RbuState *pState){ /* If pState is NULL, then the wal file may not have been opened and ** recovered. Running a read-statement here to ensure that doing so ** does not interfere with the "capture" process below. */ if( pState==0 ){ p->eStage = 0; if( p->rc==SQLITE_OK ){ p->rc = sqlite3_exec(p->dbMain, "SELECT * FROM sqlite_master", 0, 0, 0); } } /* Assuming no error has occurred, run a "restart" checkpoint with the ** sqlite3rbu.eStage variable set to CAPTURE. This turns on the following ** special behaviour in the rbu VFS: ** ** * If the exclusive shm WRITER or READ0 lock cannot be obtained, ** the checkpoint fails with SQLITE_BUSY (normally SQLite would ** proceed with running a passive checkpoint instead of failing). ** ** * Attempts to read from the *-wal file or write to the database file ** do not perform any IO. Instead, the frame/page combinations that ** would be read/written are recorded in the sqlite3rbu.aFrame[] ** array. ** ** * Calls to xShmLock(UNLOCK) to release the exclusive shm WRITER, ** READ0 and CHECKPOINT locks taken as part of the checkpoint are ** no-ops. These locks will not be released until the connection ** is closed. ** ** * Attempting to xSync() the database file causes an SQLITE_INTERNAL ** error. ** ** As a result, unless an error (i.e. OOM or SQLITE_BUSY) occurs, the ** checkpoint below fails with SQLITE_INTERNAL, and leaves the aFrame[] ** array populated with a set of (frame -> page) mappings. Because the ** WRITER, CHECKPOINT and READ0 locks are still held, it is safe to copy ** data from the wal file into the database file according to the ** contents of aFrame[]. */ if( p->rc==SQLITE_OK ){ int rc2; p->eStage = RBU_STAGE_CAPTURE; rc2 = sqlite3_exec(p->dbMain, "PRAGMA main.wal_checkpoint=restart", 0, 0,0); if( rc2!=SQLITE_INTERNAL ) p->rc = rc2; } if( p->rc==SQLITE_OK ){ p->eStage = RBU_STAGE_CKPT; p->nStep = (pState ? pState->nRow : 0); p->aBuf = rbuMalloc(p, p->pgsz); p->iWalCksum = rbuShmChecksum(p); } if( p->rc==SQLITE_OK && pState && pState->iWalCksum!=p->iWalCksum ){ p->rc = SQLITE_DONE; p->eStage = RBU_STAGE_DONE; } } /* ** Called when iAmt bytes are read from offset iOff of the wal file while ** the rbu object is in capture mode. Record the frame number of the frame ** being read in the aFrame[] array. */ static int rbuCaptureWalRead(sqlite3rbu *pRbu, i64 iOff, int iAmt){ const u32 mReq = (1<<WAL_LOCK_WRITE)|(1<<WAL_LOCK_CKPT)|(1<<WAL_LOCK_READ0); u32 iFrame; if( pRbu->mLock!=mReq ){ pRbu->rc = SQLITE_BUSY; return SQLITE_INTERNAL; } pRbu->pgsz = iAmt; if( pRbu->nFrame==pRbu->nFrameAlloc ){ int nNew = (pRbu->nFrameAlloc ? pRbu->nFrameAlloc : 64) * 2; RbuFrame *aNew; aNew = (RbuFrame*)sqlite3_realloc(pRbu->aFrame, nNew * sizeof(RbuFrame)); if( aNew==0 ) return SQLITE_NOMEM; pRbu->aFrame = aNew; pRbu->nFrameAlloc = nNew; } iFrame = (u32)((iOff-32) / (i64)(iAmt+24)) + 1; if( pRbu->iMaxFrame<iFrame ) pRbu->iMaxFrame = iFrame; pRbu->aFrame[pRbu->nFrame].iWalFrame = iFrame; pRbu->aFrame[pRbu->nFrame].iDbPage = 0; pRbu->nFrame++; return SQLITE_OK; } /* ** Called when a page of data is written to offset iOff of the database ** file while the rbu handle is in capture mode. Record the page number ** of the page being written in the aFrame[] array. */ static int rbuCaptureDbWrite(sqlite3rbu *pRbu, i64 iOff){ pRbu->aFrame[pRbu->nFrame-1].iDbPage = (u32)(iOff / pRbu->pgsz) + 1; return SQLITE_OK; } /* ** This is called as part of an incremental checkpoint operation. Copy ** a single frame of data from the wal file into the database file, as ** indicated by the RbuFrame object. */ static void rbuCheckpointFrame(sqlite3rbu *p, RbuFrame *pFrame){ sqlite3_file *pWal = p->pTargetFd->pWalFd->pReal; sqlite3_file *pDb = p->pTargetFd->pReal; i64 iOff; assert( p->rc==SQLITE_OK ); iOff = (i64)(pFrame->iWalFrame-1) * (p->pgsz + 24) + 32 + 24; p->rc = pWal->pMethods->xRead(pWal, p->aBuf, p->pgsz, iOff); if( p->rc ) return; iOff = (i64)(pFrame->iDbPage-1) * p->pgsz; p->rc = pDb->pMethods->xWrite(pDb, p->aBuf, p->pgsz, iOff); } /* ** Take an EXCLUSIVE lock on the database file. */ static void rbuLockDatabase(sqlite3rbu *p){ sqlite3_file *pReal = p->pTargetFd->pReal; assert( p->rc==SQLITE_OK ); p->rc = pReal->pMethods->xLock(pReal, SQLITE_LOCK_SHARED); if( p->rc==SQLITE_OK ){ p->rc = pReal->pMethods->xLock(pReal, SQLITE_LOCK_EXCLUSIVE); } } /* ** The RBU handle is currently in RBU_STAGE_OAL state, with a SHARED lock ** on the database file. This proc moves the *-oal file to the *-wal path, ** then reopens the database file (this time in vanilla, non-oal, WAL mode). ** If an error occurs, leave an error code and error message in the rbu ** handle. */ static void rbuMoveOalFile(sqlite3rbu *p){ const char *zBase = sqlite3_db_filename(p->dbMain, "main"); char *zWal = sqlite3_mprintf("%s-wal", zBase); char *zOal = sqlite3_mprintf("%s-oal", zBase); assert( p->eStage==RBU_STAGE_MOVE ); assert( p->rc==SQLITE_OK && p->zErrmsg==0 ); if( zWal==0 || zOal==0 ){ p->rc = SQLITE_NOMEM; }else{ /* Move the *-oal file to *-wal. At this point connection p->db is ** holding a SHARED lock on the target database file (because it is ** in WAL mode). So no other connection may be writing the db. ** ** In order to ensure that there are no database readers, an EXCLUSIVE ** lock is obtained here before the *-oal is moved to *-wal. */ rbuLockDatabase(p); if( p->rc==SQLITE_OK ){ rbuFileSuffix3(zBase, zWal); rbuFileSuffix3(zBase, zOal); /* Re-open the databases. */ rbuObjIterFinalize(&p->objiter); sqlite3_close(p->dbMain); sqlite3_close(p->dbRbu); p->rc = rename(zOal, zWal) ? SQLITE_IOERR : SQLITE_OK; if( p->rc==SQLITE_OK ){ p->dbMain = 0; p->dbRbu = 0; rbuOpenDatabase(p); rbuSetupCheckpoint(p, 0); } } } sqlite3_free(zWal); sqlite3_free(zOal); } /* ** The SELECT statement iterating through the keys for the current object ** (p->objiter.pSelect) currently points to a valid row. This function ** determines the type of operation requested by this row and returns ** one of the following values to indicate the result: ** ** * RBU_INSERT ** * RBU_DELETE ** * RBU_IDX_DELETE ** * RBU_UPDATE ** ** If RBU_UPDATE is returned, then output variable *pzMask is set to ** point to the text value indicating the columns to update. ** ** If the rbu_control field contains an invalid value, an error code and ** message are left in the RBU handle and zero returned. */ static int rbuStepType(sqlite3rbu *p, const char **pzMask){ int iCol = p->objiter.nCol; /* Index of rbu_control column */ int res = 0; /* Return value */ switch( sqlite3_column_type(p->objiter.pSelect, iCol) ){ case SQLITE_INTEGER: { int iVal = sqlite3_column_int(p->objiter.pSelect, iCol); if( iVal==0 ){ res = RBU_INSERT; }else if( iVal==1 ){ res = RBU_DELETE; }else if( iVal==2 ){ res = RBU_IDX_DELETE; }else if( iVal==3 ){ res = RBU_IDX_INSERT; } break; } case SQLITE_TEXT: { const unsigned char *z = sqlite3_column_text(p->objiter.pSelect, iCol); if( z==0 ){ p->rc = SQLITE_NOMEM; }else{ *pzMask = (const char*)z; } res = RBU_UPDATE; break; } default: break; } if( res==0 ){ rbuBadControlError(p); } return res; } #ifdef SQLITE_DEBUG /* ** Assert that column iCol of statement pStmt is named zName. */ static void assertColumnName(sqlite3_stmt *pStmt, int iCol, const char *zName){ const char *zCol = sqlite3_column_name(pStmt, iCol); assert( 0==sqlite3_stricmp(zName, zCol) ); } #else # define assertColumnName(x,y,z) #endif /* ** This function does the work for an sqlite3rbu_step() call. ** ** The object-iterator (p->objiter) currently points to a valid object, ** and the input cursor (p->objiter.pSelect) currently points to a valid ** input row. Perform whatever processing is required and return. ** ** If no error occurs, SQLITE_OK is returned. Otherwise, an error code ** and message is left in the RBU handle and a copy of the error code ** returned. */ static int rbuStep(sqlite3rbu *p){ RbuObjIter *pIter = &p->objiter; const char *zMask = 0; int i; int eType = rbuStepType(p, &zMask); if( eType ){ assert( eType!=RBU_UPDATE || pIter->zIdx==0 ); if( pIter->zIdx==0 && eType==RBU_IDX_DELETE ){ rbuBadControlError(p); } else if( eType==RBU_INSERT || eType==RBU_DELETE || eType==RBU_IDX_DELETE || eType==RBU_IDX_INSERT ){ sqlite3_value *pVal; sqlite3_stmt *pWriter; assert( eType!=RBU_UPDATE ); assert( eType!=RBU_DELETE || pIter->zIdx==0 ); if( eType==RBU_IDX_DELETE || eType==RBU_DELETE ){ pWriter = pIter->pDelete; }else{ pWriter = pIter->pInsert; } for(i=0; i<pIter->nCol; i++){ /* If this is an INSERT into a table b-tree and the table has an ** explicit INTEGER PRIMARY KEY, check that this is not an attempt ** to write a NULL into the IPK column. That is not permitted. */ if( eType==RBU_INSERT && pIter->zIdx==0 && pIter->eType==RBU_PK_IPK && pIter->abTblPk[i] && sqlite3_column_type(pIter->pSelect, i)==SQLITE_NULL ){ p->rc = SQLITE_MISMATCH; p->zErrmsg = sqlite3_mprintf("datatype mismatch"); goto step_out; } if( eType==RBU_DELETE && pIter->abTblPk[i]==0 ){ continue; } pVal = sqlite3_column_value(pIter->pSelect, i); p->rc = sqlite3_bind_value(pWriter, i+1, pVal); if( p->rc ) goto step_out; } if( pIter->zIdx==0 && (pIter->eType==RBU_PK_VTAB || pIter->eType==RBU_PK_NONE) ){ /* For a virtual table, or a table with no primary key, the ** SELECT statement is: ** ** SELECT <cols>, rbu_control, rbu_rowid FROM .... ** ** Hence column_value(pIter->nCol+1). */ assertColumnName(pIter->pSelect, pIter->nCol+1, "rbu_rowid"); pVal = sqlite3_column_value(pIter->pSelect, pIter->nCol+1); p->rc = sqlite3_bind_value(pWriter, pIter->nCol+1, pVal); } if( p->rc==SQLITE_OK ){ sqlite3_step(pWriter); p->rc = resetAndCollectError(pWriter, &p->zErrmsg); } }else{ sqlite3_value *pVal; sqlite3_stmt *pUpdate = 0; assert( eType==RBU_UPDATE ); rbuGetUpdateStmt(p, pIter, zMask, &pUpdate); if( pUpdate ){ for(i=0; p->rc==SQLITE_OK && i<pIter->nCol; i++){ char c = zMask[pIter->aiSrcOrder[i]]; pVal = sqlite3_column_value(pIter->pSelect, i); if( pIter->abTblPk[i] || c=='x' || c=='d' ){ p->rc = sqlite3_bind_value(pUpdate, i+1, pVal); } } if( p->rc==SQLITE_OK && (pIter->eType==RBU_PK_VTAB || pIter->eType==RBU_PK_NONE) ){ /* Bind the rbu_rowid value to column _rowid_ */ assertColumnName(pIter->pSelect, pIter->nCol+1, "rbu_rowid"); pVal = sqlite3_column_value(pIter->pSelect, pIter->nCol+1); p->rc = sqlite3_bind_value(pUpdate, pIter->nCol+1, pVal); } if( p->rc==SQLITE_OK ){ sqlite3_step(pUpdate); p->rc = resetAndCollectError(pUpdate, &p->zErrmsg); } } } } step_out: return p->rc; } /* ** Increment the schema cookie of the main database opened by p->dbMain. */ static void rbuIncrSchemaCookie(sqlite3rbu *p){ if( p->rc==SQLITE_OK ){ int iCookie = 1000000; sqlite3_stmt *pStmt; p->rc = prepareAndCollectError(p->dbMain, &pStmt, &p->zErrmsg, "PRAGMA schema_version" ); if( p->rc==SQLITE_OK ){ /* Coverage: it may be that this sqlite3_step() cannot fail. There ** is already a transaction open, so the prepared statement cannot ** throw an SQLITE_SCHEMA exception. The only database page the ** statement reads is page 1, which is guaranteed to be in the cache. ** And no memory allocations are required. */ if( SQLITE_ROW==sqlite3_step(pStmt) ){ iCookie = sqlite3_column_int(pStmt, 0); } rbuFinalize(p, pStmt); } if( p->rc==SQLITE_OK ){ rbuMPrintfExec(p, p->dbMain, "PRAGMA schema_version = %d", iCookie+1); } } } /* ** Update the contents of the rbu_state table within the rbu database. The ** value stored in the RBU_STATE_STAGE column is eStage. All other values ** are determined by inspecting the rbu handle passed as the first argument. */ static void rbuSaveState(sqlite3rbu *p, int eStage){ if( p->rc==SQLITE_OK || p->rc==SQLITE_DONE ){ sqlite3_stmt *pInsert = 0; int rc; assert( p->zErrmsg==0 ); rc = prepareFreeAndCollectError(p->dbRbu, &pInsert, &p->zErrmsg, sqlite3_mprintf( "INSERT OR REPLACE INTO %s.rbu_state(k, v) VALUES " "(%d, %d), " "(%d, %Q), " "(%d, %Q), " "(%d, %d), " "(%d, %d), " "(%d, %lld), " "(%d, %lld), " "(%d, %lld) ", p->zStateDb, RBU_STATE_STAGE, eStage, RBU_STATE_TBL, p->objiter.zTbl, RBU_STATE_IDX, p->objiter.zIdx, RBU_STATE_ROW, p->nStep, RBU_STATE_PROGRESS, p->nProgress, RBU_STATE_CKPT, p->iWalCksum, RBU_STATE_COOKIE, (i64)p->pTargetFd->iCookie, RBU_STATE_OALSZ, p->iOalSz ) ); assert( pInsert==0 || rc==SQLITE_OK ); if( rc==SQLITE_OK ){ sqlite3_step(pInsert); rc = sqlite3_finalize(pInsert); } if( rc!=SQLITE_OK ) p->rc = rc; } } /* ** Step the RBU object. */ SQLITE_API int SQLITE_STDCALL sqlite3rbu_step(sqlite3rbu *p){ if( p ){ switch( p->eStage ){ case RBU_STAGE_OAL: { RbuObjIter *pIter = &p->objiter; while( p->rc==SQLITE_OK && pIter->zTbl ){ if( pIter->bCleanup ){ /* Clean up the rbu_tmp_xxx table for the previous table. It ** cannot be dropped as there are currently active SQL statements. ** But the contents can be deleted. */ if( pIter->abIndexed ){ rbuMPrintfExec(p, p->dbRbu, "DELETE FROM %s.'rbu_tmp_%q'", p->zStateDb, pIter->zTbl ); } }else{ rbuObjIterPrepareAll(p, pIter, 0); /* Advance to the next row to process. */ if( p->rc==SQLITE_OK ){ int rc = sqlite3_step(pIter->pSelect); if( rc==SQLITE_ROW ){ p->nProgress++; p->nStep++; return rbuStep(p); } p->rc = sqlite3_reset(pIter->pSelect); p->nStep = 0; } } rbuObjIterNext(p, pIter); } if( p->rc==SQLITE_OK ){ assert( pIter->zTbl==0 ); rbuSaveState(p, RBU_STAGE_MOVE); rbuIncrSchemaCookie(p); if( p->rc==SQLITE_OK ){ p->rc = sqlite3_exec(p->dbMain, "COMMIT", 0, 0, &p->zErrmsg); } if( p->rc==SQLITE_OK ){ p->rc = sqlite3_exec(p->dbRbu, "COMMIT", 0, 0, &p->zErrmsg); } p->eStage = RBU_STAGE_MOVE; } break; } case RBU_STAGE_MOVE: { if( p->rc==SQLITE_OK ){ rbuMoveOalFile(p); p->nProgress++; } break; } case RBU_STAGE_CKPT: { if( p->rc==SQLITE_OK ){ if( p->nStep>=p->nFrame ){ sqlite3_file *pDb = p->pTargetFd->pReal; /* Sync the db file */ p->rc = pDb->pMethods->xSync(pDb, SQLITE_SYNC_NORMAL); /* Update nBackfill */ if( p->rc==SQLITE_OK ){ void volatile *ptr; p->rc = pDb->pMethods->xShmMap(pDb, 0, 32*1024, 0, &ptr); if( p->rc==SQLITE_OK ){ ((u32 volatile*)ptr)[24] = p->iMaxFrame; } } if( p->rc==SQLITE_OK ){ p->eStage = RBU_STAGE_DONE; p->rc = SQLITE_DONE; } }else{ RbuFrame *pFrame = &p->aFrame[p->nStep]; rbuCheckpointFrame(p, pFrame); p->nStep++; } p->nProgress++; } break; } default: break; } return p->rc; }else{ return SQLITE_NOMEM; } } /* ** Free an RbuState object allocated by rbuLoadState(). */ static void rbuFreeState(RbuState *p){ if( p ){ sqlite3_free(p->zTbl); sqlite3_free(p->zIdx); sqlite3_free(p); } } /* ** Allocate an RbuState object and load the contents of the rbu_state ** table into it. Return a pointer to the new object. It is the ** responsibility of the caller to eventually free the object using ** sqlite3_free(). ** ** If an error occurs, leave an error code and message in the rbu handle ** and return NULL. */ static RbuState *rbuLoadState(sqlite3rbu *p){ RbuState *pRet = 0; sqlite3_stmt *pStmt = 0; int rc; int rc2; pRet = (RbuState*)rbuMalloc(p, sizeof(RbuState)); if( pRet==0 ) return 0; rc = prepareFreeAndCollectError(p->dbRbu, &pStmt, &p->zErrmsg, sqlite3_mprintf("SELECT k, v FROM %s.rbu_state", p->zStateDb) ); while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ switch( sqlite3_column_int(pStmt, 0) ){ case RBU_STATE_STAGE: pRet->eStage = sqlite3_column_int(pStmt, 1); if( pRet->eStage!=RBU_STAGE_OAL && pRet->eStage!=RBU_STAGE_MOVE && pRet->eStage!=RBU_STAGE_CKPT ){ p->rc = SQLITE_CORRUPT; } break; case RBU_STATE_TBL: pRet->zTbl = rbuStrndup((char*)sqlite3_column_text(pStmt, 1), &rc); break; case RBU_STATE_IDX: pRet->zIdx = rbuStrndup((char*)sqlite3_column_text(pStmt, 1), &rc); break; case RBU_STATE_ROW: pRet->nRow = sqlite3_column_int(pStmt, 1); break; case RBU_STATE_PROGRESS: pRet->nProgress = sqlite3_column_int64(pStmt, 1); break; case RBU_STATE_CKPT: pRet->iWalCksum = sqlite3_column_int64(pStmt, 1); break; case RBU_STATE_COOKIE: pRet->iCookie = (u32)sqlite3_column_int64(pStmt, 1); break; case RBU_STATE_OALSZ: pRet->iOalSz = (u32)sqlite3_column_int64(pStmt, 1); break; default: rc = SQLITE_CORRUPT; break; } } rc2 = sqlite3_finalize(pStmt); if( rc==SQLITE_OK ) rc = rc2; p->rc = rc; return pRet; } /* ** Compare strings z1 and z2, returning 0 if they are identical, or non-zero ** otherwise. Either or both argument may be NULL. Two NULL values are ** considered equal, and NULL is considered distinct from all other values. */ static int rbuStrCompare(const char *z1, const char *z2){ if( z1==0 && z2==0 ) return 0; if( z1==0 || z2==0 ) return 1; return (sqlite3_stricmp(z1, z2)!=0); } /* ** This function is called as part of sqlite3rbu_open() when initializing ** an rbu handle in OAL stage. If the rbu update has not started (i.e. ** the rbu_state table was empty) it is a no-op. Otherwise, it arranges ** things so that the next call to sqlite3rbu_step() continues on from ** where the previous rbu handle left off. ** ** If an error occurs, an error code and error message are left in the ** rbu handle passed as the first argument. */ static void rbuSetupOal(sqlite3rbu *p, RbuState *pState){ assert( p->rc==SQLITE_OK ); if( pState->zTbl ){ RbuObjIter *pIter = &p->objiter; int rc = SQLITE_OK; while( rc==SQLITE_OK && pIter->zTbl && (pIter->bCleanup || rbuStrCompare(pIter->zIdx, pState->zIdx) || rbuStrCompare(pIter->zTbl, pState->zTbl) )){ rc = rbuObjIterNext(p, pIter); } if( rc==SQLITE_OK && !pIter->zTbl ){ rc = SQLITE_ERROR; p->zErrmsg = sqlite3_mprintf("rbu_state mismatch error"); } if( rc==SQLITE_OK ){ p->nStep = pState->nRow; rc = rbuObjIterPrepareAll(p, &p->objiter, p->nStep); } p->rc = rc; } } /* ** If there is a "*-oal" file in the file-system corresponding to the ** target database in the file-system, delete it. If an error occurs, ** leave an error code and error message in the rbu handle. */ static void rbuDeleteOalFile(sqlite3rbu *p){ char *zOal = sqlite3_mprintf("%s-oal", p->zTarget); assert( p->rc==SQLITE_OK && p->zErrmsg==0 ); unlink(zOal); sqlite3_free(zOal); } /* ** Allocate a private rbu VFS for the rbu handle passed as the only ** argument. This VFS will be used unless the call to sqlite3rbu_open() ** specified a URI with a vfs=? option in place of a target database ** file name. */ static void rbuCreateVfs(sqlite3rbu *p){ int rnd; char zRnd[64]; assert( p->rc==SQLITE_OK ); sqlite3_randomness(sizeof(int), (void*)&rnd); sqlite3_snprintf(sizeof(zRnd), zRnd, "rbu_vfs_%d", rnd); p->rc = sqlite3rbu_create_vfs(zRnd, 0); if( p->rc==SQLITE_OK ){ sqlite3_vfs *pVfs = sqlite3_vfs_find(zRnd); assert( pVfs ); p->zVfsName = pVfs->zName; } } /* ** Destroy the private VFS created for the rbu handle passed as the only ** argument by an earlier call to rbuCreateVfs(). */ static void rbuDeleteVfs(sqlite3rbu *p){ if( p->zVfsName ){ sqlite3rbu_destroy_vfs(p->zVfsName); p->zVfsName = 0; } } /* ** Open and return a new RBU handle. */ SQLITE_API sqlite3rbu *SQLITE_STDCALL sqlite3rbu_open( const char *zTarget, const char *zRbu, const char *zState ){ sqlite3rbu *p; int nTarget = strlen(zTarget); int nRbu = strlen(zRbu); int nState = zState ? strlen(zState) : 0; p = (sqlite3rbu*)sqlite3_malloc(sizeof(sqlite3rbu)+nTarget+1+nRbu+1+nState+1); if( p ){ RbuState *pState = 0; /* Create the custom VFS. */ memset(p, 0, sizeof(sqlite3rbu)); rbuCreateVfs(p); /* Open the target database */ if( p->rc==SQLITE_OK ){ p->zTarget = (char*)&p[1]; memcpy(p->zTarget, zTarget, nTarget+1); p->zRbu = &p->zTarget[nTarget+1]; memcpy(p->zRbu, zRbu, nRbu+1); if( zState ){ p->zState = &p->zRbu[nRbu+1]; memcpy(p->zState, zState, nState+1); } rbuOpenDatabase(p); } /* If it has not already been created, create the rbu_state table */ rbuMPrintfExec(p, p->dbRbu, RBU_CREATE_STATE, p->zStateDb); if( p->rc==SQLITE_OK ){ pState = rbuLoadState(p); assert( pState || p->rc!=SQLITE_OK ); if( p->rc==SQLITE_OK ){ if( pState->eStage==0 ){ rbuDeleteOalFile(p); p->eStage = RBU_STAGE_OAL; }else{ p->eStage = pState->eStage; } p->nProgress = pState->nProgress; p->iOalSz = pState->iOalSz; } } assert( p->rc!=SQLITE_OK || p->eStage!=0 ); if( p->rc==SQLITE_OK && p->pTargetFd->pWalFd ){ if( p->eStage==RBU_STAGE_OAL ){ p->rc = SQLITE_ERROR; p->zErrmsg = sqlite3_mprintf("cannot update wal mode database"); }else if( p->eStage==RBU_STAGE_MOVE ){ p->eStage = RBU_STAGE_CKPT; p->nStep = 0; } } if( p->rc==SQLITE_OK && (p->eStage==RBU_STAGE_OAL || p->eStage==RBU_STAGE_MOVE) && pState->eStage!=0 && p->pTargetFd->iCookie!=pState->iCookie ){ /* At this point (pTargetFd->iCookie) contains the value of the ** change-counter cookie (the thing that gets incremented when a ** transaction is committed in rollback mode) currently stored on ** page 1 of the database file. */ p->rc = SQLITE_BUSY; p->zErrmsg = sqlite3_mprintf("database modified during rbu update"); } if( p->rc==SQLITE_OK ){ if( p->eStage==RBU_STAGE_OAL ){ /* Open transactions both databases. The *-oal file is opened or ** created at this point. */ p->rc = sqlite3_exec(p->dbMain, "BEGIN IMMEDIATE", 0, 0, &p->zErrmsg); if( p->rc==SQLITE_OK ){ p->rc = sqlite3_exec(p->dbRbu, "BEGIN IMMEDIATE", 0, 0, &p->zErrmsg); } /* Point the object iterator at the first object */ if( p->rc==SQLITE_OK ){ p->rc = rbuObjIterFirst(p, &p->objiter); } /* If the RBU database contains no data_xxx tables, declare the RBU ** update finished. */ if( p->rc==SQLITE_OK && p->objiter.zTbl==0 ){ p->rc = SQLITE_DONE; } if( p->rc==SQLITE_OK ){ rbuSetupOal(p, pState); } }else if( p->eStage==RBU_STAGE_MOVE ){ /* no-op */ }else if( p->eStage==RBU_STAGE_CKPT ){ rbuSetupCheckpoint(p, pState); }else if( p->eStage==RBU_STAGE_DONE ){ p->rc = SQLITE_DONE; }else{ p->rc = SQLITE_CORRUPT; } } rbuFreeState(pState); } return p; } /* ** Return the database handle used by pRbu. */ SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3rbu_db(sqlite3rbu *pRbu, int bRbu){ sqlite3 *db = 0; if( pRbu ){ db = (bRbu ? pRbu->dbRbu : pRbu->dbMain); } return db; } /* ** If the error code currently stored in the RBU handle is SQLITE_CONSTRAINT, ** then edit any error message string so as to remove all occurrences of ** the pattern "rbu_imp_[0-9]*". */ static void rbuEditErrmsg(sqlite3rbu *p){ if( p->rc==SQLITE_CONSTRAINT && p->zErrmsg ){ int i; int nErrmsg = strlen(p->zErrmsg); for(i=0; i<(nErrmsg-8); i++){ if( memcmp(&p->zErrmsg[i], "rbu_imp_", 8)==0 ){ int nDel = 8; while( p->zErrmsg[i+nDel]>='0' && p->zErrmsg[i+nDel]<='9' ) nDel++; memmove(&p->zErrmsg[i], &p->zErrmsg[i+nDel], nErrmsg + 1 - i - nDel); nErrmsg -= nDel; } } } } /* ** Close the RBU handle. */ SQLITE_API int SQLITE_STDCALL sqlite3rbu_close(sqlite3rbu *p, char **pzErrmsg){ int rc; if( p ){ /* Commit the transaction to the *-oal file. */ if( p->rc==SQLITE_OK && p->eStage==RBU_STAGE_OAL ){ p->rc = sqlite3_exec(p->dbMain, "COMMIT", 0, 0, &p->zErrmsg); } rbuSaveState(p, p->eStage); if( p->rc==SQLITE_OK && p->eStage==RBU_STAGE_OAL ){ p->rc = sqlite3_exec(p->dbRbu, "COMMIT", 0, 0, &p->zErrmsg); } /* Close any open statement handles. */ rbuObjIterFinalize(&p->objiter); /* Close the open database handle and VFS object. */ sqlite3_close(p->dbMain); sqlite3_close(p->dbRbu); rbuDeleteVfs(p); sqlite3_free(p->aBuf); sqlite3_free(p->aFrame); rbuEditErrmsg(p); rc = p->rc; *pzErrmsg = p->zErrmsg; sqlite3_free(p); }else{ rc = SQLITE_NOMEM; *pzErrmsg = 0; } return rc; } /* ** Return the total number of key-value operations (inserts, deletes or ** updates) that have been performed on the target database since the ** current RBU update was started. */ SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3rbu_progress(sqlite3rbu *pRbu){ return pRbu->nProgress; } /************************************************************************** ** Beginning of RBU VFS shim methods. The VFS shim modifies the behaviour ** of a standard VFS in the following ways: ** ** 1. Whenever the first page of a main database file is read or ** written, the value of the change-counter cookie is stored in ** rbu_file.iCookie. Similarly, the value of the "write-version" ** database header field is stored in rbu_file.iWriteVer. This ensures ** that the values are always trustworthy within an open transaction. ** ** 2. Whenever an SQLITE_OPEN_WAL file is opened, the (rbu_file.pWalFd) ** member variable of the associated database file descriptor is set ** to point to the new file. A mutex protected linked list of all main ** db fds opened using a particular RBU VFS is maintained at ** rbu_vfs.pMain to facilitate this. ** ** 3. Using a new file-control "SQLITE_FCNTL_RBU", a main db rbu_file ** object can be marked as the target database of an RBU update. This ** turns on the following extra special behaviour: ** ** 3a. If xAccess() is called to check if there exists a *-wal file ** associated with an RBU target database currently in RBU_STAGE_OAL ** stage (preparing the *-oal file), the following special handling ** applies: ** ** * if the *-wal file does exist, return SQLITE_CANTOPEN. An RBU ** target database may not be in wal mode already. ** ** * if the *-wal file does not exist, set the output parameter to ** non-zero (to tell SQLite that it does exist) anyway. ** ** Then, when xOpen() is called to open the *-wal file associated with ** the RBU target in RBU_STAGE_OAL stage, instead of opening the *-wal ** file, the rbu vfs opens the corresponding *-oal file instead. ** ** 3b. The *-shm pages returned by xShmMap() for a target db file in ** RBU_STAGE_OAL mode are actually stored in heap memory. This is to ** avoid creating a *-shm file on disk. Additionally, xShmLock() calls ** are no-ops on target database files in RBU_STAGE_OAL mode. This is ** because assert() statements in some VFS implementations fail if ** xShmLock() is called before xShmMap(). ** ** 3c. If an EXCLUSIVE lock is attempted on a target database file in any ** mode except RBU_STAGE_DONE (all work completed and checkpointed), it ** fails with an SQLITE_BUSY error. This is to stop RBU connections ** from automatically checkpointing a *-wal (or *-oal) file from within ** sqlite3_close(). ** ** 3d. In RBU_STAGE_CAPTURE mode, all xRead() calls on the wal file, and ** all xWrite() calls on the target database file perform no IO. ** Instead the frame and page numbers that would be read and written ** are recorded. Additionally, successful attempts to obtain exclusive ** xShmLock() WRITER, CHECKPOINTER and READ0 locks on the target ** database file are recorded. xShmLock() calls to unlock the same ** locks are no-ops (so that once obtained, these locks are never ** relinquished). Finally, calls to xSync() on the target database ** file fail with SQLITE_INTERNAL errors. */ static void rbuUnlockShm(rbu_file *p){ if( p->pRbu ){ int (*xShmLock)(sqlite3_file*,int,int,int) = p->pReal->pMethods->xShmLock; int i; for(i=0; i<SQLITE_SHM_NLOCK;i++){ if( (1<<i) & p->pRbu->mLock ){ xShmLock(p->pReal, i, 1, SQLITE_SHM_UNLOCK|SQLITE_SHM_EXCLUSIVE); } } p->pRbu->mLock = 0; } } /* ** Close an rbu file. */ static int rbuVfsClose(sqlite3_file *pFile){ rbu_file *p = (rbu_file*)pFile; int rc; int i; /* Free the contents of the apShm[] array. And the array itself. */ for(i=0; i<p->nShm; i++){ sqlite3_free(p->apShm[i]); } sqlite3_free(p->apShm); p->apShm = 0; sqlite3_free(p->zDel); if( p->openFlags & SQLITE_OPEN_MAIN_DB ){ rbu_file **pp; sqlite3_mutex_enter(p->pRbuVfs->mutex); for(pp=&p->pRbuVfs->pMain; *pp!=p; pp=&((*pp)->pMainNext)); *pp = p->pMainNext; sqlite3_mutex_leave(p->pRbuVfs->mutex); rbuUnlockShm(p); p->pReal->pMethods->xShmUnmap(p->pReal, 0); } /* Close the underlying file handle */ rc = p->pReal->pMethods->xClose(p->pReal); return rc; } /* ** Read and return an unsigned 32-bit big-endian integer from the buffer ** passed as the only argument. */ static u32 rbuGetU32(u8 *aBuf){ return ((u32)aBuf[0] << 24) + ((u32)aBuf[1] << 16) + ((u32)aBuf[2] << 8) + ((u32)aBuf[3]); } /* ** Read data from an rbuVfs-file. */ static int rbuVfsRead( sqlite3_file *pFile, void *zBuf, int iAmt, sqlite_int64 iOfst ){ rbu_file *p = (rbu_file*)pFile; sqlite3rbu *pRbu = p->pRbu; int rc; if( pRbu && pRbu->eStage==RBU_STAGE_CAPTURE ){ assert( p->openFlags & SQLITE_OPEN_WAL ); rc = rbuCaptureWalRead(p->pRbu, iOfst, iAmt); }else{ if( pRbu && pRbu->eStage==RBU_STAGE_OAL && (p->openFlags & SQLITE_OPEN_WAL) && iOfst>=pRbu->iOalSz ){ rc = SQLITE_OK; memset(zBuf, 0, iAmt); }else{ rc = p->pReal->pMethods->xRead(p->pReal, zBuf, iAmt, iOfst); } if( rc==SQLITE_OK && iOfst==0 && (p->openFlags & SQLITE_OPEN_MAIN_DB) ){ /* These look like magic numbers. But they are stable, as they are part ** of the definition of the SQLite file format, which may not change. */ u8 *pBuf = (u8*)zBuf; p->iCookie = rbuGetU32(&pBuf[24]); p->iWriteVer = pBuf[19]; } } return rc; } /* ** Write data to an rbuVfs-file. */ static int rbuVfsWrite( sqlite3_file *pFile, const void *zBuf, int iAmt, sqlite_int64 iOfst ){ rbu_file *p = (rbu_file*)pFile; sqlite3rbu *pRbu = p->pRbu; int rc; if( pRbu && pRbu->eStage==RBU_STAGE_CAPTURE ){ assert( p->openFlags & SQLITE_OPEN_MAIN_DB ); rc = rbuCaptureDbWrite(p->pRbu, iOfst); }else{ if( pRbu && pRbu->eStage==RBU_STAGE_OAL && (p->openFlags & SQLITE_OPEN_WAL) && iOfst>=pRbu->iOalSz ){ pRbu->iOalSz = iAmt + iOfst; } rc = p->pReal->pMethods->xWrite(p->pReal, zBuf, iAmt, iOfst); if( rc==SQLITE_OK && iOfst==0 && (p->openFlags & SQLITE_OPEN_MAIN_DB) ){ /* These look like magic numbers. But they are stable, as they are part ** of the definition of the SQLite file format, which may not change. */ u8 *pBuf = (u8*)zBuf; p->iCookie = rbuGetU32(&pBuf[24]); p->iWriteVer = pBuf[19]; } } return rc; } /* ** Truncate an rbuVfs-file. */ static int rbuVfsTruncate(sqlite3_file *pFile, sqlite_int64 size){ rbu_file *p = (rbu_file*)pFile; return p->pReal->pMethods->xTruncate(p->pReal, size); } /* ** Sync an rbuVfs-file. */ static int rbuVfsSync(sqlite3_file *pFile, int flags){ rbu_file *p = (rbu_file *)pFile; if( p->pRbu && p->pRbu->eStage==RBU_STAGE_CAPTURE ){ if( p->openFlags & SQLITE_OPEN_MAIN_DB ){ return SQLITE_INTERNAL; } return SQLITE_OK; } return p->pReal->pMethods->xSync(p->pReal, flags); } /* ** Return the current file-size of an rbuVfs-file. */ static int rbuVfsFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){ rbu_file *p = (rbu_file *)pFile; return p->pReal->pMethods->xFileSize(p->pReal, pSize); } /* ** Lock an rbuVfs-file. */ static int rbuVfsLock(sqlite3_file *pFile, int eLock){ rbu_file *p = (rbu_file*)pFile; sqlite3rbu *pRbu = p->pRbu; int rc = SQLITE_OK; assert( p->openFlags & (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_TEMP_DB) ); if( pRbu && eLock==SQLITE_LOCK_EXCLUSIVE && pRbu->eStage!=RBU_STAGE_DONE ){ /* Do not allow EXCLUSIVE locks. Preventing SQLite from taking this ** prevents it from checkpointing the database from sqlite3_close(). */ rc = SQLITE_BUSY; }else{ rc = p->pReal->pMethods->xLock(p->pReal, eLock); } return rc; } /* ** Unlock an rbuVfs-file. */ static int rbuVfsUnlock(sqlite3_file *pFile, int eLock){ rbu_file *p = (rbu_file *)pFile; return p->pReal->pMethods->xUnlock(p->pReal, eLock); } /* ** Check if another file-handle holds a RESERVED lock on an rbuVfs-file. */ static int rbuVfsCheckReservedLock(sqlite3_file *pFile, int *pResOut){ rbu_file *p = (rbu_file *)pFile; return p->pReal->pMethods->xCheckReservedLock(p->pReal, pResOut); } /* ** File control method. For custom operations on an rbuVfs-file. */ static int rbuVfsFileControl(sqlite3_file *pFile, int op, void *pArg){ rbu_file *p = (rbu_file *)pFile; int (*xControl)(sqlite3_file*,int,void*) = p->pReal->pMethods->xFileControl; int rc; assert( p->openFlags & (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_TEMP_DB) || p->openFlags & (SQLITE_OPEN_TRANSIENT_DB|SQLITE_OPEN_TEMP_JOURNAL) ); if( op==SQLITE_FCNTL_RBU ){ sqlite3rbu *pRbu = (sqlite3rbu*)pArg; /* First try to find another RBU vfs lower down in the vfs stack. If ** one is found, this vfs will operate in pass-through mode. The lower ** level vfs will do the special RBU handling. */ rc = xControl(p->pReal, op, pArg); if( rc==SQLITE_NOTFOUND ){ /* Now search for a zipvfs instance lower down in the VFS stack. If ** one is found, this is an error. */ void *dummy = 0; rc = xControl(p->pReal, SQLITE_FCNTL_ZIPVFS, &dummy); if( rc==SQLITE_OK ){ rc = SQLITE_ERROR; pRbu->zErrmsg = sqlite3_mprintf("rbu/zipvfs setup error"); }else if( rc==SQLITE_NOTFOUND ){ pRbu->pTargetFd = p; p->pRbu = pRbu; if( p->pWalFd ) p->pWalFd->pRbu = pRbu; rc = SQLITE_OK; } } return rc; } rc = xControl(p->pReal, op, pArg); if( rc==SQLITE_OK && op==SQLITE_FCNTL_VFSNAME ){ rbu_vfs *pRbuVfs = p->pRbuVfs; char *zIn = *(char**)pArg; char *zOut = sqlite3_mprintf("rbu(%s)/%z", pRbuVfs->base.zName, zIn); *(char**)pArg = zOut; if( zOut==0 ) rc = SQLITE_NOMEM; } return rc; } /* ** Return the sector-size in bytes for an rbuVfs-file. */ static int rbuVfsSectorSize(sqlite3_file *pFile){ rbu_file *p = (rbu_file *)pFile; return p->pReal->pMethods->xSectorSize(p->pReal); } /* ** Return the device characteristic flags supported by an rbuVfs-file. */ static int rbuVfsDeviceCharacteristics(sqlite3_file *pFile){ rbu_file *p = (rbu_file *)pFile; return p->pReal->pMethods->xDeviceCharacteristics(p->pReal); } /* ** Take or release a shared-memory lock. */ static int rbuVfsShmLock(sqlite3_file *pFile, int ofst, int n, int flags){ rbu_file *p = (rbu_file*)pFile; sqlite3rbu *pRbu = p->pRbu; int rc = SQLITE_OK; #ifdef SQLITE_AMALGAMATION assert( WAL_CKPT_LOCK==1 ); #endif assert( p->openFlags & (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_TEMP_DB) ); if( pRbu && (pRbu->eStage==RBU_STAGE_OAL || pRbu->eStage==RBU_STAGE_MOVE) ){ /* Magic number 1 is the WAL_CKPT_LOCK lock. Preventing SQLite from ** taking this lock also prevents any checkpoints from occurring. ** todo: really, it's not clear why this might occur, as ** wal_autocheckpoint ought to be turned off. */ if( ofst==WAL_LOCK_CKPT && n==1 ) rc = SQLITE_BUSY; }else{ int bCapture = 0; if( n==1 && (flags & SQLITE_SHM_EXCLUSIVE) && pRbu && pRbu->eStage==RBU_STAGE_CAPTURE && (ofst==WAL_LOCK_WRITE || ofst==WAL_LOCK_CKPT || ofst==WAL_LOCK_READ0) ){ bCapture = 1; } if( bCapture==0 || 0==(flags & SQLITE_SHM_UNLOCK) ){ rc = p->pReal->pMethods->xShmLock(p->pReal, ofst, n, flags); if( bCapture && rc==SQLITE_OK ){ pRbu->mLock |= (1 << ofst); } } } return rc; } /* ** Obtain a pointer to a mapping of a single 32KiB page of the *-shm file. */ static int rbuVfsShmMap( sqlite3_file *pFile, int iRegion, int szRegion, int isWrite, void volatile **pp ){ rbu_file *p = (rbu_file*)pFile; int rc = SQLITE_OK; int eStage = (p->pRbu ? p->pRbu->eStage : 0); /* If not in RBU_STAGE_OAL, allow this call to pass through. Or, if this ** rbu is in the RBU_STAGE_OAL state, use heap memory for *-shm space ** instead of a file on disk. */ assert( p->openFlags & (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_TEMP_DB) ); if( eStage==RBU_STAGE_OAL || eStage==RBU_STAGE_MOVE ){ if( iRegion<=p->nShm ){ int nByte = (iRegion+1) * sizeof(char*); char **apNew = (char**)sqlite3_realloc(p->apShm, nByte); if( apNew==0 ){ rc = SQLITE_NOMEM; }else{ memset(&apNew[p->nShm], 0, sizeof(char*) * (1 + iRegion - p->nShm)); |
︙ | ︙ | |||
160330 160331 160332 160333 160334 160335 160336 | return rc; } /* ** Memory barrier. */ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 160575 160576 160577 160578 160579 160580 160581 160582 160583 160584 160585 160586 160587 160588 160589 160590 160591 160592 160593 160594 160595 160596 160597 160598 160599 160600 160601 160602 160603 160604 160605 160606 160607 160608 160609 160610 160611 160612 160613 160614 160615 160616 160617 160618 160619 160620 160621 160622 160623 160624 160625 160626 160627 160628 160629 160630 160631 160632 160633 160634 160635 160636 160637 160638 160639 160640 160641 160642 160643 160644 160645 160646 160647 160648 160649 160650 160651 160652 160653 160654 160655 160656 160657 160658 160659 160660 160661 160662 160663 160664 | return rc; } /* ** Memory barrier. */ static void rbuVfsShmBarrier(sqlite3_file *pFile){ rbu_file *p = (rbu_file *)pFile; p->pReal->pMethods->xShmBarrier(p->pReal); } /* ** The xShmUnmap method. */ static int rbuVfsShmUnmap(sqlite3_file *pFile, int delFlag){ rbu_file *p = (rbu_file*)pFile; int rc = SQLITE_OK; int eStage = (p->pRbu ? p->pRbu->eStage : 0); assert( p->openFlags & (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_TEMP_DB) ); if( eStage==RBU_STAGE_OAL || eStage==RBU_STAGE_MOVE ){ /* no-op */ }else{ /* Release the checkpointer and writer locks */ rbuUnlockShm(p); rc = p->pReal->pMethods->xShmUnmap(p->pReal, delFlag); } return rc; } /* ** Given that zWal points to a buffer containing a wal file name passed to ** either the xOpen() or xAccess() VFS method, return a pointer to the ** file-handle opened by the same database connection on the corresponding ** database file. */ static rbu_file *rbuFindMaindb(rbu_vfs *pRbuVfs, const char *zWal){ rbu_file *pDb; sqlite3_mutex_enter(pRbuVfs->mutex); for(pDb=pRbuVfs->pMain; pDb && pDb->zWal!=zWal; pDb=pDb->pMainNext); sqlite3_mutex_leave(pRbuVfs->mutex); return pDb; } /* ** Open an rbu file handle. */ static int rbuVfsOpen( sqlite3_vfs *pVfs, const char *zName, sqlite3_file *pFile, int flags, int *pOutFlags ){ static sqlite3_io_methods rbuvfs_io_methods = { 2, /* iVersion */ rbuVfsClose, /* xClose */ rbuVfsRead, /* xRead */ rbuVfsWrite, /* xWrite */ rbuVfsTruncate, /* xTruncate */ rbuVfsSync, /* xSync */ rbuVfsFileSize, /* xFileSize */ rbuVfsLock, /* xLock */ rbuVfsUnlock, /* xUnlock */ rbuVfsCheckReservedLock, /* xCheckReservedLock */ rbuVfsFileControl, /* xFileControl */ rbuVfsSectorSize, /* xSectorSize */ rbuVfsDeviceCharacteristics, /* xDeviceCharacteristics */ rbuVfsShmMap, /* xShmMap */ rbuVfsShmLock, /* xShmLock */ rbuVfsShmBarrier, /* xShmBarrier */ rbuVfsShmUnmap /* xShmUnmap */ }; rbu_vfs *pRbuVfs = (rbu_vfs*)pVfs; sqlite3_vfs *pRealVfs = pRbuVfs->pRealVfs; rbu_file *pFd = (rbu_file *)pFile; int rc = SQLITE_OK; const char *zOpen = zName; memset(pFd, 0, sizeof(rbu_file)); pFd->pReal = (sqlite3_file*)&pFd[1]; pFd->pRbuVfs = pRbuVfs; pFd->openFlags = flags; if( zName ){ if( flags & SQLITE_OPEN_MAIN_DB ){ /* A main database has just been opened. The following block sets ** (pFd->zWal) to point to a buffer owned by SQLite that contains ** the name of the *-wal file this db connection will use. SQLite ** happens to pass a pointer to this buffer when using xAccess() |
︙ | ︙ | |||
160433 160434 160435 160436 160437 160438 160439 | }else{ while( *z==0 ) z++; } z += (n + 8 + 1); pFd->zWal = z; } else if( flags & SQLITE_OPEN_WAL ){ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 160678 160679 160680 160681 160682 160683 160684 160685 160686 160687 160688 160689 160690 160691 160692 160693 160694 160695 160696 160697 160698 160699 160700 160701 160702 160703 160704 160705 160706 160707 160708 160709 160710 160711 160712 160713 160714 160715 160716 160717 160718 160719 160720 160721 160722 160723 160724 160725 160726 160727 160728 160729 160730 160731 160732 160733 160734 160735 160736 160737 160738 160739 160740 160741 160742 160743 160744 160745 160746 160747 160748 160749 160750 160751 160752 160753 160754 160755 160756 160757 160758 160759 160760 160761 160762 160763 160764 160765 160766 160767 160768 160769 160770 160771 160772 160773 160774 160775 160776 160777 160778 160779 160780 160781 160782 160783 160784 160785 160786 160787 160788 160789 160790 160791 160792 160793 160794 160795 160796 160797 160798 160799 160800 160801 160802 160803 160804 160805 160806 160807 160808 160809 160810 160811 160812 160813 160814 160815 160816 160817 160818 160819 160820 160821 160822 160823 160824 160825 160826 160827 160828 160829 160830 160831 160832 160833 160834 160835 160836 160837 160838 160839 160840 160841 160842 160843 160844 160845 160846 160847 160848 160849 160850 160851 160852 160853 160854 160855 160856 160857 160858 160859 160860 160861 160862 160863 160864 160865 160866 160867 160868 160869 160870 160871 160872 160873 160874 160875 160876 160877 160878 160879 160880 160881 160882 160883 160884 160885 160886 160887 160888 160889 160890 160891 160892 160893 160894 160895 160896 160897 160898 160899 160900 160901 160902 160903 160904 160905 160906 160907 160908 160909 160910 160911 160912 160913 160914 160915 160916 160917 160918 160919 160920 160921 160922 160923 160924 160925 160926 160927 160928 160929 160930 160931 160932 160933 160934 160935 160936 160937 160938 160939 160940 160941 160942 160943 160944 160945 160946 160947 160948 | }else{ while( *z==0 ) z++; } z += (n + 8 + 1); pFd->zWal = z; } else if( flags & SQLITE_OPEN_WAL ){ rbu_file *pDb = rbuFindMaindb(pRbuVfs, zName); if( pDb ){ if( pDb->pRbu && pDb->pRbu->eStage==RBU_STAGE_OAL ){ /* This call is to open a *-wal file. Intead, open the *-oal. This ** code ensures that the string passed to xOpen() is terminated by a ** pair of '\0' bytes in case the VFS attempts to extract a URI ** parameter from it. */ int nCopy = strlen(zName); char *zCopy = sqlite3_malloc(nCopy+2); if( zCopy ){ memcpy(zCopy, zName, nCopy); zCopy[nCopy-3] = 'o'; zCopy[nCopy] = '\0'; zCopy[nCopy+1] = '\0'; zOpen = (const char*)(pFd->zDel = zCopy); }else{ rc = SQLITE_NOMEM; } pFd->pRbu = pDb->pRbu; } pDb->pWalFd = pFd; } } } if( rc==SQLITE_OK ){ rc = pRealVfs->xOpen(pRealVfs, zOpen, pFd->pReal, flags, pOutFlags); } if( pFd->pReal->pMethods ){ /* The xOpen() operation has succeeded. Set the sqlite3_file.pMethods ** pointer and, if the file is a main database file, link it into the ** mutex protected linked list of all such files. */ pFile->pMethods = &rbuvfs_io_methods; if( flags & SQLITE_OPEN_MAIN_DB ){ sqlite3_mutex_enter(pRbuVfs->mutex); pFd->pMainNext = pRbuVfs->pMain; pRbuVfs->pMain = pFd; sqlite3_mutex_leave(pRbuVfs->mutex); } }else{ sqlite3_free(pFd->zDel); } return rc; } /* ** Delete the file located at zPath. */ static int rbuVfsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ sqlite3_vfs *pRealVfs = ((rbu_vfs*)pVfs)->pRealVfs; return pRealVfs->xDelete(pRealVfs, zPath, dirSync); } /* ** Test for access permissions. Return true if the requested permission ** is available, or false otherwise. */ static int rbuVfsAccess( sqlite3_vfs *pVfs, const char *zPath, int flags, int *pResOut ){ rbu_vfs *pRbuVfs = (rbu_vfs*)pVfs; sqlite3_vfs *pRealVfs = pRbuVfs->pRealVfs; int rc; rc = pRealVfs->xAccess(pRealVfs, zPath, flags, pResOut); /* If this call is to check if a *-wal file associated with an RBU target ** database connection exists, and the RBU update is in RBU_STAGE_OAL, ** the following special handling is activated: ** ** a) if the *-wal file does exist, return SQLITE_CANTOPEN. This ** ensures that the RBU extension never tries to update a database ** in wal mode, even if the first page of the database file has ** been damaged. ** ** b) if the *-wal file does not exist, claim that it does anyway, ** causing SQLite to call xOpen() to open it. This call will also ** be intercepted (see the rbuVfsOpen() function) and the *-oal ** file opened instead. */ if( rc==SQLITE_OK && flags==SQLITE_ACCESS_EXISTS ){ rbu_file *pDb = rbuFindMaindb(pRbuVfs, zPath); if( pDb && pDb->pRbu && pDb->pRbu->eStage==RBU_STAGE_OAL ){ if( *pResOut ){ rc = SQLITE_CANTOPEN; }else{ *pResOut = 1; } } } return rc; } /* ** Populate buffer zOut with the full canonical pathname corresponding ** to the pathname in zPath. zOut is guaranteed to point to a buffer ** of at least (DEVSYM_MAX_PATHNAME+1) bytes. */ static int rbuVfsFullPathname( sqlite3_vfs *pVfs, const char *zPath, int nOut, char *zOut ){ sqlite3_vfs *pRealVfs = ((rbu_vfs*)pVfs)->pRealVfs; return pRealVfs->xFullPathname(pRealVfs, zPath, nOut, zOut); } #ifndef SQLITE_OMIT_LOAD_EXTENSION /* ** Open the dynamic library located at zPath and return a handle. */ static void *rbuVfsDlOpen(sqlite3_vfs *pVfs, const char *zPath){ sqlite3_vfs *pRealVfs = ((rbu_vfs*)pVfs)->pRealVfs; return pRealVfs->xDlOpen(pRealVfs, zPath); } /* ** Populate the buffer zErrMsg (size nByte bytes) with a human readable ** utf-8 string describing the most recent error encountered associated ** with dynamic libraries. */ static void rbuVfsDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){ sqlite3_vfs *pRealVfs = ((rbu_vfs*)pVfs)->pRealVfs; pRealVfs->xDlError(pRealVfs, nByte, zErrMsg); } /* ** Return a pointer to the symbol zSymbol in the dynamic library pHandle. */ static void (*rbuVfsDlSym( sqlite3_vfs *pVfs, void *pArg, const char *zSym ))(void){ sqlite3_vfs *pRealVfs = ((rbu_vfs*)pVfs)->pRealVfs; return pRealVfs->xDlSym(pRealVfs, pArg, zSym); } /* ** Close the dynamic library handle pHandle. */ static void rbuVfsDlClose(sqlite3_vfs *pVfs, void *pHandle){ sqlite3_vfs *pRealVfs = ((rbu_vfs*)pVfs)->pRealVfs; pRealVfs->xDlClose(pRealVfs, pHandle); } #endif /* SQLITE_OMIT_LOAD_EXTENSION */ /* ** Populate the buffer pointed to by zBufOut with nByte bytes of ** random data. */ static int rbuVfsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ sqlite3_vfs *pRealVfs = ((rbu_vfs*)pVfs)->pRealVfs; return pRealVfs->xRandomness(pRealVfs, nByte, zBufOut); } /* ** Sleep for nMicro microseconds. Return the number of microseconds ** actually slept. */ static int rbuVfsSleep(sqlite3_vfs *pVfs, int nMicro){ sqlite3_vfs *pRealVfs = ((rbu_vfs*)pVfs)->pRealVfs; return pRealVfs->xSleep(pRealVfs, nMicro); } /* ** Return the current time as a Julian Day number in *pTimeOut. */ static int rbuVfsCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){ sqlite3_vfs *pRealVfs = ((rbu_vfs*)pVfs)->pRealVfs; return pRealVfs->xCurrentTime(pRealVfs, pTimeOut); } /* ** No-op. */ static int rbuVfsGetLastError(sqlite3_vfs *pVfs, int a, char *b){ return 0; } /* ** Deregister and destroy an RBU vfs created by an earlier call to ** sqlite3rbu_create_vfs(). */ SQLITE_API void SQLITE_STDCALL sqlite3rbu_destroy_vfs(const char *zName){ sqlite3_vfs *pVfs = sqlite3_vfs_find(zName); if( pVfs && pVfs->xOpen==rbuVfsOpen ){ sqlite3_mutex_free(((rbu_vfs*)pVfs)->mutex); sqlite3_vfs_unregister(pVfs); sqlite3_free(pVfs); } } /* ** Create an RBU VFS named zName that accesses the underlying file-system ** via existing VFS zParent. The new object is registered as a non-default ** VFS with SQLite before returning. */ SQLITE_API int SQLITE_STDCALL sqlite3rbu_create_vfs(const char *zName, const char *zParent){ /* Template for VFS */ static sqlite3_vfs vfs_template = { 1, /* iVersion */ 0, /* szOsFile */ 0, /* mxPathname */ 0, /* pNext */ 0, /* zName */ 0, /* pAppData */ rbuVfsOpen, /* xOpen */ rbuVfsDelete, /* xDelete */ rbuVfsAccess, /* xAccess */ rbuVfsFullPathname, /* xFullPathname */ #ifndef SQLITE_OMIT_LOAD_EXTENSION rbuVfsDlOpen, /* xDlOpen */ rbuVfsDlError, /* xDlError */ rbuVfsDlSym, /* xDlSym */ rbuVfsDlClose, /* xDlClose */ #else 0, 0, 0, 0, #endif rbuVfsRandomness, /* xRandomness */ rbuVfsSleep, /* xSleep */ rbuVfsCurrentTime, /* xCurrentTime */ rbuVfsGetLastError, /* xGetLastError */ 0, /* xCurrentTimeInt64 (version 2) */ 0, 0, 0 /* Unimplemented version 3 methods */ }; rbu_vfs *pNew = 0; /* Newly allocated VFS */ int nName; int rc = SQLITE_OK; int nByte; nName = strlen(zName); nByte = sizeof(rbu_vfs) + nName + 1; pNew = (rbu_vfs*)sqlite3_malloc(nByte); if( pNew==0 ){ rc = SQLITE_NOMEM; }else{ sqlite3_vfs *pParent; /* Parent VFS */ memset(pNew, 0, nByte); pParent = sqlite3_vfs_find(zParent); if( pParent==0 ){ rc = SQLITE_NOTFOUND; }else{ char *zSpace; memcpy(&pNew->base, &vfs_template, sizeof(sqlite3_vfs)); pNew->base.mxPathname = pParent->mxPathname; pNew->base.szOsFile = sizeof(rbu_file) + pParent->szOsFile; pNew->pRealVfs = pParent; pNew->base.zName = (const char*)(zSpace = (char*)&pNew[1]); memcpy(zSpace, zName, nName); /* Allocate the mutex and register the new VFS (not as the default) */ pNew->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_RECURSIVE); if( pNew->mutex==0 ){ |
︙ | ︙ | |||
160715 160716 160717 160718 160719 160720 160721 | return rc; } /**************************************************************************/ | | | | 160960 160961 160962 160963 160964 160965 160966 160967 160968 160969 160970 160971 160972 160973 160974 160975 160976 | return rc; } /**************************************************************************/ #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_RBU) */ /************** End of sqlite3rbu.c ******************************************/ /************** Begin file dbstat.c ******************************************/ /* ** 2010 July 12 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** |
︙ | ︙ | |||
160739 160740 160741 160742 160743 160744 160745 160746 160747 160748 160749 160750 160751 160752 | ** ** The dbstat virtual table is used to extract low-level formatting ** information from an SQLite database in order to implement the ** "sqlite3_analyzer" utility. See the ../tool/spaceanal.tcl script ** for an example implementation. */ #if (defined(SQLITE_ENABLE_DBSTAT_VTAB) || defined(SQLITE_TEST)) \ && !defined(SQLITE_OMIT_VIRTUALTABLE) /* ** Page paths: ** ** The value of the 'path' column describes the path taken from the | > | 160984 160985 160986 160987 160988 160989 160990 160991 160992 160993 160994 160995 160996 160997 160998 | ** ** The dbstat virtual table is used to extract low-level formatting ** information from an SQLite database in order to implement the ** "sqlite3_analyzer" utility. See the ../tool/spaceanal.tcl script ** for an example implementation. */ /* #include "sqliteInt.h" ** Requires access to internal data structures ** */ #if (defined(SQLITE_ENABLE_DBSTAT_VTAB) || defined(SQLITE_TEST)) \ && !defined(SQLITE_OMIT_VIRTUALTABLE) /* ** Page paths: ** ** The value of the 'path' column describes the path taken from the |
︙ | ︙ |
Changes to src/sqlite3.h.
︙ | ︙ | |||
107 108 109 110 111 112 113 | ** string contains the date and time of the check-in (UTC) and an SHA1 ** hash of the entire source tree. ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ | | | | 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | ** string contains the date and time of the check-in (UTC) and an SHA1 ** hash of the entire source tree. ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.8.11.1" #define SQLITE_VERSION_NUMBER 3008011 #define SQLITE_SOURCE_ID "2015-07-29 20:00:57 cf538e2783e468bbc25e7cb2a9ee64d3e0e80b2f" /* ** CAPI3REF: Run-Time Library Version Numbers ** KEYWORDS: sqlite3_version, sqlite3_sourceid ** ** These interfaces provide the same information as the [SQLITE_VERSION], ** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros |
︙ | ︙ | |||
963 964 965 966 967 968 969 | ** circumstances in order to fix a problem with priority inversion. ** Applications should <em>not</em> use this file-control. ** ** <li>[[SQLITE_FCNTL_ZIPVFS]] ** The [SQLITE_FCNTL_ZIPVFS] opcode is implemented by zipvfs only. All other ** VFS should return SQLITE_NOTFOUND for this opcode. ** | | | | | 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 | ** circumstances in order to fix a problem with priority inversion. ** Applications should <em>not</em> use this file-control. ** ** <li>[[SQLITE_FCNTL_ZIPVFS]] ** The [SQLITE_FCNTL_ZIPVFS] opcode is implemented by zipvfs only. All other ** VFS should return SQLITE_NOTFOUND for this opcode. ** ** <li>[[SQLITE_FCNTL_RBU]] ** The [SQLITE_FCNTL_RBU] opcode is implemented by the special VFS used by ** the RBU extension only. All other VFS should return SQLITE_NOTFOUND for ** this opcode. ** </ul> */ #define SQLITE_FCNTL_LOCKSTATE 1 #define SQLITE_FCNTL_GET_LOCKPROXYFILE 2 #define SQLITE_FCNTL_SET_LOCKPROXYFILE 3 #define SQLITE_FCNTL_LAST_ERRNO 4 |
︙ | ︙ | |||
993 994 995 996 997 998 999 | #define SQLITE_FCNTL_TRACE 19 #define SQLITE_FCNTL_HAS_MOVED 20 #define SQLITE_FCNTL_SYNC 21 #define SQLITE_FCNTL_COMMIT_PHASETWO 22 #define SQLITE_FCNTL_WIN32_SET_HANDLE 23 #define SQLITE_FCNTL_WAL_BLOCK 24 #define SQLITE_FCNTL_ZIPVFS 25 | | | 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 | #define SQLITE_FCNTL_TRACE 19 #define SQLITE_FCNTL_HAS_MOVED 20 #define SQLITE_FCNTL_SYNC 21 #define SQLITE_FCNTL_COMMIT_PHASETWO 22 #define SQLITE_FCNTL_WIN32_SET_HANDLE 23 #define SQLITE_FCNTL_WAL_BLOCK 24 #define SQLITE_FCNTL_ZIPVFS 25 #define SQLITE_FCNTL_RBU 26 /* deprecated names */ #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE #define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO |
︙ | ︙ | |||
3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 | SQLITE_API int SQLITE_STDCALL sqlite3_bind_null(sqlite3_stmt*, int); SQLITE_API int SQLITE_STDCALL sqlite3_bind_text(sqlite3_stmt*,int,const char*,int,void(*)(void*)); SQLITE_API int SQLITE_STDCALL sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*)); SQLITE_API int SQLITE_STDCALL sqlite3_bind_text64(sqlite3_stmt*, int, const char*, sqlite3_uint64, void(*)(void*), unsigned char encoding); SQLITE_API int SQLITE_STDCALL sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); SQLITE_API int SQLITE_STDCALL sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); /* ** CAPI3REF: Number Of SQL Parameters ** METHOD: sqlite3_stmt ** ** ^This routine can be used to find the number of [SQL parameters] ** in a [prepared statement]. SQL parameters are tokens of the | > | 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 | SQLITE_API int SQLITE_STDCALL sqlite3_bind_null(sqlite3_stmt*, int); SQLITE_API int SQLITE_STDCALL sqlite3_bind_text(sqlite3_stmt*,int,const char*,int,void(*)(void*)); SQLITE_API int SQLITE_STDCALL sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*)); SQLITE_API int SQLITE_STDCALL sqlite3_bind_text64(sqlite3_stmt*, int, const char*, sqlite3_uint64, void(*)(void*), unsigned char encoding); SQLITE_API int SQLITE_STDCALL sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); SQLITE_API int SQLITE_STDCALL sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); SQLITE_API int SQLITE_STDCALL sqlite3_bind_zeroblob64(sqlite3_stmt*, int, sqlite3_uint64); /* ** CAPI3REF: Number Of SQL Parameters ** METHOD: sqlite3_stmt ** ** ^This routine can be used to find the number of [SQL parameters] ** in a [prepared statement]. SQL parameters are tokens of the |
︙ | ︙ | |||
4530 4531 4532 4533 4534 4535 4536 | ** Refer to the [SQL parameter] documentation for additional information. ** ** ^The sqlite3_result_blob() interface sets the result from ** an application-defined function to be the BLOB whose content is pointed ** to by the second parameter and which is N bytes long where N is the ** third parameter. ** | | | | | 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 | ** Refer to the [SQL parameter] documentation for additional information. ** ** ^The sqlite3_result_blob() interface sets the result from ** an application-defined function to be the BLOB whose content is pointed ** to by the second parameter and which is N bytes long where N is the ** third parameter. ** ** ^The sqlite3_result_zeroblob(C,N) and sqlite3_result_zeroblob64(C,N) ** interfaces set the result of the application-defined function to be ** a BLOB containing all zero bytes and N bytes in size. ** ** ^The sqlite3_result_double() interface sets the result from ** an application-defined function to be a floating point value specified ** by its 2nd argument. ** ** ^The sqlite3_result_error() and sqlite3_result_error16() functions ** cause the implemented SQL function to throw an exception. |
︙ | ︙ | |||
4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 4660 | SQLITE_API void SQLITE_STDCALL sqlite3_result_text64(sqlite3_context*, const char*,sqlite3_uint64, void(*)(void*), unsigned char encoding); SQLITE_API void SQLITE_STDCALL sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*)); SQLITE_API void SQLITE_STDCALL sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*)); SQLITE_API void SQLITE_STDCALL sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*)); SQLITE_API void SQLITE_STDCALL sqlite3_result_value(sqlite3_context*, sqlite3_value*); SQLITE_API void SQLITE_STDCALL sqlite3_result_zeroblob(sqlite3_context*, int n); /* ** CAPI3REF: Define New Collating Sequences ** METHOD: sqlite3 ** ** ^These functions add, remove, or modify a [collation] associated ** with the [database connection] specified as the first argument. | > | 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 | SQLITE_API void SQLITE_STDCALL sqlite3_result_text64(sqlite3_context*, const char*,sqlite3_uint64, void(*)(void*), unsigned char encoding); SQLITE_API void SQLITE_STDCALL sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*)); SQLITE_API void SQLITE_STDCALL sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*)); SQLITE_API void SQLITE_STDCALL sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*)); SQLITE_API void SQLITE_STDCALL sqlite3_result_value(sqlite3_context*, sqlite3_value*); SQLITE_API void SQLITE_STDCALL sqlite3_result_zeroblob(sqlite3_context*, int n); SQLITE_API int SQLITE_STDCALL sqlite3_result_zeroblob64(sqlite3_context*, sqlite3_uint64 n); /* ** CAPI3REF: Define New Collating Sequences ** METHOD: sqlite3 ** ** ^These functions add, remove, or modify a [collation] associated ** with the [database connection] specified as the first argument. |
︙ | ︙ |
Changes to src/stash.c.
︙ | ︙ | |||
501 502 503 504 505 506 507 508 509 510 511 512 513 514 | Stmt q; db_prepare(&q,"SELECT origname FROM stashfile WHERE stashid=%d", stashid); while( db_step(&q)==SQLITE_ROW ){ newArgv[i++] = mprintf("%s%s", g.zLocalRoot, db_column_text(&q, 0)); } db_finalize(&q); newArgv[0] = g.argv[0]; g.argv = newArgv; g.argc = nFile+2; if( nFile==0 ) return; } g.argv[1] = "revert"; revert_cmd(); }else | > | 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 | Stmt q; db_prepare(&q,"SELECT origname FROM stashfile WHERE stashid=%d", stashid); while( db_step(&q)==SQLITE_ROW ){ newArgv[i++] = mprintf("%s%s", g.zLocalRoot, db_column_text(&q, 0)); } db_finalize(&q); newArgv[0] = g.argv[0]; newArgv[1] = 0; g.argv = newArgv; g.argc = nFile+2; if( nFile==0 ) return; } g.argv[1] = "revert"; revert_cmd(); }else |
︙ | ︙ |
Changes to src/statrep.c.
︙ | ︙ | |||
460 461 462 463 464 465 466 | int nEventTotal = 0; /* Total event count */ int rowClass = 0; /* counter for alternating row colors */ int nMaxEvents = 1; /* max number of events for all rows. */ Blob userFilter = empty_blob; /* Optional user=johndoe query string */ static const char *const daysOfWeek[] = { | | | | | | | | | | | > | | 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 | int nEventTotal = 0; /* Total event count */ int rowClass = 0; /* counter for alternating row colors */ int nMaxEvents = 1; /* max number of events for all rows. */ Blob userFilter = empty_blob; /* Optional user=johndoe query string */ static const char *const daysOfWeek[] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }; stats_report_init_view(); if( zUserName ){ blob_appendf(&userFilter, "user=%s", zUserName); } db_prepare(&query, "SELECT cast(strftime('%%w', mtime) AS INTEGER) dow," " COUNT(*) AS eventCount" " FROM v_reports" " WHERE ifnull(coalesce(euser,user,'')=%Q,1)" " GROUP BY dow ORDER BY dow", zUserName); @ <h1>Timeline Events (%h(stats_report_label_for_type())) by Day of the Week if( zUserName ){ @ for user %h(zUserName) } @ </h1> db_multi_exec( "CREATE TEMP TABLE piechart(amt,label);" "INSERT INTO piechart" " SELECT count(*), cast(strftime('%%w', mtime) AS INT) FROM v_reports" " WHERE ifnull(coalesce(euser,user,'')=%Q,1)" " GROUP BY 2 ORDER BY 2;" "UPDATE piechart SET label = CASE label" " WHEN 0 THEN 'Sunday'" " WHEN 1 THEN 'Monday'" " WHEN 2 THEN 'Tuesday'" " WHEN 3 THEN 'Wednesday'" " WHEN 4 THEN 'Thursday'" " WHEN 5 THEN 'Friday'" " WHEN 6 THEN 'Saturday'" " ELSE 'ERROR' END;", zUserName ); if( db_int(0, "SELECT count(*) FROM piechart")>=2 ){ @ <center><svg width=700 height=400> piechart_render(700, 400, PIE_OTHER|PIE_PERCENT); @ </svg></centre><hr/> } @ <table class='statistics-report-table-events' border='0' |
︙ | ︙ |
Changes to src/th_lang.c.
︙ | ︙ | |||
720 721 722 723 724 725 726 | ** TH Syntax: ** ** string is CLASS STRING */ static int string_is_command( Th_Interp *interp, void *ctx, int argc, const char **argv, int *argl ){ | < < | < < > > | < | | | | | | > > > > > > > > > > > > > > > > > > > > > > | 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 | ** TH Syntax: ** ** string is CLASS STRING */ static int string_is_command( Th_Interp *interp, void *ctx, int argc, const char **argv, int *argl ){ if( argc!=4 ){ return Th_WrongNumArgs(interp, "string is class string"); } if( argl[2]==5 && 0==memcmp(argv[2], "alnum", 5) ){ int i; int iRes = 1; for(i=0; i<argl[3]; i++){ if( !th_isalnum(argv[3][i]) ){ iRes = 0; } } return Th_SetResultInt(interp, iRes); }else if( argl[2]==6 && 0==memcmp(argv[2], "double", 6) ){ double fVal; if( Th_ToDouble(interp, argv[3], argl[3], &fVal)==TH_OK ){ return Th_SetResultInt(interp, 1); } return Th_SetResultInt(interp, 0); }else if( argl[2]==7 && 0==memcmp(argv[2], "integer", 7) ){ int iVal; if( Th_ToInt(interp, argv[3], argl[3], &iVal)==TH_OK ){ return Th_SetResultInt(interp, 1); } return Th_SetResultInt(interp, 0); }else if( argl[2]==4 && 0==memcmp(argv[2], "list", 4) ){ if( Th_SplitList(interp, argv[3], argl[3], 0, 0, 0)==TH_OK ){ return Th_SetResultInt(interp, 1); } return Th_SetResultInt(interp, 0); }else{ Th_ErrorMessage(interp, "Expected alnum, double, integer, or list, got:", argv[2], argl[2]); return TH_ERROR; } } /* ** TH Syntax: ** ** string last NEEDLE HAYSTACK */ |
︙ | ︙ |
Changes to src/th_main.c.
︙ | ︙ | |||
335 336 337 338 339 340 341 342 343 344 345 346 347 348 | ){ if( argc!=2 ){ return Th_WrongNumArgs(interp, "puts STRING"); } sendText((char*)argv[1], argl[1], *(unsigned int*)pConvert); return TH_OK; } /* ** TH1 command: decorate STRING ** TH1 command: wiki STRING ** ** Render the input string as wiki. For the decorate command, only links ** are handled. | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 | ){ if( argc!=2 ){ return Th_WrongNumArgs(interp, "puts STRING"); } sendText((char*)argv[1], argl[1], *(unsigned int*)pConvert); return TH_OK; } /* ** TH1 command: markdown STRING ** ** Renders the input string as markdown. The result is a two-element list. ** The first element is the text-only title string. The second element ** contains the body, rendered as HTML. */ static int markdownCmd( Th_Interp *interp, void *p, int argc, const char **argv, int *argl ){ Blob src, title, body; char *zValue = 0; int nValue = 0; if( argc!=2 ){ return Th_WrongNumArgs(interp, "markdown STRING"); } blob_zero(&src); blob_init(&src, (char*)argv[1], argl[1]); blob_zero(&title); blob_zero(&body); markdown_to_html(&src, &title, &body); Th_ListAppend(interp, &zValue, &nValue, blob_str(&title), blob_size(&title)); Th_ListAppend(interp, &zValue, &nValue, blob_str(&body), blob_size(&body)); Th_SetResult(interp, zValue, nValue); return TH_OK; } /* ** TH1 command: decorate STRING ** TH1 command: wiki STRING ** ** Render the input string as wiki. For the decorate command, only links ** are handled. |
︙ | ︙ | |||
1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 | {"httpize", httpizeCmd, 0}, {"hascap", hascapCmd, (void*)&zeroInt}, {"hasfeature", hasfeatureCmd, 0}, {"html", putsCmd, (void*)&aFlags[0]}, {"htmlize", htmlizeCmd, 0}, {"http", httpCmd, 0}, {"linecount", linecntCmd, 0}, {"puts", putsCmd, (void*)&aFlags[1]}, {"query", queryCmd, 0}, {"randhex", randhexCmd, 0}, {"regexp", regexpCmd, 0}, {"reinitialize", reinitializeCmd, 0}, {"render", renderCmd, 0}, {"repository", repositoryCmd, 0}, | > | 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 | {"httpize", httpizeCmd, 0}, {"hascap", hascapCmd, (void*)&zeroInt}, {"hasfeature", hasfeatureCmd, 0}, {"html", putsCmd, (void*)&aFlags[0]}, {"htmlize", htmlizeCmd, 0}, {"http", httpCmd, 0}, {"linecount", linecntCmd, 0}, {"markdown", markdownCmd, 0}, {"puts", putsCmd, (void*)&aFlags[1]}, {"query", queryCmd, 0}, {"randhex", randhexCmd, 0}, {"regexp", regexpCmd, 0}, {"reinitialize", reinitializeCmd, 0}, {"render", renderCmd, 0}, {"repository", repositoryCmd, 0}, |
︙ | ︙ |
Changes to src/undo.c.
︙ | ︙ | |||
22 23 24 25 26 27 28 | #if INTERFACE /* ** Possible return values from the undo_maybe_save() routine. */ #define UNDO_NONE (0) /* Placeholder only used to initialize vars. */ #define UNDO_SAVED_OK (1) /* The specified file was saved succesfully. */ | > | | | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | #if INTERFACE /* ** Possible return values from the undo_maybe_save() routine. */ #define UNDO_NONE (0) /* Placeholder only used to initialize vars. */ #define UNDO_SAVED_OK (1) /* The specified file was saved succesfully. */ #define UNDO_DISABLED (2) /* File not saved, subsystem is disabled. */ #define UNDO_INACTIVE (3) /* File not saved, subsystem is not active. */ #define UNDO_TOOBIG (4) /* File not saved, it exceeded a size limit. */ #endif /* ** Undo the change to the file zPathname. zPathname is the pathname ** of the file relative to the root of the repository. If redoFlag is ** true the redo a change. If there is nothing to undo (or redo) then ** this routine is a noop. |
︙ | ︙ | |||
72 73 74 75 76 77 78 | old_exists = db_column_int(&q, 1); old_exe = db_column_int(&q, 2); if( old_exists ){ db_ephemeral_blob(&q, 0, &new); } if( old_exists ){ if( new_exists ){ | | | | 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | old_exists = db_column_int(&q, 1); old_exe = db_column_int(&q, 2); if( old_exists ){ db_ephemeral_blob(&q, 0, &new); } if( old_exists ){ if( new_exists ){ fossil_print("%s %s\n", redoFlag ? "REDO" : "UNDO", zPathname); }else{ fossil_print("NEW %s\n", zPathname); } if( new_exists && (new_link || old_link) ){ file_delete(zFullname); } if( old_link ){ symlink_create(blob_str(&new), zFullname); }else{ |
︙ | ︙ | |||
267 268 269 270 271 272 273 274 275 276 277 278 279 280 | /* ** Save the current content of the file zPathname so that it ** will be undoable. The name is relative to the root of the ** tree. */ void undo_save(const char *zPathname){ if( undo_maybe_save(zPathname, -1)!=UNDO_SAVED_OK ){ fossil_panic("failed to save undo information for path: %s", zPathname); } } /* | > | 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 | /* ** Save the current content of the file zPathname so that it ** will be undoable. The name is relative to the root of the ** tree. */ void undo_save(const char *zPathname){ if( undoDisable ) return; if( undo_maybe_save(zPathname, -1)!=UNDO_SAVED_OK ){ fossil_panic("failed to save undo information for path: %s", zPathname); } } /* |
︙ | ︙ | |||
289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 | ** value less than zero, call the undo_save() ** function instead. ** ** The return value of this function will always be one of the ** following codes: ** ** UNDO_SAVED_OK: The specified file was saved succesfully. ** ** UNDO_INACTIVE: The specified file was NOT saved, because the ** "undo subsystem" is not active. This error ** may indicate that a call to undo_begin() is ** missing. ** ** UNDO_TOOBIG: The specified file was NOT saved, because it ** exceeded the specified size limit. It is ** impossible for this value to be returned if ** the specified size limit is less than zero ** (i.e. unlimited). */ int undo_maybe_save(const char *zPathname, i64 limit){ char *zFullname; i64 size; int result; if( !undoActive ) return UNDO_INACTIVE; zFullname = mprintf("%s%s", g.zLocalRoot, zPathname); size = file_wd_size(zFullname); if( limit<0 || size<=limit ){ int existsFlag = (size>=0); int isLink = file_wd_islink(zFullname); Stmt q; | > > > > > > | 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 | ** value less than zero, call the undo_save() ** function instead. ** ** The return value of this function will always be one of the ** following codes: ** ** UNDO_SAVED_OK: The specified file was saved succesfully. ** ** UNDO_DISABLED: The specified file was NOT saved, because the ** "undo subsystem" is disabled. This error may ** indicate that a call to undo_disable() was ** issued. ** ** UNDO_INACTIVE: The specified file was NOT saved, because the ** "undo subsystem" is not active. This error ** may indicate that a call to undo_begin() is ** missing. ** ** UNDO_TOOBIG: The specified file was NOT saved, because it ** exceeded the specified size limit. It is ** impossible for this value to be returned if ** the specified size limit is less than zero ** (i.e. unlimited). */ int undo_maybe_save(const char *zPathname, i64 limit){ char *zFullname; i64 size; int result; if( undoDisable ) return UNDO_DISABLED; if( !undoActive ) return UNDO_INACTIVE; zFullname = mprintf("%s%s", g.zLocalRoot, zPathname); size = file_wd_size(zFullname); if( limit<0 || size<=limit ){ int existsFlag = (size>=0); int isLink = file_wd_islink(zFullname); Stmt q; |
︙ | ︙ | |||
353 354 355 356 357 358 359 360 361 362 363 364 365 366 | */ const char *undo_save_message(int rc){ static char zRc[32]; switch( rc ){ case UNDO_NONE: return "undo is disabled for this operation"; case UNDO_SAVED_OK: return "the save operation was successful"; case UNDO_INACTIVE: return "the undo subsystem is inactive"; case UNDO_TOOBIG: return "the file is too big"; default: { sqlite3_snprintf(sizeof(zRc), zRc, "of error code %d", rc); } } return zRc; | > | 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 | */ const char *undo_save_message(int rc){ static char zRc[32]; switch( rc ){ case UNDO_NONE: return "undo is disabled for this operation"; case UNDO_SAVED_OK: return "the save operation was successful"; case UNDO_DISABLED: return "the undo subsystem is disabled"; case UNDO_INACTIVE: return "the undo subsystem is inactive"; case UNDO_TOOBIG: return "the file is too big"; default: { sqlite3_snprintf(sizeof(zRc), zRc, "of error code %d", rc); } } return zRc; |
︙ | ︙ |
Changes to src/update.c.
︙ | ︙ | |||
422 423 424 425 426 427 428 | /* File added in the target. */ if( file_wd_isfile_or_link(zFullPath) ){ fossil_print("ADD %s - overwrites an unmanaged file\n", zName); nOverwrite++; }else{ fossil_print("ADD %s\n", zName); } | | < > | | | | 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 | /* File added in the target. */ if( file_wd_isfile_or_link(zFullPath) ){ fossil_print("ADD %s - overwrites an unmanaged file\n", zName); nOverwrite++; }else{ fossil_print("ADD %s\n", zName); } if( !dryRunFlag && !internalUpdate ) undo_save(zName); if( !dryRunFlag ) vfile_to_disk(0, idt, 0, 0); }else if( idt>0 && idv>0 && ridt!=ridv && (chnged==0 || deleted) ){ /* The file is unedited. Change it to the target version */ if( deleted ){ fossil_print("UPDATE %s - change to unmanaged file\n", zName); }else{ fossil_print("UPDATE %s\n", zName); } if( !dryRunFlag && !internalUpdate ) undo_save(zName); if( !dryRunFlag ) vfile_to_disk(0, idt, 0, 0); }else if( idt>0 && idv>0 && !deleted && file_wd_size(zFullPath)<0 ){ /* The file missing from the local check-out. Restore it to the ** version that appears in the target. */ fossil_print("UPDATE %s\n", zName); if( !dryRunFlag && !internalUpdate ) undo_save(zName); if( !dryRunFlag ) vfile_to_disk(0, idt, 0, 0); }else if( idt==0 && idv>0 ){ if( ridv==0 ){ /* Added in current checkout. Continue to hold the file as ** as an addition */ db_multi_exec("UPDATE vfile SET vid=%d WHERE id=%d", tid, idv); }else if( chnged ){ /* Edited locally but deleted from the target. Do not track the ** file but keep the edited version around. */ fossil_print("CONFLICT %s - edited locally but deleted by update\n", zName); nConflict++; }else{ fossil_print("REMOVE %s\n", zName); if( !dryRunFlag && !internalUpdate ) undo_save(zName); if( !dryRunFlag ) file_delete(zFullPath); } }else if( idt>0 && idv>0 && ridt!=ridv && chnged ){ /* Merge the changes in the current tree into the target version */ Blob r, t, v; int rc; if( nameChng ){ fossil_print("MERGE %s -> %s\n", zName, zNewName); }else{ fossil_print("MERGE %s\n", zName); } if( islinkv || islinkt /* || file_wd_islink(zFullPath) */ ){ fossil_print("***** Cannot merge symlink %s\n", zNewName); nConflict++; }else{ unsigned mergeFlags = dryRunFlag ? MERGE_DRYRUN : 0; if( !dryRunFlag && !internalUpdate ) undo_save(zName); content_get(ridt, &t); content_get(ridv, &v); rc = merge_3way(&v, zFullPath, &t, &r, mergeFlags); if( rc>=0 ){ if( !dryRunFlag ){ blob_write_to_file(&r, zFullNewPath); file_wd_setexe(zFullNewPath, isexe); |
︙ | ︙ | |||
736 737 738 739 740 741 742 743 744 745 746 747 748 749 | undo_begin(); db_multi_exec("CREATE TEMP TABLE torevert(name UNIQUE);"); if( g.argc>2 ){ for(i=2; i<g.argc; i++){ Blob fname; zFile = mprintf("%/", g.argv[i]); file_tree_name(zFile, &fname, 0, 1); db_multi_exec( "REPLACE INTO torevert VALUES(%B);" "INSERT OR IGNORE INTO torevert" " SELECT pathname" " FROM vfile" " WHERE origname=%B;", | > | 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 | undo_begin(); db_multi_exec("CREATE TEMP TABLE torevert(name UNIQUE);"); if( g.argc>2 ){ for(i=2; i<g.argc; i++){ Blob fname; zFile = mprintf("%/", g.argv[i]); blob_zero(&fname); file_tree_name(zFile, &fname, 0, 1); db_multi_exec( "REPLACE INTO torevert VALUES(%B);" "INSERT OR IGNORE INTO torevert" " SELECT pathname" " FROM vfile" " WHERE origname=%B;", |
︙ | ︙ | |||
782 783 784 785 786 787 788 | zFile = db_column_text(&q, 0); zFull = mprintf("%/%/", g.zLocalRoot, zFile); errCode = historical_version_of_file(zRevision, zFile, &record, &isLink, &isExe, 0, 2); if( errCode==2 ){ if( db_int(0, "SELECT rid FROM vfile WHERE pathname=%Q OR origname=%Q", zFile, zFile)==0 ){ | | | | | 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 | zFile = db_column_text(&q, 0); zFull = mprintf("%/%/", g.zLocalRoot, zFile); errCode = historical_version_of_file(zRevision, zFile, &record, &isLink, &isExe, 0, 2); if( errCode==2 ){ if( db_int(0, "SELECT rid FROM vfile WHERE pathname=%Q OR origname=%Q", zFile, zFile)==0 ){ fossil_print("UNMANAGE %s\n", zFile); }else{ undo_save(zFile); file_delete(zFull); fossil_print("DELETE %s\n", zFile); } db_multi_exec( "UPDATE OR REPLACE vfile" " SET pathname=origname, origname=NULL" " WHERE pathname=%Q AND origname!=pathname;" "DELETE FROM vfile WHERE pathname=%Q", zFile, zFile ); }else{ sqlite3_int64 mtime; undo_save(zFile); if( file_wd_size(zFull)>=0 && (isLink || file_wd_islink(0)) ){ file_delete(zFull); } if( isLink ){ symlink_create(blob_str(&record), zFull); }else{ blob_write_to_file(&record, zFull); } file_wd_setexe(zFull, isExe); fossil_print("REVERT %s\n", zFile); mtime = file_wd_mtime(zFull); db_multi_exec( "UPDATE vfile" " SET mtime=%lld, chnged=0, deleted=0, isexe=%d, islink=%d,mrid=rid" " WHERE pathname=%Q OR origname=%Q", mtime, isExe, isLink, zFile, zFile ); |
︙ | ︙ |
Added test/amend.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 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 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 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 | # # Tests for the "amend" command. # proc short_uuid {uuid {len 10}} { string range $uuid 0 $len-1 } proc artifact_from_timeline {res var} { upvar $var artid regexp {(?x)[0-9]{2}(?::[0-9]{2}){2}\s+\[([0-9a-f]+)]} $res m artid } proc manifest_comment {comment} { string map [list { } {\\s} \n {\\n} \r {\\r}] $comment } proc uuid_from_commit {res var} { upvar $var UUID regexp {^New_Version: ([0-9a-f]{40})$} $res m UUID } proc uuid_from_branch {res var} { upvar $var UUID regexp {^New branch: ([0-9a-f]{40})$} $res m UUID } proc uuid_from_checkout {var} { global RESULT upvar $var UUID fossil status regexp {checkout:\s+([0-9a-f]{40})} $RESULT m UUID } # Make sure we are not in an open repository and initialize new repository repo_init ######################################## # Setup: Add file and commit # ######################################## if {![uuid_from_checkout UUIDINIT]} { test amend-checkout-failure false return } write_file datafile "data" fossil add datafile fossil commit -m "c1" if {![uuid_from_commit $RESULT UUID]} { test amend-setup-failure false return } ######################################## # Test: -branch # ######################################## set UUIDB UUIDB write_file datafile "data.file" fossil commit -m "c2" if {![uuid_from_commit $RESULT UUIDB]} { test amend-branch.setup false } fossil amend $UUIDB -branch amended-branch test amend-branch-1.1 {[regexp {tags:\s+amended-branch} $RESULT]} fossil branch ls test amend-branch-1.2 {[string first "* amended-branch" $RESULT] != -1} fossil tag list test amend-branch-1.3 {[string first amended-branch $RESULT] != -1} fossil tag list --raw $UUIDB test amend-branch-1.4 {[string first "branch=amended-branch" $RESULT] != -1} test amend-branch-1.5 {[string first "sym-amended-branch" $RESULT] != -1} fossil timeline -n 1 test amend-branch-1.6 {[string match {*Move*to*branch*amended-branch*} $RESULT]} ######################################## # Test: -bgcolor # ######################################## set tc 0 foreach {color result} { 0 0 a a abcdef #abcdef abc123 #abc123 123efg 123efg abcdefg abcdefg abcdeg abcdeg blue blue acf #acf 123 #123 #1234 #1234 1234 1234 123456 #123456 } { incr tc fossil amend $UUID -bgcolor $color test amend-bgcolor-1.$tc.a {[string match "*uuid:*$UUID*" $RESULT]} fossil tag list --raw $UUID test amend-bgcolor-1.$tc.b {[string first "bgcolor=$result" $RESULT] != -1} fossil timeline -n 1 test amend-bgcolor-1.$tc.c { [string match "*Change*background*color*to*\"$result\"*" $RESULT] } if {[artifact_from_timeline $RESULT artid]} { fossil artifact $artid test amend-bgcolor-1.$tc.d { [string match "*T +bgcolor $UUID $result*" $RESULT] } } else { if {$VERBOSE} { protOut "No artifact found in timeline output" } test amend-bgcolor-1.$tc.d false } } fossil amend $UUID -bgcolor {} test amend-bgcolor-2.1 {[string match "*uuid:*$UUID*" $RESULT]} fossil tag list --raw $UUID test amend-bgcolor-2.2 { [string first "bgcolor=" $RESULT] == -1 && [string first "bgcolor" $RESULT] != -1 } fossil timeline -n 1 test amend-bgcolor-2.3 {[string match "*Cancel*background*color.*" $RESULT]} if {[artifact_from_timeline $RESULT artid]} { fossil artifact $artid test amend-bgcolor-2.4 {[string match "*T -bgcolor $UUID*" $RESULT]} } else { if {$VERBOSE} { protOut "No artifact found in timeline output" } test amend-bgcolor-2.4 false } ######################################## # Test: -branchcolor # ######################################## set UUID2 UUID2 fossil branch new brclr $UUID if {![uuid_from_branch $RESULT UUID2]} { test amend-branchcolor.setup false } fossil update $UUID2 fossil amend $UUID2 -branchcolor yellow test amend-branchcolor-1.1 {[string match "*uuid:*$UUID2*" $RESULT]} fossil tag ls --raw $UUID2 test amend-branchcolor-1.2 {[string first "bgcolor=yellow" $RESULT] != -1} fossil timeline -n 1 test amend-branchcolor-1.3 { [string match {*Change*branch*background*color*to*"yellow".*} $RESULT] } if {[regexp {(?x)[0-9]{2}(?::[0-9]{2}){2}\s+\[([0-9a-f]+)]} $RESULT m artid]} { fossil artifact $artid test amend-branchcolor-1.4 { [string match "*T \*bgcolor $UUID2 yellow*" $RESULT] } } else { if {$VERBOSE} { protOut "No artifact found in timeline output" } test amend-branchcolor-1.4 false } set UUIDN UUIDN write_file datafile "brclr" fossil commit -m "brclr" if {![uuid_from_commit $RESULT UUIDN]} { test amend-branchcolor-propagating.setup false } write_file datafile "bc1" fossil commit -m "mc1" write_file datafile "bc2" fossil commit -m "mc2" fossil amend $UUIDN -branchcolor deadbe test amend-branchcolor-2.1 {[string match "*uuid:*$UUIDN*" $RESULT]} fossil tag ls --raw current test amend-branchcolor-2.2 {[string first "bgcolor=#deadbe" $RESULT] != -1} fossil timeline -n 1 test amend-branchcolor-2.3 { [string match {*Change*branch*background*color*to*"#deadbe".*} $RESULT] } ######################################## # Test: -author # ######################################## fossil amend $UUID -author author-test test amend-author-1.1 {[string match {*comment:*(user:*author-test)*} $RESULT]} fossil tag ls --raw $UUID test amend-author-1.2 {[string first "user=author-test" $RESULT] != -1} fossil timeline -n 1 test amend-author-1.3 {[string match {*Change*user*to*"author-test".*} $RESULT]} ######################################## # Test: -date # ######################################## set timestamp [clock scan yesterday] set date [clock format $timestamp -format "%Y-%m-%d" -gmt 1] set time [clock format $timestamp -format "%H:%M:%S" -gmt 1] set datetime "$date $time" fossil amend $UUIDINIT -date $datetime test amend-date-1.1 {[string match "*uuid:*$UUIDINIT*$datetime*" $RESULT]} fossil tag ls --raw $UUIDINIT test amend-date-1.2 {[string first "date=$datetime" $RESULT] != -1} fossil timeline -n 1 test amend-date-1.3 {[string match "*Timestamp*$date*$time*" $RESULT]} set badformats { "%+" "%Y-%m-%d %H:%M%:%S %Z" "%d/%m/%Y %H:%M%:%S %Z" "%d/%m/%Y %H:%M%:%S" "%d/%m/%Y" } set sc 0 foreach badformat $badformats { incr sc set datetime [clock format $timestamp -format $badformat -gmt 1] fossil amend $UUIDINIT -date $datetime test amend-date-2.$sc {[string first "YYYY-MM-DD HH:MM:SS" $RESULT] != -1} } ######################################## # Test: -hide # ######################################## set UUIDH UUIDH fossil revert fossil update trunk fossil branch new tohide current if {![uuid_from_branch $RESULT UUIDH]} { test amend-hide-setup false } fossil amend $UUIDH -hide test amend-hide-1.1 {[string match "*uuid:*$UUIDH*" $RESULT]} fossil tag ls --raw $UUIDH test amend-hide-1.2 {[string first "hidden" $RESULT] != -1} fossil timeline -n 1 test amend-hide-1.3 {[string match {*Add*propagating*"hidden".*} $RESULT]} ######################################## # Test: -close # ######################################## set UUIDC UUIDC fossil branch new cllf $UUID if {![uuid_from_branch $RESULT UUIDC]} { test amend-close.setup false } fossil update $UUIDC fossil amend $UUIDC -close test amend-close-1.1.a {[string match "*uuid:*$UUIDC*" $RESULT]} test amend-close-1.1.b { [string match "*comment:*Create*new*branch*named*\"cllf\"*" $RESULT] } fossil tag ls --raw $UUIDC test amend-close-1.2 {[string first "closed" $RESULT] != -1} fossil timeline -n 1 test amend-close-1.3 {[string match {*Marked*"Closed".*} $RESULT]} write_file datafile "cllf" fossil commit -m "should fail" test amend-close-2 {[string first "closed leaf" $RESULT] != -1} set UUID3 UUID3 fossil revert fossil update trunk write_file datafile "cb" fossil commit -m "closed-branch" --branch "closebranch" if {![uuid_from_commit $RESULT UUID3]} { test amend-close-3.setup false } write_file datafile "b1" fossil commit -m "m1" write_file datafile "b2" fossil commit -m "m2" fossil amend $UUID3 --close test amend-close-3.1 {[string match "*uuid:*$UUID3*" $RESULT]} fossil tag ls --raw current test amend-close-3.2 {[string first "closed" $RESULT] != -1} fossil timeline -n 1 test amend-close-3.3 { [string match "*Add*propagating*\"closed\".*" $RESULT] } write_file datafile "changed" fossil commit -m "should fail" test amend-close-3.4 {[string first "closed leaf" $RESULT] != -1} ######################################## # Test: -tag/-cancel # ######################################## set tagtests { tagged tagged {000000 lower Upper alpha 0alpha} {000000 0alpha Upper alpha lower} } set tc 0 foreach {tagt result} $tagtests { incr tc set tags {} set cancels {} set t1exp "" set t2exp "*" set t3exp "*" set t5exp "*" foreach tag $tagt { lappend tags -tag $tag lappend cancels -cancel $tag } foreach res $result { append t1exp ", $res" append t2exp "sym-$res*" append t3exp "Add*tag*\"$res\".*" append t5exp "Cancel*tag*\"$res\".*" } eval fossil amend $UUID $tags test amend-tag-$tc.1 {[string match "*uuid:*$UUID*tags:*$t1exp*" $RESULT]} fossil tag ls --raw $UUID test amend-tag-$tc.2 {[string match $t2exp $RESULT]} fossil timeline -n 1 test amend-tag-$tc.3 {[string match $t3exp $RESULT]} eval fossil amend $UUID $cancels test amend-tag-$tc.4 {![string match "*tags:*$t1exp*" $RESULT]} fossil timeline -n 1 test amend-tag-$tc.5 {[string match $t5exp $RESULT]} } ######################################## # Test: -comment # ######################################## proc prep-test {comment content} { global UUID RESULT fossil revert fossil update trunk write_file datafile $comment fossil commit -m $content if {![uuid_from_commit $RESULT UUID]} { set UUID "" } } proc test-comment {name UUID comment} { global VERBOSE RESULT test amend-comment-$name.1 { [string match "*uuid:*$UUID*comment:*$comment*" $RESULT] } fossil timeline -n 1 if {[artifact_from_timeline $RESULT artid]} { fossil artifact $artid test amend-comment-$name.2 { [string match "*T +comment $UUID *[manifest_comment $comment]*" $RESULT] } } else { if {$VERBOSE} { protOut "No artifact found in timeline output: $RESULT" } test amend-comment-$name.2 false } fossil timeline -n 1 test amend-comment-$name.3 { [string match "*[short_uuid $UUID]*Edit*check-in*comment.*" $RESULT] } fossil info $UUID test amend-comment-$name.4 { [string match "*uuid:*$UUID*comment:*$comment*" $RESULT] } } prep-test "revision 1" "revision 1" fossil amend $UUID -comment "revised revision 1" test-comment 1 $UUID "revised revision 1" prep-test "revision 2" "revision 2" fossil amend $UUID -m "revised revision 2 with -m" test-comment 2 $UUID "revised revision 2 with -m" prep-test "revision 3" "revision 3" write_file commitmsg "revision 3 revised" fossil amend $UUID -message-file commitmsg test-comment 3 $UUID "revision 3 revised" prep-test "revision 4" "revision 4" write_file commitmsg "revision 4 revised with -M" fossil amend $UUID -M commitmsg test-comment 4 $UUID "revision 4 revised with -M" prep-test "final comment" "final content" if {[catch {exec which ed} result]} { if {$VERBOSE} { protOut "Install ed for interactive comment test: $result" } test-comment 5 $UUID "ed required for interactive edit" } else { set env(EDITOR) "ed -s" set comment "interactive edited comment" fossil_maybe_answer "a\n$comment\n.\nw\nq\n" amend $UUID --edit-comment unset env(EDITOR) test-comment 5 $UUID $comment } ######################################## # Test: NULL UUID # ######################################## fossil amend {} -close test amend-null-uuid {$CODE && [string first "no such check-in" $RESULT] != -1} |
Changes to test/merge5.test.
︙ | ︙ | |||
35 36 37 38 39 40 41 | test merge5-$testid 0 } else { test merge5-$testid 1 } } catch {exec $::fossilexe info} res | < | 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | test merge5-$testid 0 } else { test merge5-$testid 1 } } catch {exec $::fossilexe info} res if {![regexp {use --repository} $res]} { puts stderr "Cannot run this test within an open checkout" return } # # Fossil will write data on $HOME, running 'fossil open' here. # We need not to clutter the $HOME of the test caller. |
︙ | ︙ |
Changes to test/merge_renames.test.
1 2 3 4 5 6 | # # Tests for merging with renames # # catch {exec $::fossilexe info} res | < | 1 2 3 4 5 6 7 8 9 10 11 12 13 | # # Tests for merging with renames # # catch {exec $::fossilexe info} res if {![regexp {use --repository} $res]} { puts stderr "Cannot run this test within an open checkout" return } ###################################### # Test 1 # |
︙ | ︙ |
Changes to test/mv-rm.test.
︙ | ︙ | |||
15 16 17 18 19 20 21 | # ############################################################################ # # MV / RM Commands # catch {exec $::fossilexe info} res | < | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | # ############################################################################ # # MV / RM Commands # catch {exec $::fossilexe info} res if {![regexp {use --repository} $res]} { puts stderr "Cannot run this test within an open checkout" return } ######################################## # Setup: Add Files and Commit # |
︙ | ︙ |
Changes to test/revert.test.
︙ | ︙ | |||
36 37 38 39 40 41 42 | test revert-$testid$key $passed } fossil undo } catch {exec $::fossilexe info} res | < | 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | test revert-$testid$key $passed } fossil undo } catch {exec $::fossilexe info} res if {![regexp {use --repository} $res]} { puts stderr "Cannot run this test within an open checkout" return } repo_init |
︙ | ︙ |
Changes to test/th1.test.
︙ | ︙ | |||
14 15 16 17 18 19 20 21 22 23 24 25 26 27 | # http://www.hwaci.com/drh/ # ############################################################################ # # TH1 Commands # fossil test-th-eval --open-config "setting th1-hooks" set th1Hooks [expr {$RESULT eq "1"}] ############################################################################### fossil test-th-eval --open-config "setting abc" test th1-setting-1 {$RESULT eq ""} | > > > > | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | # http://www.hwaci.com/drh/ # ############################################################################ # # TH1 Commands # set dir [file dirname [info script]] ############################################################################### fossil test-th-eval --open-config "setting th1-hooks" set th1Hooks [expr {$RESULT eq "1"}] ############################################################################### fossil test-th-eval --open-config "setting abc" test th1-setting-1 {$RESULT eq ""} |
︙ | ︙ | |||
857 858 859 860 861 862 863 | # NOTE: This test may fail if the command names do not always come # out in a deterministic order from TH1. # fossil test-th-eval "info commands" test th1-info-commands-1 {$RESULT eq {linecount htmlize date stime\ enable_output uplevel http expr glob_match utime styleFooter catch if\ tclReady searchable reinitialize combobox lindex query html anoncap randhex\ | | | | 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 | # NOTE: This test may fail if the command names do not always come # out in a deterministic order from TH1. # fossil test-th-eval "info commands" test th1-info-commands-1 {$RESULT eq {linecount htmlize date stime\ enable_output uplevel http expr glob_match utime styleFooter catch if\ tclReady searchable reinitialize combobox lindex query html anoncap randhex\ llength for set break regexp markdown styleHeader puts return checkout\ decorate artifact trace wiki proc hascap globalState continue getParameter\ hasfeature setting lsearch breakpoint upvar render repository string unset\ setParameter list error info rename anycap httpize}} ############################################################################### fossil test-th-eval "info vars" test th1-info-vars-1 {$RESULT eq ""} |
︙ | ︙ | |||
1010 1011 1012 1013 1014 1015 1016 | fossil test-th-eval {list [glob_match a?c abc] [glob_match abc a?c]} test th1-glob-match-12 {$RESULT eq "1 0"} ############################################################################### fossil test-th-eval {list [glob_match {a[bd]c} abc] [glob_match abc {a[bd]c}]} test th1-glob-match-13 {$RESULT eq "1 0"} | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 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 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 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 | fossil test-th-eval {list [glob_match a?c abc] [glob_match abc a?c]} test th1-glob-match-12 {$RESULT eq "1 0"} ############################################################################### fossil test-th-eval {list [glob_match {a[bd]c} abc] [glob_match abc {a[bd]c}]} test th1-glob-match-13 {$RESULT eq "1 0"} ############################################################################### fossil test-th-eval {string is} test th1-string-is-1 {$RESULT eq \ {TH_ERROR: wrong # args: should be "string is class string"}} ############################################################################### fossil test-th-eval {string is something} test th1-string-is-2 {$RESULT eq \ {TH_ERROR: wrong # args: should be "string is class string"}} ############################################################################### fossil test-th-eval {string is not something else} test th1-string-is-3 {$RESULT eq \ {TH_ERROR: wrong # args: should be "string is class string"}} ############################################################################### fossil test-th-eval {string is other 123} test th1-string-is-4 {$RESULT eq \ "TH_ERROR: Expected alnum, double, integer, or list, got: other"} ############################################################################### fossil test-th-eval {string is alnum 123} test th1-string-is-5 {$RESULT eq "1"} ############################################################################### fossil test-th-eval {string is alnum abc} test th1-string-is-6 {$RESULT eq "1"} ############################################################################### fossil test-th-eval {string is alnum 123abc} test th1-string-is-7 {$RESULT eq "1"} ############################################################################### fossil test-th-eval {string is alnum abc123} test th1-string-is-8 {$RESULT eq "1"} ############################################################################### fossil test-th-eval {string is alnum _abc123} test th1-string-is-9 {$RESULT eq "0"} ############################################################################### fossil test-th-eval {string is alnum abc.123} test th1-string-is-10 {$RESULT eq "0"} ############################################################################### fossil test-th-eval {string is alnum abc123_} test th1-string-is-11 {$RESULT eq "0"} ############################################################################### fossil test-th-eval {string is list ""} test th1-string-is-12 {$RESULT eq "1"} ############################################################################### fossil test-th-eval {string is list 1} test th1-string-is-13 {$RESULT eq "1"} ############################################################################### fossil test-th-eval {string is list "1 2 3"} test th1-string-is-14 {$RESULT eq "1"} ############################################################################### fossil test-th-eval {string is list "\{"} test th1-string-is-15 {$RESULT eq "0"} ############################################################################### fossil test-th-eval {string is list "1 2 3 \{"} test th1-string-is-16 {$RESULT eq "0"} ############################################################################### fossil test-th-eval {string is list "1 2 3 \{\}"} test th1-string-is-17 {$RESULT eq "1"} ############################################################################### fossil test-th-eval {string is list "1 2 3 \{\{\}"} test th1-string-is-18 {$RESULT eq "0"} ############################################################################### fossil test-th-eval {string is double 123} test th1-string-is-19 {$RESULT eq "1"} ############################################################################### fossil test-th-eval {string is double 123.456} test th1-string-is-20 {$RESULT eq "1"} ############################################################################### fossil test-th-eval {string is double 123abc} test th1-string-is-21 {$RESULT eq "0"} ############################################################################### fossil test-th-eval {string is double 123_456} test th1-string-is-22 {$RESULT eq "0"} ############################################################################### fossil test-th-eval {string is integer 123} test th1-string-is-23 {$RESULT eq "1"} ############################################################################### fossil test-th-eval {string is integer 123.456} test th1-string-is-24 {$RESULT eq "0"} ############################################################################### fossil test-th-eval {string is integer 123abc} test th1-string-is-25 {$RESULT eq "0"} ############################################################################### fossil test-th-eval {string is integer 0b11001001} test th1-string-is-26 {$RESULT eq "1"} ############################################################################### fossil test-th-eval {string is integer 0b11001002} test th1-string-is-27 {$RESULT eq "0"} ############################################################################### fossil test-th-eval {string is integer 0o777} test th1-string-is-28 {$RESULT eq "1"} ############################################################################### fossil test-th-eval {string is integer 0o778} test th1-string-is-29 {$RESULT eq "0"} ############################################################################### fossil test-th-eval {string is integer 0xC0DEF00D} test th1-string-is-30 {$RESULT eq "1"} ############################################################################### fossil test-th-eval {string is integer 0xC0DEF00Z} test th1-string-is-31 {$RESULT eq "0"} ############################################################################### fossil test-th-eval {markdown} test th1-markdown-1 {$RESULT eq \ {TH_ERROR: wrong # args: should be "markdown STRING"}} ############################################################################### fossil test-th-eval {markdown one two} test th1-markdown-2 {$RESULT eq \ {TH_ERROR: wrong # args: should be "markdown STRING"}} ############################################################################### fossil test-th-eval {markdown "*This is a test.*"} test th1-markdown-3 {[normalize_result] eq {{} {<div class="markdown"> <p><em>This is a test.</em></p> </div> }}} ############################################################################### fossil test-th-eval {markdown "Test1\n=====\n*This is a test.*"} test th1-markdown-4 {[normalize_result] eq {Test1 {<div class="markdown"> <h1>Test1</h1> <p><em>This is a test.</em></p> </div> }}} ############################################################################### set markdown [read_file [file join $dir markdown-test1.md]] fossil test-th-eval [string map \ [list %markdown% $markdown] {markdown {%markdown%}}] test th1-markdown-5 {[normalize_result] eq \ {{Markdown Formatter Test Document} {<div class="markdown"> <h1>Markdown Formatter Test Document</h1> <p>This document is designed to test the markdown formatter.</p> <ul> <li>A bullet item. <ul> <li>A subitem</li> </ul></li> <li>Second bullet</li> </ul> <p>More text</p> <ol> <li>Enumeration 1.1. Subitem 1 1.2. Subitem 2</li> <li>Second enumeration.</li> </ol> <p>Another paragraph.</p> <h2>Other Features</h2> <p>Text can show <em>emphasis</em> or <em>emphasis</em> or <strong>strong emphassis</strong>.</p> </div> }}} |
Changes to www/changes.wiki.
1 2 3 | <title>Change Log</title> <h2>Changes for Version 1.34 (2015-??-??)</h2> | > > | > | | | > | > > > > > > | 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 | <title>Change Log</title> <h2>Changes for Version 1.34 (2015-??-??)</h2> * Fix --hard option to [/help?cmd=mv|fossil mv] and [/help?cmd=rm|fossil rm] to enable them to work properly with certain relative paths. * Make the [/help?cmd=clean|fossil clean] command undoable for files less than 10MiB. * Add minimal <nowiki>[lsearch]</nowiki> command to TH1. Only exact case-sensitive matching is supported. * Add the <nowiki>[glob_match]</nowiki> and <nowiki>[markdown]</nowiki> commands to TH1. * Add the <nowiki>[tclIsSafe] and [tclMakeSafe]</nowiki> TH1 commands to the Tcl integration subsystem. * Add 'double', 'integer', and 'list' classes to the <nowiki>[string is]</nowiki> command in TH1. * Update internal Unicode character tables, used in regular expression handling, from version 7.0 to 8.0. * Add the new [/help?cmd=amend|amend] command which is used to modify tags of a "check-in". <h2>Changes for Version 1.33 (2015-05-23)</h2> * Improved fork detection on [/help?cmd=update|fossil update], [/help?cmd=status|fossil status] and related commands. * Change the default skin to what used to be called "San Francisco Modern". * Add the [/repo-tabsize] web page * Add [/help?cmd=import|fossil import --svn], for importing a subversion |
︙ | ︙ |
Changes to www/checkin_names.wiki.
︙ | ︙ | |||
13 14 15 16 17 18 19 20 21 22 23 24 25 26 | <li> <b>root :</b> <i>branchname</i> <li> Special names: <ul> <li> <b>tip</b> <li> <b>current</b> <li> <b>next</b> <li> <b>previous</b> or <b>prev</b> </ul> </ul> </td></tr> </table> Many Fossil [/help|commands] and [./webui.wiki | web-interface] URLs accept check-in names as an argument. For example, the "[/help/info|info]" command accepts an optional check-in name to identify the specific checkout | > | 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | <li> <b>root :</b> <i>branchname</i> <li> Special names: <ul> <li> <b>tip</b> <li> <b>current</b> <li> <b>next</b> <li> <b>previous</b> or <b>prev</b> <li> <b>ckout</b> for embedded docs </ul> </ul> </td></tr> </table> Many Fossil [/help|commands] and [./webui.wiki | web-interface] URLs accept check-in names as an argument. For example, the "[/help/info|info]" command accepts an optional check-in name to identify the specific checkout |
︙ | ︙ | |||
214 215 216 217 218 219 220 221 222 223 224 225 226 227 | equivalent to the timestamp tag "5000-01-01". If the command is being run from a working check-out (not against a bare repository) then a few extra tags apply. The "current" tag means the current check-out. The "next" tag means the youngest child of the current check-out. And the "previous" or "prev" tag means the primary (non-merge) parent of the current check-out. <h2>Additional Examples</h2> To view the changes in the most recent check-in prior to the version currently checked out: <blockquote><pre> | > > > > > > | 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 | equivalent to the timestamp tag "5000-01-01". If the command is being run from a working check-out (not against a bare repository) then a few extra tags apply. The "current" tag means the current check-out. The "next" tag means the youngest child of the current check-out. And the "previous" or "prev" tag means the primary (non-merge) parent of the current check-out. For embedded documentation, the tag "ckout" means the version as present in the local source tree on disk, provided that the web server is started using "fossil ui" or "fossil server" from within the source tree. This tag can be used to preview local changes to documentation before committing them. It does not apply to CLI commands. <h2>Additional Examples</h2> To view the changes in the most recent check-in prior to the version currently checked out: <blockquote><pre> |
︙ | ︙ |
Changes to www/server.wiki.
︙ | ︙ | |||
177 178 179 180 181 182 183 184 185 186 187 188 189 190 | must be readable by the process which executes the CGI.</li> <li>ALL directories leading to the CGI script must also be readable and the CGI script itself must be executable for the user under which it will run (which often differs from the one running the web server - consult your site's documentation or administrator).</li> <li>The repository file AND the directory containing it must be writable by the same account which executes the Fossil binary (again, this might differ from the WWW user). The directory needs to be writable so that sqlite can write its journal files.</li> </ul> </p> <p> Once the script is set up correctly, and assuming your server is also set correctly, you should be able to access your repository with a URL like: <b>http://mydomain.org/cgi-bin/repo</b> (assuming the "repo" script is | > > > > | 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 | must be readable by the process which executes the CGI.</li> <li>ALL directories leading to the CGI script must also be readable and the CGI script itself must be executable for the user under which it will run (which often differs from the one running the web server - consult your site's documentation or administrator).</li> <li>The repository file AND the directory containing it must be writable by the same account which executes the Fossil binary (again, this might differ from the WWW user). The directory needs to be writable so that sqlite can write its journal files.</li> <li>Fossil must be able to create temporary files, the default directory for which depends on the OS. When the CGI process is operating within a chroot, ensure that this directory exists and is readable/writeable by the user who executes the Fossil binary.</li> </ul> </p> <p> Once the script is set up correctly, and assuming your server is also set correctly, you should be able to access your repository with a URL like: <b>http://mydomain.org/cgi-bin/repo</b> (assuming the "repo" script is |
︙ | ︙ |
Changes to www/settings.wiki.
︙ | ︙ | |||
40 41 42 43 44 45 46 | <tt>manifest</tt>. The most important is <tt>ignore-glob</tt> which specifies which files should be ignored when looking for unmanaged files with the <tt>extras</tt> command. Because these options can change over time, and the inconvenience of replicating changes, these settings are "versionable". As well as being able to be set using the <tt>settings</tt> command or the web interface, | | > | | 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | <tt>manifest</tt>. The most important is <tt>ignore-glob</tt> which specifies which files should be ignored when looking for unmanaged files with the <tt>extras</tt> command. Because these options can change over time, and the inconvenience of replicating changes, these settings are "versionable". As well as being able to be set using the <tt>settings</tt> command or the web interface, you can create versioned files in the <tt>.fossil-settings</tt> subdirectory of the check-out root, named with the setting name. The contents of the file is the value of the setting, and these files are checked in, committed, merged, and so on, as with any other file. Where a setting is a list of values, such as <tt>ignore-glob</tt>, you can use a newline as a separator as well as a comma. For example, to set the list of ignored files, create a |
︙ | ︙ |
Changes to www/th1.md.
︙ | ︙ | |||
111 112 113 114 115 116 117 | * string range STRING FIRST LAST * string repeat STRING COUNT * unset VARNAME * uplevel ?LEVEL? SCRIPT * upvar ?FRAME? OTHERVAR MYVAR ?OTHERVAR MYVAR? All of the above commands works as in the original Tcl. Refer to the | > | | 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | * string range STRING FIRST LAST * string repeat STRING COUNT * unset VARNAME * uplevel ?LEVEL? SCRIPT * upvar ?FRAME? OTHERVAR MYVAR ?OTHERVAR MYVAR? All of the above commands works as in the original Tcl. Refer to the <a href="https://www.tcl.tk/man/tcl/contents.htm">Tcl documentation</a> for details. TH1 Extended Commands --------------------- There are many new commands added to TH1 and used to access the special features of Fossil. The following is a summary of the extended commands: |
︙ | ︙ | |||
137 138 139 140 141 142 143 144 145 146 147 148 149 150 | * hascap * hasfeature * html * htmlize * http * httpize * linecount * puts * query * randhex * regexp * reinitialize * render * repository | > | 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 | * hascap * hasfeature * html * htmlize * http * httpize * linecount * markdown * puts * query * randhex * regexp * reinitialize * render * repository |
︙ | ︙ | |||
348 349 350 351 352 353 354 355 356 357 358 359 360 361 | <a name="linecount"></a>TH1 linecount Command --------------------------------------------- * linecount STRING MAX MIN Returns one more than the number of \n characters in STRING. But never returns less than MIN or more than MAX. <a name="puts"></a>TH1 puts Command ----------------------------------- * puts STRING Outputs the STRING unchanged. | > > > > > > > > > | 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 | <a name="linecount"></a>TH1 linecount Command --------------------------------------------- * linecount STRING MAX MIN Returns one more than the number of \n characters in STRING. But never returns less than MIN or more than MAX. <a name="markdown"></a>TH1 markdown Command --------------------------------------------- * markdown STRING Renders the input string as markdown. The result is a two-element list. The first element contains the body, rendered as HTML. The second element is the text-only title string. <a name="puts"></a>TH1 puts Command ----------------------------------- * puts STRING Outputs the STRING unchanged. |
︙ | ︙ |
Changes to www/webui.wiki.
︙ | ︙ | |||
59 60 61 62 63 64 65 | from within an open check-out, you can omit the repository name: <b>fossil ui</b> The latter case is a very useful short-cut when you are working on a Fossil project and you want to quickly do some work with the web interface. Notice that Fossil automatically finds an unused TCP port to run the | | | 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | from within an open check-out, you can omit the repository name: <b>fossil ui</b> The latter case is a very useful short-cut when you are working on a Fossil project and you want to quickly do some work with the web interface. Notice that Fossil automatically finds an unused TCP port to run the server on and automatically points your web browser to the correct URL. So there is never any fumbling around trying to find an open port or to type arcane strings into your browser URL entry box. The interface just pops right up, ready to run. The Fossil web interface is also very easy to setup and run on a network server, as either a CGI program or from inetd, or as an SCGI server. Details on how |
︙ | ︙ |