Fossil SCM
Merge updates from trunk.
Commit
25285f06f2a02cd7a3314a627b04dc2ffe9993ca
Parent
66c4efe765c3566…
125 files changed
+1
-1
+1
-1
+1
+21
-8
+3
-3
+11
-5
+18
-3
+14
-4
+65
-7
+207
-18
+1
-2
+11
-11
+57
-37
+30
-6
+91
-48
+63
-12
+1
-1
+4
-7
+19
-4
+8
-7
+1
-1
+1
-1
+19
-1
+79
-4
+2
+2
+2
+4
-4
+1
-1
+4
+1
-1
+1
-1
+24
-16
+1277
-1181
+28
-7
+42
-31
+4
-7
+1
+1
+52
-16
+84
-1
+36
-18
+14
-8
+3
-2
+37
-12
+48
-16
+1
-1
+57
+8
-8
+105
-17
+1
-1
+55
-17
+12
-3
+31
+2
+3
+1
-1
+1
+2
+113
+4
-1
+1
-1
+2
-6
+68
+126
-18
+2
-2
+14
-4
+2
-2
+12
-12
+39
-3
+1
+1
-1
+1
-1
+2
+2
+2
+2
+2
+2
+11
-11
+5
-5
+11
-11
+4
-4
+1
-1
+31
-2
+9
-9
+3
-3
+13
-8
+7
-7
+2
-2
+4
+1
-1
+9
-9
+9
-9
+1
-1
+5
-1
+3
-3
+5
-5
+33
-33
+19
-19
+2
-2
+11
-11
+2
-2
+54
-15
+13
-13
+48
-60
+1
-1
+5
-5
+3
-3
+10
-10
+26
-26
+13
-13
+12
-12
+3
-3
+6
-6
+21
-21
+3
-3
+10
-10
+3
-3
+9
-9
+28
-5
+5
-5
+1
-2
+3
-2
+4
-4
~
Dockerfile
~
VERSION
~
auto.def
~
src/add.c
~
src/allrepo.c
~
src/blob.c
~
src/branch.c
~
src/checkin.c
~
src/checkout.c
~
src/db.c
~
src/delta.c
~
src/deltacmd.c
~
src/diff.c
~
src/diffcmd.c
~
src/export.c
~
src/file.c
~
src/finfo.c
~
src/fusefs.c
~
src/graph.c
~
src/import.c
~
src/info.c
~
src/json_branch.c
~
src/json_wiki.c
~
src/main.c
~
src/main.mk
~
src/makemake.tcl
~
src/makemake.tcl
~
src/merge3.c
~
src/mkindex.c
~
src/mkversion.c
~
src/search.c
~
src/setup.c
~
src/shell.c
~
src/sqlite3.c
~
src/sqlite3.h
~
src/stash.c
~
src/stat.c
~
src/style.c
~
src/tag.c
~
src/tar.c
~
src/th_main.c
~
src/timeline.c
~
src/tkt.c
~
src/undo.c
~
src/unversioned.c
~
src/user.c
~
src/utf8.c
~
src/util.c
~
src/vfile.c
~
src/winhttp.c
~
src/xfer.c
~
src/zip.c
~
test/delta1.test
~
test/diff.test
~
test/fake-editor.tcl
~
test/graph-test-1.wiki
~
test/json.test
~
test/merge2.test
~
test/mv-rm.test
~
test/set-manifest.test
~
test/settings-repo.test
~
test/settings.test
~
test/stash.test
~
test/symlinks.test
~
test/tester.tcl
~
test/th1-docs.test
~
test/th1-hooks.test
~
test/th1-repo.test
~
test/th1-tcl.test
~
test/th1.test
~
test/unversioned.test
~
win/Makefile.PellesCGMake
~
win/Makefile.dmc
~
win/Makefile.mingw
~
win/Makefile.mingw
~
win/Makefile.mingw.mistachkin
~
win/Makefile.mingw.mistachkin
~
win/Makefile.msc
~
win/Makefile.msc
~
www/aboutcgi.wiki
~
www/adding_code.wiki
~
www/antibot.wiki
~
www/blame.wiki
~
www/bugtheory.wiki
~
www/changes.wiki
~
www/checkin_names.wiki
~
www/childprojects.wiki
~
www/concepts.wiki
~
www/contribute.wiki
~
www/custom_ticket.wiki
~
www/customskin.md
~
www/delta_encoder_algorithm.wiki
~
www/delta_format.wiki
~
www/embeddeddoc.wiki
~
www/encryptedrepos.wiki
~
www/env-opts.md
~
www/event.wiki
~
www/faq.wiki
~
www/fileformat.wiki
~
www/fiveminutes.wiki
~
www/foss-cklist.wiki
~
www/fossil-from-msvc.wiki
~
www/index.wiki
~
www/inout.wiki
~
www/makefile.wiki
~
www/mkdownload.tcl
~
www/newrepo.wiki
~
www/pop.wiki
~
www/private.wiki
~
www/qandc.wiki
~
www/quickstart.wiki
~
www/quotes.wiki
~
www/reviews.wiki
~
www/selfcheck.wiki
~
www/selfhost.wiki
~
www/server.wiki
~
www/settings.wiki
~
www/shunning.wiki
~
www/stats.wiki
~
www/sync.wiki
~
www/th1.md
~
www/theory1.wiki
~
www/webui.wiki
~
www/whyusefossil.wiki
~
www/wikitheory.wiki
+1
-1
| --- Dockerfile | ||
| +++ Dockerfile | ||
| @@ -1,9 +1,9 @@ | ||
| 1 | 1 | ### |
| 2 | 2 | # Dockerfile for Fossil |
| 3 | 3 | ### |
| 4 | -FROM fedora:23 | |
| 4 | +FROM fedora:24 | |
| 5 | 5 | |
| 6 | 6 | ### Now install some additional parts we will need for the build |
| 7 | 7 | RUN dnf update -y && dnf install -y gcc make zlib-devel openssl-devel tar && dnf clean all && groupadd -r fossil -g 433 && useradd -u 431 -r -g fossil -d /opt/fossil -s /sbin/nologin -c "Fossil user" fossil |
| 8 | 8 | |
| 9 | 9 | ### If you want to build "trunk", change the next line accordingly. |
| 10 | 10 |
| --- Dockerfile | |
| +++ Dockerfile | |
| @@ -1,9 +1,9 @@ | |
| 1 | ### |
| 2 | # Dockerfile for Fossil |
| 3 | ### |
| 4 | FROM fedora:23 |
| 5 | |
| 6 | ### Now install some additional parts we will need for the build |
| 7 | RUN dnf update -y && dnf install -y gcc make zlib-devel openssl-devel tar && dnf clean all && groupadd -r fossil -g 433 && useradd -u 431 -r -g fossil -d /opt/fossil -s /sbin/nologin -c "Fossil user" fossil |
| 8 | |
| 9 | ### If you want to build "trunk", change the next line accordingly. |
| 10 |
| --- Dockerfile | |
| +++ Dockerfile | |
| @@ -1,9 +1,9 @@ | |
| 1 | ### |
| 2 | # Dockerfile for Fossil |
| 3 | ### |
| 4 | FROM fedora:24 |
| 5 | |
| 6 | ### Now install some additional parts we will need for the build |
| 7 | RUN dnf update -y && dnf install -y gcc make zlib-devel openssl-devel tar && dnf clean all && groupadd -r fossil -g 433 && useradd -u 431 -r -g fossil -d /opt/fossil -s /sbin/nologin -c "Fossil user" fossil |
| 8 | |
| 9 | ### If you want to build "trunk", change the next line accordingly. |
| 10 |
M
VERSION
+1
-1
| --- VERSION | ||
| +++ VERSION | ||
| @@ -1,1 +1,1 @@ | ||
| 1 | -1.36 | |
| 1 | +1.37 | |
| 2 | 2 |
| --- VERSION | |
| +++ VERSION | |
| @@ -1,1 +1,1 @@ | |
| 1 | 1.36 |
| 2 |
| --- VERSION | |
| +++ VERSION | |
| @@ -1,1 +1,1 @@ | |
| 1 | 1.37 |
| 2 |
M
auto.def
+1
| --- auto.def | ||
| +++ auto.def | ||
| @@ -479,10 +479,11 @@ | ||
| 479 | 479 | cc-check-function-in-lib sin m |
| 480 | 480 | |
| 481 | 481 | # Check for the FuseFS library |
| 482 | 482 | if {[opt-bool fusefs]} { |
| 483 | 483 | if {[cc-check-function-in-lib fuse_mount fuse]} { |
| 484 | + define-append EXTRA_CFLAGS -DFOSSIL_HAVE_FUSEFS | |
| 484 | 485 | define FOSSIL_HAVE_FUSEFS 1 |
| 485 | 486 | define-append LIBS -lfuse |
| 486 | 487 | msg-result "FuseFS support enabled" |
| 487 | 488 | } |
| 488 | 489 | } |
| 489 | 490 |
| --- auto.def | |
| +++ auto.def | |
| @@ -479,10 +479,11 @@ | |
| 479 | cc-check-function-in-lib sin m |
| 480 | |
| 481 | # Check for the FuseFS library |
| 482 | if {[opt-bool fusefs]} { |
| 483 | if {[cc-check-function-in-lib fuse_mount fuse]} { |
| 484 | define FOSSIL_HAVE_FUSEFS 1 |
| 485 | define-append LIBS -lfuse |
| 486 | msg-result "FuseFS support enabled" |
| 487 | } |
| 488 | } |
| 489 |
| --- auto.def | |
| +++ auto.def | |
| @@ -479,10 +479,11 @@ | |
| 479 | cc-check-function-in-lib sin m |
| 480 | |
| 481 | # Check for the FuseFS library |
| 482 | if {[opt-bool fusefs]} { |
| 483 | if {[cc-check-function-in-lib fuse_mount fuse]} { |
| 484 | define-append EXTRA_CFLAGS -DFOSSIL_HAVE_FUSEFS |
| 485 | define FOSSIL_HAVE_FUSEFS 1 |
| 486 | define-append LIBS -lfuse |
| 487 | msg-result "FuseFS support enabled" |
| 488 | } |
| 489 | } |
| 490 |
+21
-8
| --- src/add.c | ||
| +++ src/add.c | ||
| @@ -71,29 +71,42 @@ | ||
| 71 | 71 | ".fos-journal", |
| 72 | 72 | ".fos-wal", |
| 73 | 73 | ".fos-shm", |
| 74 | 74 | }; |
| 75 | 75 | |
| 76 | - /* Names of auxiliary files generated by SQLite when the "manifest" | |
| 77 | - ** property is enabled | |
| 76 | + /* Possible names of auxiliary files generated when the "manifest" property | |
| 77 | + ** is used | |
| 78 | 78 | */ |
| 79 | - static const char *const azManifest[] = { | |
| 80 | - "manifest", | |
| 81 | - "manifest.uuid", | |
| 79 | + static const struct { | |
| 80 | + const char *fname; | |
| 81 | + int flg; | |
| 82 | + }aManifestflags[] = { | |
| 83 | + { "manifest", MFESTFLG_RAW }, | |
| 84 | + { "manifest.uuid", MFESTFLG_UUID }, | |
| 85 | + { "manifest.tags", MFESTFLG_TAGS } | |
| 82 | 86 | }; |
| 87 | + static const char *azManifests[3]; | |
| 83 | 88 | |
| 84 | 89 | /* |
| 85 | 90 | ** Names of repository files, if they exist in the checkout. |
| 86 | 91 | */ |
| 87 | 92 | static const char *azRepo[4] = { 0, 0, 0, 0 }; |
| 88 | 93 | |
| 89 | 94 | /* Cached setting "manifest" */ |
| 90 | 95 | static int cachedManifest = -1; |
| 96 | + static int numManifests; | |
| 91 | 97 | |
| 92 | 98 | if( cachedManifest == -1 ){ |
| 99 | + int i; | |
| 93 | 100 | Blob repo; |
| 94 | - cachedManifest = db_get_boolean("manifest",0); | |
| 101 | + cachedManifest = db_get_manifest_setting(); | |
| 102 | + numManifests = 0; | |
| 103 | + for(i=0; i<count(aManifestflags); i++){ | |
| 104 | + if( cachedManifest&aManifestflags[i].flg ) { | |
| 105 | + azManifests[numManifests++] = aManifestflags[i].fname; | |
| 106 | + } | |
| 107 | + } | |
| 95 | 108 | blob_zero(&repo); |
| 96 | 109 | if( file_tree_name(g.zRepositoryName, &repo, 0, 0) ){ |
| 97 | 110 | const char *zRepo = blob_str(&repo); |
| 98 | 111 | azRepo[0] = zRepo; |
| 99 | 112 | azRepo[1] = mprintf("%s-journal", zRepo); |
| @@ -104,12 +117,12 @@ | ||
| 104 | 117 | |
| 105 | 118 | if( N<0 ) return 0; |
| 106 | 119 | if( N<count(azName) ) return azName[N]; |
| 107 | 120 | N -= count(azName); |
| 108 | 121 | if( cachedManifest ){ |
| 109 | - if( N<count(azManifest) ) return azManifest[N]; | |
| 110 | - N -= count(azManifest); | |
| 122 | + if( N<numManifests ) return azManifests[N]; | |
| 123 | + N -= numManifests; | |
| 111 | 124 | } |
| 112 | 125 | if( !omitRepo && N<count(azRepo) ) return azRepo[N]; |
| 113 | 126 | return 0; |
| 114 | 127 | } |
| 115 | 128 | |
| 116 | 129 |
| --- src/add.c | |
| +++ src/add.c | |
| @@ -71,29 +71,42 @@ | |
| 71 | ".fos-journal", |
| 72 | ".fos-wal", |
| 73 | ".fos-shm", |
| 74 | }; |
| 75 | |
| 76 | /* Names of auxiliary files generated by SQLite when the "manifest" |
| 77 | ** property is enabled |
| 78 | */ |
| 79 | static const char *const azManifest[] = { |
| 80 | "manifest", |
| 81 | "manifest.uuid", |
| 82 | }; |
| 83 | |
| 84 | /* |
| 85 | ** Names of repository files, if they exist in the checkout. |
| 86 | */ |
| 87 | static const char *azRepo[4] = { 0, 0, 0, 0 }; |
| 88 | |
| 89 | /* Cached setting "manifest" */ |
| 90 | static int cachedManifest = -1; |
| 91 | |
| 92 | if( cachedManifest == -1 ){ |
| 93 | Blob repo; |
| 94 | cachedManifest = db_get_boolean("manifest",0); |
| 95 | blob_zero(&repo); |
| 96 | if( file_tree_name(g.zRepositoryName, &repo, 0, 0) ){ |
| 97 | const char *zRepo = blob_str(&repo); |
| 98 | azRepo[0] = zRepo; |
| 99 | azRepo[1] = mprintf("%s-journal", zRepo); |
| @@ -104,12 +117,12 @@ | |
| 104 | |
| 105 | if( N<0 ) return 0; |
| 106 | if( N<count(azName) ) return azName[N]; |
| 107 | N -= count(azName); |
| 108 | if( cachedManifest ){ |
| 109 | if( N<count(azManifest) ) return azManifest[N]; |
| 110 | N -= count(azManifest); |
| 111 | } |
| 112 | if( !omitRepo && N<count(azRepo) ) return azRepo[N]; |
| 113 | return 0; |
| 114 | } |
| 115 | |
| 116 |
| --- src/add.c | |
| +++ src/add.c | |
| @@ -71,29 +71,42 @@ | |
| 71 | ".fos-journal", |
| 72 | ".fos-wal", |
| 73 | ".fos-shm", |
| 74 | }; |
| 75 | |
| 76 | /* Possible names of auxiliary files generated when the "manifest" property |
| 77 | ** is used |
| 78 | */ |
| 79 | static const struct { |
| 80 | const char *fname; |
| 81 | int flg; |
| 82 | }aManifestflags[] = { |
| 83 | { "manifest", MFESTFLG_RAW }, |
| 84 | { "manifest.uuid", MFESTFLG_UUID }, |
| 85 | { "manifest.tags", MFESTFLG_TAGS } |
| 86 | }; |
| 87 | static const char *azManifests[3]; |
| 88 | |
| 89 | /* |
| 90 | ** Names of repository files, if they exist in the checkout. |
| 91 | */ |
| 92 | static const char *azRepo[4] = { 0, 0, 0, 0 }; |
| 93 | |
| 94 | /* Cached setting "manifest" */ |
| 95 | static int cachedManifest = -1; |
| 96 | static int numManifests; |
| 97 | |
| 98 | if( cachedManifest == -1 ){ |
| 99 | int i; |
| 100 | Blob repo; |
| 101 | cachedManifest = db_get_manifest_setting(); |
| 102 | numManifests = 0; |
| 103 | for(i=0; i<count(aManifestflags); i++){ |
| 104 | if( cachedManifest&aManifestflags[i].flg ) { |
| 105 | azManifests[numManifests++] = aManifestflags[i].fname; |
| 106 | } |
| 107 | } |
| 108 | blob_zero(&repo); |
| 109 | if( file_tree_name(g.zRepositoryName, &repo, 0, 0) ){ |
| 110 | const char *zRepo = blob_str(&repo); |
| 111 | azRepo[0] = zRepo; |
| 112 | azRepo[1] = mprintf("%s-journal", zRepo); |
| @@ -104,12 +117,12 @@ | |
| 117 | |
| 118 | if( N<0 ) return 0; |
| 119 | if( N<count(azName) ) return azName[N]; |
| 120 | N -= count(azName); |
| 121 | if( cachedManifest ){ |
| 122 | if( N<numManifests ) return azManifests[N]; |
| 123 | N -= numManifests; |
| 124 | } |
| 125 | if( !omitRepo && N<count(azRepo) ) return azRepo[N]; |
| 126 | return 0; |
| 127 | } |
| 128 | |
| 129 |
+3
-3
| --- src/allrepo.c | ||
| +++ src/allrepo.c | ||
| @@ -173,11 +173,10 @@ | ||
| 173 | 173 | int useCheckouts = 0; |
| 174 | 174 | int quiet = 0; |
| 175 | 175 | int dryRunFlag = 0; |
| 176 | 176 | int showFile = find_option("showfile",0,0)!=0; |
| 177 | 177 | int stopOnError = find_option("dontstop",0,0)==0; |
| 178 | - int rc; | |
| 179 | 178 | int nToDel = 0; |
| 180 | 179 | int showLabel = 0; |
| 181 | 180 | |
| 182 | 181 | dryRunFlag = find_option("dry-run","n",0)!=0; |
| 183 | 182 | if( !dryRunFlag ){ |
| @@ -375,22 +374,23 @@ | ||
| 375 | 374 | " FROM global_config" |
| 376 | 375 | " WHERE substr(name, 1, 5)=='repo:'" |
| 377 | 376 | " ORDER BY 1" |
| 378 | 377 | ); |
| 379 | 378 | } |
| 380 | - db_multi_exec("CREATE TEMP TABLE todel(x TEXT)"); | |
| 379 | + db_multi_exec("CREATE TEMP TABLE toDel(x TEXT)"); | |
| 381 | 380 | db_prepare(&q, "SELECT name, tag FROM repolist ORDER BY 1"); |
| 382 | 381 | while( db_step(&q)==SQLITE_ROW ){ |
| 382 | + int rc; | |
| 383 | 383 | const char *zFilename = db_column_text(&q, 0); |
| 384 | 384 | #if !USE_SEE |
| 385 | 385 | if( sqlite3_strglob("*.efossil", zFilename)==0 ) continue; |
| 386 | 386 | #endif |
| 387 | 387 | if( file_access(zFilename, F_OK) |
| 388 | 388 | || !file_is_canonical(zFilename) |
| 389 | 389 | || (useCheckouts && file_isdir(zFilename)!=1) |
| 390 | 390 | ){ |
| 391 | - db_multi_exec("INSERT INTO todel VALUES(%Q)", db_column_text(&q, 1)); | |
| 391 | + db_multi_exec("INSERT INTO toDel VALUES(%Q)", db_column_text(&q, 1)); | |
| 392 | 392 | nToDel++; |
| 393 | 393 | continue; |
| 394 | 394 | } |
| 395 | 395 | if( zCmd[0]=='l' ){ |
| 396 | 396 | fossil_print("%s\n", zFilename); |
| 397 | 397 |
| --- src/allrepo.c | |
| +++ src/allrepo.c | |
| @@ -173,11 +173,10 @@ | |
| 173 | int useCheckouts = 0; |
| 174 | int quiet = 0; |
| 175 | int dryRunFlag = 0; |
| 176 | int showFile = find_option("showfile",0,0)!=0; |
| 177 | int stopOnError = find_option("dontstop",0,0)==0; |
| 178 | int rc; |
| 179 | int nToDel = 0; |
| 180 | int showLabel = 0; |
| 181 | |
| 182 | dryRunFlag = find_option("dry-run","n",0)!=0; |
| 183 | if( !dryRunFlag ){ |
| @@ -375,22 +374,23 @@ | |
| 375 | " FROM global_config" |
| 376 | " WHERE substr(name, 1, 5)=='repo:'" |
| 377 | " ORDER BY 1" |
| 378 | ); |
| 379 | } |
| 380 | db_multi_exec("CREATE TEMP TABLE todel(x TEXT)"); |
| 381 | db_prepare(&q, "SELECT name, tag FROM repolist ORDER BY 1"); |
| 382 | while( db_step(&q)==SQLITE_ROW ){ |
| 383 | const char *zFilename = db_column_text(&q, 0); |
| 384 | #if !USE_SEE |
| 385 | if( sqlite3_strglob("*.efossil", zFilename)==0 ) continue; |
| 386 | #endif |
| 387 | if( file_access(zFilename, F_OK) |
| 388 | || !file_is_canonical(zFilename) |
| 389 | || (useCheckouts && file_isdir(zFilename)!=1) |
| 390 | ){ |
| 391 | db_multi_exec("INSERT INTO todel VALUES(%Q)", db_column_text(&q, 1)); |
| 392 | nToDel++; |
| 393 | continue; |
| 394 | } |
| 395 | if( zCmd[0]=='l' ){ |
| 396 | fossil_print("%s\n", zFilename); |
| 397 |
| --- src/allrepo.c | |
| +++ src/allrepo.c | |
| @@ -173,11 +173,10 @@ | |
| 173 | int useCheckouts = 0; |
| 174 | int quiet = 0; |
| 175 | int dryRunFlag = 0; |
| 176 | int showFile = find_option("showfile",0,0)!=0; |
| 177 | int stopOnError = find_option("dontstop",0,0)==0; |
| 178 | int nToDel = 0; |
| 179 | int showLabel = 0; |
| 180 | |
| 181 | dryRunFlag = find_option("dry-run","n",0)!=0; |
| 182 | if( !dryRunFlag ){ |
| @@ -375,22 +374,23 @@ | |
| 374 | " FROM global_config" |
| 375 | " WHERE substr(name, 1, 5)=='repo:'" |
| 376 | " ORDER BY 1" |
| 377 | ); |
| 378 | } |
| 379 | db_multi_exec("CREATE TEMP TABLE toDel(x TEXT)"); |
| 380 | db_prepare(&q, "SELECT name, tag FROM repolist ORDER BY 1"); |
| 381 | while( db_step(&q)==SQLITE_ROW ){ |
| 382 | int rc; |
| 383 | const char *zFilename = db_column_text(&q, 0); |
| 384 | #if !USE_SEE |
| 385 | if( sqlite3_strglob("*.efossil", zFilename)==0 ) continue; |
| 386 | #endif |
| 387 | if( file_access(zFilename, F_OK) |
| 388 | || !file_is_canonical(zFilename) |
| 389 | || (useCheckouts && file_isdir(zFilename)!=1) |
| 390 | ){ |
| 391 | db_multi_exec("INSERT INTO toDel VALUES(%Q)", db_column_text(&q, 1)); |
| 392 | nToDel++; |
| 393 | continue; |
| 394 | } |
| 395 | if( zCmd[0]=='l' ){ |
| 396 | fossil_print("%s\n", zFilename); |
| 397 |
+11
-5
| --- src/blob.c | ||
| +++ src/blob.c | ||
| @@ -851,27 +851,33 @@ | ||
| 851 | 851 | int blob_write_to_file(Blob *pBlob, const char *zFilename){ |
| 852 | 852 | FILE *out; |
| 853 | 853 | int nWrote; |
| 854 | 854 | |
| 855 | 855 | if( zFilename[0]==0 || (zFilename[0]=='-' && zFilename[1]==0) ){ |
| 856 | - nWrote = blob_size(pBlob); | |
| 856 | + blob_is_init(pBlob); | |
| 857 | 857 | #if defined(_WIN32) |
| 858 | - if( fossil_utf8_to_console(blob_buffer(pBlob), nWrote, 0) >= 0 ){ | |
| 859 | - return nWrote; | |
| 860 | - } | |
| 858 | + nWrote = fossil_utf8_to_console(blob_buffer(pBlob), blob_size(pBlob), 0); | |
| 859 | + if( nWrote>=0 ) return nWrote; | |
| 861 | 860 | fflush(stdout); |
| 862 | 861 | _setmode(_fileno(stdout), _O_BINARY); |
| 863 | 862 | #endif |
| 864 | - fwrite(blob_buffer(pBlob), 1, nWrote, stdout); | |
| 863 | + nWrote = fwrite(blob_buffer(pBlob), 1, blob_size(pBlob), stdout); | |
| 865 | 864 | #if defined(_WIN32) |
| 866 | 865 | fflush(stdout); |
| 867 | 866 | _setmode(_fileno(stdout), _O_TEXT); |
| 868 | 867 | #endif |
| 869 | 868 | }else{ |
| 870 | 869 | file_mkfolder(zFilename, 1, 0); |
| 871 | 870 | out = fossil_fopen(zFilename, "wb"); |
| 872 | 871 | if( out==0 ){ |
| 872 | +#if _WIN32 | |
| 873 | + const char *zReserved = file_is_win_reserved(zFilename); | |
| 874 | + if( zReserved ){ | |
| 875 | + fossil_fatal("cannot open \"%s\" because \"%s\" is " | |
| 876 | + "a reserved name on Windows", zFilename, zReserved); | |
| 877 | + } | |
| 878 | +#endif | |
| 873 | 879 | fossil_fatal_recursive("unable to open file \"%s\" for writing", |
| 874 | 880 | zFilename); |
| 875 | 881 | return 0; |
| 876 | 882 | } |
| 877 | 883 | blob_is_init(pBlob); |
| 878 | 884 |
| --- src/blob.c | |
| +++ src/blob.c | |
| @@ -851,27 +851,33 @@ | |
| 851 | int blob_write_to_file(Blob *pBlob, const char *zFilename){ |
| 852 | FILE *out; |
| 853 | int nWrote; |
| 854 | |
| 855 | if( zFilename[0]==0 || (zFilename[0]=='-' && zFilename[1]==0) ){ |
| 856 | nWrote = blob_size(pBlob); |
| 857 | #if defined(_WIN32) |
| 858 | if( fossil_utf8_to_console(blob_buffer(pBlob), nWrote, 0) >= 0 ){ |
| 859 | return nWrote; |
| 860 | } |
| 861 | fflush(stdout); |
| 862 | _setmode(_fileno(stdout), _O_BINARY); |
| 863 | #endif |
| 864 | fwrite(blob_buffer(pBlob), 1, nWrote, stdout); |
| 865 | #if defined(_WIN32) |
| 866 | fflush(stdout); |
| 867 | _setmode(_fileno(stdout), _O_TEXT); |
| 868 | #endif |
| 869 | }else{ |
| 870 | file_mkfolder(zFilename, 1, 0); |
| 871 | out = fossil_fopen(zFilename, "wb"); |
| 872 | if( out==0 ){ |
| 873 | fossil_fatal_recursive("unable to open file \"%s\" for writing", |
| 874 | zFilename); |
| 875 | return 0; |
| 876 | } |
| 877 | blob_is_init(pBlob); |
| 878 |
| --- src/blob.c | |
| +++ src/blob.c | |
| @@ -851,27 +851,33 @@ | |
| 851 | int blob_write_to_file(Blob *pBlob, const char *zFilename){ |
| 852 | FILE *out; |
| 853 | int nWrote; |
| 854 | |
| 855 | if( zFilename[0]==0 || (zFilename[0]=='-' && zFilename[1]==0) ){ |
| 856 | blob_is_init(pBlob); |
| 857 | #if defined(_WIN32) |
| 858 | nWrote = fossil_utf8_to_console(blob_buffer(pBlob), blob_size(pBlob), 0); |
| 859 | if( nWrote>=0 ) return nWrote; |
| 860 | fflush(stdout); |
| 861 | _setmode(_fileno(stdout), _O_BINARY); |
| 862 | #endif |
| 863 | nWrote = fwrite(blob_buffer(pBlob), 1, blob_size(pBlob), stdout); |
| 864 | #if defined(_WIN32) |
| 865 | fflush(stdout); |
| 866 | _setmode(_fileno(stdout), _O_TEXT); |
| 867 | #endif |
| 868 | }else{ |
| 869 | file_mkfolder(zFilename, 1, 0); |
| 870 | out = fossil_fopen(zFilename, "wb"); |
| 871 | if( out==0 ){ |
| 872 | #if _WIN32 |
| 873 | const char *zReserved = file_is_win_reserved(zFilename); |
| 874 | if( zReserved ){ |
| 875 | fossil_fatal("cannot open \"%s\" because \"%s\" is " |
| 876 | "a reserved name on Windows", zFilename, zReserved); |
| 877 | } |
| 878 | #endif |
| 879 | fossil_fatal_recursive("unable to open file \"%s\" for writing", |
| 880 | zFilename); |
| 881 | return 0; |
| 882 | } |
| 883 | blob_is_init(pBlob); |
| 884 |
+18
-3
| --- src/branch.c | ||
| +++ src/branch.c | ||
| @@ -154,11 +154,11 @@ | ||
| 154 | 154 | if( brid==0 ){ |
| 155 | 155 | fossil_fatal("trouble committing manifest: %s", g.zErrMsg); |
| 156 | 156 | } |
| 157 | 157 | db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", brid); |
| 158 | 158 | if( manifest_crosslink(brid, &branch, MC_PERMIT_HOOKS)==0 ){ |
| 159 | - fossil_fatal("%s\n", g.zErrMsg); | |
| 159 | + fossil_fatal("%s", g.zErrMsg); | |
| 160 | 160 | } |
| 161 | 161 | assert( blob_is_reset(&branch) ); |
| 162 | 162 | content_deltify(rootid, brid, 0); |
| 163 | 163 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", brid); |
| 164 | 164 | fossil_print("New branch: %s\n", zUuid); |
| @@ -323,11 +323,12 @@ | ||
| 323 | 323 | @ WHERE plink.pid=event.objid |
| 324 | 324 | @ AND tagxref.rid=plink.cid |
| 325 | 325 | @ AND tagxref.tagid=(SELECT tagid FROM tag WHERE tagname='branch') |
| 326 | 326 | @ AND tagtype>0), |
| 327 | 327 | @ count(*), |
| 328 | -@ (SELECT uuid FROM blob WHERE rid=tagxref.rid) | |
| 328 | +@ (SELECT uuid FROM blob WHERE rid=tagxref.rid), | |
| 329 | +@ event.bgcolor | |
| 329 | 330 | @ FROM tagxref, tag, event |
| 330 | 331 | @ WHERE tagxref.tagid=tag.tagid |
| 331 | 332 | @ AND tagxref.tagtype>0 |
| 332 | 333 | @ AND tag.tagname='branch' |
| 333 | 334 | @ AND event.objid=tagxref.rid |
| @@ -344,14 +345,16 @@ | ||
| 344 | 345 | ** if there are no query parameters. |
| 345 | 346 | */ |
| 346 | 347 | static void new_brlist_page(void){ |
| 347 | 348 | Stmt q; |
| 348 | 349 | double rNow; |
| 350 | + int show_colors = PB("colors"); | |
| 349 | 351 | login_check_credentials(); |
| 350 | 352 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 351 | 353 | style_header("Branches"); |
| 352 | 354 | style_adunit_config(ADUNIT_RIGHT_OK); |
| 355 | + style_submenu_binary("colors", "Color", "B/W", 0); | |
| 353 | 356 | login_anonymous_available(); |
| 354 | 357 | |
| 355 | 358 | db_prepare(&q, brlistQuery/*works-like:""*/); |
| 356 | 359 | rNow = db_double(0.0, "SELECT julianday('now')"); |
| 357 | 360 | @ <div class="brlist"><table id="branchlisttable"> |
| @@ -367,14 +370,26 @@ | ||
| 367 | 370 | double rMtime = db_column_double(&q, 1); |
| 368 | 371 | int isClosed = db_column_int(&q, 2); |
| 369 | 372 | const char *zMergeTo = db_column_text(&q, 3); |
| 370 | 373 | int nCkin = db_column_int(&q, 4); |
| 371 | 374 | const char *zLastCkin = db_column_text(&q, 5); |
| 375 | + const char *zBgClr = db_column_text(&q, 6); | |
| 372 | 376 | char *zAge = human_readable_age(rNow - rMtime); |
| 373 | 377 | sqlite3_int64 iMtime = (sqlite3_int64)(rMtime*86400.0); |
| 374 | 378 | if( zMergeTo && zMergeTo[0]==0 ) zMergeTo = 0; |
| 375 | - @ <tr> | |
| 379 | + if( zBgClr == 0 ){ | |
| 380 | + if( zBranch==0 || strcmp(zBranch,"trunk")==0 ){ | |
| 381 | + zBgClr = 0; | |
| 382 | + }else{ | |
| 383 | + zBgClr = hash_color(zBranch); | |
| 384 | + } | |
| 385 | + } | |
| 386 | + if( zBgClr && zBgClr[0] && show_colors ){ | |
| 387 | + @ <tr style="background-color:%s(zBgClr)"> | |
| 388 | + }else{ | |
| 389 | + @ <tr> | |
| 390 | + } | |
| 376 | 391 | @ <td>%z(href("%R/timeline?n=100&r=%T",zBranch))%h(zBranch)</a></td> |
| 377 | 392 | @ <td data-sortkey="%016llx(-iMtime)">%s(zAge)</td> |
| 378 | 393 | @ <td>%d(nCkin)</td> |
| 379 | 394 | fossil_free(zAge); |
| 380 | 395 | @ <td>%s(isClosed?"closed":"")</td> |
| 381 | 396 |
| --- src/branch.c | |
| +++ src/branch.c | |
| @@ -154,11 +154,11 @@ | |
| 154 | if( brid==0 ){ |
| 155 | fossil_fatal("trouble committing manifest: %s", g.zErrMsg); |
| 156 | } |
| 157 | db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", brid); |
| 158 | if( manifest_crosslink(brid, &branch, MC_PERMIT_HOOKS)==0 ){ |
| 159 | fossil_fatal("%s\n", g.zErrMsg); |
| 160 | } |
| 161 | assert( blob_is_reset(&branch) ); |
| 162 | content_deltify(rootid, brid, 0); |
| 163 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", brid); |
| 164 | fossil_print("New branch: %s\n", zUuid); |
| @@ -323,11 +323,12 @@ | |
| 323 | @ WHERE plink.pid=event.objid |
| 324 | @ AND tagxref.rid=plink.cid |
| 325 | @ AND tagxref.tagid=(SELECT tagid FROM tag WHERE tagname='branch') |
| 326 | @ AND tagtype>0), |
| 327 | @ count(*), |
| 328 | @ (SELECT uuid FROM blob WHERE rid=tagxref.rid) |
| 329 | @ FROM tagxref, tag, event |
| 330 | @ WHERE tagxref.tagid=tag.tagid |
| 331 | @ AND tagxref.tagtype>0 |
| 332 | @ AND tag.tagname='branch' |
| 333 | @ AND event.objid=tagxref.rid |
| @@ -344,14 +345,16 @@ | |
| 344 | ** if there are no query parameters. |
| 345 | */ |
| 346 | static void new_brlist_page(void){ |
| 347 | Stmt q; |
| 348 | double rNow; |
| 349 | login_check_credentials(); |
| 350 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 351 | style_header("Branches"); |
| 352 | style_adunit_config(ADUNIT_RIGHT_OK); |
| 353 | login_anonymous_available(); |
| 354 | |
| 355 | db_prepare(&q, brlistQuery/*works-like:""*/); |
| 356 | rNow = db_double(0.0, "SELECT julianday('now')"); |
| 357 | @ <div class="brlist"><table id="branchlisttable"> |
| @@ -367,14 +370,26 @@ | |
| 367 | double rMtime = db_column_double(&q, 1); |
| 368 | int isClosed = db_column_int(&q, 2); |
| 369 | const char *zMergeTo = db_column_text(&q, 3); |
| 370 | int nCkin = db_column_int(&q, 4); |
| 371 | const char *zLastCkin = db_column_text(&q, 5); |
| 372 | char *zAge = human_readable_age(rNow - rMtime); |
| 373 | sqlite3_int64 iMtime = (sqlite3_int64)(rMtime*86400.0); |
| 374 | if( zMergeTo && zMergeTo[0]==0 ) zMergeTo = 0; |
| 375 | @ <tr> |
| 376 | @ <td>%z(href("%R/timeline?n=100&r=%T",zBranch))%h(zBranch)</a></td> |
| 377 | @ <td data-sortkey="%016llx(-iMtime)">%s(zAge)</td> |
| 378 | @ <td>%d(nCkin)</td> |
| 379 | fossil_free(zAge); |
| 380 | @ <td>%s(isClosed?"closed":"")</td> |
| 381 |
| --- src/branch.c | |
| +++ src/branch.c | |
| @@ -154,11 +154,11 @@ | |
| 154 | if( brid==0 ){ |
| 155 | fossil_fatal("trouble committing manifest: %s", g.zErrMsg); |
| 156 | } |
| 157 | db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", brid); |
| 158 | if( manifest_crosslink(brid, &branch, MC_PERMIT_HOOKS)==0 ){ |
| 159 | fossil_fatal("%s", g.zErrMsg); |
| 160 | } |
| 161 | assert( blob_is_reset(&branch) ); |
| 162 | content_deltify(rootid, brid, 0); |
| 163 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", brid); |
| 164 | fossil_print("New branch: %s\n", zUuid); |
| @@ -323,11 +323,12 @@ | |
| 323 | @ WHERE plink.pid=event.objid |
| 324 | @ AND tagxref.rid=plink.cid |
| 325 | @ AND tagxref.tagid=(SELECT tagid FROM tag WHERE tagname='branch') |
| 326 | @ AND tagtype>0), |
| 327 | @ count(*), |
| 328 | @ (SELECT uuid FROM blob WHERE rid=tagxref.rid), |
| 329 | @ event.bgcolor |
| 330 | @ FROM tagxref, tag, event |
| 331 | @ WHERE tagxref.tagid=tag.tagid |
| 332 | @ AND tagxref.tagtype>0 |
| 333 | @ AND tag.tagname='branch' |
| 334 | @ AND event.objid=tagxref.rid |
| @@ -344,14 +345,16 @@ | |
| 345 | ** if there are no query parameters. |
| 346 | */ |
| 347 | static void new_brlist_page(void){ |
| 348 | Stmt q; |
| 349 | double rNow; |
| 350 | int show_colors = PB("colors"); |
| 351 | login_check_credentials(); |
| 352 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 353 | style_header("Branches"); |
| 354 | style_adunit_config(ADUNIT_RIGHT_OK); |
| 355 | style_submenu_binary("colors", "Color", "B/W", 0); |
| 356 | login_anonymous_available(); |
| 357 | |
| 358 | db_prepare(&q, brlistQuery/*works-like:""*/); |
| 359 | rNow = db_double(0.0, "SELECT julianday('now')"); |
| 360 | @ <div class="brlist"><table id="branchlisttable"> |
| @@ -367,14 +370,26 @@ | |
| 370 | double rMtime = db_column_double(&q, 1); |
| 371 | int isClosed = db_column_int(&q, 2); |
| 372 | const char *zMergeTo = db_column_text(&q, 3); |
| 373 | int nCkin = db_column_int(&q, 4); |
| 374 | const char *zLastCkin = db_column_text(&q, 5); |
| 375 | const char *zBgClr = db_column_text(&q, 6); |
| 376 | char *zAge = human_readable_age(rNow - rMtime); |
| 377 | sqlite3_int64 iMtime = (sqlite3_int64)(rMtime*86400.0); |
| 378 | if( zMergeTo && zMergeTo[0]==0 ) zMergeTo = 0; |
| 379 | if( zBgClr == 0 ){ |
| 380 | if( zBranch==0 || strcmp(zBranch,"trunk")==0 ){ |
| 381 | zBgClr = 0; |
| 382 | }else{ |
| 383 | zBgClr = hash_color(zBranch); |
| 384 | } |
| 385 | } |
| 386 | if( zBgClr && zBgClr[0] && show_colors ){ |
| 387 | @ <tr style="background-color:%s(zBgClr)"> |
| 388 | }else{ |
| 389 | @ <tr> |
| 390 | } |
| 391 | @ <td>%z(href("%R/timeline?n=100&r=%T",zBranch))%h(zBranch)</a></td> |
| 392 | @ <td data-sortkey="%016llx(-iMtime)">%s(zAge)</td> |
| 393 | @ <td>%d(nCkin)</td> |
| 394 | fossil_free(zAge); |
| 395 | @ <td>%s(isClosed?"closed":"")</td> |
| 396 |
+14
-4
| --- src/checkin.c | ||
| +++ src/checkin.c | ||
| @@ -1869,11 +1869,11 @@ | ||
| 1869 | 1869 | sCiInfo.zUserOvrd = find_option("user-override",0,1); |
| 1870 | 1870 | db_must_be_within_tree(); |
| 1871 | 1871 | noSign = db_get_boolean("omitsign", 0)|noSign; |
| 1872 | 1872 | if( db_get_boolean("clearsign", 0)==0 ){ noSign = 1; } |
| 1873 | 1873 | useCksum = db_get_boolean("repo-cksum", 1); |
| 1874 | - outputManifest = db_get_boolean("manifest", 0); | |
| 1874 | + outputManifest = db_get_manifest_setting(); | |
| 1875 | 1875 | verify_all_options(); |
| 1876 | 1876 | |
| 1877 | 1877 | /* Escape special characters in tags and put all tags in sorted order */ |
| 1878 | 1878 | if( nTag ){ |
| 1879 | 1879 | int i; |
| @@ -2230,11 +2230,11 @@ | ||
| 2230 | 2230 | ** and rollback the transaction. |
| 2231 | 2231 | */ |
| 2232 | 2232 | if( dryRunFlag ){ |
| 2233 | 2233 | blob_write_to_file(&manifest, ""); |
| 2234 | 2234 | } |
| 2235 | - if( outputManifest ){ | |
| 2235 | + if( outputManifest & MFESTFLG_RAW ){ | |
| 2236 | 2236 | zManifestFile = mprintf("%smanifest", g.zLocalRoot); |
| 2237 | 2237 | blob_write_to_file(&manifest, zManifestFile); |
| 2238 | 2238 | blob_reset(&manifest); |
| 2239 | 2239 | blob_read_from_file(&manifest, zManifestFile); |
| 2240 | 2240 | free(zManifestFile); |
| @@ -2245,11 +2245,11 @@ | ||
| 2245 | 2245 | fossil_fatal("trouble committing manifest: %s", g.zErrMsg); |
| 2246 | 2246 | } |
| 2247 | 2247 | db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nvid); |
| 2248 | 2248 | if( manifest_crosslink(nvid, &manifest, |
| 2249 | 2249 | dryRunFlag ? MC_NONE : MC_PERMIT_HOOKS)==0 ){ |
| 2250 | - fossil_fatal("%s\n", g.zErrMsg); | |
| 2250 | + fossil_fatal("%s", g.zErrMsg); | |
| 2251 | 2251 | } |
| 2252 | 2252 | assert( blob_is_reset(&manifest) ); |
| 2253 | 2253 | content_deltify(vid, nvid, 0); |
| 2254 | 2254 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nvid); |
| 2255 | 2255 | |
| @@ -2264,11 +2264,11 @@ | ||
| 2264 | 2264 | } |
| 2265 | 2265 | } |
| 2266 | 2266 | db_finalize(&q); |
| 2267 | 2267 | |
| 2268 | 2268 | fossil_print("New_Version: %s\n", zUuid); |
| 2269 | - if( outputManifest ){ | |
| 2269 | + if( outputManifest & MFESTFLG_UUID ){ | |
| 2270 | 2270 | zManifestFile = mprintf("%smanifest.uuid", g.zLocalRoot); |
| 2271 | 2271 | blob_zero(&muuid); |
| 2272 | 2272 | blob_appendf(&muuid, "%s\n", zUuid); |
| 2273 | 2273 | blob_write_to_file(&muuid, zManifestFile); |
| 2274 | 2274 | free(zManifestFile); |
| @@ -2346,13 +2346,23 @@ | ||
| 2346 | 2346 | if( dryRunFlag ){ |
| 2347 | 2347 | db_end_transaction(1); |
| 2348 | 2348 | exit(1); |
| 2349 | 2349 | } |
| 2350 | 2350 | db_end_transaction(0); |
| 2351 | + | |
| 2352 | + if( outputManifest & MFESTFLG_TAGS ){ | |
| 2353 | + Blob tagslist; | |
| 2354 | + zManifestFile = mprintf("%smanifest.tags", g.zLocalRoot); | |
| 2355 | + blob_zero(&tagslist); | |
| 2356 | + get_checkin_taglist(nvid, &tagslist); | |
| 2357 | + blob_write_to_file(&tagslist, zManifestFile); | |
| 2358 | + blob_reset(&tagslist); | |
| 2359 | + free(zManifestFile); | |
| 2360 | + } | |
| 2351 | 2361 | |
| 2352 | 2362 | if( !g.markPrivate ){ |
| 2353 | 2363 | autosync_loop(SYNC_PUSH|SYNC_PULL, db_get_int("autosync-tries", 1), 0); |
| 2354 | 2364 | } |
| 2355 | 2365 | if( count_nonbranch_children(vid)>1 ){ |
| 2356 | 2366 | fossil_print("**** warning: a fork has occurred *****\n"); |
| 2357 | 2367 | } |
| 2358 | 2368 | } |
| 2359 | 2369 |
| --- src/checkin.c | |
| +++ src/checkin.c | |
| @@ -1869,11 +1869,11 @@ | |
| 1869 | sCiInfo.zUserOvrd = find_option("user-override",0,1); |
| 1870 | db_must_be_within_tree(); |
| 1871 | noSign = db_get_boolean("omitsign", 0)|noSign; |
| 1872 | if( db_get_boolean("clearsign", 0)==0 ){ noSign = 1; } |
| 1873 | useCksum = db_get_boolean("repo-cksum", 1); |
| 1874 | outputManifest = db_get_boolean("manifest", 0); |
| 1875 | verify_all_options(); |
| 1876 | |
| 1877 | /* Escape special characters in tags and put all tags in sorted order */ |
| 1878 | if( nTag ){ |
| 1879 | int i; |
| @@ -2230,11 +2230,11 @@ | |
| 2230 | ** and rollback the transaction. |
| 2231 | */ |
| 2232 | if( dryRunFlag ){ |
| 2233 | blob_write_to_file(&manifest, ""); |
| 2234 | } |
| 2235 | if( outputManifest ){ |
| 2236 | zManifestFile = mprintf("%smanifest", g.zLocalRoot); |
| 2237 | blob_write_to_file(&manifest, zManifestFile); |
| 2238 | blob_reset(&manifest); |
| 2239 | blob_read_from_file(&manifest, zManifestFile); |
| 2240 | free(zManifestFile); |
| @@ -2245,11 +2245,11 @@ | |
| 2245 | fossil_fatal("trouble committing manifest: %s", g.zErrMsg); |
| 2246 | } |
| 2247 | db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nvid); |
| 2248 | if( manifest_crosslink(nvid, &manifest, |
| 2249 | dryRunFlag ? MC_NONE : MC_PERMIT_HOOKS)==0 ){ |
| 2250 | fossil_fatal("%s\n", g.zErrMsg); |
| 2251 | } |
| 2252 | assert( blob_is_reset(&manifest) ); |
| 2253 | content_deltify(vid, nvid, 0); |
| 2254 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nvid); |
| 2255 | |
| @@ -2264,11 +2264,11 @@ | |
| 2264 | } |
| 2265 | } |
| 2266 | db_finalize(&q); |
| 2267 | |
| 2268 | fossil_print("New_Version: %s\n", zUuid); |
| 2269 | if( outputManifest ){ |
| 2270 | zManifestFile = mprintf("%smanifest.uuid", g.zLocalRoot); |
| 2271 | blob_zero(&muuid); |
| 2272 | blob_appendf(&muuid, "%s\n", zUuid); |
| 2273 | blob_write_to_file(&muuid, zManifestFile); |
| 2274 | free(zManifestFile); |
| @@ -2346,13 +2346,23 @@ | |
| 2346 | if( dryRunFlag ){ |
| 2347 | db_end_transaction(1); |
| 2348 | exit(1); |
| 2349 | } |
| 2350 | db_end_transaction(0); |
| 2351 | |
| 2352 | if( !g.markPrivate ){ |
| 2353 | autosync_loop(SYNC_PUSH|SYNC_PULL, db_get_int("autosync-tries", 1), 0); |
| 2354 | } |
| 2355 | if( count_nonbranch_children(vid)>1 ){ |
| 2356 | fossil_print("**** warning: a fork has occurred *****\n"); |
| 2357 | } |
| 2358 | } |
| 2359 |
| --- src/checkin.c | |
| +++ src/checkin.c | |
| @@ -1869,11 +1869,11 @@ | |
| 1869 | sCiInfo.zUserOvrd = find_option("user-override",0,1); |
| 1870 | db_must_be_within_tree(); |
| 1871 | noSign = db_get_boolean("omitsign", 0)|noSign; |
| 1872 | if( db_get_boolean("clearsign", 0)==0 ){ noSign = 1; } |
| 1873 | useCksum = db_get_boolean("repo-cksum", 1); |
| 1874 | outputManifest = db_get_manifest_setting(); |
| 1875 | verify_all_options(); |
| 1876 | |
| 1877 | /* Escape special characters in tags and put all tags in sorted order */ |
| 1878 | if( nTag ){ |
| 1879 | int i; |
| @@ -2230,11 +2230,11 @@ | |
| 2230 | ** and rollback the transaction. |
| 2231 | */ |
| 2232 | if( dryRunFlag ){ |
| 2233 | blob_write_to_file(&manifest, ""); |
| 2234 | } |
| 2235 | if( outputManifest & MFESTFLG_RAW ){ |
| 2236 | zManifestFile = mprintf("%smanifest", g.zLocalRoot); |
| 2237 | blob_write_to_file(&manifest, zManifestFile); |
| 2238 | blob_reset(&manifest); |
| 2239 | blob_read_from_file(&manifest, zManifestFile); |
| 2240 | free(zManifestFile); |
| @@ -2245,11 +2245,11 @@ | |
| 2245 | fossil_fatal("trouble committing manifest: %s", g.zErrMsg); |
| 2246 | } |
| 2247 | db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nvid); |
| 2248 | if( manifest_crosslink(nvid, &manifest, |
| 2249 | dryRunFlag ? MC_NONE : MC_PERMIT_HOOKS)==0 ){ |
| 2250 | fossil_fatal("%s", g.zErrMsg); |
| 2251 | } |
| 2252 | assert( blob_is_reset(&manifest) ); |
| 2253 | content_deltify(vid, nvid, 0); |
| 2254 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nvid); |
| 2255 | |
| @@ -2264,11 +2264,11 @@ | |
| 2264 | } |
| 2265 | } |
| 2266 | db_finalize(&q); |
| 2267 | |
| 2268 | fossil_print("New_Version: %s\n", zUuid); |
| 2269 | if( outputManifest & MFESTFLG_UUID ){ |
| 2270 | zManifestFile = mprintf("%smanifest.uuid", g.zLocalRoot); |
| 2271 | blob_zero(&muuid); |
| 2272 | blob_appendf(&muuid, "%s\n", zUuid); |
| 2273 | blob_write_to_file(&muuid, zManifestFile); |
| 2274 | free(zManifestFile); |
| @@ -2346,13 +2346,23 @@ | |
| 2346 | if( dryRunFlag ){ |
| 2347 | db_end_transaction(1); |
| 2348 | exit(1); |
| 2349 | } |
| 2350 | db_end_transaction(0); |
| 2351 | |
| 2352 | if( outputManifest & MFESTFLG_TAGS ){ |
| 2353 | Blob tagslist; |
| 2354 | zManifestFile = mprintf("%smanifest.tags", g.zLocalRoot); |
| 2355 | blob_zero(&tagslist); |
| 2356 | get_checkin_taglist(nvid, &tagslist); |
| 2357 | blob_write_to_file(&tagslist, zManifestFile); |
| 2358 | blob_reset(&tagslist); |
| 2359 | free(zManifestFile); |
| 2360 | } |
| 2361 | |
| 2362 | if( !g.markPrivate ){ |
| 2363 | autosync_loop(SYNC_PUSH|SYNC_PULL, db_get_int("autosync-tries", 1), 0); |
| 2364 | } |
| 2365 | if( count_nonbranch_children(vid)>1 ){ |
| 2366 | fossil_print("**** warning: a fork has occurred *****\n"); |
| 2367 | } |
| 2368 | } |
| 2369 |
+65
-7
| --- src/checkout.c | ||
| +++ src/checkout.c | ||
| @@ -127,44 +127,102 @@ | ||
| 127 | 127 | |
| 128 | 128 | /* |
| 129 | 129 | ** If the "manifest" setting is true, then automatically generate |
| 130 | 130 | ** files named "manifest" and "manifest.uuid" containing, respectively, |
| 131 | 131 | ** the text of the manifest and the artifact ID of the manifest. |
| 132 | +** If the manifest setting is set, but is not a boolean value, then treat | |
| 133 | +** each character as a flag to enable writing "manifest", "manifest.uuid" or | |
| 134 | +** "manifest.tags". | |
| 132 | 135 | */ |
| 133 | 136 | void manifest_to_disk(int vid){ |
| 134 | 137 | char *zManFile; |
| 135 | 138 | Blob manifest; |
| 136 | 139 | Blob hash; |
| 140 | + Blob taglist; | |
| 141 | + int flg; | |
| 142 | + | |
| 143 | + flg = db_get_manifest_setting(); | |
| 137 | 144 | |
| 138 | - if( db_get_boolean("manifest",0) ){ | |
| 145 | + if( flg & (MFESTFLG_RAW|MFESTFLG_UUID) ){ | |
| 139 | 146 | blob_zero(&manifest); |
| 140 | 147 | content_get(vid, &manifest); |
| 141 | - zManFile = mprintf("%smanifest", g.zLocalRoot); | |
| 142 | 148 | blob_zero(&hash); |
| 143 | 149 | sha1sum_blob(&manifest, &hash); |
| 144 | 150 | sterilize_manifest(&manifest); |
| 151 | + } | |
| 152 | + if( flg & MFESTFLG_RAW ){ | |
| 153 | + zManFile = mprintf("%smanifest", g.zLocalRoot); | |
| 145 | 154 | blob_write_to_file(&manifest, zManFile); |
| 146 | 155 | free(zManFile); |
| 147 | - zManFile = mprintf("%smanifest.uuid", g.zLocalRoot); | |
| 148 | - blob_append(&hash, "\n", 1); | |
| 149 | - blob_write_to_file(&hash, zManFile); | |
| 150 | - free(zManFile); | |
| 151 | - blob_reset(&hash); | |
| 152 | 156 | }else{ |
| 153 | 157 | if( !db_exists("SELECT 1 FROM vfile WHERE pathname='manifest'") ){ |
| 154 | 158 | zManFile = mprintf("%smanifest", g.zLocalRoot); |
| 155 | 159 | file_delete(zManFile); |
| 156 | 160 | free(zManFile); |
| 157 | 161 | } |
| 162 | + } | |
| 163 | + if( flg & MFESTFLG_UUID ){ | |
| 164 | + zManFile = mprintf("%smanifest.uuid", g.zLocalRoot); | |
| 165 | + blob_append(&hash, "\n", 1); | |
| 166 | + blob_write_to_file(&hash, zManFile); | |
| 167 | + free(zManFile); | |
| 168 | + blob_reset(&hash); | |
| 169 | + }else{ | |
| 158 | 170 | if( !db_exists("SELECT 1 FROM vfile WHERE pathname='manifest.uuid'") ){ |
| 159 | 171 | zManFile = mprintf("%smanifest.uuid", g.zLocalRoot); |
| 160 | 172 | file_delete(zManFile); |
| 161 | 173 | free(zManFile); |
| 162 | 174 | } |
| 163 | 175 | } |
| 176 | + if( flg & MFESTFLG_TAGS ){ | |
| 177 | + blob_zero(&taglist); | |
| 178 | + zManFile = mprintf("%smanifest.tags", g.zLocalRoot); | |
| 179 | + get_checkin_taglist(vid, &taglist); | |
| 180 | + blob_write_to_file(&taglist, zManFile); | |
| 181 | + free(zManFile); | |
| 182 | + blob_reset(&taglist); | |
| 183 | + }else{ | |
| 184 | + if( !db_exists("SELECT 1 FROM vfile WHERE pathname='manifest.tags'") ){ | |
| 185 | + zManFile = mprintf("%smanifest.tags", g.zLocalRoot); | |
| 186 | + file_delete(zManFile); | |
| 187 | + free(zManFile); | |
| 188 | + } | |
| 189 | + } | |
| 190 | +} | |
| 164 | 191 | |
| 192 | +/* | |
| 193 | +** Find the branch name and all symbolic tags for a particular check-in | |
| 194 | +** identified by "rid". | |
| 195 | +** | |
| 196 | +** The branch name is actually only extracted if this procedure is run | |
| 197 | +** from within a local check-out. And the branch name is not the branch | |
| 198 | +** name for "rid" but rather the branch name for the current check-out. | |
| 199 | +** It is unclear if the rid parameter is always the same as the current | |
| 200 | +** check-out. | |
| 201 | +*/ | |
| 202 | +void get_checkin_taglist(int rid, Blob *pOut){ | |
| 203 | + Stmt stmt; | |
| 204 | + char *zCurrent; | |
| 205 | + blob_reset(pOut); | |
| 206 | + zCurrent = db_text(0, "SELECT value FROM tagxref" | |
| 207 | + " WHERE rid=%d AND tagid=%d", rid, TAG_BRANCH); | |
| 208 | + blob_appendf(pOut, "branch %s\n", zCurrent); | |
| 209 | + db_prepare(&stmt, "SELECT substr(tagname, 5)" | |
| 210 | + " FROM tagxref, tag" | |
| 211 | + " WHERE tagxref.rid=%d" | |
| 212 | + " AND tagxref.tagtype>0" | |
| 213 | + " AND tag.tagid=tagxref.tagid" | |
| 214 | + " AND tag.tagname GLOB 'sym-*'", rid); | |
| 215 | + while( db_step(&stmt)==SQLITE_ROW ){ | |
| 216 | + const char *zName; | |
| 217 | + zName = db_column_text(&stmt, 0); | |
| 218 | + blob_appendf(pOut, "tag %s\n", zName); | |
| 219 | + } | |
| 220 | + db_reset(&stmt); | |
| 221 | + db_finalize(&stmt); | |
| 165 | 222 | } |
| 223 | + | |
| 166 | 224 | |
| 167 | 225 | /* |
| 168 | 226 | ** COMMAND: checkout* |
| 169 | 227 | ** COMMAND: co* |
| 170 | 228 | ** |
| 171 | 229 |
| --- src/checkout.c | |
| +++ src/checkout.c | |
| @@ -127,44 +127,102 @@ | |
| 127 | |
| 128 | /* |
| 129 | ** If the "manifest" setting is true, then automatically generate |
| 130 | ** files named "manifest" and "manifest.uuid" containing, respectively, |
| 131 | ** the text of the manifest and the artifact ID of the manifest. |
| 132 | */ |
| 133 | void manifest_to_disk(int vid){ |
| 134 | char *zManFile; |
| 135 | Blob manifest; |
| 136 | Blob hash; |
| 137 | |
| 138 | if( db_get_boolean("manifest",0) ){ |
| 139 | blob_zero(&manifest); |
| 140 | content_get(vid, &manifest); |
| 141 | zManFile = mprintf("%smanifest", g.zLocalRoot); |
| 142 | blob_zero(&hash); |
| 143 | sha1sum_blob(&manifest, &hash); |
| 144 | sterilize_manifest(&manifest); |
| 145 | blob_write_to_file(&manifest, zManFile); |
| 146 | free(zManFile); |
| 147 | zManFile = mprintf("%smanifest.uuid", g.zLocalRoot); |
| 148 | blob_append(&hash, "\n", 1); |
| 149 | blob_write_to_file(&hash, zManFile); |
| 150 | free(zManFile); |
| 151 | blob_reset(&hash); |
| 152 | }else{ |
| 153 | if( !db_exists("SELECT 1 FROM vfile WHERE pathname='manifest'") ){ |
| 154 | zManFile = mprintf("%smanifest", g.zLocalRoot); |
| 155 | file_delete(zManFile); |
| 156 | free(zManFile); |
| 157 | } |
| 158 | if( !db_exists("SELECT 1 FROM vfile WHERE pathname='manifest.uuid'") ){ |
| 159 | zManFile = mprintf("%smanifest.uuid", g.zLocalRoot); |
| 160 | file_delete(zManFile); |
| 161 | free(zManFile); |
| 162 | } |
| 163 | } |
| 164 | |
| 165 | } |
| 166 | |
| 167 | /* |
| 168 | ** COMMAND: checkout* |
| 169 | ** COMMAND: co* |
| 170 | ** |
| 171 |
| --- src/checkout.c | |
| +++ src/checkout.c | |
| @@ -127,44 +127,102 @@ | |
| 127 | |
| 128 | /* |
| 129 | ** If the "manifest" setting is true, then automatically generate |
| 130 | ** files named "manifest" and "manifest.uuid" containing, respectively, |
| 131 | ** the text of the manifest and the artifact ID of the manifest. |
| 132 | ** If the manifest setting is set, but is not a boolean value, then treat |
| 133 | ** each character as a flag to enable writing "manifest", "manifest.uuid" or |
| 134 | ** "manifest.tags". |
| 135 | */ |
| 136 | void manifest_to_disk(int vid){ |
| 137 | char *zManFile; |
| 138 | Blob manifest; |
| 139 | Blob hash; |
| 140 | Blob taglist; |
| 141 | int flg; |
| 142 | |
| 143 | flg = db_get_manifest_setting(); |
| 144 | |
| 145 | if( flg & (MFESTFLG_RAW|MFESTFLG_UUID) ){ |
| 146 | blob_zero(&manifest); |
| 147 | content_get(vid, &manifest); |
| 148 | blob_zero(&hash); |
| 149 | sha1sum_blob(&manifest, &hash); |
| 150 | sterilize_manifest(&manifest); |
| 151 | } |
| 152 | if( flg & MFESTFLG_RAW ){ |
| 153 | zManFile = mprintf("%smanifest", g.zLocalRoot); |
| 154 | blob_write_to_file(&manifest, zManFile); |
| 155 | free(zManFile); |
| 156 | }else{ |
| 157 | if( !db_exists("SELECT 1 FROM vfile WHERE pathname='manifest'") ){ |
| 158 | zManFile = mprintf("%smanifest", g.zLocalRoot); |
| 159 | file_delete(zManFile); |
| 160 | free(zManFile); |
| 161 | } |
| 162 | } |
| 163 | if( flg & MFESTFLG_UUID ){ |
| 164 | zManFile = mprintf("%smanifest.uuid", g.zLocalRoot); |
| 165 | blob_append(&hash, "\n", 1); |
| 166 | blob_write_to_file(&hash, zManFile); |
| 167 | free(zManFile); |
| 168 | blob_reset(&hash); |
| 169 | }else{ |
| 170 | if( !db_exists("SELECT 1 FROM vfile WHERE pathname='manifest.uuid'") ){ |
| 171 | zManFile = mprintf("%smanifest.uuid", g.zLocalRoot); |
| 172 | file_delete(zManFile); |
| 173 | free(zManFile); |
| 174 | } |
| 175 | } |
| 176 | if( flg & MFESTFLG_TAGS ){ |
| 177 | blob_zero(&taglist); |
| 178 | zManFile = mprintf("%smanifest.tags", g.zLocalRoot); |
| 179 | get_checkin_taglist(vid, &taglist); |
| 180 | blob_write_to_file(&taglist, zManFile); |
| 181 | free(zManFile); |
| 182 | blob_reset(&taglist); |
| 183 | }else{ |
| 184 | if( !db_exists("SELECT 1 FROM vfile WHERE pathname='manifest.tags'") ){ |
| 185 | zManFile = mprintf("%smanifest.tags", g.zLocalRoot); |
| 186 | file_delete(zManFile); |
| 187 | free(zManFile); |
| 188 | } |
| 189 | } |
| 190 | } |
| 191 | |
| 192 | /* |
| 193 | ** Find the branch name and all symbolic tags for a particular check-in |
| 194 | ** identified by "rid". |
| 195 | ** |
| 196 | ** The branch name is actually only extracted if this procedure is run |
| 197 | ** from within a local check-out. And the branch name is not the branch |
| 198 | ** name for "rid" but rather the branch name for the current check-out. |
| 199 | ** It is unclear if the rid parameter is always the same as the current |
| 200 | ** check-out. |
| 201 | */ |
| 202 | void get_checkin_taglist(int rid, Blob *pOut){ |
| 203 | Stmt stmt; |
| 204 | char *zCurrent; |
| 205 | blob_reset(pOut); |
| 206 | zCurrent = db_text(0, "SELECT value FROM tagxref" |
| 207 | " WHERE rid=%d AND tagid=%d", rid, TAG_BRANCH); |
| 208 | blob_appendf(pOut, "branch %s\n", zCurrent); |
| 209 | db_prepare(&stmt, "SELECT substr(tagname, 5)" |
| 210 | " FROM tagxref, tag" |
| 211 | " WHERE tagxref.rid=%d" |
| 212 | " AND tagxref.tagtype>0" |
| 213 | " AND tag.tagid=tagxref.tagid" |
| 214 | " AND tag.tagname GLOB 'sym-*'", rid); |
| 215 | while( db_step(&stmt)==SQLITE_ROW ){ |
| 216 | const char *zName; |
| 217 | zName = db_column_text(&stmt, 0); |
| 218 | blob_appendf(pOut, "tag %s\n", zName); |
| 219 | } |
| 220 | db_reset(&stmt); |
| 221 | db_finalize(&stmt); |
| 222 | } |
| 223 | |
| 224 | |
| 225 | /* |
| 226 | ** COMMAND: checkout* |
| 227 | ** COMMAND: co* |
| 228 | ** |
| 229 |
M
src/db.c
+207
-18
| --- src/db.c | ||
| +++ src/db.c | ||
| @@ -27,11 +27,15 @@ | ||
| 27 | 27 | ** (3) A local checkout database named "_FOSSIL_" or ".fslckout" |
| 28 | 28 | ** and located at the root of the local copy of the source tree. |
| 29 | 29 | ** |
| 30 | 30 | */ |
| 31 | 31 | #include "config.h" |
| 32 | -#if ! defined(_WIN32) | |
| 32 | +#if defined(_WIN32) | |
| 33 | +# if USE_SEE | |
| 34 | +# include <windows.h> | |
| 35 | +# endif | |
| 36 | +#else | |
| 33 | 37 | # include <pwd.h> |
| 34 | 38 | #endif |
| 35 | 39 | #include <sqlite3.h> |
| 36 | 40 | #include <sys/types.h> |
| 37 | 41 | #include <sys/stat.h> |
| @@ -870,31 +874,170 @@ | ||
| 870 | 874 | db_tolocal_function, 0, 0); |
| 871 | 875 | sqlite3_create_function(db, "fromLocal", 0, SQLITE_UTF8, 0, |
| 872 | 876 | db_fromlocal_function, 0, 0); |
| 873 | 877 | } |
| 874 | 878 | |
| 879 | +#if USE_SEE | |
| 880 | +/* | |
| 881 | +** This is a pointer to the saved database encryption key string. | |
| 882 | +*/ | |
| 883 | +static char *zSavedKey = 0; | |
| 884 | + | |
| 885 | +/* | |
| 886 | +** This is the size of the saved database encryption key, in bytes. | |
| 887 | +*/ | |
| 888 | +size_t savedKeySize = 0; | |
| 889 | + | |
| 890 | +/* | |
| 891 | +** This function returns the saved database encryption key -OR- zero if | |
| 892 | +** no database encryption key is saved. | |
| 893 | +*/ | |
| 894 | +char *db_get_saved_encryption_key(){ | |
| 895 | + return zSavedKey; | |
| 896 | +} | |
| 897 | + | |
| 898 | +/* | |
| 899 | +** This function returns the size of the saved database encryption key | |
| 900 | +** -OR- zero if no database encryption key is saved. | |
| 901 | +*/ | |
| 902 | +size_t db_get_saved_encryption_key_size(){ | |
| 903 | + return savedKeySize; | |
| 904 | +} | |
| 905 | + | |
| 906 | +/* | |
| 907 | +** This function arranges for the database encryption key to be securely | |
| 908 | +** saved in non-pagable memory (on platforms where this is possible). | |
| 909 | +*/ | |
| 910 | +static void db_save_encryption_key( | |
| 911 | + Blob *pKey | |
| 912 | +){ | |
| 913 | + void *p = NULL; | |
| 914 | + size_t n = 0; | |
| 915 | + size_t pageSize = 0; | |
| 916 | + size_t blobSize = 0; | |
| 917 | + | |
| 918 | + blobSize = blob_size(pKey); | |
| 919 | + if( blobSize==0 ) return; | |
| 920 | + fossil_get_page_size(&pageSize); | |
| 921 | + assert( pageSize>0 ); | |
| 922 | + if( blobSize>pageSize ){ | |
| 923 | + fossil_fatal("key blob too large: %u versus %u", blobSize, pageSize); | |
| 924 | + } | |
| 925 | + p = fossil_secure_alloc_page(&n); | |
| 926 | + assert( p!=NULL ); | |
| 927 | + assert( n==pageSize ); | |
| 928 | + assert( n>=blobSize ); | |
| 929 | + memcpy(p, blob_str(pKey), blobSize); | |
| 930 | + zSavedKey = p; | |
| 931 | + savedKeySize = n; | |
| 932 | +} | |
| 933 | + | |
| 934 | +/* | |
| 935 | +** This function arranges for the saved database encryption key to be | |
| 936 | +** securely zeroed, unlocked (if necessary), and freed. | |
| 937 | +*/ | |
| 938 | +void db_unsave_encryption_key(){ | |
| 939 | + fossil_secure_free_page(zSavedKey, savedKeySize); | |
| 940 | + zSavedKey = NULL; | |
| 941 | + savedKeySize = 0; | |
| 942 | +} | |
| 943 | + | |
| 944 | +/* | |
| 945 | +** This function sets the saved database encryption key to the specified | |
| 946 | +** string value, allocating or freeing the underlying memory if needed. | |
| 947 | +*/ | |
| 948 | +void db_set_saved_encryption_key( | |
| 949 | + Blob *pKey | |
| 950 | +){ | |
| 951 | + if( zSavedKey!=NULL ){ | |
| 952 | + size_t blobSize = blob_size(pKey); | |
| 953 | + if( blobSize==0 ){ | |
| 954 | + db_unsave_encryption_key(); | |
| 955 | + }else{ | |
| 956 | + if( blobSize>savedKeySize ){ | |
| 957 | + fossil_fatal("key blob too large: %u versus %u", | |
| 958 | + blobSize, savedKeySize); | |
| 959 | + } | |
| 960 | + fossil_secure_zero(zSavedKey, savedKeySize); | |
| 961 | + memcpy(zSavedKey, blob_str(pKey), blobSize); | |
| 962 | + } | |
| 963 | + }else{ | |
| 964 | + db_save_encryption_key(pKey); | |
| 965 | + } | |
| 966 | +} | |
| 967 | + | |
| 968 | +#if defined(_WIN32) | |
| 969 | +/* | |
| 970 | +** This function sets the saved database encryption key to one that gets | |
| 971 | +** read from the specified Fossil parent process. This is only necessary | |
| 972 | +** (or functional) on Windows. | |
| 973 | +*/ | |
| 974 | +void db_read_saved_encryption_key_from_process( | |
| 975 | + DWORD processId, /* Identifier for Fossil parent process. */ | |
| 976 | + LPVOID pAddress, /* Pointer to saved key buffer in the parent process. */ | |
| 977 | + SIZE_T nSize /* Size of saved key buffer in the parent process. */ | |
| 978 | +){ | |
| 979 | + void *p = NULL; | |
| 980 | + size_t n = 0; | |
| 981 | + size_t pageSize = 0; | |
| 982 | + HANDLE hProcess = NULL; | |
| 983 | + | |
| 984 | + fossil_get_page_size(&pageSize); | |
| 985 | + assert( pageSize>0 ); | |
| 986 | + if( nSize>pageSize ){ | |
| 987 | + fossil_fatal("key too large: %u versus %u", nSize, pageSize); | |
| 988 | + } | |
| 989 | + p = fossil_secure_alloc_page(&n); | |
| 990 | + assert( p!=NULL ); | |
| 991 | + assert( n==pageSize ); | |
| 992 | + assert( n>=nSize ); | |
| 993 | + hProcess = OpenProcess(PROCESS_VM_READ, FALSE, processId); | |
| 994 | + if( hProcess!=NULL ){ | |
| 995 | + SIZE_T nRead = 0; | |
| 996 | + if( ReadProcessMemory(hProcess, pAddress, p, nSize, &nRead) ){ | |
| 997 | + CloseHandle(hProcess); | |
| 998 | + if( nRead==nSize ){ | |
| 999 | + db_unsave_encryption_key(); | |
| 1000 | + zSavedKey = p; | |
| 1001 | + savedKeySize = n; | |
| 1002 | + }else{ | |
| 1003 | + fossil_fatal("bad size read, %u out of %u bytes at %p from pid %lu", | |
| 1004 | + nRead, nSize, pAddress, processId); | |
| 1005 | + } | |
| 1006 | + }else{ | |
| 1007 | + CloseHandle(hProcess); | |
| 1008 | + fossil_fatal("failed read, %u bytes at %p from pid %lu: %lu", nSize, | |
| 1009 | + pAddress, processId, GetLastError()); | |
| 1010 | + } | |
| 1011 | + }else{ | |
| 1012 | + fossil_fatal("failed to open pid %lu: %lu", processId, GetLastError()); | |
| 1013 | + } | |
| 1014 | +} | |
| 1015 | +#endif /* defined(_WIN32) */ | |
| 1016 | +#endif /* USE_SEE */ | |
| 1017 | + | |
| 875 | 1018 | /* |
| 876 | 1019 | ** If the database file zDbFile has a name that suggests that it is |
| 877 | -** encrypted, then prompt for the encryption key and return it in the | |
| 878 | -** blob *pKey. Or, if the encryption key has previously been requested, | |
| 879 | -** just return a copy of the previous result. | |
| 1020 | +** encrypted, then prompt for the database encryption key and return it | |
| 1021 | +** in the blob *pKey. Or, if the encryption key has previously been | |
| 1022 | +** requested, just return a copy of the previous result. The blob in | |
| 1023 | +** *pKey must be initialized. | |
| 880 | 1024 | */ |
| 881 | -static void db_encryption_key( | |
| 1025 | +static void db_maybe_obtain_encryption_key( | |
| 882 | 1026 | const char *zDbFile, /* Name of the database file */ |
| 883 | 1027 | Blob *pKey /* Put the encryption key here */ |
| 884 | 1028 | ){ |
| 885 | - blob_init(pKey, 0, 0); | |
| 886 | 1029 | #if USE_SEE |
| 887 | 1030 | if( sqlite3_strglob("*.efossil", zDbFile)==0 ){ |
| 888 | - static char *zSavedKey = 0; | |
| 889 | - if( zSavedKey ){ | |
| 890 | - blob_set(pKey, zSavedKey); | |
| 1031 | + char *zKey = db_get_saved_encryption_key(); | |
| 1032 | + if( zKey ){ | |
| 1033 | + blob_set(pKey, zKey); | |
| 891 | 1034 | }else{ |
| 892 | 1035 | char *zPrompt = mprintf("\rencryption key for '%s': ", zDbFile); |
| 893 | 1036 | prompt_for_password(zPrompt, pKey, 0); |
| 894 | 1037 | fossil_free(zPrompt); |
| 895 | - zSavedKey = fossil_strdup(blob_str(pKey)); | |
| 1038 | + db_set_saved_encryption_key(pKey); | |
| 896 | 1039 | } |
| 897 | 1040 | } |
| 898 | 1041 | #endif |
| 899 | 1042 | } |
| 900 | 1043 | |
| @@ -915,14 +1058,16 @@ | ||
| 915 | 1058 | g.zVfsName |
| 916 | 1059 | ); |
| 917 | 1060 | if( rc!=SQLITE_OK ){ |
| 918 | 1061 | db_err("[%s]: %s", zDbName, sqlite3_errmsg(db)); |
| 919 | 1062 | } |
| 920 | - db_encryption_key(zDbName, &key); | |
| 1063 | + blob_init(&key, 0, 0); | |
| 1064 | + db_maybe_obtain_encryption_key(zDbName, &key); | |
| 921 | 1065 | if( blob_size(&key)>0 ){ |
| 922 | 1066 | char *zCmd = sqlite3_mprintf("PRAGMA key(%Q)", blob_str(&key)); |
| 923 | 1067 | sqlite3_exec(db, zCmd, 0, 0, 0); |
| 1068 | + fossil_secure_zero(zCmd, strlen(zCmd)); | |
| 924 | 1069 | sqlite3_free(zCmd); |
| 925 | 1070 | } |
| 926 | 1071 | blob_reset(&key); |
| 927 | 1072 | sqlite3_busy_timeout(db, 5000); |
| 928 | 1073 | sqlite3_wal_autocheckpoint(db, 1); /* Set to checkpoint frequently */ |
| @@ -955,14 +1100,19 @@ | ||
| 955 | 1100 | /* |
| 956 | 1101 | ** zDbName is the name of a database file. Attach zDbName using |
| 957 | 1102 | ** the name zLabel. |
| 958 | 1103 | */ |
| 959 | 1104 | void db_attach(const char *zDbName, const char *zLabel){ |
| 1105 | + char *zCmd; | |
| 960 | 1106 | Blob key; |
| 961 | - db_encryption_key(zDbName, &key); | |
| 962 | - db_multi_exec("ATTACH DATABASE %Q AS %Q KEY %Q", | |
| 963 | - zDbName, zLabel, blob_str(&key)); | |
| 1107 | + blob_init(&key, 0, 0); | |
| 1108 | + db_maybe_obtain_encryption_key(zDbName, &key); | |
| 1109 | + zCmd = sqlite3_mprintf("ATTACH DATABASE %Q AS %Q KEY %Q", | |
| 1110 | + zDbName, zLabel, blob_str(&key)); | |
| 1111 | + db_multi_exec(zCmd /*works-like:""*/); | |
| 1112 | + fossil_secure_zero(zCmd, strlen(zCmd)); | |
| 1113 | + sqlite3_free(zCmd); | |
| 964 | 1114 | blob_reset(&key); |
| 965 | 1115 | } |
| 966 | 1116 | |
| 967 | 1117 | /* |
| 968 | 1118 | ** Change the schema name of the "main" database to zLabel. |
| @@ -1192,10 +1342,11 @@ | ||
| 1192 | 1342 | } |
| 1193 | 1343 | if( db_local_table_exists_but_lacks_column("undo_vfile", "islink") ){ |
| 1194 | 1344 | db_multi_exec("ALTER TABLE undo_vfile ADD COLUMN islink BOOL DEFAULT 0"); |
| 1195 | 1345 | } |
| 1196 | 1346 | } |
| 1347 | + fossil_free(zVFileDef); | |
| 1197 | 1348 | return 1; |
| 1198 | 1349 | } |
| 1199 | 1350 | |
| 1200 | 1351 | /* |
| 1201 | 1352 | ** Locate the root directory of the local repository tree. The root |
| @@ -2270,10 +2421,45 @@ | ||
| 2270 | 2421 | return db_int(dflt, "SELECT value FROM vvar WHERE name=%Q", zName); |
| 2271 | 2422 | } |
| 2272 | 2423 | void db_lset_int(const char *zName, int value){ |
| 2273 | 2424 | db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%d)", zName, value); |
| 2274 | 2425 | } |
| 2426 | + | |
| 2427 | +#if INTERFACE | |
| 2428 | +/* Manifest generation flags */ | |
| 2429 | +#define MFESTFLG_RAW 0x01 | |
| 2430 | +#define MFESTFLG_UUID 0x02 | |
| 2431 | +#define MFESTFLG_TAGS 0x04 | |
| 2432 | +#endif /* INTERFACE */ | |
| 2433 | + | |
| 2434 | +/* | |
| 2435 | +** Get the manifest setting. For backwards compatibility first check if the | |
| 2436 | +** value is a boolean. If it's not a boolean, treat each character as a flag | |
| 2437 | +** to enable a manifest type. This system puts certain boundary conditions on | |
| 2438 | +** which letters can be used to represent flags (any permutation of flags must | |
| 2439 | +** not be able to fully form one of the boolean values). | |
| 2440 | +*/ | |
| 2441 | +int db_get_manifest_setting(void){ | |
| 2442 | + int flg; | |
| 2443 | + char *zVal = db_get("manifest", 0); | |
| 2444 | + if( zVal==0 || is_false(zVal) ){ | |
| 2445 | + return 0; | |
| 2446 | + }else if( is_truth(zVal) ){ | |
| 2447 | + return MFESTFLG_RAW|MFESTFLG_UUID; | |
| 2448 | + } | |
| 2449 | + flg = 0; | |
| 2450 | + while( *zVal ){ | |
| 2451 | + switch( *zVal ){ | |
| 2452 | + case 'r': flg |= MFESTFLG_RAW; break; | |
| 2453 | + case 'u': flg |= MFESTFLG_UUID; break; | |
| 2454 | + case 't': flg |= MFESTFLG_TAGS; break; | |
| 2455 | + } | |
| 2456 | + zVal++; | |
| 2457 | + } | |
| 2458 | + return flg; | |
| 2459 | +} | |
| 2460 | + | |
| 2275 | 2461 | |
| 2276 | 2462 | /* |
| 2277 | 2463 | ** Record the name of a local repository in the global_config() database. |
| 2278 | 2464 | ** The repository filename %s is recorded as an entry with a "name" field |
| 2279 | 2465 | ** of the following form: |
| @@ -2570,11 +2756,11 @@ | ||
| 2570 | 2756 | { "https-login", 0, 0, 0, 0, "off" }, |
| 2571 | 2757 | { "ignore-glob", 0, 40, 1, 0, "" }, |
| 2572 | 2758 | { "keep-glob", 0, 40, 1, 0, "" }, |
| 2573 | 2759 | { "localauth", 0, 0, 0, 0, "off" }, |
| 2574 | 2760 | { "main-branch", 0, 40, 0, 0, "trunk" }, |
| 2575 | - { "manifest", 0, 0, 1, 0, "off" }, | |
| 2761 | + { "manifest", 0, 5, 1, 0, "off" }, | |
| 2576 | 2762 | { "max-loadavg", 0, 25, 0, 0, "0.0" }, |
| 2577 | 2763 | { "max-upload", 0, 25, 0, 0, "250000" }, |
| 2578 | 2764 | { "mtime-changes", 0, 0, 0, 0, "on" }, |
| 2579 | 2765 | #if FOSSIL_ENABLE_LEGACY_MV_RM |
| 2580 | 2766 | { "mv-rm-files", 0, 0, 0, 0, "off" }, |
| @@ -2775,13 +2961,16 @@ | ||
| 2775 | 2961 | ** false, all HTTP requests from localhost have |
| 2776 | 2962 | ** unrestricted access to the repository. |
| 2777 | 2963 | ** |
| 2778 | 2964 | ** main-branch The primary branch for the project. Default: trunk |
| 2779 | 2965 | ** |
| 2780 | -** manifest If enabled, automatically create files "manifest" and | |
| 2781 | -** (versionable) "manifest.uuid" in every checkout. The SQLite and | |
| 2782 | -** Fossil repositories both require this. Default: off. | |
| 2966 | +** manifest If set to a true boolean value, automatically create | |
| 2967 | +** (versionable) files "manifest" and "manifest.uuid" in every checkout. | |
| 2968 | +** Optionally use combinations of characters 'r' | |
| 2969 | +** for "manifest", 'u' for "manifest.uuid" and 't' for | |
| 2970 | +** "manifest.tags". The SQLite and Fossil repositories | |
| 2971 | +** both require manifests. Default: off. | |
| 2783 | 2972 | ** |
| 2784 | 2973 | ** max-loadavg Some CPU-intensive web pages (ex: /zip, /tarball, /blame) |
| 2785 | 2974 | ** are disallowed if the system load average goes above this |
| 2786 | 2975 | ** value. "0.0" means no limit. This only works on unix. |
| 2787 | 2976 | ** Only local settings of this value make a difference since |
| 2788 | 2977 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -27,11 +27,15 @@ | |
| 27 | ** (3) A local checkout database named "_FOSSIL_" or ".fslckout" |
| 28 | ** and located at the root of the local copy of the source tree. |
| 29 | ** |
| 30 | */ |
| 31 | #include "config.h" |
| 32 | #if ! defined(_WIN32) |
| 33 | # include <pwd.h> |
| 34 | #endif |
| 35 | #include <sqlite3.h> |
| 36 | #include <sys/types.h> |
| 37 | #include <sys/stat.h> |
| @@ -870,31 +874,170 @@ | |
| 870 | db_tolocal_function, 0, 0); |
| 871 | sqlite3_create_function(db, "fromLocal", 0, SQLITE_UTF8, 0, |
| 872 | db_fromlocal_function, 0, 0); |
| 873 | } |
| 874 | |
| 875 | /* |
| 876 | ** If the database file zDbFile has a name that suggests that it is |
| 877 | ** encrypted, then prompt for the encryption key and return it in the |
| 878 | ** blob *pKey. Or, if the encryption key has previously been requested, |
| 879 | ** just return a copy of the previous result. |
| 880 | */ |
| 881 | static void db_encryption_key( |
| 882 | const char *zDbFile, /* Name of the database file */ |
| 883 | Blob *pKey /* Put the encryption key here */ |
| 884 | ){ |
| 885 | blob_init(pKey, 0, 0); |
| 886 | #if USE_SEE |
| 887 | if( sqlite3_strglob("*.efossil", zDbFile)==0 ){ |
| 888 | static char *zSavedKey = 0; |
| 889 | if( zSavedKey ){ |
| 890 | blob_set(pKey, zSavedKey); |
| 891 | }else{ |
| 892 | char *zPrompt = mprintf("\rencryption key for '%s': ", zDbFile); |
| 893 | prompt_for_password(zPrompt, pKey, 0); |
| 894 | fossil_free(zPrompt); |
| 895 | zSavedKey = fossil_strdup(blob_str(pKey)); |
| 896 | } |
| 897 | } |
| 898 | #endif |
| 899 | } |
| 900 | |
| @@ -915,14 +1058,16 @@ | |
| 915 | g.zVfsName |
| 916 | ); |
| 917 | if( rc!=SQLITE_OK ){ |
| 918 | db_err("[%s]: %s", zDbName, sqlite3_errmsg(db)); |
| 919 | } |
| 920 | db_encryption_key(zDbName, &key); |
| 921 | if( blob_size(&key)>0 ){ |
| 922 | char *zCmd = sqlite3_mprintf("PRAGMA key(%Q)", blob_str(&key)); |
| 923 | sqlite3_exec(db, zCmd, 0, 0, 0); |
| 924 | sqlite3_free(zCmd); |
| 925 | } |
| 926 | blob_reset(&key); |
| 927 | sqlite3_busy_timeout(db, 5000); |
| 928 | sqlite3_wal_autocheckpoint(db, 1); /* Set to checkpoint frequently */ |
| @@ -955,14 +1100,19 @@ | |
| 955 | /* |
| 956 | ** zDbName is the name of a database file. Attach zDbName using |
| 957 | ** the name zLabel. |
| 958 | */ |
| 959 | void db_attach(const char *zDbName, const char *zLabel){ |
| 960 | Blob key; |
| 961 | db_encryption_key(zDbName, &key); |
| 962 | db_multi_exec("ATTACH DATABASE %Q AS %Q KEY %Q", |
| 963 | zDbName, zLabel, blob_str(&key)); |
| 964 | blob_reset(&key); |
| 965 | } |
| 966 | |
| 967 | /* |
| 968 | ** Change the schema name of the "main" database to zLabel. |
| @@ -1192,10 +1342,11 @@ | |
| 1192 | } |
| 1193 | if( db_local_table_exists_but_lacks_column("undo_vfile", "islink") ){ |
| 1194 | db_multi_exec("ALTER TABLE undo_vfile ADD COLUMN islink BOOL DEFAULT 0"); |
| 1195 | } |
| 1196 | } |
| 1197 | return 1; |
| 1198 | } |
| 1199 | |
| 1200 | /* |
| 1201 | ** Locate the root directory of the local repository tree. The root |
| @@ -2270,10 +2421,45 @@ | |
| 2270 | return db_int(dflt, "SELECT value FROM vvar WHERE name=%Q", zName); |
| 2271 | } |
| 2272 | void db_lset_int(const char *zName, int value){ |
| 2273 | db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%d)", zName, value); |
| 2274 | } |
| 2275 | |
| 2276 | /* |
| 2277 | ** Record the name of a local repository in the global_config() database. |
| 2278 | ** The repository filename %s is recorded as an entry with a "name" field |
| 2279 | ** of the following form: |
| @@ -2570,11 +2756,11 @@ | |
| 2570 | { "https-login", 0, 0, 0, 0, "off" }, |
| 2571 | { "ignore-glob", 0, 40, 1, 0, "" }, |
| 2572 | { "keep-glob", 0, 40, 1, 0, "" }, |
| 2573 | { "localauth", 0, 0, 0, 0, "off" }, |
| 2574 | { "main-branch", 0, 40, 0, 0, "trunk" }, |
| 2575 | { "manifest", 0, 0, 1, 0, "off" }, |
| 2576 | { "max-loadavg", 0, 25, 0, 0, "0.0" }, |
| 2577 | { "max-upload", 0, 25, 0, 0, "250000" }, |
| 2578 | { "mtime-changes", 0, 0, 0, 0, "on" }, |
| 2579 | #if FOSSIL_ENABLE_LEGACY_MV_RM |
| 2580 | { "mv-rm-files", 0, 0, 0, 0, "off" }, |
| @@ -2775,13 +2961,16 @@ | |
| 2775 | ** false, all HTTP requests from localhost have |
| 2776 | ** unrestricted access to the repository. |
| 2777 | ** |
| 2778 | ** main-branch The primary branch for the project. Default: trunk |
| 2779 | ** |
| 2780 | ** manifest If enabled, automatically create files "manifest" and |
| 2781 | ** (versionable) "manifest.uuid" in every checkout. The SQLite and |
| 2782 | ** Fossil repositories both require this. Default: off. |
| 2783 | ** |
| 2784 | ** max-loadavg Some CPU-intensive web pages (ex: /zip, /tarball, /blame) |
| 2785 | ** are disallowed if the system load average goes above this |
| 2786 | ** value. "0.0" means no limit. This only works on unix. |
| 2787 | ** Only local settings of this value make a difference since |
| 2788 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -27,11 +27,15 @@ | |
| 27 | ** (3) A local checkout database named "_FOSSIL_" or ".fslckout" |
| 28 | ** and located at the root of the local copy of the source tree. |
| 29 | ** |
| 30 | */ |
| 31 | #include "config.h" |
| 32 | #if defined(_WIN32) |
| 33 | # if USE_SEE |
| 34 | # include <windows.h> |
| 35 | # endif |
| 36 | #else |
| 37 | # include <pwd.h> |
| 38 | #endif |
| 39 | #include <sqlite3.h> |
| 40 | #include <sys/types.h> |
| 41 | #include <sys/stat.h> |
| @@ -870,31 +874,170 @@ | |
| 874 | db_tolocal_function, 0, 0); |
| 875 | sqlite3_create_function(db, "fromLocal", 0, SQLITE_UTF8, 0, |
| 876 | db_fromlocal_function, 0, 0); |
| 877 | } |
| 878 | |
| 879 | #if USE_SEE |
| 880 | /* |
| 881 | ** This is a pointer to the saved database encryption key string. |
| 882 | */ |
| 883 | static char *zSavedKey = 0; |
| 884 | |
| 885 | /* |
| 886 | ** This is the size of the saved database encryption key, in bytes. |
| 887 | */ |
| 888 | size_t savedKeySize = 0; |
| 889 | |
| 890 | /* |
| 891 | ** This function returns the saved database encryption key -OR- zero if |
| 892 | ** no database encryption key is saved. |
| 893 | */ |
| 894 | char *db_get_saved_encryption_key(){ |
| 895 | return zSavedKey; |
| 896 | } |
| 897 | |
| 898 | /* |
| 899 | ** This function returns the size of the saved database encryption key |
| 900 | ** -OR- zero if no database encryption key is saved. |
| 901 | */ |
| 902 | size_t db_get_saved_encryption_key_size(){ |
| 903 | return savedKeySize; |
| 904 | } |
| 905 | |
| 906 | /* |
| 907 | ** This function arranges for the database encryption key to be securely |
| 908 | ** saved in non-pagable memory (on platforms where this is possible). |
| 909 | */ |
| 910 | static void db_save_encryption_key( |
| 911 | Blob *pKey |
| 912 | ){ |
| 913 | void *p = NULL; |
| 914 | size_t n = 0; |
| 915 | size_t pageSize = 0; |
| 916 | size_t blobSize = 0; |
| 917 | |
| 918 | blobSize = blob_size(pKey); |
| 919 | if( blobSize==0 ) return; |
| 920 | fossil_get_page_size(&pageSize); |
| 921 | assert( pageSize>0 ); |
| 922 | if( blobSize>pageSize ){ |
| 923 | fossil_fatal("key blob too large: %u versus %u", blobSize, pageSize); |
| 924 | } |
| 925 | p = fossil_secure_alloc_page(&n); |
| 926 | assert( p!=NULL ); |
| 927 | assert( n==pageSize ); |
| 928 | assert( n>=blobSize ); |
| 929 | memcpy(p, blob_str(pKey), blobSize); |
| 930 | zSavedKey = p; |
| 931 | savedKeySize = n; |
| 932 | } |
| 933 | |
| 934 | /* |
| 935 | ** This function arranges for the saved database encryption key to be |
| 936 | ** securely zeroed, unlocked (if necessary), and freed. |
| 937 | */ |
| 938 | void db_unsave_encryption_key(){ |
| 939 | fossil_secure_free_page(zSavedKey, savedKeySize); |
| 940 | zSavedKey = NULL; |
| 941 | savedKeySize = 0; |
| 942 | } |
| 943 | |
| 944 | /* |
| 945 | ** This function sets the saved database encryption key to the specified |
| 946 | ** string value, allocating or freeing the underlying memory if needed. |
| 947 | */ |
| 948 | void db_set_saved_encryption_key( |
| 949 | Blob *pKey |
| 950 | ){ |
| 951 | if( zSavedKey!=NULL ){ |
| 952 | size_t blobSize = blob_size(pKey); |
| 953 | if( blobSize==0 ){ |
| 954 | db_unsave_encryption_key(); |
| 955 | }else{ |
| 956 | if( blobSize>savedKeySize ){ |
| 957 | fossil_fatal("key blob too large: %u versus %u", |
| 958 | blobSize, savedKeySize); |
| 959 | } |
| 960 | fossil_secure_zero(zSavedKey, savedKeySize); |
| 961 | memcpy(zSavedKey, blob_str(pKey), blobSize); |
| 962 | } |
| 963 | }else{ |
| 964 | db_save_encryption_key(pKey); |
| 965 | } |
| 966 | } |
| 967 | |
| 968 | #if defined(_WIN32) |
| 969 | /* |
| 970 | ** This function sets the saved database encryption key to one that gets |
| 971 | ** read from the specified Fossil parent process. This is only necessary |
| 972 | ** (or functional) on Windows. |
| 973 | */ |
| 974 | void db_read_saved_encryption_key_from_process( |
| 975 | DWORD processId, /* Identifier for Fossil parent process. */ |
| 976 | LPVOID pAddress, /* Pointer to saved key buffer in the parent process. */ |
| 977 | SIZE_T nSize /* Size of saved key buffer in the parent process. */ |
| 978 | ){ |
| 979 | void *p = NULL; |
| 980 | size_t n = 0; |
| 981 | size_t pageSize = 0; |
| 982 | HANDLE hProcess = NULL; |
| 983 | |
| 984 | fossil_get_page_size(&pageSize); |
| 985 | assert( pageSize>0 ); |
| 986 | if( nSize>pageSize ){ |
| 987 | fossil_fatal("key too large: %u versus %u", nSize, pageSize); |
| 988 | } |
| 989 | p = fossil_secure_alloc_page(&n); |
| 990 | assert( p!=NULL ); |
| 991 | assert( n==pageSize ); |
| 992 | assert( n>=nSize ); |
| 993 | hProcess = OpenProcess(PROCESS_VM_READ, FALSE, processId); |
| 994 | if( hProcess!=NULL ){ |
| 995 | SIZE_T nRead = 0; |
| 996 | if( ReadProcessMemory(hProcess, pAddress, p, nSize, &nRead) ){ |
| 997 | CloseHandle(hProcess); |
| 998 | if( nRead==nSize ){ |
| 999 | db_unsave_encryption_key(); |
| 1000 | zSavedKey = p; |
| 1001 | savedKeySize = n; |
| 1002 | }else{ |
| 1003 | fossil_fatal("bad size read, %u out of %u bytes at %p from pid %lu", |
| 1004 | nRead, nSize, pAddress, processId); |
| 1005 | } |
| 1006 | }else{ |
| 1007 | CloseHandle(hProcess); |
| 1008 | fossil_fatal("failed read, %u bytes at %p from pid %lu: %lu", nSize, |
| 1009 | pAddress, processId, GetLastError()); |
| 1010 | } |
| 1011 | }else{ |
| 1012 | fossil_fatal("failed to open pid %lu: %lu", processId, GetLastError()); |
| 1013 | } |
| 1014 | } |
| 1015 | #endif /* defined(_WIN32) */ |
| 1016 | #endif /* USE_SEE */ |
| 1017 | |
| 1018 | /* |
| 1019 | ** If the database file zDbFile has a name that suggests that it is |
| 1020 | ** encrypted, then prompt for the database encryption key and return it |
| 1021 | ** in the blob *pKey. Or, if the encryption key has previously been |
| 1022 | ** requested, just return a copy of the previous result. The blob in |
| 1023 | ** *pKey must be initialized. |
| 1024 | */ |
| 1025 | static void db_maybe_obtain_encryption_key( |
| 1026 | const char *zDbFile, /* Name of the database file */ |
| 1027 | Blob *pKey /* Put the encryption key here */ |
| 1028 | ){ |
| 1029 | #if USE_SEE |
| 1030 | if( sqlite3_strglob("*.efossil", zDbFile)==0 ){ |
| 1031 | char *zKey = db_get_saved_encryption_key(); |
| 1032 | if( zKey ){ |
| 1033 | blob_set(pKey, zKey); |
| 1034 | }else{ |
| 1035 | char *zPrompt = mprintf("\rencryption key for '%s': ", zDbFile); |
| 1036 | prompt_for_password(zPrompt, pKey, 0); |
| 1037 | fossil_free(zPrompt); |
| 1038 | db_set_saved_encryption_key(pKey); |
| 1039 | } |
| 1040 | } |
| 1041 | #endif |
| 1042 | } |
| 1043 | |
| @@ -915,14 +1058,16 @@ | |
| 1058 | g.zVfsName |
| 1059 | ); |
| 1060 | if( rc!=SQLITE_OK ){ |
| 1061 | db_err("[%s]: %s", zDbName, sqlite3_errmsg(db)); |
| 1062 | } |
| 1063 | blob_init(&key, 0, 0); |
| 1064 | db_maybe_obtain_encryption_key(zDbName, &key); |
| 1065 | if( blob_size(&key)>0 ){ |
| 1066 | char *zCmd = sqlite3_mprintf("PRAGMA key(%Q)", blob_str(&key)); |
| 1067 | sqlite3_exec(db, zCmd, 0, 0, 0); |
| 1068 | fossil_secure_zero(zCmd, strlen(zCmd)); |
| 1069 | sqlite3_free(zCmd); |
| 1070 | } |
| 1071 | blob_reset(&key); |
| 1072 | sqlite3_busy_timeout(db, 5000); |
| 1073 | sqlite3_wal_autocheckpoint(db, 1); /* Set to checkpoint frequently */ |
| @@ -955,14 +1100,19 @@ | |
| 1100 | /* |
| 1101 | ** zDbName is the name of a database file. Attach zDbName using |
| 1102 | ** the name zLabel. |
| 1103 | */ |
| 1104 | void db_attach(const char *zDbName, const char *zLabel){ |
| 1105 | char *zCmd; |
| 1106 | Blob key; |
| 1107 | blob_init(&key, 0, 0); |
| 1108 | db_maybe_obtain_encryption_key(zDbName, &key); |
| 1109 | zCmd = sqlite3_mprintf("ATTACH DATABASE %Q AS %Q KEY %Q", |
| 1110 | zDbName, zLabel, blob_str(&key)); |
| 1111 | db_multi_exec(zCmd /*works-like:""*/); |
| 1112 | fossil_secure_zero(zCmd, strlen(zCmd)); |
| 1113 | sqlite3_free(zCmd); |
| 1114 | blob_reset(&key); |
| 1115 | } |
| 1116 | |
| 1117 | /* |
| 1118 | ** Change the schema name of the "main" database to zLabel. |
| @@ -1192,10 +1342,11 @@ | |
| 1342 | } |
| 1343 | if( db_local_table_exists_but_lacks_column("undo_vfile", "islink") ){ |
| 1344 | db_multi_exec("ALTER TABLE undo_vfile ADD COLUMN islink BOOL DEFAULT 0"); |
| 1345 | } |
| 1346 | } |
| 1347 | fossil_free(zVFileDef); |
| 1348 | return 1; |
| 1349 | } |
| 1350 | |
| 1351 | /* |
| 1352 | ** Locate the root directory of the local repository tree. The root |
| @@ -2270,10 +2421,45 @@ | |
| 2421 | return db_int(dflt, "SELECT value FROM vvar WHERE name=%Q", zName); |
| 2422 | } |
| 2423 | void db_lset_int(const char *zName, int value){ |
| 2424 | db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%d)", zName, value); |
| 2425 | } |
| 2426 | |
| 2427 | #if INTERFACE |
| 2428 | /* Manifest generation flags */ |
| 2429 | #define MFESTFLG_RAW 0x01 |
| 2430 | #define MFESTFLG_UUID 0x02 |
| 2431 | #define MFESTFLG_TAGS 0x04 |
| 2432 | #endif /* INTERFACE */ |
| 2433 | |
| 2434 | /* |
| 2435 | ** Get the manifest setting. For backwards compatibility first check if the |
| 2436 | ** value is a boolean. If it's not a boolean, treat each character as a flag |
| 2437 | ** to enable a manifest type. This system puts certain boundary conditions on |
| 2438 | ** which letters can be used to represent flags (any permutation of flags must |
| 2439 | ** not be able to fully form one of the boolean values). |
| 2440 | */ |
| 2441 | int db_get_manifest_setting(void){ |
| 2442 | int flg; |
| 2443 | char *zVal = db_get("manifest", 0); |
| 2444 | if( zVal==0 || is_false(zVal) ){ |
| 2445 | return 0; |
| 2446 | }else if( is_truth(zVal) ){ |
| 2447 | return MFESTFLG_RAW|MFESTFLG_UUID; |
| 2448 | } |
| 2449 | flg = 0; |
| 2450 | while( *zVal ){ |
| 2451 | switch( *zVal ){ |
| 2452 | case 'r': flg |= MFESTFLG_RAW; break; |
| 2453 | case 'u': flg |= MFESTFLG_UUID; break; |
| 2454 | case 't': flg |= MFESTFLG_TAGS; break; |
| 2455 | } |
| 2456 | zVal++; |
| 2457 | } |
| 2458 | return flg; |
| 2459 | } |
| 2460 | |
| 2461 | |
| 2462 | /* |
| 2463 | ** Record the name of a local repository in the global_config() database. |
| 2464 | ** The repository filename %s is recorded as an entry with a "name" field |
| 2465 | ** of the following form: |
| @@ -2570,11 +2756,11 @@ | |
| 2756 | { "https-login", 0, 0, 0, 0, "off" }, |
| 2757 | { "ignore-glob", 0, 40, 1, 0, "" }, |
| 2758 | { "keep-glob", 0, 40, 1, 0, "" }, |
| 2759 | { "localauth", 0, 0, 0, 0, "off" }, |
| 2760 | { "main-branch", 0, 40, 0, 0, "trunk" }, |
| 2761 | { "manifest", 0, 5, 1, 0, "off" }, |
| 2762 | { "max-loadavg", 0, 25, 0, 0, "0.0" }, |
| 2763 | { "max-upload", 0, 25, 0, 0, "250000" }, |
| 2764 | { "mtime-changes", 0, 0, 0, 0, "on" }, |
| 2765 | #if FOSSIL_ENABLE_LEGACY_MV_RM |
| 2766 | { "mv-rm-files", 0, 0, 0, 0, "off" }, |
| @@ -2775,13 +2961,16 @@ | |
| 2961 | ** false, all HTTP requests from localhost have |
| 2962 | ** unrestricted access to the repository. |
| 2963 | ** |
| 2964 | ** main-branch The primary branch for the project. Default: trunk |
| 2965 | ** |
| 2966 | ** manifest If set to a true boolean value, automatically create |
| 2967 | ** (versionable) files "manifest" and "manifest.uuid" in every checkout. |
| 2968 | ** Optionally use combinations of characters 'r' |
| 2969 | ** for "manifest", 'u' for "manifest.uuid" and 't' for |
| 2970 | ** "manifest.tags". The SQLite and Fossil repositories |
| 2971 | ** both require manifests. Default: off. |
| 2972 | ** |
| 2973 | ** max-loadavg Some CPU-intensive web pages (ex: /zip, /tarball, /blame) |
| 2974 | ** are disallowed if the system load average goes above this |
| 2975 | ** value. "0.0" means no limit. This only works on unix. |
| 2976 | ** Only local settings of this value make a difference since |
| 2977 |
+1
-2
| --- src/delta.c | ||
| +++ src/delta.c | ||
| @@ -377,13 +377,12 @@ | ||
| 377 | 377 | /* Compute the hash table used to locate matching sections in the |
| 378 | 378 | ** source file. |
| 379 | 379 | */ |
| 380 | 380 | nHash = lenSrc/NHASH; |
| 381 | 381 | collide = fossil_malloc( nHash*2*sizeof(int) ); |
| 382 | + memset(collide, -1, nHash*2*sizeof(int)); | |
| 382 | 383 | landmark = &collide[nHash]; |
| 383 | - memset(landmark, -1, nHash*sizeof(int)); | |
| 384 | - memset(collide, -1, nHash*sizeof(int)); | |
| 385 | 384 | for(i=0; i<lenSrc-NHASH; i+=NHASH){ |
| 386 | 385 | int hv = hash_once(&zSrc[i]) % nHash; |
| 387 | 386 | collide[i/NHASH] = landmark[hv]; |
| 388 | 387 | landmark[hv] = i/NHASH; |
| 389 | 388 | } |
| 390 | 389 |
| --- src/delta.c | |
| +++ src/delta.c | |
| @@ -377,13 +377,12 @@ | |
| 377 | /* Compute the hash table used to locate matching sections in the |
| 378 | ** source file. |
| 379 | */ |
| 380 | nHash = lenSrc/NHASH; |
| 381 | collide = fossil_malloc( nHash*2*sizeof(int) ); |
| 382 | landmark = &collide[nHash]; |
| 383 | memset(landmark, -1, nHash*sizeof(int)); |
| 384 | memset(collide, -1, nHash*sizeof(int)); |
| 385 | for(i=0; i<lenSrc-NHASH; i+=NHASH){ |
| 386 | int hv = hash_once(&zSrc[i]) % nHash; |
| 387 | collide[i/NHASH] = landmark[hv]; |
| 388 | landmark[hv] = i/NHASH; |
| 389 | } |
| 390 |
| --- src/delta.c | |
| +++ src/delta.c | |
| @@ -377,13 +377,12 @@ | |
| 377 | /* Compute the hash table used to locate matching sections in the |
| 378 | ** source file. |
| 379 | */ |
| 380 | nHash = lenSrc/NHASH; |
| 381 | collide = fossil_malloc( nHash*2*sizeof(int) ); |
| 382 | memset(collide, -1, nHash*2*sizeof(int)); |
| 383 | landmark = &collide[nHash]; |
| 384 | for(i=0; i<lenSrc-NHASH; i+=NHASH){ |
| 385 | int hv = hash_once(&zSrc[i]) % nHash; |
| 386 | collide[i/NHASH] = landmark[hv]; |
| 387 | landmark[hv] = i/NHASH; |
| 388 | } |
| 389 |
+11
-11
| --- src/deltacmd.c | ||
| +++ src/deltacmd.c | ||
| @@ -29,16 +29,16 @@ | ||
| 29 | 29 | const char *zOrig, *zTarg; |
| 30 | 30 | int lenOrig, lenTarg; |
| 31 | 31 | int len; |
| 32 | 32 | char *zRes; |
| 33 | 33 | blob_zero(pDelta); |
| 34 | - zOrig = blob_buffer(pOriginal); | |
| 34 | + zOrig = blob_materialize(pOriginal); | |
| 35 | 35 | lenOrig = blob_size(pOriginal); |
| 36 | - zTarg = blob_buffer(pTarget); | |
| 36 | + zTarg = blob_materialize(pTarget); | |
| 37 | 37 | lenTarg = blob_size(pTarget); |
| 38 | 38 | blob_resize(pDelta, lenTarg+16); |
| 39 | - zRes = blob_buffer(pDelta); | |
| 39 | + zRes = blob_materialize(pDelta); | |
| 40 | 40 | len = delta_create(zOrig, lenOrig, zTarg, lenTarg, zRes); |
| 41 | 41 | blob_resize(pDelta, len); |
| 42 | 42 | return 0; |
| 43 | 43 | } |
| 44 | 44 | |
| @@ -54,18 +54,18 @@ | ||
| 54 | 54 | Blob orig, target, delta; |
| 55 | 55 | if( g.argc!=5 ){ |
| 56 | 56 | usage("ORIGIN TARGET DELTA"); |
| 57 | 57 | } |
| 58 | 58 | if( blob_read_from_file(&orig, g.argv[2])<0 ){ |
| 59 | - fossil_fatal("cannot read %s\n", g.argv[2]); | |
| 59 | + fossil_fatal("cannot read %s", g.argv[2]); | |
| 60 | 60 | } |
| 61 | 61 | if( blob_read_from_file(&target, g.argv[3])<0 ){ |
| 62 | - fossil_fatal("cannot read %s\n", g.argv[3]); | |
| 62 | + fossil_fatal("cannot read %s", g.argv[3]); | |
| 63 | 63 | } |
| 64 | 64 | blob_delta_create(&orig, &target, &delta); |
| 65 | 65 | if( blob_write_to_file(&delta, g.argv[4])<blob_size(&delta) ){ |
| 66 | - fossil_fatal("cannot write %s\n", g.argv[4]); | |
| 66 | + fossil_fatal("cannot write %s", g.argv[4]); | |
| 67 | 67 | } |
| 68 | 68 | blob_reset(&orig); |
| 69 | 69 | blob_reset(&target); |
| 70 | 70 | blob_reset(&delta); |
| 71 | 71 | } |
| @@ -85,14 +85,14 @@ | ||
| 85 | 85 | int sz1, sz2, sz3; |
| 86 | 86 | if( g.argc!=4 ){ |
| 87 | 87 | usage("ORIGIN TARGET"); |
| 88 | 88 | } |
| 89 | 89 | if( blob_read_from_file(&orig, g.argv[2])<0 ){ |
| 90 | - fossil_fatal("cannot read %s\n", g.argv[2]); | |
| 90 | + fossil_fatal("cannot read %s", g.argv[2]); | |
| 91 | 91 | } |
| 92 | 92 | if( blob_read_from_file(&target, g.argv[3])<0 ){ |
| 93 | - fossil_fatal("cannot read %s\n", g.argv[3]); | |
| 93 | + fossil_fatal("cannot read %s", g.argv[3]); | |
| 94 | 94 | } |
| 95 | 95 | blob_delta_create(&orig, &target, &delta); |
| 96 | 96 | delta_analyze(blob_buffer(&delta), blob_size(&delta), &nCopy, &nInsert); |
| 97 | 97 | sz1 = blob_size(&orig); |
| 98 | 98 | sz2 = blob_size(&target); |
| @@ -153,18 +153,18 @@ | ||
| 153 | 153 | Blob orig, target, delta; |
| 154 | 154 | if( g.argc!=5 ){ |
| 155 | 155 | usage("ORIGIN DELTA TARGET"); |
| 156 | 156 | } |
| 157 | 157 | if( blob_read_from_file(&orig, g.argv[2])<0 ){ |
| 158 | - fossil_fatal("cannot read %s\n", g.argv[2]); | |
| 158 | + fossil_fatal("cannot read %s", g.argv[2]); | |
| 159 | 159 | } |
| 160 | 160 | if( blob_read_from_file(&delta, g.argv[3])<0 ){ |
| 161 | - fossil_fatal("cannot read %s\n", g.argv[3]); | |
| 161 | + fossil_fatal("cannot read %s", g.argv[3]); | |
| 162 | 162 | } |
| 163 | 163 | blob_delta_apply(&orig, &delta, &target); |
| 164 | 164 | if( blob_write_to_file(&target, g.argv[4])<blob_size(&target) ){ |
| 165 | - fossil_fatal("cannot write %s\n", g.argv[4]); | |
| 165 | + fossil_fatal("cannot write %s", g.argv[4]); | |
| 166 | 166 | } |
| 167 | 167 | blob_reset(&orig); |
| 168 | 168 | blob_reset(&target); |
| 169 | 169 | blob_reset(&delta); |
| 170 | 170 | } |
| 171 | 171 |
| --- src/deltacmd.c | |
| +++ src/deltacmd.c | |
| @@ -29,16 +29,16 @@ | |
| 29 | const char *zOrig, *zTarg; |
| 30 | int lenOrig, lenTarg; |
| 31 | int len; |
| 32 | char *zRes; |
| 33 | blob_zero(pDelta); |
| 34 | zOrig = blob_buffer(pOriginal); |
| 35 | lenOrig = blob_size(pOriginal); |
| 36 | zTarg = blob_buffer(pTarget); |
| 37 | lenTarg = blob_size(pTarget); |
| 38 | blob_resize(pDelta, lenTarg+16); |
| 39 | zRes = blob_buffer(pDelta); |
| 40 | len = delta_create(zOrig, lenOrig, zTarg, lenTarg, zRes); |
| 41 | blob_resize(pDelta, len); |
| 42 | return 0; |
| 43 | } |
| 44 | |
| @@ -54,18 +54,18 @@ | |
| 54 | Blob orig, target, delta; |
| 55 | if( g.argc!=5 ){ |
| 56 | usage("ORIGIN TARGET DELTA"); |
| 57 | } |
| 58 | if( blob_read_from_file(&orig, g.argv[2])<0 ){ |
| 59 | fossil_fatal("cannot read %s\n", g.argv[2]); |
| 60 | } |
| 61 | if( blob_read_from_file(&target, g.argv[3])<0 ){ |
| 62 | fossil_fatal("cannot read %s\n", g.argv[3]); |
| 63 | } |
| 64 | blob_delta_create(&orig, &target, &delta); |
| 65 | if( blob_write_to_file(&delta, g.argv[4])<blob_size(&delta) ){ |
| 66 | fossil_fatal("cannot write %s\n", g.argv[4]); |
| 67 | } |
| 68 | blob_reset(&orig); |
| 69 | blob_reset(&target); |
| 70 | blob_reset(&delta); |
| 71 | } |
| @@ -85,14 +85,14 @@ | |
| 85 | int sz1, sz2, sz3; |
| 86 | if( g.argc!=4 ){ |
| 87 | usage("ORIGIN TARGET"); |
| 88 | } |
| 89 | if( blob_read_from_file(&orig, g.argv[2])<0 ){ |
| 90 | fossil_fatal("cannot read %s\n", g.argv[2]); |
| 91 | } |
| 92 | if( blob_read_from_file(&target, g.argv[3])<0 ){ |
| 93 | fossil_fatal("cannot read %s\n", g.argv[3]); |
| 94 | } |
| 95 | blob_delta_create(&orig, &target, &delta); |
| 96 | delta_analyze(blob_buffer(&delta), blob_size(&delta), &nCopy, &nInsert); |
| 97 | sz1 = blob_size(&orig); |
| 98 | sz2 = blob_size(&target); |
| @@ -153,18 +153,18 @@ | |
| 153 | Blob orig, target, delta; |
| 154 | if( g.argc!=5 ){ |
| 155 | usage("ORIGIN DELTA TARGET"); |
| 156 | } |
| 157 | if( blob_read_from_file(&orig, g.argv[2])<0 ){ |
| 158 | fossil_fatal("cannot read %s\n", g.argv[2]); |
| 159 | } |
| 160 | if( blob_read_from_file(&delta, g.argv[3])<0 ){ |
| 161 | fossil_fatal("cannot read %s\n", g.argv[3]); |
| 162 | } |
| 163 | blob_delta_apply(&orig, &delta, &target); |
| 164 | if( blob_write_to_file(&target, g.argv[4])<blob_size(&target) ){ |
| 165 | fossil_fatal("cannot write %s\n", g.argv[4]); |
| 166 | } |
| 167 | blob_reset(&orig); |
| 168 | blob_reset(&target); |
| 169 | blob_reset(&delta); |
| 170 | } |
| 171 |
| --- src/deltacmd.c | |
| +++ src/deltacmd.c | |
| @@ -29,16 +29,16 @@ | |
| 29 | const char *zOrig, *zTarg; |
| 30 | int lenOrig, lenTarg; |
| 31 | int len; |
| 32 | char *zRes; |
| 33 | blob_zero(pDelta); |
| 34 | zOrig = blob_materialize(pOriginal); |
| 35 | lenOrig = blob_size(pOriginal); |
| 36 | zTarg = blob_materialize(pTarget); |
| 37 | lenTarg = blob_size(pTarget); |
| 38 | blob_resize(pDelta, lenTarg+16); |
| 39 | zRes = blob_materialize(pDelta); |
| 40 | len = delta_create(zOrig, lenOrig, zTarg, lenTarg, zRes); |
| 41 | blob_resize(pDelta, len); |
| 42 | return 0; |
| 43 | } |
| 44 | |
| @@ -54,18 +54,18 @@ | |
| 54 | Blob orig, target, delta; |
| 55 | if( g.argc!=5 ){ |
| 56 | usage("ORIGIN TARGET DELTA"); |
| 57 | } |
| 58 | if( blob_read_from_file(&orig, g.argv[2])<0 ){ |
| 59 | fossil_fatal("cannot read %s", g.argv[2]); |
| 60 | } |
| 61 | if( blob_read_from_file(&target, g.argv[3])<0 ){ |
| 62 | fossil_fatal("cannot read %s", g.argv[3]); |
| 63 | } |
| 64 | blob_delta_create(&orig, &target, &delta); |
| 65 | if( blob_write_to_file(&delta, g.argv[4])<blob_size(&delta) ){ |
| 66 | fossil_fatal("cannot write %s", g.argv[4]); |
| 67 | } |
| 68 | blob_reset(&orig); |
| 69 | blob_reset(&target); |
| 70 | blob_reset(&delta); |
| 71 | } |
| @@ -85,14 +85,14 @@ | |
| 85 | int sz1, sz2, sz3; |
| 86 | if( g.argc!=4 ){ |
| 87 | usage("ORIGIN TARGET"); |
| 88 | } |
| 89 | if( blob_read_from_file(&orig, g.argv[2])<0 ){ |
| 90 | fossil_fatal("cannot read %s", g.argv[2]); |
| 91 | } |
| 92 | if( blob_read_from_file(&target, g.argv[3])<0 ){ |
| 93 | fossil_fatal("cannot read %s", g.argv[3]); |
| 94 | } |
| 95 | blob_delta_create(&orig, &target, &delta); |
| 96 | delta_analyze(blob_buffer(&delta), blob_size(&delta), &nCopy, &nInsert); |
| 97 | sz1 = blob_size(&orig); |
| 98 | sz2 = blob_size(&target); |
| @@ -153,18 +153,18 @@ | |
| 153 | Blob orig, target, delta; |
| 154 | if( g.argc!=5 ){ |
| 155 | usage("ORIGIN DELTA TARGET"); |
| 156 | } |
| 157 | if( blob_read_from_file(&orig, g.argv[2])<0 ){ |
| 158 | fossil_fatal("cannot read %s", g.argv[2]); |
| 159 | } |
| 160 | if( blob_read_from_file(&delta, g.argv[3])<0 ){ |
| 161 | fossil_fatal("cannot read %s", g.argv[3]); |
| 162 | } |
| 163 | blob_delta_apply(&orig, &delta, &target); |
| 164 | if( blob_write_to_file(&target, g.argv[4])<blob_size(&target) ){ |
| 165 | fossil_fatal("cannot write %s", g.argv[4]); |
| 166 | } |
| 167 | blob_reset(&orig); |
| 168 | blob_reset(&target); |
| 169 | blob_reset(&delta); |
| 170 | } |
| 171 |
+57
-37
| --- src/diff.c | ||
| +++ src/diff.c | ||
| @@ -115,10 +115,34 @@ | ||
| 115 | 115 | int nFrom; /* Number of lines in aFrom[] */ |
| 116 | 116 | DLine *aTo; /* File on right side of the diff */ |
| 117 | 117 | int nTo; /* Number of lines in aTo[] */ |
| 118 | 118 | int (*same_fn)(const DLine*,const DLine*); /* comparison function */ |
| 119 | 119 | }; |
| 120 | + | |
| 121 | +/* | |
| 122 | +** Count the number of lines in the input string. Include the last line | |
| 123 | +** in the count even if it lacks the \n terminator. If an empty string | |
| 124 | +** is specified, the number of lines is zero. For the purposes of this | |
| 125 | +** function, a string is considered empty if it contains no characters | |
| 126 | +** -OR- it contains only NUL characters. | |
| 127 | +*/ | |
| 128 | +static int count_lines( | |
| 129 | + const char *z, | |
| 130 | + int n, | |
| 131 | + int *pnLine | |
| 132 | +){ | |
| 133 | + int nLine; | |
| 134 | + const char *zNL, *z2; | |
| 135 | + for(nLine=0, z2=z; (zNL = strchr(z2,'\n'))!=0; z2=zNL+1, nLine++){} | |
| 136 | + if( z2[0]!='\0' ){ | |
| 137 | + nLine++; | |
| 138 | + do{ z2++; }while( z2[0]!='\0' ); | |
| 139 | + } | |
| 140 | + if( n!=(int)(z2-z) ) return 0; | |
| 141 | + if( pnLine ) *pnLine = nLine; | |
| 142 | + return 1; | |
| 143 | +} | |
| 120 | 144 | |
| 121 | 145 | /* |
| 122 | 146 | ** Return an array of DLine objects containing a pointer to the |
| 123 | 147 | ** start of each line and a hash of that line. The lower |
| 124 | 148 | ** bits of the hash store the length of each line. |
| @@ -137,45 +161,36 @@ | ||
| 137 | 161 | const char *z, |
| 138 | 162 | int n, |
| 139 | 163 | int *pnLine, |
| 140 | 164 | u64 diffFlags |
| 141 | 165 | ){ |
| 142 | - int nLine, i, j, k, s, x; | |
| 166 | + int nLine, i, k, nn, s, x; | |
| 143 | 167 | unsigned int h, h2; |
| 144 | 168 | DLine *a; |
| 145 | - | |
| 146 | - /* Count the number of lines. Allocate space to hold | |
| 147 | - ** the returned array. | |
| 148 | - */ | |
| 149 | - for(i=j=0, nLine=1; i<n; i++, j++){ | |
| 150 | - int c = z[i]; | |
| 151 | - if( c==0 ){ | |
| 152 | - return 0; | |
| 153 | - } | |
| 154 | - if( c=='\n' && z[i+1]!=0 ){ | |
| 155 | - nLine++; | |
| 156 | - if( j>LENGTH_MASK ){ | |
| 157 | - return 0; | |
| 158 | - } | |
| 159 | - j = 0; | |
| 160 | - } | |
| 161 | - } | |
| 162 | - if( j>LENGTH_MASK ){ | |
| 163 | - return 0; | |
| 164 | - } | |
| 165 | - a = fossil_malloc( nLine*sizeof(a[0]) ); | |
| 166 | - memset(a, 0, nLine*sizeof(a[0]) ); | |
| 167 | - if( n==0 ){ | |
| 169 | + const char *zNL; | |
| 170 | + | |
| 171 | + if( count_lines(z, n, &nLine)==0 ){ | |
| 172 | + return 0; | |
| 173 | + } | |
| 174 | + assert( nLine>0 || z[0]=='\0' ); | |
| 175 | + a = fossil_malloc( sizeof(a[0])*nLine ); | |
| 176 | + memset(a, 0, sizeof(a[0])*nLine); | |
| 177 | + if( nLine==0 ){ | |
| 168 | 178 | *pnLine = 0; |
| 169 | 179 | return a; |
| 170 | 180 | } |
| 171 | - | |
| 172 | - /* Fill in the array */ | |
| 173 | - for(i=0; i<nLine; i++){ | |
| 174 | - for(j=0; z[j] && z[j]!='\n'; j++){} | |
| 181 | + i = 0; | |
| 182 | + do{ | |
| 183 | + zNL = strchr(z,'\n'); | |
| 184 | + if( zNL==0 ) zNL = z+n; | |
| 185 | + nn = (int)(zNL - z); | |
| 186 | + if( nn>LENGTH_MASK ){ | |
| 187 | + fossil_free(a); | |
| 188 | + return 0; | |
| 189 | + } | |
| 175 | 190 | a[i].z = z; |
| 176 | - k = j; | |
| 191 | + k = nn; | |
| 177 | 192 | if( diffFlags & DIFF_STRIP_EOLCR ){ |
| 178 | 193 | if( k>0 && z[k-1]=='\r' ){ k--; } |
| 179 | 194 | } |
| 180 | 195 | a[i].n = k; |
| 181 | 196 | s = 0; |
| @@ -184,29 +199,34 @@ | ||
| 184 | 199 | } |
| 185 | 200 | if( (diffFlags & DIFF_IGNORE_ALLWS)==DIFF_IGNORE_ALLWS ){ |
| 186 | 201 | int numws = 0; |
| 187 | 202 | while( s<k && fossil_isspace(z[s]) ){ s++; } |
| 188 | 203 | for(h=0, x=s; x<k; x++){ |
| 189 | - if( fossil_isspace(z[x]) ){ | |
| 204 | + char c = z[x]; | |
| 205 | + if( fossil_isspace(c) ){ | |
| 190 | 206 | ++numws; |
| 191 | 207 | }else{ |
| 192 | - h = h ^ (h<<2) ^ z[x]; | |
| 208 | + h += c; | |
| 209 | + h *= 0x9e3779b1; | |
| 193 | 210 | } |
| 194 | 211 | } |
| 195 | 212 | k -= numws; |
| 196 | 213 | }else{ |
| 197 | 214 | for(h=0, x=s; x<k; x++){ |
| 198 | - h = h ^ (h<<2) ^ z[x]; | |
| 215 | + h += z[x]; | |
| 216 | + h *= 0x9e3779b1; | |
| 199 | 217 | } |
| 200 | 218 | } |
| 201 | 219 | a[i].indent = s; |
| 202 | 220 | a[i].h = h = (h<<LENGTH_MASK_SZ) | (k-s); |
| 203 | 221 | h2 = h % nLine; |
| 204 | 222 | a[i].iNext = a[h2].iHash; |
| 205 | 223 | a[h2].iHash = i+1; |
| 206 | - z += j+1; | |
| 207 | - } | |
| 224 | + z += nn+1; n -= nn+1; | |
| 225 | + i++; | |
| 226 | + }while( zNL[0]!='\0' && zNL[1]!='\0' ); | |
| 227 | + assert( i==nLine ); | |
| 208 | 228 | |
| 209 | 229 | /* Return results */ |
| 210 | 230 | *pnLine = nLine; |
| 211 | 231 | return a; |
| 212 | 232 | } |
| @@ -963,23 +983,23 @@ | ||
| 963 | 983 | if( nA>250 ) nA = 250; |
| 964 | 984 | if( nB>250 ) nB = 250; |
| 965 | 985 | avg = (nA+nB)/2; |
| 966 | 986 | if( avg==0 ) return 0; |
| 967 | 987 | if( nA==nB && memcmp(zA, zB, nA)==0 ) return 0; |
| 968 | - memset(aFirst, 0, sizeof(aFirst)); | |
| 988 | + memset(aFirst, 0xff, sizeof(aFirst)); | |
| 969 | 989 | zA--; zB--; /* Make both zA[] and zB[] 1-indexed */ |
| 970 | 990 | for(i=nB; i>0; i--){ |
| 971 | 991 | c = (unsigned char)zB[i]; |
| 972 | 992 | aNext[i] = aFirst[c]; |
| 973 | 993 | aFirst[c] = i; |
| 974 | 994 | } |
| 975 | 995 | best = 0; |
| 976 | 996 | for(i=1; i<=nA-best; i++){ |
| 977 | 997 | c = (unsigned char)zA[i]; |
| 978 | - for(j=aFirst[c]; j>0 && j<nB-best; j = aNext[j]){ | |
| 998 | + for(j=aFirst[c]; j<nB-best && memcmp(&zA[i],&zB[j],best)==0; j = aNext[j]){ | |
| 979 | 999 | int limit = minInt(nA-i, nB-j); |
| 980 | - for(k=1; k<=limit && zA[k+i]==zB[k+j]; k++){} | |
| 1000 | + for(k=best; k<=limit && zA[k+i]==zB[k+j]; k++){} | |
| 981 | 1001 | if( k>best ) best = k; |
| 982 | 1002 | } |
| 983 | 1003 | } |
| 984 | 1004 | score = (best>avg) ? 0 : (avg - best)*100/avg; |
| 985 | 1005 | |
| 986 | 1006 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -115,10 +115,34 @@ | |
| 115 | int nFrom; /* Number of lines in aFrom[] */ |
| 116 | DLine *aTo; /* File on right side of the diff */ |
| 117 | int nTo; /* Number of lines in aTo[] */ |
| 118 | int (*same_fn)(const DLine*,const DLine*); /* comparison function */ |
| 119 | }; |
| 120 | |
| 121 | /* |
| 122 | ** Return an array of DLine objects containing a pointer to the |
| 123 | ** start of each line and a hash of that line. The lower |
| 124 | ** bits of the hash store the length of each line. |
| @@ -137,45 +161,36 @@ | |
| 137 | const char *z, |
| 138 | int n, |
| 139 | int *pnLine, |
| 140 | u64 diffFlags |
| 141 | ){ |
| 142 | int nLine, i, j, k, s, x; |
| 143 | unsigned int h, h2; |
| 144 | DLine *a; |
| 145 | |
| 146 | /* Count the number of lines. Allocate space to hold |
| 147 | ** the returned array. |
| 148 | */ |
| 149 | for(i=j=0, nLine=1; i<n; i++, j++){ |
| 150 | int c = z[i]; |
| 151 | if( c==0 ){ |
| 152 | return 0; |
| 153 | } |
| 154 | if( c=='\n' && z[i+1]!=0 ){ |
| 155 | nLine++; |
| 156 | if( j>LENGTH_MASK ){ |
| 157 | return 0; |
| 158 | } |
| 159 | j = 0; |
| 160 | } |
| 161 | } |
| 162 | if( j>LENGTH_MASK ){ |
| 163 | return 0; |
| 164 | } |
| 165 | a = fossil_malloc( nLine*sizeof(a[0]) ); |
| 166 | memset(a, 0, nLine*sizeof(a[0]) ); |
| 167 | if( n==0 ){ |
| 168 | *pnLine = 0; |
| 169 | return a; |
| 170 | } |
| 171 | |
| 172 | /* Fill in the array */ |
| 173 | for(i=0; i<nLine; i++){ |
| 174 | for(j=0; z[j] && z[j]!='\n'; j++){} |
| 175 | a[i].z = z; |
| 176 | k = j; |
| 177 | if( diffFlags & DIFF_STRIP_EOLCR ){ |
| 178 | if( k>0 && z[k-1]=='\r' ){ k--; } |
| 179 | } |
| 180 | a[i].n = k; |
| 181 | s = 0; |
| @@ -184,29 +199,34 @@ | |
| 184 | } |
| 185 | if( (diffFlags & DIFF_IGNORE_ALLWS)==DIFF_IGNORE_ALLWS ){ |
| 186 | int numws = 0; |
| 187 | while( s<k && fossil_isspace(z[s]) ){ s++; } |
| 188 | for(h=0, x=s; x<k; x++){ |
| 189 | if( fossil_isspace(z[x]) ){ |
| 190 | ++numws; |
| 191 | }else{ |
| 192 | h = h ^ (h<<2) ^ z[x]; |
| 193 | } |
| 194 | } |
| 195 | k -= numws; |
| 196 | }else{ |
| 197 | for(h=0, x=s; x<k; x++){ |
| 198 | h = h ^ (h<<2) ^ z[x]; |
| 199 | } |
| 200 | } |
| 201 | a[i].indent = s; |
| 202 | a[i].h = h = (h<<LENGTH_MASK_SZ) | (k-s); |
| 203 | h2 = h % nLine; |
| 204 | a[i].iNext = a[h2].iHash; |
| 205 | a[h2].iHash = i+1; |
| 206 | z += j+1; |
| 207 | } |
| 208 | |
| 209 | /* Return results */ |
| 210 | *pnLine = nLine; |
| 211 | return a; |
| 212 | } |
| @@ -963,23 +983,23 @@ | |
| 963 | if( nA>250 ) nA = 250; |
| 964 | if( nB>250 ) nB = 250; |
| 965 | avg = (nA+nB)/2; |
| 966 | if( avg==0 ) return 0; |
| 967 | if( nA==nB && memcmp(zA, zB, nA)==0 ) return 0; |
| 968 | memset(aFirst, 0, sizeof(aFirst)); |
| 969 | zA--; zB--; /* Make both zA[] and zB[] 1-indexed */ |
| 970 | for(i=nB; i>0; i--){ |
| 971 | c = (unsigned char)zB[i]; |
| 972 | aNext[i] = aFirst[c]; |
| 973 | aFirst[c] = i; |
| 974 | } |
| 975 | best = 0; |
| 976 | for(i=1; i<=nA-best; i++){ |
| 977 | c = (unsigned char)zA[i]; |
| 978 | for(j=aFirst[c]; j>0 && j<nB-best; j = aNext[j]){ |
| 979 | int limit = minInt(nA-i, nB-j); |
| 980 | for(k=1; k<=limit && zA[k+i]==zB[k+j]; k++){} |
| 981 | if( k>best ) best = k; |
| 982 | } |
| 983 | } |
| 984 | score = (best>avg) ? 0 : (avg - best)*100/avg; |
| 985 | |
| 986 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -115,10 +115,34 @@ | |
| 115 | int nFrom; /* Number of lines in aFrom[] */ |
| 116 | DLine *aTo; /* File on right side of the diff */ |
| 117 | int nTo; /* Number of lines in aTo[] */ |
| 118 | int (*same_fn)(const DLine*,const DLine*); /* comparison function */ |
| 119 | }; |
| 120 | |
| 121 | /* |
| 122 | ** Count the number of lines in the input string. Include the last line |
| 123 | ** in the count even if it lacks the \n terminator. If an empty string |
| 124 | ** is specified, the number of lines is zero. For the purposes of this |
| 125 | ** function, a string is considered empty if it contains no characters |
| 126 | ** -OR- it contains only NUL characters. |
| 127 | */ |
| 128 | static int count_lines( |
| 129 | const char *z, |
| 130 | int n, |
| 131 | int *pnLine |
| 132 | ){ |
| 133 | int nLine; |
| 134 | const char *zNL, *z2; |
| 135 | for(nLine=0, z2=z; (zNL = strchr(z2,'\n'))!=0; z2=zNL+1, nLine++){} |
| 136 | if( z2[0]!='\0' ){ |
| 137 | nLine++; |
| 138 | do{ z2++; }while( z2[0]!='\0' ); |
| 139 | } |
| 140 | if( n!=(int)(z2-z) ) return 0; |
| 141 | if( pnLine ) *pnLine = nLine; |
| 142 | return 1; |
| 143 | } |
| 144 | |
| 145 | /* |
| 146 | ** Return an array of DLine objects containing a pointer to the |
| 147 | ** start of each line and a hash of that line. The lower |
| 148 | ** bits of the hash store the length of each line. |
| @@ -137,45 +161,36 @@ | |
| 161 | const char *z, |
| 162 | int n, |
| 163 | int *pnLine, |
| 164 | u64 diffFlags |
| 165 | ){ |
| 166 | int nLine, i, k, nn, s, x; |
| 167 | unsigned int h, h2; |
| 168 | DLine *a; |
| 169 | const char *zNL; |
| 170 | |
| 171 | if( count_lines(z, n, &nLine)==0 ){ |
| 172 | return 0; |
| 173 | } |
| 174 | assert( nLine>0 || z[0]=='\0' ); |
| 175 | a = fossil_malloc( sizeof(a[0])*nLine ); |
| 176 | memset(a, 0, sizeof(a[0])*nLine); |
| 177 | if( nLine==0 ){ |
| 178 | *pnLine = 0; |
| 179 | return a; |
| 180 | } |
| 181 | i = 0; |
| 182 | do{ |
| 183 | zNL = strchr(z,'\n'); |
| 184 | if( zNL==0 ) zNL = z+n; |
| 185 | nn = (int)(zNL - z); |
| 186 | if( nn>LENGTH_MASK ){ |
| 187 | fossil_free(a); |
| 188 | return 0; |
| 189 | } |
| 190 | a[i].z = z; |
| 191 | k = nn; |
| 192 | if( diffFlags & DIFF_STRIP_EOLCR ){ |
| 193 | if( k>0 && z[k-1]=='\r' ){ k--; } |
| 194 | } |
| 195 | a[i].n = k; |
| 196 | s = 0; |
| @@ -184,29 +199,34 @@ | |
| 199 | } |
| 200 | if( (diffFlags & DIFF_IGNORE_ALLWS)==DIFF_IGNORE_ALLWS ){ |
| 201 | int numws = 0; |
| 202 | while( s<k && fossil_isspace(z[s]) ){ s++; } |
| 203 | for(h=0, x=s; x<k; x++){ |
| 204 | char c = z[x]; |
| 205 | if( fossil_isspace(c) ){ |
| 206 | ++numws; |
| 207 | }else{ |
| 208 | h += c; |
| 209 | h *= 0x9e3779b1; |
| 210 | } |
| 211 | } |
| 212 | k -= numws; |
| 213 | }else{ |
| 214 | for(h=0, x=s; x<k; x++){ |
| 215 | h += z[x]; |
| 216 | h *= 0x9e3779b1; |
| 217 | } |
| 218 | } |
| 219 | a[i].indent = s; |
| 220 | a[i].h = h = (h<<LENGTH_MASK_SZ) | (k-s); |
| 221 | h2 = h % nLine; |
| 222 | a[i].iNext = a[h2].iHash; |
| 223 | a[h2].iHash = i+1; |
| 224 | z += nn+1; n -= nn+1; |
| 225 | i++; |
| 226 | }while( zNL[0]!='\0' && zNL[1]!='\0' ); |
| 227 | assert( i==nLine ); |
| 228 | |
| 229 | /* Return results */ |
| 230 | *pnLine = nLine; |
| 231 | return a; |
| 232 | } |
| @@ -963,23 +983,23 @@ | |
| 983 | if( nA>250 ) nA = 250; |
| 984 | if( nB>250 ) nB = 250; |
| 985 | avg = (nA+nB)/2; |
| 986 | if( avg==0 ) return 0; |
| 987 | if( nA==nB && memcmp(zA, zB, nA)==0 ) return 0; |
| 988 | memset(aFirst, 0xff, sizeof(aFirst)); |
| 989 | zA--; zB--; /* Make both zA[] and zB[] 1-indexed */ |
| 990 | for(i=nB; i>0; i--){ |
| 991 | c = (unsigned char)zB[i]; |
| 992 | aNext[i] = aFirst[c]; |
| 993 | aFirst[c] = i; |
| 994 | } |
| 995 | best = 0; |
| 996 | for(i=1; i<=nA-best; i++){ |
| 997 | c = (unsigned char)zA[i]; |
| 998 | for(j=aFirst[c]; j<nB-best && memcmp(&zA[i],&zB[j],best)==0; j = aNext[j]){ |
| 999 | int limit = minInt(nA-i, nB-j); |
| 1000 | for(k=best; k<=limit && zA[k+i]==zB[k+j]; k++){} |
| 1001 | if( k>best ) best = k; |
| 1002 | } |
| 1003 | } |
| 1004 | score = (best>avg) ? 0 : (avg - best)*100/avg; |
| 1005 | |
| 1006 |
+30
-6
| --- src/diffcmd.c | ||
| +++ src/diffcmd.c | ||
| @@ -412,10 +412,11 @@ | ||
| 412 | 412 | " ORDER BY pathname /*scan*/", |
| 413 | 413 | vid |
| 414 | 414 | ); |
| 415 | 415 | } |
| 416 | 416 | db_prepare(&q, "%s", blob_sql_text(&sql)); |
| 417 | + blob_reset(&sql); | |
| 417 | 418 | while( db_step(&q)==SQLITE_ROW ){ |
| 418 | 419 | const char *zPathname = db_column_text(&q,0); |
| 419 | 420 | int isDeleted = db_column_int(&q, 1); |
| 420 | 421 | int isChnged = db_column_int(&q,2); |
| 421 | 422 | int isNew = db_column_int(&q,3); |
| @@ -773,10 +774,13 @@ | ||
| 773 | 774 | ** |
| 774 | 775 | ** If the "--to VERSION" option appears, it specifies the check-in from |
| 775 | 776 | ** which the second version of the file or files is taken. If there is |
| 776 | 777 | ** no "--to" option then the (possibly edited) files in the current check-out |
| 777 | 778 | ** are used. |
| 779 | +** | |
| 780 | +** The "--checkin VERSION" option shows the changes made by | |
| 781 | +** check-in VERSION relative to its primary parent. | |
| 778 | 782 | ** |
| 779 | 783 | ** The "-i" command-line option forces the use of the internal diff logic |
| 780 | 784 | ** rather than any external diff program that might be configured using |
| 781 | 785 | ** the "setting" command. If no external diff program is configured, then |
| 782 | 786 | ** the "-i" option is a no-op. The "-i" option converts "gdiff" into "diff". |
| @@ -793,10 +797,12 @@ | ||
| 793 | 797 | ** |
| 794 | 798 | ** Options: |
| 795 | 799 | ** --binary PATTERN Treat files that match the glob PATTERN as binary |
| 796 | 800 | ** --branch BRANCH Show diff of all changes on BRANCH |
| 797 | 801 | ** --brief Show filenames only |
| 802 | +** --checkin VERSION Show diff of all changes in VERSION | |
| 803 | +** --command PROG External diff program - overrides "diff-command" | |
| 798 | 804 | ** --context|-c N Use N lines of context |
| 799 | 805 | ** --diff-binary BOOL Include binary files when using external commands |
| 800 | 806 | ** --exec-abs-paths Force absolute path names with external commands. |
| 801 | 807 | ** --exec-rel-paths Force relative path names with external commands. |
| 802 | 808 | ** --from|-r VERSION Select VERSION as source for the diff |
| @@ -816,10 +822,11 @@ | ||
| 816 | 822 | int isGDiff; /* True for gdiff. False for normal diff */ |
| 817 | 823 | int isInternDiff; /* True for internal diff */ |
| 818 | 824 | int verboseFlag; /* True if -v or --verbose flag is used */ |
| 819 | 825 | const char *zFrom; /* Source version number */ |
| 820 | 826 | const char *zTo; /* Target version number */ |
| 827 | + const char *zCheckin; /* Check-in version number */ | |
| 821 | 828 | const char *zBranch; /* Branch to diff */ |
| 822 | 829 | const char *zDiffCmd = 0; /* External diff command. NULL for internal diff */ |
| 823 | 830 | const char *zBinGlob = 0; /* Treat file names matching this as binary */ |
| 824 | 831 | int fIncludeBinary = 0; /* Include binary files for external diff */ |
| 825 | 832 | int againstUndo = 0; /* Diff against files in the undo buffer */ |
| @@ -832,37 +839,43 @@ | ||
| 832 | 839 | } |
| 833 | 840 | isGDiff = g.argv[1][0]=='g'; |
| 834 | 841 | isInternDiff = find_option("internal","i",0)!=0; |
| 835 | 842 | zFrom = find_option("from", "r", 1); |
| 836 | 843 | zTo = find_option("to", 0, 1); |
| 844 | + zCheckin = find_option("checkin", 0, 1); | |
| 837 | 845 | zBranch = find_option("branch", 0, 1); |
| 838 | 846 | againstUndo = find_option("undo",0,0)!=0; |
| 839 | 847 | diffFlags = diff_options(); |
| 840 | 848 | verboseFlag = find_option("verbose","v",0)!=0; |
| 841 | 849 | if( !verboseFlag ){ |
| 842 | 850 | verboseFlag = find_option("new-file","N",0)!=0; /* deprecated */ |
| 843 | 851 | } |
| 844 | 852 | if( verboseFlag ) diffFlags |= DIFF_VERBOSE; |
| 845 | - if( againstUndo && (zFrom!=0 || zTo!=0 || zBranch!=0) ){ | |
| 846 | - fossil_fatal("cannot use --undo together with --from or --to or --branch"); | |
| 853 | + if( againstUndo && ( zFrom!=0 || zTo!=0 || zCheckin!=0 || zBranch!=0) ){ | |
| 854 | + fossil_fatal("cannot use --undo together with --from, --to, --checkin," | |
| 855 | + " or --branch"); | |
| 847 | 856 | } |
| 848 | 857 | if( zBranch ){ |
| 849 | - if( zTo || zFrom ){ | |
| 850 | - fossil_fatal("cannot use --from or --to with --branch"); | |
| 858 | + if( zTo || zFrom || zCheckin ){ | |
| 859 | + fossil_fatal("cannot use --from, --to, or --checkin with --branch"); | |
| 851 | 860 | } |
| 852 | 861 | zTo = zBranch; |
| 853 | 862 | zFrom = mprintf("root:%s", zBranch); |
| 854 | 863 | } |
| 864 | + if( zCheckin!=0 && ( zFrom!=0 || zTo!=0 ) ){ | |
| 865 | + fossil_fatal("cannot use --checkin together with --from or --to"); | |
| 866 | + } | |
| 855 | 867 | if( zTo==0 || againstUndo ){ |
| 856 | 868 | db_must_be_within_tree(); |
| 857 | 869 | }else if( zFrom==0 ){ |
| 858 | 870 | fossil_fatal("must use --from if --to is present"); |
| 859 | 871 | }else{ |
| 860 | 872 | db_find_and_open_repository(0, 0); |
| 861 | 873 | } |
| 862 | 874 | if( !isInternDiff ){ |
| 863 | - zDiffCmd = diff_command_external(isGDiff); | |
| 875 | + zDiffCmd = find_option("command", 0, 1); | |
| 876 | + if( zDiffCmd==0 ) zDiffCmd = diff_command_external(isGDiff); | |
| 864 | 877 | } |
| 865 | 878 | zBinGlob = diff_get_binary_glob(); |
| 866 | 879 | fIncludeBinary = diff_include_binary_files(); |
| 867 | 880 | determine_exec_relative_option(1); |
| 868 | 881 | verify_all_options(); |
| @@ -881,10 +894,21 @@ | ||
| 881 | 894 | } |
| 882 | 895 | pFileDir[i-2].nName = blob_size(&fname); |
| 883 | 896 | pFileDir[i-2].nUsed = 0; |
| 884 | 897 | blob_reset(&fname); |
| 885 | 898 | } |
| 899 | + } | |
| 900 | + if ( zCheckin!=0 ){ | |
| 901 | + int ridTo = name_to_typed_rid(zCheckin, "ci"); | |
| 902 | + zTo = zCheckin; | |
| 903 | + zFrom = db_text(0, | |
| 904 | + "SELECT uuid FROM blob, plink" | |
| 905 | + " WHERE plink.cid=%d AND plink.isprim AND plink.pid=blob.rid", | |
| 906 | + ridTo); | |
| 907 | + if( zFrom==0 ){ | |
| 908 | + fossil_fatal("check-in %s has no parent", zTo); | |
| 909 | + } | |
| 886 | 910 | } |
| 887 | 911 | if( againstUndo ){ |
| 888 | 912 | if( db_lget_int("undo_available",0)==0 ){ |
| 889 | 913 | fossil_print("No undo or redo is available\n"); |
| 890 | 914 | return; |
| @@ -901,11 +925,11 @@ | ||
| 901 | 925 | if( pFileDir ){ |
| 902 | 926 | int i; |
| 903 | 927 | for(i=0; pFileDir[i].zName; i++){ |
| 904 | 928 | if( pFileDir[i].nUsed==0 |
| 905 | 929 | && strcmp(pFileDir[0].zName,".")!=0 |
| 906 | - && !file_isdir(g.argv[i+2]) | |
| 930 | + && !file_wd_isdir(g.argv[i+2]) | |
| 907 | 931 | ){ |
| 908 | 932 | fossil_fatal("not found: '%s'", g.argv[i+2]); |
| 909 | 933 | } |
| 910 | 934 | fossil_free(pFileDir[i].zName); |
| 911 | 935 | } |
| 912 | 936 |
| --- src/diffcmd.c | |
| +++ src/diffcmd.c | |
| @@ -412,10 +412,11 @@ | |
| 412 | " ORDER BY pathname /*scan*/", |
| 413 | vid |
| 414 | ); |
| 415 | } |
| 416 | db_prepare(&q, "%s", blob_sql_text(&sql)); |
| 417 | while( db_step(&q)==SQLITE_ROW ){ |
| 418 | const char *zPathname = db_column_text(&q,0); |
| 419 | int isDeleted = db_column_int(&q, 1); |
| 420 | int isChnged = db_column_int(&q,2); |
| 421 | int isNew = db_column_int(&q,3); |
| @@ -773,10 +774,13 @@ | |
| 773 | ** |
| 774 | ** If the "--to VERSION" option appears, it specifies the check-in from |
| 775 | ** which the second version of the file or files is taken. If there is |
| 776 | ** no "--to" option then the (possibly edited) files in the current check-out |
| 777 | ** are used. |
| 778 | ** |
| 779 | ** The "-i" command-line option forces the use of the internal diff logic |
| 780 | ** rather than any external diff program that might be configured using |
| 781 | ** the "setting" command. If no external diff program is configured, then |
| 782 | ** the "-i" option is a no-op. The "-i" option converts "gdiff" into "diff". |
| @@ -793,10 +797,12 @@ | |
| 793 | ** |
| 794 | ** Options: |
| 795 | ** --binary PATTERN Treat files that match the glob PATTERN as binary |
| 796 | ** --branch BRANCH Show diff of all changes on BRANCH |
| 797 | ** --brief Show filenames only |
| 798 | ** --context|-c N Use N lines of context |
| 799 | ** --diff-binary BOOL Include binary files when using external commands |
| 800 | ** --exec-abs-paths Force absolute path names with external commands. |
| 801 | ** --exec-rel-paths Force relative path names with external commands. |
| 802 | ** --from|-r VERSION Select VERSION as source for the diff |
| @@ -816,10 +822,11 @@ | |
| 816 | int isGDiff; /* True for gdiff. False for normal diff */ |
| 817 | int isInternDiff; /* True for internal diff */ |
| 818 | int verboseFlag; /* True if -v or --verbose flag is used */ |
| 819 | const char *zFrom; /* Source version number */ |
| 820 | const char *zTo; /* Target version number */ |
| 821 | const char *zBranch; /* Branch to diff */ |
| 822 | const char *zDiffCmd = 0; /* External diff command. NULL for internal diff */ |
| 823 | const char *zBinGlob = 0; /* Treat file names matching this as binary */ |
| 824 | int fIncludeBinary = 0; /* Include binary files for external diff */ |
| 825 | int againstUndo = 0; /* Diff against files in the undo buffer */ |
| @@ -832,37 +839,43 @@ | |
| 832 | } |
| 833 | isGDiff = g.argv[1][0]=='g'; |
| 834 | isInternDiff = find_option("internal","i",0)!=0; |
| 835 | zFrom = find_option("from", "r", 1); |
| 836 | zTo = find_option("to", 0, 1); |
| 837 | zBranch = find_option("branch", 0, 1); |
| 838 | againstUndo = find_option("undo",0,0)!=0; |
| 839 | diffFlags = diff_options(); |
| 840 | verboseFlag = find_option("verbose","v",0)!=0; |
| 841 | if( !verboseFlag ){ |
| 842 | verboseFlag = find_option("new-file","N",0)!=0; /* deprecated */ |
| 843 | } |
| 844 | if( verboseFlag ) diffFlags |= DIFF_VERBOSE; |
| 845 | if( againstUndo && (zFrom!=0 || zTo!=0 || zBranch!=0) ){ |
| 846 | fossil_fatal("cannot use --undo together with --from or --to or --branch"); |
| 847 | } |
| 848 | if( zBranch ){ |
| 849 | if( zTo || zFrom ){ |
| 850 | fossil_fatal("cannot use --from or --to with --branch"); |
| 851 | } |
| 852 | zTo = zBranch; |
| 853 | zFrom = mprintf("root:%s", zBranch); |
| 854 | } |
| 855 | if( zTo==0 || againstUndo ){ |
| 856 | db_must_be_within_tree(); |
| 857 | }else if( zFrom==0 ){ |
| 858 | fossil_fatal("must use --from if --to is present"); |
| 859 | }else{ |
| 860 | db_find_and_open_repository(0, 0); |
| 861 | } |
| 862 | if( !isInternDiff ){ |
| 863 | zDiffCmd = diff_command_external(isGDiff); |
| 864 | } |
| 865 | zBinGlob = diff_get_binary_glob(); |
| 866 | fIncludeBinary = diff_include_binary_files(); |
| 867 | determine_exec_relative_option(1); |
| 868 | verify_all_options(); |
| @@ -881,10 +894,21 @@ | |
| 881 | } |
| 882 | pFileDir[i-2].nName = blob_size(&fname); |
| 883 | pFileDir[i-2].nUsed = 0; |
| 884 | blob_reset(&fname); |
| 885 | } |
| 886 | } |
| 887 | if( againstUndo ){ |
| 888 | if( db_lget_int("undo_available",0)==0 ){ |
| 889 | fossil_print("No undo or redo is available\n"); |
| 890 | return; |
| @@ -901,11 +925,11 @@ | |
| 901 | if( pFileDir ){ |
| 902 | int i; |
| 903 | for(i=0; pFileDir[i].zName; i++){ |
| 904 | if( pFileDir[i].nUsed==0 |
| 905 | && strcmp(pFileDir[0].zName,".")!=0 |
| 906 | && !file_isdir(g.argv[i+2]) |
| 907 | ){ |
| 908 | fossil_fatal("not found: '%s'", g.argv[i+2]); |
| 909 | } |
| 910 | fossil_free(pFileDir[i].zName); |
| 911 | } |
| 912 |
| --- src/diffcmd.c | |
| +++ src/diffcmd.c | |
| @@ -412,10 +412,11 @@ | |
| 412 | " ORDER BY pathname /*scan*/", |
| 413 | vid |
| 414 | ); |
| 415 | } |
| 416 | db_prepare(&q, "%s", blob_sql_text(&sql)); |
| 417 | blob_reset(&sql); |
| 418 | while( db_step(&q)==SQLITE_ROW ){ |
| 419 | const char *zPathname = db_column_text(&q,0); |
| 420 | int isDeleted = db_column_int(&q, 1); |
| 421 | int isChnged = db_column_int(&q,2); |
| 422 | int isNew = db_column_int(&q,3); |
| @@ -773,10 +774,13 @@ | |
| 774 | ** |
| 775 | ** If the "--to VERSION" option appears, it specifies the check-in from |
| 776 | ** which the second version of the file or files is taken. If there is |
| 777 | ** no "--to" option then the (possibly edited) files in the current check-out |
| 778 | ** are used. |
| 779 | ** |
| 780 | ** The "--checkin VERSION" option shows the changes made by |
| 781 | ** check-in VERSION relative to its primary parent. |
| 782 | ** |
| 783 | ** The "-i" command-line option forces the use of the internal diff logic |
| 784 | ** rather than any external diff program that might be configured using |
| 785 | ** the "setting" command. If no external diff program is configured, then |
| 786 | ** the "-i" option is a no-op. The "-i" option converts "gdiff" into "diff". |
| @@ -793,10 +797,12 @@ | |
| 797 | ** |
| 798 | ** Options: |
| 799 | ** --binary PATTERN Treat files that match the glob PATTERN as binary |
| 800 | ** --branch BRANCH Show diff of all changes on BRANCH |
| 801 | ** --brief Show filenames only |
| 802 | ** --checkin VERSION Show diff of all changes in VERSION |
| 803 | ** --command PROG External diff program - overrides "diff-command" |
| 804 | ** --context|-c N Use N lines of context |
| 805 | ** --diff-binary BOOL Include binary files when using external commands |
| 806 | ** --exec-abs-paths Force absolute path names with external commands. |
| 807 | ** --exec-rel-paths Force relative path names with external commands. |
| 808 | ** --from|-r VERSION Select VERSION as source for the diff |
| @@ -816,10 +822,11 @@ | |
| 822 | int isGDiff; /* True for gdiff. False for normal diff */ |
| 823 | int isInternDiff; /* True for internal diff */ |
| 824 | int verboseFlag; /* True if -v or --verbose flag is used */ |
| 825 | const char *zFrom; /* Source version number */ |
| 826 | const char *zTo; /* Target version number */ |
| 827 | const char *zCheckin; /* Check-in version number */ |
| 828 | const char *zBranch; /* Branch to diff */ |
| 829 | const char *zDiffCmd = 0; /* External diff command. NULL for internal diff */ |
| 830 | const char *zBinGlob = 0; /* Treat file names matching this as binary */ |
| 831 | int fIncludeBinary = 0; /* Include binary files for external diff */ |
| 832 | int againstUndo = 0; /* Diff against files in the undo buffer */ |
| @@ -832,37 +839,43 @@ | |
| 839 | } |
| 840 | isGDiff = g.argv[1][0]=='g'; |
| 841 | isInternDiff = find_option("internal","i",0)!=0; |
| 842 | zFrom = find_option("from", "r", 1); |
| 843 | zTo = find_option("to", 0, 1); |
| 844 | zCheckin = find_option("checkin", 0, 1); |
| 845 | zBranch = find_option("branch", 0, 1); |
| 846 | againstUndo = find_option("undo",0,0)!=0; |
| 847 | diffFlags = diff_options(); |
| 848 | verboseFlag = find_option("verbose","v",0)!=0; |
| 849 | if( !verboseFlag ){ |
| 850 | verboseFlag = find_option("new-file","N",0)!=0; /* deprecated */ |
| 851 | } |
| 852 | if( verboseFlag ) diffFlags |= DIFF_VERBOSE; |
| 853 | if( againstUndo && ( zFrom!=0 || zTo!=0 || zCheckin!=0 || zBranch!=0) ){ |
| 854 | fossil_fatal("cannot use --undo together with --from, --to, --checkin," |
| 855 | " or --branch"); |
| 856 | } |
| 857 | if( zBranch ){ |
| 858 | if( zTo || zFrom || zCheckin ){ |
| 859 | fossil_fatal("cannot use --from, --to, or --checkin with --branch"); |
| 860 | } |
| 861 | zTo = zBranch; |
| 862 | zFrom = mprintf("root:%s", zBranch); |
| 863 | } |
| 864 | if( zCheckin!=0 && ( zFrom!=0 || zTo!=0 ) ){ |
| 865 | fossil_fatal("cannot use --checkin together with --from or --to"); |
| 866 | } |
| 867 | if( zTo==0 || againstUndo ){ |
| 868 | db_must_be_within_tree(); |
| 869 | }else if( zFrom==0 ){ |
| 870 | fossil_fatal("must use --from if --to is present"); |
| 871 | }else{ |
| 872 | db_find_and_open_repository(0, 0); |
| 873 | } |
| 874 | if( !isInternDiff ){ |
| 875 | zDiffCmd = find_option("command", 0, 1); |
| 876 | if( zDiffCmd==0 ) zDiffCmd = diff_command_external(isGDiff); |
| 877 | } |
| 878 | zBinGlob = diff_get_binary_glob(); |
| 879 | fIncludeBinary = diff_include_binary_files(); |
| 880 | determine_exec_relative_option(1); |
| 881 | verify_all_options(); |
| @@ -881,10 +894,21 @@ | |
| 894 | } |
| 895 | pFileDir[i-2].nName = blob_size(&fname); |
| 896 | pFileDir[i-2].nUsed = 0; |
| 897 | blob_reset(&fname); |
| 898 | } |
| 899 | } |
| 900 | if ( zCheckin!=0 ){ |
| 901 | int ridTo = name_to_typed_rid(zCheckin, "ci"); |
| 902 | zTo = zCheckin; |
| 903 | zFrom = db_text(0, |
| 904 | "SELECT uuid FROM blob, plink" |
| 905 | " WHERE plink.cid=%d AND plink.isprim AND plink.pid=blob.rid", |
| 906 | ridTo); |
| 907 | if( zFrom==0 ){ |
| 908 | fossil_fatal("check-in %s has no parent", zTo); |
| 909 | } |
| 910 | } |
| 911 | if( againstUndo ){ |
| 912 | if( db_lget_int("undo_available",0)==0 ){ |
| 913 | fossil_print("No undo or redo is available\n"); |
| 914 | return; |
| @@ -901,11 +925,11 @@ | |
| 925 | if( pFileDir ){ |
| 926 | int i; |
| 927 | for(i=0; pFileDir[i].zName; i++){ |
| 928 | if( pFileDir[i].nUsed==0 |
| 929 | && strcmp(pFileDir[0].zName,".")!=0 |
| 930 | && !file_wd_isdir(g.argv[i+2]) |
| 931 | ){ |
| 932 | fossil_fatal("not found: '%s'", g.argv[i+2]); |
| 933 | } |
| 934 | fossil_free(pFileDir[i].zName); |
| 935 | } |
| 936 |
+91
-48
| --- src/export.c | ||
| +++ src/export.c | ||
| @@ -132,23 +132,28 @@ | ||
| 132 | 132 | |
| 133 | 133 | /* |
| 134 | 134 | ** create_mark() |
| 135 | 135 | ** Create a new (mark,rid,uuid) entry for the given rid in the 'xmark' table, |
| 136 | 136 | ** and return that information as a struct mark_t in *mark. |
| 137 | +** *unused_mark is a value representing a mark that is free for use--that is, | |
| 138 | +** it does not appear in the marks file, and has not been used during this | |
| 139 | +** export run. Specifically, it is the supremum of the set of used marks | |
| 140 | +** plus one. | |
| 137 | 141 | ** This function returns -1 in the case where 'rid' does not exist, otherwise |
| 138 | 142 | ** it returns 0. |
| 139 | 143 | ** mark->name is dynamically allocated and is owned by the caller upon return. |
| 140 | 144 | */ |
| 141 | -int create_mark(int rid, struct mark_t *mark){ | |
| 145 | +int create_mark(int rid, struct mark_t *mark, unsigned int *unused_mark){ | |
| 142 | 146 | char sid[13]; |
| 143 | 147 | char *zUuid = rid_to_uuid(rid); |
| 144 | - if(!zUuid){ | |
| 148 | + if( !zUuid ){ | |
| 145 | 149 | fossil_trace("Undefined rid=%d\n", rid); |
| 146 | 150 | return -1; |
| 147 | 151 | } |
| 148 | 152 | mark->rid = rid; |
| 149 | - sqlite3_snprintf(sizeof(sid), sid, ":%d", COMMITMARK(rid)); | |
| 153 | + sqlite3_snprintf(sizeof(sid), sid, ":%d", *unused_mark); | |
| 154 | + *unused_mark += 1; | |
| 150 | 155 | mark->name = fossil_strdup(sid); |
| 151 | 156 | sqlite3_snprintf(sizeof(mark->uuid), mark->uuid, "%s", zUuid); |
| 152 | 157 | free(zUuid); |
| 153 | 158 | insert_commit_xref(mark->rid, mark->name, mark->uuid); |
| 154 | 159 | return 0; |
| @@ -156,19 +161,22 @@ | ||
| 156 | 161 | |
| 157 | 162 | /* |
| 158 | 163 | ** mark_name_from_rid() |
| 159 | 164 | ** Find the mark associated with the given rid. Mark names always start |
| 160 | 165 | ** with ':', and are pulled from the 'xmark' temporary table. |
| 161 | -** This function returns NULL if the rid does not exist in the 'xmark' table. | |
| 162 | -** Otherwise, it returns the name of the mark, which is dynamically allocated | |
| 163 | -** and is owned by the caller of this function. | |
| 166 | +** If the given rid doesn't have a mark associated with it yet, one is | |
| 167 | +** created with a value of *unused_mark. | |
| 168 | +** *unused_mark functions exactly as in create_mark(). | |
| 169 | +** This function returns NULL if the rid does not have an associated UUID, | |
| 170 | +** (i.e. is not valid). Otherwise, it returns the name of the mark, which is | |
| 171 | +** dynamically allocated and is owned by the caller of this function. | |
| 164 | 172 | */ |
| 165 | -char * mark_name_from_rid(int rid){ | |
| 173 | +char * mark_name_from_rid(int rid, unsigned int *unused_mark){ | |
| 166 | 174 | char *zMark = db_text(0, "SELECT tname FROM xmark WHERE trid=%d", rid); |
| 167 | - if(zMark==NULL){ | |
| 175 | + if( zMark==NULL ){ | |
| 168 | 176 | struct mark_t mark; |
| 169 | - if(create_mark(rid, &mark)==0){ | |
| 177 | + if( create_mark(rid, &mark, unused_mark)==0 ){ | |
| 170 | 178 | zMark = mark.name; |
| 171 | 179 | }else{ |
| 172 | 180 | return NULL; |
| 173 | 181 | } |
| 174 | 182 | } |
| @@ -185,43 +193,52 @@ | ||
| 185 | 193 | ** database. Otherwise, 0 is returned. |
| 186 | 194 | ** mark->name is dynamically allocated, and owned by the caller. |
| 187 | 195 | */ |
| 188 | 196 | int parse_mark(char *line, struct mark_t *mark){ |
| 189 | 197 | char *cur_tok; |
| 198 | + char type_; | |
| 190 | 199 | cur_tok = strtok(line, " \t"); |
| 191 | - if(!cur_tok||strlen(cur_tok)<2){ | |
| 200 | + if( !cur_tok || strlen(cur_tok)<2 ){ | |
| 192 | 201 | return -1; |
| 193 | 202 | } |
| 194 | 203 | mark->rid = atoi(&cur_tok[1]); |
| 195 | - if(cur_tok[0]!='c'){ | |
| 204 | + type_ = cur_tok[0]; | |
| 205 | + if( type_!='c' && type_!='b' ){ | |
| 196 | 206 | /* This is probably a blob mark */ |
| 197 | 207 | mark->name = NULL; |
| 198 | 208 | return 0; |
| 199 | 209 | } |
| 200 | 210 | |
| 201 | 211 | cur_tok = strtok(NULL, " \t"); |
| 202 | - if(!cur_tok){ | |
| 212 | + if( !cur_tok ){ | |
| 203 | 213 | /* This mark was generated by an older version of Fossil and doesn't |
| 204 | 214 | ** include the mark name and uuid. create_mark() will name the new mark |
| 205 | 215 | ** exactly as it was when exported to git, so that we should have a |
| 206 | 216 | ** valid mapping from git sha1<->mark name<->fossil sha1. */ |
| 207 | - return create_mark(mark->rid, mark); | |
| 217 | + unsigned int mid; | |
| 218 | + if( type_=='c' ){ | |
| 219 | + mid = COMMITMARK(mark->rid); | |
| 220 | + } | |
| 221 | + else{ | |
| 222 | + mid = BLOBMARK(mark->rid); | |
| 223 | + } | |
| 224 | + return create_mark(mark->rid, mark, &mid); | |
| 208 | 225 | }else{ |
| 209 | 226 | mark->name = fossil_strdup(cur_tok); |
| 210 | 227 | } |
| 211 | 228 | |
| 212 | 229 | cur_tok = strtok(NULL, "\n"); |
| 213 | - if(!cur_tok||strlen(cur_tok)!=40){ | |
| 230 | + if( !cur_tok || strlen(cur_tok)!=40 ){ | |
| 214 | 231 | free(mark->name); |
| 215 | 232 | fossil_trace("Invalid SHA-1 in marks file: %s\n", cur_tok); |
| 216 | 233 | return -1; |
| 217 | 234 | }else{ |
| 218 | 235 | sqlite3_snprintf(sizeof(mark->uuid), mark->uuid, "%s", cur_tok); |
| 219 | 236 | } |
| 220 | 237 | |
| 221 | 238 | /* make sure that rid corresponds to UUID */ |
| 222 | - if(fast_uuid_to_rid(mark->uuid)!=mark->rid){ | |
| 239 | + if( fast_uuid_to_rid(mark->uuid)!=mark->rid ){ | |
| 223 | 240 | free(mark->name); |
| 224 | 241 | fossil_trace("Non-existent SHA-1 in marks file: %s\n", mark->uuid); |
| 225 | 242 | return -1; |
| 226 | 243 | } |
| 227 | 244 | |
| @@ -233,40 +250,66 @@ | ||
| 233 | 250 | /* |
| 234 | 251 | ** import_marks() |
| 235 | 252 | ** Import the marks specified in file 'f' into the 'xmark' table. |
| 236 | 253 | ** If 'blobs' is non-null, insert all blob marks into it. |
| 237 | 254 | ** If 'vers' is non-null, insert all commit marks into it. |
| 255 | +** If 'unused_marks' is non-null, upon return of this function, all values | |
| 256 | +** x >= *unused_marks are free to use as marks, i.e. they do not clash with | |
| 257 | +** any marks appearing in the marks file. | |
| 238 | 258 | ** Each line in the file must be at most 100 characters in length. This |
| 239 | 259 | ** seems like a reasonable maximum for a 40-character uuid, and 1-13 |
| 240 | 260 | ** character rid. |
| 241 | 261 | ** The function returns -1 if any of the lines in file 'f' are malformed, |
| 242 | 262 | ** or the rid/uuid information doesn't match what is in the repository |
| 243 | 263 | ** database. Otherwise, 0 is returned. |
| 244 | 264 | */ |
| 245 | -int import_marks(FILE* f, Bag *blobs, Bag *vers){ | |
| 265 | +int import_marks(FILE* f, Bag *blobs, Bag *vers, unsigned int *unused_mark){ | |
| 246 | 266 | char line[101]; |
| 247 | 267 | while(fgets(line, sizeof(line), f)){ |
| 248 | 268 | struct mark_t mark; |
| 249 | - if(strlen(line)==100&&line[99]!='\n'){ | |
| 269 | + if( strlen(line)==100 && line[99]!='\n' ){ | |
| 250 | 270 | /* line too long */ |
| 251 | 271 | return -1; |
| 252 | 272 | } |
| 253 | 273 | if( parse_mark(line, &mark)<0 ){ |
| 254 | 274 | return -1; |
| 255 | 275 | }else if( line[0]=='b' ){ |
| 256 | - /* Don't import blob marks into 'xmark' table--git doesn't use them, | |
| 257 | - ** so they need to be left free for git to reuse. */ | |
| 258 | - if(blobs!=NULL){ | |
| 276 | + if( blobs!=NULL ){ | |
| 259 | 277 | bag_insert(blobs, mark.rid); |
| 260 | 278 | } |
| 261 | - }else if( vers!=NULL ){ | |
| 262 | - bag_insert(vers, mark.rid); | |
| 279 | + }else{ | |
| 280 | + if( vers!=NULL ){ | |
| 281 | + bag_insert(vers, mark.rid); | |
| 282 | + } | |
| 283 | + } | |
| 284 | + if( unused_mark!=NULL ){ | |
| 285 | + unsigned int mid = atoi(mark.name + 1); | |
| 286 | + if( mid>=*unused_mark ){ | |
| 287 | + *unused_mark = mid + 1; | |
| 288 | + } | |
| 263 | 289 | } |
| 264 | 290 | free(mark.name); |
| 265 | 291 | } |
| 266 | 292 | return 0; |
| 267 | 293 | } |
| 294 | + | |
| 295 | +void export_mark(FILE* f, int rid, char obj_type) | |
| 296 | +{ | |
| 297 | + unsigned int z = 0; | |
| 298 | + char *zUuid = rid_to_uuid(rid); | |
| 299 | + char *zMark; | |
| 300 | + if( zUuid==NULL ){ | |
| 301 | + fossil_trace("No uuid matching rid=%d when exporting marks\n", rid); | |
| 302 | + return; | |
| 303 | + } | |
| 304 | + /* Since rid is already in the 'xmark' table, the value of z won't be | |
| 305 | + ** used, but pass in a valid pointer just to be safe. */ | |
| 306 | + zMark = mark_name_from_rid(rid, &z); | |
| 307 | + fprintf(f, "%c%d %s %s\n", obj_type, rid, zMark, zUuid); | |
| 308 | + free(zMark); | |
| 309 | + free(zUuid); | |
| 310 | +} | |
| 268 | 311 | |
| 269 | 312 | /* |
| 270 | 313 | ** If 'blobs' is non-null, it must point to a Bag of blob rids to be |
| 271 | 314 | ** written to disk. Blob rids are written as 'b<rid>'. |
| 272 | 315 | ** If 'vers' is non-null, it must point to a Bag of commit rids to be |
| @@ -275,32 +318,24 @@ | ||
| 275 | 318 | ** This function does not fail, but may produce errors if a uuid cannot |
| 276 | 319 | ** be found for an rid in 'vers'. |
| 277 | 320 | */ |
| 278 | 321 | void export_marks(FILE* f, Bag *blobs, Bag *vers){ |
| 279 | 322 | int rid; |
| 323 | + | |
| 280 | 324 | if( blobs!=NULL ){ |
| 281 | 325 | rid = bag_first(blobs); |
| 282 | - if(rid!=0){ | |
| 326 | + if( rid!=0 ){ | |
| 283 | 327 | do{ |
| 284 | - fprintf(f, "b%d\n", rid); | |
| 285 | - }while((rid = bag_next(blobs, rid))!=0); | |
| 328 | + export_mark(f, rid, 'b'); | |
| 329 | + }while( (rid = bag_next(blobs, rid))!=0 ); | |
| 286 | 330 | } |
| 287 | 331 | } |
| 288 | 332 | if( vers!=NULL ){ |
| 289 | 333 | rid = bag_first(vers); |
| 290 | 334 | if( rid!=0 ){ |
| 291 | 335 | do{ |
| 292 | - char *zUuid = rid_to_uuid(rid); | |
| 293 | - char *zMark; | |
| 294 | - if(zUuid==NULL){ | |
| 295 | - fossil_trace("No uuid matching rid=%d when exporting marks\n", rid); | |
| 296 | - continue; | |
| 297 | - } | |
| 298 | - zMark = mark_name_from_rid(rid); | |
| 299 | - fprintf(f, "c%d %s %s\n", rid, zMark, zUuid); | |
| 300 | - free(zMark); | |
| 301 | - free(zUuid); | |
| 336 | + export_mark(f, rid, 'c'); | |
| 302 | 337 | }while( (rid = bag_next(vers, rid))!=0 ); |
| 303 | 338 | } |
| 304 | 339 | } |
| 305 | 340 | } |
| 306 | 341 | |
| @@ -336,10 +371,11 @@ | ||
| 336 | 371 | */ |
| 337 | 372 | void export_cmd(void){ |
| 338 | 373 | Stmt q, q2, q3; |
| 339 | 374 | int i; |
| 340 | 375 | Bag blobs, vers; |
| 376 | + unsigned int unused_mark = 1; | |
| 341 | 377 | const char *markfile_in; |
| 342 | 378 | const char *markfile_out; |
| 343 | 379 | |
| 344 | 380 | bag_init(&blobs); |
| 345 | 381 | bag_init(&vers); |
| @@ -362,25 +398,25 @@ | ||
| 362 | 398 | |
| 363 | 399 | f = fossil_fopen(markfile_in, "r"); |
| 364 | 400 | if( f==0 ){ |
| 365 | 401 | fossil_fatal("cannot open %s for reading", markfile_in); |
| 366 | 402 | } |
| 367 | - if(import_marks(f, &blobs, &vers)<0){ | |
| 368 | - fossil_fatal("error importing marks from file: %s\n", markfile_in); | |
| 403 | + if( import_marks(f, &blobs, &vers, &unused_mark)<0 ){ | |
| 404 | + fossil_fatal("error importing marks from file: %s", markfile_in); | |
| 369 | 405 | } |
| 370 | 406 | db_prepare(&qb, "INSERT OR IGNORE INTO oldblob VALUES (:rid)"); |
| 371 | 407 | db_prepare(&qc, "INSERT OR IGNORE INTO oldcommit VALUES (:rid)"); |
| 372 | 408 | rid = bag_first(&blobs); |
| 373 | - if(rid!=0){ | |
| 409 | + if( rid!=0 ){ | |
| 374 | 410 | do{ |
| 375 | 411 | db_bind_int(&qb, ":rid", rid); |
| 376 | 412 | db_step(&qb); |
| 377 | 413 | db_reset(&qb); |
| 378 | 414 | }while((rid = bag_next(&blobs, rid))!=0); |
| 379 | 415 | } |
| 380 | 416 | rid = bag_first(&vers); |
| 381 | - if(rid!=0){ | |
| 417 | + if( rid!=0 ){ | |
| 382 | 418 | do{ |
| 383 | 419 | db_bind_int(&qc, ":rid", rid); |
| 384 | 420 | db_step(&qc); |
| 385 | 421 | db_reset(&qc); |
| 386 | 422 | }while((rid = bag_next(&vers, rid))!=0); |
| @@ -416,15 +452,18 @@ | ||
| 416 | 452 | while( db_step(&q)==SQLITE_ROW ){ |
| 417 | 453 | int rid = db_column_int(&q, 0); |
| 418 | 454 | Blob content; |
| 419 | 455 | |
| 420 | 456 | while( !bag_find(&blobs, rid) ){ |
| 457 | + char *zMark; | |
| 421 | 458 | content_get(rid, &content); |
| 422 | 459 | db_bind_int(&q2, ":rid", rid); |
| 423 | 460 | db_step(&q2); |
| 424 | 461 | db_reset(&q2); |
| 425 | - printf("blob\nmark :%d\ndata %d\n", BLOBMARK(rid), blob_size(&content)); | |
| 462 | + zMark = mark_name_from_rid(rid, &unused_mark); | |
| 463 | + printf("blob\nmark %s\ndata %d\n", zMark, blob_size(&content)); | |
| 464 | + free(zMark); | |
| 426 | 465 | bag_insert(&blobs, rid); |
| 427 | 466 | fwrite(blob_buffer(&content), 1, blob_size(&content), stdout); |
| 428 | 467 | printf("\n"); |
| 429 | 468 | blob_reset(&content); |
| 430 | 469 | |
| @@ -470,11 +509,11 @@ | ||
| 470 | 509 | if( zBranch==0 ) zBranch = "trunk"; |
| 471 | 510 | zBr = mprintf("%s", zBranch); |
| 472 | 511 | for(i=0; zBr[i]; i++){ |
| 473 | 512 | if( !fossil_isalnum(zBr[i]) ) zBr[i] = '_'; |
| 474 | 513 | } |
| 475 | - zMark = mark_name_from_rid(ckinId); | |
| 514 | + zMark = mark_name_from_rid(ckinId, &unused_mark); | |
| 476 | 515 | printf("commit refs/heads/%s\nmark %s\n", zBr, zMark); |
| 477 | 516 | free(zMark); |
| 478 | 517 | free(zBr); |
| 479 | 518 | printf("committer"); |
| 480 | 519 | print_person(zUser); |
| @@ -487,21 +526,21 @@ | ||
| 487 | 526 | " AND pid IN (SELECT objid FROM event)", |
| 488 | 527 | ckinId |
| 489 | 528 | ); |
| 490 | 529 | if( db_step(&q3) == SQLITE_ROW ){ |
| 491 | 530 | int pid = db_column_int(&q3, 0); |
| 492 | - zMark = mark_name_from_rid(pid); | |
| 531 | + zMark = mark_name_from_rid(pid, &unused_mark); | |
| 493 | 532 | printf("from %s\n", zMark); |
| 494 | 533 | free(zMark); |
| 495 | 534 | db_prepare(&q4, |
| 496 | 535 | "SELECT pid FROM plink" |
| 497 | 536 | " WHERE cid=%d AND NOT isprim" |
| 498 | 537 | " AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=pid)" |
| 499 | 538 | " ORDER BY pid", |
| 500 | 539 | ckinId); |
| 501 | 540 | while( db_step(&q4)==SQLITE_ROW ){ |
| 502 | - zMark = mark_name_from_rid(db_column_int(&q4, 0)); | |
| 541 | + zMark = mark_name_from_rid(db_column_int(&q4, 0), &unused_mark); | |
| 503 | 542 | printf("merge %s\n", zMark); |
| 504 | 543 | free(zMark); |
| 505 | 544 | } |
| 506 | 545 | db_finalize(&q4); |
| 507 | 546 | }else{ |
| @@ -516,20 +555,22 @@ | ||
| 516 | 555 | ); |
| 517 | 556 | while( db_step(&q4)==SQLITE_ROW ){ |
| 518 | 557 | const char *zName = db_column_text(&q4,0); |
| 519 | 558 | int zNew = db_column_int(&q4,1); |
| 520 | 559 | int mPerm = db_column_int(&q4,2); |
| 521 | - if( zNew==0) | |
| 560 | + if( zNew==0 ){ | |
| 522 | 561 | printf("D %s\n", zName); |
| 523 | - else if( bag_find(&blobs, zNew) ) { | |
| 562 | + }else if( bag_find(&blobs, zNew) ){ | |
| 524 | 563 | const char *zPerm; |
| 564 | + zMark = mark_name_from_rid(zNew, &unused_mark); | |
| 525 | 565 | switch( mPerm ){ |
| 526 | 566 | case PERM_LNK: zPerm = "120000"; break; |
| 527 | 567 | case PERM_EXE: zPerm = "100755"; break; |
| 528 | 568 | default: zPerm = "100644"; break; |
| 529 | 569 | } |
| 530 | - printf("M %s :%d %s\n", zPerm, BLOBMARK(zNew), zName); | |
| 570 | + printf("M %s %s %s\n", zPerm, zMark, zName); | |
| 571 | + free(zMark); | |
| 531 | 572 | } |
| 532 | 573 | } |
| 533 | 574 | db_finalize(&q4); |
| 534 | 575 | db_finalize(&q3); |
| 535 | 576 | printf("\n"); |
| @@ -547,20 +588,22 @@ | ||
| 547 | 588 | ); |
| 548 | 589 | while( db_step(&q)==SQLITE_ROW ){ |
| 549 | 590 | const char *zTagname = db_column_text(&q, 0); |
| 550 | 591 | char *zEncoded = 0; |
| 551 | 592 | int rid = db_column_int(&q, 1); |
| 593 | + char *zMark = mark_name_from_rid(rid, &unused_mark); | |
| 552 | 594 | const char *zSecSince1970 = db_column_text(&q, 2); |
| 553 | 595 | int i; |
| 554 | 596 | if( rid==0 || !bag_find(&vers, rid) ) continue; |
| 555 | 597 | zTagname += 4; |
| 556 | 598 | zEncoded = mprintf("%s", zTagname); |
| 557 | 599 | for(i=0; zEncoded[i]; i++){ |
| 558 | 600 | if( !fossil_isalnum(zEncoded[i]) ) zEncoded[i] = '_'; |
| 559 | 601 | } |
| 560 | 602 | printf("tag %s\n", zEncoded); |
| 561 | - printf("from :%d\n", COMMITMARK(rid)); | |
| 603 | + printf("from %s\n", zMark); | |
| 604 | + free(zMark); | |
| 562 | 605 | printf("tagger <tagger> %s +0000\n", zSecSince1970); |
| 563 | 606 | printf("data 0\n"); |
| 564 | 607 | fossil_free(zEncoded); |
| 565 | 608 | } |
| 566 | 609 | db_finalize(&q); |
| @@ -570,12 +613,12 @@ | ||
| 570 | 613 | f = fossil_fopen(markfile_out, "w"); |
| 571 | 614 | if( f == 0 ){ |
| 572 | 615 | fossil_fatal("cannot open %s for writing", markfile_out); |
| 573 | 616 | } |
| 574 | 617 | export_marks(f, &blobs, &vers); |
| 575 | - if( ferror(f)!=0 || fclose(f)!=0 ) { | |
| 618 | + if( ferror(f)!=0 || fclose(f)!=0 ){ | |
| 576 | 619 | fossil_fatal("error while writing %s", markfile_out); |
| 577 | 620 | } |
| 578 | 621 | } |
| 579 | 622 | bag_clear(&blobs); |
| 580 | 623 | bag_clear(&vers); |
| 581 | 624 | } |
| 582 | 625 |
| --- src/export.c | |
| +++ src/export.c | |
| @@ -132,23 +132,28 @@ | |
| 132 | |
| 133 | /* |
| 134 | ** create_mark() |
| 135 | ** Create a new (mark,rid,uuid) entry for the given rid in the 'xmark' table, |
| 136 | ** and return that information as a struct mark_t in *mark. |
| 137 | ** This function returns -1 in the case where 'rid' does not exist, otherwise |
| 138 | ** it returns 0. |
| 139 | ** mark->name is dynamically allocated and is owned by the caller upon return. |
| 140 | */ |
| 141 | int create_mark(int rid, struct mark_t *mark){ |
| 142 | char sid[13]; |
| 143 | char *zUuid = rid_to_uuid(rid); |
| 144 | if(!zUuid){ |
| 145 | fossil_trace("Undefined rid=%d\n", rid); |
| 146 | return -1; |
| 147 | } |
| 148 | mark->rid = rid; |
| 149 | sqlite3_snprintf(sizeof(sid), sid, ":%d", COMMITMARK(rid)); |
| 150 | mark->name = fossil_strdup(sid); |
| 151 | sqlite3_snprintf(sizeof(mark->uuid), mark->uuid, "%s", zUuid); |
| 152 | free(zUuid); |
| 153 | insert_commit_xref(mark->rid, mark->name, mark->uuid); |
| 154 | return 0; |
| @@ -156,19 +161,22 @@ | |
| 156 | |
| 157 | /* |
| 158 | ** mark_name_from_rid() |
| 159 | ** Find the mark associated with the given rid. Mark names always start |
| 160 | ** with ':', and are pulled from the 'xmark' temporary table. |
| 161 | ** This function returns NULL if the rid does not exist in the 'xmark' table. |
| 162 | ** Otherwise, it returns the name of the mark, which is dynamically allocated |
| 163 | ** and is owned by the caller of this function. |
| 164 | */ |
| 165 | char * mark_name_from_rid(int rid){ |
| 166 | char *zMark = db_text(0, "SELECT tname FROM xmark WHERE trid=%d", rid); |
| 167 | if(zMark==NULL){ |
| 168 | struct mark_t mark; |
| 169 | if(create_mark(rid, &mark)==0){ |
| 170 | zMark = mark.name; |
| 171 | }else{ |
| 172 | return NULL; |
| 173 | } |
| 174 | } |
| @@ -185,43 +193,52 @@ | |
| 185 | ** database. Otherwise, 0 is returned. |
| 186 | ** mark->name is dynamically allocated, and owned by the caller. |
| 187 | */ |
| 188 | int parse_mark(char *line, struct mark_t *mark){ |
| 189 | char *cur_tok; |
| 190 | cur_tok = strtok(line, " \t"); |
| 191 | if(!cur_tok||strlen(cur_tok)<2){ |
| 192 | return -1; |
| 193 | } |
| 194 | mark->rid = atoi(&cur_tok[1]); |
| 195 | if(cur_tok[0]!='c'){ |
| 196 | /* This is probably a blob mark */ |
| 197 | mark->name = NULL; |
| 198 | return 0; |
| 199 | } |
| 200 | |
| 201 | cur_tok = strtok(NULL, " \t"); |
| 202 | if(!cur_tok){ |
| 203 | /* This mark was generated by an older version of Fossil and doesn't |
| 204 | ** include the mark name and uuid. create_mark() will name the new mark |
| 205 | ** exactly as it was when exported to git, so that we should have a |
| 206 | ** valid mapping from git sha1<->mark name<->fossil sha1. */ |
| 207 | return create_mark(mark->rid, mark); |
| 208 | }else{ |
| 209 | mark->name = fossil_strdup(cur_tok); |
| 210 | } |
| 211 | |
| 212 | cur_tok = strtok(NULL, "\n"); |
| 213 | if(!cur_tok||strlen(cur_tok)!=40){ |
| 214 | free(mark->name); |
| 215 | fossil_trace("Invalid SHA-1 in marks file: %s\n", cur_tok); |
| 216 | return -1; |
| 217 | }else{ |
| 218 | sqlite3_snprintf(sizeof(mark->uuid), mark->uuid, "%s", cur_tok); |
| 219 | } |
| 220 | |
| 221 | /* make sure that rid corresponds to UUID */ |
| 222 | if(fast_uuid_to_rid(mark->uuid)!=mark->rid){ |
| 223 | free(mark->name); |
| 224 | fossil_trace("Non-existent SHA-1 in marks file: %s\n", mark->uuid); |
| 225 | return -1; |
| 226 | } |
| 227 | |
| @@ -233,40 +250,66 @@ | |
| 233 | /* |
| 234 | ** import_marks() |
| 235 | ** Import the marks specified in file 'f' into the 'xmark' table. |
| 236 | ** If 'blobs' is non-null, insert all blob marks into it. |
| 237 | ** If 'vers' is non-null, insert all commit marks into it. |
| 238 | ** Each line in the file must be at most 100 characters in length. This |
| 239 | ** seems like a reasonable maximum for a 40-character uuid, and 1-13 |
| 240 | ** character rid. |
| 241 | ** The function returns -1 if any of the lines in file 'f' are malformed, |
| 242 | ** or the rid/uuid information doesn't match what is in the repository |
| 243 | ** database. Otherwise, 0 is returned. |
| 244 | */ |
| 245 | int import_marks(FILE* f, Bag *blobs, Bag *vers){ |
| 246 | char line[101]; |
| 247 | while(fgets(line, sizeof(line), f)){ |
| 248 | struct mark_t mark; |
| 249 | if(strlen(line)==100&&line[99]!='\n'){ |
| 250 | /* line too long */ |
| 251 | return -1; |
| 252 | } |
| 253 | if( parse_mark(line, &mark)<0 ){ |
| 254 | return -1; |
| 255 | }else if( line[0]=='b' ){ |
| 256 | /* Don't import blob marks into 'xmark' table--git doesn't use them, |
| 257 | ** so they need to be left free for git to reuse. */ |
| 258 | if(blobs!=NULL){ |
| 259 | bag_insert(blobs, mark.rid); |
| 260 | } |
| 261 | }else if( vers!=NULL ){ |
| 262 | bag_insert(vers, mark.rid); |
| 263 | } |
| 264 | free(mark.name); |
| 265 | } |
| 266 | return 0; |
| 267 | } |
| 268 | |
| 269 | /* |
| 270 | ** If 'blobs' is non-null, it must point to a Bag of blob rids to be |
| 271 | ** written to disk. Blob rids are written as 'b<rid>'. |
| 272 | ** If 'vers' is non-null, it must point to a Bag of commit rids to be |
| @@ -275,32 +318,24 @@ | |
| 275 | ** This function does not fail, but may produce errors if a uuid cannot |
| 276 | ** be found for an rid in 'vers'. |
| 277 | */ |
| 278 | void export_marks(FILE* f, Bag *blobs, Bag *vers){ |
| 279 | int rid; |
| 280 | if( blobs!=NULL ){ |
| 281 | rid = bag_first(blobs); |
| 282 | if(rid!=0){ |
| 283 | do{ |
| 284 | fprintf(f, "b%d\n", rid); |
| 285 | }while((rid = bag_next(blobs, rid))!=0); |
| 286 | } |
| 287 | } |
| 288 | if( vers!=NULL ){ |
| 289 | rid = bag_first(vers); |
| 290 | if( rid!=0 ){ |
| 291 | do{ |
| 292 | char *zUuid = rid_to_uuid(rid); |
| 293 | char *zMark; |
| 294 | if(zUuid==NULL){ |
| 295 | fossil_trace("No uuid matching rid=%d when exporting marks\n", rid); |
| 296 | continue; |
| 297 | } |
| 298 | zMark = mark_name_from_rid(rid); |
| 299 | fprintf(f, "c%d %s %s\n", rid, zMark, zUuid); |
| 300 | free(zMark); |
| 301 | free(zUuid); |
| 302 | }while( (rid = bag_next(vers, rid))!=0 ); |
| 303 | } |
| 304 | } |
| 305 | } |
| 306 | |
| @@ -336,10 +371,11 @@ | |
| 336 | */ |
| 337 | void export_cmd(void){ |
| 338 | Stmt q, q2, q3; |
| 339 | int i; |
| 340 | Bag blobs, vers; |
| 341 | const char *markfile_in; |
| 342 | const char *markfile_out; |
| 343 | |
| 344 | bag_init(&blobs); |
| 345 | bag_init(&vers); |
| @@ -362,25 +398,25 @@ | |
| 362 | |
| 363 | f = fossil_fopen(markfile_in, "r"); |
| 364 | if( f==0 ){ |
| 365 | fossil_fatal("cannot open %s for reading", markfile_in); |
| 366 | } |
| 367 | if(import_marks(f, &blobs, &vers)<0){ |
| 368 | fossil_fatal("error importing marks from file: %s\n", markfile_in); |
| 369 | } |
| 370 | db_prepare(&qb, "INSERT OR IGNORE INTO oldblob VALUES (:rid)"); |
| 371 | db_prepare(&qc, "INSERT OR IGNORE INTO oldcommit VALUES (:rid)"); |
| 372 | rid = bag_first(&blobs); |
| 373 | if(rid!=0){ |
| 374 | do{ |
| 375 | db_bind_int(&qb, ":rid", rid); |
| 376 | db_step(&qb); |
| 377 | db_reset(&qb); |
| 378 | }while((rid = bag_next(&blobs, rid))!=0); |
| 379 | } |
| 380 | rid = bag_first(&vers); |
| 381 | if(rid!=0){ |
| 382 | do{ |
| 383 | db_bind_int(&qc, ":rid", rid); |
| 384 | db_step(&qc); |
| 385 | db_reset(&qc); |
| 386 | }while((rid = bag_next(&vers, rid))!=0); |
| @@ -416,15 +452,18 @@ | |
| 416 | while( db_step(&q)==SQLITE_ROW ){ |
| 417 | int rid = db_column_int(&q, 0); |
| 418 | Blob content; |
| 419 | |
| 420 | while( !bag_find(&blobs, rid) ){ |
| 421 | content_get(rid, &content); |
| 422 | db_bind_int(&q2, ":rid", rid); |
| 423 | db_step(&q2); |
| 424 | db_reset(&q2); |
| 425 | printf("blob\nmark :%d\ndata %d\n", BLOBMARK(rid), blob_size(&content)); |
| 426 | bag_insert(&blobs, rid); |
| 427 | fwrite(blob_buffer(&content), 1, blob_size(&content), stdout); |
| 428 | printf("\n"); |
| 429 | blob_reset(&content); |
| 430 | |
| @@ -470,11 +509,11 @@ | |
| 470 | if( zBranch==0 ) zBranch = "trunk"; |
| 471 | zBr = mprintf("%s", zBranch); |
| 472 | for(i=0; zBr[i]; i++){ |
| 473 | if( !fossil_isalnum(zBr[i]) ) zBr[i] = '_'; |
| 474 | } |
| 475 | zMark = mark_name_from_rid(ckinId); |
| 476 | printf("commit refs/heads/%s\nmark %s\n", zBr, zMark); |
| 477 | free(zMark); |
| 478 | free(zBr); |
| 479 | printf("committer"); |
| 480 | print_person(zUser); |
| @@ -487,21 +526,21 @@ | |
| 487 | " AND pid IN (SELECT objid FROM event)", |
| 488 | ckinId |
| 489 | ); |
| 490 | if( db_step(&q3) == SQLITE_ROW ){ |
| 491 | int pid = db_column_int(&q3, 0); |
| 492 | zMark = mark_name_from_rid(pid); |
| 493 | printf("from %s\n", zMark); |
| 494 | free(zMark); |
| 495 | db_prepare(&q4, |
| 496 | "SELECT pid FROM plink" |
| 497 | " WHERE cid=%d AND NOT isprim" |
| 498 | " AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=pid)" |
| 499 | " ORDER BY pid", |
| 500 | ckinId); |
| 501 | while( db_step(&q4)==SQLITE_ROW ){ |
| 502 | zMark = mark_name_from_rid(db_column_int(&q4, 0)); |
| 503 | printf("merge %s\n", zMark); |
| 504 | free(zMark); |
| 505 | } |
| 506 | db_finalize(&q4); |
| 507 | }else{ |
| @@ -516,20 +555,22 @@ | |
| 516 | ); |
| 517 | while( db_step(&q4)==SQLITE_ROW ){ |
| 518 | const char *zName = db_column_text(&q4,0); |
| 519 | int zNew = db_column_int(&q4,1); |
| 520 | int mPerm = db_column_int(&q4,2); |
| 521 | if( zNew==0) |
| 522 | printf("D %s\n", zName); |
| 523 | else if( bag_find(&blobs, zNew) ) { |
| 524 | const char *zPerm; |
| 525 | switch( mPerm ){ |
| 526 | case PERM_LNK: zPerm = "120000"; break; |
| 527 | case PERM_EXE: zPerm = "100755"; break; |
| 528 | default: zPerm = "100644"; break; |
| 529 | } |
| 530 | printf("M %s :%d %s\n", zPerm, BLOBMARK(zNew), zName); |
| 531 | } |
| 532 | } |
| 533 | db_finalize(&q4); |
| 534 | db_finalize(&q3); |
| 535 | printf("\n"); |
| @@ -547,20 +588,22 @@ | |
| 547 | ); |
| 548 | while( db_step(&q)==SQLITE_ROW ){ |
| 549 | const char *zTagname = db_column_text(&q, 0); |
| 550 | char *zEncoded = 0; |
| 551 | int rid = db_column_int(&q, 1); |
| 552 | const char *zSecSince1970 = db_column_text(&q, 2); |
| 553 | int i; |
| 554 | if( rid==0 || !bag_find(&vers, rid) ) continue; |
| 555 | zTagname += 4; |
| 556 | zEncoded = mprintf("%s", zTagname); |
| 557 | for(i=0; zEncoded[i]; i++){ |
| 558 | if( !fossil_isalnum(zEncoded[i]) ) zEncoded[i] = '_'; |
| 559 | } |
| 560 | printf("tag %s\n", zEncoded); |
| 561 | printf("from :%d\n", COMMITMARK(rid)); |
| 562 | printf("tagger <tagger> %s +0000\n", zSecSince1970); |
| 563 | printf("data 0\n"); |
| 564 | fossil_free(zEncoded); |
| 565 | } |
| 566 | db_finalize(&q); |
| @@ -570,12 +613,12 @@ | |
| 570 | f = fossil_fopen(markfile_out, "w"); |
| 571 | if( f == 0 ){ |
| 572 | fossil_fatal("cannot open %s for writing", markfile_out); |
| 573 | } |
| 574 | export_marks(f, &blobs, &vers); |
| 575 | if( ferror(f)!=0 || fclose(f)!=0 ) { |
| 576 | fossil_fatal("error while writing %s", markfile_out); |
| 577 | } |
| 578 | } |
| 579 | bag_clear(&blobs); |
| 580 | bag_clear(&vers); |
| 581 | } |
| 582 |
| --- src/export.c | |
| +++ src/export.c | |
| @@ -132,23 +132,28 @@ | |
| 132 | |
| 133 | /* |
| 134 | ** create_mark() |
| 135 | ** Create a new (mark,rid,uuid) entry for the given rid in the 'xmark' table, |
| 136 | ** and return that information as a struct mark_t in *mark. |
| 137 | ** *unused_mark is a value representing a mark that is free for use--that is, |
| 138 | ** it does not appear in the marks file, and has not been used during this |
| 139 | ** export run. Specifically, it is the supremum of the set of used marks |
| 140 | ** plus one. |
| 141 | ** This function returns -1 in the case where 'rid' does not exist, otherwise |
| 142 | ** it returns 0. |
| 143 | ** mark->name is dynamically allocated and is owned by the caller upon return. |
| 144 | */ |
| 145 | int create_mark(int rid, struct mark_t *mark, unsigned int *unused_mark){ |
| 146 | char sid[13]; |
| 147 | char *zUuid = rid_to_uuid(rid); |
| 148 | if( !zUuid ){ |
| 149 | fossil_trace("Undefined rid=%d\n", rid); |
| 150 | return -1; |
| 151 | } |
| 152 | mark->rid = rid; |
| 153 | sqlite3_snprintf(sizeof(sid), sid, ":%d", *unused_mark); |
| 154 | *unused_mark += 1; |
| 155 | mark->name = fossil_strdup(sid); |
| 156 | sqlite3_snprintf(sizeof(mark->uuid), mark->uuid, "%s", zUuid); |
| 157 | free(zUuid); |
| 158 | insert_commit_xref(mark->rid, mark->name, mark->uuid); |
| 159 | return 0; |
| @@ -156,19 +161,22 @@ | |
| 161 | |
| 162 | /* |
| 163 | ** mark_name_from_rid() |
| 164 | ** Find the mark associated with the given rid. Mark names always start |
| 165 | ** with ':', and are pulled from the 'xmark' temporary table. |
| 166 | ** If the given rid doesn't have a mark associated with it yet, one is |
| 167 | ** created with a value of *unused_mark. |
| 168 | ** *unused_mark functions exactly as in create_mark(). |
| 169 | ** This function returns NULL if the rid does not have an associated UUID, |
| 170 | ** (i.e. is not valid). Otherwise, it returns the name of the mark, which is |
| 171 | ** dynamically allocated and is owned by the caller of this function. |
| 172 | */ |
| 173 | char * mark_name_from_rid(int rid, unsigned int *unused_mark){ |
| 174 | char *zMark = db_text(0, "SELECT tname FROM xmark WHERE trid=%d", rid); |
| 175 | if( zMark==NULL ){ |
| 176 | struct mark_t mark; |
| 177 | if( create_mark(rid, &mark, unused_mark)==0 ){ |
| 178 | zMark = mark.name; |
| 179 | }else{ |
| 180 | return NULL; |
| 181 | } |
| 182 | } |
| @@ -185,43 +193,52 @@ | |
| 193 | ** database. Otherwise, 0 is returned. |
| 194 | ** mark->name is dynamically allocated, and owned by the caller. |
| 195 | */ |
| 196 | int parse_mark(char *line, struct mark_t *mark){ |
| 197 | char *cur_tok; |
| 198 | char type_; |
| 199 | cur_tok = strtok(line, " \t"); |
| 200 | if( !cur_tok || strlen(cur_tok)<2 ){ |
| 201 | return -1; |
| 202 | } |
| 203 | mark->rid = atoi(&cur_tok[1]); |
| 204 | type_ = cur_tok[0]; |
| 205 | if( type_!='c' && type_!='b' ){ |
| 206 | /* This is probably a blob mark */ |
| 207 | mark->name = NULL; |
| 208 | return 0; |
| 209 | } |
| 210 | |
| 211 | cur_tok = strtok(NULL, " \t"); |
| 212 | if( !cur_tok ){ |
| 213 | /* This mark was generated by an older version of Fossil and doesn't |
| 214 | ** include the mark name and uuid. create_mark() will name the new mark |
| 215 | ** exactly as it was when exported to git, so that we should have a |
| 216 | ** valid mapping from git sha1<->mark name<->fossil sha1. */ |
| 217 | unsigned int mid; |
| 218 | if( type_=='c' ){ |
| 219 | mid = COMMITMARK(mark->rid); |
| 220 | } |
| 221 | else{ |
| 222 | mid = BLOBMARK(mark->rid); |
| 223 | } |
| 224 | return create_mark(mark->rid, mark, &mid); |
| 225 | }else{ |
| 226 | mark->name = fossil_strdup(cur_tok); |
| 227 | } |
| 228 | |
| 229 | cur_tok = strtok(NULL, "\n"); |
| 230 | if( !cur_tok || strlen(cur_tok)!=40 ){ |
| 231 | free(mark->name); |
| 232 | fossil_trace("Invalid SHA-1 in marks file: %s\n", cur_tok); |
| 233 | return -1; |
| 234 | }else{ |
| 235 | sqlite3_snprintf(sizeof(mark->uuid), mark->uuid, "%s", cur_tok); |
| 236 | } |
| 237 | |
| 238 | /* make sure that rid corresponds to UUID */ |
| 239 | if( fast_uuid_to_rid(mark->uuid)!=mark->rid ){ |
| 240 | free(mark->name); |
| 241 | fossil_trace("Non-existent SHA-1 in marks file: %s\n", mark->uuid); |
| 242 | return -1; |
| 243 | } |
| 244 | |
| @@ -233,40 +250,66 @@ | |
| 250 | /* |
| 251 | ** import_marks() |
| 252 | ** Import the marks specified in file 'f' into the 'xmark' table. |
| 253 | ** If 'blobs' is non-null, insert all blob marks into it. |
| 254 | ** If 'vers' is non-null, insert all commit marks into it. |
| 255 | ** If 'unused_marks' is non-null, upon return of this function, all values |
| 256 | ** x >= *unused_marks are free to use as marks, i.e. they do not clash with |
| 257 | ** any marks appearing in the marks file. |
| 258 | ** Each line in the file must be at most 100 characters in length. This |
| 259 | ** seems like a reasonable maximum for a 40-character uuid, and 1-13 |
| 260 | ** character rid. |
| 261 | ** The function returns -1 if any of the lines in file 'f' are malformed, |
| 262 | ** or the rid/uuid information doesn't match what is in the repository |
| 263 | ** database. Otherwise, 0 is returned. |
| 264 | */ |
| 265 | int import_marks(FILE* f, Bag *blobs, Bag *vers, unsigned int *unused_mark){ |
| 266 | char line[101]; |
| 267 | while(fgets(line, sizeof(line), f)){ |
| 268 | struct mark_t mark; |
| 269 | if( strlen(line)==100 && line[99]!='\n' ){ |
| 270 | /* line too long */ |
| 271 | return -1; |
| 272 | } |
| 273 | if( parse_mark(line, &mark)<0 ){ |
| 274 | return -1; |
| 275 | }else if( line[0]=='b' ){ |
| 276 | if( blobs!=NULL ){ |
| 277 | bag_insert(blobs, mark.rid); |
| 278 | } |
| 279 | }else{ |
| 280 | if( vers!=NULL ){ |
| 281 | bag_insert(vers, mark.rid); |
| 282 | } |
| 283 | } |
| 284 | if( unused_mark!=NULL ){ |
| 285 | unsigned int mid = atoi(mark.name + 1); |
| 286 | if( mid>=*unused_mark ){ |
| 287 | *unused_mark = mid + 1; |
| 288 | } |
| 289 | } |
| 290 | free(mark.name); |
| 291 | } |
| 292 | return 0; |
| 293 | } |
| 294 | |
| 295 | void export_mark(FILE* f, int rid, char obj_type) |
| 296 | { |
| 297 | unsigned int z = 0; |
| 298 | char *zUuid = rid_to_uuid(rid); |
| 299 | char *zMark; |
| 300 | if( zUuid==NULL ){ |
| 301 | fossil_trace("No uuid matching rid=%d when exporting marks\n", rid); |
| 302 | return; |
| 303 | } |
| 304 | /* Since rid is already in the 'xmark' table, the value of z won't be |
| 305 | ** used, but pass in a valid pointer just to be safe. */ |
| 306 | zMark = mark_name_from_rid(rid, &z); |
| 307 | fprintf(f, "%c%d %s %s\n", obj_type, rid, zMark, zUuid); |
| 308 | free(zMark); |
| 309 | free(zUuid); |
| 310 | } |
| 311 | |
| 312 | /* |
| 313 | ** If 'blobs' is non-null, it must point to a Bag of blob rids to be |
| 314 | ** written to disk. Blob rids are written as 'b<rid>'. |
| 315 | ** If 'vers' is non-null, it must point to a Bag of commit rids to be |
| @@ -275,32 +318,24 @@ | |
| 318 | ** This function does not fail, but may produce errors if a uuid cannot |
| 319 | ** be found for an rid in 'vers'. |
| 320 | */ |
| 321 | void export_marks(FILE* f, Bag *blobs, Bag *vers){ |
| 322 | int rid; |
| 323 | |
| 324 | if( blobs!=NULL ){ |
| 325 | rid = bag_first(blobs); |
| 326 | if( rid!=0 ){ |
| 327 | do{ |
| 328 | export_mark(f, rid, 'b'); |
| 329 | }while( (rid = bag_next(blobs, rid))!=0 ); |
| 330 | } |
| 331 | } |
| 332 | if( vers!=NULL ){ |
| 333 | rid = bag_first(vers); |
| 334 | if( rid!=0 ){ |
| 335 | do{ |
| 336 | export_mark(f, rid, 'c'); |
| 337 | }while( (rid = bag_next(vers, rid))!=0 ); |
| 338 | } |
| 339 | } |
| 340 | } |
| 341 | |
| @@ -336,10 +371,11 @@ | |
| 371 | */ |
| 372 | void export_cmd(void){ |
| 373 | Stmt q, q2, q3; |
| 374 | int i; |
| 375 | Bag blobs, vers; |
| 376 | unsigned int unused_mark = 1; |
| 377 | const char *markfile_in; |
| 378 | const char *markfile_out; |
| 379 | |
| 380 | bag_init(&blobs); |
| 381 | bag_init(&vers); |
| @@ -362,25 +398,25 @@ | |
| 398 | |
| 399 | f = fossil_fopen(markfile_in, "r"); |
| 400 | if( f==0 ){ |
| 401 | fossil_fatal("cannot open %s for reading", markfile_in); |
| 402 | } |
| 403 | if( import_marks(f, &blobs, &vers, &unused_mark)<0 ){ |
| 404 | fossil_fatal("error importing marks from file: %s", markfile_in); |
| 405 | } |
| 406 | db_prepare(&qb, "INSERT OR IGNORE INTO oldblob VALUES (:rid)"); |
| 407 | db_prepare(&qc, "INSERT OR IGNORE INTO oldcommit VALUES (:rid)"); |
| 408 | rid = bag_first(&blobs); |
| 409 | if( rid!=0 ){ |
| 410 | do{ |
| 411 | db_bind_int(&qb, ":rid", rid); |
| 412 | db_step(&qb); |
| 413 | db_reset(&qb); |
| 414 | }while((rid = bag_next(&blobs, rid))!=0); |
| 415 | } |
| 416 | rid = bag_first(&vers); |
| 417 | if( rid!=0 ){ |
| 418 | do{ |
| 419 | db_bind_int(&qc, ":rid", rid); |
| 420 | db_step(&qc); |
| 421 | db_reset(&qc); |
| 422 | }while((rid = bag_next(&vers, rid))!=0); |
| @@ -416,15 +452,18 @@ | |
| 452 | while( db_step(&q)==SQLITE_ROW ){ |
| 453 | int rid = db_column_int(&q, 0); |
| 454 | Blob content; |
| 455 | |
| 456 | while( !bag_find(&blobs, rid) ){ |
| 457 | char *zMark; |
| 458 | content_get(rid, &content); |
| 459 | db_bind_int(&q2, ":rid", rid); |
| 460 | db_step(&q2); |
| 461 | db_reset(&q2); |
| 462 | zMark = mark_name_from_rid(rid, &unused_mark); |
| 463 | printf("blob\nmark %s\ndata %d\n", zMark, blob_size(&content)); |
| 464 | free(zMark); |
| 465 | bag_insert(&blobs, rid); |
| 466 | fwrite(blob_buffer(&content), 1, blob_size(&content), stdout); |
| 467 | printf("\n"); |
| 468 | blob_reset(&content); |
| 469 | |
| @@ -470,11 +509,11 @@ | |
| 509 | if( zBranch==0 ) zBranch = "trunk"; |
| 510 | zBr = mprintf("%s", zBranch); |
| 511 | for(i=0; zBr[i]; i++){ |
| 512 | if( !fossil_isalnum(zBr[i]) ) zBr[i] = '_'; |
| 513 | } |
| 514 | zMark = mark_name_from_rid(ckinId, &unused_mark); |
| 515 | printf("commit refs/heads/%s\nmark %s\n", zBr, zMark); |
| 516 | free(zMark); |
| 517 | free(zBr); |
| 518 | printf("committer"); |
| 519 | print_person(zUser); |
| @@ -487,21 +526,21 @@ | |
| 526 | " AND pid IN (SELECT objid FROM event)", |
| 527 | ckinId |
| 528 | ); |
| 529 | if( db_step(&q3) == SQLITE_ROW ){ |
| 530 | int pid = db_column_int(&q3, 0); |
| 531 | zMark = mark_name_from_rid(pid, &unused_mark); |
| 532 | printf("from %s\n", zMark); |
| 533 | free(zMark); |
| 534 | db_prepare(&q4, |
| 535 | "SELECT pid FROM plink" |
| 536 | " WHERE cid=%d AND NOT isprim" |
| 537 | " AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=pid)" |
| 538 | " ORDER BY pid", |
| 539 | ckinId); |
| 540 | while( db_step(&q4)==SQLITE_ROW ){ |
| 541 | zMark = mark_name_from_rid(db_column_int(&q4, 0), &unused_mark); |
| 542 | printf("merge %s\n", zMark); |
| 543 | free(zMark); |
| 544 | } |
| 545 | db_finalize(&q4); |
| 546 | }else{ |
| @@ -516,20 +555,22 @@ | |
| 555 | ); |
| 556 | while( db_step(&q4)==SQLITE_ROW ){ |
| 557 | const char *zName = db_column_text(&q4,0); |
| 558 | int zNew = db_column_int(&q4,1); |
| 559 | int mPerm = db_column_int(&q4,2); |
| 560 | if( zNew==0 ){ |
| 561 | printf("D %s\n", zName); |
| 562 | }else if( bag_find(&blobs, zNew) ){ |
| 563 | const char *zPerm; |
| 564 | zMark = mark_name_from_rid(zNew, &unused_mark); |
| 565 | switch( mPerm ){ |
| 566 | case PERM_LNK: zPerm = "120000"; break; |
| 567 | case PERM_EXE: zPerm = "100755"; break; |
| 568 | default: zPerm = "100644"; break; |
| 569 | } |
| 570 | printf("M %s %s %s\n", zPerm, zMark, zName); |
| 571 | free(zMark); |
| 572 | } |
| 573 | } |
| 574 | db_finalize(&q4); |
| 575 | db_finalize(&q3); |
| 576 | printf("\n"); |
| @@ -547,20 +588,22 @@ | |
| 588 | ); |
| 589 | while( db_step(&q)==SQLITE_ROW ){ |
| 590 | const char *zTagname = db_column_text(&q, 0); |
| 591 | char *zEncoded = 0; |
| 592 | int rid = db_column_int(&q, 1); |
| 593 | char *zMark = mark_name_from_rid(rid, &unused_mark); |
| 594 | const char *zSecSince1970 = db_column_text(&q, 2); |
| 595 | int i; |
| 596 | if( rid==0 || !bag_find(&vers, rid) ) continue; |
| 597 | zTagname += 4; |
| 598 | zEncoded = mprintf("%s", zTagname); |
| 599 | for(i=0; zEncoded[i]; i++){ |
| 600 | if( !fossil_isalnum(zEncoded[i]) ) zEncoded[i] = '_'; |
| 601 | } |
| 602 | printf("tag %s\n", zEncoded); |
| 603 | printf("from %s\n", zMark); |
| 604 | free(zMark); |
| 605 | printf("tagger <tagger> %s +0000\n", zSecSince1970); |
| 606 | printf("data 0\n"); |
| 607 | fossil_free(zEncoded); |
| 608 | } |
| 609 | db_finalize(&q); |
| @@ -570,12 +613,12 @@ | |
| 613 | f = fossil_fopen(markfile_out, "w"); |
| 614 | if( f == 0 ){ |
| 615 | fossil_fatal("cannot open %s for writing", markfile_out); |
| 616 | } |
| 617 | export_marks(f, &blobs, &vers); |
| 618 | if( ferror(f)!=0 || fclose(f)!=0 ){ |
| 619 | fossil_fatal("error while writing %s", markfile_out); |
| 620 | } |
| 621 | } |
| 622 | bag_clear(&blobs); |
| 623 | bag_clear(&vers); |
| 624 | } |
| 625 |
+63
-12
| --- src/file.c | ||
| +++ src/file.c | ||
| @@ -293,24 +293,36 @@ | ||
| 293 | 293 | } |
| 294 | 294 | return rc ? 0 : (S_ISDIR(fileStat.st_mode) ? 1 : 2); |
| 295 | 295 | } |
| 296 | 296 | |
| 297 | 297 | /* |
| 298 | -** Same as file_isdir(), but takes into account symlinks. | |
| 298 | +** Same as file_isdir(), but takes into account symlinks. Return 1 if | |
| 299 | +** zFilename is a directory -OR- a symlink that points to a directory. | |
| 300 | +** Return 0 if zFilename does not exist. Return 2 if zFilename exists | |
| 301 | +** but is something other than a directory. | |
| 299 | 302 | */ |
| 300 | 303 | int file_wd_isdir(const char *zFilename){ |
| 301 | 304 | int rc; |
| 305 | + char *zFN; | |
| 302 | 306 | |
| 303 | - if( zFilename ){ | |
| 304 | - char *zFN = mprintf("%s", zFilename); | |
| 305 | - file_simplify_name(zFN, -1, 0); | |
| 306 | - rc = getStat(zFN, 1); | |
| 307 | - free(zFN); | |
| 307 | + zFN = mprintf("%s", zFilename); | |
| 308 | + file_simplify_name(zFN, -1, 0); | |
| 309 | + rc = getStat(zFN, 1); | |
| 310 | + if( rc ){ | |
| 311 | + rc = 0; /* It does not exist at all. */ | |
| 312 | + }else if( S_ISDIR(fileStat.st_mode) ){ | |
| 313 | + rc = 1; /* It exists and is a real directory. */ | |
| 314 | + }else if( S_ISLNK(fileStat.st_mode) ){ | |
| 315 | + Blob content; | |
| 316 | + blob_read_link(&content, zFN); /* It exists and is a link. */ | |
| 317 | + rc = file_wd_isdir(blob_str(&content)); /* Points to directory? */ | |
| 318 | + blob_reset(&content); | |
| 308 | 319 | }else{ |
| 309 | - rc = getStat(0, 1); | |
| 320 | + rc = 2; /* It exists and is something else. */ | |
| 310 | 321 | } |
| 311 | - return rc ? 0 : (S_ISDIR(fileStat.st_mode) ? 1 : 2); | |
| 322 | + free(zFN); | |
| 323 | + return rc; | |
| 312 | 324 | } |
| 313 | 325 | |
| 314 | 326 | |
| 315 | 327 | /* |
| 316 | 328 | ** Wrapper around the access() system call. |
| @@ -471,16 +483,16 @@ | ||
| 471 | 483 | #if !defined(_WIN32) |
| 472 | 484 | struct stat buf; |
| 473 | 485 | if( fossil_stat(zFilename, &buf, 1)!=0 || S_ISLNK(buf.st_mode) ) return 0; |
| 474 | 486 | if( onoff ){ |
| 475 | 487 | int targetMode = (buf.st_mode & 0444)>>2; |
| 476 | - if( (buf.st_mode & 0100) == 0 ){ | |
| 488 | + if( (buf.st_mode & 0100)==0 ){ | |
| 477 | 489 | chmod(zFilename, buf.st_mode | targetMode); |
| 478 | 490 | rc = 1; |
| 479 | 491 | } |
| 480 | 492 | }else{ |
| 481 | - if( (buf.st_mode & 0100) != 0 ){ | |
| 493 | + if( (buf.st_mode & 0100)!=0 ){ | |
| 482 | 494 | chmod(zFilename, buf.st_mode & ~0111); |
| 483 | 495 | rc = 1; |
| 484 | 496 | } |
| 485 | 497 | } |
| 486 | 498 | #endif /* _WIN32 */ |
| @@ -600,11 +612,11 @@ | ||
| 600 | 612 | ** The if stops us from trying to create a directory of a drive letter |
| 601 | 613 | ** C: in this example. |
| 602 | 614 | */ |
| 603 | 615 | if( !(i==2 && zName[1]==':') ){ |
| 604 | 616 | #endif |
| 605 | - if( file_mkdir(zName, forceFlag) && file_isdir(zName)!=1 ){ | |
| 617 | + if( file_mkdir(zName, forceFlag) && file_wd_isdir(zName)!=1 ){ | |
| 606 | 618 | if (errorReturn <= 0) { |
| 607 | 619 | fossil_fatal_recursive("unable to create directory %s", zName); |
| 608 | 620 | } |
| 609 | 621 | rc = errorReturn; |
| 610 | 622 | break; |
| @@ -851,11 +863,11 @@ | ||
| 851 | 863 | #ifdef _WIN32 |
| 852 | 864 | win32_getcwd(zBuf, nBuf); |
| 853 | 865 | #else |
| 854 | 866 | if( getcwd(zBuf, nBuf-1)==0 ){ |
| 855 | 867 | if( errno==ERANGE ){ |
| 856 | - fossil_fatal("pwd too big: max %d\n", nBuf-1); | |
| 868 | + fossil_fatal("pwd too big: max %d", nBuf-1); | |
| 857 | 869 | }else{ |
| 858 | 870 | fossil_fatal("cannot find current working directory; %s", |
| 859 | 871 | strerror(errno)); |
| 860 | 872 | } |
| 861 | 873 | } |
| @@ -1384,5 +1396,44 @@ | ||
| 1384 | 1396 | #else |
| 1385 | 1397 | FILE *f = fopen(zName, zMode); |
| 1386 | 1398 | #endif |
| 1387 | 1399 | return f; |
| 1388 | 1400 | } |
| 1401 | + | |
| 1402 | +/* | |
| 1403 | +** Return non-NULL if zFilename contains pathname elements that | |
| 1404 | +** are reserved on Windows. The returned string is the disallowed | |
| 1405 | +** path element. | |
| 1406 | +*/ | |
| 1407 | +const char *file_is_win_reserved(const char *zPath){ | |
| 1408 | + static const char *azRes[] = { "CON", "PRN", "AUX", "NUL", "COM", "LPT" }; | |
| 1409 | + static char zReturn[5]; | |
| 1410 | + int i; | |
| 1411 | + while( zPath[0] ){ | |
| 1412 | + for(i=0; i<ArraySize(azRes); i++){ | |
| 1413 | + if( sqlite3_strnicmp(zPath, azRes[i], 3)==0 | |
| 1414 | + && ((i>=4 && fossil_isdigit(zPath[3]) | |
| 1415 | + && (zPath[4]=='/' || zPath[4]=='.' || zPath[4]==0)) | |
| 1416 | + || (i<4 && (zPath[3]=='/' || zPath[3]=='.' || zPath[3]==0))) | |
| 1417 | + ){ | |
| 1418 | + sqlite3_snprintf(5,zReturn,"%.*s", i>=4 ? 4 : 3, zPath); | |
| 1419 | + return zReturn; | |
| 1420 | + } | |
| 1421 | + } | |
| 1422 | + while( zPath[0] && zPath[0]!='/' ) zPath++; | |
| 1423 | + while( zPath[0]=='/' ) zPath++; | |
| 1424 | + } | |
| 1425 | + return 0; | |
| 1426 | +} | |
| 1427 | + | |
| 1428 | +/* | |
| 1429 | +** COMMAND: test-valid-for-windows | |
| 1430 | +** Usage: fossil test-valid-for-windows FILENAME .... | |
| 1431 | +** | |
| 1432 | +** Show which filenames are not valid for Windows | |
| 1433 | +*/ | |
| 1434 | +void file_test_valid_for_windows(void){ | |
| 1435 | + int i; | |
| 1436 | + for(i=2; i<g.argc; i++){ | |
| 1437 | + fossil_print("%s %s\n", file_is_win_reserved(g.argv[i]), g.argv[i]); | |
| 1438 | + } | |
| 1439 | +} | |
| 1389 | 1440 |
| --- src/file.c | |
| +++ src/file.c | |
| @@ -293,24 +293,36 @@ | |
| 293 | } |
| 294 | return rc ? 0 : (S_ISDIR(fileStat.st_mode) ? 1 : 2); |
| 295 | } |
| 296 | |
| 297 | /* |
| 298 | ** Same as file_isdir(), but takes into account symlinks. |
| 299 | */ |
| 300 | int file_wd_isdir(const char *zFilename){ |
| 301 | int rc; |
| 302 | |
| 303 | if( zFilename ){ |
| 304 | char *zFN = mprintf("%s", zFilename); |
| 305 | file_simplify_name(zFN, -1, 0); |
| 306 | rc = getStat(zFN, 1); |
| 307 | free(zFN); |
| 308 | }else{ |
| 309 | rc = getStat(0, 1); |
| 310 | } |
| 311 | return rc ? 0 : (S_ISDIR(fileStat.st_mode) ? 1 : 2); |
| 312 | } |
| 313 | |
| 314 | |
| 315 | /* |
| 316 | ** Wrapper around the access() system call. |
| @@ -471,16 +483,16 @@ | |
| 471 | #if !defined(_WIN32) |
| 472 | struct stat buf; |
| 473 | if( fossil_stat(zFilename, &buf, 1)!=0 || S_ISLNK(buf.st_mode) ) return 0; |
| 474 | if( onoff ){ |
| 475 | int targetMode = (buf.st_mode & 0444)>>2; |
| 476 | if( (buf.st_mode & 0100) == 0 ){ |
| 477 | chmod(zFilename, buf.st_mode | targetMode); |
| 478 | rc = 1; |
| 479 | } |
| 480 | }else{ |
| 481 | if( (buf.st_mode & 0100) != 0 ){ |
| 482 | chmod(zFilename, buf.st_mode & ~0111); |
| 483 | rc = 1; |
| 484 | } |
| 485 | } |
| 486 | #endif /* _WIN32 */ |
| @@ -600,11 +612,11 @@ | |
| 600 | ** The if stops us from trying to create a directory of a drive letter |
| 601 | ** C: in this example. |
| 602 | */ |
| 603 | if( !(i==2 && zName[1]==':') ){ |
| 604 | #endif |
| 605 | if( file_mkdir(zName, forceFlag) && file_isdir(zName)!=1 ){ |
| 606 | if (errorReturn <= 0) { |
| 607 | fossil_fatal_recursive("unable to create directory %s", zName); |
| 608 | } |
| 609 | rc = errorReturn; |
| 610 | break; |
| @@ -851,11 +863,11 @@ | |
| 851 | #ifdef _WIN32 |
| 852 | win32_getcwd(zBuf, nBuf); |
| 853 | #else |
| 854 | if( getcwd(zBuf, nBuf-1)==0 ){ |
| 855 | if( errno==ERANGE ){ |
| 856 | fossil_fatal("pwd too big: max %d\n", nBuf-1); |
| 857 | }else{ |
| 858 | fossil_fatal("cannot find current working directory; %s", |
| 859 | strerror(errno)); |
| 860 | } |
| 861 | } |
| @@ -1384,5 +1396,44 @@ | |
| 1384 | #else |
| 1385 | FILE *f = fopen(zName, zMode); |
| 1386 | #endif |
| 1387 | return f; |
| 1388 | } |
| 1389 |
| --- src/file.c | |
| +++ src/file.c | |
| @@ -293,24 +293,36 @@ | |
| 293 | } |
| 294 | return rc ? 0 : (S_ISDIR(fileStat.st_mode) ? 1 : 2); |
| 295 | } |
| 296 | |
| 297 | /* |
| 298 | ** Same as file_isdir(), but takes into account symlinks. Return 1 if |
| 299 | ** zFilename is a directory -OR- a symlink that points to a directory. |
| 300 | ** Return 0 if zFilename does not exist. Return 2 if zFilename exists |
| 301 | ** but is something other than a directory. |
| 302 | */ |
| 303 | int file_wd_isdir(const char *zFilename){ |
| 304 | int rc; |
| 305 | char *zFN; |
| 306 | |
| 307 | zFN = mprintf("%s", zFilename); |
| 308 | file_simplify_name(zFN, -1, 0); |
| 309 | rc = getStat(zFN, 1); |
| 310 | if( rc ){ |
| 311 | rc = 0; /* It does not exist at all. */ |
| 312 | }else if( S_ISDIR(fileStat.st_mode) ){ |
| 313 | rc = 1; /* It exists and is a real directory. */ |
| 314 | }else if( S_ISLNK(fileStat.st_mode) ){ |
| 315 | Blob content; |
| 316 | blob_read_link(&content, zFN); /* It exists and is a link. */ |
| 317 | rc = file_wd_isdir(blob_str(&content)); /* Points to directory? */ |
| 318 | blob_reset(&content); |
| 319 | }else{ |
| 320 | rc = 2; /* It exists and is something else. */ |
| 321 | } |
| 322 | free(zFN); |
| 323 | return rc; |
| 324 | } |
| 325 | |
| 326 | |
| 327 | /* |
| 328 | ** Wrapper around the access() system call. |
| @@ -471,16 +483,16 @@ | |
| 483 | #if !defined(_WIN32) |
| 484 | struct stat buf; |
| 485 | if( fossil_stat(zFilename, &buf, 1)!=0 || S_ISLNK(buf.st_mode) ) return 0; |
| 486 | if( onoff ){ |
| 487 | int targetMode = (buf.st_mode & 0444)>>2; |
| 488 | if( (buf.st_mode & 0100)==0 ){ |
| 489 | chmod(zFilename, buf.st_mode | targetMode); |
| 490 | rc = 1; |
| 491 | } |
| 492 | }else{ |
| 493 | if( (buf.st_mode & 0100)!=0 ){ |
| 494 | chmod(zFilename, buf.st_mode & ~0111); |
| 495 | rc = 1; |
| 496 | } |
| 497 | } |
| 498 | #endif /* _WIN32 */ |
| @@ -600,11 +612,11 @@ | |
| 612 | ** The if stops us from trying to create a directory of a drive letter |
| 613 | ** C: in this example. |
| 614 | */ |
| 615 | if( !(i==2 && zName[1]==':') ){ |
| 616 | #endif |
| 617 | if( file_mkdir(zName, forceFlag) && file_wd_isdir(zName)!=1 ){ |
| 618 | if (errorReturn <= 0) { |
| 619 | fossil_fatal_recursive("unable to create directory %s", zName); |
| 620 | } |
| 621 | rc = errorReturn; |
| 622 | break; |
| @@ -851,11 +863,11 @@ | |
| 863 | #ifdef _WIN32 |
| 864 | win32_getcwd(zBuf, nBuf); |
| 865 | #else |
| 866 | if( getcwd(zBuf, nBuf-1)==0 ){ |
| 867 | if( errno==ERANGE ){ |
| 868 | fossil_fatal("pwd too big: max %d", nBuf-1); |
| 869 | }else{ |
| 870 | fossil_fatal("cannot find current working directory; %s", |
| 871 | strerror(errno)); |
| 872 | } |
| 873 | } |
| @@ -1384,5 +1396,44 @@ | |
| 1396 | #else |
| 1397 | FILE *f = fopen(zName, zMode); |
| 1398 | #endif |
| 1399 | return f; |
| 1400 | } |
| 1401 | |
| 1402 | /* |
| 1403 | ** Return non-NULL if zFilename contains pathname elements that |
| 1404 | ** are reserved on Windows. The returned string is the disallowed |
| 1405 | ** path element. |
| 1406 | */ |
| 1407 | const char *file_is_win_reserved(const char *zPath){ |
| 1408 | static const char *azRes[] = { "CON", "PRN", "AUX", "NUL", "COM", "LPT" }; |
| 1409 | static char zReturn[5]; |
| 1410 | int i; |
| 1411 | while( zPath[0] ){ |
| 1412 | for(i=0; i<ArraySize(azRes); i++){ |
| 1413 | if( sqlite3_strnicmp(zPath, azRes[i], 3)==0 |
| 1414 | && ((i>=4 && fossil_isdigit(zPath[3]) |
| 1415 | && (zPath[4]=='/' || zPath[4]=='.' || zPath[4]==0)) |
| 1416 | || (i<4 && (zPath[3]=='/' || zPath[3]=='.' || zPath[3]==0))) |
| 1417 | ){ |
| 1418 | sqlite3_snprintf(5,zReturn,"%.*s", i>=4 ? 4 : 3, zPath); |
| 1419 | return zReturn; |
| 1420 | } |
| 1421 | } |
| 1422 | while( zPath[0] && zPath[0]!='/' ) zPath++; |
| 1423 | while( zPath[0]=='/' ) zPath++; |
| 1424 | } |
| 1425 | return 0; |
| 1426 | } |
| 1427 | |
| 1428 | /* |
| 1429 | ** COMMAND: test-valid-for-windows |
| 1430 | ** Usage: fossil test-valid-for-windows FILENAME .... |
| 1431 | ** |
| 1432 | ** Show which filenames are not valid for Windows |
| 1433 | */ |
| 1434 | void file_test_valid_for_windows(void){ |
| 1435 | int i; |
| 1436 | for(i=2; i<g.argc; i++){ |
| 1437 | fossil_print("%s %s\n", file_is_win_reserved(g.argv[i]), g.argv[i]); |
| 1438 | } |
| 1439 | } |
| 1440 |
+1
-1
| --- src/finfo.c | ||
| +++ src/finfo.c | ||
| @@ -705,11 +705,11 @@ | ||
| 705 | 705 | int isExec = db_column_int(&q,6); |
| 706 | 706 | int isAux = db_column_int(&q,7); |
| 707 | 707 | @ <tr> |
| 708 | 708 | @ <td><a href='%R/finfo?name=%t(zName)'>%h(zName)</a></td> |
| 709 | 709 | if( zParent ){ |
| 710 | - @ <td><a href='%R/info/%!S(zPid)'>%S(zParent)</a></td> | |
| 710 | + @ <td><a href='%R/info/%!S(zParent)'>%S(zParent)</a></td> | |
| 711 | 711 | }else{ |
| 712 | 712 | @ <td><i>(New)</i></td> |
| 713 | 713 | } |
| 714 | 714 | @ <td align='center'>%s(isAux?"✓":"")</td> |
| 715 | 715 | if( zFid ){ |
| 716 | 716 |
| --- src/finfo.c | |
| +++ src/finfo.c | |
| @@ -705,11 +705,11 @@ | |
| 705 | int isExec = db_column_int(&q,6); |
| 706 | int isAux = db_column_int(&q,7); |
| 707 | @ <tr> |
| 708 | @ <td><a href='%R/finfo?name=%t(zName)'>%h(zName)</a></td> |
| 709 | if( zParent ){ |
| 710 | @ <td><a href='%R/info/%!S(zPid)'>%S(zParent)</a></td> |
| 711 | }else{ |
| 712 | @ <td><i>(New)</i></td> |
| 713 | } |
| 714 | @ <td align='center'>%s(isAux?"✓":"")</td> |
| 715 | if( zFid ){ |
| 716 |
| --- src/finfo.c | |
| +++ src/finfo.c | |
| @@ -705,11 +705,11 @@ | |
| 705 | int isExec = db_column_int(&q,6); |
| 706 | int isAux = db_column_int(&q,7); |
| 707 | @ <tr> |
| 708 | @ <td><a href='%R/finfo?name=%t(zName)'>%h(zName)</a></td> |
| 709 | if( zParent ){ |
| 710 | @ <td><a href='%R/info/%!S(zParent)'>%S(zParent)</a></td> |
| 711 | }else{ |
| 712 | @ <td><i>(New)</i></td> |
| 713 | } |
| 714 | @ <td align='center'>%s(isAux?"✓":"")</td> |
| 715 | if( zFid ){ |
| 716 |
+4
-7
| --- src/fusefs.c | ||
| +++ src/fusefs.c | ||
| @@ -20,20 +20,20 @@ | ||
| 20 | 20 | ** |
| 21 | 21 | ** This module is a mostly a no-op unless compiled with -DFOSSIL_HAVE_FUSEFS. |
| 22 | 22 | ** The FOSSIL_HAVE_FUSEFS should be omitted on systems that lack support for |
| 23 | 23 | ** the Fuse Filesystem, of course. |
| 24 | 24 | */ |
| 25 | +#ifdef FOSSIL_HAVE_FUSEFS | |
| 25 | 26 | #include "config.h" |
| 26 | 27 | #include <stdio.h> |
| 27 | 28 | #include <string.h> |
| 28 | 29 | #include <errno.h> |
| 29 | 30 | #include <fcntl.h> |
| 30 | 31 | #include <stdlib.h> |
| 31 | 32 | #include <unistd.h> |
| 32 | 33 | #include <sys/types.h> |
| 33 | 34 | #include "fusefs.h" |
| 34 | -#ifdef FOSSIL_HAVE_FUSEFS | |
| 35 | 35 | |
| 36 | 36 | #define FUSE_USE_VERSION 26 |
| 37 | 37 | #include <fuse.h> |
| 38 | 38 | |
| 39 | 39 | /* |
| @@ -207,11 +207,12 @@ | ||
| 207 | 207 | filler(buf, ".", NULL, 0); |
| 208 | 208 | filler(buf, "..", NULL, 0); |
| 209 | 209 | manifest_file_rewind(fusefs.pMan); |
| 210 | 210 | if( n==2 ){ |
| 211 | 211 | while( (pFile = manifest_file_next(fusefs.pMan, 0))!=0 ){ |
| 212 | - if( nPrev>0 && strncmp(pFile->zName, zPrev, nPrev)==0 ) continue; | |
| 212 | + if( nPrev>0 && strncmp(pFile->zName, zPrev, nPrev)==0 | |
| 213 | + && pFile->zName[nPrev]=='/' ) continue; | |
| 213 | 214 | zPrev = pFile->zName; |
| 214 | 215 | for(nPrev=0; zPrev[nPrev] && zPrev[nPrev]!='/'; nPrev++){} |
| 215 | 216 | z = mprintf("%.*s", nPrev, zPrev); |
| 216 | 217 | filler(buf, z, NULL, 0); |
| 217 | 218 | fossil_free(z); |
| @@ -282,11 +283,10 @@ | ||
| 282 | 283 | static struct fuse_operations fusefs_methods = { |
| 283 | 284 | .getattr = fusefs_getattr, |
| 284 | 285 | .readdir = fusefs_readdir, |
| 285 | 286 | .read = fusefs_read, |
| 286 | 287 | }; |
| 287 | -#endif /* FOSSIL_HAVE_FUSEFS */ | |
| 288 | 288 | |
| 289 | 289 | /* |
| 290 | 290 | ** COMMAND: fusefs |
| 291 | 291 | ** |
| 292 | 292 | ** Usage: %fossil fusefs [--debug] DIRECTORY |
| @@ -314,13 +314,10 @@ | ||
| 314 | 314 | ** After stopping the "fossil fusefs" command, it might also be necessary |
| 315 | 315 | ** to run "fusermount -u DIRECTORY" to reset the FuseFS before using it |
| 316 | 316 | ** again. |
| 317 | 317 | */ |
| 318 | 318 | void fusefs_cmd(void){ |
| 319 | -#ifndef FOSSIL_HAVE_FUSEFS | |
| 320 | - fossil_fatal("this build of fossil does not support the fuse filesystem"); | |
| 321 | -#else | |
| 322 | 319 | char *zMountPoint; |
| 323 | 320 | char *azNewArgv[5]; |
| 324 | 321 | int doDebug = find_option("debug","d",0)!=0; |
| 325 | 322 | |
| 326 | 323 | db_find_and_open_repository(0,0); |
| @@ -338,7 +335,7 @@ | ||
| 338 | 335 | azNewArgv[4] = 0; |
| 339 | 336 | g.localOpen = 0; /* Prevent tags like "current" and "prev" */ |
| 340 | 337 | fuse_main(4, azNewArgv, &fusefs_methods, NULL); |
| 341 | 338 | fusefs_reset(); |
| 342 | 339 | fusefs_clear_path(); |
| 343 | -#endif | |
| 344 | 340 | } |
| 341 | +#endif /* FOSSIL_HAVE_FUSEFS */ | |
| 345 | 342 |
| --- src/fusefs.c | |
| +++ src/fusefs.c | |
| @@ -20,20 +20,20 @@ | |
| 20 | ** |
| 21 | ** This module is a mostly a no-op unless compiled with -DFOSSIL_HAVE_FUSEFS. |
| 22 | ** The FOSSIL_HAVE_FUSEFS should be omitted on systems that lack support for |
| 23 | ** the Fuse Filesystem, of course. |
| 24 | */ |
| 25 | #include "config.h" |
| 26 | #include <stdio.h> |
| 27 | #include <string.h> |
| 28 | #include <errno.h> |
| 29 | #include <fcntl.h> |
| 30 | #include <stdlib.h> |
| 31 | #include <unistd.h> |
| 32 | #include <sys/types.h> |
| 33 | #include "fusefs.h" |
| 34 | #ifdef FOSSIL_HAVE_FUSEFS |
| 35 | |
| 36 | #define FUSE_USE_VERSION 26 |
| 37 | #include <fuse.h> |
| 38 | |
| 39 | /* |
| @@ -207,11 +207,12 @@ | |
| 207 | filler(buf, ".", NULL, 0); |
| 208 | filler(buf, "..", NULL, 0); |
| 209 | manifest_file_rewind(fusefs.pMan); |
| 210 | if( n==2 ){ |
| 211 | while( (pFile = manifest_file_next(fusefs.pMan, 0))!=0 ){ |
| 212 | if( nPrev>0 && strncmp(pFile->zName, zPrev, nPrev)==0 ) continue; |
| 213 | zPrev = pFile->zName; |
| 214 | for(nPrev=0; zPrev[nPrev] && zPrev[nPrev]!='/'; nPrev++){} |
| 215 | z = mprintf("%.*s", nPrev, zPrev); |
| 216 | filler(buf, z, NULL, 0); |
| 217 | fossil_free(z); |
| @@ -282,11 +283,10 @@ | |
| 282 | static struct fuse_operations fusefs_methods = { |
| 283 | .getattr = fusefs_getattr, |
| 284 | .readdir = fusefs_readdir, |
| 285 | .read = fusefs_read, |
| 286 | }; |
| 287 | #endif /* FOSSIL_HAVE_FUSEFS */ |
| 288 | |
| 289 | /* |
| 290 | ** COMMAND: fusefs |
| 291 | ** |
| 292 | ** Usage: %fossil fusefs [--debug] DIRECTORY |
| @@ -314,13 +314,10 @@ | |
| 314 | ** After stopping the "fossil fusefs" command, it might also be necessary |
| 315 | ** to run "fusermount -u DIRECTORY" to reset the FuseFS before using it |
| 316 | ** again. |
| 317 | */ |
| 318 | void fusefs_cmd(void){ |
| 319 | #ifndef FOSSIL_HAVE_FUSEFS |
| 320 | fossil_fatal("this build of fossil does not support the fuse filesystem"); |
| 321 | #else |
| 322 | char *zMountPoint; |
| 323 | char *azNewArgv[5]; |
| 324 | int doDebug = find_option("debug","d",0)!=0; |
| 325 | |
| 326 | db_find_and_open_repository(0,0); |
| @@ -338,7 +335,7 @@ | |
| 338 | azNewArgv[4] = 0; |
| 339 | g.localOpen = 0; /* Prevent tags like "current" and "prev" */ |
| 340 | fuse_main(4, azNewArgv, &fusefs_methods, NULL); |
| 341 | fusefs_reset(); |
| 342 | fusefs_clear_path(); |
| 343 | #endif |
| 344 | } |
| 345 |
| --- src/fusefs.c | |
| +++ src/fusefs.c | |
| @@ -20,20 +20,20 @@ | |
| 20 | ** |
| 21 | ** This module is a mostly a no-op unless compiled with -DFOSSIL_HAVE_FUSEFS. |
| 22 | ** The FOSSIL_HAVE_FUSEFS should be omitted on systems that lack support for |
| 23 | ** the Fuse Filesystem, of course. |
| 24 | */ |
| 25 | #ifdef FOSSIL_HAVE_FUSEFS |
| 26 | #include "config.h" |
| 27 | #include <stdio.h> |
| 28 | #include <string.h> |
| 29 | #include <errno.h> |
| 30 | #include <fcntl.h> |
| 31 | #include <stdlib.h> |
| 32 | #include <unistd.h> |
| 33 | #include <sys/types.h> |
| 34 | #include "fusefs.h" |
| 35 | |
| 36 | #define FUSE_USE_VERSION 26 |
| 37 | #include <fuse.h> |
| 38 | |
| 39 | /* |
| @@ -207,11 +207,12 @@ | |
| 207 | filler(buf, ".", NULL, 0); |
| 208 | filler(buf, "..", NULL, 0); |
| 209 | manifest_file_rewind(fusefs.pMan); |
| 210 | if( n==2 ){ |
| 211 | while( (pFile = manifest_file_next(fusefs.pMan, 0))!=0 ){ |
| 212 | if( nPrev>0 && strncmp(pFile->zName, zPrev, nPrev)==0 |
| 213 | && pFile->zName[nPrev]=='/' ) continue; |
| 214 | zPrev = pFile->zName; |
| 215 | for(nPrev=0; zPrev[nPrev] && zPrev[nPrev]!='/'; nPrev++){} |
| 216 | z = mprintf("%.*s", nPrev, zPrev); |
| 217 | filler(buf, z, NULL, 0); |
| 218 | fossil_free(z); |
| @@ -282,11 +283,10 @@ | |
| 283 | static struct fuse_operations fusefs_methods = { |
| 284 | .getattr = fusefs_getattr, |
| 285 | .readdir = fusefs_readdir, |
| 286 | .read = fusefs_read, |
| 287 | }; |
| 288 | |
| 289 | /* |
| 290 | ** COMMAND: fusefs |
| 291 | ** |
| 292 | ** Usage: %fossil fusefs [--debug] DIRECTORY |
| @@ -314,13 +314,10 @@ | |
| 314 | ** After stopping the "fossil fusefs" command, it might also be necessary |
| 315 | ** to run "fusermount -u DIRECTORY" to reset the FuseFS before using it |
| 316 | ** again. |
| 317 | */ |
| 318 | void fusefs_cmd(void){ |
| 319 | char *zMountPoint; |
| 320 | char *azNewArgv[5]; |
| 321 | int doDebug = find_option("debug","d",0)!=0; |
| 322 | |
| 323 | db_find_and_open_repository(0,0); |
| @@ -338,7 +335,7 @@ | |
| 335 | azNewArgv[4] = 0; |
| 336 | g.localOpen = 0; /* Prevent tags like "current" and "prev" */ |
| 337 | fuse_main(4, azNewArgv, &fusefs_methods, NULL); |
| 338 | fusefs_reset(); |
| 339 | fusefs_clear_path(); |
| 340 | } |
| 341 | #endif /* FOSSIL_HAVE_FUSEFS */ |
| 342 |
+19
-4
| --- src/graph.c | ||
| +++ src/graph.c | ||
| @@ -258,11 +258,10 @@ | ||
| 258 | 258 | int iRail = pBottom->iRail; |
| 259 | 259 | GraphRow *pCurrent; |
| 260 | 260 | GraphRow *pPrior; |
| 261 | 261 | u64 mask = ((u64)1)<<iRail; |
| 262 | 262 | |
| 263 | - pBottom->iRail = iRail; | |
| 264 | 263 | pBottom->railInUse |= mask; |
| 265 | 264 | pPrior = pBottom; |
| 266 | 265 | for(pCurrent=pBottom->pChild; pCurrent; pCurrent=pCurrent->pChild){ |
| 267 | 266 | assert( pPrior->idx > pCurrent->idx ); |
| 268 | 267 | assert( pCurrent->iRail<0 ); |
| @@ -344,14 +343,16 @@ | ||
| 344 | 343 | /* |
| 345 | 344 | ** Compute the complete graph |
| 346 | 345 | */ |
| 347 | 346 | void graph_finish(GraphContext *p, int omitDescenders){ |
| 348 | 347 | GraphRow *pRow, *pDesc, *pDup, *pLoop, *pParent; |
| 349 | - int i; | |
| 348 | + int i, j; | |
| 350 | 349 | u64 mask; |
| 351 | 350 | int hasDup = 0; /* True if one or more isDup entries */ |
| 352 | 351 | const char *zTrunk; |
| 352 | + int railRid[GR_MAX_RAIL]; /* Maps rails to rids for lines | |
| 353 | + that enter from bottom of screen */ | |
| 353 | 354 | |
| 354 | 355 | if( p==0 || p->pFirst==0 || p->nErr ) return; |
| 355 | 356 | p->nErr = 1; /* Assume an error until proven otherwise */ |
| 356 | 357 | |
| 357 | 358 | /* Initialize all rows */ |
| @@ -366,10 +367,11 @@ | ||
| 366 | 367 | pDup->isDup = 1; |
| 367 | 368 | } |
| 368 | 369 | hashInsert(p, pRow, 1); |
| 369 | 370 | } |
| 370 | 371 | p->mxRail = -1; |
| 372 | + memset(railRid, 0, sizeof(railRid)); | |
| 371 | 373 | |
| 372 | 374 | /* Purge merge-parents that are out-of-graph if descenders are not |
| 373 | 375 | ** drawn. |
| 374 | 376 | ** |
| 375 | 377 | ** Each node has one primary parent and zero or more "merge" parents. |
| @@ -458,10 +460,13 @@ | ||
| 458 | 460 | } |
| 459 | 461 | if( p->mxRail>=GR_MAX_RAIL ) return; |
| 460 | 462 | mask = BIT(pRow->iRail); |
| 461 | 463 | if( !omitDescenders ){ |
| 462 | 464 | pRow->bDescender = pRow->nParent>0; |
| 465 | + if( pRow->bDescender ){ | |
| 466 | + railRid[pRow->iRail] = pRow->aParent[0]; | |
| 467 | + } | |
| 463 | 468 | for(pLoop=pRow; pLoop; pLoop=pLoop->pNext){ |
| 464 | 469 | pLoop->railInUse |= mask; |
| 465 | 470 | } |
| 466 | 471 | } |
| 467 | 472 | assignChildrenToRail(pRow); |
| @@ -536,12 +541,22 @@ | ||
| 536 | 541 | for(i=1; i<pRow->nParent; i++){ |
| 537 | 542 | int parentRid = pRow->aParent[i]; |
| 538 | 543 | pDesc = hashFind(p, parentRid); |
| 539 | 544 | if( pDesc==0 ){ |
| 540 | 545 | /* Merge from a node that is off-screen */ |
| 541 | - int iMrail = findFreeRail(p, pRow->idx, p->nRow, 0); | |
| 542 | - if( p->mxRail>=GR_MAX_RAIL ) return; | |
| 546 | + int iMrail = -1; | |
| 547 | + for(j=0; j<GR_MAX_RAIL; j++){ | |
| 548 | + if( railRid[j]==parentRid ){ | |
| 549 | + iMrail = j; | |
| 550 | + break; | |
| 551 | + } | |
| 552 | + } | |
| 553 | + if( iMrail==-1 ){ | |
| 554 | + iMrail = findFreeRail(p, pRow->idx, p->nRow, 0); | |
| 555 | + if( p->mxRail>=GR_MAX_RAIL ) return; | |
| 556 | + railRid[iMrail] = parentRid; | |
| 557 | + } | |
| 543 | 558 | mask = BIT(iMrail); |
| 544 | 559 | pRow->mergeIn[iMrail] = 1; |
| 545 | 560 | pRow->mergeDown |= mask; |
| 546 | 561 | for(pLoop=pRow->pNext; pLoop; pLoop=pLoop->pNext){ |
| 547 | 562 | pLoop->railInUse |= mask; |
| 548 | 563 |
| --- src/graph.c | |
| +++ src/graph.c | |
| @@ -258,11 +258,10 @@ | |
| 258 | int iRail = pBottom->iRail; |
| 259 | GraphRow *pCurrent; |
| 260 | GraphRow *pPrior; |
| 261 | u64 mask = ((u64)1)<<iRail; |
| 262 | |
| 263 | pBottom->iRail = iRail; |
| 264 | pBottom->railInUse |= mask; |
| 265 | pPrior = pBottom; |
| 266 | for(pCurrent=pBottom->pChild; pCurrent; pCurrent=pCurrent->pChild){ |
| 267 | assert( pPrior->idx > pCurrent->idx ); |
| 268 | assert( pCurrent->iRail<0 ); |
| @@ -344,14 +343,16 @@ | |
| 344 | /* |
| 345 | ** Compute the complete graph |
| 346 | */ |
| 347 | void graph_finish(GraphContext *p, int omitDescenders){ |
| 348 | GraphRow *pRow, *pDesc, *pDup, *pLoop, *pParent; |
| 349 | int i; |
| 350 | u64 mask; |
| 351 | int hasDup = 0; /* True if one or more isDup entries */ |
| 352 | const char *zTrunk; |
| 353 | |
| 354 | if( p==0 || p->pFirst==0 || p->nErr ) return; |
| 355 | p->nErr = 1; /* Assume an error until proven otherwise */ |
| 356 | |
| 357 | /* Initialize all rows */ |
| @@ -366,10 +367,11 @@ | |
| 366 | pDup->isDup = 1; |
| 367 | } |
| 368 | hashInsert(p, pRow, 1); |
| 369 | } |
| 370 | p->mxRail = -1; |
| 371 | |
| 372 | /* Purge merge-parents that are out-of-graph if descenders are not |
| 373 | ** drawn. |
| 374 | ** |
| 375 | ** Each node has one primary parent and zero or more "merge" parents. |
| @@ -458,10 +460,13 @@ | |
| 458 | } |
| 459 | if( p->mxRail>=GR_MAX_RAIL ) return; |
| 460 | mask = BIT(pRow->iRail); |
| 461 | if( !omitDescenders ){ |
| 462 | pRow->bDescender = pRow->nParent>0; |
| 463 | for(pLoop=pRow; pLoop; pLoop=pLoop->pNext){ |
| 464 | pLoop->railInUse |= mask; |
| 465 | } |
| 466 | } |
| 467 | assignChildrenToRail(pRow); |
| @@ -536,12 +541,22 @@ | |
| 536 | for(i=1; i<pRow->nParent; i++){ |
| 537 | int parentRid = pRow->aParent[i]; |
| 538 | pDesc = hashFind(p, parentRid); |
| 539 | if( pDesc==0 ){ |
| 540 | /* Merge from a node that is off-screen */ |
| 541 | int iMrail = findFreeRail(p, pRow->idx, p->nRow, 0); |
| 542 | if( p->mxRail>=GR_MAX_RAIL ) return; |
| 543 | mask = BIT(iMrail); |
| 544 | pRow->mergeIn[iMrail] = 1; |
| 545 | pRow->mergeDown |= mask; |
| 546 | for(pLoop=pRow->pNext; pLoop; pLoop=pLoop->pNext){ |
| 547 | pLoop->railInUse |= mask; |
| 548 |
| --- src/graph.c | |
| +++ src/graph.c | |
| @@ -258,11 +258,10 @@ | |
| 258 | int iRail = pBottom->iRail; |
| 259 | GraphRow *pCurrent; |
| 260 | GraphRow *pPrior; |
| 261 | u64 mask = ((u64)1)<<iRail; |
| 262 | |
| 263 | pBottom->railInUse |= mask; |
| 264 | pPrior = pBottom; |
| 265 | for(pCurrent=pBottom->pChild; pCurrent; pCurrent=pCurrent->pChild){ |
| 266 | assert( pPrior->idx > pCurrent->idx ); |
| 267 | assert( pCurrent->iRail<0 ); |
| @@ -344,14 +343,16 @@ | |
| 343 | /* |
| 344 | ** Compute the complete graph |
| 345 | */ |
| 346 | void graph_finish(GraphContext *p, int omitDescenders){ |
| 347 | GraphRow *pRow, *pDesc, *pDup, *pLoop, *pParent; |
| 348 | int i, j; |
| 349 | u64 mask; |
| 350 | int hasDup = 0; /* True if one or more isDup entries */ |
| 351 | const char *zTrunk; |
| 352 | int railRid[GR_MAX_RAIL]; /* Maps rails to rids for lines |
| 353 | that enter from bottom of screen */ |
| 354 | |
| 355 | if( p==0 || p->pFirst==0 || p->nErr ) return; |
| 356 | p->nErr = 1; /* Assume an error until proven otherwise */ |
| 357 | |
| 358 | /* Initialize all rows */ |
| @@ -366,10 +367,11 @@ | |
| 367 | pDup->isDup = 1; |
| 368 | } |
| 369 | hashInsert(p, pRow, 1); |
| 370 | } |
| 371 | p->mxRail = -1; |
| 372 | memset(railRid, 0, sizeof(railRid)); |
| 373 | |
| 374 | /* Purge merge-parents that are out-of-graph if descenders are not |
| 375 | ** drawn. |
| 376 | ** |
| 377 | ** Each node has one primary parent and zero or more "merge" parents. |
| @@ -458,10 +460,13 @@ | |
| 460 | } |
| 461 | if( p->mxRail>=GR_MAX_RAIL ) return; |
| 462 | mask = BIT(pRow->iRail); |
| 463 | if( !omitDescenders ){ |
| 464 | pRow->bDescender = pRow->nParent>0; |
| 465 | if( pRow->bDescender ){ |
| 466 | railRid[pRow->iRail] = pRow->aParent[0]; |
| 467 | } |
| 468 | for(pLoop=pRow; pLoop; pLoop=pLoop->pNext){ |
| 469 | pLoop->railInUse |= mask; |
| 470 | } |
| 471 | } |
| 472 | assignChildrenToRail(pRow); |
| @@ -536,12 +541,22 @@ | |
| 541 | for(i=1; i<pRow->nParent; i++){ |
| 542 | int parentRid = pRow->aParent[i]; |
| 543 | pDesc = hashFind(p, parentRid); |
| 544 | if( pDesc==0 ){ |
| 545 | /* Merge from a node that is off-screen */ |
| 546 | int iMrail = -1; |
| 547 | for(j=0; j<GR_MAX_RAIL; j++){ |
| 548 | if( railRid[j]==parentRid ){ |
| 549 | iMrail = j; |
| 550 | break; |
| 551 | } |
| 552 | } |
| 553 | if( iMrail==-1 ){ |
| 554 | iMrail = findFreeRail(p, pRow->idx, p->nRow, 0); |
| 555 | if( p->mxRail>=GR_MAX_RAIL ) return; |
| 556 | railRid[iMrail] = parentRid; |
| 557 | } |
| 558 | mask = BIT(iMrail); |
| 559 | pRow->mergeIn[iMrail] = 1; |
| 560 | pRow->mergeDown |= mask; |
| 561 | for(pLoop=pRow->pNext; pLoop; pLoop=pLoop->pNext){ |
| 562 | pLoop->railInUse |= mask; |
| 563 |
+8
-7
| --- src/import.c | ||
| +++ src/import.c | ||
| @@ -1761,21 +1761,22 @@ | ||
| 1761 | 1761 | ** times but only the last tag should be used. And we do not know which |
| 1762 | 1762 | ** occurrence of the tag is the last until the import finishes. |
| 1763 | 1763 | */ |
| 1764 | 1764 | db_multi_exec( |
| 1765 | 1765 | "CREATE TEMP TABLE xmark(tname TEXT UNIQUE, trid INT, tuuid TEXT);" |
| 1766 | + "CREATE INDEX temp.i_xmark ON xmark(trid);" | |
| 1766 | 1767 | "CREATE TEMP TABLE xbranch(tname TEXT UNIQUE, brnm TEXT);" |
| 1767 | 1768 | "CREATE TEMP TABLE xtag(tname TEXT UNIQUE, tcontent TEXT);" |
| 1768 | 1769 | ); |
| 1769 | 1770 | |
| 1770 | 1771 | if( markfile_in ){ |
| 1771 | 1772 | FILE *f = fossil_fopen(markfile_in, "r"); |
| 1772 | 1773 | if( !f ){ |
| 1773 | - fossil_fatal("cannot open %s for reading\n", markfile_in); | |
| 1774 | + fossil_fatal("cannot open %s for reading", markfile_in); | |
| 1774 | 1775 | } |
| 1775 | - if(import_marks(f, &blobs, NULL)<0){ | |
| 1776 | - fossil_fatal("error importing marks from file: %s\n", markfile_in); | |
| 1776 | + if( import_marks(f, &blobs, NULL, NULL)<0 ){ | |
| 1777 | + fossil_fatal("error importing marks from file: %s", markfile_in); | |
| 1777 | 1778 | } |
| 1778 | 1779 | fclose(f); |
| 1779 | 1780 | } |
| 1780 | 1781 | |
| 1781 | 1782 | manifest_crosslink_begin(); |
| @@ -1795,21 +1796,21 @@ | ||
| 1795 | 1796 | db_prepare(&q_marks, "SELECT DISTINCT trid FROM xmark"); |
| 1796 | 1797 | while( db_step(&q_marks)==SQLITE_ROW ){ |
| 1797 | 1798 | rid = db_column_int(&q_marks, 0); |
| 1798 | 1799 | if( db_int(0, "SELECT count(objid) FROM event" |
| 1799 | 1800 | " WHERE objid=%d AND type='ci'", rid)==0 ){ |
| 1800 | - if( bag_find(&blobs, rid)==0 ){ | |
| 1801 | - bag_insert(&blobs, rid); | |
| 1802 | - } | |
| 1801 | + /* Blob marks exported by git aren't saved between runs, so they need | |
| 1802 | + ** to be left free for git to re-use in the future. | |
| 1803 | + */ | |
| 1803 | 1804 | }else{ |
| 1804 | 1805 | bag_insert(&vers, rid); |
| 1805 | 1806 | } |
| 1806 | 1807 | } |
| 1807 | 1808 | db_finalize(&q_marks); |
| 1808 | 1809 | f = fossil_fopen(markfile_out, "w"); |
| 1809 | 1810 | if( !f ){ |
| 1810 | - fossil_fatal("cannot open %s for writing\n", markfile_out); | |
| 1811 | + fossil_fatal("cannot open %s for writing", markfile_out); | |
| 1811 | 1812 | } |
| 1812 | 1813 | export_marks(f, &blobs, &vers); |
| 1813 | 1814 | fclose(f); |
| 1814 | 1815 | bag_clear(&blobs); |
| 1815 | 1816 | bag_clear(&vers); |
| 1816 | 1817 |
| --- src/import.c | |
| +++ src/import.c | |
| @@ -1761,21 +1761,22 @@ | |
| 1761 | ** times but only the last tag should be used. And we do not know which |
| 1762 | ** occurrence of the tag is the last until the import finishes. |
| 1763 | */ |
| 1764 | db_multi_exec( |
| 1765 | "CREATE TEMP TABLE xmark(tname TEXT UNIQUE, trid INT, tuuid TEXT);" |
| 1766 | "CREATE TEMP TABLE xbranch(tname TEXT UNIQUE, brnm TEXT);" |
| 1767 | "CREATE TEMP TABLE xtag(tname TEXT UNIQUE, tcontent TEXT);" |
| 1768 | ); |
| 1769 | |
| 1770 | if( markfile_in ){ |
| 1771 | FILE *f = fossil_fopen(markfile_in, "r"); |
| 1772 | if( !f ){ |
| 1773 | fossil_fatal("cannot open %s for reading\n", markfile_in); |
| 1774 | } |
| 1775 | if(import_marks(f, &blobs, NULL)<0){ |
| 1776 | fossil_fatal("error importing marks from file: %s\n", markfile_in); |
| 1777 | } |
| 1778 | fclose(f); |
| 1779 | } |
| 1780 | |
| 1781 | manifest_crosslink_begin(); |
| @@ -1795,21 +1796,21 @@ | |
| 1795 | db_prepare(&q_marks, "SELECT DISTINCT trid FROM xmark"); |
| 1796 | while( db_step(&q_marks)==SQLITE_ROW ){ |
| 1797 | rid = db_column_int(&q_marks, 0); |
| 1798 | if( db_int(0, "SELECT count(objid) FROM event" |
| 1799 | " WHERE objid=%d AND type='ci'", rid)==0 ){ |
| 1800 | if( bag_find(&blobs, rid)==0 ){ |
| 1801 | bag_insert(&blobs, rid); |
| 1802 | } |
| 1803 | }else{ |
| 1804 | bag_insert(&vers, rid); |
| 1805 | } |
| 1806 | } |
| 1807 | db_finalize(&q_marks); |
| 1808 | f = fossil_fopen(markfile_out, "w"); |
| 1809 | if( !f ){ |
| 1810 | fossil_fatal("cannot open %s for writing\n", markfile_out); |
| 1811 | } |
| 1812 | export_marks(f, &blobs, &vers); |
| 1813 | fclose(f); |
| 1814 | bag_clear(&blobs); |
| 1815 | bag_clear(&vers); |
| 1816 |
| --- src/import.c | |
| +++ src/import.c | |
| @@ -1761,21 +1761,22 @@ | |
| 1761 | ** times but only the last tag should be used. And we do not know which |
| 1762 | ** occurrence of the tag is the last until the import finishes. |
| 1763 | */ |
| 1764 | db_multi_exec( |
| 1765 | "CREATE TEMP TABLE xmark(tname TEXT UNIQUE, trid INT, tuuid TEXT);" |
| 1766 | "CREATE INDEX temp.i_xmark ON xmark(trid);" |
| 1767 | "CREATE TEMP TABLE xbranch(tname TEXT UNIQUE, brnm TEXT);" |
| 1768 | "CREATE TEMP TABLE xtag(tname TEXT UNIQUE, tcontent TEXT);" |
| 1769 | ); |
| 1770 | |
| 1771 | if( markfile_in ){ |
| 1772 | FILE *f = fossil_fopen(markfile_in, "r"); |
| 1773 | if( !f ){ |
| 1774 | fossil_fatal("cannot open %s for reading", markfile_in); |
| 1775 | } |
| 1776 | if( import_marks(f, &blobs, NULL, NULL)<0 ){ |
| 1777 | fossil_fatal("error importing marks from file: %s", markfile_in); |
| 1778 | } |
| 1779 | fclose(f); |
| 1780 | } |
| 1781 | |
| 1782 | manifest_crosslink_begin(); |
| @@ -1795,21 +1796,21 @@ | |
| 1796 | db_prepare(&q_marks, "SELECT DISTINCT trid FROM xmark"); |
| 1797 | while( db_step(&q_marks)==SQLITE_ROW ){ |
| 1798 | rid = db_column_int(&q_marks, 0); |
| 1799 | if( db_int(0, "SELECT count(objid) FROM event" |
| 1800 | " WHERE objid=%d AND type='ci'", rid)==0 ){ |
| 1801 | /* Blob marks exported by git aren't saved between runs, so they need |
| 1802 | ** to be left free for git to re-use in the future. |
| 1803 | */ |
| 1804 | }else{ |
| 1805 | bag_insert(&vers, rid); |
| 1806 | } |
| 1807 | } |
| 1808 | db_finalize(&q_marks); |
| 1809 | f = fossil_fopen(markfile_out, "w"); |
| 1810 | if( !f ){ |
| 1811 | fossil_fatal("cannot open %s for writing", markfile_out); |
| 1812 | } |
| 1813 | export_marks(f, &blobs, &vers); |
| 1814 | fclose(f); |
| 1815 | bag_clear(&blobs); |
| 1816 | bag_clear(&vers); |
| 1817 |
+1
-1
| --- src/info.c | ||
| +++ src/info.c | ||
| @@ -231,11 +231,11 @@ | ||
| 231 | 231 | db_int(-1, "SELECT count(*) FROM event WHERE type='ci' /*scan*/")); |
| 232 | 232 | }else{ |
| 233 | 233 | int rid; |
| 234 | 234 | rid = name_to_rid(g.argv[2]); |
| 235 | 235 | if( rid==0 ){ |
| 236 | - fossil_fatal("no such object: %s\n", g.argv[2]); | |
| 236 | + fossil_fatal("no such object: %s", g.argv[2]); | |
| 237 | 237 | } |
| 238 | 238 | show_common_info(rid, "uuid:", 1, 1); |
| 239 | 239 | } |
| 240 | 240 | } |
| 241 | 241 | |
| 242 | 242 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -231,11 +231,11 @@ | |
| 231 | db_int(-1, "SELECT count(*) FROM event WHERE type='ci' /*scan*/")); |
| 232 | }else{ |
| 233 | int rid; |
| 234 | rid = name_to_rid(g.argv[2]); |
| 235 | if( rid==0 ){ |
| 236 | fossil_fatal("no such object: %s\n", g.argv[2]); |
| 237 | } |
| 238 | show_common_info(rid, "uuid:", 1, 1); |
| 239 | } |
| 240 | } |
| 241 | |
| 242 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -231,11 +231,11 @@ | |
| 231 | db_int(-1, "SELECT count(*) FROM event WHERE type='ci' /*scan*/")); |
| 232 | }else{ |
| 233 | int rid; |
| 234 | rid = name_to_rid(g.argv[2]); |
| 235 | if( rid==0 ){ |
| 236 | fossil_fatal("no such object: %s", g.argv[2]); |
| 237 | } |
| 238 | show_common_info(rid, "uuid:", 1, 1); |
| 239 | } |
| 240 | } |
| 241 | |
| 242 |
+1
-1
| --- src/json_branch.c | ||
| +++ src/json_branch.c | ||
| @@ -292,11 +292,11 @@ | ||
| 292 | 292 | if( brid==0 ){ |
| 293 | 293 | fossil_fatal("Problem committing manifest: %s", g.zErrMsg); |
| 294 | 294 | } |
| 295 | 295 | db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", brid); |
| 296 | 296 | if( manifest_crosslink(brid, &branch, MC_PERMIT_HOOKS)==0 ){ |
| 297 | - fossil_fatal("%s\n", g.zErrMsg); | |
| 297 | + fossil_fatal("%s", g.zErrMsg); | |
| 298 | 298 | } |
| 299 | 299 | assert( blob_is_reset(&branch) ); |
| 300 | 300 | content_deltify(rootid, brid, 0); |
| 301 | 301 | if( zNewRid ){ |
| 302 | 302 | *zNewRid = brid; |
| 303 | 303 |
| --- src/json_branch.c | |
| +++ src/json_branch.c | |
| @@ -292,11 +292,11 @@ | |
| 292 | if( brid==0 ){ |
| 293 | fossil_fatal("Problem committing manifest: %s", g.zErrMsg); |
| 294 | } |
| 295 | db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", brid); |
| 296 | if( manifest_crosslink(brid, &branch, MC_PERMIT_HOOKS)==0 ){ |
| 297 | fossil_fatal("%s\n", g.zErrMsg); |
| 298 | } |
| 299 | assert( blob_is_reset(&branch) ); |
| 300 | content_deltify(rootid, brid, 0); |
| 301 | if( zNewRid ){ |
| 302 | *zNewRid = brid; |
| 303 |
| --- src/json_branch.c | |
| +++ src/json_branch.c | |
| @@ -292,11 +292,11 @@ | |
| 292 | if( brid==0 ){ |
| 293 | fossil_fatal("Problem committing manifest: %s", g.zErrMsg); |
| 294 | } |
| 295 | db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", brid); |
| 296 | if( manifest_crosslink(brid, &branch, MC_PERMIT_HOOKS)==0 ){ |
| 297 | fossil_fatal("%s", g.zErrMsg); |
| 298 | } |
| 299 | assert( blob_is_reset(&branch) ); |
| 300 | content_deltify(rootid, brid, 0); |
| 301 | if( zNewRid ){ |
| 302 | *zNewRid = brid; |
| 303 |
+19
-1
| --- src/json_wiki.c | ||
| +++ src/json_wiki.c | ||
| @@ -115,12 +115,30 @@ | ||
| 115 | 115 | if( contentFormat>0 ){/*HTML-ize it*/ |
| 116 | 116 | Blob content = empty_blob; |
| 117 | 117 | Blob raw = empty_blob; |
| 118 | 118 | zFormat = "html"; |
| 119 | 119 | if(zBody && *zBody){ |
| 120 | + const char *zMimetype = pWiki->zMimetype; | |
| 121 | + if( zMimetype==0 ) zMimetype = "text/plain"; | |
| 122 | + zMimetype = wiki_filter_mimetypes(zMimetype); | |
| 120 | 123 | blob_append(&raw,zBody,-1); |
| 121 | - wiki_convert(&raw,&content,0); | |
| 124 | + if( fossil_strcmp(zMimetype, "text/x-fossil-wiki")==0 ){ | |
| 125 | + wiki_convert(&raw,&content,0); | |
| 126 | + }else if( fossil_strcmp(zMimetype, "text/x-markdown")==0 ){ | |
| 127 | + markdown_to_html(&raw,0,&content); | |
| 128 | + }else if( fossil_strcmp(zMimetype, "text/plain")==0 ){ | |
| 129 | + htmlize_to_blob(&content,blob_str(&raw),blob_size(&raw)); | |
| 130 | + }else{ | |
| 131 | + json_set_err( FSL_JSON_E_UNKNOWN, | |
| 132 | + "Unsupported MIME type '%s' for wiki page '%s'.", | |
| 133 | + zMimetype, pWiki->zWikiTitle ); | |
| 134 | + blob_reset(&content); | |
| 135 | + blob_reset(&raw); | |
| 136 | + cson_free_object(pay); | |
| 137 | + manifest_destroy(pWiki); | |
| 138 | + return NULL; | |
| 139 | + } | |
| 122 | 140 | len = (unsigned int)blob_size(&content); |
| 123 | 141 | } |
| 124 | 142 | cson_object_set(pay,"size",json_new_int((cson_int_t)len)); |
| 125 | 143 | cson_object_set(pay,"content", |
| 126 | 144 | cson_value_new_string(blob_buffer(&content),len)); |
| 127 | 145 |
| --- src/json_wiki.c | |
| +++ src/json_wiki.c | |
| @@ -115,12 +115,30 @@ | |
| 115 | if( contentFormat>0 ){/*HTML-ize it*/ |
| 116 | Blob content = empty_blob; |
| 117 | Blob raw = empty_blob; |
| 118 | zFormat = "html"; |
| 119 | if(zBody && *zBody){ |
| 120 | blob_append(&raw,zBody,-1); |
| 121 | wiki_convert(&raw,&content,0); |
| 122 | len = (unsigned int)blob_size(&content); |
| 123 | } |
| 124 | cson_object_set(pay,"size",json_new_int((cson_int_t)len)); |
| 125 | cson_object_set(pay,"content", |
| 126 | cson_value_new_string(blob_buffer(&content),len)); |
| 127 |
| --- src/json_wiki.c | |
| +++ src/json_wiki.c | |
| @@ -115,12 +115,30 @@ | |
| 115 | if( contentFormat>0 ){/*HTML-ize it*/ |
| 116 | Blob content = empty_blob; |
| 117 | Blob raw = empty_blob; |
| 118 | zFormat = "html"; |
| 119 | if(zBody && *zBody){ |
| 120 | const char *zMimetype = pWiki->zMimetype; |
| 121 | if( zMimetype==0 ) zMimetype = "text/plain"; |
| 122 | zMimetype = wiki_filter_mimetypes(zMimetype); |
| 123 | blob_append(&raw,zBody,-1); |
| 124 | if( fossil_strcmp(zMimetype, "text/x-fossil-wiki")==0 ){ |
| 125 | wiki_convert(&raw,&content,0); |
| 126 | }else if( fossil_strcmp(zMimetype, "text/x-markdown")==0 ){ |
| 127 | markdown_to_html(&raw,0,&content); |
| 128 | }else if( fossil_strcmp(zMimetype, "text/plain")==0 ){ |
| 129 | htmlize_to_blob(&content,blob_str(&raw),blob_size(&raw)); |
| 130 | }else{ |
| 131 | json_set_err( FSL_JSON_E_UNKNOWN, |
| 132 | "Unsupported MIME type '%s' for wiki page '%s'.", |
| 133 | zMimetype, pWiki->zWikiTitle ); |
| 134 | blob_reset(&content); |
| 135 | blob_reset(&raw); |
| 136 | cson_free_object(pay); |
| 137 | manifest_destroy(pWiki); |
| 138 | return NULL; |
| 139 | } |
| 140 | len = (unsigned int)blob_size(&content); |
| 141 | } |
| 142 | cson_object_set(pay,"size",json_new_int((cson_int_t)len)); |
| 143 | cson_object_set(pay,"content", |
| 144 | cson_value_new_string(blob_buffer(&content),len)); |
| 145 |
+79
-4
| --- src/main.c | ||
| +++ src/main.c | ||
| @@ -18,20 +18,21 @@ | ||
| 18 | 18 | ** This module codes the main() procedure that runs first when the |
| 19 | 19 | ** program is invoked. |
| 20 | 20 | */ |
| 21 | 21 | #include "VERSION.h" |
| 22 | 22 | #include "config.h" |
| 23 | +#if defined(_WIN32) | |
| 24 | +# include <windows.h> | |
| 25 | +#endif | |
| 23 | 26 | #include "main.h" |
| 24 | 27 | #include <string.h> |
| 25 | 28 | #include <time.h> |
| 26 | 29 | #include <fcntl.h> |
| 27 | 30 | #include <sys/types.h> |
| 28 | 31 | #include <sys/stat.h> |
| 29 | 32 | #include <stdlib.h> /* atexit() */ |
| 30 | -#if defined(_WIN32) | |
| 31 | -# include <windows.h> | |
| 32 | -#else | |
| 33 | +#if !defined(_WIN32) | |
| 33 | 34 | # include <errno.h> /* errno global */ |
| 34 | 35 | #endif |
| 35 | 36 | #ifdef FOSSIL_ENABLE_SSL |
| 36 | 37 | # include "openssl/crypto.h" |
| 37 | 38 | #endif |
| @@ -299,10 +300,22 @@ | ||
| 299 | 300 | /* |
| 300 | 301 | ** atexit() handler which frees up "some" of the resources |
| 301 | 302 | ** used by fossil. |
| 302 | 303 | */ |
| 303 | 304 | static void fossil_atexit(void) { |
| 305 | +#if USE_SEE | |
| 306 | + /* | |
| 307 | + ** Zero, unlock, and free the saved database encryption key now. | |
| 308 | + */ | |
| 309 | + db_unsave_encryption_key(); | |
| 310 | +#endif | |
| 311 | +#if defined(_WIN32) || defined(__BIONIC__) | |
| 312 | + /* | |
| 313 | + ** Free the secure getpass() buffer now. | |
| 314 | + */ | |
| 315 | + freepass(); | |
| 316 | +#endif | |
| 304 | 317 | #if defined(_WIN32) && !defined(_WIN64) && defined(FOSSIL_ENABLE_TCL) && \ |
| 305 | 318 | defined(USE_TCL_STUBS) |
| 306 | 319 | /* |
| 307 | 320 | ** If Tcl is compiled on Windows using the latest MinGW, Fossil can crash |
| 308 | 321 | ** when exiting while a stubs-enabled Tcl is still loaded. This is due to |
| @@ -1917,10 +1930,41 @@ | ||
| 1917 | 1930 | } |
| 1918 | 1931 | } |
| 1919 | 1932 | } |
| 1920 | 1933 | } |
| 1921 | 1934 | |
| 1935 | +#if defined(_WIN32) && USE_SEE | |
| 1936 | +/* | |
| 1937 | +** This function attempts to parse a string value in the following | |
| 1938 | +** format: | |
| 1939 | +** | |
| 1940 | +** "%lu:%p:%u" | |
| 1941 | +** | |
| 1942 | +** There are three parts, which must be delimited by colons. The | |
| 1943 | +** first part is an unsigned long integer in base-10 (decimal) format. | |
| 1944 | +** The second part is a numerical representation of a native pointer, | |
| 1945 | +** in the appropriate implementation defined format. The third part | |
| 1946 | +** is an unsigned integer in base-10 (decimal) format. | |
| 1947 | +** | |
| 1948 | +** If the specified value cannot be parsed, for any reason, a fatal | |
| 1949 | +** error will be raised and the process will be terminated. | |
| 1950 | +*/ | |
| 1951 | +void parse_pid_key_value( | |
| 1952 | + const char *zPidKey, /* The value to be parsed. */ | |
| 1953 | + DWORD *pProcessId, /* The extracted process identifier. */ | |
| 1954 | + LPVOID *ppAddress, /* The extracted pointer value. */ | |
| 1955 | + SIZE_T *pnSize /* The extracted size value. */ | |
| 1956 | +){ | |
| 1957 | + unsigned int nSize = 0; | |
| 1958 | + if( sscanf(zPidKey, "%lu:%p:%u", pProcessId, ppAddress, &nSize)==3 ){ | |
| 1959 | + *pnSize = (SIZE_T)nSize; | |
| 1960 | + }else{ | |
| 1961 | + fossil_fatal("failed to parse pid key"); | |
| 1962 | + } | |
| 1963 | +} | |
| 1964 | +#endif | |
| 1965 | + | |
| 1922 | 1966 | /* |
| 1923 | 1967 | ** undocumented format: |
| 1924 | 1968 | ** |
| 1925 | 1969 | ** fossil http INFILE OUTFILE IPADDR ?REPOSITORY? |
| 1926 | 1970 | ** |
| @@ -1968,10 +2012,12 @@ | ||
| 1968 | 2012 | ** --notfound URL use URL as "HTTP 404, object not found" page. |
| 1969 | 2013 | ** --repolist If REPOSITORY is directory, URL "/" lists all repos |
| 1970 | 2014 | ** --scgi Interpret input as SCGI rather than HTTP |
| 1971 | 2015 | ** --skin LABEL Use override skin LABEL |
| 1972 | 2016 | ** --th-trace trace TH1 execution (for debugging purposes) |
| 2017 | +** --usepidkey Use saved encryption key from parent process. This is | |
| 2018 | +** only necessary when using SEE on Windows. | |
| 1973 | 2019 | ** |
| 1974 | 2020 | ** See also: cgi, server, winsrv |
| 1975 | 2021 | */ |
| 1976 | 2022 | void cmd_http(void){ |
| 1977 | 2023 | const char *zIpAddr = 0; |
| @@ -1980,10 +2026,13 @@ | ||
| 1980 | 2026 | const char *zAltBase; |
| 1981 | 2027 | const char *zFileGlob; |
| 1982 | 2028 | int useSCGI; |
| 1983 | 2029 | int noJail; |
| 1984 | 2030 | int allowRepoList; |
| 2031 | +#if defined(_WIN32) && USE_SEE | |
| 2032 | + const char *zPidKey; | |
| 2033 | +#endif | |
| 1985 | 2034 | |
| 1986 | 2035 | Th_InitTraceLog(); |
| 1987 | 2036 | |
| 1988 | 2037 | /* The winhttp module passes the --files option as --files-urlenc with |
| 1989 | 2038 | ** the argument being URL encoded, to avoid wildcard expansion in the |
| @@ -2010,10 +2059,21 @@ | ||
| 2010 | 2059 | zIpAddr = fossil_getenv("REMOTE_HOST"); /* From stunnel */ |
| 2011 | 2060 | cgi_replace_parameter("HTTPS","on"); |
| 2012 | 2061 | } |
| 2013 | 2062 | zHost = find_option("host", 0, 1); |
| 2014 | 2063 | if( zHost ) cgi_replace_parameter("HTTP_HOST",zHost); |
| 2064 | + | |
| 2065 | +#if defined(_WIN32) && USE_SEE | |
| 2066 | + zPidKey = find_option("usepidkey", 0, 1); | |
| 2067 | + if( zPidKey ){ | |
| 2068 | + DWORD processId = 0; | |
| 2069 | + LPVOID pAddress = NULL; | |
| 2070 | + SIZE_T nSize = 0; | |
| 2071 | + parse_pid_key_value(zPidKey, &processId, &pAddress, &nSize); | |
| 2072 | + db_read_saved_encryption_key_from_process(processId, pAddress, nSize); | |
| 2073 | + } | |
| 2074 | +#endif | |
| 2015 | 2075 | |
| 2016 | 2076 | /* We should be done with options.. */ |
| 2017 | 2077 | verify_all_options(); |
| 2018 | 2078 | |
| 2019 | 2079 | if( g.argc!=2 && g.argc!=3 && g.argc!=5 && g.argc!=6 ){ |
| @@ -2171,11 +2231,12 @@ | ||
| 2171 | 2231 | ** -P|--port TCPPORT listen to request on port TCPPORT |
| 2172 | 2232 | ** --th-trace trace TH1 execution (for debugging purposes) |
| 2173 | 2233 | ** --repolist If REPOSITORY is dir, URL "/" lists repos. |
| 2174 | 2234 | ** --scgi Accept SCGI rather than HTTP |
| 2175 | 2235 | ** --skin LABEL Use override skin LABEL |
| 2176 | - | |
| 2236 | +** --usepidkey Use saved encryption key from parent process. This is | |
| 2237 | +** only necessary when using SEE on Windows. | |
| 2177 | 2238 | ** |
| 2178 | 2239 | ** See also: cgi, http, winsrv |
| 2179 | 2240 | */ |
| 2180 | 2241 | void cmd_webserver(void){ |
| 2181 | 2242 | int iPort, mxPort; /* Range of TCP ports allowed */ |
| @@ -2192,10 +2253,13 @@ | ||
| 2192 | 2253 | const char *zAltBase; /* Argument to the --baseurl option */ |
| 2193 | 2254 | const char *zFileGlob; /* Static content must match this */ |
| 2194 | 2255 | char *zIpAddr = 0; /* Bind to this IP address */ |
| 2195 | 2256 | int fCreate = 0; /* The --create flag */ |
| 2196 | 2257 | const char *zInitPage = 0; /* Start on this page. --page option */ |
| 2258 | +#if defined(_WIN32) && USE_SEE | |
| 2259 | + const char *zPidKey; | |
| 2260 | +#endif | |
| 2197 | 2261 | |
| 2198 | 2262 | #if defined(_WIN32) |
| 2199 | 2263 | const char *zStopperFile; /* Name of file used to terminate server */ |
| 2200 | 2264 | zStopperFile = find_option("stopper", 0, 1); |
| 2201 | 2265 | #endif |
| @@ -2235,10 +2299,21 @@ | ||
| 2235 | 2299 | g.sslNotAvailable = 1; |
| 2236 | 2300 | } |
| 2237 | 2301 | if( find_option("localhost", 0, 0)!=0 ){ |
| 2238 | 2302 | flags |= HTTP_SERVER_LOCALHOST; |
| 2239 | 2303 | } |
| 2304 | + | |
| 2305 | +#if defined(_WIN32) && USE_SEE | |
| 2306 | + zPidKey = find_option("usepidkey", 0, 1); | |
| 2307 | + if( zPidKey ){ | |
| 2308 | + DWORD processId = 0; | |
| 2309 | + LPVOID pAddress = NULL; | |
| 2310 | + SIZE_T nSize = 0; | |
| 2311 | + parse_pid_key_value(zPidKey, &processId, &pAddress, &nSize); | |
| 2312 | + db_read_saved_encryption_key_from_process(processId, pAddress, nSize); | |
| 2313 | + } | |
| 2314 | +#endif | |
| 2240 | 2315 | |
| 2241 | 2316 | /* We should be done with options.. */ |
| 2242 | 2317 | verify_all_options(); |
| 2243 | 2318 | |
| 2244 | 2319 | if( g.argc!=2 && g.argc!=3 ) usage("?REPOSITORY?"); |
| 2245 | 2320 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -18,20 +18,21 @@ | |
| 18 | ** This module codes the main() procedure that runs first when the |
| 19 | ** program is invoked. |
| 20 | */ |
| 21 | #include "VERSION.h" |
| 22 | #include "config.h" |
| 23 | #include "main.h" |
| 24 | #include <string.h> |
| 25 | #include <time.h> |
| 26 | #include <fcntl.h> |
| 27 | #include <sys/types.h> |
| 28 | #include <sys/stat.h> |
| 29 | #include <stdlib.h> /* atexit() */ |
| 30 | #if defined(_WIN32) |
| 31 | # include <windows.h> |
| 32 | #else |
| 33 | # include <errno.h> /* errno global */ |
| 34 | #endif |
| 35 | #ifdef FOSSIL_ENABLE_SSL |
| 36 | # include "openssl/crypto.h" |
| 37 | #endif |
| @@ -299,10 +300,22 @@ | |
| 299 | /* |
| 300 | ** atexit() handler which frees up "some" of the resources |
| 301 | ** used by fossil. |
| 302 | */ |
| 303 | static void fossil_atexit(void) { |
| 304 | #if defined(_WIN32) && !defined(_WIN64) && defined(FOSSIL_ENABLE_TCL) && \ |
| 305 | defined(USE_TCL_STUBS) |
| 306 | /* |
| 307 | ** If Tcl is compiled on Windows using the latest MinGW, Fossil can crash |
| 308 | ** when exiting while a stubs-enabled Tcl is still loaded. This is due to |
| @@ -1917,10 +1930,41 @@ | |
| 1917 | } |
| 1918 | } |
| 1919 | } |
| 1920 | } |
| 1921 | |
| 1922 | /* |
| 1923 | ** undocumented format: |
| 1924 | ** |
| 1925 | ** fossil http INFILE OUTFILE IPADDR ?REPOSITORY? |
| 1926 | ** |
| @@ -1968,10 +2012,12 @@ | |
| 1968 | ** --notfound URL use URL as "HTTP 404, object not found" page. |
| 1969 | ** --repolist If REPOSITORY is directory, URL "/" lists all repos |
| 1970 | ** --scgi Interpret input as SCGI rather than HTTP |
| 1971 | ** --skin LABEL Use override skin LABEL |
| 1972 | ** --th-trace trace TH1 execution (for debugging purposes) |
| 1973 | ** |
| 1974 | ** See also: cgi, server, winsrv |
| 1975 | */ |
| 1976 | void cmd_http(void){ |
| 1977 | const char *zIpAddr = 0; |
| @@ -1980,10 +2026,13 @@ | |
| 1980 | const char *zAltBase; |
| 1981 | const char *zFileGlob; |
| 1982 | int useSCGI; |
| 1983 | int noJail; |
| 1984 | int allowRepoList; |
| 1985 | |
| 1986 | Th_InitTraceLog(); |
| 1987 | |
| 1988 | /* The winhttp module passes the --files option as --files-urlenc with |
| 1989 | ** the argument being URL encoded, to avoid wildcard expansion in the |
| @@ -2010,10 +2059,21 @@ | |
| 2010 | zIpAddr = fossil_getenv("REMOTE_HOST"); /* From stunnel */ |
| 2011 | cgi_replace_parameter("HTTPS","on"); |
| 2012 | } |
| 2013 | zHost = find_option("host", 0, 1); |
| 2014 | if( zHost ) cgi_replace_parameter("HTTP_HOST",zHost); |
| 2015 | |
| 2016 | /* We should be done with options.. */ |
| 2017 | verify_all_options(); |
| 2018 | |
| 2019 | if( g.argc!=2 && g.argc!=3 && g.argc!=5 && g.argc!=6 ){ |
| @@ -2171,11 +2231,12 @@ | |
| 2171 | ** -P|--port TCPPORT listen to request on port TCPPORT |
| 2172 | ** --th-trace trace TH1 execution (for debugging purposes) |
| 2173 | ** --repolist If REPOSITORY is dir, URL "/" lists repos. |
| 2174 | ** --scgi Accept SCGI rather than HTTP |
| 2175 | ** --skin LABEL Use override skin LABEL |
| 2176 | |
| 2177 | ** |
| 2178 | ** See also: cgi, http, winsrv |
| 2179 | */ |
| 2180 | void cmd_webserver(void){ |
| 2181 | int iPort, mxPort; /* Range of TCP ports allowed */ |
| @@ -2192,10 +2253,13 @@ | |
| 2192 | const char *zAltBase; /* Argument to the --baseurl option */ |
| 2193 | const char *zFileGlob; /* Static content must match this */ |
| 2194 | char *zIpAddr = 0; /* Bind to this IP address */ |
| 2195 | int fCreate = 0; /* The --create flag */ |
| 2196 | const char *zInitPage = 0; /* Start on this page. --page option */ |
| 2197 | |
| 2198 | #if defined(_WIN32) |
| 2199 | const char *zStopperFile; /* Name of file used to terminate server */ |
| 2200 | zStopperFile = find_option("stopper", 0, 1); |
| 2201 | #endif |
| @@ -2235,10 +2299,21 @@ | |
| 2235 | g.sslNotAvailable = 1; |
| 2236 | } |
| 2237 | if( find_option("localhost", 0, 0)!=0 ){ |
| 2238 | flags |= HTTP_SERVER_LOCALHOST; |
| 2239 | } |
| 2240 | |
| 2241 | /* We should be done with options.. */ |
| 2242 | verify_all_options(); |
| 2243 | |
| 2244 | if( g.argc!=2 && g.argc!=3 ) usage("?REPOSITORY?"); |
| 2245 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -18,20 +18,21 @@ | |
| 18 | ** This module codes the main() procedure that runs first when the |
| 19 | ** program is invoked. |
| 20 | */ |
| 21 | #include "VERSION.h" |
| 22 | #include "config.h" |
| 23 | #if defined(_WIN32) |
| 24 | # include <windows.h> |
| 25 | #endif |
| 26 | #include "main.h" |
| 27 | #include <string.h> |
| 28 | #include <time.h> |
| 29 | #include <fcntl.h> |
| 30 | #include <sys/types.h> |
| 31 | #include <sys/stat.h> |
| 32 | #include <stdlib.h> /* atexit() */ |
| 33 | #if !defined(_WIN32) |
| 34 | # include <errno.h> /* errno global */ |
| 35 | #endif |
| 36 | #ifdef FOSSIL_ENABLE_SSL |
| 37 | # include "openssl/crypto.h" |
| 38 | #endif |
| @@ -299,10 +300,22 @@ | |
| 300 | /* |
| 301 | ** atexit() handler which frees up "some" of the resources |
| 302 | ** used by fossil. |
| 303 | */ |
| 304 | static void fossil_atexit(void) { |
| 305 | #if USE_SEE |
| 306 | /* |
| 307 | ** Zero, unlock, and free the saved database encryption key now. |
| 308 | */ |
| 309 | db_unsave_encryption_key(); |
| 310 | #endif |
| 311 | #if defined(_WIN32) || defined(__BIONIC__) |
| 312 | /* |
| 313 | ** Free the secure getpass() buffer now. |
| 314 | */ |
| 315 | freepass(); |
| 316 | #endif |
| 317 | #if defined(_WIN32) && !defined(_WIN64) && defined(FOSSIL_ENABLE_TCL) && \ |
| 318 | defined(USE_TCL_STUBS) |
| 319 | /* |
| 320 | ** If Tcl is compiled on Windows using the latest MinGW, Fossil can crash |
| 321 | ** when exiting while a stubs-enabled Tcl is still loaded. This is due to |
| @@ -1917,10 +1930,41 @@ | |
| 1930 | } |
| 1931 | } |
| 1932 | } |
| 1933 | } |
| 1934 | |
| 1935 | #if defined(_WIN32) && USE_SEE |
| 1936 | /* |
| 1937 | ** This function attempts to parse a string value in the following |
| 1938 | ** format: |
| 1939 | ** |
| 1940 | ** "%lu:%p:%u" |
| 1941 | ** |
| 1942 | ** There are three parts, which must be delimited by colons. The |
| 1943 | ** first part is an unsigned long integer in base-10 (decimal) format. |
| 1944 | ** The second part is a numerical representation of a native pointer, |
| 1945 | ** in the appropriate implementation defined format. The third part |
| 1946 | ** is an unsigned integer in base-10 (decimal) format. |
| 1947 | ** |
| 1948 | ** If the specified value cannot be parsed, for any reason, a fatal |
| 1949 | ** error will be raised and the process will be terminated. |
| 1950 | */ |
| 1951 | void parse_pid_key_value( |
| 1952 | const char *zPidKey, /* The value to be parsed. */ |
| 1953 | DWORD *pProcessId, /* The extracted process identifier. */ |
| 1954 | LPVOID *ppAddress, /* The extracted pointer value. */ |
| 1955 | SIZE_T *pnSize /* The extracted size value. */ |
| 1956 | ){ |
| 1957 | unsigned int nSize = 0; |
| 1958 | if( sscanf(zPidKey, "%lu:%p:%u", pProcessId, ppAddress, &nSize)==3 ){ |
| 1959 | *pnSize = (SIZE_T)nSize; |
| 1960 | }else{ |
| 1961 | fossil_fatal("failed to parse pid key"); |
| 1962 | } |
| 1963 | } |
| 1964 | #endif |
| 1965 | |
| 1966 | /* |
| 1967 | ** undocumented format: |
| 1968 | ** |
| 1969 | ** fossil http INFILE OUTFILE IPADDR ?REPOSITORY? |
| 1970 | ** |
| @@ -1968,10 +2012,12 @@ | |
| 2012 | ** --notfound URL use URL as "HTTP 404, object not found" page. |
| 2013 | ** --repolist If REPOSITORY is directory, URL "/" lists all repos |
| 2014 | ** --scgi Interpret input as SCGI rather than HTTP |
| 2015 | ** --skin LABEL Use override skin LABEL |
| 2016 | ** --th-trace trace TH1 execution (for debugging purposes) |
| 2017 | ** --usepidkey Use saved encryption key from parent process. This is |
| 2018 | ** only necessary when using SEE on Windows. |
| 2019 | ** |
| 2020 | ** See also: cgi, server, winsrv |
| 2021 | */ |
| 2022 | void cmd_http(void){ |
| 2023 | const char *zIpAddr = 0; |
| @@ -1980,10 +2026,13 @@ | |
| 2026 | const char *zAltBase; |
| 2027 | const char *zFileGlob; |
| 2028 | int useSCGI; |
| 2029 | int noJail; |
| 2030 | int allowRepoList; |
| 2031 | #if defined(_WIN32) && USE_SEE |
| 2032 | const char *zPidKey; |
| 2033 | #endif |
| 2034 | |
| 2035 | Th_InitTraceLog(); |
| 2036 | |
| 2037 | /* The winhttp module passes the --files option as --files-urlenc with |
| 2038 | ** the argument being URL encoded, to avoid wildcard expansion in the |
| @@ -2010,10 +2059,21 @@ | |
| 2059 | zIpAddr = fossil_getenv("REMOTE_HOST"); /* From stunnel */ |
| 2060 | cgi_replace_parameter("HTTPS","on"); |
| 2061 | } |
| 2062 | zHost = find_option("host", 0, 1); |
| 2063 | if( zHost ) cgi_replace_parameter("HTTP_HOST",zHost); |
| 2064 | |
| 2065 | #if defined(_WIN32) && USE_SEE |
| 2066 | zPidKey = find_option("usepidkey", 0, 1); |
| 2067 | if( zPidKey ){ |
| 2068 | DWORD processId = 0; |
| 2069 | LPVOID pAddress = NULL; |
| 2070 | SIZE_T nSize = 0; |
| 2071 | parse_pid_key_value(zPidKey, &processId, &pAddress, &nSize); |
| 2072 | db_read_saved_encryption_key_from_process(processId, pAddress, nSize); |
| 2073 | } |
| 2074 | #endif |
| 2075 | |
| 2076 | /* We should be done with options.. */ |
| 2077 | verify_all_options(); |
| 2078 | |
| 2079 | if( g.argc!=2 && g.argc!=3 && g.argc!=5 && g.argc!=6 ){ |
| @@ -2171,11 +2231,12 @@ | |
| 2231 | ** -P|--port TCPPORT listen to request on port TCPPORT |
| 2232 | ** --th-trace trace TH1 execution (for debugging purposes) |
| 2233 | ** --repolist If REPOSITORY is dir, URL "/" lists repos. |
| 2234 | ** --scgi Accept SCGI rather than HTTP |
| 2235 | ** --skin LABEL Use override skin LABEL |
| 2236 | ** --usepidkey Use saved encryption key from parent process. This is |
| 2237 | ** only necessary when using SEE on Windows. |
| 2238 | ** |
| 2239 | ** See also: cgi, http, winsrv |
| 2240 | */ |
| 2241 | void cmd_webserver(void){ |
| 2242 | int iPort, mxPort; /* Range of TCP ports allowed */ |
| @@ -2192,10 +2253,13 @@ | |
| 2253 | const char *zAltBase; /* Argument to the --baseurl option */ |
| 2254 | const char *zFileGlob; /* Static content must match this */ |
| 2255 | char *zIpAddr = 0; /* Bind to this IP address */ |
| 2256 | int fCreate = 0; /* The --create flag */ |
| 2257 | const char *zInitPage = 0; /* Start on this page. --page option */ |
| 2258 | #if defined(_WIN32) && USE_SEE |
| 2259 | const char *zPidKey; |
| 2260 | #endif |
| 2261 | |
| 2262 | #if defined(_WIN32) |
| 2263 | const char *zStopperFile; /* Name of file used to terminate server */ |
| 2264 | zStopperFile = find_option("stopper", 0, 1); |
| 2265 | #endif |
| @@ -2235,10 +2299,21 @@ | |
| 2299 | g.sslNotAvailable = 1; |
| 2300 | } |
| 2301 | if( find_option("localhost", 0, 0)!=0 ){ |
| 2302 | flags |= HTTP_SERVER_LOCALHOST; |
| 2303 | } |
| 2304 | |
| 2305 | #if defined(_WIN32) && USE_SEE |
| 2306 | zPidKey = find_option("usepidkey", 0, 1); |
| 2307 | if( zPidKey ){ |
| 2308 | DWORD processId = 0; |
| 2309 | LPVOID pAddress = NULL; |
| 2310 | SIZE_T nSize = 0; |
| 2311 | parse_pid_key_value(zPidKey, &processId, &pAddress, &nSize); |
| 2312 | db_read_saved_encryption_key_from_process(processId, pAddress, nSize); |
| 2313 | } |
| 2314 | #endif |
| 2315 | |
| 2316 | /* We should be done with options.. */ |
| 2317 | verify_all_options(); |
| 2318 | |
| 2319 | if( g.argc!=2 && g.argc!=3 ) usage("?REPOSITORY?"); |
| 2320 |
+2
| --- src/main.mk | ||
| +++ src/main.mk | ||
| @@ -498,10 +498,12 @@ | ||
| 498 | 498 | -DSQLITE_OMIT_DECLTYPE \ |
| 499 | 499 | -DSQLITE_OMIT_DEPRECATED \ |
| 500 | 500 | -DSQLITE_OMIT_PROGRESS_CALLBACK \ |
| 501 | 501 | -DSQLITE_OMIT_SHARED_CACHE \ |
| 502 | 502 | -DSQLITE_OMIT_LOAD_EXTENSION \ |
| 503 | + -DSQLITE_MAX_EXPR_DEPTH=0 \ | |
| 504 | + -DSQLITE_USE_ALLOCA \ | |
| 503 | 505 | -DSQLITE_ENABLE_LOCKING_STYLE=0 \ |
| 504 | 506 | -DSQLITE_DEFAULT_FILE_FORMAT=4 \ |
| 505 | 507 | -DSQLITE_ENABLE_EXPLAIN_COMMENTS \ |
| 506 | 508 | -DSQLITE_ENABLE_FTS4 \ |
| 507 | 509 | -DSQLITE_ENABLE_FTS3_PARENTHESIS \ |
| 508 | 510 |
| --- src/main.mk | |
| +++ src/main.mk | |
| @@ -498,10 +498,12 @@ | |
| 498 | -DSQLITE_OMIT_DECLTYPE \ |
| 499 | -DSQLITE_OMIT_DEPRECATED \ |
| 500 | -DSQLITE_OMIT_PROGRESS_CALLBACK \ |
| 501 | -DSQLITE_OMIT_SHARED_CACHE \ |
| 502 | -DSQLITE_OMIT_LOAD_EXTENSION \ |
| 503 | -DSQLITE_ENABLE_LOCKING_STYLE=0 \ |
| 504 | -DSQLITE_DEFAULT_FILE_FORMAT=4 \ |
| 505 | -DSQLITE_ENABLE_EXPLAIN_COMMENTS \ |
| 506 | -DSQLITE_ENABLE_FTS4 \ |
| 507 | -DSQLITE_ENABLE_FTS3_PARENTHESIS \ |
| 508 |
| --- src/main.mk | |
| +++ src/main.mk | |
| @@ -498,10 +498,12 @@ | |
| 498 | -DSQLITE_OMIT_DECLTYPE \ |
| 499 | -DSQLITE_OMIT_DEPRECATED \ |
| 500 | -DSQLITE_OMIT_PROGRESS_CALLBACK \ |
| 501 | -DSQLITE_OMIT_SHARED_CACHE \ |
| 502 | -DSQLITE_OMIT_LOAD_EXTENSION \ |
| 503 | -DSQLITE_MAX_EXPR_DEPTH=0 \ |
| 504 | -DSQLITE_USE_ALLOCA \ |
| 505 | -DSQLITE_ENABLE_LOCKING_STYLE=0 \ |
| 506 | -DSQLITE_DEFAULT_FILE_FORMAT=4 \ |
| 507 | -DSQLITE_ENABLE_EXPLAIN_COMMENTS \ |
| 508 | -DSQLITE_ENABLE_FTS4 \ |
| 509 | -DSQLITE_ENABLE_FTS3_PARENTHESIS \ |
| 510 |
+2
| --- src/makemake.tcl | ||
| +++ src/makemake.tcl | ||
| @@ -164,10 +164,12 @@ | ||
| 164 | 164 | -DSQLITE_OMIT_DECLTYPE |
| 165 | 165 | -DSQLITE_OMIT_DEPRECATED |
| 166 | 166 | -DSQLITE_OMIT_PROGRESS_CALLBACK |
| 167 | 167 | -DSQLITE_OMIT_SHARED_CACHE |
| 168 | 168 | -DSQLITE_OMIT_LOAD_EXTENSION |
| 169 | + -DSQLITE_MAX_EXPR_DEPTH=0 | |
| 170 | + -DSQLITE_USE_ALLOCA | |
| 169 | 171 | -DSQLITE_ENABLE_LOCKING_STYLE=0 |
| 170 | 172 | -DSQLITE_DEFAULT_FILE_FORMAT=4 |
| 171 | 173 | -DSQLITE_ENABLE_EXPLAIN_COMMENTS |
| 172 | 174 | -DSQLITE_ENABLE_FTS4 |
| 173 | 175 | -DSQLITE_ENABLE_FTS3_PARENTHESIS |
| 174 | 176 |
| --- src/makemake.tcl | |
| +++ src/makemake.tcl | |
| @@ -164,10 +164,12 @@ | |
| 164 | -DSQLITE_OMIT_DECLTYPE |
| 165 | -DSQLITE_OMIT_DEPRECATED |
| 166 | -DSQLITE_OMIT_PROGRESS_CALLBACK |
| 167 | -DSQLITE_OMIT_SHARED_CACHE |
| 168 | -DSQLITE_OMIT_LOAD_EXTENSION |
| 169 | -DSQLITE_ENABLE_LOCKING_STYLE=0 |
| 170 | -DSQLITE_DEFAULT_FILE_FORMAT=4 |
| 171 | -DSQLITE_ENABLE_EXPLAIN_COMMENTS |
| 172 | -DSQLITE_ENABLE_FTS4 |
| 173 | -DSQLITE_ENABLE_FTS3_PARENTHESIS |
| 174 |
| --- src/makemake.tcl | |
| +++ src/makemake.tcl | |
| @@ -164,10 +164,12 @@ | |
| 164 | -DSQLITE_OMIT_DECLTYPE |
| 165 | -DSQLITE_OMIT_DEPRECATED |
| 166 | -DSQLITE_OMIT_PROGRESS_CALLBACK |
| 167 | -DSQLITE_OMIT_SHARED_CACHE |
| 168 | -DSQLITE_OMIT_LOAD_EXTENSION |
| 169 | -DSQLITE_MAX_EXPR_DEPTH=0 |
| 170 | -DSQLITE_USE_ALLOCA |
| 171 | -DSQLITE_ENABLE_LOCKING_STYLE=0 |
| 172 | -DSQLITE_DEFAULT_FILE_FORMAT=4 |
| 173 | -DSQLITE_ENABLE_EXPLAIN_COMMENTS |
| 174 | -DSQLITE_ENABLE_FTS4 |
| 175 | -DSQLITE_ENABLE_FTS3_PARENTHESIS |
| 176 |
+2
| --- src/makemake.tcl | ||
| +++ src/makemake.tcl | ||
| @@ -164,10 +164,12 @@ | ||
| 164 | 164 | -DSQLITE_OMIT_DECLTYPE |
| 165 | 165 | -DSQLITE_OMIT_DEPRECATED |
| 166 | 166 | -DSQLITE_OMIT_PROGRESS_CALLBACK |
| 167 | 167 | -DSQLITE_OMIT_SHARED_CACHE |
| 168 | 168 | -DSQLITE_OMIT_LOAD_EXTENSION |
| 169 | + -DSQLITE_MAX_EXPR_DEPTH=0 | |
| 170 | + -DSQLITE_USE_ALLOCA | |
| 169 | 171 | -DSQLITE_ENABLE_LOCKING_STYLE=0 |
| 170 | 172 | -DSQLITE_DEFAULT_FILE_FORMAT=4 |
| 171 | 173 | -DSQLITE_ENABLE_EXPLAIN_COMMENTS |
| 172 | 174 | -DSQLITE_ENABLE_FTS4 |
| 173 | 175 | -DSQLITE_ENABLE_FTS3_PARENTHESIS |
| 174 | 176 |
| --- src/makemake.tcl | |
| +++ src/makemake.tcl | |
| @@ -164,10 +164,12 @@ | |
| 164 | -DSQLITE_OMIT_DECLTYPE |
| 165 | -DSQLITE_OMIT_DEPRECATED |
| 166 | -DSQLITE_OMIT_PROGRESS_CALLBACK |
| 167 | -DSQLITE_OMIT_SHARED_CACHE |
| 168 | -DSQLITE_OMIT_LOAD_EXTENSION |
| 169 | -DSQLITE_ENABLE_LOCKING_STYLE=0 |
| 170 | -DSQLITE_DEFAULT_FILE_FORMAT=4 |
| 171 | -DSQLITE_ENABLE_EXPLAIN_COMMENTS |
| 172 | -DSQLITE_ENABLE_FTS4 |
| 173 | -DSQLITE_ENABLE_FTS3_PARENTHESIS |
| 174 |
| --- src/makemake.tcl | |
| +++ src/makemake.tcl | |
| @@ -164,10 +164,12 @@ | |
| 164 | -DSQLITE_OMIT_DECLTYPE |
| 165 | -DSQLITE_OMIT_DEPRECATED |
| 166 | -DSQLITE_OMIT_PROGRESS_CALLBACK |
| 167 | -DSQLITE_OMIT_SHARED_CACHE |
| 168 | -DSQLITE_OMIT_LOAD_EXTENSION |
| 169 | -DSQLITE_MAX_EXPR_DEPTH=0 |
| 170 | -DSQLITE_USE_ALLOCA |
| 171 | -DSQLITE_ENABLE_LOCKING_STYLE=0 |
| 172 | -DSQLITE_DEFAULT_FILE_FORMAT=4 |
| 173 | -DSQLITE_ENABLE_EXPLAIN_COMMENTS |
| 174 | -DSQLITE_ENABLE_FTS4 |
| 175 | -DSQLITE_ENABLE_FTS3_PARENTHESIS |
| 176 |
+4
-4
| --- src/merge3.c | ||
| +++ src/merge3.c | ||
| @@ -376,21 +376,21 @@ | ||
| 376 | 376 | |
| 377 | 377 | if( g.argc!=6 ){ |
| 378 | 378 | usage("PIVOT V1 V2 MERGED"); |
| 379 | 379 | } |
| 380 | 380 | if( blob_read_from_file(&pivot, g.argv[2])<0 ){ |
| 381 | - fossil_fatal("cannot read %s\n", g.argv[2]); | |
| 381 | + fossil_fatal("cannot read %s", g.argv[2]); | |
| 382 | 382 | } |
| 383 | 383 | if( blob_read_from_file(&v1, g.argv[3])<0 ){ |
| 384 | - fossil_fatal("cannot read %s\n", g.argv[3]); | |
| 384 | + fossil_fatal("cannot read %s", g.argv[3]); | |
| 385 | 385 | } |
| 386 | 386 | if( blob_read_from_file(&v2, g.argv[4])<0 ){ |
| 387 | - fossil_fatal("cannot read %s\n", g.argv[4]); | |
| 387 | + fossil_fatal("cannot read %s", g.argv[4]); | |
| 388 | 388 | } |
| 389 | 389 | blob_merge(&pivot, &v1, &v2, &merged); |
| 390 | 390 | if( blob_write_to_file(&merged, g.argv[5])<blob_size(&merged) ){ |
| 391 | - fossil_fatal("cannot write %s\n", g.argv[4]); | |
| 391 | + fossil_fatal("cannot write %s", g.argv[4]); | |
| 392 | 392 | } |
| 393 | 393 | blob_reset(&pivot); |
| 394 | 394 | blob_reset(&v1); |
| 395 | 395 | blob_reset(&v2); |
| 396 | 396 | blob_reset(&merged); |
| 397 | 397 |
| --- src/merge3.c | |
| +++ src/merge3.c | |
| @@ -376,21 +376,21 @@ | |
| 376 | |
| 377 | if( g.argc!=6 ){ |
| 378 | usage("PIVOT V1 V2 MERGED"); |
| 379 | } |
| 380 | if( blob_read_from_file(&pivot, g.argv[2])<0 ){ |
| 381 | fossil_fatal("cannot read %s\n", g.argv[2]); |
| 382 | } |
| 383 | if( blob_read_from_file(&v1, g.argv[3])<0 ){ |
| 384 | fossil_fatal("cannot read %s\n", g.argv[3]); |
| 385 | } |
| 386 | if( blob_read_from_file(&v2, g.argv[4])<0 ){ |
| 387 | fossil_fatal("cannot read %s\n", g.argv[4]); |
| 388 | } |
| 389 | blob_merge(&pivot, &v1, &v2, &merged); |
| 390 | if( blob_write_to_file(&merged, g.argv[5])<blob_size(&merged) ){ |
| 391 | fossil_fatal("cannot write %s\n", g.argv[4]); |
| 392 | } |
| 393 | blob_reset(&pivot); |
| 394 | blob_reset(&v1); |
| 395 | blob_reset(&v2); |
| 396 | blob_reset(&merged); |
| 397 |
| --- src/merge3.c | |
| +++ src/merge3.c | |
| @@ -376,21 +376,21 @@ | |
| 376 | |
| 377 | if( g.argc!=6 ){ |
| 378 | usage("PIVOT V1 V2 MERGED"); |
| 379 | } |
| 380 | if( blob_read_from_file(&pivot, g.argv[2])<0 ){ |
| 381 | fossil_fatal("cannot read %s", g.argv[2]); |
| 382 | } |
| 383 | if( blob_read_from_file(&v1, g.argv[3])<0 ){ |
| 384 | fossil_fatal("cannot read %s", g.argv[3]); |
| 385 | } |
| 386 | if( blob_read_from_file(&v2, g.argv[4])<0 ){ |
| 387 | fossil_fatal("cannot read %s", g.argv[4]); |
| 388 | } |
| 389 | blob_merge(&pivot, &v1, &v2, &merged); |
| 390 | if( blob_write_to_file(&merged, g.argv[5])<blob_size(&merged) ){ |
| 391 | fossil_fatal("cannot write %s", g.argv[4]); |
| 392 | } |
| 393 | blob_reset(&pivot); |
| 394 | blob_reset(&v1); |
| 395 | blob_reset(&v2); |
| 396 | blob_reset(&merged); |
| 397 |
+1
-1
| --- src/mkindex.c | ||
| +++ src/mkindex.c | ||
| @@ -223,11 +223,11 @@ | ||
| 223 | 223 | fprintf(stderr, "%s:%d: unknown option: '%.*s'\n", |
| 224 | 224 | zFile, nLine, j, &zLine[i]); |
| 225 | 225 | nErr++; |
| 226 | 226 | } |
| 227 | 227 | } |
| 228 | - | |
| 228 | + | |
| 229 | 229 | nUsed++; |
| 230 | 230 | } |
| 231 | 231 | |
| 232 | 232 | /* |
| 233 | 233 | ** Check to see if the current line is an #if and if it is, add it to |
| 234 | 234 |
| --- src/mkindex.c | |
| +++ src/mkindex.c | |
| @@ -223,11 +223,11 @@ | |
| 223 | fprintf(stderr, "%s:%d: unknown option: '%.*s'\n", |
| 224 | zFile, nLine, j, &zLine[i]); |
| 225 | nErr++; |
| 226 | } |
| 227 | } |
| 228 | |
| 229 | nUsed++; |
| 230 | } |
| 231 | |
| 232 | /* |
| 233 | ** Check to see if the current line is an #if and if it is, add it to |
| 234 |
| --- src/mkindex.c | |
| +++ src/mkindex.c | |
| @@ -223,11 +223,11 @@ | |
| 223 | fprintf(stderr, "%s:%d: unknown option: '%.*s'\n", |
| 224 | zFile, nLine, j, &zLine[i]); |
| 225 | nErr++; |
| 226 | } |
| 227 | } |
| 228 | |
| 229 | nUsed++; |
| 230 | } |
| 231 | |
| 232 | /* |
| 233 | ** Check to see if the current line is an #if and if it is, add it to |
| 234 |
+4
| --- src/mkversion.c | ||
| +++ src/mkversion.c | ||
| @@ -64,10 +64,14 @@ | ||
| 64 | 64 | printf("#define RELEASE_VERSION_NUMBER %s\n", z); |
| 65 | 65 | memset(vx,0,sizeof(vx)); |
| 66 | 66 | strcpy(vx,b); |
| 67 | 67 | d = 0; |
| 68 | 68 | for(z=vx; z[0]; z++){ |
| 69 | + if( z[0]=='-' ){ | |
| 70 | + z[0] = 0; | |
| 71 | + break; | |
| 72 | + } | |
| 69 | 73 | if( z[0]!='.' ) continue; |
| 70 | 74 | if ( d<3 ){ |
| 71 | 75 | z[0] = ','; |
| 72 | 76 | d++; |
| 73 | 77 | }else{ |
| 74 | 78 |
| --- src/mkversion.c | |
| +++ src/mkversion.c | |
| @@ -64,10 +64,14 @@ | |
| 64 | printf("#define RELEASE_VERSION_NUMBER %s\n", z); |
| 65 | memset(vx,0,sizeof(vx)); |
| 66 | strcpy(vx,b); |
| 67 | d = 0; |
| 68 | for(z=vx; z[0]; z++){ |
| 69 | if( z[0]!='.' ) continue; |
| 70 | if ( d<3 ){ |
| 71 | z[0] = ','; |
| 72 | d++; |
| 73 | }else{ |
| 74 |
| --- src/mkversion.c | |
| +++ src/mkversion.c | |
| @@ -64,10 +64,14 @@ | |
| 64 | printf("#define RELEASE_VERSION_NUMBER %s\n", z); |
| 65 | memset(vx,0,sizeof(vx)); |
| 66 | strcpy(vx,b); |
| 67 | d = 0; |
| 68 | for(z=vx; z[0]; z++){ |
| 69 | if( z[0]=='-' ){ |
| 70 | z[0] = 0; |
| 71 | break; |
| 72 | } |
| 73 | if( z[0]!='.' ) continue; |
| 74 | if ( d<3 ){ |
| 75 | z[0] = ','; |
| 76 | d++; |
| 77 | }else{ |
| 78 |
+1
-1
| --- src/search.c | ||
| +++ src/search.c | ||
| @@ -407,11 +407,11 @@ | ||
| 407 | 407 | |
| 408 | 408 | /* search_match(TEXT, TEXT, ....) |
| 409 | 409 | ** |
| 410 | 410 | ** Using the full-scan search engine created by the most recent call |
| 411 | 411 | ** to search_init(), match the input the TEXT arguments. |
| 412 | -** Remember the results global full-scan search object. | |
| 412 | +** Remember the results global full-scan search object. | |
| 413 | 413 | ** Return non-zero on a match and zero on a miss. |
| 414 | 414 | */ |
| 415 | 415 | static void search_match_sqlfunc( |
| 416 | 416 | sqlite3_context *context, |
| 417 | 417 | int argc, |
| 418 | 418 |
| --- src/search.c | |
| +++ src/search.c | |
| @@ -407,11 +407,11 @@ | |
| 407 | |
| 408 | /* search_match(TEXT, TEXT, ....) |
| 409 | ** |
| 410 | ** Using the full-scan search engine created by the most recent call |
| 411 | ** to search_init(), match the input the TEXT arguments. |
| 412 | ** Remember the results global full-scan search object. |
| 413 | ** Return non-zero on a match and zero on a miss. |
| 414 | */ |
| 415 | static void search_match_sqlfunc( |
| 416 | sqlite3_context *context, |
| 417 | int argc, |
| 418 |
| --- src/search.c | |
| +++ src/search.c | |
| @@ -407,11 +407,11 @@ | |
| 407 | |
| 408 | /* search_match(TEXT, TEXT, ....) |
| 409 | ** |
| 410 | ** Using the full-scan search engine created by the most recent call |
| 411 | ** to search_init(), match the input the TEXT arguments. |
| 412 | ** Remember the results global full-scan search object. |
| 413 | ** Return non-zero on a match and zero on a miss. |
| 414 | */ |
| 415 | static void search_match_sqlfunc( |
| 416 | sqlite3_context *context, |
| 417 | int argc, |
| 418 |
+1
-1
| --- src/setup.c | ||
| +++ src/setup.c | ||
| @@ -1537,11 +1537,11 @@ | ||
| 1537 | 1537 | @ <p>Settings marked with (v) are 'versionable' and will be overridden |
| 1538 | 1538 | @ by the contents of files named <tt>.fossil-settings/PROPERTY</tt> |
| 1539 | 1539 | @ in the check-out root. |
| 1540 | 1540 | @ If such a file is present, the corresponding field above is not |
| 1541 | 1541 | @ editable.</p><hr /><p> |
| 1542 | - @ These settings work the same as the | |
| 1542 | + @ These settings work the same as the | |
| 1543 | 1543 | @ <a href='%R/help?cmd=settings'>fossil set</a> command. |
| 1544 | 1544 | db_end_transaction(0); |
| 1545 | 1545 | style_footer(); |
| 1546 | 1546 | } |
| 1547 | 1547 | |
| 1548 | 1548 |
| --- src/setup.c | |
| +++ src/setup.c | |
| @@ -1537,11 +1537,11 @@ | |
| 1537 | @ <p>Settings marked with (v) are 'versionable' and will be overridden |
| 1538 | @ by the contents of files named <tt>.fossil-settings/PROPERTY</tt> |
| 1539 | @ in the check-out root. |
| 1540 | @ If such a file is present, the corresponding field above is not |
| 1541 | @ editable.</p><hr /><p> |
| 1542 | @ These settings work the same as the |
| 1543 | @ <a href='%R/help?cmd=settings'>fossil set</a> command. |
| 1544 | db_end_transaction(0); |
| 1545 | style_footer(); |
| 1546 | } |
| 1547 | |
| 1548 |
| --- src/setup.c | |
| +++ src/setup.c | |
| @@ -1537,11 +1537,11 @@ | |
| 1537 | @ <p>Settings marked with (v) are 'versionable' and will be overridden |
| 1538 | @ by the contents of files named <tt>.fossil-settings/PROPERTY</tt> |
| 1539 | @ in the check-out root. |
| 1540 | @ If such a file is present, the corresponding field above is not |
| 1541 | @ editable.</p><hr /><p> |
| 1542 | @ These settings work the same as the |
| 1543 | @ <a href='%R/help?cmd=settings'>fossil set</a> command. |
| 1544 | db_end_transaction(0); |
| 1545 | style_footer(); |
| 1546 | } |
| 1547 | |
| 1548 |
+24
-16
| --- src/shell.c | ||
| +++ src/shell.c | ||
| @@ -666,23 +666,25 @@ | ||
| 666 | 666 | #define MODE_Column 1 /* One record per line in neat columns */ |
| 667 | 667 | #define MODE_List 2 /* One record per line with a separator */ |
| 668 | 668 | #define MODE_Semi 3 /* Same as MODE_List but append ";" to each line */ |
| 669 | 669 | #define MODE_Html 4 /* Generate an XHTML table */ |
| 670 | 670 | #define MODE_Insert 5 /* Generate SQL "insert" statements */ |
| 671 | -#define MODE_Tcl 6 /* Generate ANSI-C or TCL quoted elements */ | |
| 672 | -#define MODE_Csv 7 /* Quote strings, numbers are plain */ | |
| 673 | -#define MODE_Explain 8 /* Like MODE_Column, but do not truncate data */ | |
| 674 | -#define MODE_Ascii 9 /* Use ASCII unit and record separators (0x1F/0x1E) */ | |
| 675 | -#define MODE_Pretty 10 /* Pretty-print schemas */ | |
| 671 | +#define MODE_Quote 6 /* Quote values as for SQL */ | |
| 672 | +#define MODE_Tcl 7 /* Generate ANSI-C or TCL quoted elements */ | |
| 673 | +#define MODE_Csv 8 /* Quote strings, numbers are plain */ | |
| 674 | +#define MODE_Explain 9 /* Like MODE_Column, but do not truncate data */ | |
| 675 | +#define MODE_Ascii 10 /* Use ASCII unit and record separators (0x1F/0x1E) */ | |
| 676 | +#define MODE_Pretty 11 /* Pretty-print schemas */ | |
| 676 | 677 | |
| 677 | 678 | static const char *modeDescr[] = { |
| 678 | 679 | "line", |
| 679 | 680 | "column", |
| 680 | 681 | "list", |
| 681 | 682 | "semi", |
| 682 | 683 | "html", |
| 683 | 684 | "insert", |
| 685 | + "quote", | |
| 684 | 686 | "tcl", |
| 685 | 687 | "csv", |
| 686 | 688 | "explain", |
| 687 | 689 | "ascii", |
| 688 | 690 | "prettyprint", |
| @@ -1196,23 +1198,26 @@ | ||
| 1196 | 1198 | utf8_printf(p->out, "%s", p->rowSeparator); |
| 1197 | 1199 | } |
| 1198 | 1200 | setTextMode(p->out, 1); |
| 1199 | 1201 | break; |
| 1200 | 1202 | } |
| 1203 | + case MODE_Quote: | |
| 1201 | 1204 | case MODE_Insert: { |
| 1202 | 1205 | p->cnt++; |
| 1203 | 1206 | if( azArg==0 ) break; |
| 1204 | - utf8_printf(p->out,"INSERT INTO %s",p->zDestTable); | |
| 1205 | - if( p->showHeader ){ | |
| 1206 | - raw_printf(p->out,"("); | |
| 1207 | - for(i=0; i<nArg; i++){ | |
| 1208 | - char *zSep = i>0 ? ",": ""; | |
| 1209 | - utf8_printf(p->out, "%s%s", zSep, azCol[i]); | |
| 1210 | - } | |
| 1211 | - raw_printf(p->out,")"); | |
| 1212 | - } | |
| 1213 | - raw_printf(p->out," VALUES("); | |
| 1207 | + if( p->cMode==MODE_Insert ){ | |
| 1208 | + utf8_printf(p->out,"INSERT INTO %s",p->zDestTable); | |
| 1209 | + if( p->showHeader ){ | |
| 1210 | + raw_printf(p->out,"("); | |
| 1211 | + for(i=0; i<nArg; i++){ | |
| 1212 | + char *zSep = i>0 ? ",": ""; | |
| 1213 | + utf8_printf(p->out, "%s%s", zSep, azCol[i]); | |
| 1214 | + } | |
| 1215 | + raw_printf(p->out,")"); | |
| 1216 | + } | |
| 1217 | + raw_printf(p->out," VALUES("); | |
| 1218 | + } | |
| 1214 | 1219 | for(i=0; i<nArg; i++){ |
| 1215 | 1220 | char *zSep = i>0 ? ",": ""; |
| 1216 | 1221 | if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){ |
| 1217 | 1222 | utf8_printf(p->out,"%sNULL",zSep); |
| 1218 | 1223 | }else if( aiType && aiType[i]==SQLITE_TEXT ){ |
| @@ -1231,11 +1236,11 @@ | ||
| 1231 | 1236 | }else{ |
| 1232 | 1237 | if( zSep[0] ) utf8_printf(p->out,"%s",zSep); |
| 1233 | 1238 | output_quoted_string(p->out, azArg[i]); |
| 1234 | 1239 | } |
| 1235 | 1240 | } |
| 1236 | - raw_printf(p->out,");\n"); | |
| 1241 | + raw_printf(p->out,p->cMode==MODE_Quote?"\n":");\n"); | |
| 1237 | 1242 | break; |
| 1238 | 1243 | } |
| 1239 | 1244 | case MODE_Ascii: { |
| 1240 | 1245 | if( p->cnt++==0 && p->showHeader ){ |
| 1241 | 1246 | for(i=0; i<nArg; i++){ |
| @@ -2175,10 +2180,11 @@ | ||
| 2175 | 2180 | " column Left-aligned columns. (See .width)\n" |
| 2176 | 2181 | " html HTML <table> code\n" |
| 2177 | 2182 | " insert SQL insert statements for TABLE\n" |
| 2178 | 2183 | " line One value per line\n" |
| 2179 | 2184 | " list Values delimited by .separator strings\n" |
| 2185 | + " quote Escape answers as for SQL\n" | |
| 2180 | 2186 | " tabs Tab-separated values\n" |
| 2181 | 2187 | " tcl TCL list elements\n" |
| 2182 | 2188 | ".nullvalue STRING Use STRING in place of NULL values\n" |
| 2183 | 2189 | ".once FILENAME Output for the next SQL command only to FILENAME\n" |
| 2184 | 2190 | ".open ?--new? ?FILE? Close existing database and reopen FILE\n" |
| @@ -3975,10 +3981,12 @@ | ||
| 3975 | 3981 | p->mode = MODE_List; |
| 3976 | 3982 | sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Tab); |
| 3977 | 3983 | }else if( c2=='i' && strncmp(azArg[1],"insert",n2)==0 ){ |
| 3978 | 3984 | p->mode = MODE_Insert; |
| 3979 | 3985 | set_table_name(p, nArg>=3 ? azArg[2] : "table"); |
| 3986 | + }else if( c2=='q' && strncmp(azArg[1],"quote",n2)==0 ){ | |
| 3987 | + p->mode = MODE_Quote; | |
| 3980 | 3988 | }else if( c2=='a' && strncmp(azArg[1],"ascii",n2)==0 ){ |
| 3981 | 3989 | p->mode = MODE_Ascii; |
| 3982 | 3990 | sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit); |
| 3983 | 3991 | sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record); |
| 3984 | 3992 | }else { |
| 3985 | 3993 |
| --- src/shell.c | |
| +++ src/shell.c | |
| @@ -666,23 +666,25 @@ | |
| 666 | #define MODE_Column 1 /* One record per line in neat columns */ |
| 667 | #define MODE_List 2 /* One record per line with a separator */ |
| 668 | #define MODE_Semi 3 /* Same as MODE_List but append ";" to each line */ |
| 669 | #define MODE_Html 4 /* Generate an XHTML table */ |
| 670 | #define MODE_Insert 5 /* Generate SQL "insert" statements */ |
| 671 | #define MODE_Tcl 6 /* Generate ANSI-C or TCL quoted elements */ |
| 672 | #define MODE_Csv 7 /* Quote strings, numbers are plain */ |
| 673 | #define MODE_Explain 8 /* Like MODE_Column, but do not truncate data */ |
| 674 | #define MODE_Ascii 9 /* Use ASCII unit and record separators (0x1F/0x1E) */ |
| 675 | #define MODE_Pretty 10 /* Pretty-print schemas */ |
| 676 | |
| 677 | static const char *modeDescr[] = { |
| 678 | "line", |
| 679 | "column", |
| 680 | "list", |
| 681 | "semi", |
| 682 | "html", |
| 683 | "insert", |
| 684 | "tcl", |
| 685 | "csv", |
| 686 | "explain", |
| 687 | "ascii", |
| 688 | "prettyprint", |
| @@ -1196,23 +1198,26 @@ | |
| 1196 | utf8_printf(p->out, "%s", p->rowSeparator); |
| 1197 | } |
| 1198 | setTextMode(p->out, 1); |
| 1199 | break; |
| 1200 | } |
| 1201 | case MODE_Insert: { |
| 1202 | p->cnt++; |
| 1203 | if( azArg==0 ) break; |
| 1204 | utf8_printf(p->out,"INSERT INTO %s",p->zDestTable); |
| 1205 | if( p->showHeader ){ |
| 1206 | raw_printf(p->out,"("); |
| 1207 | for(i=0; i<nArg; i++){ |
| 1208 | char *zSep = i>0 ? ",": ""; |
| 1209 | utf8_printf(p->out, "%s%s", zSep, azCol[i]); |
| 1210 | } |
| 1211 | raw_printf(p->out,")"); |
| 1212 | } |
| 1213 | raw_printf(p->out," VALUES("); |
| 1214 | for(i=0; i<nArg; i++){ |
| 1215 | char *zSep = i>0 ? ",": ""; |
| 1216 | if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){ |
| 1217 | utf8_printf(p->out,"%sNULL",zSep); |
| 1218 | }else if( aiType && aiType[i]==SQLITE_TEXT ){ |
| @@ -1231,11 +1236,11 @@ | |
| 1231 | }else{ |
| 1232 | if( zSep[0] ) utf8_printf(p->out,"%s",zSep); |
| 1233 | output_quoted_string(p->out, azArg[i]); |
| 1234 | } |
| 1235 | } |
| 1236 | raw_printf(p->out,");\n"); |
| 1237 | break; |
| 1238 | } |
| 1239 | case MODE_Ascii: { |
| 1240 | if( p->cnt++==0 && p->showHeader ){ |
| 1241 | for(i=0; i<nArg; i++){ |
| @@ -2175,10 +2180,11 @@ | |
| 2175 | " column Left-aligned columns. (See .width)\n" |
| 2176 | " html HTML <table> code\n" |
| 2177 | " insert SQL insert statements for TABLE\n" |
| 2178 | " line One value per line\n" |
| 2179 | " list Values delimited by .separator strings\n" |
| 2180 | " tabs Tab-separated values\n" |
| 2181 | " tcl TCL list elements\n" |
| 2182 | ".nullvalue STRING Use STRING in place of NULL values\n" |
| 2183 | ".once FILENAME Output for the next SQL command only to FILENAME\n" |
| 2184 | ".open ?--new? ?FILE? Close existing database and reopen FILE\n" |
| @@ -3975,10 +3981,12 @@ | |
| 3975 | p->mode = MODE_List; |
| 3976 | sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Tab); |
| 3977 | }else if( c2=='i' && strncmp(azArg[1],"insert",n2)==0 ){ |
| 3978 | p->mode = MODE_Insert; |
| 3979 | set_table_name(p, nArg>=3 ? azArg[2] : "table"); |
| 3980 | }else if( c2=='a' && strncmp(azArg[1],"ascii",n2)==0 ){ |
| 3981 | p->mode = MODE_Ascii; |
| 3982 | sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit); |
| 3983 | sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record); |
| 3984 | }else { |
| 3985 |
| --- src/shell.c | |
| +++ src/shell.c | |
| @@ -666,23 +666,25 @@ | |
| 666 | #define MODE_Column 1 /* One record per line in neat columns */ |
| 667 | #define MODE_List 2 /* One record per line with a separator */ |
| 668 | #define MODE_Semi 3 /* Same as MODE_List but append ";" to each line */ |
| 669 | #define MODE_Html 4 /* Generate an XHTML table */ |
| 670 | #define MODE_Insert 5 /* Generate SQL "insert" statements */ |
| 671 | #define MODE_Quote 6 /* Quote values as for SQL */ |
| 672 | #define MODE_Tcl 7 /* Generate ANSI-C or TCL quoted elements */ |
| 673 | #define MODE_Csv 8 /* Quote strings, numbers are plain */ |
| 674 | #define MODE_Explain 9 /* Like MODE_Column, but do not truncate data */ |
| 675 | #define MODE_Ascii 10 /* Use ASCII unit and record separators (0x1F/0x1E) */ |
| 676 | #define MODE_Pretty 11 /* Pretty-print schemas */ |
| 677 | |
| 678 | static const char *modeDescr[] = { |
| 679 | "line", |
| 680 | "column", |
| 681 | "list", |
| 682 | "semi", |
| 683 | "html", |
| 684 | "insert", |
| 685 | "quote", |
| 686 | "tcl", |
| 687 | "csv", |
| 688 | "explain", |
| 689 | "ascii", |
| 690 | "prettyprint", |
| @@ -1196,23 +1198,26 @@ | |
| 1198 | utf8_printf(p->out, "%s", p->rowSeparator); |
| 1199 | } |
| 1200 | setTextMode(p->out, 1); |
| 1201 | break; |
| 1202 | } |
| 1203 | case MODE_Quote: |
| 1204 | case MODE_Insert: { |
| 1205 | p->cnt++; |
| 1206 | if( azArg==0 ) break; |
| 1207 | if( p->cMode==MODE_Insert ){ |
| 1208 | utf8_printf(p->out,"INSERT INTO %s",p->zDestTable); |
| 1209 | if( p->showHeader ){ |
| 1210 | raw_printf(p->out,"("); |
| 1211 | for(i=0; i<nArg; i++){ |
| 1212 | char *zSep = i>0 ? ",": ""; |
| 1213 | utf8_printf(p->out, "%s%s", zSep, azCol[i]); |
| 1214 | } |
| 1215 | raw_printf(p->out,")"); |
| 1216 | } |
| 1217 | raw_printf(p->out," VALUES("); |
| 1218 | } |
| 1219 | for(i=0; i<nArg; i++){ |
| 1220 | char *zSep = i>0 ? ",": ""; |
| 1221 | if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){ |
| 1222 | utf8_printf(p->out,"%sNULL",zSep); |
| 1223 | }else if( aiType && aiType[i]==SQLITE_TEXT ){ |
| @@ -1231,11 +1236,11 @@ | |
| 1236 | }else{ |
| 1237 | if( zSep[0] ) utf8_printf(p->out,"%s",zSep); |
| 1238 | output_quoted_string(p->out, azArg[i]); |
| 1239 | } |
| 1240 | } |
| 1241 | raw_printf(p->out,p->cMode==MODE_Quote?"\n":");\n"); |
| 1242 | break; |
| 1243 | } |
| 1244 | case MODE_Ascii: { |
| 1245 | if( p->cnt++==0 && p->showHeader ){ |
| 1246 | for(i=0; i<nArg; i++){ |
| @@ -2175,10 +2180,11 @@ | |
| 2180 | " column Left-aligned columns. (See .width)\n" |
| 2181 | " html HTML <table> code\n" |
| 2182 | " insert SQL insert statements for TABLE\n" |
| 2183 | " line One value per line\n" |
| 2184 | " list Values delimited by .separator strings\n" |
| 2185 | " quote Escape answers as for SQL\n" |
| 2186 | " tabs Tab-separated values\n" |
| 2187 | " tcl TCL list elements\n" |
| 2188 | ".nullvalue STRING Use STRING in place of NULL values\n" |
| 2189 | ".once FILENAME Output for the next SQL command only to FILENAME\n" |
| 2190 | ".open ?--new? ?FILE? Close existing database and reopen FILE\n" |
| @@ -3975,10 +3981,12 @@ | |
| 3981 | p->mode = MODE_List; |
| 3982 | sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Tab); |
| 3983 | }else if( c2=='i' && strncmp(azArg[1],"insert",n2)==0 ){ |
| 3984 | p->mode = MODE_Insert; |
| 3985 | set_table_name(p, nArg>=3 ? azArg[2] : "table"); |
| 3986 | }else if( c2=='q' && strncmp(azArg[1],"quote",n2)==0 ){ |
| 3987 | p->mode = MODE_Quote; |
| 3988 | }else if( c2=='a' && strncmp(azArg[1],"ascii",n2)==0 ){ |
| 3989 | p->mode = MODE_Ascii; |
| 3990 | sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit); |
| 3991 | sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record); |
| 3992 | }else { |
| 3993 |
+1277
-1181
| --- src/sqlite3.c | ||
| +++ src/sqlite3.c | ||
| @@ -1,8 +1,8 @@ | ||
| 1 | 1 | /****************************************************************************** |
| 2 | 2 | ** This file is an amalgamation of many separate C source files from SQLite |
| 3 | -** version 3.15.0. By combining all the individual C code files into this | |
| 3 | +** version 3.16.0. By combining all the individual C code files into this | |
| 4 | 4 | ** single large file, the entire code can be compiled as a single translation |
| 5 | 5 | ** unit. This allows many compilers to do optimizations that would not be |
| 6 | 6 | ** possible if the files were compiled separately. Performance improvements |
| 7 | 7 | ** of 5% or more are commonly seen when SQLite is compiled as a single |
| 8 | 8 | ** translation unit. |
| @@ -379,13 +379,13 @@ | ||
| 379 | 379 | ** |
| 380 | 380 | ** See also: [sqlite3_libversion()], |
| 381 | 381 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 382 | 382 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 383 | 383 | */ |
| 384 | -#define SQLITE_VERSION "3.15.0" | |
| 385 | -#define SQLITE_VERSION_NUMBER 3015000 | |
| 386 | -#define SQLITE_SOURCE_ID "2016-09-22 18:53:13 c3774c6a5fe48af91fda28e9e18c6ed9053ea992" | |
| 384 | +#define SQLITE_VERSION "3.16.0" | |
| 385 | +#define SQLITE_VERSION_NUMBER 3016000 | |
| 386 | +#define SQLITE_SOURCE_ID "2016-11-02 14:50:19 3028845329c9b7acdec2ec8b01d00d782347454c" | |
| 387 | 387 | |
| 388 | 388 | /* |
| 389 | 389 | ** CAPI3REF: Run-Time Library Version Numbers |
| 390 | 390 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 391 | 391 | ** |
| @@ -1235,10 +1235,16 @@ | ||
| 1235 | 1235 | ** <li>[[SQLITE_FCNTL_HAS_MOVED]] |
| 1236 | 1236 | ** The [SQLITE_FCNTL_HAS_MOVED] file control interprets its argument as a |
| 1237 | 1237 | ** pointer to an integer and it writes a boolean into that integer depending |
| 1238 | 1238 | ** on whether or not the file has been renamed, moved, or deleted since it |
| 1239 | 1239 | ** was first opened. |
| 1240 | +** | |
| 1241 | +** <li>[[SQLITE_FCNTL_WIN32_GET_HANDLE]] | |
| 1242 | +** The [SQLITE_FCNTL_WIN32_GET_HANDLE] opcode can be used to obtain the | |
| 1243 | +** underlying native file handle associated with a file handle. This file | |
| 1244 | +** control interprets its argument as a pointer to a native file handle and | |
| 1245 | +** writes the resulting value there. | |
| 1240 | 1246 | ** |
| 1241 | 1247 | ** <li>[[SQLITE_FCNTL_WIN32_SET_HANDLE]] |
| 1242 | 1248 | ** The [SQLITE_FCNTL_WIN32_SET_HANDLE] opcode is used for debugging. This |
| 1243 | 1249 | ** opcode causes the xFileControl method to swap the file handle with the one |
| 1244 | 1250 | ** pointed to by the pArg argument. This capability is used during testing |
| @@ -1286,10 +1292,12 @@ | ||
| 1286 | 1292 | #define SQLITE_FCNTL_WAL_BLOCK 24 |
| 1287 | 1293 | #define SQLITE_FCNTL_ZIPVFS 25 |
| 1288 | 1294 | #define SQLITE_FCNTL_RBU 26 |
| 1289 | 1295 | #define SQLITE_FCNTL_VFS_POINTER 27 |
| 1290 | 1296 | #define SQLITE_FCNTL_JOURNAL_POINTER 28 |
| 1297 | +#define SQLITE_FCNTL_WIN32_GET_HANDLE 29 | |
| 1298 | +#define SQLITE_FCNTL_PDB 30 | |
| 1291 | 1299 | |
| 1292 | 1300 | /* deprecated names */ |
| 1293 | 1301 | #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE |
| 1294 | 1302 | #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE |
| 1295 | 1303 | #define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO |
| @@ -2238,18 +2246,31 @@ | ||
| 2238 | 2246 | ** does not make a copy of the new main schema name string, so the application |
| 2239 | 2247 | ** must ensure that the argument passed into this DBCONFIG option is unchanged |
| 2240 | 2248 | ** until after the database connection closes. |
| 2241 | 2249 | ** </dd> |
| 2242 | 2250 | ** |
| 2251 | +** <dt>SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE</dt> | |
| 2252 | +** <dd> Usually, when a database in wal mode is closed or detached from a | |
| 2253 | +** database handle, SQLite checks if this will mean that there are now no | |
| 2254 | +** connections at all to the database. If so, it performs a checkpoint | |
| 2255 | +** operation before closing the connection. This option may be used to | |
| 2256 | +** override this behaviour. The first parameter passed to this operation | |
| 2257 | +** is an integer - non-zero to disable checkpoints-on-close, or zero (the | |
| 2258 | +** default) to enable them. The second parameter is a pointer to an integer | |
| 2259 | +** into which is written 0 or 1 to indicate whether checkpoints-on-close | |
| 2260 | +** have been disabled - 0 if they are not disabled, 1 if they are. | |
| 2261 | +** </dd> | |
| 2262 | +** | |
| 2243 | 2263 | ** </dl> |
| 2244 | 2264 | */ |
| 2245 | 2265 | #define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */ |
| 2246 | 2266 | #define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */ |
| 2247 | 2267 | #define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */ |
| 2248 | 2268 | #define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */ |
| 2249 | 2269 | #define SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1004 /* int int* */ |
| 2250 | 2270 | #define SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1005 /* int int* */ |
| 2271 | +#define SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE 1006 /* int int* */ | |
| 2251 | 2272 | |
| 2252 | 2273 | |
| 2253 | 2274 | /* |
| 2254 | 2275 | ** CAPI3REF: Enable Or Disable Extended Result Codes |
| 2255 | 2276 | ** METHOD: sqlite3 |
| @@ -8915,11 +8936,11 @@ | ||
| 8915 | 8936 | |
| 8916 | 8937 | /* |
| 8917 | 8938 | ** CAPI3REF: Set a table filter on a Session Object. |
| 8918 | 8939 | ** |
| 8919 | 8940 | ** The second argument (xFilter) is the "filter callback". For changes to rows |
| 8920 | -** in tables that are not attached to the Session oject, the filter is called | |
| 8941 | +** in tables that are not attached to the Session object, the filter is called | |
| 8921 | 8942 | ** to determine whether changes to the table's rows should be tracked or not. |
| 8922 | 8943 | ** If xFilter returns 0, changes is not tracked. Note that once a table is |
| 8923 | 8944 | ** attached, xFilter will not be called again. |
| 8924 | 8945 | */ |
| 8925 | 8946 | void sqlite3session_table_filter( |
| @@ -9181,11 +9202,11 @@ | ||
| 9181 | 9202 | ** Assuming the changeset blob was created by one of the |
| 9182 | 9203 | ** [sqlite3session_changeset()], [sqlite3changeset_concat()] or |
| 9183 | 9204 | ** [sqlite3changeset_invert()] functions, all changes within the changeset |
| 9184 | 9205 | ** that apply to a single table are grouped together. This means that when |
| 9185 | 9206 | ** an application iterates through a changeset using an iterator created by |
| 9186 | -** this function, all changes that relate to a single table are visted | |
| 9207 | +** this function, all changes that relate to a single table are visited | |
| 9187 | 9208 | ** consecutively. There is no chance that the iterator will visit a change |
| 9188 | 9209 | ** the applies to table X, then one for table Y, and then later on visit |
| 9189 | 9210 | ** another change for table X. |
| 9190 | 9211 | */ |
| 9191 | 9212 | int sqlite3changeset_start( |
| @@ -9268,11 +9289,11 @@ | ||
| 9268 | 9289 | ** If successful, *pabPK is set to point to an array of nCol entries, where |
| 9269 | 9290 | ** nCol is the number of columns in the table. Elements of *pabPK are set to |
| 9270 | 9291 | ** 0x01 if the corresponding column is part of the tables primary key, or |
| 9271 | 9292 | ** 0x00 if it is not. |
| 9272 | 9293 | ** |
| 9273 | -** If argumet pnCol is not NULL, then *pnCol is set to the number of columns | |
| 9294 | +** If argument pnCol is not NULL, then *pnCol is set to the number of columns | |
| 9274 | 9295 | ** in the table. |
| 9275 | 9296 | ** |
| 9276 | 9297 | ** If this function is called when the iterator does not point to a valid |
| 9277 | 9298 | ** entry, SQLITE_MISUSE is returned and the output variables zeroed. Otherwise, |
| 9278 | 9299 | ** SQLITE_OK is returned and the output variables populated as described |
| @@ -9543,11 +9564,11 @@ | ||
| 9543 | 9564 | ** Rows within the changeset and changegroup are identified by the values in |
| 9544 | 9565 | ** their PRIMARY KEY columns. A change in the changeset is considered to |
| 9545 | 9566 | ** apply to the same row as a change already present in the changegroup if |
| 9546 | 9567 | ** the two rows have the same primary key. |
| 9547 | 9568 | ** |
| 9548 | -** Changes to rows that that do not already appear in the changegroup are | |
| 9569 | +** Changes to rows that do not already appear in the changegroup are | |
| 9549 | 9570 | ** simply copied into it. Or, if both the new changeset and the changegroup |
| 9550 | 9571 | ** contain changes that apply to a single row, the final contents of the |
| 9551 | 9572 | ** changegroup depends on the type of each change, as follows: |
| 9552 | 9573 | ** |
| 9553 | 9574 | ** <table border=1 style="margin-left:8ex;margin-right:8ex"> |
| @@ -11411,13 +11432,13 @@ | ||
| 11411 | 11432 | #define TK_GROUP 127 |
| 11412 | 11433 | #define TK_HAVING 128 |
| 11413 | 11434 | #define TK_LIMIT 129 |
| 11414 | 11435 | #define TK_WHERE 130 |
| 11415 | 11436 | #define TK_INTO 131 |
| 11416 | -#define TK_INTEGER 132 | |
| 11417 | -#define TK_FLOAT 133 | |
| 11418 | -#define TK_BLOB 134 | |
| 11437 | +#define TK_FLOAT 132 | |
| 11438 | +#define TK_BLOB 133 | |
| 11439 | +#define TK_INTEGER 134 | |
| 11419 | 11440 | #define TK_VARIABLE 135 |
| 11420 | 11441 | #define TK_CASE 136 |
| 11421 | 11442 | #define TK_WHEN 137 |
| 11422 | 11443 | #define TK_THEN 138 |
| 11423 | 11444 | #define TK_ELSE 139 |
| @@ -12675,19 +12696,19 @@ | ||
| 12675 | 12696 | #define OP_SorterData 120 /* synopsis: r[P2]=data */ |
| 12676 | 12697 | #define OP_RowKey 121 /* synopsis: r[P2]=key */ |
| 12677 | 12698 | #define OP_RowData 122 /* synopsis: r[P2]=data */ |
| 12678 | 12699 | #define OP_Rowid 123 /* synopsis: r[P2]=rowid */ |
| 12679 | 12700 | #define OP_NullRow 124 |
| 12680 | -#define OP_SorterInsert 125 | |
| 12701 | +#define OP_SorterInsert 125 /* synopsis: key=r[P2] */ | |
| 12681 | 12702 | #define OP_IdxInsert 126 /* synopsis: key=r[P2] */ |
| 12682 | 12703 | #define OP_IdxDelete 127 /* synopsis: key=r[P2@P3] */ |
| 12683 | 12704 | #define OP_Seek 128 /* synopsis: Move P3 to P1.rowid */ |
| 12684 | 12705 | #define OP_IdxRowid 129 /* synopsis: r[P2]=rowid */ |
| 12685 | 12706 | #define OP_Destroy 130 |
| 12686 | 12707 | #define OP_Clear 131 |
| 12687 | -#define OP_ResetSorter 132 | |
| 12688 | -#define OP_Real 133 /* same as TK_FLOAT, synopsis: r[P2]=P4 */ | |
| 12708 | +#define OP_Real 132 /* same as TK_FLOAT, synopsis: r[P2]=P4 */ | |
| 12709 | +#define OP_ResetSorter 133 | |
| 12689 | 12710 | #define OP_CreateIndex 134 /* synopsis: r[P2]=root iDb=P1 */ |
| 12690 | 12711 | #define OP_CreateTable 135 /* synopsis: r[P2]=root iDb=P1 */ |
| 12691 | 12712 | #define OP_ParseSchema 136 |
| 12692 | 12713 | #define OP_LoadAnalysis 137 |
| 12693 | 12714 | #define OP_DropTable 138 |
| @@ -12741,11 +12762,11 @@ | ||
| 12741 | 12762 | /* 88 */ 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00,\ |
| 12742 | 12763 | /* 96 */ 0x00, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,\ |
| 12743 | 12764 | /* 104 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ |
| 12744 | 12765 | /* 112 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,\ |
| 12745 | 12766 | /* 120 */ 0x00, 0x00, 0x00, 0x10, 0x00, 0x04, 0x04, 0x00,\ |
| 12746 | -/* 128 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x10,\ | |
| 12767 | +/* 128 */ 0x00, 0x10, 0x10, 0x00, 0x10, 0x00, 0x10, 0x10,\ | |
| 12747 | 12768 | /* 136 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x10,\ |
| 12748 | 12769 | /* 144 */ 0x00, 0x04, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00,\ |
| 12749 | 12770 | /* 152 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10,\ |
| 12750 | 12771 | /* 160 */ 0x00, 0x00, 0x00,} |
| 12751 | 12772 | |
| @@ -13030,11 +13051,11 @@ | ||
| 13030 | 13051 | int, |
| 13031 | 13052 | int, |
| 13032 | 13053 | int, |
| 13033 | 13054 | void(*)(DbPage*) |
| 13034 | 13055 | ); |
| 13035 | -SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager); | |
| 13056 | +SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3*); | |
| 13036 | 13057 | SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager*, int, unsigned char*); |
| 13037 | 13058 | |
| 13038 | 13059 | /* Functions used to configure a Pager object. */ |
| 13039 | 13060 | SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(Pager*, int(*)(void *), void *); |
| 13040 | 13061 | SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager*, u32*, int); |
| @@ -13081,19 +13102,22 @@ | ||
| 13081 | 13102 | SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int n); |
| 13082 | 13103 | SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint); |
| 13083 | 13104 | SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager); |
| 13084 | 13105 | |
| 13085 | 13106 | #ifndef SQLITE_OMIT_WAL |
| 13086 | -SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, int, int*, int*); | |
| 13107 | +SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, sqlite3*, int, int*, int*); | |
| 13087 | 13108 | SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager); |
| 13088 | 13109 | SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager); |
| 13089 | 13110 | SQLITE_PRIVATE int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen); |
| 13090 | -SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager); | |
| 13111 | +SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager, sqlite3*); | |
| 13112 | +SQLITE_PRIVATE int sqlite3PagerUseWal(Pager *pPager); | |
| 13091 | 13113 | # ifdef SQLITE_ENABLE_SNAPSHOT |
| 13092 | 13114 | SQLITE_PRIVATE int sqlite3PagerSnapshotGet(Pager *pPager, sqlite3_snapshot **ppSnapshot); |
| 13093 | 13115 | SQLITE_PRIVATE int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSnapshot); |
| 13094 | 13116 | # endif |
| 13117 | +#else | |
| 13118 | +# define sqlite3PagerUseWal(x) 0 | |
| 13095 | 13119 | #endif |
| 13096 | 13120 | |
| 13097 | 13121 | #ifdef SQLITE_ENABLE_ZIPVFS |
| 13098 | 13122 | SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager); |
| 13099 | 13123 | #endif |
| @@ -14060,10 +14084,11 @@ | ||
| 14060 | 14084 | #define SQLITE_QueryOnly 0x04000000 /* Disable database changes */ |
| 14061 | 14085 | #define SQLITE_VdbeEQP 0x08000000 /* Debug EXPLAIN QUERY PLAN */ |
| 14062 | 14086 | #define SQLITE_Vacuum 0x10000000 /* Currently in a VACUUM */ |
| 14063 | 14087 | #define SQLITE_CellSizeCk 0x20000000 /* Check btree cell sizes on load */ |
| 14064 | 14088 | #define SQLITE_Fts3Tokenizer 0x40000000 /* Enable fts3_tokenizer(2) */ |
| 14089 | +#define SQLITE_NoCkptOnClose 0x80000000 /* No checkpoint on close()/DETACH */ | |
| 14065 | 14090 | |
| 14066 | 14091 | |
| 14067 | 14092 | /* |
| 14068 | 14093 | ** Bits of the sqlite3.dbOptFlags field that are used by the |
| 14069 | 14094 | ** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface to |
| @@ -14963,10 +14988,11 @@ | ||
| 14963 | 14988 | #define EP_Unlikely 0x040000 /* unlikely() or likelihood() function */ |
| 14964 | 14989 | #define EP_ConstFunc 0x080000 /* A SQLITE_FUNC_CONSTANT or _SLOCHNG function */ |
| 14965 | 14990 | #define EP_CanBeNull 0x100000 /* Can be null despite NOT NULL constraint */ |
| 14966 | 14991 | #define EP_Subquery 0x200000 /* Tree contains a TK_SELECT operator */ |
| 14967 | 14992 | #define EP_Alias 0x400000 /* Is an alias for a result set column */ |
| 14993 | +#define EP_Leaf 0x800000 /* Expr.pLeft, .pRight, .u.pSelect all NULL */ | |
| 14968 | 14994 | |
| 14969 | 14995 | /* |
| 14970 | 14996 | ** Combinations of two or more EP_* flags |
| 14971 | 14997 | */ |
| 14972 | 14998 | #define EP_Propagate (EP_Collate|EP_Subquery) /* Propagate these bits up tree */ |
| @@ -15514,39 +15540,27 @@ | ||
| 15514 | 15540 | u8 mayAbort; /* True if statement may throw an ABORT exception */ |
| 15515 | 15541 | u8 hasCompound; /* Need to invoke convertCompoundSelectToSubquery() */ |
| 15516 | 15542 | u8 okConstFactor; /* OK to factor out constants */ |
| 15517 | 15543 | u8 disableLookaside; /* Number of times lookaside has been disabled */ |
| 15518 | 15544 | u8 nColCache; /* Number of entries in aColCache[] */ |
| 15519 | - int aTempReg[8]; /* Holding area for temporary registers */ | |
| 15520 | 15545 | int nRangeReg; /* Size of the temporary register block */ |
| 15521 | 15546 | int iRangeReg; /* First register in temporary register block */ |
| 15522 | 15547 | int nErr; /* Number of errors seen */ |
| 15523 | 15548 | int nTab; /* Number of previously allocated VDBE cursors */ |
| 15524 | 15549 | int nMem; /* Number of memory cells used so far */ |
| 15525 | - int nSet; /* Number of sets used so far */ | |
| 15526 | 15550 | int nOpAlloc; /* Number of slots allocated for Vdbe.aOp[] */ |
| 15527 | 15551 | int szOpAlloc; /* Bytes of memory space allocated for Vdbe.aOp[] */ |
| 15528 | - int iFixedOp; /* Never back out opcodes iFixedOp-1 or earlier */ | |
| 15529 | 15552 | int ckBase; /* Base register of data during check constraints */ |
| 15530 | 15553 | int iSelfTab; /* Table of an index whose exprs are being coded */ |
| 15531 | 15554 | int iCacheLevel; /* ColCache valid when aColCache[].iLevel<=iCacheLevel */ |
| 15532 | 15555 | int iCacheCnt; /* Counter used to generate aColCache[].lru values */ |
| 15533 | 15556 | int nLabel; /* Number of labels used */ |
| 15534 | 15557 | int *aLabel; /* Space to hold the labels */ |
| 15535 | - struct yColCache { | |
| 15536 | - int iTable; /* Table cursor number */ | |
| 15537 | - i16 iColumn; /* Table column number */ | |
| 15538 | - u8 tempReg; /* iReg is a temp register that needs to be freed */ | |
| 15539 | - int iLevel; /* Nesting level */ | |
| 15540 | - int iReg; /* Reg with value of this column. 0 means none. */ | |
| 15541 | - int lru; /* Least recently used entry has the smallest value */ | |
| 15542 | - } aColCache[SQLITE_N_COLCACHE]; /* One for each column cache entry */ | |
| 15543 | 15558 | ExprList *pConstExpr;/* Constant expressions */ |
| 15544 | 15559 | Token constraintName;/* Name of the constraint currently being parsed */ |
| 15545 | 15560 | yDbMask writeMask; /* Start a write transaction on these databases */ |
| 15546 | 15561 | yDbMask cookieMask; /* Bitmask of schema verified databases */ |
| 15547 | - int cookieValue[SQLITE_MAX_ATTACHED+2]; /* Values of cookies to verify */ | |
| 15548 | 15562 | int regRowid; /* Register holding rowid of CREATE TABLE entry */ |
| 15549 | 15563 | int regRoot; /* Register holding root page number for new objects */ |
| 15550 | 15564 | int nMaxArg; /* Max args passed to user function by sub-program */ |
| 15551 | 15565 | #if SELECTTRACE_ENABLED |
| 15552 | 15566 | int nSelect; /* Number of SELECT statements seen */ |
| @@ -15555,21 +15569,38 @@ | ||
| 15555 | 15569 | #ifndef SQLITE_OMIT_SHARED_CACHE |
| 15556 | 15570 | int nTableLock; /* Number of locks in aTableLock */ |
| 15557 | 15571 | TableLock *aTableLock; /* Required table locks for shared-cache mode */ |
| 15558 | 15572 | #endif |
| 15559 | 15573 | AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters */ |
| 15560 | - | |
| 15561 | - /* Information used while coding trigger programs. */ | |
| 15562 | 15574 | Parse *pToplevel; /* Parse structure for main program (or NULL) */ |
| 15563 | 15575 | Table *pTriggerTab; /* Table triggers are being coded for */ |
| 15564 | 15576 | int addrCrTab; /* Address of OP_CreateTable opcode on CREATE TABLE */ |
| 15565 | 15577 | u32 nQueryLoop; /* Est number of iterations of a query (10*log2(N)) */ |
| 15566 | 15578 | u32 oldmask; /* Mask of old.* columns referenced */ |
| 15567 | 15579 | u32 newmask; /* Mask of new.* columns referenced */ |
| 15568 | 15580 | u8 eTriggerOp; /* TK_UPDATE, TK_INSERT or TK_DELETE */ |
| 15569 | 15581 | u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */ |
| 15570 | 15582 | u8 disableTriggers; /* True to disable triggers */ |
| 15583 | + | |
| 15584 | + /************************************************************************** | |
| 15585 | + ** Fields above must be initialized to zero. The fields that follow, | |
| 15586 | + ** down to the beginning of the recursive section, do not need to be | |
| 15587 | + ** initialized as they will be set before being used. The boundary is | |
| 15588 | + ** determined by offsetof(Parse,aColCache). | |
| 15589 | + **************************************************************************/ | |
| 15590 | + | |
| 15591 | + struct yColCache { | |
| 15592 | + int iTable; /* Table cursor number */ | |
| 15593 | + i16 iColumn; /* Table column number */ | |
| 15594 | + u8 tempReg; /* iReg is a temp register that needs to be freed */ | |
| 15595 | + int iLevel; /* Nesting level */ | |
| 15596 | + int iReg; /* Reg with value of this column. 0 means none. */ | |
| 15597 | + int lru; /* Least recently used entry has the smallest value */ | |
| 15598 | + } aColCache[SQLITE_N_COLCACHE]; /* One for each column cache entry */ | |
| 15599 | + int aTempReg[8]; /* Holding area for temporary registers */ | |
| 15600 | + Token sNameToken; /* Token with unqualified schema object name */ | |
| 15601 | + Token sLastToken; /* The last token parsed */ | |
| 15571 | 15602 | |
| 15572 | 15603 | /************************************************************************ |
| 15573 | 15604 | ** Above is constant between recursions. Below is reset before and after |
| 15574 | 15605 | ** each recursion. The boundary between these two regions is determined |
| 15575 | 15606 | ** using offsetof(Parse,nVar) so the nVar field must be the first field |
| @@ -15582,11 +15613,10 @@ | ||
| 15582 | 15613 | u8 explain; /* True if the EXPLAIN flag is found on the query */ |
| 15583 | 15614 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 15584 | 15615 | u8 declareVtab; /* True if inside sqlite3_declare_vtab() */ |
| 15585 | 15616 | int nVtabLock; /* Number of virtual tables to lock */ |
| 15586 | 15617 | #endif |
| 15587 | - int nAlias; /* Number of aliased result set columns */ | |
| 15588 | 15618 | int nHeight; /* Expression tree height of current sub-select */ |
| 15589 | 15619 | #ifndef SQLITE_OMIT_EXPLAIN |
| 15590 | 15620 | int iSelectId; /* ID of current select for EXPLAIN output */ |
| 15591 | 15621 | int iNextSelectId; /* Next available select ID for EXPLAIN output */ |
| 15592 | 15622 | #endif |
| @@ -15594,12 +15624,10 @@ | ||
| 15594 | 15624 | Vdbe *pReprepare; /* VM being reprepared (sqlite3Reprepare()) */ |
| 15595 | 15625 | const char *zTail; /* All SQL text past the last semicolon parsed */ |
| 15596 | 15626 | Table *pNewTable; /* A table being constructed by CREATE TABLE */ |
| 15597 | 15627 | Trigger *pNewTrigger; /* Trigger under construct by a CREATE TRIGGER */ |
| 15598 | 15628 | const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */ |
| 15599 | - Token sNameToken; /* Token with unqualified schema object name */ | |
| 15600 | - Token sLastToken; /* The last token parsed */ | |
| 15601 | 15629 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 15602 | 15630 | Token sArg; /* Complete text of a module argument */ |
| 15603 | 15631 | Table **apVtabLock; /* Pointer to virtual tables needing locking */ |
| 15604 | 15632 | #endif |
| 15605 | 15633 | Table *pZombieTab; /* List of Table objects to delete after code gen */ |
| @@ -15606,10 +15634,18 @@ | ||
| 15606 | 15634 | TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */ |
| 15607 | 15635 | With *pWith; /* Current WITH clause, or NULL */ |
| 15608 | 15636 | With *pWithToFree; /* Free this WITH object at the end of the parse */ |
| 15609 | 15637 | }; |
| 15610 | 15638 | |
| 15639 | +/* | |
| 15640 | +** Sizes and pointers of various parts of the Parse object. | |
| 15641 | +*/ | |
| 15642 | +#define PARSE_HDR_SZ offsetof(Parse,aColCache) /* Recursive part w/o aColCache*/ | |
| 15643 | +#define PARSE_RECURSE_SZ offsetof(Parse,nVar) /* Recursive part */ | |
| 15644 | +#define PARSE_TAIL_SZ (sizeof(Parse)-PARSE_RECURSE_SZ) /* Non-recursive part */ | |
| 15645 | +#define PARSE_TAIL(X) (((char*)(X))+PARSE_RECURSE_SZ) /* Pointer to tail */ | |
| 15646 | + | |
| 15611 | 15647 | /* |
| 15612 | 15648 | ** Return true if currently inside an sqlite3_declare_vtab() call. |
| 15613 | 15649 | */ |
| 15614 | 15650 | #ifdef SQLITE_OMIT_VIRTUALTABLE |
| 15615 | 15651 | #define IN_DECLARE_VTAB 0 |
| @@ -16169,11 +16205,11 @@ | ||
| 16169 | 16205 | SQLITE_PRIVATE void sqlite3ExprAttachSubtrees(sqlite3*,Expr*,Expr*,Expr*); |
| 16170 | 16206 | SQLITE_PRIVATE Expr *sqlite3PExpr(Parse*, int, Expr*, Expr*, const Token*); |
| 16171 | 16207 | SQLITE_PRIVATE void sqlite3PExprAddSelect(Parse*, Expr*, Select*); |
| 16172 | 16208 | SQLITE_PRIVATE Expr *sqlite3ExprAnd(sqlite3*,Expr*, Expr*); |
| 16173 | 16209 | SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*); |
| 16174 | -SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse*, Expr*); | |
| 16210 | +SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse*, Expr*, u32); | |
| 16175 | 16211 | SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3*, Expr*); |
| 16176 | 16212 | SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*); |
| 16177 | 16213 | SQLITE_PRIVATE ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*); |
| 16178 | 16214 | SQLITE_PRIVATE void sqlite3ExprListSetSortOrder(ExprList*,int); |
| 16179 | 16215 | SQLITE_PRIVATE void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int); |
| @@ -16989,20 +17025,17 @@ | ||
| 16989 | 17025 | ** If x is a lower-case ASCII character, then its upper-case equivalent |
| 16990 | 17026 | ** is (x - 0x20). Therefore toupper() can be implemented as: |
| 16991 | 17027 | ** |
| 16992 | 17028 | ** (x & ~(map[x]&0x20)) |
| 16993 | 17029 | ** |
| 16994 | -** Standard function tolower() is implemented using the sqlite3UpperToLower[] | |
| 17030 | +** The equivalent of tolower() is implemented using the sqlite3UpperToLower[] | |
| 16995 | 17031 | ** array. tolower() is used more often than toupper() by SQLite. |
| 16996 | 17032 | ** |
| 16997 | -** Bit 0x40 is set if the character non-alphanumeric and can be used in an | |
| 17033 | +** Bit 0x40 is set if the character is non-alphanumeric and can be used in an | |
| 16998 | 17034 | ** SQLite identifier. Identifiers are alphanumerics, "_", "$", and any |
| 16999 | 17035 | ** non-ASCII UTF character. Hence the test for whether or not a character is |
| 17000 | 17036 | ** part of an identifier is 0x46. |
| 17001 | -** | |
| 17002 | -** SQLite's versions are identical to the standard versions assuming a | |
| 17003 | -** locale of "C". They are implemented as macros in sqliteInt.h. | |
| 17004 | 17037 | */ |
| 17005 | 17038 | #ifdef SQLITE_ASCII |
| 17006 | 17039 | SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[256] = { |
| 17007 | 17040 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 00..07 ........ */ |
| 17008 | 17041 | 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, /* 08..0f ........ */ |
| @@ -17071,11 +17104,11 @@ | ||
| 17071 | 17104 | #ifndef SQLITE_SORTER_PMASZ |
| 17072 | 17105 | # define SQLITE_SORTER_PMASZ 250 |
| 17073 | 17106 | #endif |
| 17074 | 17107 | |
| 17075 | 17108 | /* Statement journals spill to disk when their size exceeds the following |
| 17076 | -** threashold (in bytes). 0 means that statement journals are created and | |
| 17109 | +** threshold (in bytes). 0 means that statement journals are created and | |
| 17077 | 17110 | ** written to disk immediately (the default behavior for SQLite versions |
| 17078 | 17111 | ** before 3.12.0). -1 means always keep the entire statement journal in |
| 17079 | 17112 | ** memory. (The statement journal is also always held entirely in memory |
| 17080 | 17113 | ** if journal_mode=MEMORY or if temp_store=MEMORY, regardless of this |
| 17081 | 17114 | ** setting.) |
| @@ -17159,11 +17192,11 @@ | ||
| 17159 | 17192 | |
| 17160 | 17193 | /* |
| 17161 | 17194 | ** The value of the "pending" byte must be 0x40000000 (1 byte past the |
| 17162 | 17195 | ** 1-gibabyte boundary) in a compatible database. SQLite never uses |
| 17163 | 17196 | ** the database page that contains the pending byte. It never attempts |
| 17164 | -** to read or write that page. The pending byte page is set assign | |
| 17197 | +** to read or write that page. The pending byte page is set aside | |
| 17165 | 17198 | ** for use by the VFS layers as space for managing file locks. |
| 17166 | 17199 | ** |
| 17167 | 17200 | ** During testing, it is often desirable to move the pending byte to |
| 17168 | 17201 | ** a different position in the file. This allows code that has to |
| 17169 | 17202 | ** deal with the pending byte to run on files that are much smaller |
| @@ -17260,10 +17293,13 @@ | ||
| 17260 | 17293 | #if SQLITE_DEFAULT_LOCKING_MODE |
| 17261 | 17294 | "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE), |
| 17262 | 17295 | #endif |
| 17263 | 17296 | #if defined(SQLITE_DEFAULT_MMAP_SIZE) && !defined(SQLITE_DEFAULT_MMAP_SIZE_xc) |
| 17264 | 17297 | "DEFAULT_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_MMAP_SIZE), |
| 17298 | +#endif | |
| 17299 | +#if SQLITE_DIRECT_OVERFLOW_READ | |
| 17300 | + "DIRECT_OVERFLOW_READ", | |
| 17265 | 17301 | #endif |
| 17266 | 17302 | #if SQLITE_DISABLE_DIRSYNC |
| 17267 | 17303 | "DISABLE_DIRSYNC", |
| 17268 | 17304 | #endif |
| 17269 | 17305 | #if SQLITE_DISABLE_LFS |
| @@ -17346,10 +17382,13 @@ | ||
| 17346 | 17382 | #if SQLITE_ENABLE_UNLOCK_NOTIFY |
| 17347 | 17383 | "ENABLE_UNLOCK_NOTIFY", |
| 17348 | 17384 | #endif |
| 17349 | 17385 | #if SQLITE_ENABLE_UPDATE_DELETE_LIMIT |
| 17350 | 17386 | "ENABLE_UPDATE_DELETE_LIMIT", |
| 17387 | +#endif | |
| 17388 | +#if defined(SQLITE_ENABLE_URI_00_ERROR) | |
| 17389 | + "ENABLE_URI_00_ERROR", | |
| 17351 | 17390 | #endif |
| 17352 | 17391 | #if SQLITE_HAS_CODEC |
| 17353 | 17392 | "HAS_CODEC", |
| 17354 | 17393 | #endif |
| 17355 | 17394 | #if HAVE_ISNAN || SQLITE_HAVE_ISNAN |
| @@ -17719,13 +17758,10 @@ | ||
| 17719 | 17758 | typedef unsigned Bool; |
| 17720 | 17759 | |
| 17721 | 17760 | /* Opaque type used by code in vdbesort.c */ |
| 17722 | 17761 | typedef struct VdbeSorter VdbeSorter; |
| 17723 | 17762 | |
| 17724 | -/* Opaque type used by the explainer */ | |
| 17725 | -typedef struct Explain Explain; | |
| 17726 | - | |
| 17727 | 17763 | /* Elements of the linked list at Vdbe.pAuxData */ |
| 17728 | 17764 | typedef struct AuxData AuxData; |
| 17729 | 17765 | |
| 17730 | 17766 | /* Types of VDBE cursors */ |
| 17731 | 17767 | #define CURTYPE_BTREE 0 |
| @@ -17796,10 +17832,16 @@ | ||
| 17796 | 17832 | /* 2*nField extra array elements allocated for aType[], beyond the one |
| 17797 | 17833 | ** static element declared in the structure. nField total array slots for |
| 17798 | 17834 | ** aType[] and nField+1 array slots for aOffset[] */ |
| 17799 | 17835 | }; |
| 17800 | 17836 | |
| 17837 | + | |
| 17838 | +/* | |
| 17839 | +** A value for VdbeCursor.cacheStatus that means the cache is always invalid. | |
| 17840 | +*/ | |
| 17841 | +#define CACHE_STALE 0 | |
| 17842 | + | |
| 17801 | 17843 | /* |
| 17802 | 17844 | ** When a sub-program is executed (OP_Program), a structure of this type |
| 17803 | 17845 | ** is allocated to store the current value of the program counter, as |
| 17804 | 17846 | ** well as the current memory cell array and various other frame specific |
| 17805 | 17847 | ** values stored in the Vdbe struct. When the sub-program is finished, |
| @@ -17840,15 +17882,10 @@ | ||
| 17840 | 17882 | int nDbChange; /* Value of db->nChange */ |
| 17841 | 17883 | }; |
| 17842 | 17884 | |
| 17843 | 17885 | #define VdbeFrameMem(p) ((Mem *)&((u8 *)p)[ROUND8(sizeof(VdbeFrame))]) |
| 17844 | 17886 | |
| 17845 | -/* | |
| 17846 | -** A value for VdbeCursor.cacheValid that means the cache is always invalid. | |
| 17847 | -*/ | |
| 17848 | -#define CACHE_STALE 0 | |
| 17849 | - | |
| 17850 | 17887 | /* |
| 17851 | 17888 | ** Internally, the vdbe manipulates nearly all SQL values as Mem |
| 17852 | 17889 | ** structures. Each Mem struct may cache multiple representations (string, |
| 17853 | 17890 | ** integer etc.) of the same value. |
| 17854 | 17891 | */ |
| @@ -17985,22 +18022,10 @@ | ||
| 17985 | 18022 | u8 fErrorOrAux; /* isError!=0 or pVdbe->pAuxData modified */ |
| 17986 | 18023 | u8 argc; /* Number of arguments */ |
| 17987 | 18024 | sqlite3_value *argv[1]; /* Argument set */ |
| 17988 | 18025 | }; |
| 17989 | 18026 | |
| 17990 | -/* | |
| 17991 | -** An Explain object accumulates indented output which is helpful | |
| 17992 | -** in describing recursive data structures. | |
| 17993 | -*/ | |
| 17994 | -struct Explain { | |
| 17995 | - Vdbe *pVdbe; /* Attach the explanation to this Vdbe */ | |
| 17996 | - StrAccum str; /* The string being accumulated */ | |
| 17997 | - int nIndent; /* Number of elements in aIndent */ | |
| 17998 | - u16 aIndent[100]; /* Levels of indentation */ | |
| 17999 | - char zBase[100]; /* Initial space */ | |
| 18000 | -}; | |
| 18001 | - | |
| 18002 | 18027 | /* A bitfield type for use inside of structures. Always follow with :N where |
| 18003 | 18028 | ** N is the number of bits. |
| 18004 | 18029 | */ |
| 18005 | 18030 | typedef unsigned bft; /* Bit Field Type */ |
| 18006 | 18031 | |
| @@ -18021,57 +18046,61 @@ | ||
| 18021 | 18046 | ** The "sqlite3_stmt" structure pointer that is returned by sqlite3_prepare() |
| 18022 | 18047 | ** is really a pointer to an instance of this structure. |
| 18023 | 18048 | */ |
| 18024 | 18049 | struct Vdbe { |
| 18025 | 18050 | sqlite3 *db; /* The database connection that owns this statement */ |
| 18051 | + Vdbe *pPrev,*pNext; /* Linked list of VDBEs with the same Vdbe.db */ | |
| 18052 | + Parse *pParse; /* Parsing context used to create this Vdbe */ | |
| 18053 | + ynVar nVar; /* Number of entries in aVar[] */ | |
| 18054 | + ynVar nzVar; /* Number of entries in azVar[] */ | |
| 18055 | + u32 magic; /* Magic number for sanity checking */ | |
| 18056 | + int nMem; /* Number of memory locations currently allocated */ | |
| 18057 | + int nCursor; /* Number of slots in apCsr[] */ | |
| 18058 | + u32 cacheCtr; /* VdbeCursor row cache generation counter */ | |
| 18059 | + int pc; /* The program counter */ | |
| 18060 | + int rc; /* Value to return */ | |
| 18061 | + int nChange; /* Number of db changes made since last reset */ | |
| 18062 | + int iStatement; /* Statement number (or 0 if has not opened stmt) */ | |
| 18063 | + i64 iCurrentTime; /* Value of julianday('now') for this statement */ | |
| 18064 | + i64 nFkConstraint; /* Number of imm. FK constraints this VM */ | |
| 18065 | + i64 nStmtDefCons; /* Number of def. constraints when stmt started */ | |
| 18066 | + i64 nStmtDefImmCons; /* Number of def. imm constraints when stmt started */ | |
| 18067 | + | |
| 18068 | + /* When allocating a new Vdbe object, all of the fields below should be | |
| 18069 | + ** initialized to zero or NULL */ | |
| 18070 | + | |
| 18026 | 18071 | Op *aOp; /* Space to hold the virtual machine's program */ |
| 18027 | 18072 | Mem *aMem; /* The memory locations */ |
| 18028 | 18073 | Mem **apArg; /* Arguments to currently executing user function */ |
| 18029 | 18074 | Mem *aColName; /* Column names to return */ |
| 18030 | 18075 | Mem *pResultSet; /* Pointer to an array of results */ |
| 18031 | - Parse *pParse; /* Parsing context used to create this Vdbe */ | |
| 18032 | - int nMem; /* Number of memory locations currently allocated */ | |
| 18033 | - int nOp; /* Number of instructions in the program */ | |
| 18034 | - int nCursor; /* Number of slots in apCsr[] */ | |
| 18035 | - u32 magic; /* Magic number for sanity checking */ | |
| 18036 | 18076 | char *zErrMsg; /* Error message written here */ |
| 18037 | - Vdbe *pPrev,*pNext; /* Linked list of VDBEs with the same Vdbe.db */ | |
| 18038 | 18077 | VdbeCursor **apCsr; /* One element of this array for each open cursor */ |
| 18039 | 18078 | Mem *aVar; /* Values for the OP_Variable opcode. */ |
| 18040 | 18079 | char **azVar; /* Name of variables */ |
| 18041 | - ynVar nVar; /* Number of entries in aVar[] */ | |
| 18042 | - ynVar nzVar; /* Number of entries in azVar[] */ | |
| 18043 | - u32 cacheCtr; /* VdbeCursor row cache generation counter */ | |
| 18044 | - int pc; /* The program counter */ | |
| 18045 | - int rc; /* Value to return */ | |
| 18080 | +#ifndef SQLITE_OMIT_TRACE | |
| 18081 | + i64 startTime; /* Time when query started - used for profiling */ | |
| 18082 | +#endif | |
| 18083 | + int nOp; /* Number of instructions in the program */ | |
| 18046 | 18084 | #ifdef SQLITE_DEBUG |
| 18047 | 18085 | int rcApp; /* errcode set by sqlite3_result_error_code() */ |
| 18048 | 18086 | #endif |
| 18049 | 18087 | u16 nResColumn; /* Number of columns in one row of the result set */ |
| 18050 | 18088 | u8 errorAction; /* Recovery action to do in case of an error */ |
| 18089 | + u8 minWriteFileFormat; /* Minimum file format for writable database files */ | |
| 18051 | 18090 | bft expired:1; /* True if the VM needs to be recompiled */ |
| 18052 | 18091 | bft doingRerun:1; /* True if rerunning after an auto-reprepare */ |
| 18053 | - u8 minWriteFileFormat; /* Minimum file format for writable database files */ | |
| 18054 | 18092 | bft explain:2; /* True if EXPLAIN present on SQL command */ |
| 18055 | 18093 | bft changeCntOn:1; /* True to update the change-counter */ |
| 18056 | 18094 | bft runOnlyOnce:1; /* Automatically expire on reset */ |
| 18057 | 18095 | bft usesStmtJournal:1; /* True if uses a statement journal */ |
| 18058 | 18096 | bft readOnly:1; /* True for statements that do not write */ |
| 18059 | 18097 | bft bIsReader:1; /* True for statements that read */ |
| 18060 | 18098 | bft isPrepareV2:1; /* True if prepared with prepare_v2() */ |
| 18061 | - int nChange; /* Number of db changes made since last reset */ | |
| 18062 | 18099 | yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */ |
| 18063 | 18100 | yDbMask lockMask; /* Subset of btreeMask that requires a lock */ |
| 18064 | - int iStatement; /* Statement number (or 0 if has not opened stmt) */ | |
| 18065 | 18101 | u32 aCounter[5]; /* Counters used by sqlite3_stmt_status() */ |
| 18066 | -#ifndef SQLITE_OMIT_TRACE | |
| 18067 | - i64 startTime; /* Time when query started - used for profiling */ | |
| 18068 | -#endif | |
| 18069 | - i64 iCurrentTime; /* Value of julianday('now') for this statement */ | |
| 18070 | - i64 nFkConstraint; /* Number of imm. FK constraints this VM */ | |
| 18071 | - i64 nStmtDefCons; /* Number of def. constraints when stmt started */ | |
| 18072 | - i64 nStmtDefImmCons; /* Number of def. imm constraints when stmt started */ | |
| 18073 | 18102 | char *zSql; /* Text of the SQL statement that generated this */ |
| 18074 | 18103 | void *pFree; /* Free this when deleting the vdbe */ |
| 18075 | 18104 | VdbeFrame *pFrame; /* Parent frame */ |
| 18076 | 18105 | VdbeFrame *pDelFrame; /* List of frame objects to free on VM reset */ |
| 18077 | 18106 | int nFrame; /* Number of frames in pFrame list */ |
| @@ -18086,14 +18115,15 @@ | ||
| 18086 | 18115 | }; |
| 18087 | 18116 | |
| 18088 | 18117 | /* |
| 18089 | 18118 | ** The following are allowed values for Vdbe.magic |
| 18090 | 18119 | */ |
| 18091 | -#define VDBE_MAGIC_INIT 0x26bceaa5 /* Building a VDBE program */ | |
| 18092 | -#define VDBE_MAGIC_RUN 0xbdf20da3 /* VDBE is ready to execute */ | |
| 18093 | -#define VDBE_MAGIC_HALT 0x519c2973 /* VDBE has completed execution */ | |
| 18094 | -#define VDBE_MAGIC_DEAD 0xb606c3c8 /* The VDBE has been deallocated */ | |
| 18120 | +#define VDBE_MAGIC_INIT 0x16bceaa5 /* Building a VDBE program */ | |
| 18121 | +#define VDBE_MAGIC_RUN 0x2df20da3 /* VDBE is ready to execute */ | |
| 18122 | +#define VDBE_MAGIC_HALT 0x319c2973 /* VDBE has completed execution */ | |
| 18123 | +#define VDBE_MAGIC_RESET 0x48fa9f76 /* Reset and ready to run again */ | |
| 18124 | +#define VDBE_MAGIC_DEAD 0x5606c3c8 /* The VDBE has been deallocated */ | |
| 18095 | 18125 | |
| 18096 | 18126 | /* |
| 18097 | 18127 | ** Structure used to store the context required by the |
| 18098 | 18128 | ** sqlite3_preupdate_*() API functions. |
| 18099 | 18129 | */ |
| @@ -18106,12 +18136,12 @@ | ||
| 18106 | 18136 | UnpackedRecord *pUnpacked; /* Unpacked version of aRecord[] */ |
| 18107 | 18137 | UnpackedRecord *pNewUnpacked; /* Unpacked version of new.* record */ |
| 18108 | 18138 | int iNewReg; /* Register for new.* values */ |
| 18109 | 18139 | i64 iKey1; /* First key value passed to hook */ |
| 18110 | 18140 | i64 iKey2; /* Second key value passed to hook */ |
| 18111 | - int iPKey; /* If not negative index of IPK column */ | |
| 18112 | 18141 | Mem *aNew; /* Array of new.* values */ |
| 18142 | + Table *pTab; /* Schema object being upated */ | |
| 18113 | 18143 | }; |
| 18114 | 18144 | |
| 18115 | 18145 | /* |
| 18116 | 18146 | ** Function prototypes |
| 18117 | 18147 | */ |
| @@ -24599,13 +24629,12 @@ | ||
| 24599 | 24629 | char *zNew; |
| 24600 | 24630 | size_t n; |
| 24601 | 24631 | if( z==0 ){ |
| 24602 | 24632 | return 0; |
| 24603 | 24633 | } |
| 24604 | - n = sqlite3Strlen30(z) + 1; | |
| 24605 | - assert( (n&0x7fffffff)==n ); | |
| 24606 | - zNew = sqlite3DbMallocRaw(db, (int)n); | |
| 24634 | + n = strlen(z) + 1; | |
| 24635 | + zNew = sqlite3DbMallocRaw(db, n); | |
| 24607 | 24636 | if( zNew ){ |
| 24608 | 24637 | memcpy(zNew, z, n); |
| 24609 | 24638 | } |
| 24610 | 24639 | return zNew; |
| 24611 | 24640 | } |
| @@ -28775,11 +28804,15 @@ | ||
| 28775 | 28804 | */ |
| 28776 | 28805 | static unsigned int strHash(const char *z){ |
| 28777 | 28806 | unsigned int h = 0; |
| 28778 | 28807 | unsigned char c; |
| 28779 | 28808 | while( (c = (unsigned char)*z++)!=0 ){ /*OPTIMIZATION-IF-TRUE*/ |
| 28780 | - h = (h<<3) ^ h ^ sqlite3UpperToLower[c]; | |
| 28809 | + /* Knuth multiplicative hashing. (Sorting & Searching, p. 510). | |
| 28810 | + ** 0x9e3779b1 is 2654435761 which is the closest prime number to | |
| 28811 | + ** (2**32)*golden_ratio, where golden_ratio = (sqrt(5) - 1)/2. */ | |
| 28812 | + h += sqlite3UpperToLower[c]; | |
| 28813 | + h *= 0x9e3779b1; | |
| 28781 | 28814 | } |
| 28782 | 28815 | return h; |
| 28783 | 28816 | } |
| 28784 | 28817 | |
| 28785 | 28818 | |
| @@ -29124,19 +29157,19 @@ | ||
| 29124 | 29157 | /* 120 */ "SorterData" OpHelp("r[P2]=data"), |
| 29125 | 29158 | /* 121 */ "RowKey" OpHelp("r[P2]=key"), |
| 29126 | 29159 | /* 122 */ "RowData" OpHelp("r[P2]=data"), |
| 29127 | 29160 | /* 123 */ "Rowid" OpHelp("r[P2]=rowid"), |
| 29128 | 29161 | /* 124 */ "NullRow" OpHelp(""), |
| 29129 | - /* 125 */ "SorterInsert" OpHelp(""), | |
| 29162 | + /* 125 */ "SorterInsert" OpHelp("key=r[P2]"), | |
| 29130 | 29163 | /* 126 */ "IdxInsert" OpHelp("key=r[P2]"), |
| 29131 | 29164 | /* 127 */ "IdxDelete" OpHelp("key=r[P2@P3]"), |
| 29132 | 29165 | /* 128 */ "Seek" OpHelp("Move P3 to P1.rowid"), |
| 29133 | 29166 | /* 129 */ "IdxRowid" OpHelp("r[P2]=rowid"), |
| 29134 | 29167 | /* 130 */ "Destroy" OpHelp(""), |
| 29135 | 29168 | /* 131 */ "Clear" OpHelp(""), |
| 29136 | - /* 132 */ "ResetSorter" OpHelp(""), | |
| 29137 | - /* 133 */ "Real" OpHelp("r[P2]=P4"), | |
| 29169 | + /* 132 */ "Real" OpHelp("r[P2]=P4"), | |
| 29170 | + /* 133 */ "ResetSorter" OpHelp(""), | |
| 29138 | 29171 | /* 134 */ "CreateIndex" OpHelp("r[P2]=root iDb=P1"), |
| 29139 | 29172 | /* 135 */ "CreateTable" OpHelp("r[P2]=root iDb=P1"), |
| 29140 | 29173 | /* 136 */ "ParseSchema" OpHelp(""), |
| 29141 | 29174 | /* 137 */ "LoadAnalysis" OpHelp(""), |
| 29142 | 29175 | /* 138 */ "DropTable" OpHelp(""), |
| @@ -40671,10 +40704,16 @@ | ||
| 40671 | 40704 | a[1] = winIoerrRetryDelay; |
| 40672 | 40705 | } |
| 40673 | 40706 | OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); |
| 40674 | 40707 | return SQLITE_OK; |
| 40675 | 40708 | } |
| 40709 | + case SQLITE_FCNTL_WIN32_GET_HANDLE: { | |
| 40710 | + LPHANDLE phFile = (LPHANDLE)pArg; | |
| 40711 | + *phFile = pFile->h; | |
| 40712 | + OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); | |
| 40713 | + return SQLITE_OK; | |
| 40714 | + } | |
| 40676 | 40715 | #ifdef SQLITE_TEST |
| 40677 | 40716 | case SQLITE_FCNTL_WIN32_SET_HANDLE: { |
| 40678 | 40717 | LPHANDLE phFile = (LPHANDLE)pArg; |
| 40679 | 40718 | HANDLE hOldFile = pFile->h; |
| 40680 | 40719 | pFile->h = *phFile; |
| @@ -44018,11 +44057,11 @@ | ||
| 44018 | 44057 | ){ |
| 44019 | 44058 | PgHdr *pPgHdr; |
| 44020 | 44059 | assert( pPage!=0 ); |
| 44021 | 44060 | pPgHdr = (PgHdr*)pPage->pExtra; |
| 44022 | 44061 | assert( pPgHdr->pPage==0 ); |
| 44023 | - memset(pPgHdr, 0, sizeof(PgHdr)); | |
| 44062 | + memset(&pPgHdr->pDirty, 0, sizeof(PgHdr) - offsetof(PgHdr,pDirty)); | |
| 44024 | 44063 | pPgHdr->pPage = pPage; |
| 44025 | 44064 | pPgHdr->pData = pPage->pBuf; |
| 44026 | 44065 | pPgHdr->pExtra = (void *)&pPgHdr[1]; |
| 44027 | 44066 | memset(pPgHdr->pExtra, 0, pCache->szExtra); |
| 44028 | 44067 | pPgHdr->pCache = pCache; |
| @@ -44712,11 +44751,11 @@ | ||
| 44712 | 44751 | szBulk = pCache->szAlloc * (i64)pcache1.nInitPage; |
| 44713 | 44752 | }else{ |
| 44714 | 44753 | szBulk = -1024 * (i64)pcache1.nInitPage; |
| 44715 | 44754 | } |
| 44716 | 44755 | if( szBulk > pCache->szAlloc*(i64)pCache->nMax ){ |
| 44717 | - szBulk = pCache->szAlloc*pCache->nMax; | |
| 44756 | + szBulk = pCache->szAlloc*(i64)pCache->nMax; | |
| 44718 | 44757 | } |
| 44719 | 44758 | zBulk = pCache->pBulk = sqlite3Malloc( szBulk ); |
| 44720 | 44759 | sqlite3EndBenignMalloc(); |
| 44721 | 44760 | if( zBulk ){ |
| 44722 | 44761 | int nBulk = sqlite3MallocSize(zBulk)/pCache->szAlloc; |
| @@ -46246,21 +46285,21 @@ | ||
| 46246 | 46285 | #define SQLITE_SYNC_MASK 0x13 /* Mask off the SQLITE_SYNC_* values */ |
| 46247 | 46286 | |
| 46248 | 46287 | #ifdef SQLITE_OMIT_WAL |
| 46249 | 46288 | # define sqlite3WalOpen(x,y,z) 0 |
| 46250 | 46289 | # define sqlite3WalLimit(x,y) |
| 46251 | -# define sqlite3WalClose(w,x,y,z) 0 | |
| 46290 | +# define sqlite3WalClose(v,w,x,y,z) 0 | |
| 46252 | 46291 | # define sqlite3WalBeginReadTransaction(y,z) 0 |
| 46253 | 46292 | # define sqlite3WalEndReadTransaction(z) |
| 46254 | 46293 | # define sqlite3WalDbsize(y) 0 |
| 46255 | 46294 | # define sqlite3WalBeginWriteTransaction(y) 0 |
| 46256 | 46295 | # define sqlite3WalEndWriteTransaction(x) 0 |
| 46257 | 46296 | # define sqlite3WalUndo(x,y,z) 0 |
| 46258 | 46297 | # define sqlite3WalSavepoint(y,z) |
| 46259 | 46298 | # define sqlite3WalSavepointUndo(y,z) 0 |
| 46260 | 46299 | # define sqlite3WalFrames(u,v,w,x,y,z) 0 |
| 46261 | -# define sqlite3WalCheckpoint(r,s,t,u,v,w,x,y,z) 0 | |
| 46300 | +# define sqlite3WalCheckpoint(q,r,s,t,u,v,w,x,y,z) 0 | |
| 46262 | 46301 | # define sqlite3WalCallback(z) 0 |
| 46263 | 46302 | # define sqlite3WalExclusiveMode(y,z) 0 |
| 46264 | 46303 | # define sqlite3WalHeapMemory(z) 0 |
| 46265 | 46304 | # define sqlite3WalFramesize(z) 0 |
| 46266 | 46305 | # define sqlite3WalFindFrame(x,y,z) 0 |
| @@ -46274,11 +46313,11 @@ | ||
| 46274 | 46313 | */ |
| 46275 | 46314 | typedef struct Wal Wal; |
| 46276 | 46315 | |
| 46277 | 46316 | /* Open and close a connection to a write-ahead log. */ |
| 46278 | 46317 | SQLITE_PRIVATE int sqlite3WalOpen(sqlite3_vfs*, sqlite3_file*, const char *, int, i64, Wal**); |
| 46279 | -SQLITE_PRIVATE int sqlite3WalClose(Wal *pWal, int sync_flags, int, u8 *); | |
| 46318 | +SQLITE_PRIVATE int sqlite3WalClose(Wal *pWal, sqlite3*, int sync_flags, int, u8 *); | |
| 46280 | 46319 | |
| 46281 | 46320 | /* Set the limiting size of a WAL file. */ |
| 46282 | 46321 | SQLITE_PRIVATE void sqlite3WalLimit(Wal*, i64); |
| 46283 | 46322 | |
| 46284 | 46323 | /* Used by readers to open (lock) and close (unlock) a snapshot. A |
| @@ -46317,10 +46356,11 @@ | ||
| 46317 | 46356 | SQLITE_PRIVATE int sqlite3WalFrames(Wal *pWal, int, PgHdr *, Pgno, int, int); |
| 46318 | 46357 | |
| 46319 | 46358 | /* Copy pages from the log to the database file */ |
| 46320 | 46359 | SQLITE_PRIVATE int sqlite3WalCheckpoint( |
| 46321 | 46360 | Wal *pWal, /* Write-ahead log connection */ |
| 46361 | + sqlite3 *db, /* Check this handle's interrupt flag */ | |
| 46322 | 46362 | int eMode, /* One of PASSIVE, FULL and RESTART */ |
| 46323 | 46363 | int (*xBusy)(void*), /* Function to call when busy */ |
| 46324 | 46364 | void *pBusyArg, /* Context argument for xBusyHandler */ |
| 46325 | 46365 | int sync_flags, /* Flags to sync db file with (or 0) */ |
| 46326 | 46366 | int nBuf, /* Size of buffer nBuf */ |
| @@ -47161,13 +47201,14 @@ | ||
| 47161 | 47201 | /* |
| 47162 | 47202 | ** Return true if this pager uses a write-ahead log instead of the usual |
| 47163 | 47203 | ** rollback journal. Otherwise false. |
| 47164 | 47204 | */ |
| 47165 | 47205 | #ifndef SQLITE_OMIT_WAL |
| 47166 | -static int pagerUseWal(Pager *pPager){ | |
| 47206 | +SQLITE_PRIVATE int sqlite3PagerUseWal(Pager *pPager){ | |
| 47167 | 47207 | return (pPager->pWal!=0); |
| 47168 | 47208 | } |
| 47209 | +# define pagerUseWal(x) sqlite3PagerUseWal(x) | |
| 47169 | 47210 | #else |
| 47170 | 47211 | # define pagerUseWal(x) 0 |
| 47171 | 47212 | # define pagerRollbackWal(x) 0 |
| 47172 | 47213 | # define pagerWalFrames(v,w,x,y) 0 |
| 47173 | 47214 | # define pagerOpenWalIfPresent(z) SQLITE_OK |
| @@ -50365,21 +50406,22 @@ | ||
| 50365 | 50406 | ** This function always succeeds. If a transaction is active an attempt |
| 50366 | 50407 | ** is made to roll it back. If an error occurs during the rollback |
| 50367 | 50408 | ** a hot journal may be left in the filesystem but no error is returned |
| 50368 | 50409 | ** to the caller. |
| 50369 | 50410 | */ |
| 50370 | -SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager){ | |
| 50411 | +SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3 *db){ | |
| 50371 | 50412 | u8 *pTmp = (u8 *)pPager->pTmpSpace; |
| 50372 | 50413 | |
| 50414 | + assert( db || pagerUseWal(pPager)==0 ); | |
| 50373 | 50415 | assert( assert_pager_state(pPager) ); |
| 50374 | 50416 | disable_simulated_io_errors(); |
| 50375 | 50417 | sqlite3BeginBenignMalloc(); |
| 50376 | 50418 | pagerFreeMapHdrs(pPager); |
| 50377 | 50419 | /* pPager->errCode = 0; */ |
| 50378 | 50420 | pPager->exclusiveMode = 0; |
| 50379 | 50421 | #ifndef SQLITE_OMIT_WAL |
| 50380 | - sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags, pPager->pageSize, pTmp); | |
| 50422 | + sqlite3WalClose(pPager->pWal,db,pPager->ckptSyncFlags,pPager->pageSize,pTmp); | |
| 50381 | 50423 | pPager->pWal = 0; |
| 50382 | 50424 | #endif |
| 50383 | 50425 | pager_reset(pPager); |
| 50384 | 50426 | if( MEMDB ){ |
| 50385 | 50427 | pager_unlock(pPager); |
| @@ -53538,14 +53580,20 @@ | ||
| 53538 | 53580 | ** "PRAGMA wal_blocking_checkpoint" or calls the sqlite3_wal_checkpoint() |
| 53539 | 53581 | ** or wal_blocking_checkpoint() API functions. |
| 53540 | 53582 | ** |
| 53541 | 53583 | ** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART. |
| 53542 | 53584 | */ |
| 53543 | -SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, int eMode, int *pnLog, int *pnCkpt){ | |
| 53585 | +SQLITE_PRIVATE int sqlite3PagerCheckpoint( | |
| 53586 | + Pager *pPager, /* Checkpoint on this pager */ | |
| 53587 | + sqlite3 *db, /* Db handle used to check for interrupts */ | |
| 53588 | + int eMode, /* Type of checkpoint */ | |
| 53589 | + int *pnLog, /* OUT: Final number of frames in log */ | |
| 53590 | + int *pnCkpt /* OUT: Final number of checkpointed frames */ | |
| 53591 | +){ | |
| 53544 | 53592 | int rc = SQLITE_OK; |
| 53545 | 53593 | if( pPager->pWal ){ |
| 53546 | - rc = sqlite3WalCheckpoint(pPager->pWal, eMode, | |
| 53594 | + rc = sqlite3WalCheckpoint(pPager->pWal, db, eMode, | |
| 53547 | 53595 | (eMode==SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler), |
| 53548 | 53596 | pPager->pBusyHandlerArg, |
| 53549 | 53597 | pPager->ckptSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace, |
| 53550 | 53598 | pnLog, pnCkpt |
| 53551 | 53599 | ); |
| @@ -53673,11 +53721,11 @@ | ||
| 53673 | 53721 | ** Before closing the log file, this function attempts to take an |
| 53674 | 53722 | ** EXCLUSIVE lock on the database file. If this cannot be obtained, an |
| 53675 | 53723 | ** error (SQLITE_BUSY) is returned and the log connection is not closed. |
| 53676 | 53724 | ** If successful, the EXCLUSIVE lock is not released before returning. |
| 53677 | 53725 | */ |
| 53678 | -SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager){ | |
| 53726 | +SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager, sqlite3 *db){ | |
| 53679 | 53727 | int rc = SQLITE_OK; |
| 53680 | 53728 | |
| 53681 | 53729 | assert( pPager->journalMode==PAGER_JOURNALMODE_WAL ); |
| 53682 | 53730 | |
| 53683 | 53731 | /* If the log file is not already open, but does exist in the file-system, |
| @@ -53701,11 +53749,11 @@ | ||
| 53701 | 53749 | ** the database file, the log and log-summary files will be deleted. |
| 53702 | 53750 | */ |
| 53703 | 53751 | if( rc==SQLITE_OK && pPager->pWal ){ |
| 53704 | 53752 | rc = pagerExclusiveLock(pPager); |
| 53705 | 53753 | if( rc==SQLITE_OK ){ |
| 53706 | - rc = sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags, | |
| 53754 | + rc = sqlite3WalClose(pPager->pWal, db, pPager->ckptSyncFlags, | |
| 53707 | 53755 | pPager->pageSize, (u8*)pPager->pTmpSpace); |
| 53708 | 53756 | pPager->pWal = 0; |
| 53709 | 53757 | pagerFixMaplimit(pPager); |
| 53710 | 53758 | if( rc && !pPager->exclusiveMode ) pagerUnlockDb(pPager, SHARED_LOCK); |
| 53711 | 53759 | } |
| @@ -55484,10 +55532,11 @@ | ||
| 55484 | 55532 | ** checkpoint is running (in any other thread or process) at the same |
| 55485 | 55533 | ** time. |
| 55486 | 55534 | */ |
| 55487 | 55535 | static int walCheckpoint( |
| 55488 | 55536 | Wal *pWal, /* Wal connection */ |
| 55537 | + sqlite3 *db, /* Check for interrupts on this handle */ | |
| 55489 | 55538 | int eMode, /* One of PASSIVE, FULL or RESTART */ |
| 55490 | 55539 | int (*xBusy)(void*), /* Function to call when busy */ |
| 55491 | 55540 | void *pBusyArg, /* Context argument for xBusyHandler */ |
| 55492 | 55541 | int sync_flags, /* Flags for OsSync() (or 0) */ |
| 55493 | 55542 | u8 *zBuf /* Temporary buffer to use */ |
| @@ -55578,10 +55627,14 @@ | ||
| 55578 | 55627 | |
| 55579 | 55628 | /* Iterate through the contents of the WAL, copying data to the db file */ |
| 55580 | 55629 | while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){ |
| 55581 | 55630 | i64 iOffset; |
| 55582 | 55631 | assert( walFramePgno(pWal, iFrame)==iDbpage ); |
| 55632 | + if( db->u1.isInterrupted ){ | |
| 55633 | + rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_INTERRUPT; | |
| 55634 | + break; | |
| 55635 | + } | |
| 55583 | 55636 | if( iFrame<=nBackfill || iFrame>mxSafeFrame || iDbpage>mxPage ){ |
| 55584 | 55637 | continue; |
| 55585 | 55638 | } |
| 55586 | 55639 | iOffset = walFrameOffset(iFrame, szPage) + WAL_FRAME_HDRSIZE; |
| 55587 | 55640 | /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL file */ |
| @@ -55682,10 +55735,11 @@ | ||
| 55682 | 55735 | /* |
| 55683 | 55736 | ** Close a connection to a log file. |
| 55684 | 55737 | */ |
| 55685 | 55738 | SQLITE_PRIVATE int sqlite3WalClose( |
| 55686 | 55739 | Wal *pWal, /* Wal to close */ |
| 55740 | + sqlite3 *db, /* For interrupt flag */ | |
| 55687 | 55741 | int sync_flags, /* Flags to pass to OsSync() (or 0) */ |
| 55688 | 55742 | int nBuf, |
| 55689 | 55743 | u8 *zBuf /* Buffer of at least nBuf bytes */ |
| 55690 | 55744 | ){ |
| 55691 | 55745 | int rc = SQLITE_OK; |
| @@ -55698,17 +55752,18 @@ | ||
| 55698 | 55752 | ** the database. In this case checkpoint the database and unlink both |
| 55699 | 55753 | ** the wal and wal-index files. |
| 55700 | 55754 | ** |
| 55701 | 55755 | ** The EXCLUSIVE lock is not released before returning. |
| 55702 | 55756 | */ |
| 55703 | - rc = sqlite3OsLock(pWal->pDbFd, SQLITE_LOCK_EXCLUSIVE); | |
| 55704 | - if( rc==SQLITE_OK ){ | |
| 55757 | + if( (db->flags & SQLITE_NoCkptOnClose)==0 | |
| 55758 | + && SQLITE_OK==(rc = sqlite3OsLock(pWal->pDbFd, SQLITE_LOCK_EXCLUSIVE)) | |
| 55759 | + ){ | |
| 55705 | 55760 | if( pWal->exclusiveMode==WAL_NORMAL_MODE ){ |
| 55706 | 55761 | pWal->exclusiveMode = WAL_EXCLUSIVE_MODE; |
| 55707 | 55762 | } |
| 55708 | - rc = sqlite3WalCheckpoint( | |
| 55709 | - pWal, SQLITE_CHECKPOINT_PASSIVE, 0, 0, sync_flags, nBuf, zBuf, 0, 0 | |
| 55763 | + rc = sqlite3WalCheckpoint(pWal, db, | |
| 55764 | + SQLITE_CHECKPOINT_PASSIVE, 0, 0, sync_flags, nBuf, zBuf, 0, 0 | |
| 55710 | 55765 | ); |
| 55711 | 55766 | if( rc==SQLITE_OK ){ |
| 55712 | 55767 | int bPersist = -1; |
| 55713 | 55768 | sqlite3OsFileControlHint( |
| 55714 | 55769 | pWal->pDbFd, SQLITE_FCNTL_PERSIST_WAL, &bPersist |
| @@ -56952,10 +57007,11 @@ | ||
| 56952 | 57007 | ** If parameter xBusy is not NULL, it is a pointer to a busy-handler |
| 56953 | 57008 | ** callback. In this case this function runs a blocking checkpoint. |
| 56954 | 57009 | */ |
| 56955 | 57010 | SQLITE_PRIVATE int sqlite3WalCheckpoint( |
| 56956 | 57011 | Wal *pWal, /* Wal connection */ |
| 57012 | + sqlite3 *db, /* Check this handle's interrupt flag */ | |
| 56957 | 57013 | int eMode, /* PASSIVE, FULL, RESTART, or TRUNCATE */ |
| 56958 | 57014 | int (*xBusy)(void*), /* Function to call when busy */ |
| 56959 | 57015 | void *pBusyArg, /* Context argument for xBusyHandler */ |
| 56960 | 57016 | int sync_flags, /* Flags to sync db file with (or 0) */ |
| 56961 | 57017 | int nBuf, /* Size of temporary buffer */ |
| @@ -57026,11 +57082,11 @@ | ||
| 57026 | 57082 | if( rc==SQLITE_OK ){ |
| 57027 | 57083 | |
| 57028 | 57084 | if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){ |
| 57029 | 57085 | rc = SQLITE_CORRUPT_BKPT; |
| 57030 | 57086 | }else{ |
| 57031 | - rc = walCheckpoint(pWal, eMode2, xBusy2, pBusyArg, sync_flags, zBuf); | |
| 57087 | + rc = walCheckpoint(pWal, db, eMode2, xBusy2, pBusyArg, sync_flags, zBuf); | |
| 57032 | 57088 | } |
| 57033 | 57089 | |
| 57034 | 57090 | /* If no error occurred, set the output variables. */ |
| 57035 | 57091 | if( rc==SQLITE_OK || rc==SQLITE_BUSY ){ |
| 57036 | 57092 | if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame; |
| @@ -58984,11 +59040,11 @@ | ||
| 58984 | 59040 | int bias, /* Bias search to the high end */ |
| 58985 | 59041 | int *pRes /* Write search results here */ |
| 58986 | 59042 | ){ |
| 58987 | 59043 | int rc; /* Status code */ |
| 58988 | 59044 | UnpackedRecord *pIdxKey; /* Unpacked index key */ |
| 58989 | - char aSpace[200]; /* Temp space for pIdxKey - to avoid a malloc */ | |
| 59045 | + char aSpace[384]; /* Temp space for pIdxKey - to avoid a malloc */ | |
| 58990 | 59046 | char *pFree = 0; |
| 58991 | 59047 | |
| 58992 | 59048 | if( pKey ){ |
| 58993 | 59049 | assert( nKey==(i64)(int)nKey ); |
| 58994 | 59050 | pIdxKey = sqlite3VdbeAllocUnpackedRecord( |
| @@ -60616,23 +60672,30 @@ | ||
| 60616 | 60672 | *ppBtree = p; |
| 60617 | 60673 | |
| 60618 | 60674 | btree_open_out: |
| 60619 | 60675 | if( rc!=SQLITE_OK ){ |
| 60620 | 60676 | if( pBt && pBt->pPager ){ |
| 60621 | - sqlite3PagerClose(pBt->pPager); | |
| 60677 | + sqlite3PagerClose(pBt->pPager, 0); | |
| 60622 | 60678 | } |
| 60623 | 60679 | sqlite3_free(pBt); |
| 60624 | 60680 | sqlite3_free(p); |
| 60625 | 60681 | *ppBtree = 0; |
| 60626 | 60682 | }else{ |
| 60683 | + sqlite3_file *pFile; | |
| 60684 | + | |
| 60627 | 60685 | /* If the B-Tree was successfully opened, set the pager-cache size to the |
| 60628 | 60686 | ** default value. Except, when opening on an existing shared pager-cache, |
| 60629 | 60687 | ** do not change the pager-cache size. |
| 60630 | 60688 | */ |
| 60631 | 60689 | if( sqlite3BtreeSchema(p, 0, 0)==0 ){ |
| 60632 | 60690 | sqlite3PagerSetCachesize(p->pBt->pPager, SQLITE_DEFAULT_CACHE_SIZE); |
| 60633 | 60691 | } |
| 60692 | + | |
| 60693 | + pFile = sqlite3PagerFile(pBt->pPager); | |
| 60694 | + if( pFile->pMethods ){ | |
| 60695 | + sqlite3OsFileControlHint(pFile, SQLITE_FCNTL_PDB, (void*)&pBt->db); | |
| 60696 | + } | |
| 60634 | 60697 | } |
| 60635 | 60698 | if( mutexOpen ){ |
| 60636 | 60699 | assert( sqlite3_mutex_held(mutexOpen) ); |
| 60637 | 60700 | sqlite3_mutex_leave(mutexOpen); |
| 60638 | 60701 | } |
| @@ -60758,11 +60821,11 @@ | ||
| 60758 | 60821 | ** it without having to hold the mutex. |
| 60759 | 60822 | ** |
| 60760 | 60823 | ** Clean out and delete the BtShared object. |
| 60761 | 60824 | */ |
| 60762 | 60825 | assert( !pBt->pCursor ); |
| 60763 | - sqlite3PagerClose(pBt->pPager); | |
| 60826 | + sqlite3PagerClose(pBt->pPager, p->db); | |
| 60764 | 60827 | if( pBt->xFreeSchema && pBt->pSchema ){ |
| 60765 | 60828 | pBt->xFreeSchema(pBt->pSchema); |
| 60766 | 60829 | } |
| 60767 | 60830 | sqlite3DbFree(0, pBt->pSchema); |
| 60768 | 60831 | freeTempSpace(pBt); |
| @@ -62822,11 +62885,11 @@ | ||
| 62822 | 62885 | if( (eOp&0x01)==0 /* (1) */ |
| 62823 | 62886 | && offset==0 /* (2) */ |
| 62824 | 62887 | && (bEnd || a==ovflSize) /* (6) */ |
| 62825 | 62888 | && pBt->inTransaction==TRANS_READ /* (4) */ |
| 62826 | 62889 | && (fd = sqlite3PagerFile(pBt->pPager))->pMethods /* (3) */ |
| 62827 | - && pBt->pPage1->aData[19]==0x01 /* (5) */ | |
| 62890 | + && 0==sqlite3PagerUseWal(pBt->pPager) /* (5) */ | |
| 62828 | 62891 | && &pBuf[-4]>=pBufStart /* (7) */ |
| 62829 | 62892 | ){ |
| 62830 | 62893 | u8 aSave[4]; |
| 62831 | 62894 | u8 *aWrite = &pBuf[-4]; |
| 62832 | 62895 | assert( aWrite>=pBufStart ); /* hence (7) */ |
| @@ -63078,13 +63141,16 @@ | ||
| 63078 | 63141 | } |
| 63079 | 63142 | sqlite3BtreeClearCursor(pCur); |
| 63080 | 63143 | } |
| 63081 | 63144 | |
| 63082 | 63145 | if( pCur->iPage>=0 ){ |
| 63083 | - while( pCur->iPage ){ | |
| 63084 | - assert( pCur->apPage[pCur->iPage]!=0 ); | |
| 63085 | - releasePageNotNull(pCur->apPage[pCur->iPage--]); | |
| 63146 | + if( pCur->iPage ){ | |
| 63147 | + do{ | |
| 63148 | + assert( pCur->apPage[pCur->iPage]!=0 ); | |
| 63149 | + releasePageNotNull(pCur->apPage[pCur->iPage--]); | |
| 63150 | + }while( pCur->iPage); | |
| 63151 | + goto skip_init; | |
| 63086 | 63152 | } |
| 63087 | 63153 | }else if( pCur->pgnoRoot==0 ){ |
| 63088 | 63154 | pCur->eState = CURSOR_INVALID; |
| 63089 | 63155 | return SQLITE_OK; |
| 63090 | 63156 | }else{ |
| @@ -63091,11 +63157,11 @@ | ||
| 63091 | 63157 | assert( pCur->iPage==(-1) ); |
| 63092 | 63158 | rc = getAndInitPage(pCur->pBtree->pBt, pCur->pgnoRoot, &pCur->apPage[0], |
| 63093 | 63159 | 0, pCur->curPagerFlags); |
| 63094 | 63160 | if( rc!=SQLITE_OK ){ |
| 63095 | 63161 | pCur->eState = CURSOR_INVALID; |
| 63096 | - return rc; | |
| 63162 | + return rc; | |
| 63097 | 63163 | } |
| 63098 | 63164 | pCur->iPage = 0; |
| 63099 | 63165 | pCur->curIntKey = pCur->apPage[0]->intKey; |
| 63100 | 63166 | } |
| 63101 | 63167 | pRoot = pCur->apPage[0]; |
| @@ -63114,14 +63180,16 @@ | ||
| 63114 | 63180 | assert( pRoot->intKey==1 || pRoot->intKey==0 ); |
| 63115 | 63181 | if( pRoot->isInit==0 || (pCur->pKeyInfo==0)!=pRoot->intKey ){ |
| 63116 | 63182 | return SQLITE_CORRUPT_BKPT; |
| 63117 | 63183 | } |
| 63118 | 63184 | |
| 63185 | +skip_init: | |
| 63119 | 63186 | pCur->aiIdx[0] = 0; |
| 63120 | 63187 | pCur->info.nSize = 0; |
| 63121 | 63188 | pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidNKey|BTCF_ValidOvfl); |
| 63122 | 63189 | |
| 63190 | + pRoot = pCur->apPage[0]; | |
| 63123 | 63191 | if( pRoot->nCell>0 ){ |
| 63124 | 63192 | pCur->eState = CURSOR_VALID; |
| 63125 | 63193 | }else if( !pRoot->leaf ){ |
| 63126 | 63194 | Pgno subpage; |
| 63127 | 63195 | if( pRoot->pgno!=1 ) return SQLITE_CORRUPT_BKPT; |
| @@ -64321,12 +64389,10 @@ | ||
| 64321 | 64389 | nSrc = pX->nData; |
| 64322 | 64390 | assert( pPage->intKeyLeaf ); /* fillInCell() only called for leaves */ |
| 64323 | 64391 | nHeader += putVarint32(&pCell[nHeader], nPayload); |
| 64324 | 64392 | nHeader += putVarint(&pCell[nHeader], *(u64*)&pX->nKey); |
| 64325 | 64393 | }else{ |
| 64326 | - assert( pX->nData==0 ); | |
| 64327 | - assert( pX->nZero==0 ); | |
| 64328 | 64394 | assert( pX->nKey<=0x7fffffff && pX->pKey!=0 ); |
| 64329 | 64395 | nSrc = nPayload = (int)pX->nKey; |
| 64330 | 64396 | pSrc = pX->pKey; |
| 64331 | 64397 | nHeader += putVarint32(&pCell[nHeader], nPayload); |
| 64332 | 64398 | } |
| @@ -67700,11 +67766,11 @@ | ||
| 67700 | 67766 | BtShared *pBt = p->pBt; |
| 67701 | 67767 | sqlite3BtreeEnter(p); |
| 67702 | 67768 | if( pBt->inTransaction!=TRANS_NONE ){ |
| 67703 | 67769 | rc = SQLITE_LOCKED; |
| 67704 | 67770 | }else{ |
| 67705 | - rc = sqlite3PagerCheckpoint(pBt->pPager, eMode, pnLog, pnCkpt); | |
| 67771 | + rc = sqlite3PagerCheckpoint(pBt->pPager, p->db, eMode, pnLog, pnCkpt); | |
| 67706 | 67772 | } |
| 67707 | 67773 | sqlite3BtreeLeave(p); |
| 67708 | 67774 | } |
| 67709 | 67775 | return rc; |
| 67710 | 67776 | } |
| @@ -68022,26 +68088,20 @@ | ||
| 68022 | 68088 | */ |
| 68023 | 68089 | static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){ |
| 68024 | 68090 | int i = sqlite3FindDbName(pDb, zDb); |
| 68025 | 68091 | |
| 68026 | 68092 | if( i==1 ){ |
| 68027 | - Parse *pParse; | |
| 68093 | + Parse sParse; | |
| 68028 | 68094 | int rc = 0; |
| 68029 | - pParse = sqlite3StackAllocZero(pErrorDb, sizeof(*pParse)); | |
| 68030 | - if( pParse==0 ){ | |
| 68031 | - sqlite3ErrorWithMsg(pErrorDb, SQLITE_NOMEM, "out of memory"); | |
| 68032 | - rc = SQLITE_NOMEM_BKPT; | |
| 68033 | - }else{ | |
| 68034 | - pParse->db = pDb; | |
| 68035 | - if( sqlite3OpenTempDatabase(pParse) ){ | |
| 68036 | - sqlite3ErrorWithMsg(pErrorDb, pParse->rc, "%s", pParse->zErrMsg); | |
| 68037 | - rc = SQLITE_ERROR; | |
| 68038 | - } | |
| 68039 | - sqlite3DbFree(pErrorDb, pParse->zErrMsg); | |
| 68040 | - sqlite3ParserReset(pParse); | |
| 68041 | - sqlite3StackFree(pErrorDb, pParse); | |
| 68042 | - } | |
| 68095 | + memset(&sParse, 0, sizeof(sParse)); | |
| 68096 | + sParse.db = pDb; | |
| 68097 | + if( sqlite3OpenTempDatabase(&sParse) ){ | |
| 68098 | + sqlite3ErrorWithMsg(pErrorDb, sParse.rc, "%s", sParse.zErrMsg); | |
| 68099 | + rc = SQLITE_ERROR; | |
| 68100 | + } | |
| 68101 | + sqlite3DbFree(pErrorDb, sParse.zErrMsg); | |
| 68102 | + sqlite3ParserReset(&sParse); | |
| 68043 | 68103 | if( rc ){ |
| 68044 | 68104 | return 0; |
| 68045 | 68105 | } |
| 68046 | 68106 | } |
| 68047 | 68107 | |
| @@ -69041,10 +69101,11 @@ | ||
| 69041 | 69101 | assert( (pMem->flags&MEM_RowSet)==0 ); |
| 69042 | 69102 | assert( EIGHT_BYTE_ALIGNMENT(pMem) ); |
| 69043 | 69103 | |
| 69044 | 69104 | |
| 69045 | 69105 | if( sqlite3VdbeMemClearAndResize(pMem, nByte) ){ |
| 69106 | + pMem->enc = 0; | |
| 69046 | 69107 | return SQLITE_NOMEM_BKPT; |
| 69047 | 69108 | } |
| 69048 | 69109 | |
| 69049 | 69110 | /* For a Real or Integer, use sqlite3_snprintf() to produce the UTF-8 |
| 69050 | 69111 | ** string representation of the value. Then, if the required encoding |
| @@ -69340,11 +69401,11 @@ | ||
| 69340 | 69401 | switch( aff ){ |
| 69341 | 69402 | case SQLITE_AFF_BLOB: { /* Really a cast to BLOB */ |
| 69342 | 69403 | if( (pMem->flags & MEM_Blob)==0 ){ |
| 69343 | 69404 | sqlite3ValueApplyAffinity(pMem, SQLITE_AFF_TEXT, encoding); |
| 69344 | 69405 | assert( pMem->flags & MEM_Str || pMem->db->mallocFailed ); |
| 69345 | - MemSetTypeFlag(pMem, MEM_Blob); | |
| 69406 | + if( pMem->flags & MEM_Str ) MemSetTypeFlag(pMem, MEM_Blob); | |
| 69346 | 69407 | }else{ |
| 69347 | 69408 | pMem->flags &= ~(MEM_TypeMask&~MEM_Blob); |
| 69348 | 69409 | } |
| 69349 | 69410 | break; |
| 69350 | 69411 | } |
| @@ -70017,14 +70078,11 @@ | ||
| 70017 | 70078 | sqlite3_value *pVal = 0; |
| 70018 | 70079 | int negInt = 1; |
| 70019 | 70080 | const char *zNeg = ""; |
| 70020 | 70081 | int rc = SQLITE_OK; |
| 70021 | 70082 | |
| 70022 | - if( !pExpr ){ | |
| 70023 | - *ppVal = 0; | |
| 70024 | - return SQLITE_OK; | |
| 70025 | - } | |
| 70083 | + assert( pExpr!=0 ); | |
| 70026 | 70084 | while( (op = pExpr->op)==TK_UPLUS || op==TK_SPAN ) pExpr = pExpr->pLeft; |
| 70027 | 70085 | if( NEVER(op==TK_REGISTER) ) op = pExpr->op2; |
| 70028 | 70086 | |
| 70029 | 70087 | /* Compressed expressions only appear when parsing the DEFAULT clause |
| 70030 | 70088 | ** on a table column definition, and hence only when pCtx==0. This |
| @@ -70144,11 +70202,11 @@ | ||
| 70144 | 70202 | Expr *pExpr, /* The expression to evaluate */ |
| 70145 | 70203 | u8 enc, /* Encoding to use */ |
| 70146 | 70204 | u8 affinity, /* Affinity to use */ |
| 70147 | 70205 | sqlite3_value **ppVal /* Write the new value here */ |
| 70148 | 70206 | ){ |
| 70149 | - return valueFromExpr(db, pExpr, enc, affinity, ppVal, 0); | |
| 70207 | + return pExpr ? valueFromExpr(db, pExpr, enc, affinity, ppVal, 0) : 0; | |
| 70150 | 70208 | } |
| 70151 | 70209 | |
| 70152 | 70210 | #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 |
| 70153 | 70211 | /* |
| 70154 | 70212 | ** The implementation of the sqlite_record() function. This function accepts |
| @@ -70487,12 +70545,13 @@ | ||
| 70487 | 70545 | ** Create a new virtual database engine. |
| 70488 | 70546 | */ |
| 70489 | 70547 | SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(Parse *pParse){ |
| 70490 | 70548 | sqlite3 *db = pParse->db; |
| 70491 | 70549 | Vdbe *p; |
| 70492 | - p = sqlite3DbMallocZero(db, sizeof(Vdbe) ); | |
| 70550 | + p = sqlite3DbMallocRawNN(db, sizeof(Vdbe) ); | |
| 70493 | 70551 | if( p==0 ) return 0; |
| 70552 | + memset(&p->aOp, 0, sizeof(Vdbe)-offsetof(Vdbe,aOp)); | |
| 70494 | 70553 | p->db = db; |
| 70495 | 70554 | if( db->pVdbe ){ |
| 70496 | 70555 | db->pVdbe->pPrev = p; |
| 70497 | 70556 | } |
| 70498 | 70557 | p->pNext = db->pVdbe; |
| @@ -70650,13 +70709,12 @@ | ||
| 70650 | 70709 | #endif |
| 70651 | 70710 | #ifdef SQLITE_DEBUG |
| 70652 | 70711 | if( p->db->flags & SQLITE_VdbeAddopTrace ){ |
| 70653 | 70712 | int jj, kk; |
| 70654 | 70713 | Parse *pParse = p->pParse; |
| 70655 | - for(jj=kk=0; jj<SQLITE_N_COLCACHE; jj++){ | |
| 70714 | + for(jj=kk=0; jj<pParse->nColCache; jj++){ | |
| 70656 | 70715 | struct yColCache *x = pParse->aColCache + jj; |
| 70657 | - if( x->iLevel>pParse->iCacheLevel || x->iReg==0 ) continue; | |
| 70658 | 70716 | printf(" r[%d]={%d:%d}", x->iReg, x->iTable, x->iColumn); |
| 70659 | 70717 | kk++; |
| 70660 | 70718 | } |
| 70661 | 70719 | if( kk ) printf("\n"); |
| 70662 | 70720 | sqlite3VdbePrintOp(0, i, &p->aOp[i]); |
| @@ -70840,11 +70898,10 @@ | ||
| 70840 | 70898 | assert( j<p->nLabel ); |
| 70841 | 70899 | assert( j>=0 ); |
| 70842 | 70900 | if( p->aLabel ){ |
| 70843 | 70901 | p->aLabel[j] = v->nOp; |
| 70844 | 70902 | } |
| 70845 | - p->iFixedOp = v->nOp - 1; | |
| 70846 | 70903 | } |
| 70847 | 70904 | |
| 70848 | 70905 | /* |
| 70849 | 70906 | ** Mark the VDBE as one that can only be run one time. |
| 70850 | 70907 | */ |
| @@ -71231,19 +71288,19 @@ | ||
| 71231 | 71288 | } |
| 71232 | 71289 | SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe *p, u32 addr, int val){ |
| 71233 | 71290 | sqlite3VdbeGetOp(p,addr)->p3 = val; |
| 71234 | 71291 | } |
| 71235 | 71292 | SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe *p, u8 p5){ |
| 71236 | - if( !p->db->mallocFailed ) p->aOp[p->nOp-1].p5 = p5; | |
| 71293 | + assert( p->nOp>0 || p->db->mallocFailed ); | |
| 71294 | + if( p->nOp>0 ) p->aOp[p->nOp-1].p5 = p5; | |
| 71237 | 71295 | } |
| 71238 | 71296 | |
| 71239 | 71297 | /* |
| 71240 | 71298 | ** Change the P2 operand of instruction addr so that it points to |
| 71241 | 71299 | ** the address of the next instruction to be coded. |
| 71242 | 71300 | */ |
| 71243 | 71301 | SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe *p, int addr){ |
| 71244 | - p->pParse->iFixedOp = p->nOp - 1; | |
| 71245 | 71302 | sqlite3VdbeChangeP2(p, addr, p->nOp); |
| 71246 | 71303 | } |
| 71247 | 71304 | |
| 71248 | 71305 | |
| 71249 | 71306 | /* |
| @@ -71362,11 +71419,11 @@ | ||
| 71362 | 71419 | /* |
| 71363 | 71420 | ** If the last opcode is "op" and it is not a jump destination, |
| 71364 | 71421 | ** then remove it. Return true if and only if an opcode was removed. |
| 71365 | 71422 | */ |
| 71366 | 71423 | SQLITE_PRIVATE int sqlite3VdbeDeletePriorOpcode(Vdbe *p, u8 op){ |
| 71367 | - if( (p->nOp-1)>(p->pParse->iFixedOp) && p->aOp[p->nOp-1].opcode==op ){ | |
| 71424 | + if( p->nOp>0 && p->aOp[p->nOp-1].opcode==op ){ | |
| 71368 | 71425 | return sqlite3VdbeChangeToNoop(p, p->nOp-1); |
| 71369 | 71426 | }else{ |
| 71370 | 71427 | return 0; |
| 71371 | 71428 | } |
| 71372 | 71429 | } |
| @@ -71924,10 +71981,25 @@ | ||
| 71924 | 71981 | zCom |
| 71925 | 71982 | ); |
| 71926 | 71983 | fflush(pOut); |
| 71927 | 71984 | } |
| 71928 | 71985 | #endif |
| 71986 | + | |
| 71987 | +/* | |
| 71988 | +** Initialize an array of N Mem element. | |
| 71989 | +*/ | |
| 71990 | +static void initMemArray(Mem *p, int N, sqlite3 *db, u16 flags){ | |
| 71991 | + while( (N--)>0 ){ | |
| 71992 | + p->db = db; | |
| 71993 | + p->flags = flags; | |
| 71994 | + p->szMalloc = 0; | |
| 71995 | +#ifdef SQLITE_DEBUG | |
| 71996 | + p->pScopyFrom = 0; | |
| 71997 | +#endif | |
| 71998 | + p++; | |
| 71999 | + } | |
| 72000 | +} | |
| 71929 | 72001 | |
| 71930 | 72002 | /* |
| 71931 | 72003 | ** Release an array of N Mem elements |
| 71932 | 72004 | */ |
| 71933 | 72005 | static void releaseMemArray(Mem *p, int N){ |
| @@ -72136,10 +72208,11 @@ | ||
| 72136 | 72208 | return SQLITE_ERROR; |
| 72137 | 72209 | } |
| 72138 | 72210 | pMem->flags = MEM_Str|MEM_Term; |
| 72139 | 72211 | zP4 = displayP4(pOp, pMem->z, pMem->szMalloc); |
| 72140 | 72212 | if( zP4!=pMem->z ){ |
| 72213 | + pMem->n = 0; | |
| 72141 | 72214 | sqlite3VdbeMemSetStr(pMem, zP4, -1, SQLITE_UTF8, 0); |
| 72142 | 72215 | }else{ |
| 72143 | 72216 | assert( pMem->z!=0 ); |
| 72144 | 72217 | pMem->n = sqlite3Strlen30(pMem->z); |
| 72145 | 72218 | pMem->enc = SQLITE_UTF8; |
| @@ -72278,11 +72351,11 @@ | ||
| 72278 | 72351 | SQLITE_PRIVATE void sqlite3VdbeRewind(Vdbe *p){ |
| 72279 | 72352 | #if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) |
| 72280 | 72353 | int i; |
| 72281 | 72354 | #endif |
| 72282 | 72355 | assert( p!=0 ); |
| 72283 | - assert( p->magic==VDBE_MAGIC_INIT ); | |
| 72356 | + assert( p->magic==VDBE_MAGIC_INIT || p->magic==VDBE_MAGIC_RESET ); | |
| 72284 | 72357 | |
| 72285 | 72358 | /* There should be at least one opcode. |
| 72286 | 72359 | */ |
| 72287 | 72360 | assert( p->nOp>0 ); |
| 72288 | 72361 | |
| @@ -72367,14 +72440,11 @@ | ||
| 72367 | 72440 | n = ROUND8(sizeof(Op)*p->nOp); /* Bytes of opcode memory used */ |
| 72368 | 72441 | x.pSpace = &((u8*)p->aOp)[n]; /* Unused opcode memory */ |
| 72369 | 72442 | assert( EIGHT_BYTE_ALIGNMENT(x.pSpace) ); |
| 72370 | 72443 | x.nFree = ROUNDDOWN8(pParse->szOpAlloc - n); /* Bytes of unused memory */ |
| 72371 | 72444 | assert( x.nFree>=0 ); |
| 72372 | - if( x.nFree>0 ){ | |
| 72373 | - memset(x.pSpace, 0, x.nFree); | |
| 72374 | - assert( EIGHT_BYTE_ALIGNMENT(&x.pSpace[x.nFree]) ); | |
| 72375 | - } | |
| 72445 | + assert( EIGHT_BYTE_ALIGNMENT(&x.pSpace[x.nFree]) ); | |
| 72376 | 72446 | |
| 72377 | 72447 | resolveP2Values(p, &nArg); |
| 72378 | 72448 | p->usesStmtJournal = (u8)(pParse->isMultiWrite && pParse->mayAbort); |
| 72379 | 72449 | if( pParse->explain && nMem<10 ){ |
| 72380 | 72450 | nMem = 10; |
| @@ -72399,34 +72469,34 @@ | ||
| 72399 | 72469 | p->apCsr = allocSpace(&x, p->apCsr, nCursor*sizeof(VdbeCursor*)); |
| 72400 | 72470 | #ifdef SQLITE_ENABLE_STMT_SCANSTATUS |
| 72401 | 72471 | p->anExec = allocSpace(&x, p->anExec, p->nOp*sizeof(i64)); |
| 72402 | 72472 | #endif |
| 72403 | 72473 | if( x.nNeeded==0 ) break; |
| 72404 | - x.pSpace = p->pFree = sqlite3DbMallocZero(db, x.nNeeded); | |
| 72474 | + x.pSpace = p->pFree = sqlite3DbMallocRawNN(db, x.nNeeded); | |
| 72405 | 72475 | x.nFree = x.nNeeded; |
| 72406 | 72476 | }while( !db->mallocFailed ); |
| 72407 | 72477 | |
| 72408 | - p->nCursor = nCursor; | |
| 72409 | - if( p->aVar ){ | |
| 72410 | - p->nVar = (ynVar)nVar; | |
| 72411 | - for(n=0; n<nVar; n++){ | |
| 72412 | - p->aVar[n].flags = MEM_Null; | |
| 72413 | - p->aVar[n].db = db; | |
| 72414 | - } | |
| 72415 | - } | |
| 72416 | 72478 | p->nzVar = pParse->nzVar; |
| 72417 | 72479 | p->azVar = pParse->azVar; |
| 72418 | 72480 | pParse->nzVar = 0; |
| 72419 | 72481 | pParse->azVar = 0; |
| 72420 | - if( p->aMem ){ | |
| 72421 | - p->nMem = nMem; | |
| 72422 | - for(n=0; n<nMem; n++){ | |
| 72423 | - p->aMem[n].flags = MEM_Undefined; | |
| 72424 | - p->aMem[n].db = db; | |
| 72425 | - } | |
| 72426 | - } | |
| 72427 | 72482 | p->explain = pParse->explain; |
| 72483 | + if( db->mallocFailed ){ | |
| 72484 | + p->nVar = 0; | |
| 72485 | + p->nCursor = 0; | |
| 72486 | + p->nMem = 0; | |
| 72487 | + }else{ | |
| 72488 | + p->nCursor = nCursor; | |
| 72489 | + p->nVar = (ynVar)nVar; | |
| 72490 | + initMemArray(p->aVar, nVar, db, MEM_Null); | |
| 72491 | + p->nMem = nMem; | |
| 72492 | + initMemArray(p->aMem, nMem, db, MEM_Undefined); | |
| 72493 | + memset(p->apCsr, 0, nCursor*sizeof(VdbeCursor*)); | |
| 72494 | +#ifdef SQLITE_ENABLE_STMT_SCANSTATUS | |
| 72495 | + memset(p->anExec, 0, p->nOp*sizeof(i64)); | |
| 72496 | +#endif | |
| 72497 | + } | |
| 72428 | 72498 | sqlite3VdbeRewind(p); |
| 72429 | 72499 | } |
| 72430 | 72500 | |
| 72431 | 72501 | /* |
| 72432 | 72502 | ** Close a VDBE cursor and release all the resources that cursor |
| @@ -72574,17 +72644,13 @@ | ||
| 72574 | 72644 | |
| 72575 | 72645 | releaseMemArray(p->aColName, p->nResColumn*COLNAME_N); |
| 72576 | 72646 | sqlite3DbFree(db, p->aColName); |
| 72577 | 72647 | n = nResColumn*COLNAME_N; |
| 72578 | 72648 | p->nResColumn = (u16)nResColumn; |
| 72579 | - p->aColName = pColName = (Mem*)sqlite3DbMallocZero(db, sizeof(Mem)*n ); | |
| 72649 | + p->aColName = pColName = (Mem*)sqlite3DbMallocRawNN(db, sizeof(Mem)*n ); | |
| 72580 | 72650 | if( p->aColName==0 ) return; |
| 72581 | - while( n-- > 0 ){ | |
| 72582 | - pColName->flags = MEM_Null; | |
| 72583 | - pColName->db = p->db; | |
| 72584 | - pColName++; | |
| 72585 | - } | |
| 72651 | + initMemArray(p->aColName, n, p->db, MEM_Null); | |
| 72586 | 72652 | } |
| 72587 | 72653 | |
| 72588 | 72654 | /* |
| 72589 | 72655 | ** Set the name of the idx'th column to be returned by the SQL statement. |
| 72590 | 72656 | ** zName must be a pointer to a nul terminated string. |
| @@ -73342,11 +73408,11 @@ | ||
| 73342 | 73408 | fclose(out); |
| 73343 | 73409 | } |
| 73344 | 73410 | } |
| 73345 | 73411 | #endif |
| 73346 | 73412 | p->iCurrentTime = 0; |
| 73347 | - p->magic = VDBE_MAGIC_INIT; | |
| 73413 | + p->magic = VDBE_MAGIC_RESET; | |
| 73348 | 73414 | return p->rc & db->errMask; |
| 73349 | 73415 | } |
| 73350 | 73416 | |
| 73351 | 73417 | /* |
| 73352 | 73418 | ** Clean up and delete a VDBE after execution. Return an integer which is |
| @@ -73406,23 +73472,25 @@ | ||
| 73406 | 73472 | */ |
| 73407 | 73473 | SQLITE_PRIVATE void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){ |
| 73408 | 73474 | SubProgram *pSub, *pNext; |
| 73409 | 73475 | int i; |
| 73410 | 73476 | assert( p->db==0 || p->db==db ); |
| 73411 | - releaseMemArray(p->aVar, p->nVar); | |
| 73412 | 73477 | releaseMemArray(p->aColName, p->nResColumn*COLNAME_N); |
| 73413 | 73478 | for(pSub=p->pProgram; pSub; pSub=pNext){ |
| 73414 | 73479 | pNext = pSub->pNext; |
| 73415 | 73480 | vdbeFreeOpArray(db, pSub->aOp, pSub->nOp); |
| 73416 | 73481 | sqlite3DbFree(db, pSub); |
| 73417 | 73482 | } |
| 73418 | - for(i=p->nzVar-1; i>=0; i--) sqlite3DbFree(db, p->azVar[i]); | |
| 73419 | - sqlite3DbFree(db, p->azVar); | |
| 73483 | + if( p->magic!=VDBE_MAGIC_INIT ){ | |
| 73484 | + releaseMemArray(p->aVar, p->nVar); | |
| 73485 | + for(i=p->nzVar-1; i>=0; i--) sqlite3DbFree(db, p->azVar[i]); | |
| 73486 | + sqlite3DbFree(db, p->azVar); | |
| 73487 | + sqlite3DbFree(db, p->pFree); | |
| 73488 | + } | |
| 73420 | 73489 | vdbeFreeOpArray(db, p->aOp, p->nOp); |
| 73421 | 73490 | sqlite3DbFree(db, p->aColName); |
| 73422 | 73491 | sqlite3DbFree(db, p->zSql); |
| 73423 | - sqlite3DbFree(db, p->pFree); | |
| 73424 | 73492 | #ifdef SQLITE_ENABLE_STMT_SCANSTATUS |
| 73425 | 73493 | for(i=0; i<p->nScan; i++){ |
| 73426 | 73494 | sqlite3DbFree(db, p->aScan[i].zName); |
| 73427 | 73495 | } |
| 73428 | 73496 | sqlite3DbFree(db, p->aScan); |
| @@ -75073,11 +75141,11 @@ | ||
| 75073 | 75141 | preupdate.keyinfo.enc = ENC(db); |
| 75074 | 75142 | preupdate.keyinfo.nField = pTab->nCol; |
| 75075 | 75143 | preupdate.keyinfo.aSortOrder = (u8*)&fakeSortOrder; |
| 75076 | 75144 | preupdate.iKey1 = iKey1; |
| 75077 | 75145 | preupdate.iKey2 = iKey2; |
| 75078 | - preupdate.iPKey = pTab->iPKey; | |
| 75146 | + preupdate.pTab = pTab; | |
| 75079 | 75147 | |
| 75080 | 75148 | db->pPreUpdate = &preupdate; |
| 75081 | 75149 | db->xPreUpdateCallback(db->pPreUpdateArg, db, op, zDb, zTbl, iKey1, iKey2); |
| 75082 | 75150 | db->pPreUpdate = 0; |
| 75083 | 75151 | sqlite3DbFree(db, preupdate.aRecord); |
| @@ -76047,18 +76115,17 @@ | ||
| 76047 | 76115 | static Mem *columnMem(sqlite3_stmt *pStmt, int i){ |
| 76048 | 76116 | Vdbe *pVm; |
| 76049 | 76117 | Mem *pOut; |
| 76050 | 76118 | |
| 76051 | 76119 | pVm = (Vdbe *)pStmt; |
| 76052 | - if( pVm && pVm->pResultSet!=0 && i<pVm->nResColumn && i>=0 ){ | |
| 76053 | - sqlite3_mutex_enter(pVm->db->mutex); | |
| 76120 | + if( pVm==0 ) return (Mem*)columnNullValue(); | |
| 76121 | + assert( pVm->db ); | |
| 76122 | + sqlite3_mutex_enter(pVm->db->mutex); | |
| 76123 | + if( pVm->pResultSet!=0 && i<pVm->nResColumn && i>=0 ){ | |
| 76054 | 76124 | pOut = &pVm->pResultSet[i]; |
| 76055 | 76125 | }else{ |
| 76056 | - if( pVm && ALWAYS(pVm->db) ){ | |
| 76057 | - sqlite3_mutex_enter(pVm->db->mutex); | |
| 76058 | - sqlite3Error(pVm->db, SQLITE_RANGE); | |
| 76059 | - } | |
| 76126 | + sqlite3Error(pVm->db, SQLITE_RANGE); | |
| 76060 | 76127 | pOut = (Mem*)columnNullValue(); |
| 76061 | 76128 | } |
| 76062 | 76129 | return pOut; |
| 76063 | 76130 | } |
| 76064 | 76131 | |
| @@ -76087,10 +76154,12 @@ | ||
| 76087 | 76154 | ** SQLITE_NOMEM. The next call to _step() (if any) will return SQLITE_ERROR |
| 76088 | 76155 | ** and _finalize() will return NOMEM. |
| 76089 | 76156 | */ |
| 76090 | 76157 | Vdbe *p = (Vdbe *)pStmt; |
| 76091 | 76158 | if( p ){ |
| 76159 | + assert( p->db!=0 ); | |
| 76160 | + assert( sqlite3_mutex_held(p->db->mutex) ); | |
| 76092 | 76161 | p->rc = sqlite3ApiExit(p->db, p->rc); |
| 76093 | 76162 | sqlite3_mutex_leave(p->db->mutex); |
| 76094 | 76163 | } |
| 76095 | 76164 | } |
| 76096 | 76165 | |
| @@ -76663,11 +76732,11 @@ | ||
| 76663 | 76732 | /* |
| 76664 | 76733 | ** Return true if the prepared statement is in need of being reset. |
| 76665 | 76734 | */ |
| 76666 | 76735 | SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt *pStmt){ |
| 76667 | 76736 | Vdbe *v = (Vdbe*)pStmt; |
| 76668 | - return v!=0 && v->pc>=0 && v->magic==VDBE_MAGIC_RUN; | |
| 76737 | + return v!=0 && v->magic==VDBE_MAGIC_RUN && v->pc>=0; | |
| 76669 | 76738 | } |
| 76670 | 76739 | |
| 76671 | 76740 | /* |
| 76672 | 76741 | ** Return a pointer to the next prepared statement after pStmt associated |
| 76673 | 76742 | ** with database connection pDb. If pStmt is NULL, return the first |
| @@ -76804,13 +76873,18 @@ | ||
| 76804 | 76873 | } |
| 76805 | 76874 | |
| 76806 | 76875 | if( iIdx>=p->pUnpacked->nField ){ |
| 76807 | 76876 | *ppValue = (sqlite3_value *)columnNullValue(); |
| 76808 | 76877 | }else{ |
| 76878 | + Mem *pMem = *ppValue = &p->pUnpacked->aMem[iIdx]; | |
| 76809 | 76879 | *ppValue = &p->pUnpacked->aMem[iIdx]; |
| 76810 | - if( iIdx==p->iPKey ){ | |
| 76811 | - sqlite3VdbeMemSetInt64(*ppValue, p->iKey1); | |
| 76880 | + if( iIdx==p->pTab->iPKey ){ | |
| 76881 | + sqlite3VdbeMemSetInt64(pMem, p->iKey1); | |
| 76882 | + }else if( p->pTab->aCol[iIdx].affinity==SQLITE_AFF_REAL ){ | |
| 76883 | + if( pMem->flags & MEM_Int ){ | |
| 76884 | + sqlite3VdbeMemRealify(pMem); | |
| 76885 | + } | |
| 76812 | 76886 | } |
| 76813 | 76887 | } |
| 76814 | 76888 | |
| 76815 | 76889 | preupdate_old_out: |
| 76816 | 76890 | sqlite3Error(db, rc); |
| @@ -76883,11 +76957,11 @@ | ||
| 76883 | 76957 | } |
| 76884 | 76958 | if( iIdx>=pUnpack->nField ){ |
| 76885 | 76959 | pMem = (sqlite3_value *)columnNullValue(); |
| 76886 | 76960 | }else{ |
| 76887 | 76961 | pMem = &pUnpack->aMem[iIdx]; |
| 76888 | - if( iIdx==p->iPKey ){ | |
| 76962 | + if( iIdx==p->pTab->iPKey ){ | |
| 76889 | 76963 | sqlite3VdbeMemSetInt64(pMem, p->iKey2); |
| 76890 | 76964 | } |
| 76891 | 76965 | } |
| 76892 | 76966 | }else{ |
| 76893 | 76967 | /* For an UPDATE, memory cell (p->iNewReg+1+iIdx) contains the required |
| @@ -76904,11 +76978,11 @@ | ||
| 76904 | 76978 | } |
| 76905 | 76979 | } |
| 76906 | 76980 | assert( iIdx>=0 && iIdx<p->pCsr->nField ); |
| 76907 | 76981 | pMem = &p->aNew[iIdx]; |
| 76908 | 76982 | if( pMem->flags==0 ){ |
| 76909 | - if( iIdx==p->iPKey ){ | |
| 76983 | + if( iIdx==p->pTab->iPKey ){ | |
| 76910 | 76984 | sqlite3VdbeMemSetInt64(pMem, p->iKey2); |
| 76911 | 76985 | }else{ |
| 76912 | 76986 | rc = sqlite3VdbeMemCopy(pMem, &p->v->aMem[p->iNewReg+1+iIdx]); |
| 76913 | 76987 | if( rc!=SQLITE_OK ) goto preupdate_new_out; |
| 76914 | 76988 | } |
| @@ -78415,15 +78489,17 @@ | ||
| 78415 | 78489 | u16 nullFlag; |
| 78416 | 78490 | pOut = out2Prerelease(p, pOp); |
| 78417 | 78491 | cnt = pOp->p3-pOp->p2; |
| 78418 | 78492 | assert( pOp->p3<=(p->nMem+1 - p->nCursor) ); |
| 78419 | 78493 | pOut->flags = nullFlag = pOp->p1 ? (MEM_Null|MEM_Cleared) : MEM_Null; |
| 78494 | + pOut->n = 0; | |
| 78420 | 78495 | while( cnt>0 ){ |
| 78421 | 78496 | pOut++; |
| 78422 | 78497 | memAboutToChange(p, pOut); |
| 78423 | 78498 | sqlite3VdbeMemSetNull(pOut); |
| 78424 | 78499 | pOut->flags = nullFlag; |
| 78500 | + pOut->n = 0; | |
| 78425 | 78501 | cnt--; |
| 78426 | 78502 | } |
| 78427 | 78503 | break; |
| 78428 | 78504 | } |
| 78429 | 78505 | |
| @@ -79280,12 +79356,11 @@ | ||
| 79280 | 79356 | ** or not both operands are null. |
| 79281 | 79357 | */ |
| 79282 | 79358 | assert( pOp->opcode==OP_Eq || pOp->opcode==OP_Ne ); |
| 79283 | 79359 | assert( (flags1 & MEM_Cleared)==0 ); |
| 79284 | 79360 | assert( (pOp->p5 & SQLITE_JUMPIFNULL)==0 ); |
| 79285 | - if( (flags1&MEM_Null)!=0 | |
| 79286 | - && (flags3&MEM_Null)!=0 | |
| 79361 | + if( (flags1&flags3&MEM_Null)!=0 | |
| 79287 | 79362 | && (flags3&MEM_Cleared)==0 |
| 79288 | 79363 | ){ |
| 79289 | 79364 | res = 0; /* Operands are equal */ |
| 79290 | 79365 | }else{ |
| 79291 | 79366 | res = 1; /* Operands are not equal */ |
| @@ -80487,14 +80562,13 @@ | ||
| 80487 | 80562 | p->nStmtDefCons = db->nDeferredCons; |
| 80488 | 80563 | p->nStmtDefImmCons = db->nDeferredImmCons; |
| 80489 | 80564 | } |
| 80490 | 80565 | |
| 80491 | 80566 | /* Gather the schema version number for checking: |
| 80492 | - ** IMPLEMENTATION-OF: R-32195-19465 The schema version is used by SQLite | |
| 80493 | - ** each time a query is executed to ensure that the internal cache of the | |
| 80494 | - ** schema used when compiling the SQL query matches the schema of the | |
| 80495 | - ** database against which the compiled query is actually executed. | |
| 80567 | + ** IMPLEMENTATION-OF: R-03189-51135 As each SQL statement runs, the schema | |
| 80568 | + ** version is checked to ensure that the schema has not changed since the | |
| 80569 | + ** SQL statement was prepared. | |
| 80496 | 80570 | */ |
| 80497 | 80571 | sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&iMeta); |
| 80498 | 80572 | iGen = db->aDb[pOp->p1].pSchema->iGeneration; |
| 80499 | 80573 | }else{ |
| 80500 | 80574 | iGen = iMeta = 0; |
| @@ -81549,11 +81623,11 @@ | ||
| 81549 | 81623 | |
| 81550 | 81624 | REGISTER_TRACE(pOp->p3, pMem); |
| 81551 | 81625 | sqlite3VdbeMemIntegerify(pMem); |
| 81552 | 81626 | assert( (pMem->flags & MEM_Int)!=0 ); /* mem(P3) holds an integer */ |
| 81553 | 81627 | if( pMem->u.i==MAX_ROWID || pC->useRandomRowid ){ |
| 81554 | - rc = SQLITE_FULL; /* IMP: R-12275-61338 */ | |
| 81628 | + rc = SQLITE_FULL; /* IMP: R-17817-00630 */ | |
| 81555 | 81629 | goto abort_due_to_error; |
| 81556 | 81630 | } |
| 81557 | 81631 | if( v<pMem->u.i+1 ){ |
| 81558 | 81632 | v = pMem->u.i + 1; |
| 81559 | 81633 | } |
| @@ -81746,11 +81820,11 @@ | ||
| 81746 | 81820 | ** change count is incremented (otherwise not). |
| 81747 | 81821 | ** |
| 81748 | 81822 | ** P1 must not be pseudo-table. It has to be a real table with |
| 81749 | 81823 | ** multiple rows. |
| 81750 | 81824 | ** |
| 81751 | -** If P4 is not NULL then it points to a Table struture. In this case either | |
| 81825 | +** If P4 is not NULL then it points to a Table object. In this case either | |
| 81752 | 81826 | ** the update or pre-update hook, or both, may be invoked. The P1 cursor must |
| 81753 | 81827 | ** have been positioned using OP_NotFound prior to invoking this opcode in |
| 81754 | 81828 | ** this case. Specifically, if one is configured, the pre-update hook is |
| 81755 | 81829 | ** invoked if P4 is not NULL. The update-hook is invoked if one is configured, |
| 81756 | 81830 | ** P4 is not NULL, and the OPFLAG_NCHANGE flag is set in P2. |
| @@ -82316,10 +82390,17 @@ | ||
| 82316 | 82390 | ** This flag avoids doing an extra seek. |
| 82317 | 82391 | ** |
| 82318 | 82392 | ** This instruction only works for indices. The equivalent instruction |
| 82319 | 82393 | ** for tables is OP_Insert. |
| 82320 | 82394 | */ |
| 82395 | +/* Opcode: SorterInsert P1 P2 * * * | |
| 82396 | +** Synopsis: key=r[P2] | |
| 82397 | +** | |
| 82398 | +** Register P2 holds an SQL index key made using the | |
| 82399 | +** MakeRecord instructions. This opcode writes that key | |
| 82400 | +** into the sorter P1. Data for the entry is nil. | |
| 82401 | +*/ | |
| 82321 | 82402 | case OP_SorterInsert: /* in2 */ |
| 82322 | 82403 | case OP_IdxInsert: { /* in2 */ |
| 82323 | 82404 | VdbeCursor *pC; |
| 82324 | 82405 | BtreePayload x; |
| 82325 | 82406 | |
| @@ -82337,13 +82418,10 @@ | ||
| 82337 | 82418 | if( pOp->opcode==OP_SorterInsert ){ |
| 82338 | 82419 | rc = sqlite3VdbeSorterWrite(pC, pIn2); |
| 82339 | 82420 | }else{ |
| 82340 | 82421 | x.nKey = pIn2->n; |
| 82341 | 82422 | x.pKey = pIn2->z; |
| 82342 | - x.nData = 0; | |
| 82343 | - x.nZero = 0; | |
| 82344 | - x.pData = 0; | |
| 82345 | 82423 | rc = sqlite3BtreeInsert(pC->uc.pCursor, &x, pOp->p3, |
| 82346 | 82424 | ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0) |
| 82347 | 82425 | ); |
| 82348 | 82426 | assert( pC->deferredMoveto==0 ); |
| 82349 | 82427 | pC->cacheStatus = CACHE_STALE; |
| @@ -83547,11 +83625,11 @@ | ||
| 83547 | 83625 | /* If leaving WAL mode, close the log file. If successful, the call |
| 83548 | 83626 | ** to PagerCloseWal() checkpoints and deletes the write-ahead-log |
| 83549 | 83627 | ** file. An EXCLUSIVE lock may still be held on the database file |
| 83550 | 83628 | ** after a successful return. |
| 83551 | 83629 | */ |
| 83552 | - rc = sqlite3PagerCloseWal(pPager); | |
| 83630 | + rc = sqlite3PagerCloseWal(pPager, db); | |
| 83553 | 83631 | if( rc==SQLITE_OK ){ |
| 83554 | 83632 | sqlite3PagerSetJournalMode(pPager, eNew); |
| 83555 | 83633 | } |
| 83556 | 83634 | }else if( eOld==PAGER_JOURNALMODE_MEMORY ){ |
| 83557 | 83635 | /* Cannot transition directly from MEMORY to WAL. Use mode OFF |
| @@ -88036,11 +88114,13 @@ | ||
| 88036 | 88114 | static SQLITE_NOINLINE int walkExpr(Walker *pWalker, Expr *pExpr){ |
| 88037 | 88115 | int rc; |
| 88038 | 88116 | testcase( ExprHasProperty(pExpr, EP_TokenOnly) ); |
| 88039 | 88117 | testcase( ExprHasProperty(pExpr, EP_Reduced) ); |
| 88040 | 88118 | rc = pWalker->xExprCallback(pWalker, pExpr); |
| 88041 | - if( rc || ExprHasProperty(pExpr,EP_TokenOnly) ) return rc & WRC_Abort; | |
| 88119 | + if( rc || ExprHasProperty(pExpr,(EP_TokenOnly|EP_Leaf)) ){ | |
| 88120 | + return rc & WRC_Abort; | |
| 88121 | + } | |
| 88042 | 88122 | if( pExpr->pLeft && walkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort; |
| 88043 | 88123 | if( pExpr->pRight && walkExpr(pWalker, pExpr->pRight) ) return WRC_Abort; |
| 88044 | 88124 | if( ExprHasProperty(pExpr, EP_xIsSelect) ){ |
| 88045 | 88125 | if( sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort; |
| 88046 | 88126 | }else if( pExpr->x.pList ){ |
| @@ -88780,11 +88860,10 @@ | ||
| 88780 | 88860 | const char *zDb; |
| 88781 | 88861 | Expr *pRight; |
| 88782 | 88862 | |
| 88783 | 88863 | /* if( pSrcList==0 ) break; */ |
| 88784 | 88864 | notValid(pParse, pNC, "the \".\" operator", NC_IdxExpr); |
| 88785 | - /*notValid(pParse, pNC, "the \".\" operator", NC_PartIdx|NC_IsCheck, 1);*/ | |
| 88786 | 88865 | pRight = pExpr->pRight; |
| 88787 | 88866 | if( pRight->op==TK_ID ){ |
| 88788 | 88867 | zDb = 0; |
| 88789 | 88868 | zTable = pExpr->pLeft->u.zToken; |
| 88790 | 88869 | zColumn = pRight->u.zToken; |
| @@ -88809,11 +88888,10 @@ | ||
| 88809 | 88888 | const char *zId; /* The function name. */ |
| 88810 | 88889 | FuncDef *pDef; /* Information about the function */ |
| 88811 | 88890 | u8 enc = ENC(pParse->db); /* The database encoding */ |
| 88812 | 88891 | |
| 88813 | 88892 | assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); |
| 88814 | - notValid(pParse, pNC, "functions", NC_PartIdx); | |
| 88815 | 88893 | zId = pExpr->u.zToken; |
| 88816 | 88894 | nId = sqlite3Strlen30(zId); |
| 88817 | 88895 | pDef = sqlite3FindFunction(pParse->db, zId, n, enc, 0); |
| 88818 | 88896 | if( pDef==0 ){ |
| 88819 | 88897 | pDef = sqlite3FindFunction(pParse->db, zId, -2, enc, 0); |
| @@ -88869,11 +88947,12 @@ | ||
| 88869 | 88947 | } |
| 88870 | 88948 | if( (pDef->funcFlags & SQLITE_FUNC_CONSTANT)==0 ){ |
| 88871 | 88949 | /* Date/time functions that use 'now', and other functions like |
| 88872 | 88950 | ** sqlite_version() that might change over time cannot be used |
| 88873 | 88951 | ** in an index. */ |
| 88874 | - notValid(pParse, pNC, "non-deterministic functions", NC_IdxExpr); | |
| 88952 | + notValid(pParse, pNC, "non-deterministic functions", | |
| 88953 | + NC_IdxExpr|NC_PartIdx); | |
| 88875 | 88954 | } |
| 88876 | 88955 | } |
| 88877 | 88956 | if( is_agg && (pNC->ncFlags & NC_AllowAgg)==0 ){ |
| 88878 | 88957 | sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId); |
| 88879 | 88958 | pNC->nErr++; |
| @@ -90409,11 +90488,11 @@ | ||
| 90409 | 90488 | ** stored in u.zToken. Instead, the integer values is written |
| 90410 | 90489 | ** into u.iValue and the EP_IntValue flag is set. No extra storage |
| 90411 | 90490 | ** is allocated to hold the integer text and the dequote flag is ignored. |
| 90412 | 90491 | */ |
| 90413 | 90492 | SQLITE_PRIVATE Expr *sqlite3ExprAlloc( |
| 90414 | - sqlite3 *db, /* Handle for sqlite3DbMallocZero() (may be null) */ | |
| 90493 | + sqlite3 *db, /* Handle for sqlite3DbMallocRawNN() */ | |
| 90415 | 90494 | int op, /* Expression opcode */ |
| 90416 | 90495 | const Token *pToken, /* Token argument. Might be NULL */ |
| 90417 | 90496 | int dequote /* True to dequote */ |
| 90418 | 90497 | ){ |
| 90419 | 90498 | Expr *pNew; |
| @@ -90627,40 +90706,40 @@ | ||
| 90627 | 90706 | ** Wildcards of the form ":aaa", "@aaa", or "$aaa" are assigned the same number |
| 90628 | 90707 | ** as the previous instance of the same wildcard. Or if this is the first |
| 90629 | 90708 | ** instance of the wildcard, the next sequential variable number is |
| 90630 | 90709 | ** assigned. |
| 90631 | 90710 | */ |
| 90632 | -SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){ | |
| 90711 | +SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr, u32 n){ | |
| 90633 | 90712 | sqlite3 *db = pParse->db; |
| 90634 | 90713 | const char *z; |
| 90635 | 90714 | |
| 90636 | 90715 | if( pExpr==0 ) return; |
| 90637 | 90716 | assert( !ExprHasProperty(pExpr, EP_IntValue|EP_Reduced|EP_TokenOnly) ); |
| 90638 | 90717 | z = pExpr->u.zToken; |
| 90639 | 90718 | assert( z!=0 ); |
| 90640 | 90719 | assert( z[0]!=0 ); |
| 90720 | + assert( n==sqlite3Strlen30(z) ); | |
| 90641 | 90721 | if( z[1]==0 ){ |
| 90642 | 90722 | /* Wildcard of the form "?". Assign the next variable number */ |
| 90643 | 90723 | assert( z[0]=='?' ); |
| 90644 | 90724 | pExpr->iColumn = (ynVar)(++pParse->nVar); |
| 90645 | 90725 | }else{ |
| 90646 | - ynVar x = 0; | |
| 90647 | - u32 n = sqlite3Strlen30(z); | |
| 90726 | + ynVar x; | |
| 90648 | 90727 | if( z[0]=='?' ){ |
| 90649 | 90728 | /* Wildcard of the form "?nnn". Convert "nnn" to an integer and |
| 90650 | 90729 | ** use it as the variable number */ |
| 90651 | 90730 | i64 i; |
| 90652 | 90731 | int bOk = 0==sqlite3Atoi64(&z[1], &i, n-1, SQLITE_UTF8); |
| 90653 | - pExpr->iColumn = x = (ynVar)i; | |
| 90732 | + x = (ynVar)i; | |
| 90654 | 90733 | testcase( i==0 ); |
| 90655 | 90734 | testcase( i==1 ); |
| 90656 | 90735 | testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]-1 ); |
| 90657 | 90736 | testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ); |
| 90658 | 90737 | if( bOk==0 || i<1 || i>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){ |
| 90659 | 90738 | sqlite3ErrorMsg(pParse, "variable number must be between ?1 and ?%d", |
| 90660 | 90739 | db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]); |
| 90661 | - x = 0; | |
| 90740 | + return; | |
| 90662 | 90741 | } |
| 90663 | 90742 | if( i>pParse->nVar ){ |
| 90664 | 90743 | pParse->nVar = (int)i; |
| 90665 | 90744 | } |
| 90666 | 90745 | }else{ |
| @@ -90667,37 +90746,35 @@ | ||
| 90667 | 90746 | /* Wildcards like ":aaa", "$aaa" or "@aaa". Reuse the same variable |
| 90668 | 90747 | ** number as the prior appearance of the same name, or if the name |
| 90669 | 90748 | ** has never appeared before, reuse the same variable number |
| 90670 | 90749 | */ |
| 90671 | 90750 | ynVar i; |
| 90672 | - for(i=0; i<pParse->nzVar; i++){ | |
| 90751 | + for(i=x=0; i<pParse->nzVar; i++){ | |
| 90673 | 90752 | if( pParse->azVar[i] && strcmp(pParse->azVar[i],z)==0 ){ |
| 90674 | - pExpr->iColumn = x = (ynVar)i+1; | |
| 90675 | - break; | |
| 90676 | - } | |
| 90677 | - } | |
| 90678 | - if( x==0 ) x = pExpr->iColumn = (ynVar)(++pParse->nVar); | |
| 90679 | - } | |
| 90680 | - if( x>0 ){ | |
| 90681 | - if( x>pParse->nzVar ){ | |
| 90682 | - char **a; | |
| 90683 | - a = sqlite3DbRealloc(db, pParse->azVar, x*sizeof(a[0])); | |
| 90684 | - if( a==0 ){ | |
| 90685 | - assert( db->mallocFailed ); /* Error reported through mallocFailed */ | |
| 90686 | - return; | |
| 90687 | - } | |
| 90688 | - pParse->azVar = a; | |
| 90689 | - memset(&a[pParse->nzVar], 0, (x-pParse->nzVar)*sizeof(a[0])); | |
| 90690 | - pParse->nzVar = x; | |
| 90691 | - } | |
| 90692 | - if( z[0]!='?' || pParse->azVar[x-1]==0 ){ | |
| 90693 | - sqlite3DbFree(db, pParse->azVar[x-1]); | |
| 90694 | - pParse->azVar[x-1] = sqlite3DbStrNDup(db, z, n); | |
| 90695 | - } | |
| 90696 | - } | |
| 90697 | - } | |
| 90698 | - if( !pParse->nErr && pParse->nVar>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){ | |
| 90753 | + x = (ynVar)i+1; | |
| 90754 | + break; | |
| 90755 | + } | |
| 90756 | + } | |
| 90757 | + if( x==0 ) x = (ynVar)(++pParse->nVar); | |
| 90758 | + } | |
| 90759 | + pExpr->iColumn = x; | |
| 90760 | + if( x>pParse->nzVar ){ | |
| 90761 | + char **a; | |
| 90762 | + a = sqlite3DbRealloc(db, pParse->azVar, x*sizeof(a[0])); | |
| 90763 | + if( a==0 ){ | |
| 90764 | + assert( db->mallocFailed ); /* Error reported through mallocFailed */ | |
| 90765 | + return; | |
| 90766 | + } | |
| 90767 | + pParse->azVar = a; | |
| 90768 | + memset(&a[pParse->nzVar], 0, (x-pParse->nzVar)*sizeof(a[0])); | |
| 90769 | + pParse->nzVar = x; | |
| 90770 | + } | |
| 90771 | + if( pParse->azVar[x-1]==0 ){ | |
| 90772 | + pParse->azVar[x-1] = sqlite3DbStrNDup(db, z, n); | |
| 90773 | + } | |
| 90774 | + } | |
| 90775 | + if( pParse->nVar>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){ | |
| 90699 | 90776 | sqlite3ErrorMsg(pParse, "too many SQL variables"); |
| 90700 | 90777 | } |
| 90701 | 90778 | } |
| 90702 | 90779 | |
| 90703 | 90780 | /* |
| @@ -90705,22 +90782,29 @@ | ||
| 90705 | 90782 | */ |
| 90706 | 90783 | static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){ |
| 90707 | 90784 | assert( p!=0 ); |
| 90708 | 90785 | /* Sanity check: Assert that the IntValue is non-negative if it exists */ |
| 90709 | 90786 | assert( !ExprHasProperty(p, EP_IntValue) || p->u.iValue>=0 ); |
| 90710 | - if( !ExprHasProperty(p, EP_TokenOnly) ){ | |
| 90787 | +#ifdef SQLITE_DEBUG | |
| 90788 | + if( ExprHasProperty(p, EP_Leaf) && !ExprHasProperty(p, EP_TokenOnly) ){ | |
| 90789 | + assert( p->pLeft==0 ); | |
| 90790 | + assert( p->pRight==0 ); | |
| 90791 | + assert( p->x.pSelect==0 ); | |
| 90792 | + } | |
| 90793 | +#endif | |
| 90794 | + if( !ExprHasProperty(p, (EP_TokenOnly|EP_Leaf)) ){ | |
| 90711 | 90795 | /* The Expr.x union is never used at the same time as Expr.pRight */ |
| 90712 | 90796 | assert( p->x.pList==0 || p->pRight==0 ); |
| 90713 | 90797 | if( p->pLeft && p->op!=TK_SELECT_COLUMN ) sqlite3ExprDeleteNN(db, p->pLeft); |
| 90714 | 90798 | sqlite3ExprDelete(db, p->pRight); |
| 90715 | - if( ExprHasProperty(p, EP_MemToken) ) sqlite3DbFree(db, p->u.zToken); | |
| 90716 | 90799 | if( ExprHasProperty(p, EP_xIsSelect) ){ |
| 90717 | 90800 | sqlite3SelectDelete(db, p->x.pSelect); |
| 90718 | 90801 | }else{ |
| 90719 | 90802 | sqlite3ExprListDelete(db, p->x.pList); |
| 90720 | 90803 | } |
| 90721 | 90804 | } |
| 90805 | + if( ExprHasProperty(p, EP_MemToken) ) sqlite3DbFree(db, p->u.zToken); | |
| 90722 | 90806 | if( !ExprHasProperty(p, EP_Static) ){ |
| 90723 | 90807 | sqlite3DbFree(db, p); |
| 90724 | 90808 | } |
| 90725 | 90809 | } |
| 90726 | 90810 | SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3 *db, Expr *p){ |
| @@ -90893,11 +90977,11 @@ | ||
| 90893 | 90977 | if( nToken ){ |
| 90894 | 90978 | char *zToken = pNew->u.zToken = (char*)&zAlloc[nNewSize]; |
| 90895 | 90979 | memcpy(zToken, p->u.zToken, nToken); |
| 90896 | 90980 | } |
| 90897 | 90981 | |
| 90898 | - if( 0==((p->flags|pNew->flags) & EP_TokenOnly) ){ | |
| 90982 | + if( 0==((p->flags|pNew->flags) & (EP_TokenOnly|EP_Leaf)) ){ | |
| 90899 | 90983 | /* Fill in the pNew->x.pSelect or pNew->x.pList member. */ |
| 90900 | 90984 | if( ExprHasProperty(p, EP_xIsSelect) ){ |
| 90901 | 90985 | pNew->x.pSelect = sqlite3SelectDup(db, p->x.pSelect, dupFlags); |
| 90902 | 90986 | }else{ |
| 90903 | 90987 | pNew->x.pList = sqlite3ExprListDup(db, p->x.pList, dupFlags); |
| @@ -90905,21 +90989,21 @@ | ||
| 90905 | 90989 | } |
| 90906 | 90990 | |
| 90907 | 90991 | /* Fill in pNew->pLeft and pNew->pRight. */ |
| 90908 | 90992 | if( ExprHasProperty(pNew, EP_Reduced|EP_TokenOnly) ){ |
| 90909 | 90993 | zAlloc += dupedExprNodeSize(p, dupFlags); |
| 90910 | - if( ExprHasProperty(pNew, EP_Reduced) ){ | |
| 90994 | + if( !ExprHasProperty(pNew, EP_TokenOnly|EP_Leaf) ){ | |
| 90911 | 90995 | pNew->pLeft = p->pLeft ? |
| 90912 | 90996 | exprDup(db, p->pLeft, EXPRDUP_REDUCE, &zAlloc) : 0; |
| 90913 | 90997 | pNew->pRight = p->pRight ? |
| 90914 | 90998 | exprDup(db, p->pRight, EXPRDUP_REDUCE, &zAlloc) : 0; |
| 90915 | 90999 | } |
| 90916 | 91000 | if( pzBuffer ){ |
| 90917 | 91001 | *pzBuffer = zAlloc; |
| 90918 | 91002 | } |
| 90919 | 91003 | }else{ |
| 90920 | - if( !ExprHasProperty(p, EP_TokenOnly) ){ | |
| 91004 | + if( !ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){ | |
| 90921 | 91005 | if( pNew->op==TK_SELECT_COLUMN ){ |
| 90922 | 91006 | pNew->pLeft = p->pLeft; |
| 90923 | 91007 | }else{ |
| 90924 | 91008 | pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0); |
| 90925 | 91009 | } |
| @@ -92276,12 +92360,12 @@ | ||
| 92276 | 92360 | dest.eDest = SRT_Exists; |
| 92277 | 92361 | sqlite3VdbeAddOp2(v, OP_Integer, 0, dest.iSDParm); |
| 92278 | 92362 | VdbeComment((v, "Init EXISTS result")); |
| 92279 | 92363 | } |
| 92280 | 92364 | sqlite3ExprDelete(pParse->db, pSel->pLimit); |
| 92281 | - pSel->pLimit = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, | |
| 92282 | - &sqlite3IntTokens[1]); | |
| 92365 | + pSel->pLimit = sqlite3ExprAlloc(pParse->db, TK_INTEGER, | |
| 92366 | + &sqlite3IntTokens[1], 0); | |
| 92283 | 92367 | pSel->iLimit = 0; |
| 92284 | 92368 | pSel->selFlags &= ~SF_MultiValue; |
| 92285 | 92369 | if( sqlite3Select(pParse, pSel, &dest) ){ |
| 92286 | 92370 | return 0; |
| 92287 | 92371 | } |
| @@ -92646,36 +92730,23 @@ | ||
| 92646 | 92730 | #endif |
| 92647 | 92731 | } |
| 92648 | 92732 | } |
| 92649 | 92733 | } |
| 92650 | 92734 | |
| 92651 | -#if defined(SQLITE_DEBUG) | |
| 92652 | -/* | |
| 92653 | -** Verify the consistency of the column cache | |
| 92654 | -*/ | |
| 92655 | -static int cacheIsValid(Parse *pParse){ | |
| 92656 | - int i, n; | |
| 92657 | - for(i=n=0; i<SQLITE_N_COLCACHE; i++){ | |
| 92658 | - if( pParse->aColCache[i].iReg>0 ) n++; | |
| 92659 | - } | |
| 92660 | - return n==pParse->nColCache; | |
| 92661 | -} | |
| 92662 | -#endif | |
| 92663 | - | |
| 92664 | -/* | |
| 92665 | -** Clear a cache entry. | |
| 92666 | -*/ | |
| 92667 | -static void cacheEntryClear(Parse *pParse, struct yColCache *p){ | |
| 92668 | - if( p->tempReg ){ | |
| 92735 | +/* | |
| 92736 | +** Erase column-cache entry number i | |
| 92737 | +*/ | |
| 92738 | +static void cacheEntryClear(Parse *pParse, int i){ | |
| 92739 | + if( pParse->aColCache[i].tempReg ){ | |
| 92669 | 92740 | if( pParse->nTempReg<ArraySize(pParse->aTempReg) ){ |
| 92670 | - pParse->aTempReg[pParse->nTempReg++] = p->iReg; | |
| 92741 | + pParse->aTempReg[pParse->nTempReg++] = pParse->aColCache[i].iReg; | |
| 92671 | 92742 | } |
| 92672 | - p->tempReg = 0; | |
| 92673 | 92743 | } |
| 92674 | - p->iReg = 0; | |
| 92675 | 92744 | pParse->nColCache--; |
| 92676 | - assert( pParse->db->mallocFailed || cacheIsValid(pParse) ); | |
| 92745 | + if( i<pParse->nColCache ){ | |
| 92746 | + pParse->aColCache[i] = pParse->aColCache[pParse->nColCache]; | |
| 92747 | + } | |
| 92677 | 92748 | } |
| 92678 | 92749 | |
| 92679 | 92750 | |
| 92680 | 92751 | /* |
| 92681 | 92752 | ** Record in the column cache that a particular column from a |
| @@ -92701,64 +92772,52 @@ | ||
| 92701 | 92772 | ** |
| 92702 | 92773 | ** Actually, the way the column cache is currently used, we are guaranteed |
| 92703 | 92774 | ** that the object will never already be in cache. Verify this guarantee. |
| 92704 | 92775 | */ |
| 92705 | 92776 | #ifndef NDEBUG |
| 92706 | - for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){ | |
| 92707 | - assert( p->iReg==0 || p->iTable!=iTab || p->iColumn!=iCol ); | |
| 92777 | + for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){ | |
| 92778 | + assert( p->iTable!=iTab || p->iColumn!=iCol ); | |
| 92708 | 92779 | } |
| 92709 | 92780 | #endif |
| 92710 | 92781 | |
| 92711 | - /* Find an empty slot and replace it */ | |
| 92712 | - for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){ | |
| 92713 | - if( p->iReg==0 ){ | |
| 92714 | - p->iLevel = pParse->iCacheLevel; | |
| 92715 | - p->iTable = iTab; | |
| 92716 | - p->iColumn = iCol; | |
| 92717 | - p->iReg = iReg; | |
| 92718 | - p->tempReg = 0; | |
| 92719 | - p->lru = pParse->iCacheCnt++; | |
| 92720 | - pParse->nColCache++; | |
| 92721 | - assert( pParse->db->mallocFailed || cacheIsValid(pParse) ); | |
| 92722 | - return; | |
| 92723 | - } | |
| 92724 | - } | |
| 92725 | - | |
| 92726 | - /* Replace the last recently used */ | |
| 92727 | - minLru = 0x7fffffff; | |
| 92728 | - idxLru = -1; | |
| 92729 | - for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){ | |
| 92730 | - if( p->lru<minLru ){ | |
| 92731 | - idxLru = i; | |
| 92732 | - minLru = p->lru; | |
| 92733 | - } | |
| 92734 | - } | |
| 92735 | - if( ALWAYS(idxLru>=0) ){ | |
| 92782 | + /* If the cache is already full, delete the least recently used entry */ | |
| 92783 | + if( pParse->nColCache>=SQLITE_N_COLCACHE ){ | |
| 92784 | + minLru = 0x7fffffff; | |
| 92785 | + idxLru = -1; | |
| 92786 | + for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){ | |
| 92787 | + if( p->lru<minLru ){ | |
| 92788 | + idxLru = i; | |
| 92789 | + minLru = p->lru; | |
| 92790 | + } | |
| 92791 | + } | |
| 92736 | 92792 | p = &pParse->aColCache[idxLru]; |
| 92737 | - p->iLevel = pParse->iCacheLevel; | |
| 92738 | - p->iTable = iTab; | |
| 92739 | - p->iColumn = iCol; | |
| 92740 | - p->iReg = iReg; | |
| 92741 | - p->tempReg = 0; | |
| 92742 | - p->lru = pParse->iCacheCnt++; | |
| 92743 | - assert( cacheIsValid(pParse) ); | |
| 92744 | - return; | |
| 92745 | - } | |
| 92793 | + }else{ | |
| 92794 | + p = &pParse->aColCache[pParse->nColCache++]; | |
| 92795 | + } | |
| 92796 | + | |
| 92797 | + /* Add the new entry to the end of the cache */ | |
| 92798 | + p->iLevel = pParse->iCacheLevel; | |
| 92799 | + p->iTable = iTab; | |
| 92800 | + p->iColumn = iCol; | |
| 92801 | + p->iReg = iReg; | |
| 92802 | + p->tempReg = 0; | |
| 92803 | + p->lru = pParse->iCacheCnt++; | |
| 92746 | 92804 | } |
| 92747 | 92805 | |
| 92748 | 92806 | /* |
| 92749 | 92807 | ** Indicate that registers between iReg..iReg+nReg-1 are being overwritten. |
| 92750 | 92808 | ** Purge the range of registers from the column cache. |
| 92751 | 92809 | */ |
| 92752 | 92810 | SQLITE_PRIVATE void sqlite3ExprCacheRemove(Parse *pParse, int iReg, int nReg){ |
| 92753 | - struct yColCache *p; | |
| 92754 | - if( iReg<=0 || pParse->nColCache==0 ) return; | |
| 92755 | - p = &pParse->aColCache[SQLITE_N_COLCACHE-1]; | |
| 92756 | - while(1){ | |
| 92757 | - if( p->iReg >= iReg && p->iReg < iReg+nReg ) cacheEntryClear(pParse, p); | |
| 92758 | - if( p==pParse->aColCache ) break; | |
| 92759 | - p--; | |
| 92811 | + int i = 0; | |
| 92812 | + while( i<pParse->nColCache ){ | |
| 92813 | + struct yColCache *p = &pParse->aColCache[i]; | |
| 92814 | + if( p->iReg >= iReg && p->iReg < iReg+nReg ){ | |
| 92815 | + cacheEntryClear(pParse, i); | |
| 92816 | + }else{ | |
| 92817 | + i++; | |
| 92818 | + } | |
| 92760 | 92819 | } |
| 92761 | 92820 | } |
| 92762 | 92821 | |
| 92763 | 92822 | /* |
| 92764 | 92823 | ** Remember the current column cache context. Any new entries added |
| @@ -92778,22 +92837,23 @@ | ||
| 92778 | 92837 | ** Remove from the column cache any entries that were added since the |
| 92779 | 92838 | ** the previous sqlite3ExprCachePush operation. In other words, restore |
| 92780 | 92839 | ** the cache to the state it was in prior the most recent Push. |
| 92781 | 92840 | */ |
| 92782 | 92841 | SQLITE_PRIVATE void sqlite3ExprCachePop(Parse *pParse){ |
| 92783 | - int i; | |
| 92784 | - struct yColCache *p; | |
| 92842 | + int i = 0; | |
| 92785 | 92843 | assert( pParse->iCacheLevel>=1 ); |
| 92786 | 92844 | pParse->iCacheLevel--; |
| 92787 | 92845 | #ifdef SQLITE_DEBUG |
| 92788 | 92846 | if( pParse->db->flags & SQLITE_VdbeAddopTrace ){ |
| 92789 | 92847 | printf("POP to %d\n", pParse->iCacheLevel); |
| 92790 | 92848 | } |
| 92791 | 92849 | #endif |
| 92792 | - for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){ | |
| 92793 | - if( p->iReg && p->iLevel>pParse->iCacheLevel ){ | |
| 92794 | - cacheEntryClear(pParse, p); | |
| 92850 | + while( i<pParse->nColCache ){ | |
| 92851 | + if( pParse->aColCache[i].iLevel>pParse->iCacheLevel ){ | |
| 92852 | + cacheEntryClear(pParse, i); | |
| 92853 | + }else{ | |
| 92854 | + i++; | |
| 92795 | 92855 | } |
| 92796 | 92856 | } |
| 92797 | 92857 | } |
| 92798 | 92858 | |
| 92799 | 92859 | /* |
| @@ -92803,11 +92863,11 @@ | ||
| 92803 | 92863 | ** get them all. |
| 92804 | 92864 | */ |
| 92805 | 92865 | static void sqlite3ExprCachePinRegister(Parse *pParse, int iReg){ |
| 92806 | 92866 | int i; |
| 92807 | 92867 | struct yColCache *p; |
| 92808 | - for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){ | |
| 92868 | + for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){ | |
| 92809 | 92869 | if( p->iReg==iReg ){ |
| 92810 | 92870 | p->tempReg = 0; |
| 92811 | 92871 | } |
| 92812 | 92872 | } |
| 92813 | 92873 | } |
| @@ -92881,12 +92941,12 @@ | ||
| 92881 | 92941 | ){ |
| 92882 | 92942 | Vdbe *v = pParse->pVdbe; |
| 92883 | 92943 | int i; |
| 92884 | 92944 | struct yColCache *p; |
| 92885 | 92945 | |
| 92886 | - for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){ | |
| 92887 | - if( p->iReg>0 && p->iTable==iTable && p->iColumn==iColumn ){ | |
| 92946 | + for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){ | |
| 92947 | + if( p->iTable==iTable && p->iColumn==iColumn ){ | |
| 92888 | 92948 | p->lru = pParse->iCacheCnt++; |
| 92889 | 92949 | sqlite3ExprCachePinRegister(pParse, p->iReg); |
| 92890 | 92950 | return p->iReg; |
| 92891 | 92951 | } |
| 92892 | 92952 | } |
| @@ -92914,22 +92974,24 @@ | ||
| 92914 | 92974 | /* |
| 92915 | 92975 | ** Clear all column cache entries. |
| 92916 | 92976 | */ |
| 92917 | 92977 | SQLITE_PRIVATE void sqlite3ExprCacheClear(Parse *pParse){ |
| 92918 | 92978 | int i; |
| 92919 | - struct yColCache *p; | |
| 92920 | 92979 | |
| 92921 | 92980 | #if SQLITE_DEBUG |
| 92922 | 92981 | if( pParse->db->flags & SQLITE_VdbeAddopTrace ){ |
| 92923 | 92982 | printf("CLEAR\n"); |
| 92924 | 92983 | } |
| 92925 | 92984 | #endif |
| 92926 | - for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){ | |
| 92927 | - if( p->iReg ){ | |
| 92928 | - cacheEntryClear(pParse, p); | |
| 92985 | + for(i=0; i<pParse->nColCache; i++){ | |
| 92986 | + if( pParse->aColCache[i].tempReg | |
| 92987 | + && pParse->nTempReg<ArraySize(pParse->aTempReg) | |
| 92988 | + ){ | |
| 92989 | + pParse->aTempReg[pParse->nTempReg++] = pParse->aColCache[i].iReg; | |
| 92929 | 92990 | } |
| 92930 | 92991 | } |
| 92992 | + pParse->nColCache = 0; | |
| 92931 | 92993 | } |
| 92932 | 92994 | |
| 92933 | 92995 | /* |
| 92934 | 92996 | ** Record the fact that an affinity change has occurred on iCount |
| 92935 | 92997 | ** registers starting with iStart. |
| @@ -92957,11 +93019,11 @@ | ||
| 92957 | 93019 | ** and does not appear in a normal build. |
| 92958 | 93020 | */ |
| 92959 | 93021 | static int usedAsColumnCache(Parse *pParse, int iFrom, int iTo){ |
| 92960 | 93022 | int i; |
| 92961 | 93023 | struct yColCache *p; |
| 92962 | - for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){ | |
| 93024 | + for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){ | |
| 92963 | 93025 | int r = p->iReg; |
| 92964 | 93026 | if( r>=iFrom && r<=iTo ) return 1; /*NO_TEST*/ |
| 92965 | 93027 | } |
| 92966 | 93028 | return 0; |
| 92967 | 93029 | } |
| @@ -94306,15 +94368,14 @@ | ||
| 94306 | 94368 | && (sqlite3ExprImpliesExpr(pE1, pE2->pLeft, iTab) |
| 94307 | 94369 | || sqlite3ExprImpliesExpr(pE1, pE2->pRight, iTab) ) |
| 94308 | 94370 | ){ |
| 94309 | 94371 | return 1; |
| 94310 | 94372 | } |
| 94311 | - if( pE2->op==TK_NOTNULL | |
| 94312 | - && sqlite3ExprCompare(pE1->pLeft, pE2->pLeft, iTab)==0 | |
| 94313 | - && (pE1->op!=TK_ISNULL && pE1->op!=TK_IS) | |
| 94314 | - ){ | |
| 94315 | - return 1; | |
| 94373 | + if( pE2->op==TK_NOTNULL && pE1->op!=TK_ISNULL && pE1->op!=TK_IS ){ | |
| 94374 | + Expr *pX = sqlite3ExprSkipCollate(pE1->pLeft); | |
| 94375 | + testcase( pX!=pE1->pLeft ); | |
| 94376 | + if( sqlite3ExprCompare(pX, pE2->pLeft, iTab)==0 ) return 1; | |
| 94316 | 94377 | } |
| 94317 | 94378 | return 0; |
| 94318 | 94379 | } |
| 94319 | 94380 | |
| 94320 | 94381 | /* |
| @@ -94653,11 +94714,11 @@ | ||
| 94653 | 94714 | */ |
| 94654 | 94715 | SQLITE_PRIVATE void sqlite3ReleaseTempReg(Parse *pParse, int iReg){ |
| 94655 | 94716 | if( iReg && pParse->nTempReg<ArraySize(pParse->aTempReg) ){ |
| 94656 | 94717 | int i; |
| 94657 | 94718 | struct yColCache *p; |
| 94658 | - for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){ | |
| 94719 | + for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){ | |
| 94659 | 94720 | if( p->iReg==iReg ){ |
| 94660 | 94721 | p->tempReg = 1; |
| 94661 | 94722 | return; |
| 94662 | 94723 | } |
| 94663 | 94724 | } |
| @@ -97959,11 +98020,11 @@ | ||
| 97959 | 98020 | }else{ |
| 97960 | 98021 | sqlite3ErrorMsg(pFix->pParse, "%s cannot use variables", pFix->zType); |
| 97961 | 98022 | return 1; |
| 97962 | 98023 | } |
| 97963 | 98024 | } |
| 97964 | - if( ExprHasProperty(pExpr, EP_TokenOnly) ) break; | |
| 98025 | + if( ExprHasProperty(pExpr, EP_TokenOnly|EP_Leaf) ) break; | |
| 97965 | 98026 | if( ExprHasProperty(pExpr, EP_xIsSelect) ){ |
| 97966 | 98027 | if( sqlite3FixSelect(pFix, pExpr->x.pSelect) ) return 1; |
| 97967 | 98028 | }else{ |
| 97968 | 98029 | if( sqlite3FixExprList(pFix, pExpr->x.pList) ) return 1; |
| 97969 | 98030 | } |
| @@ -98423,11 +98484,10 @@ | ||
| 98423 | 98484 | */ |
| 98424 | 98485 | v = sqlite3GetVdbe(pParse); |
| 98425 | 98486 | assert( !pParse->isMultiWrite |
| 98426 | 98487 | || sqlite3VdbeAssertMayAbort(v, pParse->mayAbort)); |
| 98427 | 98488 | if( v ){ |
| 98428 | - while( sqlite3VdbeDeletePriorOpcode(v, OP_Close) ){} | |
| 98429 | 98489 | sqlite3VdbeAddOp0(v, OP_Halt); |
| 98430 | 98490 | |
| 98431 | 98491 | #if SQLITE_USER_AUTHENTICATION |
| 98432 | 98492 | if( pParse->nTableLock>0 && db->init.busy==0 ){ |
| 98433 | 98493 | sqlite3UserAuthInit(db); |
| @@ -98450,18 +98510,20 @@ | ||
| 98450 | 98510 | ){ |
| 98451 | 98511 | int iDb, i; |
| 98452 | 98512 | assert( sqlite3VdbeGetOp(v, 0)->opcode==OP_Init ); |
| 98453 | 98513 | sqlite3VdbeJumpHere(v, 0); |
| 98454 | 98514 | for(iDb=0; iDb<db->nDb; iDb++){ |
| 98515 | + Schema *pSchema; | |
| 98455 | 98516 | if( DbMaskTest(pParse->cookieMask, iDb)==0 ) continue; |
| 98456 | 98517 | sqlite3VdbeUsesBtree(v, iDb); |
| 98518 | + pSchema = db->aDb[iDb].pSchema; | |
| 98457 | 98519 | sqlite3VdbeAddOp4Int(v, |
| 98458 | 98520 | OP_Transaction, /* Opcode */ |
| 98459 | 98521 | iDb, /* P1 */ |
| 98460 | 98522 | DbMaskTest(pParse->writeMask,iDb), /* P2 */ |
| 98461 | - pParse->cookieValue[iDb], /* P3 */ | |
| 98462 | - db->aDb[iDb].pSchema->iGeneration /* P4 */ | |
| 98523 | + pSchema->schema_cookie, /* P3 */ | |
| 98524 | + pSchema->iGeneration /* P4 */ | |
| 98463 | 98525 | ); |
| 98464 | 98526 | if( db->init.busy==0 ) sqlite3VdbeChangeP5(v, 1); |
| 98465 | 98527 | VdbeComment((v, |
| 98466 | 98528 | "usesStmtJournal=%d", pParse->mayAbort && pParse->isMultiWrite)); |
| 98467 | 98529 | } |
| @@ -98508,20 +98570,10 @@ | ||
| 98508 | 98570 | sqlite3VdbeMakeReady(v, pParse); |
| 98509 | 98571 | pParse->rc = SQLITE_DONE; |
| 98510 | 98572 | }else{ |
| 98511 | 98573 | pParse->rc = SQLITE_ERROR; |
| 98512 | 98574 | } |
| 98513 | - | |
| 98514 | - /* We are done with this Parse object. There is no need to de-initialize it */ | |
| 98515 | -#if 0 | |
| 98516 | - pParse->colNamesSet = 0; | |
| 98517 | - pParse->nTab = 0; | |
| 98518 | - pParse->nMem = 0; | |
| 98519 | - pParse->nSet = 0; | |
| 98520 | - pParse->nVar = 0; | |
| 98521 | - DbMaskZero(pParse->cookieMask); | |
| 98522 | -#endif | |
| 98523 | 98575 | } |
| 98524 | 98576 | |
| 98525 | 98577 | /* |
| 98526 | 98578 | ** Run the parser and code generator recursively in order to generate |
| 98527 | 98579 | ** code for the SQL statement given onto the end of the pParse context |
| @@ -98537,12 +98589,11 @@ | ||
| 98537 | 98589 | SQLITE_PRIVATE void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){ |
| 98538 | 98590 | va_list ap; |
| 98539 | 98591 | char *zSql; |
| 98540 | 98592 | char *zErrMsg = 0; |
| 98541 | 98593 | sqlite3 *db = pParse->db; |
| 98542 | -# define SAVE_SZ (sizeof(Parse) - offsetof(Parse,nVar)) | |
| 98543 | - char saveBuf[SAVE_SZ]; | |
| 98594 | + char saveBuf[PARSE_TAIL_SZ]; | |
| 98544 | 98595 | |
| 98545 | 98596 | if( pParse->nErr ) return; |
| 98546 | 98597 | assert( pParse->nested<10 ); /* Nesting should only be of limited depth */ |
| 98547 | 98598 | va_start(ap, zFormat); |
| 98548 | 98599 | zSql = sqlite3VMPrintf(db, zFormat, ap); |
| @@ -98549,16 +98600,16 @@ | ||
| 98549 | 98600 | va_end(ap); |
| 98550 | 98601 | if( zSql==0 ){ |
| 98551 | 98602 | return; /* A malloc must have failed */ |
| 98552 | 98603 | } |
| 98553 | 98604 | pParse->nested++; |
| 98554 | - memcpy(saveBuf, &pParse->nVar, SAVE_SZ); | |
| 98555 | - memset(&pParse->nVar, 0, SAVE_SZ); | |
| 98605 | + memcpy(saveBuf, PARSE_TAIL(pParse), PARSE_TAIL_SZ); | |
| 98606 | + memset(PARSE_TAIL(pParse), 0, PARSE_TAIL_SZ); | |
| 98556 | 98607 | sqlite3RunParser(pParse, zSql, &zErrMsg); |
| 98557 | 98608 | sqlite3DbFree(db, zErrMsg); |
| 98558 | 98609 | sqlite3DbFree(db, zSql); |
| 98559 | - memcpy(&pParse->nVar, saveBuf, SAVE_SZ); | |
| 98610 | + memcpy(PARSE_TAIL(pParse), saveBuf, PARSE_TAIL_SZ); | |
| 98560 | 98611 | pParse->nested--; |
| 98561 | 98612 | } |
| 98562 | 98613 | |
| 98563 | 98614 | #if SQLITE_USER_AUTHENTICATION |
| 98564 | 98615 | /* |
| @@ -99735,10 +99786,13 @@ | ||
| 99735 | 99786 | ** This plan is not completely bullet-proof. It is possible for |
| 99736 | 99787 | ** the schema to change multiple times and for the cookie to be |
| 99737 | 99788 | ** set back to prior value. But schema changes are infrequent |
| 99738 | 99789 | ** and the probability of hitting the same cookie value is only |
| 99739 | 99790 | ** 1 chance in 2^32. So we're safe enough. |
| 99791 | +** | |
| 99792 | +** IMPLEMENTATION-OF: R-34230-56049 SQLite automatically increments | |
| 99793 | +** the schema-version whenever the schema changes. | |
| 99740 | 99794 | */ |
| 99741 | 99795 | SQLITE_PRIVATE void sqlite3ChangeCookie(Parse *pParse, int iDb){ |
| 99742 | 99796 | sqlite3 *db = pParse->db; |
| 99743 | 99797 | Vdbe *v = pParse->pVdbe; |
| 99744 | 99798 | assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); |
| @@ -102318,19 +102372,17 @@ | ||
| 102318 | 102372 | ** will occur at the end of the top-level VDBE and will be generated |
| 102319 | 102373 | ** later, by sqlite3FinishCoding(). |
| 102320 | 102374 | */ |
| 102321 | 102375 | SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse *pParse, int iDb){ |
| 102322 | 102376 | Parse *pToplevel = sqlite3ParseToplevel(pParse); |
| 102323 | - sqlite3 *db = pToplevel->db; | |
| 102324 | 102377 | |
| 102325 | - assert( iDb>=0 && iDb<db->nDb ); | |
| 102326 | - assert( db->aDb[iDb].pBt!=0 || iDb==1 ); | |
| 102378 | + assert( iDb>=0 && iDb<pParse->db->nDb ); | |
| 102379 | + assert( pParse->db->aDb[iDb].pBt!=0 || iDb==1 ); | |
| 102327 | 102380 | assert( iDb<SQLITE_MAX_ATTACHED+2 ); |
| 102328 | - assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); | |
| 102381 | + assert( sqlite3SchemaMutexHeld(pParse->db, iDb, 0) ); | |
| 102329 | 102382 | if( DbMaskTest(pToplevel->cookieMask, iDb)==0 ){ |
| 102330 | 102383 | DbMaskSet(pToplevel->cookieMask, iDb); |
| 102331 | - pToplevel->cookieValue[iDb] = db->aDb[iDb].pSchema->schema_cookie; | |
| 102332 | 102384 | if( !OMIT_TEMPDB && iDb==1 ){ |
| 102333 | 102385 | sqlite3OpenTempDatabase(pToplevel); |
| 102334 | 102386 | } |
| 102335 | 102387 | } |
| 102336 | 102388 | } |
| @@ -107192,14 +107244,14 @@ | ||
| 107192 | 107244 | }else if( action==OE_SetDflt ){ |
| 107193 | 107245 | Expr *pDflt = pFKey->pFrom->aCol[iFromCol].pDflt; |
| 107194 | 107246 | if( pDflt ){ |
| 107195 | 107247 | pNew = sqlite3ExprDup(db, pDflt, 0); |
| 107196 | 107248 | }else{ |
| 107197 | - pNew = sqlite3PExpr(pParse, TK_NULL, 0, 0, 0); | |
| 107249 | + pNew = sqlite3ExprAlloc(db, TK_NULL, 0, 0); | |
| 107198 | 107250 | } |
| 107199 | 107251 | }else{ |
| 107200 | - pNew = sqlite3PExpr(pParse, TK_NULL, 0, 0, 0); | |
| 107252 | + pNew = sqlite3ExprAlloc(db, TK_NULL, 0, 0); | |
| 107201 | 107253 | } |
| 107202 | 107254 | pList = sqlite3ExprListAppend(pParse, pList, pNew); |
| 107203 | 107255 | sqlite3ExprListSetName(pParse, pList, &tFromCol, 0); |
| 107204 | 107256 | } |
| 107205 | 107257 | } |
| @@ -109538,10 +109590,11 @@ | ||
| 109538 | 109590 | } |
| 109539 | 109591 | if( emptySrcTest ) sqlite3VdbeJumpHere(v, emptySrcTest); |
| 109540 | 109592 | sqlite3ReleaseTempReg(pParse, regRowid); |
| 109541 | 109593 | sqlite3ReleaseTempReg(pParse, regData); |
| 109542 | 109594 | if( emptyDestTest ){ |
| 109595 | + sqlite3AutoincrementEnd(pParse); | |
| 109543 | 109596 | sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_OK, 0); |
| 109544 | 109597 | sqlite3VdbeJumpHere(v, emptyDestTest); |
| 109545 | 109598 | sqlite3VdbeAddOp2(v, OP_Close, iDest, 0); |
| 109546 | 109599 | return 0; |
| 109547 | 109600 | }else{ |
| @@ -114034,22 +114087,18 @@ | ||
| 114034 | 114087 | int saveSqlFlag, /* True to copy SQL text into the sqlite3_stmt */ |
| 114035 | 114088 | Vdbe *pReprepare, /* VM being reprepared */ |
| 114036 | 114089 | sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ |
| 114037 | 114090 | const char **pzTail /* OUT: End of parsed string */ |
| 114038 | 114091 | ){ |
| 114039 | - Parse *pParse; /* Parsing context */ | |
| 114040 | 114092 | char *zErrMsg = 0; /* Error message */ |
| 114041 | 114093 | int rc = SQLITE_OK; /* Result code */ |
| 114042 | 114094 | int i; /* Loop counter */ |
| 114043 | - | |
| 114044 | - /* Allocate the parsing context */ | |
| 114045 | - pParse = sqlite3StackAllocZero(db, sizeof(*pParse)); | |
| 114046 | - if( pParse==0 ){ | |
| 114047 | - rc = SQLITE_NOMEM_BKPT; | |
| 114048 | - goto end_prepare; | |
| 114049 | - } | |
| 114050 | - pParse->pReprepare = pReprepare; | |
| 114095 | + Parse sParse; /* Parsing context */ | |
| 114096 | + | |
| 114097 | + memset(&sParse, 0, PARSE_HDR_SZ); | |
| 114098 | + memset(PARSE_TAIL(&sParse), 0, PARSE_TAIL_SZ); | |
| 114099 | + sParse.pReprepare = pReprepare; | |
| 114051 | 114100 | assert( ppStmt && *ppStmt==0 ); |
| 114052 | 114101 | /* assert( !db->mallocFailed ); // not true with SQLITE_USE_ALLOCA */ |
| 114053 | 114102 | assert( sqlite3_mutex_held(db->mutex) ); |
| 114054 | 114103 | |
| 114055 | 114104 | /* Check to verify that it is possible to get a read lock on all |
| @@ -114089,12 +114138,11 @@ | ||
| 114089 | 114138 | } |
| 114090 | 114139 | } |
| 114091 | 114140 | |
| 114092 | 114141 | sqlite3VtabUnlockList(db); |
| 114093 | 114142 | |
| 114094 | - pParse->db = db; | |
| 114095 | - pParse->nQueryLoop = 0; /* Logarithmic, so 0 really means 1 */ | |
| 114143 | + sParse.db = db; | |
| 114096 | 114144 | if( nBytes>=0 && (nBytes==0 || zSql[nBytes-1]!=0) ){ |
| 114097 | 114145 | char *zSqlCopy; |
| 114098 | 114146 | int mxLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH]; |
| 114099 | 114147 | testcase( nBytes==mxLen ); |
| 114100 | 114148 | testcase( nBytes==mxLen+1 ); |
| @@ -114103,65 +114151,65 @@ | ||
| 114103 | 114151 | rc = sqlite3ApiExit(db, SQLITE_TOOBIG); |
| 114104 | 114152 | goto end_prepare; |
| 114105 | 114153 | } |
| 114106 | 114154 | zSqlCopy = sqlite3DbStrNDup(db, zSql, nBytes); |
| 114107 | 114155 | if( zSqlCopy ){ |
| 114108 | - sqlite3RunParser(pParse, zSqlCopy, &zErrMsg); | |
| 114109 | - pParse->zTail = &zSql[pParse->zTail-zSqlCopy]; | |
| 114156 | + sqlite3RunParser(&sParse, zSqlCopy, &zErrMsg); | |
| 114157 | + sParse.zTail = &zSql[sParse.zTail-zSqlCopy]; | |
| 114110 | 114158 | sqlite3DbFree(db, zSqlCopy); |
| 114111 | 114159 | }else{ |
| 114112 | - pParse->zTail = &zSql[nBytes]; | |
| 114160 | + sParse.zTail = &zSql[nBytes]; | |
| 114113 | 114161 | } |
| 114114 | 114162 | }else{ |
| 114115 | - sqlite3RunParser(pParse, zSql, &zErrMsg); | |
| 114163 | + sqlite3RunParser(&sParse, zSql, &zErrMsg); | |
| 114116 | 114164 | } |
| 114117 | - assert( 0==pParse->nQueryLoop ); | |
| 114165 | + assert( 0==sParse.nQueryLoop ); | |
| 114118 | 114166 | |
| 114119 | - if( pParse->rc==SQLITE_DONE ) pParse->rc = SQLITE_OK; | |
| 114120 | - if( pParse->checkSchema ){ | |
| 114121 | - schemaIsValid(pParse); | |
| 114167 | + if( sParse.rc==SQLITE_DONE ) sParse.rc = SQLITE_OK; | |
| 114168 | + if( sParse.checkSchema ){ | |
| 114169 | + schemaIsValid(&sParse); | |
| 114122 | 114170 | } |
| 114123 | 114171 | if( db->mallocFailed ){ |
| 114124 | - pParse->rc = SQLITE_NOMEM_BKPT; | |
| 114172 | + sParse.rc = SQLITE_NOMEM_BKPT; | |
| 114125 | 114173 | } |
| 114126 | 114174 | if( pzTail ){ |
| 114127 | - *pzTail = pParse->zTail; | |
| 114175 | + *pzTail = sParse.zTail; | |
| 114128 | 114176 | } |
| 114129 | - rc = pParse->rc; | |
| 114177 | + rc = sParse.rc; | |
| 114130 | 114178 | |
| 114131 | 114179 | #ifndef SQLITE_OMIT_EXPLAIN |
| 114132 | - if( rc==SQLITE_OK && pParse->pVdbe && pParse->explain ){ | |
| 114180 | + if( rc==SQLITE_OK && sParse.pVdbe && sParse.explain ){ | |
| 114133 | 114181 | static const char * const azColName[] = { |
| 114134 | 114182 | "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment", |
| 114135 | 114183 | "selectid", "order", "from", "detail" |
| 114136 | 114184 | }; |
| 114137 | 114185 | int iFirst, mx; |
| 114138 | - if( pParse->explain==2 ){ | |
| 114139 | - sqlite3VdbeSetNumCols(pParse->pVdbe, 4); | |
| 114186 | + if( sParse.explain==2 ){ | |
| 114187 | + sqlite3VdbeSetNumCols(sParse.pVdbe, 4); | |
| 114140 | 114188 | iFirst = 8; |
| 114141 | 114189 | mx = 12; |
| 114142 | 114190 | }else{ |
| 114143 | - sqlite3VdbeSetNumCols(pParse->pVdbe, 8); | |
| 114191 | + sqlite3VdbeSetNumCols(sParse.pVdbe, 8); | |
| 114144 | 114192 | iFirst = 0; |
| 114145 | 114193 | mx = 8; |
| 114146 | 114194 | } |
| 114147 | 114195 | for(i=iFirst; i<mx; i++){ |
| 114148 | - sqlite3VdbeSetColName(pParse->pVdbe, i-iFirst, COLNAME_NAME, | |
| 114196 | + sqlite3VdbeSetColName(sParse.pVdbe, i-iFirst, COLNAME_NAME, | |
| 114149 | 114197 | azColName[i], SQLITE_STATIC); |
| 114150 | 114198 | } |
| 114151 | 114199 | } |
| 114152 | 114200 | #endif |
| 114153 | 114201 | |
| 114154 | 114202 | if( db->init.busy==0 ){ |
| 114155 | - Vdbe *pVdbe = pParse->pVdbe; | |
| 114156 | - sqlite3VdbeSetSql(pVdbe, zSql, (int)(pParse->zTail-zSql), saveSqlFlag); | |
| 114203 | + Vdbe *pVdbe = sParse.pVdbe; | |
| 114204 | + sqlite3VdbeSetSql(pVdbe, zSql, (int)(sParse.zTail-zSql), saveSqlFlag); | |
| 114157 | 114205 | } |
| 114158 | - if( pParse->pVdbe && (rc!=SQLITE_OK || db->mallocFailed) ){ | |
| 114159 | - sqlite3VdbeFinalize(pParse->pVdbe); | |
| 114206 | + if( sParse.pVdbe && (rc!=SQLITE_OK || db->mallocFailed) ){ | |
| 114207 | + sqlite3VdbeFinalize(sParse.pVdbe); | |
| 114160 | 114208 | assert(!(*ppStmt)); |
| 114161 | 114209 | }else{ |
| 114162 | - *ppStmt = (sqlite3_stmt*)pParse->pVdbe; | |
| 114210 | + *ppStmt = (sqlite3_stmt*)sParse.pVdbe; | |
| 114163 | 114211 | } |
| 114164 | 114212 | |
| 114165 | 114213 | if( zErrMsg ){ |
| 114166 | 114214 | sqlite3ErrorWithMsg(db, rc, "%s", zErrMsg); |
| 114167 | 114215 | sqlite3DbFree(db, zErrMsg); |
| @@ -114168,20 +114216,19 @@ | ||
| 114168 | 114216 | }else{ |
| 114169 | 114217 | sqlite3Error(db, rc); |
| 114170 | 114218 | } |
| 114171 | 114219 | |
| 114172 | 114220 | /* Delete any TriggerPrg structures allocated while parsing this statement. */ |
| 114173 | - while( pParse->pTriggerPrg ){ | |
| 114174 | - TriggerPrg *pT = pParse->pTriggerPrg; | |
| 114175 | - pParse->pTriggerPrg = pT->pNext; | |
| 114221 | + while( sParse.pTriggerPrg ){ | |
| 114222 | + TriggerPrg *pT = sParse.pTriggerPrg; | |
| 114223 | + sParse.pTriggerPrg = pT->pNext; | |
| 114176 | 114224 | sqlite3DbFree(db, pT); |
| 114177 | 114225 | } |
| 114178 | 114226 | |
| 114179 | 114227 | end_prepare: |
| 114180 | 114228 | |
| 114181 | - sqlite3ParserReset(pParse); | |
| 114182 | - sqlite3StackFree(db, pParse); | |
| 114229 | + sqlite3ParserReset(&sParse); | |
| 114183 | 114230 | rc = sqlite3ApiExit(db, rc); |
| 114184 | 114231 | assert( (rc&db->errMask)==rc ); |
| 114185 | 114232 | return rc; |
| 114186 | 114233 | } |
| 114187 | 114234 | static int sqlite3LockAndPrepare( |
| @@ -115382,11 +115429,11 @@ | ||
| 115382 | 115429 | ** Allocate a KeyInfo object sufficient for an index of N key columns and |
| 115383 | 115430 | ** X extra columns. |
| 115384 | 115431 | */ |
| 115385 | 115432 | SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N, int X){ |
| 115386 | 115433 | int nExtra = (N+X)*(sizeof(CollSeq*)+1); |
| 115387 | - KeyInfo *p = sqlite3DbMallocRaw(db, sizeof(KeyInfo) + nExtra); | |
| 115434 | + KeyInfo *p = sqlite3DbMallocRawNN(db, sizeof(KeyInfo) + nExtra); | |
| 115388 | 115435 | if( p ){ |
| 115389 | 115436 | p->aSortOrder = (u8*)&p->aColl[N+X]; |
| 115390 | 115437 | p->nField = (u16)N; |
| 115391 | 115438 | p->nXField = (u16)X; |
| 115392 | 115439 | p->enc = ENC(db); |
| @@ -118072,16 +118119,17 @@ | ||
| 118072 | 118119 | pWhere = sqlite3ExprDup(db, pSub->pWhere, 0); |
| 118073 | 118120 | if( subqueryIsAgg ){ |
| 118074 | 118121 | assert( pParent->pHaving==0 ); |
| 118075 | 118122 | pParent->pHaving = pParent->pWhere; |
| 118076 | 118123 | pParent->pWhere = pWhere; |
| 118077 | - pParent->pHaving = sqlite3ExprAnd(db, pParent->pHaving, | |
| 118078 | - sqlite3ExprDup(db, pSub->pHaving, 0)); | |
| 118124 | + pParent->pHaving = sqlite3ExprAnd(db, | |
| 118125 | + sqlite3ExprDup(db, pSub->pHaving, 0), pParent->pHaving | |
| 118126 | + ); | |
| 118079 | 118127 | assert( pParent->pGroupBy==0 ); |
| 118080 | 118128 | pParent->pGroupBy = sqlite3ExprListDup(db, pSub->pGroupBy, 0); |
| 118081 | 118129 | }else{ |
| 118082 | - pParent->pWhere = sqlite3ExprAnd(db, pParent->pWhere, pWhere); | |
| 118130 | + pParent->pWhere = sqlite3ExprAnd(db, pWhere, pParent->pWhere); | |
| 118083 | 118131 | } |
| 118084 | 118132 | substSelect(db, pParent, iParent, pSub->pEList, 0); |
| 118085 | 118133 | |
| 118086 | 118134 | /* The flattened query is distinct if either the inner or the |
| 118087 | 118135 | ** outer query is distinct. |
| @@ -122381,11 +122429,11 @@ | ||
| 122381 | 122429 | } |
| 122382 | 122430 | #endif |
| 122383 | 122431 | |
| 122384 | 122432 | sqlite3BtreeSetCacheSize(pTemp, db->aDb[iDb].pSchema->cache_size); |
| 122385 | 122433 | sqlite3BtreeSetSpillSize(pTemp, sqlite3BtreeSetSpillSize(pMain,0)); |
| 122386 | - sqlite3BtreeSetPagerFlags(pTemp, PAGER_SYNCHRONOUS_OFF); | |
| 122434 | + sqlite3BtreeSetPagerFlags(pTemp, PAGER_SYNCHRONOUS_OFF|PAGER_CACHESPILL); | |
| 122387 | 122435 | |
| 122388 | 122436 | /* Begin a transaction and take an exclusive lock on the main database |
| 122389 | 122437 | ** file. This is done before the sqlite3BtreeGetPageSize(pMain) call below, |
| 122390 | 122438 | ** to ensure that we do not try to change the page-size on a WAL database. |
| 122391 | 122439 | */ |
| @@ -124041,24 +124089,24 @@ | ||
| 124041 | 124089 | ** in prereqRight and prereqAll. The default is 64 bits, hence SQLite |
| 124042 | 124090 | ** is only able to process joins with 64 or fewer tables. |
| 124043 | 124091 | */ |
| 124044 | 124092 | struct WhereTerm { |
| 124045 | 124093 | Expr *pExpr; /* Pointer to the subexpression that is this term */ |
| 124094 | + WhereClause *pWC; /* The clause this term is part of */ | |
| 124095 | + LogEst truthProb; /* Probability of truth for this expression */ | |
| 124096 | + u16 wtFlags; /* TERM_xxx bit flags. See below */ | |
| 124097 | + u16 eOperator; /* A WO_xx value describing <op> */ | |
| 124098 | + u8 nChild; /* Number of children that must disable us */ | |
| 124099 | + u8 eMatchOp; /* Op for vtab MATCH/LIKE/GLOB/REGEXP terms */ | |
| 124046 | 124100 | int iParent; /* Disable pWC->a[iParent] when this term disabled */ |
| 124047 | 124101 | int leftCursor; /* Cursor number of X in "X <op> <expr>" */ |
| 124048 | 124102 | int iField; /* Field in (?,?,?) IN (SELECT...) vector */ |
| 124049 | 124103 | union { |
| 124050 | 124104 | int leftColumn; /* Column number of X in "X <op> <expr>" */ |
| 124051 | 124105 | WhereOrInfo *pOrInfo; /* Extra information if (eOperator & WO_OR)!=0 */ |
| 124052 | 124106 | WhereAndInfo *pAndInfo; /* Extra information if (eOperator& WO_AND)!=0 */ |
| 124053 | 124107 | } u; |
| 124054 | - LogEst truthProb; /* Probability of truth for this expression */ | |
| 124055 | - u16 eOperator; /* A WO_xx value describing <op> */ | |
| 124056 | - u16 wtFlags; /* TERM_xxx bit flags. See below */ | |
| 124057 | - u8 nChild; /* Number of children that must disable us */ | |
| 124058 | - u8 eMatchOp; /* Op for vtab MATCH/LIKE/GLOB/REGEXP terms */ | |
| 124059 | - WhereClause *pWC; /* The clause this term is part of */ | |
| 124060 | 124108 | Bitmask prereqRight; /* Bitmask of tables used by pExpr->pRight */ |
| 124061 | 124109 | Bitmask prereqAll; /* Bitmask of tables referenced by pExpr */ |
| 124062 | 124110 | }; |
| 124063 | 124111 | |
| 124064 | 124112 | /* |
| @@ -124207,29 +124255,29 @@ | ||
| 124207 | 124255 | struct WhereInfo { |
| 124208 | 124256 | Parse *pParse; /* Parsing and code generating context */ |
| 124209 | 124257 | SrcList *pTabList; /* List of tables in the join */ |
| 124210 | 124258 | ExprList *pOrderBy; /* The ORDER BY clause or NULL */ |
| 124211 | 124259 | ExprList *pDistinctSet; /* DISTINCT over all these values */ |
| 124212 | - WhereLoop *pLoops; /* List of all WhereLoop objects */ | |
| 124213 | - Bitmask revMask; /* Mask of ORDER BY terms that need reversing */ | |
| 124214 | - LogEst nRowOut; /* Estimated number of output rows */ | |
| 124215 | 124260 | LogEst iLimit; /* LIMIT if wctrlFlags has WHERE_USE_LIMIT */ |
| 124261 | + int aiCurOnePass[2]; /* OP_OpenWrite cursors for the ONEPASS opt */ | |
| 124262 | + int iContinue; /* Jump here to continue with next record */ | |
| 124263 | + int iBreak; /* Jump here to break out of the loop */ | |
| 124264 | + int savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */ | |
| 124216 | 124265 | u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */ |
| 124266 | + u8 nLevel; /* Number of nested loop */ | |
| 124217 | 124267 | i8 nOBSat; /* Number of ORDER BY terms satisfied by indices */ |
| 124218 | 124268 | u8 sorted; /* True if really sorted (not just grouped) */ |
| 124219 | 124269 | u8 eOnePass; /* ONEPASS_OFF, or _SINGLE, or _MULTI */ |
| 124220 | 124270 | u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */ |
| 124221 | 124271 | u8 eDistinct; /* One of the WHERE_DISTINCT_* values */ |
| 124222 | - u8 nLevel; /* Number of nested loop */ | |
| 124223 | 124272 | u8 bOrderedInnerLoop; /* True if only the inner-most loop is ordered */ |
| 124224 | 124273 | int iTop; /* The very beginning of the WHERE loop */ |
| 124225 | - int iContinue; /* Jump here to continue with next record */ | |
| 124226 | - int iBreak; /* Jump here to break out of the loop */ | |
| 124227 | - int savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */ | |
| 124228 | - int aiCurOnePass[2]; /* OP_OpenWrite cursors for the ONEPASS opt */ | |
| 124229 | - WhereMaskSet sMaskSet; /* Map cursor numbers to bitmasks */ | |
| 124274 | + WhereLoop *pLoops; /* List of all WhereLoop objects */ | |
| 124275 | + Bitmask revMask; /* Mask of ORDER BY terms that need reversing */ | |
| 124276 | + LogEst nRowOut; /* Estimated number of output rows */ | |
| 124230 | 124277 | WhereClause sWC; /* Decomposition of the WHERE clause */ |
| 124278 | + WhereMaskSet sMaskSet; /* Map cursor numbers to bitmasks */ | |
| 124231 | 124279 | WhereLevel a[1]; /* Information about each nest loop in WHERE */ |
| 124232 | 124280 | }; |
| 124233 | 124281 | |
| 124234 | 124282 | /* |
| 124235 | 124283 | ** Private interfaces - callable only by other where.c routines. |
| @@ -124689,11 +124737,10 @@ | ||
| 124689 | 124737 | ** |
| 124690 | 124738 | ** * the comparison will be performed with no affinity, or |
| 124691 | 124739 | ** * the affinity change in zAff is guaranteed not to change the value. |
| 124692 | 124740 | */ |
| 124693 | 124741 | static void updateRangeAffinityStr( |
| 124694 | - Parse *pParse, /* Parse context */ | |
| 124695 | 124742 | Expr *pRight, /* RHS of comparison */ |
| 124696 | 124743 | int n, /* Number of vector elements in comparison */ |
| 124697 | 124744 | char *zAff /* Affinity string to modify */ |
| 124698 | 124745 | ){ |
| 124699 | 124746 | int i; |
| @@ -125775,15 +125822,15 @@ | ||
| 125775 | 125822 | assert( (bRev & ~1)==0 ); |
| 125776 | 125823 | pLevel->iLikeRepCntr <<=1; |
| 125777 | 125824 | pLevel->iLikeRepCntr |= bRev ^ (pIdx->aSortOrder[nEq]==SQLITE_SO_DESC); |
| 125778 | 125825 | } |
| 125779 | 125826 | #endif |
| 125780 | - if( pRangeStart==0 | |
| 125781 | - && (j = pIdx->aiColumn[nEq])>=0 | |
| 125782 | - && pIdx->pTable->aCol[j].notNull==0 | |
| 125783 | - ){ | |
| 125784 | - bSeekPastNull = 1; | |
| 125827 | + if( pRangeStart==0 ){ | |
| 125828 | + j = pIdx->aiColumn[nEq]; | |
| 125829 | + if( (j>=0 && pIdx->pTable->aCol[j].notNull==0) || j==XN_EXPR ){ | |
| 125830 | + bSeekPastNull = 1; | |
| 125831 | + } | |
| 125785 | 125832 | } |
| 125786 | 125833 | } |
| 125787 | 125834 | assert( pRangeEnd==0 || (pRangeEnd->wtFlags & TERM_VNULL)==0 ); |
| 125788 | 125835 | |
| 125789 | 125836 | /* If we are doing a reverse order scan on an ascending index, or |
| @@ -125829,11 +125876,11 @@ | ||
| 125829 | 125876 | ){ |
| 125830 | 125877 | sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt); |
| 125831 | 125878 | VdbeCoverage(v); |
| 125832 | 125879 | } |
| 125833 | 125880 | if( zStartAff ){ |
| 125834 | - updateRangeAffinityStr(pParse, pRight, nBtm, &zStartAff[nEq]); | |
| 125881 | + updateRangeAffinityStr(pRight, nBtm, &zStartAff[nEq]); | |
| 125835 | 125882 | } |
| 125836 | 125883 | nConstraint += nBtm; |
| 125837 | 125884 | testcase( pRangeStart->wtFlags & TERM_VIRTUAL ); |
| 125838 | 125885 | if( sqlite3ExprIsVector(pRight)==0 ){ |
| 125839 | 125886 | disableTerm(pLevel, pRangeStart); |
| @@ -125879,11 +125926,11 @@ | ||
| 125879 | 125926 | ){ |
| 125880 | 125927 | sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt); |
| 125881 | 125928 | VdbeCoverage(v); |
| 125882 | 125929 | } |
| 125883 | 125930 | if( zEndAff ){ |
| 125884 | - updateRangeAffinityStr(pParse, pRight, nTop, zEndAff); | |
| 125931 | + updateRangeAffinityStr(pRight, nTop, zEndAff); | |
| 125885 | 125932 | codeApplyAffinity(pParse, regBase+nEq, nTop, zEndAff); |
| 125886 | 125933 | }else{ |
| 125887 | 125934 | assert( pParse->db->mallocFailed ); |
| 125888 | 125935 | } |
| 125889 | 125936 | nConstraint += nTop; |
| @@ -126315,11 +126362,11 @@ | ||
| 126315 | 126362 | ** and we are coding the t1 loop and the t2 loop has not yet coded, |
| 126316 | 126363 | ** then we cannot use the "t1.a=t2.b" constraint, but we can code |
| 126317 | 126364 | ** the implied "t1.a=123" constraint. |
| 126318 | 126365 | */ |
| 126319 | 126366 | for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){ |
| 126320 | - Expr *pE, *pEAlt; | |
| 126367 | + Expr *pE, sEAlt; | |
| 126321 | 126368 | WhereTerm *pAlt; |
| 126322 | 126369 | if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue; |
| 126323 | 126370 | if( (pTerm->eOperator & (WO_EQ|WO_IS))==0 ) continue; |
| 126324 | 126371 | if( (pTerm->eOperator & WO_EQUIV)==0 ) continue; |
| 126325 | 126372 | if( pTerm->leftCursor!=iCur ) continue; |
| @@ -126333,17 +126380,13 @@ | ||
| 126333 | 126380 | if( pAlt->wtFlags & (TERM_CODED) ) continue; |
| 126334 | 126381 | testcase( pAlt->eOperator & WO_EQ ); |
| 126335 | 126382 | testcase( pAlt->eOperator & WO_IS ); |
| 126336 | 126383 | testcase( pAlt->eOperator & WO_IN ); |
| 126337 | 126384 | VdbeModuleComment((v, "begin transitive constraint")); |
| 126338 | - pEAlt = sqlite3StackAllocRaw(db, sizeof(*pEAlt)); | |
| 126339 | - if( pEAlt ){ | |
| 126340 | - *pEAlt = *pAlt->pExpr; | |
| 126341 | - pEAlt->pLeft = pE->pLeft; | |
| 126342 | - sqlite3ExprIfFalse(pParse, pEAlt, addrCont, SQLITE_JUMPIFNULL); | |
| 126343 | - sqlite3StackFree(db, pEAlt); | |
| 126344 | - } | |
| 126385 | + sEAlt = *pAlt->pExpr; | |
| 126386 | + sEAlt.pLeft = pE->pLeft; | |
| 126387 | + sqlite3ExprIfFalse(pParse, &sEAlt, addrCont, SQLITE_JUMPIFNULL); | |
| 126345 | 126388 | } |
| 126346 | 126389 | |
| 126347 | 126390 | /* For a LEFT OUTER JOIN, generate code that will record the fact that |
| 126348 | 126391 | ** at least one row of the right table has matched the left table. |
| 126349 | 126392 | */ |
| @@ -126448,11 +126491,10 @@ | ||
| 126448 | 126491 | memcpy(pWC->a, pOld, sizeof(pWC->a[0])*pWC->nTerm); |
| 126449 | 126492 | if( pOld!=pWC->aStatic ){ |
| 126450 | 126493 | sqlite3DbFree(db, pOld); |
| 126451 | 126494 | } |
| 126452 | 126495 | pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]); |
| 126453 | - memset(&pWC->a[pWC->nTerm], 0, sizeof(pWC->a[0])*(pWC->nSlot-pWC->nTerm)); | |
| 126454 | 126496 | } |
| 126455 | 126497 | pTerm = &pWC->a[idx = pWC->nTerm++]; |
| 126456 | 126498 | if( p && ExprHasProperty(p, EP_Unlikely) ){ |
| 126457 | 126499 | pTerm->truthProb = sqlite3LogEst(p->iTable) - 270; |
| 126458 | 126500 | }else{ |
| @@ -126460,10 +126502,12 @@ | ||
| 126460 | 126502 | } |
| 126461 | 126503 | pTerm->pExpr = sqlite3ExprSkipCollate(p); |
| 126462 | 126504 | pTerm->wtFlags = wtFlags; |
| 126463 | 126505 | pTerm->pWC = pWC; |
| 126464 | 126506 | pTerm->iParent = -1; |
| 126507 | + memset(&pTerm->eOperator, 0, | |
| 126508 | + sizeof(WhereTerm) - offsetof(WhereTerm,eOperator)); | |
| 126465 | 126509 | return idx; |
| 126466 | 126510 | } |
| 126467 | 126511 | |
| 126468 | 126512 | /* |
| 126469 | 126513 | ** Return TRUE if the given operator is one of the operators that is |
| @@ -127568,10 +127612,11 @@ | ||
| 127568 | 127612 | Expr *pNew; |
| 127569 | 127613 | Expr *pLeft = sqlite3ExprForVectorField(pParse, pExpr->pLeft, i); |
| 127570 | 127614 | Expr *pRight = sqlite3ExprForVectorField(pParse, pExpr->pRight, i); |
| 127571 | 127615 | |
| 127572 | 127616 | pNew = sqlite3PExpr(pParse, pExpr->op, pLeft, pRight, 0); |
| 127617 | + transferJoinMarkings(pNew, pExpr); | |
| 127573 | 127618 | idxNew = whereClauseInsert(pWC, pNew, TERM_DYNAMIC); |
| 127574 | 127619 | exprAnalyze(pSrc, pWC, idxNew); |
| 127575 | 127620 | } |
| 127576 | 127621 | pTerm = &pWC->a[idxTerm]; |
| 127577 | 127622 | pTerm->wtFlags = TERM_CODED|TERM_VIRTUAL; /* Disable the original */ |
| @@ -127618,11 +127663,11 @@ | ||
| 127618 | 127663 | int idxNew; |
| 127619 | 127664 | WhereTerm *pNewTerm; |
| 127620 | 127665 | |
| 127621 | 127666 | pNewExpr = sqlite3PExpr(pParse, TK_GT, |
| 127622 | 127667 | sqlite3ExprDup(db, pLeft, 0), |
| 127623 | - sqlite3PExpr(pParse, TK_NULL, 0, 0, 0), 0); | |
| 127668 | + sqlite3ExprAlloc(db, TK_NULL, 0, 0), 0); | |
| 127624 | 127669 | |
| 127625 | 127670 | idxNew = whereClauseInsert(pWC, pNewExpr, |
| 127626 | 127671 | TERM_VIRTUAL|TERM_DYNAMIC|TERM_VNULL); |
| 127627 | 127672 | if( idxNew ){ |
| 127628 | 127673 | pNewTerm = &pWC->a[idxNew]; |
| @@ -127796,11 +127841,11 @@ | ||
| 127796 | 127841 | if( k>=pTab->nCol ){ |
| 127797 | 127842 | sqlite3ErrorMsg(pParse, "too many arguments on %s() - max %d", |
| 127798 | 127843 | pTab->zName, j); |
| 127799 | 127844 | return; |
| 127800 | 127845 | } |
| 127801 | - pColRef = sqlite3PExpr(pParse, TK_COLUMN, 0, 0, 0); | |
| 127846 | + pColRef = sqlite3ExprAlloc(pParse->db, TK_COLUMN, 0, 0); | |
| 127802 | 127847 | if( pColRef==0 ) return; |
| 127803 | 127848 | pColRef->iTable = pItem->iCursor; |
| 127804 | 127849 | pColRef->iColumn = k++; |
| 127805 | 127850 | pColRef->pTab = pTab; |
| 127806 | 127851 | pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef, |
| @@ -128009,15 +128054,17 @@ | ||
| 128009 | 128054 | Expr *pX; /* An expression being tested */ |
| 128010 | 128055 | WhereClause *pWC; /* Shorthand for pScan->pWC */ |
| 128011 | 128056 | WhereTerm *pTerm; /* The term being tested */ |
| 128012 | 128057 | int k = pScan->k; /* Where to start scanning */ |
| 128013 | 128058 | |
| 128014 | - while( pScan->iEquiv<=pScan->nEquiv ){ | |
| 128015 | - iCur = pScan->aiCur[pScan->iEquiv-1]; | |
| 128059 | + assert( pScan->iEquiv<=pScan->nEquiv ); | |
| 128060 | + pWC = pScan->pWC; | |
| 128061 | + while(1){ | |
| 128016 | 128062 | iColumn = pScan->aiColumn[pScan->iEquiv-1]; |
| 128017 | - if( iColumn==XN_EXPR && pScan->pIdxExpr==0 ) return 0; | |
| 128018 | - while( (pWC = pScan->pWC)!=0 ){ | |
| 128063 | + iCur = pScan->aiCur[pScan->iEquiv-1]; | |
| 128064 | + assert( pWC!=0 ); | |
| 128065 | + do{ | |
| 128019 | 128066 | for(pTerm=pWC->a+k; k<pWC->nTerm; k++, pTerm++){ |
| 128020 | 128067 | if( pTerm->leftCursor==iCur |
| 128021 | 128068 | && pTerm->u.leftColumn==iColumn |
| 128022 | 128069 | && (iColumn!=XN_EXPR |
| 128023 | 128070 | || sqlite3ExprCompare(pTerm->pExpr->pLeft,pScan->pIdxExpr,iCur)==0) |
| @@ -128063,19 +128110,21 @@ | ||
| 128063 | 128110 | && pX->iColumn==pScan->aiColumn[0] |
| 128064 | 128111 | ){ |
| 128065 | 128112 | testcase( pTerm->eOperator & WO_IS ); |
| 128066 | 128113 | continue; |
| 128067 | 128114 | } |
| 128115 | + pScan->pWC = pWC; | |
| 128068 | 128116 | pScan->k = k+1; |
| 128069 | 128117 | return pTerm; |
| 128070 | 128118 | } |
| 128071 | 128119 | } |
| 128072 | 128120 | } |
| 128073 | - pScan->pWC = pScan->pWC->pOuter; | |
| 128121 | + pWC = pWC->pOuter; | |
| 128074 | 128122 | k = 0; |
| 128075 | - } | |
| 128076 | - pScan->pWC = pScan->pOrigWC; | |
| 128123 | + }while( pWC!=0 ); | |
| 128124 | + if( pScan->iEquiv>=pScan->nEquiv ) break; | |
| 128125 | + pWC = pScan->pOrigWC; | |
| 128077 | 128126 | k = 0; |
| 128078 | 128127 | pScan->iEquiv++; |
| 128079 | 128128 | } |
| 128080 | 128129 | return 0; |
| 128081 | 128130 | } |
| @@ -128105,28 +128154,28 @@ | ||
| 128105 | 128154 | int iCur, /* Cursor to scan for */ |
| 128106 | 128155 | int iColumn, /* Column to scan for */ |
| 128107 | 128156 | u32 opMask, /* Operator(s) to scan for */ |
| 128108 | 128157 | Index *pIdx /* Must be compatible with this index */ |
| 128109 | 128158 | ){ |
| 128110 | - int j = 0; | |
| 128111 | - | |
| 128112 | - /* memset(pScan, 0, sizeof(*pScan)); */ | |
| 128113 | 128159 | pScan->pOrigWC = pWC; |
| 128114 | 128160 | pScan->pWC = pWC; |
| 128115 | 128161 | pScan->pIdxExpr = 0; |
| 128162 | + pScan->idxaff = 0; | |
| 128163 | + pScan->zCollName = 0; | |
| 128116 | 128164 | if( pIdx ){ |
| 128117 | - j = iColumn; | |
| 128165 | + int j = iColumn; | |
| 128118 | 128166 | iColumn = pIdx->aiColumn[j]; |
| 128119 | - if( iColumn==XN_EXPR ) pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr; | |
| 128120 | - if( iColumn==pIdx->pTable->iPKey ) iColumn = XN_ROWID; | |
| 128121 | - } | |
| 128122 | - if( pIdx && iColumn>=0 ){ | |
| 128123 | - pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity; | |
| 128124 | - pScan->zCollName = pIdx->azColl[j]; | |
| 128125 | - }else{ | |
| 128126 | - pScan->idxaff = 0; | |
| 128127 | - pScan->zCollName = 0; | |
| 128167 | + if( iColumn==XN_EXPR ){ | |
| 128168 | + pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr; | |
| 128169 | + }else if( iColumn==pIdx->pTable->iPKey ){ | |
| 128170 | + iColumn = XN_ROWID; | |
| 128171 | + }else if( iColumn>=0 ){ | |
| 128172 | + pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity; | |
| 128173 | + pScan->zCollName = pIdx->azColl[j]; | |
| 128174 | + } | |
| 128175 | + }else if( iColumn==XN_EXPR ){ | |
| 128176 | + return 0; | |
| 128128 | 128177 | } |
| 128129 | 128178 | pScan->opMask = opMask; |
| 128130 | 128179 | pScan->k = 0; |
| 128131 | 128180 | pScan->aiCur[0] = iCur; |
| 128132 | 128181 | pScan->aiColumn[0] = iColumn; |
| @@ -130034,11 +130083,11 @@ | ||
| 130034 | 130083 | ** CREATE INDEX ... ON (a, b, c, d, e) |
| 130035 | 130084 | ** |
| 130036 | 130085 | ** then this function would be invoked with nEq=1. The value returned in |
| 130037 | 130086 | ** this case is 3. |
| 130038 | 130087 | */ |
| 130039 | -int whereRangeVectorLen( | |
| 130088 | +static int whereRangeVectorLen( | |
| 130040 | 130089 | Parse *pParse, /* Parsing context */ |
| 130041 | 130090 | int iCur, /* Cursor open on pIdx */ |
| 130042 | 130091 | Index *pIdx, /* The index to be used for a inequality constraint */ |
| 130043 | 130092 | int nEq, /* Number of prior equality constraints on same index */ |
| 130044 | 130093 | WhereTerm *pTerm /* The vector inequality constraint */ |
| @@ -131480,11 +131529,11 @@ | ||
| 131480 | 131529 | if( rev ) *pRevMask |= MASKBIT(iLoop); |
| 131481 | 131530 | revSet = 1; |
| 131482 | 131531 | } |
| 131483 | 131532 | } |
| 131484 | 131533 | if( isMatch ){ |
| 131485 | - if( iColumn<0 ){ | |
| 131534 | + if( iColumn==XN_ROWID ){ | |
| 131486 | 131535 | testcase( distinctColumns==0 ); |
| 131487 | 131536 | distinctColumns = 1; |
| 131488 | 131537 | } |
| 131489 | 131538 | obSat |= MASKBIT(i); |
| 131490 | 131539 | }else{ |
| @@ -131935,17 +131984,24 @@ | ||
| 131935 | 131984 | }else{ |
| 131936 | 131985 | pWInfo->nOBSat = pFrom->isOrdered; |
| 131937 | 131986 | pWInfo->revMask = pFrom->revLoop; |
| 131938 | 131987 | if( pWInfo->nOBSat<=0 ){ |
| 131939 | 131988 | pWInfo->nOBSat = 0; |
| 131940 | - if( nLoop>0 && (pFrom->aLoop[nLoop-1]->wsFlags & WHERE_ONEROW)==0 ){ | |
| 131941 | - Bitmask m = 0; | |
| 131942 | - int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pOrderBy, pFrom, | |
| 131989 | + if( nLoop>0 ){ | |
| 131990 | + u32 wsFlags = pFrom->aLoop[nLoop-1]->wsFlags; | |
| 131991 | + if( (wsFlags & WHERE_ONEROW)==0 | |
| 131992 | + && (wsFlags&(WHERE_IPK|WHERE_COLUMN_IN))!=(WHERE_IPK|WHERE_COLUMN_IN) | |
| 131993 | + ){ | |
| 131994 | + Bitmask m = 0; | |
| 131995 | + int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pOrderBy, pFrom, | |
| 131943 | 131996 | WHERE_ORDERBY_LIMIT, nLoop-1, pFrom->aLoop[nLoop-1], &m); |
| 131944 | - if( rc==pWInfo->pOrderBy->nExpr ){ | |
| 131945 | - pWInfo->bOrderedInnerLoop = 1; | |
| 131946 | - pWInfo->revMask = m; | |
| 131997 | + testcase( wsFlags & WHERE_IPK ); | |
| 131998 | + testcase( wsFlags & WHERE_COLUMN_IN ); | |
| 131999 | + if( rc==pWInfo->pOrderBy->nExpr ){ | |
| 132000 | + pWInfo->bOrderedInnerLoop = 1; | |
| 132001 | + pWInfo->revMask = m; | |
| 132002 | + } | |
| 131947 | 132003 | } |
| 131948 | 132004 | } |
| 131949 | 132005 | } |
| 131950 | 132006 | } |
| 131951 | 132007 | if( (pWInfo->wctrlFlags & WHERE_SORTBYGROUP) |
| @@ -132218,26 +132274,29 @@ | ||
| 132218 | 132274 | ** and the WhereMaskSet structure. Since WhereClause contains an 8-byte |
| 132219 | 132275 | ** field (type Bitmask) it must be aligned on an 8-byte boundary on |
| 132220 | 132276 | ** some architectures. Hence the ROUND8() below. |
| 132221 | 132277 | */ |
| 132222 | 132278 | nByteWInfo = ROUND8(sizeof(WhereInfo)+(nTabList-1)*sizeof(WhereLevel)); |
| 132223 | - pWInfo = sqlite3DbMallocZero(db, nByteWInfo + sizeof(WhereLoop)); | |
| 132279 | + pWInfo = sqlite3DbMallocRawNN(db, nByteWInfo + sizeof(WhereLoop)); | |
| 132224 | 132280 | if( db->mallocFailed ){ |
| 132225 | 132281 | sqlite3DbFree(db, pWInfo); |
| 132226 | 132282 | pWInfo = 0; |
| 132227 | 132283 | goto whereBeginError; |
| 132228 | 132284 | } |
| 132229 | - pWInfo->aiCurOnePass[0] = pWInfo->aiCurOnePass[1] = -1; | |
| 132230 | - pWInfo->nLevel = nTabList; | |
| 132231 | 132285 | pWInfo->pParse = pParse; |
| 132232 | 132286 | pWInfo->pTabList = pTabList; |
| 132233 | 132287 | pWInfo->pOrderBy = pOrderBy; |
| 132234 | 132288 | pWInfo->pDistinctSet = pDistinctSet; |
| 132289 | + pWInfo->aiCurOnePass[0] = pWInfo->aiCurOnePass[1] = -1; | |
| 132290 | + pWInfo->nLevel = nTabList; | |
| 132235 | 132291 | pWInfo->iBreak = pWInfo->iContinue = sqlite3VdbeMakeLabel(v); |
| 132236 | 132292 | pWInfo->wctrlFlags = wctrlFlags; |
| 132237 | 132293 | pWInfo->iLimit = iAuxArg; |
| 132238 | 132294 | pWInfo->savedNQueryLoop = pParse->nQueryLoop; |
| 132295 | + memset(&pWInfo->nOBSat, 0, | |
| 132296 | + offsetof(WhereInfo,sWC) - offsetof(WhereInfo,nOBSat)); | |
| 132297 | + memset(&pWInfo->a[0], 0, sizeof(WhereLoop)+nTabList*sizeof(WhereLevel)); | |
| 132239 | 132298 | assert( pWInfo->eOnePass==ONEPASS_OFF ); /* ONEPASS defaults to OFF */ |
| 132240 | 132299 | pMaskSet = &pWInfo->sMaskSet; |
| 132241 | 132300 | sWLB.pWInfo = pWInfo; |
| 132242 | 132301 | sWLB.pWC = &pWInfo->sWC; |
| 132243 | 132302 | sWLB.pNew = (WhereLoop*)(((char*)pWInfo)+nByteWInfo); |
| @@ -132661,17 +132720,19 @@ | ||
| 132661 | 132720 | pLevel->addrLikeRep); |
| 132662 | 132721 | VdbeCoverage(v); |
| 132663 | 132722 | } |
| 132664 | 132723 | #endif |
| 132665 | 132724 | if( pLevel->iLeftJoin ){ |
| 132725 | + int ws = pLoop->wsFlags; | |
| 132666 | 132726 | addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); VdbeCoverage(v); |
| 132667 | - assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 | |
| 132668 | - || (pLoop->wsFlags & WHERE_INDEXED)!=0 ); | |
| 132669 | - if( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 ){ | |
| 132727 | + assert( (ws & WHERE_IDX_ONLY)==0 || (ws & WHERE_INDEXED)!=0 ); | |
| 132728 | + if( (ws & WHERE_IDX_ONLY)==0 ){ | |
| 132670 | 132729 | sqlite3VdbeAddOp1(v, OP_NullRow, pTabList->a[i].iCursor); |
| 132671 | 132730 | } |
| 132672 | - if( pLoop->wsFlags & WHERE_INDEXED ){ | |
| 132731 | + if( (ws & WHERE_INDEXED) | |
| 132732 | + || ((ws & WHERE_MULTI_OR) && pLevel->u.pCovidx) | |
| 132733 | + ){ | |
| 132673 | 132734 | sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iIdxCur); |
| 132674 | 132735 | } |
| 132675 | 132736 | if( pLevel->op==OP_Return ){ |
| 132676 | 132737 | sqlite3VdbeAddOp2(v, OP_Gosub, pLevel->p1, pLevel->addrFirst); |
| 132677 | 132738 | }else{ |
| @@ -132844,19 +132905,10 @@ | ||
| 132844 | 132905 | struct LimitVal { |
| 132845 | 132906 | Expr *pLimit; /* The LIMIT expression. NULL if there is no limit */ |
| 132846 | 132907 | Expr *pOffset; /* The OFFSET expression. NULL if there is none */ |
| 132847 | 132908 | }; |
| 132848 | 132909 | |
| 132849 | -/* | |
| 132850 | -** An instance of this structure is used to store the LIKE, | |
| 132851 | -** GLOB, NOT LIKE, and NOT GLOB operators. | |
| 132852 | -*/ | |
| 132853 | -struct LikeOp { | |
| 132854 | - Token eOperator; /* "like" or "glob" or "regexp" */ | |
| 132855 | - int bNot; /* True if the NOT keyword is present */ | |
| 132856 | -}; | |
| 132857 | - | |
| 132858 | 132910 | /* |
| 132859 | 132911 | ** An instance of the following structure describes the event of a |
| 132860 | 132912 | ** TRIGGER. "a" is the event type, one of TK_UPDATE, TK_INSERT, |
| 132861 | 132913 | ** TK_DELETE, or TK_INSTEAD. If the event is of the form |
| 132862 | 132914 | ** |
| @@ -132864,15 +132916,10 @@ | ||
| 132864 | 132916 | ** |
| 132865 | 132917 | ** Then the "b" IdList records the list "a,b,c". |
| 132866 | 132918 | */ |
| 132867 | 132919 | struct TrigEvent { int a; IdList * b; }; |
| 132868 | 132920 | |
| 132869 | -/* | |
| 132870 | -** An instance of this structure holds the ATTACH key and the key type. | |
| 132871 | -*/ | |
| 132872 | -struct AttachKey { int type; Token key; }; | |
| 132873 | - | |
| 132874 | 132921 | /* |
| 132875 | 132922 | ** Disable lookaside memory allocation for objects that might be |
| 132876 | 132923 | ** shared across database connections. |
| 132877 | 132924 | */ |
| 132878 | 132925 | static void disableLookaside(Parse *pParse){ |
| @@ -132915,11 +132962,28 @@ | ||
| 132915 | 132962 | /* Construct a new Expr object from a single identifier. Use the |
| 132916 | 132963 | ** new Expr to populate pOut. Set the span of pOut to be the identifier |
| 132917 | 132964 | ** that created the expression. |
| 132918 | 132965 | */ |
| 132919 | 132966 | static void spanExpr(ExprSpan *pOut, Parse *pParse, int op, Token t){ |
| 132920 | - pOut->pExpr = sqlite3PExpr(pParse, op, 0, 0, &t); | |
| 132967 | + Expr *p = sqlite3DbMallocRawNN(pParse->db, sizeof(Expr)+t.n+1); | |
| 132968 | + if( p ){ | |
| 132969 | + memset(p, 0, sizeof(Expr)); | |
| 132970 | + p->op = (u8)op; | |
| 132971 | + p->flags = EP_Leaf; | |
| 132972 | + p->iAgg = -1; | |
| 132973 | + p->u.zToken = (char*)&p[1]; | |
| 132974 | + memcpy(p->u.zToken, t.z, t.n); | |
| 132975 | + p->u.zToken[t.n] = 0; | |
| 132976 | + if( sqlite3Isquote(p->u.zToken[0]) ){ | |
| 132977 | + if( p->u.zToken[0]=='"' ) p->flags |= EP_DblQuoted; | |
| 132978 | + sqlite3Dequote(p->u.zToken); | |
| 132979 | + } | |
| 132980 | +#if SQLITE_MAX_EXPR_DEPTH>0 | |
| 132981 | + p->nHeight = 1; | |
| 132982 | +#endif | |
| 132983 | + } | |
| 132984 | + pOut->pExpr = p; | |
| 132921 | 132985 | pOut->zStart = t.z; |
| 132922 | 132986 | pOut->zEnd = &t.z[t.n]; |
| 132923 | 132987 | } |
| 132924 | 132988 | |
| 132925 | 132989 | /* This routine constructs a binary expression node out of two ExprSpan |
| @@ -133078,11 +133142,10 @@ | ||
| 133078 | 133142 | Select* yy243; |
| 133079 | 133143 | IdList* yy254; |
| 133080 | 133144 | With* yy285; |
| 133081 | 133145 | struct TrigEvent yy332; |
| 133082 | 133146 | struct LimitVal yy354; |
| 133083 | - struct LikeOp yy392; | |
| 133084 | 133147 | struct {int value; int mask;} yy497; |
| 133085 | 133148 | } YYMINORTYPE; |
| 133086 | 133149 | #ifndef YYSTACKDEPTH |
| 133087 | 133150 | #define YYSTACKDEPTH 100 |
| 133088 | 133151 | #endif |
| @@ -133090,19 +133153,19 @@ | ||
| 133090 | 133153 | #define sqlite3ParserARG_PDECL ,Parse *pParse |
| 133091 | 133154 | #define sqlite3ParserARG_FETCH Parse *pParse = yypParser->pParse |
| 133092 | 133155 | #define sqlite3ParserARG_STORE yypParser->pParse = pParse |
| 133093 | 133156 | #define YYFALLBACK 1 |
| 133094 | 133157 | #define YYNSTATE 456 |
| 133095 | -#define YYNRULE 331 | |
| 133158 | +#define YYNRULE 332 | |
| 133096 | 133159 | #define YY_MAX_SHIFT 455 |
| 133097 | -#define YY_MIN_SHIFTREDUCE 667 | |
| 133098 | -#define YY_MAX_SHIFTREDUCE 997 | |
| 133099 | -#define YY_MIN_REDUCE 998 | |
| 133100 | -#define YY_MAX_REDUCE 1328 | |
| 133101 | -#define YY_ERROR_ACTION 1329 | |
| 133102 | -#define YY_ACCEPT_ACTION 1330 | |
| 133103 | -#define YY_NO_ACTION 1331 | |
| 133160 | +#define YY_MIN_SHIFTREDUCE 668 | |
| 133161 | +#define YY_MAX_SHIFTREDUCE 999 | |
| 133162 | +#define YY_MIN_REDUCE 1000 | |
| 133163 | +#define YY_MAX_REDUCE 1331 | |
| 133164 | +#define YY_ERROR_ACTION 1332 | |
| 133165 | +#define YY_ACCEPT_ACTION 1333 | |
| 133166 | +#define YY_NO_ACTION 1334 | |
| 133104 | 133167 | /************* End control #defines *******************************************/ |
| 133105 | 133168 | |
| 133106 | 133169 | /* Define the yytestcase() macro to be a no-op if is not already defined |
| 133107 | 133170 | ** otherwise. |
| 133108 | 133171 | ** |
| @@ -133170,170 +133233,169 @@ | ||
| 133170 | 133233 | ** yy_reduce_ofst[] For each state, the offset into yy_action for |
| 133171 | 133234 | ** shifting non-terminals after a reduce. |
| 133172 | 133235 | ** yy_default[] Default action for each state. |
| 133173 | 133236 | ** |
| 133174 | 133237 | *********** Begin parsing tables **********************************************/ |
| 133175 | -#define YY_ACTTAB_COUNT (1571) | |
| 133238 | +#define YY_ACTTAB_COUNT (1567) | |
| 133176 | 133239 | static const YYACTIONTYPE yy_action[] = { |
| 133177 | - /* 0 */ 325, 830, 351, 824, 5, 203, 203, 818, 99, 100, | |
| 133178 | - /* 10 */ 90, 840, 840, 852, 855, 844, 844, 97, 97, 98, | |
| 133240 | + /* 0 */ 325, 832, 351, 825, 5, 203, 203, 819, 99, 100, | |
| 133241 | + /* 10 */ 90, 842, 842, 854, 857, 846, 846, 97, 97, 98, | |
| 133179 | 133242 | /* 20 */ 98, 98, 98, 301, 96, 96, 96, 96, 95, 95, |
| 133180 | - /* 30 */ 94, 94, 94, 93, 351, 325, 975, 975, 823, 823, | |
| 133181 | - /* 40 */ 823, 945, 354, 99, 100, 90, 840, 840, 852, 855, | |
| 133182 | - /* 50 */ 844, 844, 97, 97, 98, 98, 98, 98, 338, 96, | |
| 133243 | + /* 30 */ 94, 94, 94, 93, 351, 325, 977, 977, 824, 824, | |
| 133244 | + /* 40 */ 826, 947, 354, 99, 100, 90, 842, 842, 854, 857, | |
| 133245 | + /* 50 */ 846, 846, 97, 97, 98, 98, 98, 98, 338, 96, | |
| 133183 | 133246 | /* 60 */ 96, 96, 96, 95, 95, 94, 94, 94, 93, 351, |
| 133184 | - /* 70 */ 95, 95, 94, 94, 94, 93, 351, 790, 975, 975, | |
| 133185 | - /* 80 */ 325, 94, 94, 94, 93, 351, 791, 75, 99, 100, | |
| 133186 | - /* 90 */ 90, 840, 840, 852, 855, 844, 844, 97, 97, 98, | |
| 133247 | + /* 70 */ 95, 95, 94, 94, 94, 93, 351, 791, 977, 977, | |
| 133248 | + /* 80 */ 325, 94, 94, 94, 93, 351, 792, 75, 99, 100, | |
| 133249 | + /* 90 */ 90, 842, 842, 854, 857, 846, 846, 97, 97, 98, | |
| 133187 | 133250 | /* 100 */ 98, 98, 98, 450, 96, 96, 96, 96, 95, 95, |
| 133188 | - /* 110 */ 94, 94, 94, 93, 351, 1330, 155, 155, 2, 325, | |
| 133251 | + /* 110 */ 94, 94, 94, 93, 351, 1333, 155, 155, 2, 325, | |
| 133189 | 133252 | /* 120 */ 275, 146, 132, 52, 52, 93, 351, 99, 100, 90, |
| 133190 | - /* 130 */ 840, 840, 852, 855, 844, 844, 97, 97, 98, 98, | |
| 133253 | + /* 130 */ 842, 842, 854, 857, 846, 846, 97, 97, 98, 98, | |
| 133191 | 133254 | /* 140 */ 98, 98, 101, 96, 96, 96, 96, 95, 95, 94, |
| 133192 | - /* 150 */ 94, 94, 93, 351, 956, 956, 325, 268, 428, 413, | |
| 133193 | - /* 160 */ 411, 61, 751, 751, 99, 100, 90, 840, 840, 852, | |
| 133194 | - /* 170 */ 855, 844, 844, 97, 97, 98, 98, 98, 98, 60, | |
| 133255 | + /* 150 */ 94, 94, 93, 351, 958, 958, 325, 268, 428, 413, | |
| 133256 | + /* 160 */ 411, 61, 752, 752, 99, 100, 90, 842, 842, 854, | |
| 133257 | + /* 170 */ 857, 846, 846, 97, 97, 98, 98, 98, 98, 60, | |
| 133195 | 133258 | /* 180 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, |
| 133196 | - /* 190 */ 351, 325, 270, 329, 273, 277, 957, 958, 250, 99, | |
| 133197 | - /* 200 */ 100, 90, 840, 840, 852, 855, 844, 844, 97, 97, | |
| 133259 | + /* 190 */ 351, 325, 270, 329, 273, 277, 959, 960, 250, 99, | |
| 133260 | + /* 200 */ 100, 90, 842, 842, 854, 857, 846, 846, 97, 97, | |
| 133198 | 133261 | /* 210 */ 98, 98, 98, 98, 301, 96, 96, 96, 96, 95, |
| 133199 | - /* 220 */ 95, 94, 94, 94, 93, 351, 325, 936, 1323, 697, | |
| 133200 | - /* 230 */ 705, 1323, 242, 412, 99, 100, 90, 840, 840, 852, | |
| 133201 | - /* 240 */ 855, 844, 844, 97, 97, 98, 98, 98, 98, 347, | |
| 133262 | + /* 220 */ 95, 94, 94, 94, 93, 351, 325, 938, 1326, 698, | |
| 133263 | + /* 230 */ 706, 1326, 242, 412, 99, 100, 90, 842, 842, 854, | |
| 133264 | + /* 240 */ 857, 846, 846, 97, 97, 98, 98, 98, 98, 347, | |
| 133202 | 133265 | /* 250 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, |
| 133203 | - /* 260 */ 351, 325, 936, 1324, 384, 698, 1324, 381, 379, 99, | |
| 133204 | - /* 270 */ 100, 90, 840, 840, 852, 855, 844, 844, 97, 97, | |
| 133205 | - /* 280 */ 98, 98, 98, 98, 700, 96, 96, 96, 96, 95, | |
| 133266 | + /* 260 */ 351, 325, 938, 1327, 384, 699, 1327, 381, 379, 99, | |
| 133267 | + /* 270 */ 100, 90, 842, 842, 854, 857, 846, 846, 97, 97, | |
| 133268 | + /* 280 */ 98, 98, 98, 98, 701, 96, 96, 96, 96, 95, | |
| 133206 | 133269 | /* 290 */ 95, 94, 94, 94, 93, 351, 325, 92, 89, 178, |
| 133207 | - /* 300 */ 831, 934, 373, 699, 99, 100, 90, 840, 840, 852, | |
| 133208 | - /* 310 */ 855, 844, 844, 97, 97, 98, 98, 98, 98, 375, | |
| 133270 | + /* 300 */ 833, 936, 373, 700, 99, 100, 90, 842, 842, 854, | |
| 133271 | + /* 310 */ 857, 846, 846, 97, 97, 98, 98, 98, 98, 375, | |
| 133209 | 133272 | /* 320 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, |
| 133210 | - /* 330 */ 351, 325, 1273, 945, 354, 817, 934, 738, 738, 99, | |
| 133211 | - /* 340 */ 100, 90, 840, 840, 852, 855, 844, 844, 97, 97, | |
| 133273 | + /* 330 */ 351, 325, 1276, 947, 354, 818, 936, 739, 739, 99, | |
| 133274 | + /* 340 */ 100, 90, 842, 842, 854, 857, 846, 846, 97, 97, | |
| 133212 | 133275 | /* 350 */ 98, 98, 98, 98, 230, 96, 96, 96, 96, 95, |
| 133213 | - /* 360 */ 95, 94, 94, 94, 93, 351, 325, 967, 227, 92, | |
| 133214 | - /* 370 */ 89, 178, 373, 300, 99, 100, 90, 840, 840, 852, | |
| 133215 | - /* 380 */ 855, 844, 844, 97, 97, 98, 98, 98, 98, 919, | |
| 133276 | + /* 360 */ 95, 94, 94, 94, 93, 351, 325, 969, 227, 92, | |
| 133277 | + /* 370 */ 89, 178, 373, 300, 99, 100, 90, 842, 842, 854, | |
| 133278 | + /* 380 */ 857, 846, 846, 97, 97, 98, 98, 98, 98, 921, | |
| 133216 | 133279 | /* 390 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, |
| 133217 | - /* 400 */ 351, 325, 449, 447, 447, 447, 147, 736, 736, 99, | |
| 133218 | - /* 410 */ 100, 90, 840, 840, 852, 855, 844, 844, 97, 97, | |
| 133280 | + /* 400 */ 351, 325, 449, 447, 447, 447, 147, 737, 737, 99, | |
| 133281 | + /* 410 */ 100, 90, 842, 842, 854, 857, 846, 846, 97, 97, | |
| 133219 | 133282 | /* 420 */ 98, 98, 98, 98, 296, 96, 96, 96, 96, 95, |
| 133220 | - /* 430 */ 95, 94, 94, 94, 93, 351, 325, 419, 231, 956, | |
| 133221 | - /* 440 */ 956, 158, 25, 422, 99, 100, 90, 840, 840, 852, | |
| 133222 | - /* 450 */ 855, 844, 844, 97, 97, 98, 98, 98, 98, 450, | |
| 133283 | + /* 430 */ 95, 94, 94, 94, 93, 351, 325, 419, 231, 958, | |
| 133284 | + /* 440 */ 958, 158, 25, 422, 99, 100, 90, 842, 842, 854, | |
| 133285 | + /* 450 */ 857, 846, 846, 97, 97, 98, 98, 98, 98, 450, | |
| 133223 | 133286 | /* 460 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, |
| 133224 | - /* 470 */ 351, 443, 224, 224, 420, 956, 956, 960, 325, 52, | |
| 133225 | - /* 480 */ 52, 957, 958, 176, 415, 78, 99, 100, 90, 840, | |
| 133226 | - /* 490 */ 840, 852, 855, 844, 844, 97, 97, 98, 98, 98, | |
| 133287 | + /* 470 */ 351, 443, 224, 224, 420, 958, 958, 962, 325, 52, | |
| 133288 | + /* 480 */ 52, 959, 960, 176, 415, 78, 99, 100, 90, 842, | |
| 133289 | + /* 490 */ 842, 854, 857, 846, 846, 97, 97, 98, 98, 98, | |
| 133227 | 133290 | /* 500 */ 98, 379, 96, 96, 96, 96, 95, 95, 94, 94, |
| 133228 | - /* 510 */ 94, 93, 351, 325, 428, 418, 298, 957, 958, 960, | |
| 133229 | - /* 520 */ 81, 99, 88, 90, 840, 840, 852, 855, 844, 844, | |
| 133230 | - /* 530 */ 97, 97, 98, 98, 98, 98, 716, 96, 96, 96, | |
| 133231 | - /* 540 */ 96, 95, 95, 94, 94, 94, 93, 351, 325, 841, | |
| 133232 | - /* 550 */ 841, 853, 856, 994, 318, 343, 379, 100, 90, 840, | |
| 133233 | - /* 560 */ 840, 852, 855, 844, 844, 97, 97, 98, 98, 98, | |
| 133291 | + /* 510 */ 94, 93, 351, 325, 428, 418, 298, 959, 960, 962, | |
| 133292 | + /* 520 */ 81, 99, 88, 90, 842, 842, 854, 857, 846, 846, | |
| 133293 | + /* 530 */ 97, 97, 98, 98, 98, 98, 717, 96, 96, 96, | |
| 133294 | + /* 540 */ 96, 95, 95, 94, 94, 94, 93, 351, 325, 843, | |
| 133295 | + /* 550 */ 843, 855, 858, 996, 318, 343, 379, 100, 90, 842, | |
| 133296 | + /* 560 */ 842, 854, 857, 846, 846, 97, 97, 98, 98, 98, | |
| 133234 | 133297 | /* 570 */ 98, 450, 96, 96, 96, 96, 95, 95, 94, 94, |
| 133235 | 133298 | /* 580 */ 94, 93, 351, 325, 350, 350, 350, 260, 377, 340, |
| 133236 | - /* 590 */ 927, 52, 52, 90, 840, 840, 852, 855, 844, 844, | |
| 133299 | + /* 590 */ 929, 52, 52, 90, 842, 842, 854, 857, 846, 846, | |
| 133237 | 133300 | /* 600 */ 97, 97, 98, 98, 98, 98, 361, 96, 96, 96, |
| 133238 | 133301 | /* 610 */ 96, 95, 95, 94, 94, 94, 93, 351, 86, 445, |
| 133239 | - /* 620 */ 845, 3, 1200, 361, 360, 378, 344, 812, 956, 956, | |
| 133240 | - /* 630 */ 1297, 86, 445, 728, 3, 212, 169, 287, 405, 282, | |
| 133241 | - /* 640 */ 404, 199, 232, 450, 300, 759, 83, 84, 280, 245, | |
| 133302 | + /* 620 */ 847, 3, 1203, 361, 360, 378, 344, 813, 958, 958, | |
| 133303 | + /* 630 */ 1300, 86, 445, 729, 3, 212, 169, 287, 405, 282, | |
| 133304 | + /* 640 */ 404, 199, 232, 450, 300, 760, 83, 84, 280, 245, | |
| 133242 | 133305 | /* 650 */ 262, 365, 251, 85, 352, 352, 92, 89, 178, 83, |
| 133243 | 133306 | /* 660 */ 84, 242, 412, 52, 52, 448, 85, 352, 352, 246, |
| 133244 | - /* 670 */ 957, 958, 194, 455, 669, 402, 399, 398, 448, 243, | |
| 133245 | - /* 680 */ 221, 114, 434, 775, 361, 450, 397, 268, 746, 224, | |
| 133246 | - /* 690 */ 224, 132, 132, 198, 830, 434, 452, 451, 428, 427, | |
| 133247 | - /* 700 */ 818, 415, 733, 712, 132, 52, 52, 830, 268, 452, | |
| 133248 | - /* 710 */ 451, 733, 194, 818, 363, 402, 399, 398, 450, 1268, | |
| 133249 | - /* 720 */ 1268, 23, 956, 956, 86, 445, 397, 3, 228, 429, | |
| 133250 | - /* 730 */ 893, 823, 823, 823, 825, 19, 203, 719, 52, 52, | |
| 133251 | - /* 740 */ 428, 408, 439, 249, 823, 823, 823, 825, 19, 229, | |
| 133252 | - /* 750 */ 403, 153, 83, 84, 760, 177, 241, 450, 720, 85, | |
| 133253 | - /* 760 */ 352, 352, 120, 157, 957, 958, 58, 975, 409, 355, | |
| 133254 | - /* 770 */ 330, 448, 268, 428, 430, 320, 789, 32, 32, 86, | |
| 133255 | - /* 780 */ 445, 775, 3, 341, 98, 98, 98, 98, 434, 96, | |
| 133307 | + /* 670 */ 959, 960, 194, 455, 670, 402, 399, 398, 448, 243, | |
| 133308 | + /* 680 */ 221, 114, 434, 776, 361, 450, 397, 268, 747, 224, | |
| 133309 | + /* 690 */ 224, 132, 132, 198, 832, 434, 452, 451, 428, 427, | |
| 133310 | + /* 700 */ 819, 415, 734, 713, 132, 52, 52, 832, 268, 452, | |
| 133311 | + /* 710 */ 451, 734, 194, 819, 363, 402, 399, 398, 450, 1271, | |
| 133312 | + /* 720 */ 1271, 23, 958, 958, 86, 445, 397, 3, 228, 429, | |
| 133313 | + /* 730 */ 895, 824, 824, 826, 827, 19, 203, 720, 52, 52, | |
| 133314 | + /* 740 */ 428, 408, 439, 249, 824, 824, 826, 827, 19, 229, | |
| 133315 | + /* 750 */ 403, 153, 83, 84, 761, 177, 241, 450, 721, 85, | |
| 133316 | + /* 760 */ 352, 352, 120, 157, 959, 960, 58, 977, 409, 355, | |
| 133317 | + /* 770 */ 330, 448, 268, 428, 430, 320, 790, 32, 32, 86, | |
| 133318 | + /* 780 */ 445, 776, 3, 341, 98, 98, 98, 98, 434, 96, | |
| 133256 | 133319 | /* 790 */ 96, 96, 96, 95, 95, 94, 94, 94, 93, 351, |
| 133257 | - /* 800 */ 830, 120, 452, 451, 812, 885, 818, 83, 84, 975, | |
| 133258 | - /* 810 */ 812, 132, 410, 918, 85, 352, 352, 132, 407, 788, | |
| 133259 | - /* 820 */ 956, 956, 92, 89, 178, 915, 448, 262, 370, 261, | |
| 133260 | - /* 830 */ 82, 912, 80, 262, 370, 261, 932, 823, 823, 823, | |
| 133261 | - /* 840 */ 825, 19, 257, 434, 96, 96, 96, 96, 95, 95, | |
| 133262 | - /* 850 */ 94, 94, 94, 93, 351, 830, 268, 452, 451, 956, | |
| 133263 | - /* 860 */ 956, 818, 957, 958, 120, 92, 89, 178, 943, 2, | |
| 133264 | - /* 870 */ 916, 963, 268, 1, 766, 76, 445, 761, 3, 707, | |
| 133265 | - /* 880 */ 899, 899, 387, 956, 956, 756, 917, 371, 739, 777, | |
| 133266 | - /* 890 */ 755, 907, 823, 823, 823, 825, 19, 883, 740, 450, | |
| 133267 | - /* 900 */ 24, 957, 958, 83, 84, 369, 956, 956, 708, 226, | |
| 133268 | - /* 910 */ 85, 352, 352, 745, 315, 314, 313, 215, 311, 10, | |
| 133269 | - /* 920 */ 10, 682, 448, 349, 348, 957, 958, 887, 776, 691, | |
| 133270 | - /* 930 */ 331, 956, 956, 337, 157, 450, 268, 103, 450, 434, | |
| 133271 | - /* 940 */ 450, 816, 310, 906, 887, 889, 321, 450, 957, 958, | |
| 133272 | - /* 950 */ 708, 830, 775, 452, 451, 10, 10, 818, 10, 10, | |
| 133273 | - /* 960 */ 52, 52, 171, 170, 180, 225, 248, 10, 10, 339, | |
| 133274 | - /* 970 */ 701, 701, 233, 957, 958, 247, 982, 741, 450, 956, | |
| 133275 | - /* 980 */ 956, 425, 157, 980, 685, 981, 182, 912, 823, 823, | |
| 133276 | - /* 990 */ 823, 825, 19, 183, 324, 423, 132, 181, 51, 51, | |
| 133277 | - /* 1000 */ 715, 349, 348, 394, 256, 887, 334, 915, 983, 983, | |
| 133278 | - /* 1010 */ 830, 417, 824, 234, 198, 234, 818, 268, 326, 382, | |
| 133279 | - /* 1020 */ 120, 957, 958, 264, 177, 98, 98, 98, 98, 91, | |
| 133320 | + /* 800 */ 832, 120, 452, 451, 813, 887, 819, 83, 84, 977, | |
| 133321 | + /* 810 */ 813, 132, 410, 920, 85, 352, 352, 132, 407, 789, | |
| 133322 | + /* 820 */ 958, 958, 92, 89, 178, 917, 448, 262, 370, 261, | |
| 133323 | + /* 830 */ 82, 914, 80, 262, 370, 261, 776, 824, 824, 826, | |
| 133324 | + /* 840 */ 827, 19, 934, 434, 96, 96, 96, 96, 95, 95, | |
| 133325 | + /* 850 */ 94, 94, 94, 93, 351, 832, 74, 452, 451, 958, | |
| 133326 | + /* 860 */ 958, 819, 959, 960, 120, 92, 89, 178, 945, 2, | |
| 133327 | + /* 870 */ 918, 965, 268, 1, 976, 76, 445, 762, 3, 708, | |
| 133328 | + /* 880 */ 901, 901, 387, 958, 958, 757, 919, 371, 740, 778, | |
| 133329 | + /* 890 */ 756, 257, 824, 824, 826, 827, 19, 417, 741, 450, | |
| 133330 | + /* 900 */ 24, 959, 960, 83, 84, 369, 958, 958, 177, 226, | |
| 133331 | + /* 910 */ 85, 352, 352, 885, 315, 314, 313, 215, 311, 10, | |
| 133332 | + /* 920 */ 10, 683, 448, 349, 348, 959, 960, 909, 777, 157, | |
| 133333 | + /* 930 */ 120, 958, 958, 337, 776, 416, 711, 310, 450, 434, | |
| 133334 | + /* 940 */ 450, 321, 450, 791, 103, 200, 175, 450, 959, 960, | |
| 133335 | + /* 950 */ 908, 832, 792, 452, 451, 9, 9, 819, 10, 10, | |
| 133336 | + /* 960 */ 52, 52, 51, 51, 180, 716, 248, 10, 10, 171, | |
| 133337 | + /* 970 */ 170, 167, 339, 959, 960, 247, 984, 702, 702, 450, | |
| 133338 | + /* 980 */ 715, 233, 686, 982, 889, 983, 182, 914, 824, 824, | |
| 133339 | + /* 990 */ 826, 827, 19, 183, 256, 423, 132, 181, 394, 10, | |
| 133340 | + /* 1000 */ 10, 889, 891, 749, 958, 958, 917, 268, 985, 198, | |
| 133341 | + /* 1010 */ 985, 349, 348, 425, 415, 299, 817, 832, 326, 825, | |
| 133342 | + /* 1020 */ 120, 332, 133, 819, 268, 98, 98, 98, 98, 91, | |
| 133280 | 133343 | /* 1030 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, |
| 133281 | - /* 1040 */ 351, 816, 416, 371, 120, 359, 816, 823, 823, 823, | |
| 133282 | - /* 1050 */ 775, 299, 916, 450, 368, 197, 196, 195, 358, 200, | |
| 133283 | - /* 1060 */ 175, 380, 9, 9, 450, 1287, 875, 714, 917, 450, | |
| 133284 | - /* 1070 */ 433, 237, 450, 36, 36, 132, 253, 450, 255, 450, | |
| 133285 | - /* 1080 */ 117, 450, 809, 362, 37, 37, 983, 983, 450, 12, | |
| 133286 | - /* 1090 */ 12, 330, 27, 27, 446, 331, 280, 38, 38, 39, | |
| 133287 | - /* 1100 */ 39, 40, 40, 1207, 450, 816, 335, 356, 41, 41, | |
| 133288 | - /* 1110 */ 450, 336, 450, 695, 450, 120, 450, 332, 133, 450, | |
| 133289 | - /* 1120 */ 268, 450, 269, 450, 42, 42, 450, 816, 254, 450, | |
| 133290 | - /* 1130 */ 28, 28, 29, 29, 31, 31, 43, 43, 450, 44, | |
| 133291 | - /* 1140 */ 44, 45, 45, 11, 11, 450, 46, 46, 450, 105, | |
| 133292 | - /* 1150 */ 105, 450, 748, 713, 450, 695, 450, 910, 47, 47, | |
| 133293 | - /* 1160 */ 450, 267, 450, 415, 450, 48, 48, 450, 33, 33, | |
| 133294 | - /* 1170 */ 386, 49, 49, 450, 50, 50, 34, 34, 450, 172, | |
| 133295 | - /* 1180 */ 122, 122, 123, 123, 124, 124, 450, 56, 56, 450, | |
| 133296 | - /* 1190 */ 120, 450, 345, 35, 35, 450, 790, 450, 106, 106, | |
| 133297 | - /* 1200 */ 450, 74, 450, 974, 450, 791, 53, 53, 432, 107, | |
| 133298 | - /* 1210 */ 107, 108, 108, 450, 272, 104, 104, 121, 121, 450, | |
| 133299 | - /* 1220 */ 119, 119, 112, 112, 111, 111, 450, 317, 996, 450, | |
| 133300 | - /* 1230 */ 118, 450, 162, 109, 109, 317, 935, 450, 896, 110, | |
| 133301 | - /* 1240 */ 110, 450, 895, 744, 688, 436, 55, 55, 20, 57, | |
| 133302 | - /* 1250 */ 57, 54, 54, 440, 444, 756, 385, 26, 26, 274, | |
| 133303 | - /* 1260 */ 755, 30, 30, 21, 672, 673, 674, 223, 175, 931, | |
| 133304 | - /* 1270 */ 814, 372, 319, 202, 202, 882, 120, 120, 120, 374, | |
| 133305 | - /* 1280 */ 826, 710, 202, 72, 276, 263, 120, 120, 74, 395, | |
| 133306 | - /* 1290 */ 278, 286, 208, 74, 718, 717, 725, 726, 892, 892, | |
| 133307 | - /* 1300 */ 167, 997, 285, 753, 729, 784, 77, 878, 202, 997, | |
| 133308 | - /* 1310 */ 208, 693, 891, 891, 116, 281, 782, 882, 390, 815, | |
| 133309 | - /* 1320 */ 762, 773, 826, 431, 302, 303, 822, 218, 696, 289, | |
| 133310 | - /* 1330 */ 690, 291, 293, 679, 678, 680, 950, 159, 316, 7, | |
| 133311 | - /* 1340 */ 364, 252, 259, 804, 909, 376, 400, 295, 308, 173, | |
| 133312 | - /* 1350 */ 435, 953, 168, 991, 135, 205, 926, 924, 59, 988, | |
| 133313 | - /* 1360 */ 62, 284, 880, 333, 879, 712, 144, 156, 130, 72, | |
| 133314 | - /* 1370 */ 366, 367, 393, 185, 189, 160, 383, 67, 389, 266, | |
| 133315 | - /* 1380 */ 137, 894, 774, 219, 154, 139, 190, 140, 391, 271, | |
| 133316 | - /* 1390 */ 191, 141, 142, 801, 681, 148, 811, 342, 322, 192, | |
| 133317 | - /* 1400 */ 406, 732, 911, 874, 723, 731, 323, 710, 730, 71, | |
| 133318 | - /* 1410 */ 704, 204, 283, 703, 6, 79, 421, 702, 965, 770, | |
| 133319 | - /* 1420 */ 297, 346, 426, 102, 722, 288, 73, 424, 213, 951, | |
| 133320 | - /* 1430 */ 771, 438, 22, 290, 687, 769, 442, 453, 239, 217, | |
| 133321 | - /* 1440 */ 214, 668, 125, 353, 126, 216, 454, 166, 676, 115, | |
| 133322 | - /* 1450 */ 675, 235, 244, 179, 670, 357, 810, 113, 890, 888, | |
| 133323 | - /* 1460 */ 292, 136, 128, 752, 304, 768, 294, 305, 138, 742, | |
| 133324 | - /* 1470 */ 306, 307, 127, 184, 860, 258, 905, 145, 143, 238, | |
| 133325 | - /* 1480 */ 63, 64, 65, 66, 240, 129, 908, 186, 187, 904, | |
| 133326 | - /* 1490 */ 8, 13, 188, 265, 897, 149, 202, 985, 388, 684, | |
| 133327 | - /* 1500 */ 150, 161, 392, 285, 193, 279, 151, 396, 68, 14, | |
| 133328 | - /* 1510 */ 401, 15, 327, 721, 328, 134, 69, 70, 236, 131, | |
| 133329 | - /* 1520 */ 829, 828, 858, 750, 16, 201, 754, 4, 783, 220, | |
| 133330 | - /* 1530 */ 414, 174, 222, 152, 77, 778, 74, 17, 18, 873, | |
| 133331 | - /* 1540 */ 859, 857, 914, 862, 913, 207, 206, 940, 163, 437, | |
| 133332 | - /* 1550 */ 946, 941, 164, 209, 210, 441, 861, 165, 312, 827, | |
| 133333 | - /* 1560 */ 694, 87, 1000, 309, 211, 1000, 1000, 1000, 1000, 1289, | |
| 133334 | - /* 1570 */ 1288, | |
| 133344 | + /* 1040 */ 351, 157, 810, 371, 382, 359, 959, 960, 358, 268, | |
| 133345 | + /* 1050 */ 450, 918, 368, 324, 824, 824, 826, 450, 709, 450, | |
| 133346 | + /* 1060 */ 264, 380, 889, 450, 877, 746, 253, 919, 255, 433, | |
| 133347 | + /* 1070 */ 36, 36, 234, 450, 234, 120, 269, 37, 37, 12, | |
| 133348 | + /* 1080 */ 12, 334, 272, 27, 27, 450, 330, 118, 450, 162, | |
| 133349 | + /* 1090 */ 742, 280, 450, 38, 38, 450, 985, 356, 985, 450, | |
| 133350 | + /* 1100 */ 709, 1210, 450, 132, 450, 39, 39, 450, 40, 40, | |
| 133351 | + /* 1110 */ 450, 362, 41, 41, 450, 42, 42, 450, 254, 28, | |
| 133352 | + /* 1120 */ 28, 450, 29, 29, 31, 31, 450, 43, 43, 450, | |
| 133353 | + /* 1130 */ 44, 44, 450, 714, 45, 45, 450, 11, 11, 767, | |
| 133354 | + /* 1140 */ 450, 46, 46, 450, 268, 450, 105, 105, 450, 47, | |
| 133355 | + /* 1150 */ 47, 450, 48, 48, 450, 237, 33, 33, 450, 172, | |
| 133356 | + /* 1160 */ 49, 49, 450, 50, 50, 34, 34, 274, 122, 122, | |
| 133357 | + /* 1170 */ 450, 123, 123, 450, 124, 124, 450, 898, 56, 56, | |
| 133358 | + /* 1180 */ 450, 897, 35, 35, 450, 267, 450, 817, 450, 817, | |
| 133359 | + /* 1190 */ 106, 106, 450, 53, 53, 385, 107, 107, 450, 817, | |
| 133360 | + /* 1200 */ 108, 108, 817, 450, 104, 104, 121, 121, 119, 119, | |
| 133361 | + /* 1210 */ 450, 117, 112, 112, 450, 276, 450, 225, 111, 111, | |
| 133362 | + /* 1220 */ 450, 730, 450, 109, 109, 450, 673, 674, 675, 912, | |
| 133363 | + /* 1230 */ 110, 110, 317, 998, 55, 55, 57, 57, 692, 331, | |
| 133364 | + /* 1240 */ 54, 54, 26, 26, 696, 30, 30, 317, 937, 197, | |
| 133365 | + /* 1250 */ 196, 195, 335, 281, 336, 446, 331, 745, 689, 436, | |
| 133366 | + /* 1260 */ 440, 444, 120, 72, 386, 223, 175, 345, 757, 933, | |
| 133367 | + /* 1270 */ 20, 286, 319, 756, 815, 372, 374, 202, 202, 202, | |
| 133368 | + /* 1280 */ 263, 395, 285, 74, 208, 21, 696, 719, 718, 884, | |
| 133369 | + /* 1290 */ 120, 120, 120, 120, 120, 754, 278, 828, 77, 74, | |
| 133370 | + /* 1300 */ 726, 727, 785, 783, 880, 202, 999, 208, 894, 893, | |
| 133371 | + /* 1310 */ 894, 893, 694, 816, 763, 116, 774, 1290, 431, 432, | |
| 133372 | + /* 1320 */ 302, 999, 390, 303, 823, 697, 691, 680, 159, 289, | |
| 133373 | + /* 1330 */ 679, 884, 681, 952, 291, 218, 293, 7, 316, 828, | |
| 133374 | + /* 1340 */ 173, 805, 259, 364, 252, 911, 376, 713, 295, 435, | |
| 133375 | + /* 1350 */ 308, 168, 955, 993, 135, 400, 990, 284, 882, 881, | |
| 133376 | + /* 1360 */ 205, 928, 926, 59, 333, 62, 144, 156, 130, 72, | |
| 133377 | + /* 1370 */ 802, 366, 367, 393, 137, 185, 189, 160, 139, 383, | |
| 133378 | + /* 1380 */ 67, 896, 140, 141, 142, 148, 389, 812, 775, 266, | |
| 133379 | + /* 1390 */ 219, 190, 154, 391, 913, 876, 271, 406, 191, 322, | |
| 133380 | + /* 1400 */ 682, 733, 192, 342, 732, 724, 731, 711, 723, 421, | |
| 133381 | + /* 1410 */ 705, 71, 323, 6, 204, 771, 288, 79, 297, 346, | |
| 133382 | + /* 1420 */ 772, 704, 290, 283, 703, 770, 292, 294, 967, 239, | |
| 133383 | + /* 1430 */ 769, 102, 862, 438, 426, 240, 424, 442, 73, 213, | |
| 133384 | + /* 1440 */ 688, 238, 22, 453, 953, 214, 217, 216, 454, 677, | |
| 133385 | + /* 1450 */ 676, 671, 753, 125, 115, 235, 126, 669, 353, 166, | |
| 133386 | + /* 1460 */ 127, 244, 179, 357, 306, 304, 305, 307, 113, 892, | |
| 133387 | + /* 1470 */ 327, 890, 811, 328, 134, 128, 136, 138, 743, 258, | |
| 133388 | + /* 1480 */ 907, 184, 143, 129, 910, 186, 63, 64, 145, 187, | |
| 133389 | + /* 1490 */ 906, 65, 8, 66, 13, 188, 202, 899, 265, 149, | |
| 133390 | + /* 1500 */ 987, 388, 150, 685, 161, 392, 285, 193, 279, 396, | |
| 133391 | + /* 1510 */ 151, 401, 68, 14, 15, 722, 69, 236, 831, 131, | |
| 133392 | + /* 1520 */ 830, 860, 70, 751, 16, 414, 755, 4, 174, 220, | |
| 133393 | + /* 1530 */ 222, 784, 201, 152, 779, 77, 74, 17, 18, 875, | |
| 133394 | + /* 1540 */ 861, 859, 916, 864, 915, 207, 206, 942, 163, 437, | |
| 133395 | + /* 1550 */ 948, 943, 164, 209, 1002, 441, 863, 165, 210, 829, | |
| 133396 | + /* 1560 */ 695, 87, 312, 211, 1292, 1291, 309, | |
| 133335 | 133397 | }; |
| 133336 | 133398 | static const YYCODETYPE yy_lookahead[] = { |
| 133337 | 133399 | /* 0 */ 19, 95, 53, 97, 22, 24, 24, 101, 27, 28, |
| 133338 | 133400 | /* 10 */ 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, |
| 133339 | 133401 | /* 20 */ 39, 40, 41, 152, 43, 44, 45, 46, 47, 48, |
| @@ -133415,87 +133477,86 @@ | ||
| 133415 | 133477 | /* 780 */ 20, 124, 22, 111, 38, 39, 40, 41, 83, 43, |
| 133416 | 133478 | /* 790 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, |
| 133417 | 133479 | /* 800 */ 95, 196, 97, 98, 85, 152, 101, 47, 48, 97, |
| 133418 | 133480 | /* 810 */ 85, 92, 207, 193, 54, 55, 56, 92, 49, 175, |
| 133419 | 133481 | /* 820 */ 55, 56, 221, 222, 223, 12, 66, 108, 109, 110, |
| 133420 | - /* 830 */ 137, 163, 139, 108, 109, 110, 152, 132, 133, 134, | |
| 133482 | + /* 830 */ 137, 163, 139, 108, 109, 110, 26, 132, 133, 134, | |
| 133421 | 133483 | /* 840 */ 135, 136, 152, 83, 43, 44, 45, 46, 47, 48, |
| 133422 | - /* 850 */ 49, 50, 51, 52, 53, 95, 152, 97, 98, 55, | |
| 133484 | + /* 850 */ 49, 50, 51, 52, 53, 95, 26, 97, 98, 55, | |
| 133423 | 133485 | /* 860 */ 56, 101, 97, 98, 196, 221, 222, 223, 146, 147, |
| 133424 | - /* 870 */ 57, 171, 152, 22, 213, 19, 20, 49, 22, 179, | |
| 133486 | + /* 870 */ 57, 171, 152, 22, 26, 19, 20, 49, 22, 179, | |
| 133425 | 133487 | /* 880 */ 108, 109, 110, 55, 56, 116, 73, 219, 75, 124, |
| 133426 | - /* 890 */ 121, 152, 132, 133, 134, 135, 136, 193, 85, 152, | |
| 133427 | - /* 900 */ 232, 97, 98, 47, 48, 237, 55, 56, 55, 5, | |
| 133488 | + /* 890 */ 121, 152, 132, 133, 134, 135, 136, 163, 85, 152, | |
| 133489 | + /* 900 */ 232, 97, 98, 47, 48, 237, 55, 56, 98, 5, | |
| 133428 | 133490 | /* 910 */ 54, 55, 56, 193, 10, 11, 12, 13, 14, 172, |
| 133429 | - /* 920 */ 173, 17, 66, 47, 48, 97, 98, 152, 124, 166, | |
| 133430 | - /* 930 */ 167, 55, 56, 186, 152, 152, 152, 22, 152, 83, | |
| 133431 | - /* 940 */ 152, 152, 160, 152, 169, 170, 164, 152, 97, 98, | |
| 133432 | - /* 950 */ 97, 95, 26, 97, 98, 172, 173, 101, 172, 173, | |
| 133433 | - /* 960 */ 172, 173, 47, 48, 60, 22, 62, 172, 173, 186, | |
| 133434 | - /* 970 */ 55, 56, 186, 97, 98, 71, 100, 193, 152, 55, | |
| 133435 | - /* 980 */ 56, 186, 152, 107, 21, 109, 82, 163, 132, 133, | |
| 133436 | - /* 990 */ 134, 135, 136, 89, 164, 207, 92, 93, 172, 173, | |
| 133437 | - /* 1000 */ 181, 47, 48, 19, 16, 230, 217, 12, 132, 133, | |
| 133438 | - /* 1010 */ 95, 163, 97, 183, 30, 185, 101, 152, 114, 152, | |
| 133439 | - /* 1020 */ 196, 97, 98, 152, 98, 38, 39, 40, 41, 42, | |
| 133491 | + /* 920 */ 173, 17, 66, 47, 48, 97, 98, 152, 124, 152, | |
| 133492 | + /* 930 */ 196, 55, 56, 186, 124, 152, 106, 160, 152, 83, | |
| 133493 | + /* 940 */ 152, 164, 152, 61, 22, 211, 212, 152, 97, 98, | |
| 133494 | + /* 950 */ 152, 95, 70, 97, 98, 172, 173, 101, 172, 173, | |
| 133495 | + /* 960 */ 172, 173, 172, 173, 60, 181, 62, 172, 173, 47, | |
| 133496 | + /* 970 */ 48, 123, 186, 97, 98, 71, 100, 55, 56, 152, | |
| 133497 | + /* 980 */ 181, 186, 21, 107, 152, 109, 82, 163, 132, 133, | |
| 133498 | + /* 990 */ 134, 135, 136, 89, 16, 207, 92, 93, 19, 172, | |
| 133499 | + /* 1000 */ 173, 169, 170, 195, 55, 56, 12, 152, 132, 30, | |
| 133500 | + /* 1010 */ 134, 47, 48, 186, 206, 225, 152, 95, 114, 97, | |
| 133501 | + /* 1020 */ 196, 245, 246, 101, 152, 38, 39, 40, 41, 42, | |
| 133440 | 133502 | /* 1030 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, |
| 133441 | - /* 1040 */ 53, 152, 152, 219, 196, 141, 152, 132, 133, 134, | |
| 133442 | - /* 1050 */ 124, 225, 57, 152, 91, 108, 109, 110, 193, 211, | |
| 133443 | - /* 1060 */ 212, 237, 172, 173, 152, 122, 103, 181, 73, 152, | |
| 133444 | - /* 1070 */ 75, 210, 152, 172, 173, 92, 88, 152, 90, 152, | |
| 133445 | - /* 1080 */ 22, 152, 163, 100, 172, 173, 132, 133, 152, 172, | |
| 133446 | - /* 1090 */ 173, 107, 172, 173, 166, 167, 112, 172, 173, 172, | |
| 133447 | - /* 1100 */ 173, 172, 173, 140, 152, 152, 217, 242, 172, 173, | |
| 133448 | - /* 1110 */ 152, 217, 152, 55, 152, 196, 152, 245, 246, 152, | |
| 133449 | - /* 1120 */ 152, 152, 152, 152, 172, 173, 152, 152, 140, 152, | |
| 133450 | - /* 1130 */ 172, 173, 172, 173, 172, 173, 172, 173, 152, 172, | |
| 133451 | - /* 1140 */ 173, 172, 173, 172, 173, 152, 172, 173, 152, 172, | |
| 133452 | - /* 1150 */ 173, 152, 195, 152, 152, 97, 152, 163, 172, 173, | |
| 133453 | - /* 1160 */ 152, 193, 152, 206, 152, 172, 173, 152, 172, 173, | |
| 133454 | - /* 1170 */ 217, 172, 173, 152, 172, 173, 172, 173, 152, 26, | |
| 133455 | - /* 1180 */ 172, 173, 172, 173, 172, 173, 152, 172, 173, 152, | |
| 133456 | - /* 1190 */ 196, 152, 217, 172, 173, 152, 61, 152, 172, 173, | |
| 133457 | - /* 1200 */ 152, 26, 152, 26, 152, 70, 172, 173, 191, 172, | |
| 133458 | - /* 1210 */ 173, 172, 173, 152, 152, 172, 173, 172, 173, 152, | |
| 133459 | - /* 1220 */ 172, 173, 172, 173, 172, 173, 152, 22, 23, 152, | |
| 133460 | - /* 1230 */ 22, 152, 24, 172, 173, 22, 23, 152, 59, 172, | |
| 133461 | - /* 1240 */ 173, 152, 63, 163, 163, 163, 172, 173, 22, 172, | |
| 133462 | - /* 1250 */ 173, 172, 173, 163, 163, 116, 77, 172, 173, 152, | |
| 133463 | - /* 1260 */ 121, 172, 173, 37, 7, 8, 9, 211, 212, 23, | |
| 133464 | - /* 1270 */ 23, 23, 26, 26, 26, 55, 196, 196, 196, 23, | |
| 133465 | - /* 1280 */ 55, 106, 26, 130, 152, 23, 196, 196, 26, 23, | |
| 133466 | - /* 1290 */ 23, 101, 26, 26, 100, 101, 7, 8, 132, 133, | |
| 133467 | - /* 1300 */ 123, 96, 112, 23, 152, 23, 26, 23, 26, 96, | |
| 133468 | - /* 1310 */ 26, 23, 132, 133, 26, 152, 152, 97, 234, 152, | |
| 133469 | - /* 1320 */ 152, 152, 97, 152, 152, 152, 152, 233, 152, 210, | |
| 133470 | - /* 1330 */ 152, 210, 210, 152, 152, 152, 152, 197, 150, 198, | |
| 133471 | - /* 1340 */ 214, 214, 239, 201, 201, 239, 176, 214, 200, 184, | |
| 133472 | - /* 1350 */ 227, 155, 198, 67, 243, 122, 159, 159, 240, 69, | |
| 133473 | - /* 1360 */ 240, 175, 175, 159, 175, 180, 22, 220, 27, 130, | |
| 133474 | - /* 1370 */ 18, 159, 18, 158, 158, 220, 159, 137, 74, 235, | |
| 133475 | - /* 1380 */ 189, 236, 159, 159, 22, 192, 158, 192, 177, 159, | |
| 133476 | - /* 1390 */ 158, 192, 192, 201, 159, 189, 189, 76, 177, 158, | |
| 133477 | - /* 1400 */ 107, 174, 201, 201, 182, 174, 177, 106, 174, 107, | |
| 133478 | - /* 1410 */ 174, 159, 174, 176, 22, 137, 125, 174, 174, 216, | |
| 133479 | - /* 1420 */ 159, 53, 126, 129, 182, 215, 128, 127, 25, 13, | |
| 133480 | - /* 1430 */ 216, 177, 26, 215, 162, 216, 177, 161, 229, 6, | |
| 133481 | - /* 1440 */ 153, 4, 165, 3, 165, 153, 151, 22, 151, 178, | |
| 133482 | - /* 1450 */ 151, 178, 142, 15, 151, 94, 120, 16, 23, 23, | |
| 133483 | - /* 1460 */ 215, 131, 111, 205, 204, 216, 215, 203, 123, 20, | |
| 133484 | - /* 1470 */ 202, 201, 165, 125, 224, 16, 1, 131, 123, 226, | |
| 133485 | - /* 1480 */ 37, 37, 37, 37, 229, 111, 56, 64, 122, 1, | |
| 133486 | - /* 1490 */ 5, 22, 107, 140, 80, 80, 26, 87, 72, 20, | |
| 133487 | - /* 1500 */ 107, 24, 19, 112, 105, 23, 22, 79, 22, 22, | |
| 133488 | - /* 1510 */ 79, 22, 249, 58, 249, 246, 22, 26, 79, 68, | |
| 133489 | - /* 1520 */ 23, 23, 23, 116, 22, 64, 23, 22, 56, 23, | |
| 133490 | - /* 1530 */ 26, 122, 23, 22, 26, 124, 26, 64, 64, 23, | |
| 133503 | + /* 1040 */ 53, 152, 163, 219, 152, 141, 97, 98, 193, 152, | |
| 133504 | + /* 1050 */ 152, 57, 91, 164, 132, 133, 134, 152, 55, 152, | |
| 133505 | + /* 1060 */ 152, 237, 230, 152, 103, 193, 88, 73, 90, 75, | |
| 133506 | + /* 1070 */ 172, 173, 183, 152, 185, 196, 152, 172, 173, 172, | |
| 133507 | + /* 1080 */ 173, 217, 152, 172, 173, 152, 107, 22, 152, 24, | |
| 133508 | + /* 1090 */ 193, 112, 152, 172, 173, 152, 132, 242, 134, 152, | |
| 133509 | + /* 1100 */ 97, 140, 152, 92, 152, 172, 173, 152, 172, 173, | |
| 133510 | + /* 1110 */ 152, 100, 172, 173, 152, 172, 173, 152, 140, 172, | |
| 133511 | + /* 1120 */ 173, 152, 172, 173, 172, 173, 152, 172, 173, 152, | |
| 133512 | + /* 1130 */ 172, 173, 152, 152, 172, 173, 152, 172, 173, 213, | |
| 133513 | + /* 1140 */ 152, 172, 173, 152, 152, 152, 172, 173, 152, 172, | |
| 133514 | + /* 1150 */ 173, 152, 172, 173, 152, 210, 172, 173, 152, 26, | |
| 133515 | + /* 1160 */ 172, 173, 152, 172, 173, 172, 173, 152, 172, 173, | |
| 133516 | + /* 1170 */ 152, 172, 173, 152, 172, 173, 152, 59, 172, 173, | |
| 133517 | + /* 1180 */ 152, 63, 172, 173, 152, 193, 152, 152, 152, 152, | |
| 133518 | + /* 1190 */ 172, 173, 152, 172, 173, 77, 172, 173, 152, 152, | |
| 133519 | + /* 1200 */ 172, 173, 152, 152, 172, 173, 172, 173, 172, 173, | |
| 133520 | + /* 1210 */ 152, 22, 172, 173, 152, 152, 152, 22, 172, 173, | |
| 133521 | + /* 1220 */ 152, 152, 152, 172, 173, 152, 7, 8, 9, 163, | |
| 133522 | + /* 1230 */ 172, 173, 22, 23, 172, 173, 172, 173, 166, 167, | |
| 133523 | + /* 1240 */ 172, 173, 172, 173, 55, 172, 173, 22, 23, 108, | |
| 133524 | + /* 1250 */ 109, 110, 217, 152, 217, 166, 167, 163, 163, 163, | |
| 133525 | + /* 1260 */ 163, 163, 196, 130, 217, 211, 212, 217, 116, 23, | |
| 133526 | + /* 1270 */ 22, 101, 26, 121, 23, 23, 23, 26, 26, 26, | |
| 133527 | + /* 1280 */ 23, 23, 112, 26, 26, 37, 97, 100, 101, 55, | |
| 133528 | + /* 1290 */ 196, 196, 196, 196, 196, 23, 23, 55, 26, 26, | |
| 133529 | + /* 1300 */ 7, 8, 23, 152, 23, 26, 96, 26, 132, 132, | |
| 133530 | + /* 1310 */ 134, 134, 23, 152, 152, 26, 152, 122, 152, 191, | |
| 133531 | + /* 1320 */ 152, 96, 234, 152, 152, 152, 152, 152, 197, 210, | |
| 133532 | + /* 1330 */ 152, 97, 152, 152, 210, 233, 210, 198, 150, 97, | |
| 133533 | + /* 1340 */ 184, 201, 239, 214, 214, 201, 239, 180, 214, 227, | |
| 133534 | + /* 1350 */ 200, 198, 155, 67, 243, 176, 69, 175, 175, 175, | |
| 133535 | + /* 1360 */ 122, 159, 159, 240, 159, 240, 22, 220, 27, 130, | |
| 133536 | + /* 1370 */ 201, 18, 159, 18, 189, 158, 158, 220, 192, 159, | |
| 133537 | + /* 1380 */ 137, 236, 192, 192, 192, 189, 74, 189, 159, 235, | |
| 133538 | + /* 1390 */ 159, 158, 22, 177, 201, 201, 159, 107, 158, 177, | |
| 133539 | + /* 1400 */ 159, 174, 158, 76, 174, 182, 174, 106, 182, 125, | |
| 133540 | + /* 1410 */ 174, 107, 177, 22, 159, 216, 215, 137, 159, 53, | |
| 133541 | + /* 1420 */ 216, 176, 215, 174, 174, 216, 215, 215, 174, 229, | |
| 133542 | + /* 1430 */ 216, 129, 224, 177, 126, 229, 127, 177, 128, 25, | |
| 133543 | + /* 1440 */ 162, 226, 26, 161, 13, 153, 6, 153, 151, 151, | |
| 133544 | + /* 1450 */ 151, 151, 205, 165, 178, 178, 165, 4, 3, 22, | |
| 133545 | + /* 1460 */ 165, 142, 15, 94, 202, 204, 203, 201, 16, 23, | |
| 133546 | + /* 1470 */ 249, 23, 120, 249, 246, 111, 131, 123, 20, 16, | |
| 133547 | + /* 1480 */ 1, 125, 123, 111, 56, 64, 37, 37, 131, 122, | |
| 133548 | + /* 1490 */ 1, 37, 5, 37, 22, 107, 26, 80, 140, 80, | |
| 133549 | + /* 1500 */ 87, 72, 107, 20, 24, 19, 112, 105, 23, 79, | |
| 133550 | + /* 1510 */ 22, 79, 22, 22, 22, 58, 22, 79, 23, 68, | |
| 133551 | + /* 1520 */ 23, 23, 26, 116, 22, 26, 23, 22, 122, 23, | |
| 133552 | + /* 1530 */ 23, 56, 64, 22, 124, 26, 26, 64, 64, 23, | |
| 133491 | 133553 | /* 1540 */ 23, 23, 23, 11, 23, 22, 26, 23, 22, 24, |
| 133492 | - /* 1550 */ 1, 23, 22, 26, 122, 24, 23, 22, 15, 23, | |
| 133493 | - /* 1560 */ 23, 22, 251, 23, 122, 251, 251, 251, 251, 122, | |
| 133494 | - /* 1570 */ 122, | |
| 133554 | + /* 1550 */ 1, 23, 22, 26, 251, 24, 23, 22, 122, 23, | |
| 133555 | + /* 1560 */ 23, 22, 15, 122, 122, 122, 23, | |
| 133495 | 133556 | }; |
| 133496 | -#define YY_SHIFT_USE_DFLT (1571) | |
| 133557 | +#define YY_SHIFT_USE_DFLT (1567) | |
| 133497 | 133558 | #define YY_SHIFT_COUNT (455) |
| 133498 | 133559 | #define YY_SHIFT_MIN (-94) |
| 133499 | 133560 | #define YY_SHIFT_MAX (1549) |
| 133500 | 133561 | static const short yy_shift_ofst[] = { |
| 133501 | 133562 | /* 0 */ 40, 599, 904, 612, 760, 760, 760, 760, 725, -19, |
| @@ -133507,132 +133568,132 @@ | ||
| 133507 | 133568 | /* 60 */ 760, 760, 760, 760, 760, 760, 760, 760, 760, 760, |
| 133508 | 133569 | /* 70 */ 760, 760, 760, 760, 760, 760, 760, 760, 760, 760, |
| 133509 | 133570 | /* 80 */ 760, 760, 760, 760, 760, 760, 760, 760, 760, 760, |
| 133510 | 133571 | /* 90 */ 856, 760, 760, 760, 760, 760, 760, 760, 760, 760, |
| 133511 | 133572 | /* 100 */ 760, 760, 760, 760, 987, 746, 746, 746, 746, 746, |
| 133512 | - /* 110 */ 801, 23, 32, 924, 963, 984, 954, 954, 924, 73, | |
| 133513 | - /* 120 */ 113, -51, 1571, 1571, 1571, 536, 536, 536, 99, 99, | |
| 133514 | - /* 130 */ 813, 813, 667, 205, 240, 924, 924, 924, 924, 924, | |
| 133515 | - /* 140 */ 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, | |
| 133516 | - /* 150 */ 924, 924, 924, 924, 924, 332, 983, 422, 422, 113, | |
| 133517 | - /* 160 */ 30, 30, 30, 30, 30, 30, 1571, 1571, 1571, 915, | |
| 133518 | - /* 170 */ -94, -94, 384, 613, 828, 420, 765, 804, 851, 924, | |
| 133519 | - /* 180 */ 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, | |
| 133520 | - /* 190 */ 924, 924, 924, 924, 924, 672, 672, 672, 924, 924, | |
| 133521 | - /* 200 */ 657, 924, 924, 924, -18, 924, 924, 995, 924, 924, | |
| 133522 | - /* 210 */ 924, 924, 924, 924, 924, 924, 924, 924, 772, 1179, | |
| 133523 | - /* 220 */ 712, 712, 712, 926, 45, 769, 1257, 1153, 418, 418, | |
| 133524 | - /* 230 */ 569, 1153, 569, 1175, 607, 663, 1135, 418, 693, 1135, | |
| 133525 | - /* 240 */ 1135, 1177, 1139, 1208, 1286, 1233, 1233, 1290, 1290, 1233, | |
| 133526 | - /* 250 */ 1344, 1341, 1239, 1352, 1352, 1352, 1352, 1233, 1354, 1239, | |
| 133527 | - /* 260 */ 1344, 1341, 1341, 1239, 1233, 1354, 1240, 1304, 1233, 1233, | |
| 133528 | - /* 270 */ 1354, 1362, 1233, 1354, 1233, 1354, 1362, 1293, 1293, 1293, | |
| 133529 | - /* 280 */ 1321, 1362, 1293, 1301, 1293, 1321, 1293, 1293, 1291, 1302, | |
| 133530 | - /* 290 */ 1291, 1302, 1291, 1302, 1291, 1302, 1233, 1392, 1233, 1278, | |
| 133531 | - /* 300 */ 1362, 1368, 1368, 1362, 1294, 1296, 1298, 1300, 1239, 1403, | |
| 133532 | - /* 310 */ 1406, 1416, 1416, 1433, 1433, 1433, 1433, 1571, 1571, 1571, | |
| 133533 | - /* 320 */ 1571, 1571, 1571, 1571, 1571, 519, 988, 1205, 1213, 104, | |
| 133534 | - /* 330 */ 947, 1058, 1246, 1226, 1247, 1248, 1256, 1262, 1266, 1267, | |
| 133535 | - /* 340 */ 853, 1194, 1289, 1190, 1280, 1282, 1220, 1284, 1166, 1180, | |
| 133536 | - /* 350 */ 1288, 1225, 943, 1437, 1440, 1425, 1310, 1438, 1361, 1441, | |
| 133537 | - /* 360 */ 1435, 1436, 1336, 1330, 1351, 1345, 1449, 1348, 1459, 1475, | |
| 133538 | - /* 370 */ 1355, 1346, 1443, 1444, 1445, 1446, 1374, 1430, 1423, 1366, | |
| 133539 | - /* 380 */ 1488, 1485, 1469, 1385, 1353, 1414, 1470, 1415, 1410, 1426, | |
| 133540 | - /* 390 */ 1393, 1477, 1479, 1483, 1391, 1399, 1484, 1428, 1486, 1487, | |
| 133541 | - /* 400 */ 1482, 1489, 1431, 1455, 1494, 1439, 1451, 1497, 1498, 1499, | |
| 133542 | - /* 410 */ 1491, 1407, 1502, 1503, 1505, 1504, 1409, 1506, 1509, 1472, | |
| 133543 | - /* 420 */ 1461, 1511, 1411, 1508, 1473, 1510, 1474, 1516, 1508, 1517, | |
| 133573 | + /* 110 */ 801, 23, 32, 949, 961, 979, 964, 964, 949, 73, | |
| 133574 | + /* 120 */ 113, -51, 1567, 1567, 1567, 536, 536, 536, 99, 99, | |
| 133575 | + /* 130 */ 813, 813, 667, 205, 240, 949, 949, 949, 949, 949, | |
| 133576 | + /* 140 */ 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, | |
| 133577 | + /* 150 */ 949, 949, 949, 949, 949, 332, 1011, 422, 422, 113, | |
| 133578 | + /* 160 */ 30, 30, 30, 30, 30, 30, 1567, 1567, 1567, 922, | |
| 133579 | + /* 170 */ -94, -94, 384, 613, 828, 420, 765, 804, 851, 949, | |
| 133580 | + /* 180 */ 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, | |
| 133581 | + /* 190 */ 949, 949, 949, 949, 949, 672, 672, 672, 949, 949, | |
| 133582 | + /* 200 */ 657, 949, 949, 949, -18, 949, 949, 994, 949, 949, | |
| 133583 | + /* 210 */ 949, 949, 949, 949, 949, 949, 949, 949, 772, 1118, | |
| 133584 | + /* 220 */ 712, 712, 712, 810, 45, 769, 1219, 1133, 418, 418, | |
| 133585 | + /* 230 */ 569, 1133, 569, 830, 607, 663, 882, 418, 693, 882, | |
| 133586 | + /* 240 */ 882, 848, 1152, 1065, 1286, 1238, 1238, 1287, 1287, 1238, | |
| 133587 | + /* 250 */ 1344, 1341, 1239, 1353, 1353, 1353, 1353, 1238, 1355, 1239, | |
| 133588 | + /* 260 */ 1344, 1341, 1341, 1239, 1238, 1355, 1243, 1312, 1238, 1238, | |
| 133589 | + /* 270 */ 1355, 1370, 1238, 1355, 1238, 1355, 1370, 1290, 1290, 1290, | |
| 133590 | + /* 280 */ 1327, 1370, 1290, 1301, 1290, 1327, 1290, 1290, 1284, 1304, | |
| 133591 | + /* 290 */ 1284, 1304, 1284, 1304, 1284, 1304, 1238, 1391, 1238, 1280, | |
| 133592 | + /* 300 */ 1370, 1366, 1366, 1370, 1302, 1308, 1310, 1309, 1239, 1414, | |
| 133593 | + /* 310 */ 1416, 1431, 1431, 1440, 1440, 1440, 1440, 1567, 1567, 1567, | |
| 133594 | + /* 320 */ 1567, 1567, 1567, 1567, 1567, 519, 978, 1210, 1225, 104, | |
| 133595 | + /* 330 */ 1141, 1189, 1246, 1248, 1251, 1252, 1253, 1257, 1258, 1273, | |
| 133596 | + /* 340 */ 1003, 1187, 1293, 1170, 1272, 1279, 1234, 1281, 1176, 1177, | |
| 133597 | + /* 350 */ 1289, 1242, 1195, 1453, 1455, 1437, 1319, 1447, 1369, 1452, | |
| 133598 | + /* 360 */ 1446, 1448, 1352, 1345, 1364, 1354, 1458, 1356, 1463, 1479, | |
| 133599 | + /* 370 */ 1359, 1357, 1449, 1450, 1454, 1456, 1372, 1428, 1421, 1367, | |
| 133600 | + /* 380 */ 1489, 1487, 1472, 1388, 1358, 1417, 1470, 1419, 1413, 1429, | |
| 133601 | + /* 390 */ 1395, 1480, 1483, 1486, 1394, 1402, 1488, 1430, 1490, 1491, | |
| 133602 | + /* 400 */ 1485, 1492, 1432, 1457, 1494, 1438, 1451, 1495, 1497, 1498, | |
| 133603 | + /* 410 */ 1496, 1407, 1502, 1503, 1505, 1499, 1406, 1506, 1507, 1475, | |
| 133604 | + /* 420 */ 1468, 1511, 1410, 1509, 1473, 1510, 1474, 1516, 1509, 1517, | |
| 133544 | 133605 | /* 430 */ 1518, 1519, 1520, 1521, 1523, 1532, 1524, 1526, 1525, 1527, |
| 133545 | - /* 440 */ 1528, 1530, 1531, 1527, 1533, 1535, 1536, 1537, 1539, 1432, | |
| 133546 | - /* 450 */ 1442, 1447, 1448, 1540, 1543, 1549, | |
| 133606 | + /* 440 */ 1528, 1530, 1531, 1527, 1533, 1535, 1536, 1537, 1539, 1436, | |
| 133607 | + /* 450 */ 1441, 1442, 1443, 1543, 1547, 1549, | |
| 133547 | 133608 | }; |
| 133548 | 133609 | #define YY_REDUCE_USE_DFLT (-130) |
| 133549 | 133610 | #define YY_REDUCE_COUNT (324) |
| 133550 | 133611 | #define YY_REDUCE_MIN (-129) |
| 133551 | -#define YY_REDUCE_MAX (1307) | |
| 133612 | +#define YY_REDUCE_MAX (1300) | |
| 133552 | 133613 | static const short yy_reduce_ofst[] = { |
| 133553 | 133614 | /* 0 */ -29, 566, 525, 605, -49, 307, 491, 533, 668, 435, |
| 133554 | - /* 10 */ 601, 644, 148, 747, 783, 786, 419, 788, 795, 826, | |
| 133555 | - /* 20 */ 454, 775, 830, 495, 824, 848, 76, 76, 76, 76, | |
| 133615 | + /* 10 */ 601, 644, 148, 747, 786, 795, 419, 788, 827, 790, | |
| 133616 | + /* 20 */ 454, 832, 889, 495, 824, 734, 76, 76, 76, 76, | |
| 133556 | 133617 | /* 30 */ 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, |
| 133557 | 133618 | /* 40 */ 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, |
| 133558 | - /* 50 */ 76, 76, 76, 76, 76, 76, 76, 76, 890, 901, | |
| 133559 | - /* 60 */ 912, 917, 920, 925, 927, 929, 936, 952, 958, 960, | |
| 133560 | - /* 70 */ 962, 964, 967, 969, 971, 974, 977, 986, 993, 996, | |
| 133561 | - /* 80 */ 999, 1002, 1004, 1008, 1010, 1012, 1015, 1021, 1026, 1034, | |
| 133562 | - /* 90 */ 1037, 1039, 1043, 1045, 1048, 1050, 1052, 1061, 1067, 1074, | |
| 133563 | - /* 100 */ 1077, 1079, 1085, 1089, 76, 76, 76, 76, 76, 76, | |
| 133564 | - /* 110 */ 76, 76, 76, 865, 36, 523, 235, 416, 782, 76, | |
| 133619 | + /* 50 */ 76, 76, 76, 76, 76, 76, 76, 76, 783, 898, | |
| 133620 | + /* 60 */ 905, 907, 911, 921, 933, 936, 940, 943, 947, 950, | |
| 133621 | + /* 70 */ 952, 955, 958, 962, 965, 969, 974, 977, 980, 984, | |
| 133622 | + /* 80 */ 988, 991, 993, 996, 999, 1002, 1006, 1010, 1018, 1021, | |
| 133623 | + /* 90 */ 1024, 1028, 1032, 1034, 1036, 1040, 1046, 1051, 1058, 1062, | |
| 133624 | + /* 100 */ 1064, 1068, 1070, 1073, 76, 76, 76, 76, 76, 76, | |
| 133625 | + /* 110 */ 76, 76, 76, 855, 36, 523, 235, 416, 777, 76, | |
| 133565 | 133626 | /* 120 */ 278, 76, 76, 76, 76, 700, 700, 700, 150, 220, |
| 133566 | 133627 | /* 130 */ 147, 217, 221, 306, 306, 611, 5, 535, 556, 620, |
| 133567 | - /* 140 */ 704, 720, 784, 116, 789, 349, 889, 894, 404, 953, | |
| 133568 | - /* 150 */ 968, -129, 975, 492, 62, 722, 919, 763, 928, 957, | |
| 133569 | - /* 160 */ 994, 1080, 1081, 1082, 1090, 1091, 872, 1056, 557, 57, | |
| 133628 | + /* 140 */ 720, 872, 897, 116, 864, 349, 1035, 1037, 404, 1047, | |
| 133629 | + /* 150 */ 992, -129, 1050, 492, 62, 722, 879, 1072, 1089, 808, | |
| 133630 | + /* 160 */ 1066, 1094, 1095, 1096, 1097, 1098, 776, 1054, 557, 57, | |
| 133570 | 133631 | /* 170 */ 112, 131, 167, 182, 250, 272, 291, 331, 364, 438, |
| 133571 | - /* 180 */ 497, 517, 591, 653, 684, 690, 739, 791, 867, 871, | |
| 133572 | - /* 190 */ 970, 1062, 1107, 1132, 1152, 355, 819, 886, 1001, 1163, | |
| 133573 | - /* 200 */ 661, 1164, 1167, 1168, 861, 1169, 1171, 1017, 1172, 1173, | |
| 133574 | - /* 210 */ 1174, 250, 1176, 1178, 1181, 1182, 1183, 1184, 1084, 1094, | |
| 133575 | - /* 220 */ 1119, 1121, 1122, 661, 1140, 1141, 1188, 1142, 1126, 1127, | |
| 133576 | - /* 230 */ 1103, 1143, 1106, 1170, 1165, 1185, 1186, 1133, 1123, 1187, | |
| 133577 | - /* 240 */ 1189, 1148, 1154, 1196, 1111, 1197, 1198, 1118, 1120, 1204, | |
| 133578 | - /* 250 */ 1147, 1191, 1192, 1193, 1195, 1199, 1200, 1212, 1215, 1201, | |
| 133579 | - /* 260 */ 1155, 1206, 1207, 1202, 1217, 1216, 1145, 1144, 1223, 1224, | |
| 133580 | - /* 270 */ 1228, 1211, 1230, 1232, 1235, 1241, 1221, 1227, 1231, 1234, | |
| 133581 | - /* 280 */ 1222, 1229, 1236, 1237, 1238, 1242, 1243, 1244, 1203, 1210, | |
| 133582 | - /* 290 */ 1214, 1218, 1219, 1245, 1249, 1251, 1252, 1250, 1261, 1253, | |
| 133583 | - /* 300 */ 1254, 1209, 1255, 1259, 1258, 1260, 1264, 1268, 1270, 1272, | |
| 133584 | - /* 310 */ 1276, 1287, 1292, 1295, 1297, 1299, 1303, 1263, 1265, 1269, | |
| 133585 | - /* 320 */ 1277, 1279, 1271, 1273, 1307, | |
| 133632 | + /* 180 */ 497, 517, 591, 653, 690, 739, 775, 798, 892, 908, | |
| 133633 | + /* 190 */ 924, 930, 1015, 1063, 1069, 355, 784, 799, 981, 1101, | |
| 133634 | + /* 200 */ 926, 1151, 1161, 1162, 945, 1164, 1166, 1128, 1168, 1171, | |
| 133635 | + /* 210 */ 1172, 250, 1173, 1174, 1175, 1178, 1180, 1181, 1088, 1102, | |
| 133636 | + /* 220 */ 1119, 1124, 1126, 926, 1131, 1139, 1188, 1140, 1129, 1130, | |
| 133637 | + /* 230 */ 1103, 1144, 1107, 1179, 1156, 1167, 1182, 1134, 1122, 1183, | |
| 133638 | + /* 240 */ 1184, 1150, 1153, 1197, 1111, 1202, 1203, 1123, 1125, 1205, | |
| 133639 | + /* 250 */ 1147, 1185, 1169, 1186, 1190, 1191, 1192, 1213, 1217, 1193, | |
| 133640 | + /* 260 */ 1157, 1196, 1198, 1194, 1220, 1218, 1145, 1154, 1229, 1231, | |
| 133641 | + /* 270 */ 1233, 1216, 1237, 1240, 1241, 1244, 1222, 1227, 1230, 1232, | |
| 133642 | + /* 280 */ 1223, 1235, 1236, 1245, 1249, 1226, 1250, 1254, 1199, 1201, | |
| 133643 | + /* 290 */ 1204, 1207, 1209, 1211, 1214, 1212, 1255, 1208, 1259, 1215, | |
| 133644 | + /* 300 */ 1256, 1200, 1206, 1260, 1247, 1261, 1263, 1262, 1266, 1278, | |
| 133645 | + /* 310 */ 1282, 1292, 1294, 1297, 1298, 1299, 1300, 1221, 1224, 1228, | |
| 133646 | + /* 320 */ 1288, 1291, 1276, 1277, 1295, | |
| 133586 | 133647 | }; |
| 133587 | 133648 | static const YYACTIONTYPE yy_default[] = { |
| 133588 | - /* 0 */ 1278, 1268, 1268, 1268, 1200, 1200, 1200, 1200, 1268, 1094, | |
| 133589 | - /* 10 */ 1123, 1123, 1252, 1329, 1329, 1329, 1329, 1329, 1329, 1199, | |
| 133590 | - /* 20 */ 1329, 1329, 1329, 1329, 1268, 1098, 1129, 1329, 1329, 1329, | |
| 133591 | - /* 30 */ 1329, 1201, 1202, 1329, 1329, 1329, 1251, 1253, 1139, 1138, | |
| 133592 | - /* 40 */ 1137, 1136, 1234, 1110, 1134, 1127, 1131, 1201, 1195, 1196, | |
| 133593 | - /* 50 */ 1194, 1198, 1202, 1329, 1130, 1164, 1179, 1163, 1329, 1329, | |
| 133594 | - /* 60 */ 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, | |
| 133595 | - /* 70 */ 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, | |
| 133596 | - /* 80 */ 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, | |
| 133597 | - /* 90 */ 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, | |
| 133598 | - /* 100 */ 1329, 1329, 1329, 1329, 1173, 1178, 1185, 1177, 1174, 1166, | |
| 133599 | - /* 110 */ 1165, 1167, 1168, 1329, 1017, 1065, 1329, 1329, 1329, 1169, | |
| 133600 | - /* 120 */ 1329, 1170, 1182, 1181, 1180, 1259, 1286, 1285, 1329, 1329, | |
| 133601 | - /* 130 */ 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, | |
| 133602 | - /* 140 */ 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, | |
| 133603 | - /* 150 */ 1329, 1329, 1329, 1329, 1329, 1278, 1268, 1023, 1023, 1329, | |
| 133604 | - /* 160 */ 1268, 1268, 1268, 1268, 1268, 1268, 1264, 1098, 1089, 1329, | |
| 133605 | - /* 170 */ 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, | |
| 133606 | - /* 180 */ 1256, 1254, 1329, 1215, 1329, 1329, 1329, 1329, 1329, 1329, | |
| 133607 | - /* 190 */ 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, | |
| 133608 | - /* 200 */ 1329, 1329, 1329, 1329, 1094, 1329, 1329, 1329, 1329, 1329, | |
| 133609 | - /* 210 */ 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1280, 1329, 1229, | |
| 133610 | - /* 220 */ 1094, 1094, 1094, 1096, 1078, 1088, 1002, 1133, 1112, 1112, | |
| 133611 | - /* 230 */ 1318, 1133, 1318, 1040, 1300, 1037, 1123, 1112, 1197, 1123, | |
| 133612 | - /* 240 */ 1123, 1095, 1088, 1329, 1321, 1103, 1103, 1320, 1320, 1103, | |
| 133613 | - /* 250 */ 1144, 1068, 1133, 1074, 1074, 1074, 1074, 1103, 1014, 1133, | |
| 133614 | - /* 260 */ 1144, 1068, 1068, 1133, 1103, 1014, 1233, 1315, 1103, 1103, | |
| 133615 | - /* 270 */ 1014, 1208, 1103, 1014, 1103, 1014, 1208, 1066, 1066, 1066, | |
| 133616 | - /* 280 */ 1055, 1208, 1066, 1040, 1066, 1055, 1066, 1066, 1116, 1111, | |
| 133617 | - /* 290 */ 1116, 1111, 1116, 1111, 1116, 1111, 1103, 1203, 1103, 1329, | |
| 133618 | - /* 300 */ 1208, 1212, 1212, 1208, 1128, 1117, 1126, 1124, 1133, 1020, | |
| 133619 | - /* 310 */ 1058, 1283, 1283, 1279, 1279, 1279, 1279, 1326, 1326, 1264, | |
| 133620 | - /* 320 */ 1295, 1295, 1042, 1042, 1295, 1329, 1329, 1329, 1329, 1329, | |
| 133621 | - /* 330 */ 1329, 1290, 1329, 1217, 1329, 1329, 1329, 1329, 1329, 1329, | |
| 133622 | - /* 340 */ 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, | |
| 133623 | - /* 350 */ 1329, 1329, 1150, 1329, 998, 1261, 1329, 1329, 1260, 1329, | |
| 133624 | - /* 360 */ 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, | |
| 133625 | - /* 370 */ 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1317, | |
| 133626 | - /* 380 */ 1329, 1329, 1329, 1329, 1329, 1329, 1232, 1231, 1329, 1329, | |
| 133627 | - /* 390 */ 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, | |
| 133628 | - /* 400 */ 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, | |
| 133629 | - /* 410 */ 1329, 1080, 1329, 1329, 1329, 1304, 1329, 1329, 1329, 1329, | |
| 133630 | - /* 420 */ 1329, 1329, 1329, 1125, 1329, 1118, 1329, 1329, 1308, 1329, | |
| 133631 | - /* 430 */ 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1270, | |
| 133632 | - /* 440 */ 1329, 1329, 1329, 1269, 1329, 1329, 1329, 1329, 1329, 1152, | |
| 133633 | - /* 450 */ 1329, 1151, 1155, 1329, 1008, 1329, | |
| 133649 | + /* 0 */ 1281, 1271, 1271, 1271, 1203, 1203, 1203, 1203, 1271, 1096, | |
| 133650 | + /* 10 */ 1125, 1125, 1255, 1332, 1332, 1332, 1332, 1332, 1332, 1202, | |
| 133651 | + /* 20 */ 1332, 1332, 1332, 1332, 1271, 1100, 1131, 1332, 1332, 1332, | |
| 133652 | + /* 30 */ 1332, 1204, 1205, 1332, 1332, 1332, 1254, 1256, 1141, 1140, | |
| 133653 | + /* 40 */ 1139, 1138, 1237, 1112, 1136, 1129, 1133, 1204, 1198, 1199, | |
| 133654 | + /* 50 */ 1197, 1201, 1205, 1332, 1132, 1167, 1182, 1166, 1332, 1332, | |
| 133655 | + /* 60 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, | |
| 133656 | + /* 70 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, | |
| 133657 | + /* 80 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, | |
| 133658 | + /* 90 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, | |
| 133659 | + /* 100 */ 1332, 1332, 1332, 1332, 1176, 1181, 1188, 1180, 1177, 1169, | |
| 133660 | + /* 110 */ 1168, 1170, 1171, 1332, 1019, 1067, 1332, 1332, 1332, 1172, | |
| 133661 | + /* 120 */ 1332, 1173, 1185, 1184, 1183, 1262, 1289, 1288, 1332, 1332, | |
| 133662 | + /* 130 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, | |
| 133663 | + /* 140 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, | |
| 133664 | + /* 150 */ 1332, 1332, 1332, 1332, 1332, 1281, 1271, 1025, 1025, 1332, | |
| 133665 | + /* 160 */ 1271, 1271, 1271, 1271, 1271, 1271, 1267, 1100, 1091, 1332, | |
| 133666 | + /* 170 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, | |
| 133667 | + /* 180 */ 1259, 1257, 1332, 1218, 1332, 1332, 1332, 1332, 1332, 1332, | |
| 133668 | + /* 190 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, | |
| 133669 | + /* 200 */ 1332, 1332, 1332, 1332, 1096, 1332, 1332, 1332, 1332, 1332, | |
| 133670 | + /* 210 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1283, 1332, 1232, | |
| 133671 | + /* 220 */ 1096, 1096, 1096, 1098, 1080, 1090, 1004, 1135, 1114, 1114, | |
| 133672 | + /* 230 */ 1321, 1135, 1321, 1042, 1303, 1039, 1125, 1114, 1200, 1125, | |
| 133673 | + /* 240 */ 1125, 1097, 1090, 1332, 1324, 1105, 1105, 1323, 1323, 1105, | |
| 133674 | + /* 250 */ 1146, 1070, 1135, 1076, 1076, 1076, 1076, 1105, 1016, 1135, | |
| 133675 | + /* 260 */ 1146, 1070, 1070, 1135, 1105, 1016, 1236, 1318, 1105, 1105, | |
| 133676 | + /* 270 */ 1016, 1211, 1105, 1016, 1105, 1016, 1211, 1068, 1068, 1068, | |
| 133677 | + /* 280 */ 1057, 1211, 1068, 1042, 1068, 1057, 1068, 1068, 1118, 1113, | |
| 133678 | + /* 290 */ 1118, 1113, 1118, 1113, 1118, 1113, 1105, 1206, 1105, 1332, | |
| 133679 | + /* 300 */ 1211, 1215, 1215, 1211, 1130, 1119, 1128, 1126, 1135, 1022, | |
| 133680 | + /* 310 */ 1060, 1286, 1286, 1282, 1282, 1282, 1282, 1329, 1329, 1267, | |
| 133681 | + /* 320 */ 1298, 1298, 1044, 1044, 1298, 1332, 1332, 1332, 1332, 1332, | |
| 133682 | + /* 330 */ 1332, 1293, 1332, 1220, 1332, 1332, 1332, 1332, 1332, 1332, | |
| 133683 | + /* 340 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, | |
| 133684 | + /* 350 */ 1332, 1332, 1152, 1332, 1000, 1264, 1332, 1332, 1263, 1332, | |
| 133685 | + /* 360 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, | |
| 133686 | + /* 370 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1320, | |
| 133687 | + /* 380 */ 1332, 1332, 1332, 1332, 1332, 1332, 1235, 1234, 1332, 1332, | |
| 133688 | + /* 390 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, | |
| 133689 | + /* 400 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, | |
| 133690 | + /* 410 */ 1332, 1082, 1332, 1332, 1332, 1307, 1332, 1332, 1332, 1332, | |
| 133691 | + /* 420 */ 1332, 1332, 1332, 1127, 1332, 1120, 1332, 1332, 1311, 1332, | |
| 133692 | + /* 430 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1273, | |
| 133693 | + /* 440 */ 1332, 1332, 1332, 1272, 1332, 1332, 1332, 1332, 1332, 1154, | |
| 133694 | + /* 450 */ 1332, 1153, 1157, 1332, 1010, 1332, | |
| 133634 | 133695 | }; |
| 133635 | 133696 | /********** End of lemon-generated parsing tables *****************************/ |
| 133636 | 133697 | |
| 133637 | 133698 | /* The next table maps tokens (terminal symbols) into fallback tokens. |
| 133638 | 133699 | ** If a construct like the following: |
| @@ -133862,11 +133923,11 @@ | ||
| 133862 | 133923 | "DEFERRABLE", "FOREIGN", "DROP", "UNION", |
| 133863 | 133924 | "ALL", "EXCEPT", "INTERSECT", "SELECT", |
| 133864 | 133925 | "VALUES", "DISTINCT", "DOT", "FROM", |
| 133865 | 133926 | "JOIN", "USING", "ORDER", "GROUP", |
| 133866 | 133927 | "HAVING", "LIMIT", "WHERE", "INTO", |
| 133867 | - "INTEGER", "FLOAT", "BLOB", "VARIABLE", | |
| 133928 | + "FLOAT", "BLOB", "INTEGER", "VARIABLE", | |
| 133868 | 133929 | "CASE", "WHEN", "THEN", "ELSE", |
| 133869 | 133930 | "INDEX", "ALTER", "ADD", "error", |
| 133870 | 133931 | "input", "cmdlist", "ecmd", "explain", |
| 133871 | 133932 | "cmdx", "cmd", "transtype", "trans_opt", |
| 133872 | 133933 | "nm", "savepoint_opt", "create_table", "create_table_args", |
| @@ -134055,185 +134116,186 @@ | ||
| 134055 | 134116 | /* 151 */ "term ::= NULL", |
| 134056 | 134117 | /* 152 */ "expr ::= ID|INDEXED", |
| 134057 | 134118 | /* 153 */ "expr ::= JOIN_KW", |
| 134058 | 134119 | /* 154 */ "expr ::= nm DOT nm", |
| 134059 | 134120 | /* 155 */ "expr ::= nm DOT nm DOT nm", |
| 134060 | - /* 156 */ "term ::= INTEGER|FLOAT|BLOB", | |
| 134121 | + /* 156 */ "term ::= FLOAT|BLOB", | |
| 134061 | 134122 | /* 157 */ "term ::= STRING", |
| 134062 | - /* 158 */ "expr ::= VARIABLE", | |
| 134063 | - /* 159 */ "expr ::= expr COLLATE ID|STRING", | |
| 134064 | - /* 160 */ "expr ::= CAST LP expr AS typetoken RP", | |
| 134065 | - /* 161 */ "expr ::= ID|INDEXED LP distinct exprlist RP", | |
| 134066 | - /* 162 */ "expr ::= ID|INDEXED LP STAR RP", | |
| 134067 | - /* 163 */ "term ::= CTIME_KW", | |
| 134068 | - /* 164 */ "expr ::= LP nexprlist COMMA expr RP", | |
| 134069 | - /* 165 */ "expr ::= expr AND expr", | |
| 134070 | - /* 166 */ "expr ::= expr OR expr", | |
| 134071 | - /* 167 */ "expr ::= expr LT|GT|GE|LE expr", | |
| 134072 | - /* 168 */ "expr ::= expr EQ|NE expr", | |
| 134073 | - /* 169 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr", | |
| 134074 | - /* 170 */ "expr ::= expr PLUS|MINUS expr", | |
| 134075 | - /* 171 */ "expr ::= expr STAR|SLASH|REM expr", | |
| 134076 | - /* 172 */ "expr ::= expr CONCAT expr", | |
| 134077 | - /* 173 */ "likeop ::= LIKE_KW|MATCH", | |
| 134078 | - /* 174 */ "likeop ::= NOT LIKE_KW|MATCH", | |
| 134079 | - /* 175 */ "expr ::= expr likeop expr", | |
| 134080 | - /* 176 */ "expr ::= expr likeop expr ESCAPE expr", | |
| 134081 | - /* 177 */ "expr ::= expr ISNULL|NOTNULL", | |
| 134082 | - /* 178 */ "expr ::= expr NOT NULL", | |
| 134083 | - /* 179 */ "expr ::= expr IS expr", | |
| 134084 | - /* 180 */ "expr ::= expr IS NOT expr", | |
| 134085 | - /* 181 */ "expr ::= NOT expr", | |
| 134086 | - /* 182 */ "expr ::= BITNOT expr", | |
| 134087 | - /* 183 */ "expr ::= MINUS expr", | |
| 134088 | - /* 184 */ "expr ::= PLUS expr", | |
| 134089 | - /* 185 */ "between_op ::= BETWEEN", | |
| 134090 | - /* 186 */ "between_op ::= NOT BETWEEN", | |
| 134091 | - /* 187 */ "expr ::= expr between_op expr AND expr", | |
| 134092 | - /* 188 */ "in_op ::= IN", | |
| 134093 | - /* 189 */ "in_op ::= NOT IN", | |
| 134094 | - /* 190 */ "expr ::= expr in_op LP exprlist RP", | |
| 134095 | - /* 191 */ "expr ::= LP select RP", | |
| 134096 | - /* 192 */ "expr ::= expr in_op LP select RP", | |
| 134097 | - /* 193 */ "expr ::= expr in_op nm dbnm paren_exprlist", | |
| 134098 | - /* 194 */ "expr ::= EXISTS LP select RP", | |
| 134099 | - /* 195 */ "expr ::= CASE case_operand case_exprlist case_else END", | |
| 134100 | - /* 196 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr", | |
| 134101 | - /* 197 */ "case_exprlist ::= WHEN expr THEN expr", | |
| 134102 | - /* 198 */ "case_else ::= ELSE expr", | |
| 134103 | - /* 199 */ "case_else ::=", | |
| 134104 | - /* 200 */ "case_operand ::= expr", | |
| 134105 | - /* 201 */ "case_operand ::=", | |
| 134106 | - /* 202 */ "exprlist ::=", | |
| 134107 | - /* 203 */ "nexprlist ::= nexprlist COMMA expr", | |
| 134108 | - /* 204 */ "nexprlist ::= expr", | |
| 134109 | - /* 205 */ "paren_exprlist ::=", | |
| 134110 | - /* 206 */ "paren_exprlist ::= LP exprlist RP", | |
| 134111 | - /* 207 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt", | |
| 134112 | - /* 208 */ "uniqueflag ::= UNIQUE", | |
| 134113 | - /* 209 */ "uniqueflag ::=", | |
| 134114 | - /* 210 */ "eidlist_opt ::=", | |
| 134115 | - /* 211 */ "eidlist_opt ::= LP eidlist RP", | |
| 134116 | - /* 212 */ "eidlist ::= eidlist COMMA nm collate sortorder", | |
| 134117 | - /* 213 */ "eidlist ::= nm collate sortorder", | |
| 134118 | - /* 214 */ "collate ::=", | |
| 134119 | - /* 215 */ "collate ::= COLLATE ID|STRING", | |
| 134120 | - /* 216 */ "cmd ::= DROP INDEX ifexists fullname", | |
| 134121 | - /* 217 */ "cmd ::= VACUUM", | |
| 134122 | - /* 218 */ "cmd ::= VACUUM nm", | |
| 134123 | - /* 219 */ "cmd ::= PRAGMA nm dbnm", | |
| 134124 | - /* 220 */ "cmd ::= PRAGMA nm dbnm EQ nmnum", | |
| 134125 | - /* 221 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP", | |
| 134126 | - /* 222 */ "cmd ::= PRAGMA nm dbnm EQ minus_num", | |
| 134127 | - /* 223 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP", | |
| 134128 | - /* 224 */ "plus_num ::= PLUS INTEGER|FLOAT", | |
| 134129 | - /* 225 */ "minus_num ::= MINUS INTEGER|FLOAT", | |
| 134130 | - /* 226 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END", | |
| 134131 | - /* 227 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause", | |
| 134132 | - /* 228 */ "trigger_time ::= BEFORE", | |
| 134133 | - /* 229 */ "trigger_time ::= AFTER", | |
| 134134 | - /* 230 */ "trigger_time ::= INSTEAD OF", | |
| 134135 | - /* 231 */ "trigger_time ::=", | |
| 134136 | - /* 232 */ "trigger_event ::= DELETE|INSERT", | |
| 134137 | - /* 233 */ "trigger_event ::= UPDATE", | |
| 134138 | - /* 234 */ "trigger_event ::= UPDATE OF idlist", | |
| 134139 | - /* 235 */ "when_clause ::=", | |
| 134140 | - /* 236 */ "when_clause ::= WHEN expr", | |
| 134141 | - /* 237 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI", | |
| 134142 | - /* 238 */ "trigger_cmd_list ::= trigger_cmd SEMI", | |
| 134143 | - /* 239 */ "trnm ::= nm DOT nm", | |
| 134144 | - /* 240 */ "tridxby ::= INDEXED BY nm", | |
| 134145 | - /* 241 */ "tridxby ::= NOT INDEXED", | |
| 134146 | - /* 242 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt", | |
| 134147 | - /* 243 */ "trigger_cmd ::= insert_cmd INTO trnm idlist_opt select", | |
| 134148 | - /* 244 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt", | |
| 134149 | - /* 245 */ "trigger_cmd ::= select", | |
| 134150 | - /* 246 */ "expr ::= RAISE LP IGNORE RP", | |
| 134151 | - /* 247 */ "expr ::= RAISE LP raisetype COMMA nm RP", | |
| 134152 | - /* 248 */ "raisetype ::= ROLLBACK", | |
| 134153 | - /* 249 */ "raisetype ::= ABORT", | |
| 134154 | - /* 250 */ "raisetype ::= FAIL", | |
| 134155 | - /* 251 */ "cmd ::= DROP TRIGGER ifexists fullname", | |
| 134156 | - /* 252 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", | |
| 134157 | - /* 253 */ "cmd ::= DETACH database_kw_opt expr", | |
| 134158 | - /* 254 */ "key_opt ::=", | |
| 134159 | - /* 255 */ "key_opt ::= KEY expr", | |
| 134160 | - /* 256 */ "cmd ::= REINDEX", | |
| 134161 | - /* 257 */ "cmd ::= REINDEX nm dbnm", | |
| 134162 | - /* 258 */ "cmd ::= ANALYZE", | |
| 134163 | - /* 259 */ "cmd ::= ANALYZE nm dbnm", | |
| 134164 | - /* 260 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", | |
| 134165 | - /* 261 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist", | |
| 134166 | - /* 262 */ "add_column_fullname ::= fullname", | |
| 134167 | - /* 263 */ "cmd ::= create_vtab", | |
| 134168 | - /* 264 */ "cmd ::= create_vtab LP vtabarglist RP", | |
| 134169 | - /* 265 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm", | |
| 134170 | - /* 266 */ "vtabarg ::=", | |
| 134171 | - /* 267 */ "vtabargtoken ::= ANY", | |
| 134172 | - /* 268 */ "vtabargtoken ::= lp anylist RP", | |
| 134173 | - /* 269 */ "lp ::= LP", | |
| 134174 | - /* 270 */ "with ::=", | |
| 134175 | - /* 271 */ "with ::= WITH wqlist", | |
| 134176 | - /* 272 */ "with ::= WITH RECURSIVE wqlist", | |
| 134177 | - /* 273 */ "wqlist ::= nm eidlist_opt AS LP select RP", | |
| 134178 | - /* 274 */ "wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP", | |
| 134179 | - /* 275 */ "input ::= cmdlist", | |
| 134180 | - /* 276 */ "cmdlist ::= cmdlist ecmd", | |
| 134181 | - /* 277 */ "cmdlist ::= ecmd", | |
| 134182 | - /* 278 */ "ecmd ::= SEMI", | |
| 134183 | - /* 279 */ "ecmd ::= explain cmdx SEMI", | |
| 134184 | - /* 280 */ "explain ::=", | |
| 134185 | - /* 281 */ "trans_opt ::=", | |
| 134186 | - /* 282 */ "trans_opt ::= TRANSACTION", | |
| 134187 | - /* 283 */ "trans_opt ::= TRANSACTION nm", | |
| 134188 | - /* 284 */ "savepoint_opt ::= SAVEPOINT", | |
| 134189 | - /* 285 */ "savepoint_opt ::=", | |
| 134190 | - /* 286 */ "cmd ::= create_table create_table_args", | |
| 134191 | - /* 287 */ "columnlist ::= columnlist COMMA columnname carglist", | |
| 134192 | - /* 288 */ "columnlist ::= columnname carglist", | |
| 134193 | - /* 289 */ "nm ::= ID|INDEXED", | |
| 134194 | - /* 290 */ "nm ::= STRING", | |
| 134195 | - /* 291 */ "nm ::= JOIN_KW", | |
| 134196 | - /* 292 */ "typetoken ::= typename", | |
| 134197 | - /* 293 */ "typename ::= ID|STRING", | |
| 134198 | - /* 294 */ "signed ::= plus_num", | |
| 134199 | - /* 295 */ "signed ::= minus_num", | |
| 134200 | - /* 296 */ "carglist ::= carglist ccons", | |
| 134201 | - /* 297 */ "carglist ::=", | |
| 134202 | - /* 298 */ "ccons ::= NULL onconf", | |
| 134203 | - /* 299 */ "conslist_opt ::= COMMA conslist", | |
| 134204 | - /* 300 */ "conslist ::= conslist tconscomma tcons", | |
| 134205 | - /* 301 */ "conslist ::= tcons", | |
| 134206 | - /* 302 */ "tconscomma ::=", | |
| 134207 | - /* 303 */ "defer_subclause_opt ::= defer_subclause", | |
| 134208 | - /* 304 */ "resolvetype ::= raisetype", | |
| 134209 | - /* 305 */ "selectnowith ::= oneselect", | |
| 134210 | - /* 306 */ "oneselect ::= values", | |
| 134211 | - /* 307 */ "sclp ::= selcollist COMMA", | |
| 134212 | - /* 308 */ "as ::= ID|STRING", | |
| 134213 | - /* 309 */ "expr ::= term", | |
| 134214 | - /* 310 */ "exprlist ::= nexprlist", | |
| 134215 | - /* 311 */ "nmnum ::= plus_num", | |
| 134216 | - /* 312 */ "nmnum ::= nm", | |
| 134217 | - /* 313 */ "nmnum ::= ON", | |
| 134218 | - /* 314 */ "nmnum ::= DELETE", | |
| 134219 | - /* 315 */ "nmnum ::= DEFAULT", | |
| 134220 | - /* 316 */ "plus_num ::= INTEGER|FLOAT", | |
| 134221 | - /* 317 */ "foreach_clause ::=", | |
| 134222 | - /* 318 */ "foreach_clause ::= FOR EACH ROW", | |
| 134223 | - /* 319 */ "trnm ::= nm", | |
| 134224 | - /* 320 */ "tridxby ::=", | |
| 134225 | - /* 321 */ "database_kw_opt ::= DATABASE", | |
| 134226 | - /* 322 */ "database_kw_opt ::=", | |
| 134227 | - /* 323 */ "kwcolumn_opt ::=", | |
| 134228 | - /* 324 */ "kwcolumn_opt ::= COLUMNKW", | |
| 134229 | - /* 325 */ "vtabarglist ::= vtabarg", | |
| 134230 | - /* 326 */ "vtabarglist ::= vtabarglist COMMA vtabarg", | |
| 134231 | - /* 327 */ "vtabarg ::= vtabarg vtabargtoken", | |
| 134232 | - /* 328 */ "anylist ::=", | |
| 134233 | - /* 329 */ "anylist ::= anylist LP anylist RP", | |
| 134234 | - /* 330 */ "anylist ::= anylist ANY", | |
| 134123 | + /* 158 */ "term ::= INTEGER", | |
| 134124 | + /* 159 */ "expr ::= VARIABLE", | |
| 134125 | + /* 160 */ "expr ::= expr COLLATE ID|STRING", | |
| 134126 | + /* 161 */ "expr ::= CAST LP expr AS typetoken RP", | |
| 134127 | + /* 162 */ "expr ::= ID|INDEXED LP distinct exprlist RP", | |
| 134128 | + /* 163 */ "expr ::= ID|INDEXED LP STAR RP", | |
| 134129 | + /* 164 */ "term ::= CTIME_KW", | |
| 134130 | + /* 165 */ "expr ::= LP nexprlist COMMA expr RP", | |
| 134131 | + /* 166 */ "expr ::= expr AND expr", | |
| 134132 | + /* 167 */ "expr ::= expr OR expr", | |
| 134133 | + /* 168 */ "expr ::= expr LT|GT|GE|LE expr", | |
| 134134 | + /* 169 */ "expr ::= expr EQ|NE expr", | |
| 134135 | + /* 170 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr", | |
| 134136 | + /* 171 */ "expr ::= expr PLUS|MINUS expr", | |
| 134137 | + /* 172 */ "expr ::= expr STAR|SLASH|REM expr", | |
| 134138 | + /* 173 */ "expr ::= expr CONCAT expr", | |
| 134139 | + /* 174 */ "likeop ::= LIKE_KW|MATCH", | |
| 134140 | + /* 175 */ "likeop ::= NOT LIKE_KW|MATCH", | |
| 134141 | + /* 176 */ "expr ::= expr likeop expr", | |
| 134142 | + /* 177 */ "expr ::= expr likeop expr ESCAPE expr", | |
| 134143 | + /* 178 */ "expr ::= expr ISNULL|NOTNULL", | |
| 134144 | + /* 179 */ "expr ::= expr NOT NULL", | |
| 134145 | + /* 180 */ "expr ::= expr IS expr", | |
| 134146 | + /* 181 */ "expr ::= expr IS NOT expr", | |
| 134147 | + /* 182 */ "expr ::= NOT expr", | |
| 134148 | + /* 183 */ "expr ::= BITNOT expr", | |
| 134149 | + /* 184 */ "expr ::= MINUS expr", | |
| 134150 | + /* 185 */ "expr ::= PLUS expr", | |
| 134151 | + /* 186 */ "between_op ::= BETWEEN", | |
| 134152 | + /* 187 */ "between_op ::= NOT BETWEEN", | |
| 134153 | + /* 188 */ "expr ::= expr between_op expr AND expr", | |
| 134154 | + /* 189 */ "in_op ::= IN", | |
| 134155 | + /* 190 */ "in_op ::= NOT IN", | |
| 134156 | + /* 191 */ "expr ::= expr in_op LP exprlist RP", | |
| 134157 | + /* 192 */ "expr ::= LP select RP", | |
| 134158 | + /* 193 */ "expr ::= expr in_op LP select RP", | |
| 134159 | + /* 194 */ "expr ::= expr in_op nm dbnm paren_exprlist", | |
| 134160 | + /* 195 */ "expr ::= EXISTS LP select RP", | |
| 134161 | + /* 196 */ "expr ::= CASE case_operand case_exprlist case_else END", | |
| 134162 | + /* 197 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr", | |
| 134163 | + /* 198 */ "case_exprlist ::= WHEN expr THEN expr", | |
| 134164 | + /* 199 */ "case_else ::= ELSE expr", | |
| 134165 | + /* 200 */ "case_else ::=", | |
| 134166 | + /* 201 */ "case_operand ::= expr", | |
| 134167 | + /* 202 */ "case_operand ::=", | |
| 134168 | + /* 203 */ "exprlist ::=", | |
| 134169 | + /* 204 */ "nexprlist ::= nexprlist COMMA expr", | |
| 134170 | + /* 205 */ "nexprlist ::= expr", | |
| 134171 | + /* 206 */ "paren_exprlist ::=", | |
| 134172 | + /* 207 */ "paren_exprlist ::= LP exprlist RP", | |
| 134173 | + /* 208 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt", | |
| 134174 | + /* 209 */ "uniqueflag ::= UNIQUE", | |
| 134175 | + /* 210 */ "uniqueflag ::=", | |
| 134176 | + /* 211 */ "eidlist_opt ::=", | |
| 134177 | + /* 212 */ "eidlist_opt ::= LP eidlist RP", | |
| 134178 | + /* 213 */ "eidlist ::= eidlist COMMA nm collate sortorder", | |
| 134179 | + /* 214 */ "eidlist ::= nm collate sortorder", | |
| 134180 | + /* 215 */ "collate ::=", | |
| 134181 | + /* 216 */ "collate ::= COLLATE ID|STRING", | |
| 134182 | + /* 217 */ "cmd ::= DROP INDEX ifexists fullname", | |
| 134183 | + /* 218 */ "cmd ::= VACUUM", | |
| 134184 | + /* 219 */ "cmd ::= VACUUM nm", | |
| 134185 | + /* 220 */ "cmd ::= PRAGMA nm dbnm", | |
| 134186 | + /* 221 */ "cmd ::= PRAGMA nm dbnm EQ nmnum", | |
| 134187 | + /* 222 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP", | |
| 134188 | + /* 223 */ "cmd ::= PRAGMA nm dbnm EQ minus_num", | |
| 134189 | + /* 224 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP", | |
| 134190 | + /* 225 */ "plus_num ::= PLUS INTEGER|FLOAT", | |
| 134191 | + /* 226 */ "minus_num ::= MINUS INTEGER|FLOAT", | |
| 134192 | + /* 227 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END", | |
| 134193 | + /* 228 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause", | |
| 134194 | + /* 229 */ "trigger_time ::= BEFORE", | |
| 134195 | + /* 230 */ "trigger_time ::= AFTER", | |
| 134196 | + /* 231 */ "trigger_time ::= INSTEAD OF", | |
| 134197 | + /* 232 */ "trigger_time ::=", | |
| 134198 | + /* 233 */ "trigger_event ::= DELETE|INSERT", | |
| 134199 | + /* 234 */ "trigger_event ::= UPDATE", | |
| 134200 | + /* 235 */ "trigger_event ::= UPDATE OF idlist", | |
| 134201 | + /* 236 */ "when_clause ::=", | |
| 134202 | + /* 237 */ "when_clause ::= WHEN expr", | |
| 134203 | + /* 238 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI", | |
| 134204 | + /* 239 */ "trigger_cmd_list ::= trigger_cmd SEMI", | |
| 134205 | + /* 240 */ "trnm ::= nm DOT nm", | |
| 134206 | + /* 241 */ "tridxby ::= INDEXED BY nm", | |
| 134207 | + /* 242 */ "tridxby ::= NOT INDEXED", | |
| 134208 | + /* 243 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt", | |
| 134209 | + /* 244 */ "trigger_cmd ::= insert_cmd INTO trnm idlist_opt select", | |
| 134210 | + /* 245 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt", | |
| 134211 | + /* 246 */ "trigger_cmd ::= select", | |
| 134212 | + /* 247 */ "expr ::= RAISE LP IGNORE RP", | |
| 134213 | + /* 248 */ "expr ::= RAISE LP raisetype COMMA nm RP", | |
| 134214 | + /* 249 */ "raisetype ::= ROLLBACK", | |
| 134215 | + /* 250 */ "raisetype ::= ABORT", | |
| 134216 | + /* 251 */ "raisetype ::= FAIL", | |
| 134217 | + /* 252 */ "cmd ::= DROP TRIGGER ifexists fullname", | |
| 134218 | + /* 253 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", | |
| 134219 | + /* 254 */ "cmd ::= DETACH database_kw_opt expr", | |
| 134220 | + /* 255 */ "key_opt ::=", | |
| 134221 | + /* 256 */ "key_opt ::= KEY expr", | |
| 134222 | + /* 257 */ "cmd ::= REINDEX", | |
| 134223 | + /* 258 */ "cmd ::= REINDEX nm dbnm", | |
| 134224 | + /* 259 */ "cmd ::= ANALYZE", | |
| 134225 | + /* 260 */ "cmd ::= ANALYZE nm dbnm", | |
| 134226 | + /* 261 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", | |
| 134227 | + /* 262 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist", | |
| 134228 | + /* 263 */ "add_column_fullname ::= fullname", | |
| 134229 | + /* 264 */ "cmd ::= create_vtab", | |
| 134230 | + /* 265 */ "cmd ::= create_vtab LP vtabarglist RP", | |
| 134231 | + /* 266 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm", | |
| 134232 | + /* 267 */ "vtabarg ::=", | |
| 134233 | + /* 268 */ "vtabargtoken ::= ANY", | |
| 134234 | + /* 269 */ "vtabargtoken ::= lp anylist RP", | |
| 134235 | + /* 270 */ "lp ::= LP", | |
| 134236 | + /* 271 */ "with ::=", | |
| 134237 | + /* 272 */ "with ::= WITH wqlist", | |
| 134238 | + /* 273 */ "with ::= WITH RECURSIVE wqlist", | |
| 134239 | + /* 274 */ "wqlist ::= nm eidlist_opt AS LP select RP", | |
| 134240 | + /* 275 */ "wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP", | |
| 134241 | + /* 276 */ "input ::= cmdlist", | |
| 134242 | + /* 277 */ "cmdlist ::= cmdlist ecmd", | |
| 134243 | + /* 278 */ "cmdlist ::= ecmd", | |
| 134244 | + /* 279 */ "ecmd ::= SEMI", | |
| 134245 | + /* 280 */ "ecmd ::= explain cmdx SEMI", | |
| 134246 | + /* 281 */ "explain ::=", | |
| 134247 | + /* 282 */ "trans_opt ::=", | |
| 134248 | + /* 283 */ "trans_opt ::= TRANSACTION", | |
| 134249 | + /* 284 */ "trans_opt ::= TRANSACTION nm", | |
| 134250 | + /* 285 */ "savepoint_opt ::= SAVEPOINT", | |
| 134251 | + /* 286 */ "savepoint_opt ::=", | |
| 134252 | + /* 287 */ "cmd ::= create_table create_table_args", | |
| 134253 | + /* 288 */ "columnlist ::= columnlist COMMA columnname carglist", | |
| 134254 | + /* 289 */ "columnlist ::= columnname carglist", | |
| 134255 | + /* 290 */ "nm ::= ID|INDEXED", | |
| 134256 | + /* 291 */ "nm ::= STRING", | |
| 134257 | + /* 292 */ "nm ::= JOIN_KW", | |
| 134258 | + /* 293 */ "typetoken ::= typename", | |
| 134259 | + /* 294 */ "typename ::= ID|STRING", | |
| 134260 | + /* 295 */ "signed ::= plus_num", | |
| 134261 | + /* 296 */ "signed ::= minus_num", | |
| 134262 | + /* 297 */ "carglist ::= carglist ccons", | |
| 134263 | + /* 298 */ "carglist ::=", | |
| 134264 | + /* 299 */ "ccons ::= NULL onconf", | |
| 134265 | + /* 300 */ "conslist_opt ::= COMMA conslist", | |
| 134266 | + /* 301 */ "conslist ::= conslist tconscomma tcons", | |
| 134267 | + /* 302 */ "conslist ::= tcons", | |
| 134268 | + /* 303 */ "tconscomma ::=", | |
| 134269 | + /* 304 */ "defer_subclause_opt ::= defer_subclause", | |
| 134270 | + /* 305 */ "resolvetype ::= raisetype", | |
| 134271 | + /* 306 */ "selectnowith ::= oneselect", | |
| 134272 | + /* 307 */ "oneselect ::= values", | |
| 134273 | + /* 308 */ "sclp ::= selcollist COMMA", | |
| 134274 | + /* 309 */ "as ::= ID|STRING", | |
| 134275 | + /* 310 */ "expr ::= term", | |
| 134276 | + /* 311 */ "exprlist ::= nexprlist", | |
| 134277 | + /* 312 */ "nmnum ::= plus_num", | |
| 134278 | + /* 313 */ "nmnum ::= nm", | |
| 134279 | + /* 314 */ "nmnum ::= ON", | |
| 134280 | + /* 315 */ "nmnum ::= DELETE", | |
| 134281 | + /* 316 */ "nmnum ::= DEFAULT", | |
| 134282 | + /* 317 */ "plus_num ::= INTEGER|FLOAT", | |
| 134283 | + /* 318 */ "foreach_clause ::=", | |
| 134284 | + /* 319 */ "foreach_clause ::= FOR EACH ROW", | |
| 134285 | + /* 320 */ "trnm ::= nm", | |
| 134286 | + /* 321 */ "tridxby ::=", | |
| 134287 | + /* 322 */ "database_kw_opt ::= DATABASE", | |
| 134288 | + /* 323 */ "database_kw_opt ::=", | |
| 134289 | + /* 324 */ "kwcolumn_opt ::=", | |
| 134290 | + /* 325 */ "kwcolumn_opt ::= COLUMNKW", | |
| 134291 | + /* 326 */ "vtabarglist ::= vtabarg", | |
| 134292 | + /* 327 */ "vtabarglist ::= vtabarglist COMMA vtabarg", | |
| 134293 | + /* 328 */ "vtabarg ::= vtabarg vtabargtoken", | |
| 134294 | + /* 329 */ "anylist ::=", | |
| 134295 | + /* 330 */ "anylist ::= anylist LP anylist RP", | |
| 134296 | + /* 331 */ "anylist ::= anylist ANY", | |
| 134235 | 134297 | }; |
| 134236 | 134298 | #endif /* NDEBUG */ |
| 134237 | 134299 | |
| 134238 | 134300 | |
| 134239 | 134301 | #if YYSTACKDEPTH<=0 |
| @@ -134811,10 +134873,11 @@ | ||
| 134811 | 134873 | { 173, 1 }, |
| 134812 | 134874 | { 173, 3 }, |
| 134813 | 134875 | { 173, 5 }, |
| 134814 | 134876 | { 172, 1 }, |
| 134815 | 134877 | { 172, 1 }, |
| 134878 | + { 172, 1 }, | |
| 134816 | 134879 | { 173, 1 }, |
| 134817 | 134880 | { 173, 3 }, |
| 134818 | 134881 | { 173, 6 }, |
| 134819 | 134882 | { 173, 5 }, |
| 134820 | 134883 | { 173, 4 }, |
| @@ -135105,11 +135168,11 @@ | ||
| 135105 | 135168 | case 42: /* autoinc ::= */ yytestcase(yyruleno==42); |
| 135106 | 135169 | case 57: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==57); |
| 135107 | 135170 | case 67: /* defer_subclause_opt ::= */ yytestcase(yyruleno==67); |
| 135108 | 135171 | case 76: /* ifexists ::= */ yytestcase(yyruleno==76); |
| 135109 | 135172 | case 90: /* distinct ::= */ yytestcase(yyruleno==90); |
| 135110 | - case 214: /* collate ::= */ yytestcase(yyruleno==214); | |
| 135173 | + case 215: /* collate ::= */ yytestcase(yyruleno==215); | |
| 135111 | 135174 | {yymsp[1].minor.yy194 = 0;} |
| 135112 | 135175 | break; |
| 135113 | 135176 | case 17: /* ifnotexists ::= IF NOT EXISTS */ |
| 135114 | 135177 | {yymsp[-2].minor.yy194 = 1;} |
| 135115 | 135178 | break; |
| @@ -135249,13 +135312,13 @@ | ||
| 135249 | 135312 | case 144: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==144); |
| 135250 | 135313 | {yymsp[-1].minor.yy194 = yymsp[0].minor.yy194;} |
| 135251 | 135314 | break; |
| 135252 | 135315 | case 58: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ |
| 135253 | 135316 | case 75: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==75); |
| 135254 | - case 186: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==186); | |
| 135255 | - case 189: /* in_op ::= NOT IN */ yytestcase(yyruleno==189); | |
| 135256 | - case 215: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==215); | |
| 135317 | + case 187: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==187); | |
| 135318 | + case 190: /* in_op ::= NOT IN */ yytestcase(yyruleno==190); | |
| 135319 | + case 216: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==216); | |
| 135257 | 135320 | {yymsp[-1].minor.yy194 = 1;} |
| 135258 | 135321 | break; |
| 135259 | 135322 | case 59: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ |
| 135260 | 135323 | {yymsp[-1].minor.yy194 = 0;} |
| 135261 | 135324 | break; |
| @@ -135415,13 +135478,13 @@ | ||
| 135415 | 135478 | {yymsp[0].minor.yy194 = SF_All;} |
| 135416 | 135479 | break; |
| 135417 | 135480 | case 91: /* sclp ::= */ |
| 135418 | 135481 | case 119: /* orderby_opt ::= */ yytestcase(yyruleno==119); |
| 135419 | 135482 | case 126: /* groupby_opt ::= */ yytestcase(yyruleno==126); |
| 135420 | - case 202: /* exprlist ::= */ yytestcase(yyruleno==202); | |
| 135421 | - case 205: /* paren_exprlist ::= */ yytestcase(yyruleno==205); | |
| 135422 | - case 210: /* eidlist_opt ::= */ yytestcase(yyruleno==210); | |
| 135483 | + case 203: /* exprlist ::= */ yytestcase(yyruleno==203); | |
| 135484 | + case 206: /* paren_exprlist ::= */ yytestcase(yyruleno==206); | |
| 135485 | + case 211: /* eidlist_opt ::= */ yytestcase(yyruleno==211); | |
| 135423 | 135486 | {yymsp[1].minor.yy148 = 0;} |
| 135424 | 135487 | break; |
| 135425 | 135488 | case 92: /* selcollist ::= sclp expr as */ |
| 135426 | 135489 | { |
| 135427 | 135490 | yymsp[-2].minor.yy148 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy148, yymsp[-1].minor.yy190.pExpr); |
| @@ -135435,20 +135498,20 @@ | ||
| 135435 | 135498 | yymsp[-1].minor.yy148 = sqlite3ExprListAppend(pParse, yymsp[-1].minor.yy148, p); |
| 135436 | 135499 | } |
| 135437 | 135500 | break; |
| 135438 | 135501 | case 94: /* selcollist ::= sclp nm DOT STAR */ |
| 135439 | 135502 | { |
| 135440 | - Expr *pRight = sqlite3PExpr(pParse, TK_ASTERISK, 0, 0, &yymsp[0].minor.yy0); | |
| 135503 | + Expr *pRight = sqlite3PExpr(pParse, TK_ASTERISK, 0, 0, 0); | |
| 135441 | 135504 | Expr *pLeft = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0); |
| 135442 | 135505 | Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0); |
| 135443 | 135506 | yymsp[-3].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy148, pDot); |
| 135444 | 135507 | } |
| 135445 | 135508 | break; |
| 135446 | 135509 | case 95: /* as ::= AS nm */ |
| 135447 | 135510 | case 106: /* dbnm ::= DOT nm */ yytestcase(yyruleno==106); |
| 135448 | - case 224: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==224); | |
| 135449 | - case 225: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==225); | |
| 135511 | + case 225: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==225); | |
| 135512 | + case 226: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==226); | |
| 135450 | 135513 | {yymsp[-1].minor.yy0 = yymsp[0].minor.yy0;} |
| 135451 | 135514 | break; |
| 135452 | 135515 | case 97: /* from ::= */ |
| 135453 | 135516 | {yymsp[1].minor.yy185 = sqlite3DbMallocZero(pParse->db, sizeof(*yymsp[1].minor.yy185));} |
| 135454 | 135517 | break; |
| @@ -135527,18 +135590,18 @@ | ||
| 135527 | 135590 | {yymsp[-3].minor.yy194 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/} |
| 135528 | 135591 | break; |
| 135529 | 135592 | case 112: /* on_opt ::= ON expr */ |
| 135530 | 135593 | case 129: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==129); |
| 135531 | 135594 | case 136: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==136); |
| 135532 | - case 198: /* case_else ::= ELSE expr */ yytestcase(yyruleno==198); | |
| 135595 | + case 199: /* case_else ::= ELSE expr */ yytestcase(yyruleno==199); | |
| 135533 | 135596 | {yymsp[-1].minor.yy72 = yymsp[0].minor.yy190.pExpr;} |
| 135534 | 135597 | break; |
| 135535 | 135598 | case 113: /* on_opt ::= */ |
| 135536 | 135599 | case 128: /* having_opt ::= */ yytestcase(yyruleno==128); |
| 135537 | 135600 | case 135: /* where_opt ::= */ yytestcase(yyruleno==135); |
| 135538 | - case 199: /* case_else ::= */ yytestcase(yyruleno==199); | |
| 135539 | - case 201: /* case_operand ::= */ yytestcase(yyruleno==201); | |
| 135601 | + case 200: /* case_else ::= */ yytestcase(yyruleno==200); | |
| 135602 | + case 202: /* case_operand ::= */ yytestcase(yyruleno==202); | |
| 135540 | 135603 | {yymsp[1].minor.yy72 = 0;} |
| 135541 | 135604 | break; |
| 135542 | 135605 | case 115: /* indexed_opt ::= INDEXED BY nm */ |
| 135543 | 135606 | {yymsp[-2].minor.yy0 = yymsp[0].minor.yy0;} |
| 135544 | 135607 | break; |
| @@ -135650,41 +135713,51 @@ | ||
| 135650 | 135713 | break; |
| 135651 | 135714 | case 150: /* expr ::= LP expr RP */ |
| 135652 | 135715 | {spanSet(&yymsp[-2].minor.yy190,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-B*/ yymsp[-2].minor.yy190.pExpr = yymsp[-1].minor.yy190.pExpr;} |
| 135653 | 135716 | break; |
| 135654 | 135717 | case 151: /* term ::= NULL */ |
| 135655 | - case 156: /* term ::= INTEGER|FLOAT|BLOB */ yytestcase(yyruleno==156); | |
| 135718 | + case 156: /* term ::= FLOAT|BLOB */ yytestcase(yyruleno==156); | |
| 135656 | 135719 | case 157: /* term ::= STRING */ yytestcase(yyruleno==157); |
| 135657 | 135720 | {spanExpr(&yymsp[0].minor.yy190,pParse,yymsp[0].major,yymsp[0].minor.yy0);/*A-overwrites-X*/} |
| 135658 | 135721 | break; |
| 135659 | 135722 | case 152: /* expr ::= ID|INDEXED */ |
| 135660 | 135723 | case 153: /* expr ::= JOIN_KW */ yytestcase(yyruleno==153); |
| 135661 | 135724 | {spanExpr(&yymsp[0].minor.yy190,pParse,TK_ID,yymsp[0].minor.yy0); /*A-overwrites-X*/} |
| 135662 | 135725 | break; |
| 135663 | 135726 | case 154: /* expr ::= nm DOT nm */ |
| 135664 | 135727 | { |
| 135665 | - Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0); | |
| 135666 | - Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0); | |
| 135728 | + Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1); | |
| 135729 | + Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[0].minor.yy0, 1); | |
| 135667 | 135730 | spanSet(&yymsp[-2].minor.yy190,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ |
| 135668 | 135731 | yymsp[-2].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0); |
| 135669 | 135732 | } |
| 135670 | 135733 | break; |
| 135671 | 135734 | case 155: /* expr ::= nm DOT nm DOT nm */ |
| 135672 | 135735 | { |
| 135673 | - Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-4].minor.yy0); | |
| 135674 | - Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0); | |
| 135675 | - Expr *temp3 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0); | |
| 135736 | + Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-4].minor.yy0, 1); | |
| 135737 | + Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1); | |
| 135738 | + Expr *temp3 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[0].minor.yy0, 1); | |
| 135676 | 135739 | Expr *temp4 = sqlite3PExpr(pParse, TK_DOT, temp2, temp3, 0); |
| 135677 | 135740 | spanSet(&yymsp[-4].minor.yy190,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ |
| 135678 | 135741 | yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp4, 0); |
| 135679 | 135742 | } |
| 135680 | 135743 | break; |
| 135681 | - case 158: /* expr ::= VARIABLE */ | |
| 135744 | + case 158: /* term ::= INTEGER */ | |
| 135745 | +{ | |
| 135746 | + yylhsminor.yy190.pExpr = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &yymsp[0].minor.yy0, 1); | |
| 135747 | + yylhsminor.yy190.zStart = yymsp[0].minor.yy0.z; | |
| 135748 | + yylhsminor.yy190.zEnd = yymsp[0].minor.yy0.z + yymsp[0].minor.yy0.n; | |
| 135749 | + if( yylhsminor.yy190.pExpr ) yylhsminor.yy190.pExpr->flags |= EP_Leaf; | |
| 135750 | +} | |
| 135751 | + yymsp[0].minor.yy190 = yylhsminor.yy190; | |
| 135752 | + break; | |
| 135753 | + case 159: /* expr ::= VARIABLE */ | |
| 135682 | 135754 | { |
| 135683 | 135755 | if( !(yymsp[0].minor.yy0.z[0]=='#' && sqlite3Isdigit(yymsp[0].minor.yy0.z[1])) ){ |
| 135756 | + u32 n = yymsp[0].minor.yy0.n; | |
| 135684 | 135757 | spanExpr(&yymsp[0].minor.yy190, pParse, TK_VARIABLE, yymsp[0].minor.yy0); |
| 135685 | - sqlite3ExprAssignVarNumber(pParse, yymsp[0].minor.yy190.pExpr); | |
| 135758 | + sqlite3ExprAssignVarNumber(pParse, yymsp[0].minor.yy190.pExpr, n); | |
| 135686 | 135759 | }else{ |
| 135687 | 135760 | /* When doing a nested parse, one can include terms in an expression |
| 135688 | 135761 | ** that look like this: #1 #2 ... These terms refer to registers |
| 135689 | 135762 | ** in the virtual machine. #N is the N-th register. */ |
| 135690 | 135763 | Token t = yymsp[0].minor.yy0; /*A-overwrites-X*/ |
| @@ -135692,29 +135765,29 @@ | ||
| 135692 | 135765 | spanSet(&yymsp[0].minor.yy190, &t, &t); |
| 135693 | 135766 | if( pParse->nested==0 ){ |
| 135694 | 135767 | sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &t); |
| 135695 | 135768 | yymsp[0].minor.yy190.pExpr = 0; |
| 135696 | 135769 | }else{ |
| 135697 | - yymsp[0].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_REGISTER, 0, 0, &t); | |
| 135770 | + yymsp[0].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_REGISTER, 0, 0, 0); | |
| 135698 | 135771 | if( yymsp[0].minor.yy190.pExpr ) sqlite3GetInt32(&t.z[1], &yymsp[0].minor.yy190.pExpr->iTable); |
| 135699 | 135772 | } |
| 135700 | 135773 | } |
| 135701 | 135774 | } |
| 135702 | 135775 | break; |
| 135703 | - case 159: /* expr ::= expr COLLATE ID|STRING */ | |
| 135776 | + case 160: /* expr ::= expr COLLATE ID|STRING */ | |
| 135704 | 135777 | { |
| 135705 | 135778 | yymsp[-2].minor.yy190.pExpr = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy190.pExpr, &yymsp[0].minor.yy0, 1); |
| 135706 | 135779 | yymsp[-2].minor.yy190.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; |
| 135707 | 135780 | } |
| 135708 | 135781 | break; |
| 135709 | - case 160: /* expr ::= CAST LP expr AS typetoken RP */ | |
| 135782 | + case 161: /* expr ::= CAST LP expr AS typetoken RP */ | |
| 135710 | 135783 | { |
| 135711 | 135784 | spanSet(&yymsp[-5].minor.yy190,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ |
| 135712 | 135785 | yymsp[-5].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_CAST, yymsp[-3].minor.yy190.pExpr, 0, &yymsp[-1].minor.yy0); |
| 135713 | 135786 | } |
| 135714 | 135787 | break; |
| 135715 | - case 161: /* expr ::= ID|INDEXED LP distinct exprlist RP */ | |
| 135788 | + case 162: /* expr ::= ID|INDEXED LP distinct exprlist RP */ | |
| 135716 | 135789 | { |
| 135717 | 135790 | if( yymsp[-1].minor.yy148 && yymsp[-1].minor.yy148->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){ |
| 135718 | 135791 | sqlite3ErrorMsg(pParse, "too many arguments on function %T", &yymsp[-4].minor.yy0); |
| 135719 | 135792 | } |
| 135720 | 135793 | yylhsminor.yy190.pExpr = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy148, &yymsp[-4].minor.yy0); |
| @@ -135723,25 +135796,25 @@ | ||
| 135723 | 135796 | yylhsminor.yy190.pExpr->flags |= EP_Distinct; |
| 135724 | 135797 | } |
| 135725 | 135798 | } |
| 135726 | 135799 | yymsp[-4].minor.yy190 = yylhsminor.yy190; |
| 135727 | 135800 | break; |
| 135728 | - case 162: /* expr ::= ID|INDEXED LP STAR RP */ | |
| 135801 | + case 163: /* expr ::= ID|INDEXED LP STAR RP */ | |
| 135729 | 135802 | { |
| 135730 | 135803 | yylhsminor.yy190.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0); |
| 135731 | 135804 | spanSet(&yylhsminor.yy190,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); |
| 135732 | 135805 | } |
| 135733 | 135806 | yymsp[-3].minor.yy190 = yylhsminor.yy190; |
| 135734 | 135807 | break; |
| 135735 | - case 163: /* term ::= CTIME_KW */ | |
| 135808 | + case 164: /* term ::= CTIME_KW */ | |
| 135736 | 135809 | { |
| 135737 | 135810 | yylhsminor.yy190.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0); |
| 135738 | 135811 | spanSet(&yylhsminor.yy190, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0); |
| 135739 | 135812 | } |
| 135740 | 135813 | yymsp[0].minor.yy190 = yylhsminor.yy190; |
| 135741 | 135814 | break; |
| 135742 | - case 164: /* expr ::= LP nexprlist COMMA expr RP */ | |
| 135815 | + case 165: /* expr ::= LP nexprlist COMMA expr RP */ | |
| 135743 | 135816 | { |
| 135744 | 135817 | ExprList *pList = sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy148, yymsp[-1].minor.yy190.pExpr); |
| 135745 | 135818 | yylhsminor.yy190.pExpr = sqlite3PExpr(pParse, TK_VECTOR, 0, 0, 0); |
| 135746 | 135819 | if( yylhsminor.yy190.pExpr ){ |
| 135747 | 135820 | yylhsminor.yy190.pExpr->x.pList = pList; |
| @@ -135750,82 +135823,86 @@ | ||
| 135750 | 135823 | sqlite3ExprListDelete(pParse->db, pList); |
| 135751 | 135824 | } |
| 135752 | 135825 | } |
| 135753 | 135826 | yymsp[-4].minor.yy190 = yylhsminor.yy190; |
| 135754 | 135827 | break; |
| 135755 | - case 165: /* expr ::= expr AND expr */ | |
| 135756 | - case 166: /* expr ::= expr OR expr */ yytestcase(yyruleno==166); | |
| 135757 | - case 167: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==167); | |
| 135758 | - case 168: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==168); | |
| 135759 | - case 169: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==169); | |
| 135760 | - case 170: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==170); | |
| 135761 | - case 171: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==171); | |
| 135762 | - case 172: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==172); | |
| 135828 | + case 166: /* expr ::= expr AND expr */ | |
| 135829 | + case 167: /* expr ::= expr OR expr */ yytestcase(yyruleno==167); | |
| 135830 | + case 168: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==168); | |
| 135831 | + case 169: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==169); | |
| 135832 | + case 170: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==170); | |
| 135833 | + case 171: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==171); | |
| 135834 | + case 172: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==172); | |
| 135835 | + case 173: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==173); | |
| 135763 | 135836 | {spanBinaryExpr(pParse,yymsp[-1].major,&yymsp[-2].minor.yy190,&yymsp[0].minor.yy190);} |
| 135764 | 135837 | break; |
| 135765 | - case 173: /* likeop ::= LIKE_KW|MATCH */ | |
| 135766 | -{yymsp[0].minor.yy392.eOperator = yymsp[0].minor.yy0; yymsp[0].minor.yy392.bNot = 0;/*A-overwrites-X*/} | |
| 135838 | + case 174: /* likeop ::= LIKE_KW|MATCH */ | |
| 135839 | +{yymsp[0].minor.yy0=yymsp[0].minor.yy0;/*A-overwrites-X*/} | |
| 135767 | 135840 | break; |
| 135768 | - case 174: /* likeop ::= NOT LIKE_KW|MATCH */ | |
| 135769 | -{yymsp[-1].minor.yy392.eOperator = yymsp[0].minor.yy0; yymsp[-1].minor.yy392.bNot = 1;} | |
| 135841 | + case 175: /* likeop ::= NOT LIKE_KW|MATCH */ | |
| 135842 | +{yymsp[-1].minor.yy0=yymsp[0].minor.yy0; yymsp[-1].minor.yy0.n|=0x80000000; /*yymsp[-1].minor.yy0-overwrite-yymsp[0].minor.yy0*/} | |
| 135770 | 135843 | break; |
| 135771 | - case 175: /* expr ::= expr likeop expr */ | |
| 135844 | + case 176: /* expr ::= expr likeop expr */ | |
| 135772 | 135845 | { |
| 135773 | 135846 | ExprList *pList; |
| 135847 | + int bNot = yymsp[-1].minor.yy0.n & 0x80000000; | |
| 135848 | + yymsp[-1].minor.yy0.n &= 0x7fffffff; | |
| 135774 | 135849 | pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy190.pExpr); |
| 135775 | 135850 | pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy190.pExpr); |
| 135776 | - yymsp[-2].minor.yy190.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy392.eOperator); | |
| 135777 | - exprNot(pParse, yymsp[-1].minor.yy392.bNot, &yymsp[-2].minor.yy190); | |
| 135851 | + yymsp[-2].minor.yy190.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0); | |
| 135852 | + exprNot(pParse, bNot, &yymsp[-2].minor.yy190); | |
| 135778 | 135853 | yymsp[-2].minor.yy190.zEnd = yymsp[0].minor.yy190.zEnd; |
| 135779 | 135854 | if( yymsp[-2].minor.yy190.pExpr ) yymsp[-2].minor.yy190.pExpr->flags |= EP_InfixFunc; |
| 135780 | 135855 | } |
| 135781 | 135856 | break; |
| 135782 | - case 176: /* expr ::= expr likeop expr ESCAPE expr */ | |
| 135857 | + case 177: /* expr ::= expr likeop expr ESCAPE expr */ | |
| 135783 | 135858 | { |
| 135784 | 135859 | ExprList *pList; |
| 135860 | + int bNot = yymsp[-3].minor.yy0.n & 0x80000000; | |
| 135861 | + yymsp[-3].minor.yy0.n &= 0x7fffffff; | |
| 135785 | 135862 | pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy190.pExpr); |
| 135786 | 135863 | pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy190.pExpr); |
| 135787 | 135864 | pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy190.pExpr); |
| 135788 | - yymsp[-4].minor.yy190.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy392.eOperator); | |
| 135789 | - exprNot(pParse, yymsp[-3].minor.yy392.bNot, &yymsp[-4].minor.yy190); | |
| 135865 | + yymsp[-4].minor.yy190.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy0); | |
| 135866 | + exprNot(pParse, bNot, &yymsp[-4].minor.yy190); | |
| 135790 | 135867 | yymsp[-4].minor.yy190.zEnd = yymsp[0].minor.yy190.zEnd; |
| 135791 | 135868 | if( yymsp[-4].minor.yy190.pExpr ) yymsp[-4].minor.yy190.pExpr->flags |= EP_InfixFunc; |
| 135792 | 135869 | } |
| 135793 | 135870 | break; |
| 135794 | - case 177: /* expr ::= expr ISNULL|NOTNULL */ | |
| 135871 | + case 178: /* expr ::= expr ISNULL|NOTNULL */ | |
| 135795 | 135872 | {spanUnaryPostfix(pParse,yymsp[0].major,&yymsp[-1].minor.yy190,&yymsp[0].minor.yy0);} |
| 135796 | 135873 | break; |
| 135797 | - case 178: /* expr ::= expr NOT NULL */ | |
| 135874 | + case 179: /* expr ::= expr NOT NULL */ | |
| 135798 | 135875 | {spanUnaryPostfix(pParse,TK_NOTNULL,&yymsp[-2].minor.yy190,&yymsp[0].minor.yy0);} |
| 135799 | 135876 | break; |
| 135800 | - case 179: /* expr ::= expr IS expr */ | |
| 135877 | + case 180: /* expr ::= expr IS expr */ | |
| 135801 | 135878 | { |
| 135802 | 135879 | spanBinaryExpr(pParse,TK_IS,&yymsp[-2].minor.yy190,&yymsp[0].minor.yy190); |
| 135803 | 135880 | binaryToUnaryIfNull(pParse, yymsp[0].minor.yy190.pExpr, yymsp[-2].minor.yy190.pExpr, TK_ISNULL); |
| 135804 | 135881 | } |
| 135805 | 135882 | break; |
| 135806 | - case 180: /* expr ::= expr IS NOT expr */ | |
| 135883 | + case 181: /* expr ::= expr IS NOT expr */ | |
| 135807 | 135884 | { |
| 135808 | 135885 | spanBinaryExpr(pParse,TK_ISNOT,&yymsp[-3].minor.yy190,&yymsp[0].minor.yy190); |
| 135809 | 135886 | binaryToUnaryIfNull(pParse, yymsp[0].minor.yy190.pExpr, yymsp[-3].minor.yy190.pExpr, TK_NOTNULL); |
| 135810 | 135887 | } |
| 135811 | 135888 | break; |
| 135812 | - case 181: /* expr ::= NOT expr */ | |
| 135813 | - case 182: /* expr ::= BITNOT expr */ yytestcase(yyruleno==182); | |
| 135889 | + case 182: /* expr ::= NOT expr */ | |
| 135890 | + case 183: /* expr ::= BITNOT expr */ yytestcase(yyruleno==183); | |
| 135814 | 135891 | {spanUnaryPrefix(&yymsp[-1].minor.yy190,pParse,yymsp[-1].major,&yymsp[0].minor.yy190,&yymsp[-1].minor.yy0);/*A-overwrites-B*/} |
| 135815 | 135892 | break; |
| 135816 | - case 183: /* expr ::= MINUS expr */ | |
| 135893 | + case 184: /* expr ::= MINUS expr */ | |
| 135817 | 135894 | {spanUnaryPrefix(&yymsp[-1].minor.yy190,pParse,TK_UMINUS,&yymsp[0].minor.yy190,&yymsp[-1].minor.yy0);/*A-overwrites-B*/} |
| 135818 | 135895 | break; |
| 135819 | - case 184: /* expr ::= PLUS expr */ | |
| 135896 | + case 185: /* expr ::= PLUS expr */ | |
| 135820 | 135897 | {spanUnaryPrefix(&yymsp[-1].minor.yy190,pParse,TK_UPLUS,&yymsp[0].minor.yy190,&yymsp[-1].minor.yy0);/*A-overwrites-B*/} |
| 135821 | 135898 | break; |
| 135822 | - case 185: /* between_op ::= BETWEEN */ | |
| 135823 | - case 188: /* in_op ::= IN */ yytestcase(yyruleno==188); | |
| 135899 | + case 186: /* between_op ::= BETWEEN */ | |
| 135900 | + case 189: /* in_op ::= IN */ yytestcase(yyruleno==189); | |
| 135824 | 135901 | {yymsp[0].minor.yy194 = 0;} |
| 135825 | 135902 | break; |
| 135826 | - case 187: /* expr ::= expr between_op expr AND expr */ | |
| 135903 | + case 188: /* expr ::= expr between_op expr AND expr */ | |
| 135827 | 135904 | { |
| 135828 | 135905 | ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy190.pExpr); |
| 135829 | 135906 | pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy190.pExpr); |
| 135830 | 135907 | yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy190.pExpr, 0, 0); |
| 135831 | 135908 | if( yymsp[-4].minor.yy190.pExpr ){ |
| @@ -135835,11 +135912,11 @@ | ||
| 135835 | 135912 | } |
| 135836 | 135913 | exprNot(pParse, yymsp[-3].minor.yy194, &yymsp[-4].minor.yy190); |
| 135837 | 135914 | yymsp[-4].minor.yy190.zEnd = yymsp[0].minor.yy190.zEnd; |
| 135838 | 135915 | } |
| 135839 | 135916 | break; |
| 135840 | - case 190: /* expr ::= expr in_op LP exprlist RP */ | |
| 135917 | + case 191: /* expr ::= expr in_op LP exprlist RP */ | |
| 135841 | 135918 | { |
| 135842 | 135919 | if( yymsp[-1].minor.yy148==0 ){ |
| 135843 | 135920 | /* Expressions of the form |
| 135844 | 135921 | ** |
| 135845 | 135922 | ** expr1 IN () |
| @@ -135888,26 +135965,26 @@ | ||
| 135888 | 135965 | exprNot(pParse, yymsp[-3].minor.yy194, &yymsp[-4].minor.yy190); |
| 135889 | 135966 | } |
| 135890 | 135967 | yymsp[-4].minor.yy190.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; |
| 135891 | 135968 | } |
| 135892 | 135969 | break; |
| 135893 | - case 191: /* expr ::= LP select RP */ | |
| 135970 | + case 192: /* expr ::= LP select RP */ | |
| 135894 | 135971 | { |
| 135895 | 135972 | spanSet(&yymsp[-2].minor.yy190,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-B*/ |
| 135896 | 135973 | yymsp[-2].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0); |
| 135897 | 135974 | sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy190.pExpr, yymsp[-1].minor.yy243); |
| 135898 | 135975 | } |
| 135899 | 135976 | break; |
| 135900 | - case 192: /* expr ::= expr in_op LP select RP */ | |
| 135977 | + case 193: /* expr ::= expr in_op LP select RP */ | |
| 135901 | 135978 | { |
| 135902 | 135979 | yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy190.pExpr, 0, 0); |
| 135903 | 135980 | sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy190.pExpr, yymsp[-1].minor.yy243); |
| 135904 | 135981 | exprNot(pParse, yymsp[-3].minor.yy194, &yymsp[-4].minor.yy190); |
| 135905 | 135982 | yymsp[-4].minor.yy190.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; |
| 135906 | 135983 | } |
| 135907 | 135984 | break; |
| 135908 | - case 193: /* expr ::= expr in_op nm dbnm paren_exprlist */ | |
| 135985 | + case 194: /* expr ::= expr in_op nm dbnm paren_exprlist */ | |
| 135909 | 135986 | { |
| 135910 | 135987 | SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0); |
| 135911 | 135988 | Select *pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0); |
| 135912 | 135989 | if( yymsp[0].minor.yy148 ) sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, yymsp[0].minor.yy148); |
| 135913 | 135990 | yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy190.pExpr, 0, 0); |
| @@ -135914,19 +135991,19 @@ | ||
| 135914 | 135991 | sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy190.pExpr, pSelect); |
| 135915 | 135992 | exprNot(pParse, yymsp[-3].minor.yy194, &yymsp[-4].minor.yy190); |
| 135916 | 135993 | yymsp[-4].minor.yy190.zEnd = yymsp[-1].minor.yy0.z ? &yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n] : &yymsp[-2].minor.yy0.z[yymsp[-2].minor.yy0.n]; |
| 135917 | 135994 | } |
| 135918 | 135995 | break; |
| 135919 | - case 194: /* expr ::= EXISTS LP select RP */ | |
| 135996 | + case 195: /* expr ::= EXISTS LP select RP */ | |
| 135920 | 135997 | { |
| 135921 | 135998 | Expr *p; |
| 135922 | 135999 | spanSet(&yymsp[-3].minor.yy190,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-B*/ |
| 135923 | 136000 | p = yymsp[-3].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0); |
| 135924 | 136001 | sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy243); |
| 135925 | 136002 | } |
| 135926 | 136003 | break; |
| 135927 | - case 195: /* expr ::= CASE case_operand case_exprlist case_else END */ | |
| 136004 | + case 196: /* expr ::= CASE case_operand case_exprlist case_else END */ | |
| 135928 | 136005 | { |
| 135929 | 136006 | spanSet(&yymsp[-4].minor.yy190,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-C*/ |
| 135930 | 136007 | yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy72, 0, 0); |
| 135931 | 136008 | if( yymsp[-4].minor.yy190.pExpr ){ |
| 135932 | 136009 | yymsp[-4].minor.yy190.pExpr->x.pList = yymsp[-1].minor.yy72 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy148,yymsp[-1].minor.yy72) : yymsp[-2].minor.yy148; |
| @@ -135935,334 +136012,334 @@ | ||
| 135935 | 136012 | sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy148); |
| 135936 | 136013 | sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy72); |
| 135937 | 136014 | } |
| 135938 | 136015 | } |
| 135939 | 136016 | break; |
| 135940 | - case 196: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */ | |
| 136017 | + case 197: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */ | |
| 135941 | 136018 | { |
| 135942 | 136019 | yymsp[-4].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy148, yymsp[-2].minor.yy190.pExpr); |
| 135943 | 136020 | yymsp[-4].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy148, yymsp[0].minor.yy190.pExpr); |
| 135944 | 136021 | } |
| 135945 | 136022 | break; |
| 135946 | - case 197: /* case_exprlist ::= WHEN expr THEN expr */ | |
| 136023 | + case 198: /* case_exprlist ::= WHEN expr THEN expr */ | |
| 135947 | 136024 | { |
| 135948 | 136025 | yymsp[-3].minor.yy148 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy190.pExpr); |
| 135949 | 136026 | yymsp[-3].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy148, yymsp[0].minor.yy190.pExpr); |
| 135950 | 136027 | } |
| 135951 | 136028 | break; |
| 135952 | - case 200: /* case_operand ::= expr */ | |
| 136029 | + case 201: /* case_operand ::= expr */ | |
| 135953 | 136030 | {yymsp[0].minor.yy72 = yymsp[0].minor.yy190.pExpr; /*A-overwrites-X*/} |
| 135954 | 136031 | break; |
| 135955 | - case 203: /* nexprlist ::= nexprlist COMMA expr */ | |
| 136032 | + case 204: /* nexprlist ::= nexprlist COMMA expr */ | |
| 135956 | 136033 | {yymsp[-2].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy148,yymsp[0].minor.yy190.pExpr);} |
| 135957 | 136034 | break; |
| 135958 | - case 204: /* nexprlist ::= expr */ | |
| 136035 | + case 205: /* nexprlist ::= expr */ | |
| 135959 | 136036 | {yymsp[0].minor.yy148 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy190.pExpr); /*A-overwrites-Y*/} |
| 135960 | 136037 | break; |
| 135961 | - case 206: /* paren_exprlist ::= LP exprlist RP */ | |
| 135962 | - case 211: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==211); | |
| 136038 | + case 207: /* paren_exprlist ::= LP exprlist RP */ | |
| 136039 | + case 212: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==212); | |
| 135963 | 136040 | {yymsp[-2].minor.yy148 = yymsp[-1].minor.yy148;} |
| 135964 | 136041 | break; |
| 135965 | - case 207: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ | |
| 136042 | + case 208: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ | |
| 135966 | 136043 | { |
| 135967 | 136044 | sqlite3CreateIndex(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, |
| 135968 | 136045 | sqlite3SrcListAppend(pParse->db,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy148, yymsp[-10].minor.yy194, |
| 135969 | 136046 | &yymsp[-11].minor.yy0, yymsp[0].minor.yy72, SQLITE_SO_ASC, yymsp[-8].minor.yy194, SQLITE_IDXTYPE_APPDEF); |
| 135970 | 136047 | } |
| 135971 | 136048 | break; |
| 135972 | - case 208: /* uniqueflag ::= UNIQUE */ | |
| 135973 | - case 249: /* raisetype ::= ABORT */ yytestcase(yyruleno==249); | |
| 136049 | + case 209: /* uniqueflag ::= UNIQUE */ | |
| 136050 | + case 250: /* raisetype ::= ABORT */ yytestcase(yyruleno==250); | |
| 135974 | 136051 | {yymsp[0].minor.yy194 = OE_Abort;} |
| 135975 | 136052 | break; |
| 135976 | - case 209: /* uniqueflag ::= */ | |
| 136053 | + case 210: /* uniqueflag ::= */ | |
| 135977 | 136054 | {yymsp[1].minor.yy194 = OE_None;} |
| 135978 | 136055 | break; |
| 135979 | - case 212: /* eidlist ::= eidlist COMMA nm collate sortorder */ | |
| 136056 | + case 213: /* eidlist ::= eidlist COMMA nm collate sortorder */ | |
| 135980 | 136057 | { |
| 135981 | 136058 | yymsp[-4].minor.yy148 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy148, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy194, yymsp[0].minor.yy194); |
| 135982 | 136059 | } |
| 135983 | 136060 | break; |
| 135984 | - case 213: /* eidlist ::= nm collate sortorder */ | |
| 136061 | + case 214: /* eidlist ::= nm collate sortorder */ | |
| 135985 | 136062 | { |
| 135986 | 136063 | yymsp[-2].minor.yy148 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy194, yymsp[0].minor.yy194); /*A-overwrites-Y*/ |
| 135987 | 136064 | } |
| 135988 | 136065 | break; |
| 135989 | - case 216: /* cmd ::= DROP INDEX ifexists fullname */ | |
| 136066 | + case 217: /* cmd ::= DROP INDEX ifexists fullname */ | |
| 135990 | 136067 | {sqlite3DropIndex(pParse, yymsp[0].minor.yy185, yymsp[-1].minor.yy194);} |
| 135991 | 136068 | break; |
| 135992 | - case 217: /* cmd ::= VACUUM */ | |
| 136069 | + case 218: /* cmd ::= VACUUM */ | |
| 135993 | 136070 | {sqlite3Vacuum(pParse,0);} |
| 135994 | 136071 | break; |
| 135995 | - case 218: /* cmd ::= VACUUM nm */ | |
| 136072 | + case 219: /* cmd ::= VACUUM nm */ | |
| 135996 | 136073 | {sqlite3Vacuum(pParse,&yymsp[0].minor.yy0);} |
| 135997 | 136074 | break; |
| 135998 | - case 219: /* cmd ::= PRAGMA nm dbnm */ | |
| 136075 | + case 220: /* cmd ::= PRAGMA nm dbnm */ | |
| 135999 | 136076 | {sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);} |
| 136000 | 136077 | break; |
| 136001 | - case 220: /* cmd ::= PRAGMA nm dbnm EQ nmnum */ | |
| 136078 | + case 221: /* cmd ::= PRAGMA nm dbnm EQ nmnum */ | |
| 136002 | 136079 | {sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,0);} |
| 136003 | 136080 | break; |
| 136004 | - case 221: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */ | |
| 136081 | + case 222: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */ | |
| 136005 | 136082 | {sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,0);} |
| 136006 | 136083 | break; |
| 136007 | - case 222: /* cmd ::= PRAGMA nm dbnm EQ minus_num */ | |
| 136084 | + case 223: /* cmd ::= PRAGMA nm dbnm EQ minus_num */ | |
| 136008 | 136085 | {sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,1);} |
| 136009 | 136086 | break; |
| 136010 | - case 223: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */ | |
| 136087 | + case 224: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */ | |
| 136011 | 136088 | {sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,1);} |
| 136012 | 136089 | break; |
| 136013 | - case 226: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ | |
| 136090 | + case 227: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ | |
| 136014 | 136091 | { |
| 136015 | 136092 | Token all; |
| 136016 | 136093 | all.z = yymsp[-3].minor.yy0.z; |
| 136017 | 136094 | all.n = (int)(yymsp[0].minor.yy0.z - yymsp[-3].minor.yy0.z) + yymsp[0].minor.yy0.n; |
| 136018 | 136095 | sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy145, &all); |
| 136019 | 136096 | } |
| 136020 | 136097 | break; |
| 136021 | - case 227: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ | |
| 136098 | + case 228: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ | |
| 136022 | 136099 | { |
| 136023 | 136100 | sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy194, yymsp[-4].minor.yy332.a, yymsp[-4].minor.yy332.b, yymsp[-2].minor.yy185, yymsp[0].minor.yy72, yymsp[-10].minor.yy194, yymsp[-8].minor.yy194); |
| 136024 | 136101 | yymsp[-10].minor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0); /*A-overwrites-T*/ |
| 136025 | 136102 | } |
| 136026 | 136103 | break; |
| 136027 | - case 228: /* trigger_time ::= BEFORE */ | |
| 136104 | + case 229: /* trigger_time ::= BEFORE */ | |
| 136028 | 136105 | { yymsp[0].minor.yy194 = TK_BEFORE; } |
| 136029 | 136106 | break; |
| 136030 | - case 229: /* trigger_time ::= AFTER */ | |
| 136107 | + case 230: /* trigger_time ::= AFTER */ | |
| 136031 | 136108 | { yymsp[0].minor.yy194 = TK_AFTER; } |
| 136032 | 136109 | break; |
| 136033 | - case 230: /* trigger_time ::= INSTEAD OF */ | |
| 136110 | + case 231: /* trigger_time ::= INSTEAD OF */ | |
| 136034 | 136111 | { yymsp[-1].minor.yy194 = TK_INSTEAD;} |
| 136035 | 136112 | break; |
| 136036 | - case 231: /* trigger_time ::= */ | |
| 136113 | + case 232: /* trigger_time ::= */ | |
| 136037 | 136114 | { yymsp[1].minor.yy194 = TK_BEFORE; } |
| 136038 | 136115 | break; |
| 136039 | - case 232: /* trigger_event ::= DELETE|INSERT */ | |
| 136040 | - case 233: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==233); | |
| 136116 | + case 233: /* trigger_event ::= DELETE|INSERT */ | |
| 136117 | + case 234: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==234); | |
| 136041 | 136118 | {yymsp[0].minor.yy332.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy332.b = 0;} |
| 136042 | 136119 | break; |
| 136043 | - case 234: /* trigger_event ::= UPDATE OF idlist */ | |
| 136120 | + case 235: /* trigger_event ::= UPDATE OF idlist */ | |
| 136044 | 136121 | {yymsp[-2].minor.yy332.a = TK_UPDATE; yymsp[-2].minor.yy332.b = yymsp[0].minor.yy254;} |
| 136045 | 136122 | break; |
| 136046 | - case 235: /* when_clause ::= */ | |
| 136047 | - case 254: /* key_opt ::= */ yytestcase(yyruleno==254); | |
| 136123 | + case 236: /* when_clause ::= */ | |
| 136124 | + case 255: /* key_opt ::= */ yytestcase(yyruleno==255); | |
| 136048 | 136125 | { yymsp[1].minor.yy72 = 0; } |
| 136049 | 136126 | break; |
| 136050 | - case 236: /* when_clause ::= WHEN expr */ | |
| 136051 | - case 255: /* key_opt ::= KEY expr */ yytestcase(yyruleno==255); | |
| 136127 | + case 237: /* when_clause ::= WHEN expr */ | |
| 136128 | + case 256: /* key_opt ::= KEY expr */ yytestcase(yyruleno==256); | |
| 136052 | 136129 | { yymsp[-1].minor.yy72 = yymsp[0].minor.yy190.pExpr; } |
| 136053 | 136130 | break; |
| 136054 | - case 237: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ | |
| 136131 | + case 238: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ | |
| 136055 | 136132 | { |
| 136056 | 136133 | assert( yymsp[-2].minor.yy145!=0 ); |
| 136057 | 136134 | yymsp[-2].minor.yy145->pLast->pNext = yymsp[-1].minor.yy145; |
| 136058 | 136135 | yymsp[-2].minor.yy145->pLast = yymsp[-1].minor.yy145; |
| 136059 | 136136 | } |
| 136060 | 136137 | break; |
| 136061 | - case 238: /* trigger_cmd_list ::= trigger_cmd SEMI */ | |
| 136138 | + case 239: /* trigger_cmd_list ::= trigger_cmd SEMI */ | |
| 136062 | 136139 | { |
| 136063 | 136140 | assert( yymsp[-1].minor.yy145!=0 ); |
| 136064 | 136141 | yymsp[-1].minor.yy145->pLast = yymsp[-1].minor.yy145; |
| 136065 | 136142 | } |
| 136066 | 136143 | break; |
| 136067 | - case 239: /* trnm ::= nm DOT nm */ | |
| 136144 | + case 240: /* trnm ::= nm DOT nm */ | |
| 136068 | 136145 | { |
| 136069 | 136146 | yymsp[-2].minor.yy0 = yymsp[0].minor.yy0; |
| 136070 | 136147 | sqlite3ErrorMsg(pParse, |
| 136071 | 136148 | "qualified table names are not allowed on INSERT, UPDATE, and DELETE " |
| 136072 | 136149 | "statements within triggers"); |
| 136073 | 136150 | } |
| 136074 | 136151 | break; |
| 136075 | - case 240: /* tridxby ::= INDEXED BY nm */ | |
| 136152 | + case 241: /* tridxby ::= INDEXED BY nm */ | |
| 136076 | 136153 | { |
| 136077 | 136154 | sqlite3ErrorMsg(pParse, |
| 136078 | 136155 | "the INDEXED BY clause is not allowed on UPDATE or DELETE statements " |
| 136079 | 136156 | "within triggers"); |
| 136080 | 136157 | } |
| 136081 | 136158 | break; |
| 136082 | - case 241: /* tridxby ::= NOT INDEXED */ | |
| 136159 | + case 242: /* tridxby ::= NOT INDEXED */ | |
| 136083 | 136160 | { |
| 136084 | 136161 | sqlite3ErrorMsg(pParse, |
| 136085 | 136162 | "the NOT INDEXED clause is not allowed on UPDATE or DELETE statements " |
| 136086 | 136163 | "within triggers"); |
| 136087 | 136164 | } |
| 136088 | 136165 | break; |
| 136089 | - case 242: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt */ | |
| 136166 | + case 243: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt */ | |
| 136090 | 136167 | {yymsp[-6].minor.yy145 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-4].minor.yy0, yymsp[-1].minor.yy148, yymsp[0].minor.yy72, yymsp[-5].minor.yy194);} |
| 136091 | 136168 | break; |
| 136092 | - case 243: /* trigger_cmd ::= insert_cmd INTO trnm idlist_opt select */ | |
| 136169 | + case 244: /* trigger_cmd ::= insert_cmd INTO trnm idlist_opt select */ | |
| 136093 | 136170 | {yymsp[-4].minor.yy145 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy254, yymsp[0].minor.yy243, yymsp[-4].minor.yy194);/*A-overwrites-R*/} |
| 136094 | 136171 | break; |
| 136095 | - case 244: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt */ | |
| 136172 | + case 245: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt */ | |
| 136096 | 136173 | {yymsp[-4].minor.yy145 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[0].minor.yy72);} |
| 136097 | 136174 | break; |
| 136098 | - case 245: /* trigger_cmd ::= select */ | |
| 136175 | + case 246: /* trigger_cmd ::= select */ | |
| 136099 | 136176 | {yymsp[0].minor.yy145 = sqlite3TriggerSelectStep(pParse->db, yymsp[0].minor.yy243); /*A-overwrites-X*/} |
| 136100 | 136177 | break; |
| 136101 | - case 246: /* expr ::= RAISE LP IGNORE RP */ | |
| 136178 | + case 247: /* expr ::= RAISE LP IGNORE RP */ | |
| 136102 | 136179 | { |
| 136103 | 136180 | spanSet(&yymsp[-3].minor.yy190,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ |
| 136104 | 136181 | yymsp[-3].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, 0); |
| 136105 | 136182 | if( yymsp[-3].minor.yy190.pExpr ){ |
| 136106 | 136183 | yymsp[-3].minor.yy190.pExpr->affinity = OE_Ignore; |
| 136107 | 136184 | } |
| 136108 | 136185 | } |
| 136109 | 136186 | break; |
| 136110 | - case 247: /* expr ::= RAISE LP raisetype COMMA nm RP */ | |
| 136187 | + case 248: /* expr ::= RAISE LP raisetype COMMA nm RP */ | |
| 136111 | 136188 | { |
| 136112 | 136189 | spanSet(&yymsp[-5].minor.yy190,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ |
| 136113 | 136190 | yymsp[-5].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &yymsp[-1].minor.yy0); |
| 136114 | 136191 | if( yymsp[-5].minor.yy190.pExpr ) { |
| 136115 | 136192 | yymsp[-5].minor.yy190.pExpr->affinity = (char)yymsp[-3].minor.yy194; |
| 136116 | 136193 | } |
| 136117 | 136194 | } |
| 136118 | 136195 | break; |
| 136119 | - case 248: /* raisetype ::= ROLLBACK */ | |
| 136196 | + case 249: /* raisetype ::= ROLLBACK */ | |
| 136120 | 136197 | {yymsp[0].minor.yy194 = OE_Rollback;} |
| 136121 | 136198 | break; |
| 136122 | - case 250: /* raisetype ::= FAIL */ | |
| 136199 | + case 251: /* raisetype ::= FAIL */ | |
| 136123 | 136200 | {yymsp[0].minor.yy194 = OE_Fail;} |
| 136124 | 136201 | break; |
| 136125 | - case 251: /* cmd ::= DROP TRIGGER ifexists fullname */ | |
| 136202 | + case 252: /* cmd ::= DROP TRIGGER ifexists fullname */ | |
| 136126 | 136203 | { |
| 136127 | 136204 | sqlite3DropTrigger(pParse,yymsp[0].minor.yy185,yymsp[-1].minor.yy194); |
| 136128 | 136205 | } |
| 136129 | 136206 | break; |
| 136130 | - case 252: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ | |
| 136207 | + case 253: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ | |
| 136131 | 136208 | { |
| 136132 | 136209 | sqlite3Attach(pParse, yymsp[-3].minor.yy190.pExpr, yymsp[-1].minor.yy190.pExpr, yymsp[0].minor.yy72); |
| 136133 | 136210 | } |
| 136134 | 136211 | break; |
| 136135 | - case 253: /* cmd ::= DETACH database_kw_opt expr */ | |
| 136212 | + case 254: /* cmd ::= DETACH database_kw_opt expr */ | |
| 136136 | 136213 | { |
| 136137 | 136214 | sqlite3Detach(pParse, yymsp[0].minor.yy190.pExpr); |
| 136138 | 136215 | } |
| 136139 | 136216 | break; |
| 136140 | - case 256: /* cmd ::= REINDEX */ | |
| 136217 | + case 257: /* cmd ::= REINDEX */ | |
| 136141 | 136218 | {sqlite3Reindex(pParse, 0, 0);} |
| 136142 | 136219 | break; |
| 136143 | - case 257: /* cmd ::= REINDEX nm dbnm */ | |
| 136220 | + case 258: /* cmd ::= REINDEX nm dbnm */ | |
| 136144 | 136221 | {sqlite3Reindex(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} |
| 136145 | 136222 | break; |
| 136146 | - case 258: /* cmd ::= ANALYZE */ | |
| 136223 | + case 259: /* cmd ::= ANALYZE */ | |
| 136147 | 136224 | {sqlite3Analyze(pParse, 0, 0);} |
| 136148 | 136225 | break; |
| 136149 | - case 259: /* cmd ::= ANALYZE nm dbnm */ | |
| 136226 | + case 260: /* cmd ::= ANALYZE nm dbnm */ | |
| 136150 | 136227 | {sqlite3Analyze(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} |
| 136151 | 136228 | break; |
| 136152 | - case 260: /* cmd ::= ALTER TABLE fullname RENAME TO nm */ | |
| 136229 | + case 261: /* cmd ::= ALTER TABLE fullname RENAME TO nm */ | |
| 136153 | 136230 | { |
| 136154 | 136231 | sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy185,&yymsp[0].minor.yy0); |
| 136155 | 136232 | } |
| 136156 | 136233 | break; |
| 136157 | - case 261: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ | |
| 136234 | + case 262: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ | |
| 136158 | 136235 | { |
| 136159 | 136236 | yymsp[-1].minor.yy0.n = (int)(pParse->sLastToken.z-yymsp[-1].minor.yy0.z) + pParse->sLastToken.n; |
| 136160 | 136237 | sqlite3AlterFinishAddColumn(pParse, &yymsp[-1].minor.yy0); |
| 136161 | 136238 | } |
| 136162 | 136239 | break; |
| 136163 | - case 262: /* add_column_fullname ::= fullname */ | |
| 136240 | + case 263: /* add_column_fullname ::= fullname */ | |
| 136164 | 136241 | { |
| 136165 | 136242 | disableLookaside(pParse); |
| 136166 | 136243 | sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy185); |
| 136167 | 136244 | } |
| 136168 | 136245 | break; |
| 136169 | - case 263: /* cmd ::= create_vtab */ | |
| 136246 | + case 264: /* cmd ::= create_vtab */ | |
| 136170 | 136247 | {sqlite3VtabFinishParse(pParse,0);} |
| 136171 | 136248 | break; |
| 136172 | - case 264: /* cmd ::= create_vtab LP vtabarglist RP */ | |
| 136249 | + case 265: /* cmd ::= create_vtab LP vtabarglist RP */ | |
| 136173 | 136250 | {sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);} |
| 136174 | 136251 | break; |
| 136175 | - case 265: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ | |
| 136252 | + case 266: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ | |
| 136176 | 136253 | { |
| 136177 | 136254 | sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy194); |
| 136178 | 136255 | } |
| 136179 | 136256 | break; |
| 136180 | - case 266: /* vtabarg ::= */ | |
| 136257 | + case 267: /* vtabarg ::= */ | |
| 136181 | 136258 | {sqlite3VtabArgInit(pParse);} |
| 136182 | 136259 | break; |
| 136183 | - case 267: /* vtabargtoken ::= ANY */ | |
| 136184 | - case 268: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==268); | |
| 136185 | - case 269: /* lp ::= LP */ yytestcase(yyruleno==269); | |
| 136260 | + case 268: /* vtabargtoken ::= ANY */ | |
| 136261 | + case 269: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==269); | |
| 136262 | + case 270: /* lp ::= LP */ yytestcase(yyruleno==270); | |
| 136186 | 136263 | {sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);} |
| 136187 | 136264 | break; |
| 136188 | - case 270: /* with ::= */ | |
| 136265 | + case 271: /* with ::= */ | |
| 136189 | 136266 | {yymsp[1].minor.yy285 = 0;} |
| 136190 | 136267 | break; |
| 136191 | - case 271: /* with ::= WITH wqlist */ | |
| 136268 | + case 272: /* with ::= WITH wqlist */ | |
| 136192 | 136269 | { yymsp[-1].minor.yy285 = yymsp[0].minor.yy285; } |
| 136193 | 136270 | break; |
| 136194 | - case 272: /* with ::= WITH RECURSIVE wqlist */ | |
| 136271 | + case 273: /* with ::= WITH RECURSIVE wqlist */ | |
| 136195 | 136272 | { yymsp[-2].minor.yy285 = yymsp[0].minor.yy285; } |
| 136196 | 136273 | break; |
| 136197 | - case 273: /* wqlist ::= nm eidlist_opt AS LP select RP */ | |
| 136274 | + case 274: /* wqlist ::= nm eidlist_opt AS LP select RP */ | |
| 136198 | 136275 | { |
| 136199 | 136276 | yymsp[-5].minor.yy285 = sqlite3WithAdd(pParse, 0, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy148, yymsp[-1].minor.yy243); /*A-overwrites-X*/ |
| 136200 | 136277 | } |
| 136201 | 136278 | break; |
| 136202 | - case 274: /* wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */ | |
| 136279 | + case 275: /* wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */ | |
| 136203 | 136280 | { |
| 136204 | 136281 | yymsp[-7].minor.yy285 = sqlite3WithAdd(pParse, yymsp[-7].minor.yy285, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy148, yymsp[-1].minor.yy243); |
| 136205 | 136282 | } |
| 136206 | 136283 | break; |
| 136207 | 136284 | default: |
| 136208 | - /* (275) input ::= cmdlist */ yytestcase(yyruleno==275); | |
| 136209 | - /* (276) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==276); | |
| 136210 | - /* (277) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=277); | |
| 136211 | - /* (278) ecmd ::= SEMI */ yytestcase(yyruleno==278); | |
| 136212 | - /* (279) ecmd ::= explain cmdx SEMI */ yytestcase(yyruleno==279); | |
| 136213 | - /* (280) explain ::= */ yytestcase(yyruleno==280); | |
| 136214 | - /* (281) trans_opt ::= */ yytestcase(yyruleno==281); | |
| 136215 | - /* (282) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==282); | |
| 136216 | - /* (283) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==283); | |
| 136217 | - /* (284) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==284); | |
| 136218 | - /* (285) savepoint_opt ::= */ yytestcase(yyruleno==285); | |
| 136219 | - /* (286) cmd ::= create_table create_table_args */ yytestcase(yyruleno==286); | |
| 136220 | - /* (287) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==287); | |
| 136221 | - /* (288) columnlist ::= columnname carglist */ yytestcase(yyruleno==288); | |
| 136222 | - /* (289) nm ::= ID|INDEXED */ yytestcase(yyruleno==289); | |
| 136223 | - /* (290) nm ::= STRING */ yytestcase(yyruleno==290); | |
| 136224 | - /* (291) nm ::= JOIN_KW */ yytestcase(yyruleno==291); | |
| 136225 | - /* (292) typetoken ::= typename */ yytestcase(yyruleno==292); | |
| 136226 | - /* (293) typename ::= ID|STRING */ yytestcase(yyruleno==293); | |
| 136227 | - /* (294) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=294); | |
| 136228 | - /* (295) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=295); | |
| 136229 | - /* (296) carglist ::= carglist ccons */ yytestcase(yyruleno==296); | |
| 136230 | - /* (297) carglist ::= */ yytestcase(yyruleno==297); | |
| 136231 | - /* (298) ccons ::= NULL onconf */ yytestcase(yyruleno==298); | |
| 136232 | - /* (299) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==299); | |
| 136233 | - /* (300) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==300); | |
| 136234 | - /* (301) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=301); | |
| 136235 | - /* (302) tconscomma ::= */ yytestcase(yyruleno==302); | |
| 136236 | - /* (303) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=303); | |
| 136237 | - /* (304) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=304); | |
| 136238 | - /* (305) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=305); | |
| 136239 | - /* (306) oneselect ::= values */ yytestcase(yyruleno==306); | |
| 136240 | - /* (307) sclp ::= selcollist COMMA */ yytestcase(yyruleno==307); | |
| 136241 | - /* (308) as ::= ID|STRING */ yytestcase(yyruleno==308); | |
| 136242 | - /* (309) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=309); | |
| 136243 | - /* (310) exprlist ::= nexprlist */ yytestcase(yyruleno==310); | |
| 136244 | - /* (311) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=311); | |
| 136245 | - /* (312) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=312); | |
| 136246 | - /* (313) nmnum ::= ON */ yytestcase(yyruleno==313); | |
| 136247 | - /* (314) nmnum ::= DELETE */ yytestcase(yyruleno==314); | |
| 136248 | - /* (315) nmnum ::= DEFAULT */ yytestcase(yyruleno==315); | |
| 136249 | - /* (316) plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==316); | |
| 136250 | - /* (317) foreach_clause ::= */ yytestcase(yyruleno==317); | |
| 136251 | - /* (318) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==318); | |
| 136252 | - /* (319) trnm ::= nm */ yytestcase(yyruleno==319); | |
| 136253 | - /* (320) tridxby ::= */ yytestcase(yyruleno==320); | |
| 136254 | - /* (321) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==321); | |
| 136255 | - /* (322) database_kw_opt ::= */ yytestcase(yyruleno==322); | |
| 136256 | - /* (323) kwcolumn_opt ::= */ yytestcase(yyruleno==323); | |
| 136257 | - /* (324) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==324); | |
| 136258 | - /* (325) vtabarglist ::= vtabarg */ yytestcase(yyruleno==325); | |
| 136259 | - /* (326) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==326); | |
| 136260 | - /* (327) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==327); | |
| 136261 | - /* (328) anylist ::= */ yytestcase(yyruleno==328); | |
| 136262 | - /* (329) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==329); | |
| 136263 | - /* (330) anylist ::= anylist ANY */ yytestcase(yyruleno==330); | |
| 136285 | + /* (276) input ::= cmdlist */ yytestcase(yyruleno==276); | |
| 136286 | + /* (277) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==277); | |
| 136287 | + /* (278) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=278); | |
| 136288 | + /* (279) ecmd ::= SEMI */ yytestcase(yyruleno==279); | |
| 136289 | + /* (280) ecmd ::= explain cmdx SEMI */ yytestcase(yyruleno==280); | |
| 136290 | + /* (281) explain ::= */ yytestcase(yyruleno==281); | |
| 136291 | + /* (282) trans_opt ::= */ yytestcase(yyruleno==282); | |
| 136292 | + /* (283) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==283); | |
| 136293 | + /* (284) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==284); | |
| 136294 | + /* (285) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==285); | |
| 136295 | + /* (286) savepoint_opt ::= */ yytestcase(yyruleno==286); | |
| 136296 | + /* (287) cmd ::= create_table create_table_args */ yytestcase(yyruleno==287); | |
| 136297 | + /* (288) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==288); | |
| 136298 | + /* (289) columnlist ::= columnname carglist */ yytestcase(yyruleno==289); | |
| 136299 | + /* (290) nm ::= ID|INDEXED */ yytestcase(yyruleno==290); | |
| 136300 | + /* (291) nm ::= STRING */ yytestcase(yyruleno==291); | |
| 136301 | + /* (292) nm ::= JOIN_KW */ yytestcase(yyruleno==292); | |
| 136302 | + /* (293) typetoken ::= typename */ yytestcase(yyruleno==293); | |
| 136303 | + /* (294) typename ::= ID|STRING */ yytestcase(yyruleno==294); | |
| 136304 | + /* (295) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=295); | |
| 136305 | + /* (296) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=296); | |
| 136306 | + /* (297) carglist ::= carglist ccons */ yytestcase(yyruleno==297); | |
| 136307 | + /* (298) carglist ::= */ yytestcase(yyruleno==298); | |
| 136308 | + /* (299) ccons ::= NULL onconf */ yytestcase(yyruleno==299); | |
| 136309 | + /* (300) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==300); | |
| 136310 | + /* (301) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==301); | |
| 136311 | + /* (302) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=302); | |
| 136312 | + /* (303) tconscomma ::= */ yytestcase(yyruleno==303); | |
| 136313 | + /* (304) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=304); | |
| 136314 | + /* (305) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=305); | |
| 136315 | + /* (306) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=306); | |
| 136316 | + /* (307) oneselect ::= values */ yytestcase(yyruleno==307); | |
| 136317 | + /* (308) sclp ::= selcollist COMMA */ yytestcase(yyruleno==308); | |
| 136318 | + /* (309) as ::= ID|STRING */ yytestcase(yyruleno==309); | |
| 136319 | + /* (310) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=310); | |
| 136320 | + /* (311) exprlist ::= nexprlist */ yytestcase(yyruleno==311); | |
| 136321 | + /* (312) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=312); | |
| 136322 | + /* (313) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=313); | |
| 136323 | + /* (314) nmnum ::= ON */ yytestcase(yyruleno==314); | |
| 136324 | + /* (315) nmnum ::= DELETE */ yytestcase(yyruleno==315); | |
| 136325 | + /* (316) nmnum ::= DEFAULT */ yytestcase(yyruleno==316); | |
| 136326 | + /* (317) plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==317); | |
| 136327 | + /* (318) foreach_clause ::= */ yytestcase(yyruleno==318); | |
| 136328 | + /* (319) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==319); | |
| 136329 | + /* (320) trnm ::= nm */ yytestcase(yyruleno==320); | |
| 136330 | + /* (321) tridxby ::= */ yytestcase(yyruleno==321); | |
| 136331 | + /* (322) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==322); | |
| 136332 | + /* (323) database_kw_opt ::= */ yytestcase(yyruleno==323); | |
| 136333 | + /* (324) kwcolumn_opt ::= */ yytestcase(yyruleno==324); | |
| 136334 | + /* (325) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==325); | |
| 136335 | + /* (326) vtabarglist ::= vtabarg */ yytestcase(yyruleno==326); | |
| 136336 | + /* (327) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==327); | |
| 136337 | + /* (328) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==328); | |
| 136338 | + /* (329) anylist ::= */ yytestcase(yyruleno==329); | |
| 136339 | + /* (330) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==330); | |
| 136340 | + /* (331) anylist ::= anylist ANY */ yytestcase(yyruleno==331); | |
| 136264 | 136341 | break; |
| 136265 | 136342 | /********** End reduce actions ************************************************/ |
| 136266 | 136343 | }; |
| 136267 | 136344 | assert( yyruleno<sizeof(yyRuleInfo)/sizeof(yyRuleInfo[0]) ); |
| 136268 | 136345 | yygoto = yyRuleInfo[yyruleno].lhs; |
| @@ -136449,11 +136526,11 @@ | ||
| 136449 | 136526 | } |
| 136450 | 136527 | #endif |
| 136451 | 136528 | yy_destructor(yypParser, (YYCODETYPE)yymajor, &yyminorunion); |
| 136452 | 136529 | yymajor = YYNOCODE; |
| 136453 | 136530 | }else{ |
| 136454 | - while( yypParser->yytos >= &yypParser->yystack | |
| 136531 | + while( yypParser->yytos >= yypParser->yystack | |
| 136455 | 136532 | && yymx != YYERRORSYMBOL |
| 136456 | 136533 | && (yyact = yy_find_reduce_action( |
| 136457 | 136534 | yypParser->yytos->stateno, |
| 136458 | 136535 | YYERRORSYMBOL)) >= YY_MIN_REDUCE |
| 136459 | 136536 | ){ |
| @@ -138617,10 +138694,11 @@ | ||
| 138617 | 138694 | } aFlagOp[] = { |
| 138618 | 138695 | { SQLITE_DBCONFIG_ENABLE_FKEY, SQLITE_ForeignKeys }, |
| 138619 | 138696 | { SQLITE_DBCONFIG_ENABLE_TRIGGER, SQLITE_EnableTrigger }, |
| 138620 | 138697 | { SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER, SQLITE_Fts3Tokenizer }, |
| 138621 | 138698 | { SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, SQLITE_LoadExtension }, |
| 138699 | + { SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE, SQLITE_NoCkptOnClose }, | |
| 138622 | 138700 | }; |
| 138623 | 138701 | unsigned int i; |
| 138624 | 138702 | rc = SQLITE_ERROR; /* IMP: R-42790-23372 */ |
| 138625 | 138703 | for(i=0; i<ArraySize(aFlagOp); i++){ |
| 138626 | 138704 | if( aFlagOp[i].op==op ){ |
| @@ -139913,10 +139991,17 @@ | ||
| 139913 | 139991 | db->busyHandler.nBusy = 0; |
| 139914 | 139992 | rc = sqlite3Checkpoint(db, iDb, eMode, pnLog, pnCkpt); |
| 139915 | 139993 | sqlite3Error(db, rc); |
| 139916 | 139994 | } |
| 139917 | 139995 | rc = sqlite3ApiExit(db, rc); |
| 139996 | + | |
| 139997 | + /* If there are no active statements, clear the interrupt flag at this | |
| 139998 | + ** point. */ | |
| 139999 | + if( db->nVdbeActive==0 ){ | |
| 140000 | + db->u1.isInterrupted = 0; | |
| 140001 | + } | |
| 140002 | + | |
| 139918 | 140003 | sqlite3_mutex_leave(db->mutex); |
| 139919 | 140004 | return rc; |
| 139920 | 140005 | #endif |
| 139921 | 140006 | } |
| 139922 | 140007 | |
| @@ -140415,10 +140500,11 @@ | ||
| 140415 | 140500 | int octet = (sqlite3HexToInt(zUri[iIn++]) << 4); |
| 140416 | 140501 | octet += sqlite3HexToInt(zUri[iIn++]); |
| 140417 | 140502 | |
| 140418 | 140503 | assert( octet>=0 && octet<256 ); |
| 140419 | 140504 | if( octet==0 ){ |
| 140505 | +#ifndef SQLITE_ENABLE_URI_00_ERROR | |
| 140420 | 140506 | /* This branch is taken when "%00" appears within the URI. In this |
| 140421 | 140507 | ** case we ignore all text in the remainder of the path, name or |
| 140422 | 140508 | ** value currently being parsed. So ignore the current character |
| 140423 | 140509 | ** and skip to the next "?", "=" or "&", as appropriate. */ |
| 140424 | 140510 | while( (c = zUri[iIn])!=0 && c!='#' |
| @@ -140427,10 +140513,16 @@ | ||
| 140427 | 140513 | && (eState!=2 || c!='&') |
| 140428 | 140514 | ){ |
| 140429 | 140515 | iIn++; |
| 140430 | 140516 | } |
| 140431 | 140517 | continue; |
| 140518 | +#else | |
| 140519 | + /* If ENABLE_URI_00_ERROR is defined, "%00" in a URI is an error. */ | |
| 140520 | + *pzErrMsg = sqlite3_mprintf("unexpected %%00 in uri"); | |
| 140521 | + rc = SQLITE_ERROR; | |
| 140522 | + goto parse_uri_out; | |
| 140523 | +#endif | |
| 140432 | 140524 | } |
| 140433 | 140525 | c = octet; |
| 140434 | 140526 | }else if( eState==1 && (c=='&' || c=='=') ){ |
| 140435 | 140527 | if( zFile[iOut-1]==0 ){ |
| 140436 | 140528 | /* An empty option name. Ignore this option altogether. */ |
| @@ -164306,14 +164398,16 @@ | ||
| 164306 | 164398 | char *zSql; |
| 164307 | 164399 | sqlite3_stmt *p; |
| 164308 | 164400 | int rc; |
| 164309 | 164401 | i64 nRow = 0; |
| 164310 | 164402 | |
| 164311 | - if( sqlite3_table_column_metadata(db,pRtree->zDb,"sqlite_stat1", | |
| 164312 | - 0,0,0,0,0,0)==SQLITE_ERROR ){ | |
| 164403 | + rc = sqlite3_table_column_metadata( | |
| 164404 | + db, pRtree->zDb, "sqlite_stat1",0,0,0,0,0,0 | |
| 164405 | + ); | |
| 164406 | + if( rc!=SQLITE_OK ){ | |
| 164313 | 164407 | pRtree->nRowEst = RTREE_DEFAULT_ROWEST; |
| 164314 | - return SQLITE_OK; | |
| 164408 | + return rc==SQLITE_ERROR ? SQLITE_OK : rc; | |
| 164315 | 164409 | } |
| 164316 | 164410 | zSql = sqlite3_mprintf(zFmt, pRtree->zDb, pRtree->zName); |
| 164317 | 164411 | if( zSql==0 ){ |
| 164318 | 164412 | rc = SQLITE_NOMEM; |
| 164319 | 164413 | }else{ |
| @@ -165210,11 +165304,11 @@ | ||
| 165210 | 165304 | ** of the locale to use. Passing an empty string ("") or SQL NULL value |
| 165211 | 165305 | ** as the second argument is the same as invoking the 1 argument version |
| 165212 | 165306 | ** of upper() or lower(). |
| 165213 | 165307 | ** |
| 165214 | 165308 | ** lower('I', 'en_us') -> 'i' |
| 165215 | -** lower('I', 'tr_tr') -> 'ı' (small dotless i) | |
| 165309 | +** lower('I', 'tr_tr') -> '\u131' (small dotless i) | |
| 165216 | 165310 | ** |
| 165217 | 165311 | ** http://www.icu-project.org/userguide/posix.html#case_mappings |
| 165218 | 165312 | */ |
| 165219 | 165313 | static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){ |
| 165220 | 165314 | const UChar *zInput; /* Pointer to input string */ |
| @@ -181140,11 +181234,11 @@ | ||
| 181140 | 181234 | } |
| 181141 | 181235 | #endif |
| 181142 | 181236 | fts5yy_destructor(fts5yypParser, (fts5YYCODETYPE)fts5yymajor, &fts5yyminorunion); |
| 181143 | 181237 | fts5yymajor = fts5YYNOCODE; |
| 181144 | 181238 | }else{ |
| 181145 | - while( fts5yypParser->fts5yytos >= &fts5yypParser->fts5yystack | |
| 181239 | + while( fts5yypParser->fts5yytos >= fts5yypParser->fts5yystack | |
| 181146 | 181240 | && fts5yymx != fts5YYERRORSYMBOL |
| 181147 | 181241 | && (fts5yyact = fts5yy_find_reduce_action( |
| 181148 | 181242 | fts5yypParser->fts5yytos->stateno, |
| 181149 | 181243 | fts5YYERRORSYMBOL)) >= fts5YY_MIN_REDUCE |
| 181150 | 181244 | ){ |
| @@ -181506,10 +181600,13 @@ | ||
| 181506 | 181600 | int nToken, /* Size of token in bytes */ |
| 181507 | 181601 | int iStartOff, /* Start offset of token */ |
| 181508 | 181602 | int iEndOff /* End offset of token */ |
| 181509 | 181603 | ){ |
| 181510 | 181604 | int rc = SQLITE_OK; |
| 181605 | + | |
| 181606 | + UNUSED_PARAM2(pToken, nToken); | |
| 181607 | + UNUSED_PARAM(iEndOff); | |
| 181511 | 181608 | |
| 181512 | 181609 | if( (tflags & FTS5_TOKEN_COLOCATED)==0 ){ |
| 181513 | 181610 | Fts5SFinder *p = (Fts5SFinder*)pContext; |
| 181514 | 181611 | if( p->iPos>0 ){ |
| 181515 | 181612 | int i; |
| @@ -181662,11 +181759,10 @@ | ||
| 181662 | 181759 | for(jj=0; jj<(sFinder.nFirst-1); jj++){ |
| 181663 | 181760 | if( sFinder.aFirst[jj+1]>io ) break; |
| 181664 | 181761 | } |
| 181665 | 181762 | |
| 181666 | 181763 | if( sFinder.aFirst[jj]<io ){ |
| 181667 | - int nScore; | |
| 181668 | 181764 | memset(aSeen, 0, nPhrase); |
| 181669 | 181765 | rc = fts5SnippetScore(pApi, pFts, nDocsize, aSeen, i, |
| 181670 | 181766 | sFinder.aFirst[jj], nToken, &nScore, 0 |
| 181671 | 181767 | ); |
| 181672 | 181768 | |
| @@ -195597,11 +195693,11 @@ | ||
| 195597 | 195693 | int nArg, /* Number of args */ |
| 195598 | 195694 | sqlite3_value **apUnused /* Function arguments */ |
| 195599 | 195695 | ){ |
| 195600 | 195696 | assert( nArg==0 ); |
| 195601 | 195697 | UNUSED_PARAM2(nArg, apUnused); |
| 195602 | - sqlite3_result_text(pCtx, "fts5: 2016-09-21 19:43:34 0741812d7fcd558479e4849fbb3ba8d03738d018", -1, SQLITE_TRANSIENT); | |
| 195698 | + sqlite3_result_text(pCtx, "fts5: 2016-10-26 16:05:10 ec9dab8054c71d112c68f58a45821b38c2a45677", -1, SQLITE_TRANSIENT); | |
| 195603 | 195699 | } |
| 195604 | 195700 | |
| 195605 | 195701 | static int fts5Init(sqlite3 *db){ |
| 195606 | 195702 | static const sqlite3_module fts5Mod = { |
| 195607 | 195703 | /* iVersion */ 2, |
| 195608 | 195704 |
| --- src/sqlite3.c | |
| +++ src/sqlite3.c | |
| @@ -1,8 +1,8 @@ | |
| 1 | /****************************************************************************** |
| 2 | ** This file is an amalgamation of many separate C source files from SQLite |
| 3 | ** version 3.15.0. By combining all the individual C code files into this |
| 4 | ** single large file, the entire code can be compiled as a single translation |
| 5 | ** unit. This allows many compilers to do optimizations that would not be |
| 6 | ** possible if the files were compiled separately. Performance improvements |
| 7 | ** of 5% or more are commonly seen when SQLite is compiled as a single |
| 8 | ** translation unit. |
| @@ -379,13 +379,13 @@ | |
| 379 | ** |
| 380 | ** See also: [sqlite3_libversion()], |
| 381 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 382 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 383 | */ |
| 384 | #define SQLITE_VERSION "3.15.0" |
| 385 | #define SQLITE_VERSION_NUMBER 3015000 |
| 386 | #define SQLITE_SOURCE_ID "2016-09-22 18:53:13 c3774c6a5fe48af91fda28e9e18c6ed9053ea992" |
| 387 | |
| 388 | /* |
| 389 | ** CAPI3REF: Run-Time Library Version Numbers |
| 390 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 391 | ** |
| @@ -1235,10 +1235,16 @@ | |
| 1235 | ** <li>[[SQLITE_FCNTL_HAS_MOVED]] |
| 1236 | ** The [SQLITE_FCNTL_HAS_MOVED] file control interprets its argument as a |
| 1237 | ** pointer to an integer and it writes a boolean into that integer depending |
| 1238 | ** on whether or not the file has been renamed, moved, or deleted since it |
| 1239 | ** was first opened. |
| 1240 | ** |
| 1241 | ** <li>[[SQLITE_FCNTL_WIN32_SET_HANDLE]] |
| 1242 | ** The [SQLITE_FCNTL_WIN32_SET_HANDLE] opcode is used for debugging. This |
| 1243 | ** opcode causes the xFileControl method to swap the file handle with the one |
| 1244 | ** pointed to by the pArg argument. This capability is used during testing |
| @@ -1286,10 +1292,12 @@ | |
| 1286 | #define SQLITE_FCNTL_WAL_BLOCK 24 |
| 1287 | #define SQLITE_FCNTL_ZIPVFS 25 |
| 1288 | #define SQLITE_FCNTL_RBU 26 |
| 1289 | #define SQLITE_FCNTL_VFS_POINTER 27 |
| 1290 | #define SQLITE_FCNTL_JOURNAL_POINTER 28 |
| 1291 | |
| 1292 | /* deprecated names */ |
| 1293 | #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE |
| 1294 | #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE |
| 1295 | #define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO |
| @@ -2238,18 +2246,31 @@ | |
| 2238 | ** does not make a copy of the new main schema name string, so the application |
| 2239 | ** must ensure that the argument passed into this DBCONFIG option is unchanged |
| 2240 | ** until after the database connection closes. |
| 2241 | ** </dd> |
| 2242 | ** |
| 2243 | ** </dl> |
| 2244 | */ |
| 2245 | #define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */ |
| 2246 | #define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */ |
| 2247 | #define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */ |
| 2248 | #define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */ |
| 2249 | #define SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1004 /* int int* */ |
| 2250 | #define SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1005 /* int int* */ |
| 2251 | |
| 2252 | |
| 2253 | /* |
| 2254 | ** CAPI3REF: Enable Or Disable Extended Result Codes |
| 2255 | ** METHOD: sqlite3 |
| @@ -8915,11 +8936,11 @@ | |
| 8915 | |
| 8916 | /* |
| 8917 | ** CAPI3REF: Set a table filter on a Session Object. |
| 8918 | ** |
| 8919 | ** The second argument (xFilter) is the "filter callback". For changes to rows |
| 8920 | ** in tables that are not attached to the Session oject, the filter is called |
| 8921 | ** to determine whether changes to the table's rows should be tracked or not. |
| 8922 | ** If xFilter returns 0, changes is not tracked. Note that once a table is |
| 8923 | ** attached, xFilter will not be called again. |
| 8924 | */ |
| 8925 | void sqlite3session_table_filter( |
| @@ -9181,11 +9202,11 @@ | |
| 9181 | ** Assuming the changeset blob was created by one of the |
| 9182 | ** [sqlite3session_changeset()], [sqlite3changeset_concat()] or |
| 9183 | ** [sqlite3changeset_invert()] functions, all changes within the changeset |
| 9184 | ** that apply to a single table are grouped together. This means that when |
| 9185 | ** an application iterates through a changeset using an iterator created by |
| 9186 | ** this function, all changes that relate to a single table are visted |
| 9187 | ** consecutively. There is no chance that the iterator will visit a change |
| 9188 | ** the applies to table X, then one for table Y, and then later on visit |
| 9189 | ** another change for table X. |
| 9190 | */ |
| 9191 | int sqlite3changeset_start( |
| @@ -9268,11 +9289,11 @@ | |
| 9268 | ** If successful, *pabPK is set to point to an array of nCol entries, where |
| 9269 | ** nCol is the number of columns in the table. Elements of *pabPK are set to |
| 9270 | ** 0x01 if the corresponding column is part of the tables primary key, or |
| 9271 | ** 0x00 if it is not. |
| 9272 | ** |
| 9273 | ** If argumet pnCol is not NULL, then *pnCol is set to the number of columns |
| 9274 | ** in the table. |
| 9275 | ** |
| 9276 | ** If this function is called when the iterator does not point to a valid |
| 9277 | ** entry, SQLITE_MISUSE is returned and the output variables zeroed. Otherwise, |
| 9278 | ** SQLITE_OK is returned and the output variables populated as described |
| @@ -9543,11 +9564,11 @@ | |
| 9543 | ** Rows within the changeset and changegroup are identified by the values in |
| 9544 | ** their PRIMARY KEY columns. A change in the changeset is considered to |
| 9545 | ** apply to the same row as a change already present in the changegroup if |
| 9546 | ** the two rows have the same primary key. |
| 9547 | ** |
| 9548 | ** Changes to rows that that do not already appear in the changegroup are |
| 9549 | ** simply copied into it. Or, if both the new changeset and the changegroup |
| 9550 | ** contain changes that apply to a single row, the final contents of the |
| 9551 | ** changegroup depends on the type of each change, as follows: |
| 9552 | ** |
| 9553 | ** <table border=1 style="margin-left:8ex;margin-right:8ex"> |
| @@ -11411,13 +11432,13 @@ | |
| 11411 | #define TK_GROUP 127 |
| 11412 | #define TK_HAVING 128 |
| 11413 | #define TK_LIMIT 129 |
| 11414 | #define TK_WHERE 130 |
| 11415 | #define TK_INTO 131 |
| 11416 | #define TK_INTEGER 132 |
| 11417 | #define TK_FLOAT 133 |
| 11418 | #define TK_BLOB 134 |
| 11419 | #define TK_VARIABLE 135 |
| 11420 | #define TK_CASE 136 |
| 11421 | #define TK_WHEN 137 |
| 11422 | #define TK_THEN 138 |
| 11423 | #define TK_ELSE 139 |
| @@ -12675,19 +12696,19 @@ | |
| 12675 | #define OP_SorterData 120 /* synopsis: r[P2]=data */ |
| 12676 | #define OP_RowKey 121 /* synopsis: r[P2]=key */ |
| 12677 | #define OP_RowData 122 /* synopsis: r[P2]=data */ |
| 12678 | #define OP_Rowid 123 /* synopsis: r[P2]=rowid */ |
| 12679 | #define OP_NullRow 124 |
| 12680 | #define OP_SorterInsert 125 |
| 12681 | #define OP_IdxInsert 126 /* synopsis: key=r[P2] */ |
| 12682 | #define OP_IdxDelete 127 /* synopsis: key=r[P2@P3] */ |
| 12683 | #define OP_Seek 128 /* synopsis: Move P3 to P1.rowid */ |
| 12684 | #define OP_IdxRowid 129 /* synopsis: r[P2]=rowid */ |
| 12685 | #define OP_Destroy 130 |
| 12686 | #define OP_Clear 131 |
| 12687 | #define OP_ResetSorter 132 |
| 12688 | #define OP_Real 133 /* same as TK_FLOAT, synopsis: r[P2]=P4 */ |
| 12689 | #define OP_CreateIndex 134 /* synopsis: r[P2]=root iDb=P1 */ |
| 12690 | #define OP_CreateTable 135 /* synopsis: r[P2]=root iDb=P1 */ |
| 12691 | #define OP_ParseSchema 136 |
| 12692 | #define OP_LoadAnalysis 137 |
| 12693 | #define OP_DropTable 138 |
| @@ -12741,11 +12762,11 @@ | |
| 12741 | /* 88 */ 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00,\ |
| 12742 | /* 96 */ 0x00, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,\ |
| 12743 | /* 104 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ |
| 12744 | /* 112 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,\ |
| 12745 | /* 120 */ 0x00, 0x00, 0x00, 0x10, 0x00, 0x04, 0x04, 0x00,\ |
| 12746 | /* 128 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x10,\ |
| 12747 | /* 136 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x10,\ |
| 12748 | /* 144 */ 0x00, 0x04, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00,\ |
| 12749 | /* 152 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10,\ |
| 12750 | /* 160 */ 0x00, 0x00, 0x00,} |
| 12751 | |
| @@ -13030,11 +13051,11 @@ | |
| 13030 | int, |
| 13031 | int, |
| 13032 | int, |
| 13033 | void(*)(DbPage*) |
| 13034 | ); |
| 13035 | SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager); |
| 13036 | SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager*, int, unsigned char*); |
| 13037 | |
| 13038 | /* Functions used to configure a Pager object. */ |
| 13039 | SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(Pager*, int(*)(void *), void *); |
| 13040 | SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager*, u32*, int); |
| @@ -13081,19 +13102,22 @@ | |
| 13081 | SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int n); |
| 13082 | SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint); |
| 13083 | SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager); |
| 13084 | |
| 13085 | #ifndef SQLITE_OMIT_WAL |
| 13086 | SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, int, int*, int*); |
| 13087 | SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager); |
| 13088 | SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager); |
| 13089 | SQLITE_PRIVATE int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen); |
| 13090 | SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager); |
| 13091 | # ifdef SQLITE_ENABLE_SNAPSHOT |
| 13092 | SQLITE_PRIVATE int sqlite3PagerSnapshotGet(Pager *pPager, sqlite3_snapshot **ppSnapshot); |
| 13093 | SQLITE_PRIVATE int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSnapshot); |
| 13094 | # endif |
| 13095 | #endif |
| 13096 | |
| 13097 | #ifdef SQLITE_ENABLE_ZIPVFS |
| 13098 | SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager); |
| 13099 | #endif |
| @@ -14060,10 +14084,11 @@ | |
| 14060 | #define SQLITE_QueryOnly 0x04000000 /* Disable database changes */ |
| 14061 | #define SQLITE_VdbeEQP 0x08000000 /* Debug EXPLAIN QUERY PLAN */ |
| 14062 | #define SQLITE_Vacuum 0x10000000 /* Currently in a VACUUM */ |
| 14063 | #define SQLITE_CellSizeCk 0x20000000 /* Check btree cell sizes on load */ |
| 14064 | #define SQLITE_Fts3Tokenizer 0x40000000 /* Enable fts3_tokenizer(2) */ |
| 14065 | |
| 14066 | |
| 14067 | /* |
| 14068 | ** Bits of the sqlite3.dbOptFlags field that are used by the |
| 14069 | ** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface to |
| @@ -14963,10 +14988,11 @@ | |
| 14963 | #define EP_Unlikely 0x040000 /* unlikely() or likelihood() function */ |
| 14964 | #define EP_ConstFunc 0x080000 /* A SQLITE_FUNC_CONSTANT or _SLOCHNG function */ |
| 14965 | #define EP_CanBeNull 0x100000 /* Can be null despite NOT NULL constraint */ |
| 14966 | #define EP_Subquery 0x200000 /* Tree contains a TK_SELECT operator */ |
| 14967 | #define EP_Alias 0x400000 /* Is an alias for a result set column */ |
| 14968 | |
| 14969 | /* |
| 14970 | ** Combinations of two or more EP_* flags |
| 14971 | */ |
| 14972 | #define EP_Propagate (EP_Collate|EP_Subquery) /* Propagate these bits up tree */ |
| @@ -15514,39 +15540,27 @@ | |
| 15514 | u8 mayAbort; /* True if statement may throw an ABORT exception */ |
| 15515 | u8 hasCompound; /* Need to invoke convertCompoundSelectToSubquery() */ |
| 15516 | u8 okConstFactor; /* OK to factor out constants */ |
| 15517 | u8 disableLookaside; /* Number of times lookaside has been disabled */ |
| 15518 | u8 nColCache; /* Number of entries in aColCache[] */ |
| 15519 | int aTempReg[8]; /* Holding area for temporary registers */ |
| 15520 | int nRangeReg; /* Size of the temporary register block */ |
| 15521 | int iRangeReg; /* First register in temporary register block */ |
| 15522 | int nErr; /* Number of errors seen */ |
| 15523 | int nTab; /* Number of previously allocated VDBE cursors */ |
| 15524 | int nMem; /* Number of memory cells used so far */ |
| 15525 | int nSet; /* Number of sets used so far */ |
| 15526 | int nOpAlloc; /* Number of slots allocated for Vdbe.aOp[] */ |
| 15527 | int szOpAlloc; /* Bytes of memory space allocated for Vdbe.aOp[] */ |
| 15528 | int iFixedOp; /* Never back out opcodes iFixedOp-1 or earlier */ |
| 15529 | int ckBase; /* Base register of data during check constraints */ |
| 15530 | int iSelfTab; /* Table of an index whose exprs are being coded */ |
| 15531 | int iCacheLevel; /* ColCache valid when aColCache[].iLevel<=iCacheLevel */ |
| 15532 | int iCacheCnt; /* Counter used to generate aColCache[].lru values */ |
| 15533 | int nLabel; /* Number of labels used */ |
| 15534 | int *aLabel; /* Space to hold the labels */ |
| 15535 | struct yColCache { |
| 15536 | int iTable; /* Table cursor number */ |
| 15537 | i16 iColumn; /* Table column number */ |
| 15538 | u8 tempReg; /* iReg is a temp register that needs to be freed */ |
| 15539 | int iLevel; /* Nesting level */ |
| 15540 | int iReg; /* Reg with value of this column. 0 means none. */ |
| 15541 | int lru; /* Least recently used entry has the smallest value */ |
| 15542 | } aColCache[SQLITE_N_COLCACHE]; /* One for each column cache entry */ |
| 15543 | ExprList *pConstExpr;/* Constant expressions */ |
| 15544 | Token constraintName;/* Name of the constraint currently being parsed */ |
| 15545 | yDbMask writeMask; /* Start a write transaction on these databases */ |
| 15546 | yDbMask cookieMask; /* Bitmask of schema verified databases */ |
| 15547 | int cookieValue[SQLITE_MAX_ATTACHED+2]; /* Values of cookies to verify */ |
| 15548 | int regRowid; /* Register holding rowid of CREATE TABLE entry */ |
| 15549 | int regRoot; /* Register holding root page number for new objects */ |
| 15550 | int nMaxArg; /* Max args passed to user function by sub-program */ |
| 15551 | #if SELECTTRACE_ENABLED |
| 15552 | int nSelect; /* Number of SELECT statements seen */ |
| @@ -15555,21 +15569,38 @@ | |
| 15555 | #ifndef SQLITE_OMIT_SHARED_CACHE |
| 15556 | int nTableLock; /* Number of locks in aTableLock */ |
| 15557 | TableLock *aTableLock; /* Required table locks for shared-cache mode */ |
| 15558 | #endif |
| 15559 | AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters */ |
| 15560 | |
| 15561 | /* Information used while coding trigger programs. */ |
| 15562 | Parse *pToplevel; /* Parse structure for main program (or NULL) */ |
| 15563 | Table *pTriggerTab; /* Table triggers are being coded for */ |
| 15564 | int addrCrTab; /* Address of OP_CreateTable opcode on CREATE TABLE */ |
| 15565 | u32 nQueryLoop; /* Est number of iterations of a query (10*log2(N)) */ |
| 15566 | u32 oldmask; /* Mask of old.* columns referenced */ |
| 15567 | u32 newmask; /* Mask of new.* columns referenced */ |
| 15568 | u8 eTriggerOp; /* TK_UPDATE, TK_INSERT or TK_DELETE */ |
| 15569 | u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */ |
| 15570 | u8 disableTriggers; /* True to disable triggers */ |
| 15571 | |
| 15572 | /************************************************************************ |
| 15573 | ** Above is constant between recursions. Below is reset before and after |
| 15574 | ** each recursion. The boundary between these two regions is determined |
| 15575 | ** using offsetof(Parse,nVar) so the nVar field must be the first field |
| @@ -15582,11 +15613,10 @@ | |
| 15582 | u8 explain; /* True if the EXPLAIN flag is found on the query */ |
| 15583 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 15584 | u8 declareVtab; /* True if inside sqlite3_declare_vtab() */ |
| 15585 | int nVtabLock; /* Number of virtual tables to lock */ |
| 15586 | #endif |
| 15587 | int nAlias; /* Number of aliased result set columns */ |
| 15588 | int nHeight; /* Expression tree height of current sub-select */ |
| 15589 | #ifndef SQLITE_OMIT_EXPLAIN |
| 15590 | int iSelectId; /* ID of current select for EXPLAIN output */ |
| 15591 | int iNextSelectId; /* Next available select ID for EXPLAIN output */ |
| 15592 | #endif |
| @@ -15594,12 +15624,10 @@ | |
| 15594 | Vdbe *pReprepare; /* VM being reprepared (sqlite3Reprepare()) */ |
| 15595 | const char *zTail; /* All SQL text past the last semicolon parsed */ |
| 15596 | Table *pNewTable; /* A table being constructed by CREATE TABLE */ |
| 15597 | Trigger *pNewTrigger; /* Trigger under construct by a CREATE TRIGGER */ |
| 15598 | const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */ |
| 15599 | Token sNameToken; /* Token with unqualified schema object name */ |
| 15600 | Token sLastToken; /* The last token parsed */ |
| 15601 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 15602 | Token sArg; /* Complete text of a module argument */ |
| 15603 | Table **apVtabLock; /* Pointer to virtual tables needing locking */ |
| 15604 | #endif |
| 15605 | Table *pZombieTab; /* List of Table objects to delete after code gen */ |
| @@ -15606,10 +15634,18 @@ | |
| 15606 | TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */ |
| 15607 | With *pWith; /* Current WITH clause, or NULL */ |
| 15608 | With *pWithToFree; /* Free this WITH object at the end of the parse */ |
| 15609 | }; |
| 15610 | |
| 15611 | /* |
| 15612 | ** Return true if currently inside an sqlite3_declare_vtab() call. |
| 15613 | */ |
| 15614 | #ifdef SQLITE_OMIT_VIRTUALTABLE |
| 15615 | #define IN_DECLARE_VTAB 0 |
| @@ -16169,11 +16205,11 @@ | |
| 16169 | SQLITE_PRIVATE void sqlite3ExprAttachSubtrees(sqlite3*,Expr*,Expr*,Expr*); |
| 16170 | SQLITE_PRIVATE Expr *sqlite3PExpr(Parse*, int, Expr*, Expr*, const Token*); |
| 16171 | SQLITE_PRIVATE void sqlite3PExprAddSelect(Parse*, Expr*, Select*); |
| 16172 | SQLITE_PRIVATE Expr *sqlite3ExprAnd(sqlite3*,Expr*, Expr*); |
| 16173 | SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*); |
| 16174 | SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse*, Expr*); |
| 16175 | SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3*, Expr*); |
| 16176 | SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*); |
| 16177 | SQLITE_PRIVATE ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*); |
| 16178 | SQLITE_PRIVATE void sqlite3ExprListSetSortOrder(ExprList*,int); |
| 16179 | SQLITE_PRIVATE void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int); |
| @@ -16989,20 +17025,17 @@ | |
| 16989 | ** If x is a lower-case ASCII character, then its upper-case equivalent |
| 16990 | ** is (x - 0x20). Therefore toupper() can be implemented as: |
| 16991 | ** |
| 16992 | ** (x & ~(map[x]&0x20)) |
| 16993 | ** |
| 16994 | ** Standard function tolower() is implemented using the sqlite3UpperToLower[] |
| 16995 | ** array. tolower() is used more often than toupper() by SQLite. |
| 16996 | ** |
| 16997 | ** Bit 0x40 is set if the character non-alphanumeric and can be used in an |
| 16998 | ** SQLite identifier. Identifiers are alphanumerics, "_", "$", and any |
| 16999 | ** non-ASCII UTF character. Hence the test for whether or not a character is |
| 17000 | ** part of an identifier is 0x46. |
| 17001 | ** |
| 17002 | ** SQLite's versions are identical to the standard versions assuming a |
| 17003 | ** locale of "C". They are implemented as macros in sqliteInt.h. |
| 17004 | */ |
| 17005 | #ifdef SQLITE_ASCII |
| 17006 | SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[256] = { |
| 17007 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 00..07 ........ */ |
| 17008 | 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, /* 08..0f ........ */ |
| @@ -17071,11 +17104,11 @@ | |
| 17071 | #ifndef SQLITE_SORTER_PMASZ |
| 17072 | # define SQLITE_SORTER_PMASZ 250 |
| 17073 | #endif |
| 17074 | |
| 17075 | /* Statement journals spill to disk when their size exceeds the following |
| 17076 | ** threashold (in bytes). 0 means that statement journals are created and |
| 17077 | ** written to disk immediately (the default behavior for SQLite versions |
| 17078 | ** before 3.12.0). -1 means always keep the entire statement journal in |
| 17079 | ** memory. (The statement journal is also always held entirely in memory |
| 17080 | ** if journal_mode=MEMORY or if temp_store=MEMORY, regardless of this |
| 17081 | ** setting.) |
| @@ -17159,11 +17192,11 @@ | |
| 17159 | |
| 17160 | /* |
| 17161 | ** The value of the "pending" byte must be 0x40000000 (1 byte past the |
| 17162 | ** 1-gibabyte boundary) in a compatible database. SQLite never uses |
| 17163 | ** the database page that contains the pending byte. It never attempts |
| 17164 | ** to read or write that page. The pending byte page is set assign |
| 17165 | ** for use by the VFS layers as space for managing file locks. |
| 17166 | ** |
| 17167 | ** During testing, it is often desirable to move the pending byte to |
| 17168 | ** a different position in the file. This allows code that has to |
| 17169 | ** deal with the pending byte to run on files that are much smaller |
| @@ -17260,10 +17293,13 @@ | |
| 17260 | #if SQLITE_DEFAULT_LOCKING_MODE |
| 17261 | "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE), |
| 17262 | #endif |
| 17263 | #if defined(SQLITE_DEFAULT_MMAP_SIZE) && !defined(SQLITE_DEFAULT_MMAP_SIZE_xc) |
| 17264 | "DEFAULT_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_MMAP_SIZE), |
| 17265 | #endif |
| 17266 | #if SQLITE_DISABLE_DIRSYNC |
| 17267 | "DISABLE_DIRSYNC", |
| 17268 | #endif |
| 17269 | #if SQLITE_DISABLE_LFS |
| @@ -17346,10 +17382,13 @@ | |
| 17346 | #if SQLITE_ENABLE_UNLOCK_NOTIFY |
| 17347 | "ENABLE_UNLOCK_NOTIFY", |
| 17348 | #endif |
| 17349 | #if SQLITE_ENABLE_UPDATE_DELETE_LIMIT |
| 17350 | "ENABLE_UPDATE_DELETE_LIMIT", |
| 17351 | #endif |
| 17352 | #if SQLITE_HAS_CODEC |
| 17353 | "HAS_CODEC", |
| 17354 | #endif |
| 17355 | #if HAVE_ISNAN || SQLITE_HAVE_ISNAN |
| @@ -17719,13 +17758,10 @@ | |
| 17719 | typedef unsigned Bool; |
| 17720 | |
| 17721 | /* Opaque type used by code in vdbesort.c */ |
| 17722 | typedef struct VdbeSorter VdbeSorter; |
| 17723 | |
| 17724 | /* Opaque type used by the explainer */ |
| 17725 | typedef struct Explain Explain; |
| 17726 | |
| 17727 | /* Elements of the linked list at Vdbe.pAuxData */ |
| 17728 | typedef struct AuxData AuxData; |
| 17729 | |
| 17730 | /* Types of VDBE cursors */ |
| 17731 | #define CURTYPE_BTREE 0 |
| @@ -17796,10 +17832,16 @@ | |
| 17796 | /* 2*nField extra array elements allocated for aType[], beyond the one |
| 17797 | ** static element declared in the structure. nField total array slots for |
| 17798 | ** aType[] and nField+1 array slots for aOffset[] */ |
| 17799 | }; |
| 17800 | |
| 17801 | /* |
| 17802 | ** When a sub-program is executed (OP_Program), a structure of this type |
| 17803 | ** is allocated to store the current value of the program counter, as |
| 17804 | ** well as the current memory cell array and various other frame specific |
| 17805 | ** values stored in the Vdbe struct. When the sub-program is finished, |
| @@ -17840,15 +17882,10 @@ | |
| 17840 | int nDbChange; /* Value of db->nChange */ |
| 17841 | }; |
| 17842 | |
| 17843 | #define VdbeFrameMem(p) ((Mem *)&((u8 *)p)[ROUND8(sizeof(VdbeFrame))]) |
| 17844 | |
| 17845 | /* |
| 17846 | ** A value for VdbeCursor.cacheValid that means the cache is always invalid. |
| 17847 | */ |
| 17848 | #define CACHE_STALE 0 |
| 17849 | |
| 17850 | /* |
| 17851 | ** Internally, the vdbe manipulates nearly all SQL values as Mem |
| 17852 | ** structures. Each Mem struct may cache multiple representations (string, |
| 17853 | ** integer etc.) of the same value. |
| 17854 | */ |
| @@ -17985,22 +18022,10 @@ | |
| 17985 | u8 fErrorOrAux; /* isError!=0 or pVdbe->pAuxData modified */ |
| 17986 | u8 argc; /* Number of arguments */ |
| 17987 | sqlite3_value *argv[1]; /* Argument set */ |
| 17988 | }; |
| 17989 | |
| 17990 | /* |
| 17991 | ** An Explain object accumulates indented output which is helpful |
| 17992 | ** in describing recursive data structures. |
| 17993 | */ |
| 17994 | struct Explain { |
| 17995 | Vdbe *pVdbe; /* Attach the explanation to this Vdbe */ |
| 17996 | StrAccum str; /* The string being accumulated */ |
| 17997 | int nIndent; /* Number of elements in aIndent */ |
| 17998 | u16 aIndent[100]; /* Levels of indentation */ |
| 17999 | char zBase[100]; /* Initial space */ |
| 18000 | }; |
| 18001 | |
| 18002 | /* A bitfield type for use inside of structures. Always follow with :N where |
| 18003 | ** N is the number of bits. |
| 18004 | */ |
| 18005 | typedef unsigned bft; /* Bit Field Type */ |
| 18006 | |
| @@ -18021,57 +18046,61 @@ | |
| 18021 | ** The "sqlite3_stmt" structure pointer that is returned by sqlite3_prepare() |
| 18022 | ** is really a pointer to an instance of this structure. |
| 18023 | */ |
| 18024 | struct Vdbe { |
| 18025 | sqlite3 *db; /* The database connection that owns this statement */ |
| 18026 | Op *aOp; /* Space to hold the virtual machine's program */ |
| 18027 | Mem *aMem; /* The memory locations */ |
| 18028 | Mem **apArg; /* Arguments to currently executing user function */ |
| 18029 | Mem *aColName; /* Column names to return */ |
| 18030 | Mem *pResultSet; /* Pointer to an array of results */ |
| 18031 | Parse *pParse; /* Parsing context used to create this Vdbe */ |
| 18032 | int nMem; /* Number of memory locations currently allocated */ |
| 18033 | int nOp; /* Number of instructions in the program */ |
| 18034 | int nCursor; /* Number of slots in apCsr[] */ |
| 18035 | u32 magic; /* Magic number for sanity checking */ |
| 18036 | char *zErrMsg; /* Error message written here */ |
| 18037 | Vdbe *pPrev,*pNext; /* Linked list of VDBEs with the same Vdbe.db */ |
| 18038 | VdbeCursor **apCsr; /* One element of this array for each open cursor */ |
| 18039 | Mem *aVar; /* Values for the OP_Variable opcode. */ |
| 18040 | char **azVar; /* Name of variables */ |
| 18041 | ynVar nVar; /* Number of entries in aVar[] */ |
| 18042 | ynVar nzVar; /* Number of entries in azVar[] */ |
| 18043 | u32 cacheCtr; /* VdbeCursor row cache generation counter */ |
| 18044 | int pc; /* The program counter */ |
| 18045 | int rc; /* Value to return */ |
| 18046 | #ifdef SQLITE_DEBUG |
| 18047 | int rcApp; /* errcode set by sqlite3_result_error_code() */ |
| 18048 | #endif |
| 18049 | u16 nResColumn; /* Number of columns in one row of the result set */ |
| 18050 | u8 errorAction; /* Recovery action to do in case of an error */ |
| 18051 | bft expired:1; /* True if the VM needs to be recompiled */ |
| 18052 | bft doingRerun:1; /* True if rerunning after an auto-reprepare */ |
| 18053 | u8 minWriteFileFormat; /* Minimum file format for writable database files */ |
| 18054 | bft explain:2; /* True if EXPLAIN present on SQL command */ |
| 18055 | bft changeCntOn:1; /* True to update the change-counter */ |
| 18056 | bft runOnlyOnce:1; /* Automatically expire on reset */ |
| 18057 | bft usesStmtJournal:1; /* True if uses a statement journal */ |
| 18058 | bft readOnly:1; /* True for statements that do not write */ |
| 18059 | bft bIsReader:1; /* True for statements that read */ |
| 18060 | bft isPrepareV2:1; /* True if prepared with prepare_v2() */ |
| 18061 | int nChange; /* Number of db changes made since last reset */ |
| 18062 | yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */ |
| 18063 | yDbMask lockMask; /* Subset of btreeMask that requires a lock */ |
| 18064 | int iStatement; /* Statement number (or 0 if has not opened stmt) */ |
| 18065 | u32 aCounter[5]; /* Counters used by sqlite3_stmt_status() */ |
| 18066 | #ifndef SQLITE_OMIT_TRACE |
| 18067 | i64 startTime; /* Time when query started - used for profiling */ |
| 18068 | #endif |
| 18069 | i64 iCurrentTime; /* Value of julianday('now') for this statement */ |
| 18070 | i64 nFkConstraint; /* Number of imm. FK constraints this VM */ |
| 18071 | i64 nStmtDefCons; /* Number of def. constraints when stmt started */ |
| 18072 | i64 nStmtDefImmCons; /* Number of def. imm constraints when stmt started */ |
| 18073 | char *zSql; /* Text of the SQL statement that generated this */ |
| 18074 | void *pFree; /* Free this when deleting the vdbe */ |
| 18075 | VdbeFrame *pFrame; /* Parent frame */ |
| 18076 | VdbeFrame *pDelFrame; /* List of frame objects to free on VM reset */ |
| 18077 | int nFrame; /* Number of frames in pFrame list */ |
| @@ -18086,14 +18115,15 @@ | |
| 18086 | }; |
| 18087 | |
| 18088 | /* |
| 18089 | ** The following are allowed values for Vdbe.magic |
| 18090 | */ |
| 18091 | #define VDBE_MAGIC_INIT 0x26bceaa5 /* Building a VDBE program */ |
| 18092 | #define VDBE_MAGIC_RUN 0xbdf20da3 /* VDBE is ready to execute */ |
| 18093 | #define VDBE_MAGIC_HALT 0x519c2973 /* VDBE has completed execution */ |
| 18094 | #define VDBE_MAGIC_DEAD 0xb606c3c8 /* The VDBE has been deallocated */ |
| 18095 | |
| 18096 | /* |
| 18097 | ** Structure used to store the context required by the |
| 18098 | ** sqlite3_preupdate_*() API functions. |
| 18099 | */ |
| @@ -18106,12 +18136,12 @@ | |
| 18106 | UnpackedRecord *pUnpacked; /* Unpacked version of aRecord[] */ |
| 18107 | UnpackedRecord *pNewUnpacked; /* Unpacked version of new.* record */ |
| 18108 | int iNewReg; /* Register for new.* values */ |
| 18109 | i64 iKey1; /* First key value passed to hook */ |
| 18110 | i64 iKey2; /* Second key value passed to hook */ |
| 18111 | int iPKey; /* If not negative index of IPK column */ |
| 18112 | Mem *aNew; /* Array of new.* values */ |
| 18113 | }; |
| 18114 | |
| 18115 | /* |
| 18116 | ** Function prototypes |
| 18117 | */ |
| @@ -24599,13 +24629,12 @@ | |
| 24599 | char *zNew; |
| 24600 | size_t n; |
| 24601 | if( z==0 ){ |
| 24602 | return 0; |
| 24603 | } |
| 24604 | n = sqlite3Strlen30(z) + 1; |
| 24605 | assert( (n&0x7fffffff)==n ); |
| 24606 | zNew = sqlite3DbMallocRaw(db, (int)n); |
| 24607 | if( zNew ){ |
| 24608 | memcpy(zNew, z, n); |
| 24609 | } |
| 24610 | return zNew; |
| 24611 | } |
| @@ -28775,11 +28804,15 @@ | |
| 28775 | */ |
| 28776 | static unsigned int strHash(const char *z){ |
| 28777 | unsigned int h = 0; |
| 28778 | unsigned char c; |
| 28779 | while( (c = (unsigned char)*z++)!=0 ){ /*OPTIMIZATION-IF-TRUE*/ |
| 28780 | h = (h<<3) ^ h ^ sqlite3UpperToLower[c]; |
| 28781 | } |
| 28782 | return h; |
| 28783 | } |
| 28784 | |
| 28785 | |
| @@ -29124,19 +29157,19 @@ | |
| 29124 | /* 120 */ "SorterData" OpHelp("r[P2]=data"), |
| 29125 | /* 121 */ "RowKey" OpHelp("r[P2]=key"), |
| 29126 | /* 122 */ "RowData" OpHelp("r[P2]=data"), |
| 29127 | /* 123 */ "Rowid" OpHelp("r[P2]=rowid"), |
| 29128 | /* 124 */ "NullRow" OpHelp(""), |
| 29129 | /* 125 */ "SorterInsert" OpHelp(""), |
| 29130 | /* 126 */ "IdxInsert" OpHelp("key=r[P2]"), |
| 29131 | /* 127 */ "IdxDelete" OpHelp("key=r[P2@P3]"), |
| 29132 | /* 128 */ "Seek" OpHelp("Move P3 to P1.rowid"), |
| 29133 | /* 129 */ "IdxRowid" OpHelp("r[P2]=rowid"), |
| 29134 | /* 130 */ "Destroy" OpHelp(""), |
| 29135 | /* 131 */ "Clear" OpHelp(""), |
| 29136 | /* 132 */ "ResetSorter" OpHelp(""), |
| 29137 | /* 133 */ "Real" OpHelp("r[P2]=P4"), |
| 29138 | /* 134 */ "CreateIndex" OpHelp("r[P2]=root iDb=P1"), |
| 29139 | /* 135 */ "CreateTable" OpHelp("r[P2]=root iDb=P1"), |
| 29140 | /* 136 */ "ParseSchema" OpHelp(""), |
| 29141 | /* 137 */ "LoadAnalysis" OpHelp(""), |
| 29142 | /* 138 */ "DropTable" OpHelp(""), |
| @@ -40671,10 +40704,16 @@ | |
| 40671 | a[1] = winIoerrRetryDelay; |
| 40672 | } |
| 40673 | OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); |
| 40674 | return SQLITE_OK; |
| 40675 | } |
| 40676 | #ifdef SQLITE_TEST |
| 40677 | case SQLITE_FCNTL_WIN32_SET_HANDLE: { |
| 40678 | LPHANDLE phFile = (LPHANDLE)pArg; |
| 40679 | HANDLE hOldFile = pFile->h; |
| 40680 | pFile->h = *phFile; |
| @@ -44018,11 +44057,11 @@ | |
| 44018 | ){ |
| 44019 | PgHdr *pPgHdr; |
| 44020 | assert( pPage!=0 ); |
| 44021 | pPgHdr = (PgHdr*)pPage->pExtra; |
| 44022 | assert( pPgHdr->pPage==0 ); |
| 44023 | memset(pPgHdr, 0, sizeof(PgHdr)); |
| 44024 | pPgHdr->pPage = pPage; |
| 44025 | pPgHdr->pData = pPage->pBuf; |
| 44026 | pPgHdr->pExtra = (void *)&pPgHdr[1]; |
| 44027 | memset(pPgHdr->pExtra, 0, pCache->szExtra); |
| 44028 | pPgHdr->pCache = pCache; |
| @@ -44712,11 +44751,11 @@ | |
| 44712 | szBulk = pCache->szAlloc * (i64)pcache1.nInitPage; |
| 44713 | }else{ |
| 44714 | szBulk = -1024 * (i64)pcache1.nInitPage; |
| 44715 | } |
| 44716 | if( szBulk > pCache->szAlloc*(i64)pCache->nMax ){ |
| 44717 | szBulk = pCache->szAlloc*pCache->nMax; |
| 44718 | } |
| 44719 | zBulk = pCache->pBulk = sqlite3Malloc( szBulk ); |
| 44720 | sqlite3EndBenignMalloc(); |
| 44721 | if( zBulk ){ |
| 44722 | int nBulk = sqlite3MallocSize(zBulk)/pCache->szAlloc; |
| @@ -46246,21 +46285,21 @@ | |
| 46246 | #define SQLITE_SYNC_MASK 0x13 /* Mask off the SQLITE_SYNC_* values */ |
| 46247 | |
| 46248 | #ifdef SQLITE_OMIT_WAL |
| 46249 | # define sqlite3WalOpen(x,y,z) 0 |
| 46250 | # define sqlite3WalLimit(x,y) |
| 46251 | # define sqlite3WalClose(w,x,y,z) 0 |
| 46252 | # define sqlite3WalBeginReadTransaction(y,z) 0 |
| 46253 | # define sqlite3WalEndReadTransaction(z) |
| 46254 | # define sqlite3WalDbsize(y) 0 |
| 46255 | # define sqlite3WalBeginWriteTransaction(y) 0 |
| 46256 | # define sqlite3WalEndWriteTransaction(x) 0 |
| 46257 | # define sqlite3WalUndo(x,y,z) 0 |
| 46258 | # define sqlite3WalSavepoint(y,z) |
| 46259 | # define sqlite3WalSavepointUndo(y,z) 0 |
| 46260 | # define sqlite3WalFrames(u,v,w,x,y,z) 0 |
| 46261 | # define sqlite3WalCheckpoint(r,s,t,u,v,w,x,y,z) 0 |
| 46262 | # define sqlite3WalCallback(z) 0 |
| 46263 | # define sqlite3WalExclusiveMode(y,z) 0 |
| 46264 | # define sqlite3WalHeapMemory(z) 0 |
| 46265 | # define sqlite3WalFramesize(z) 0 |
| 46266 | # define sqlite3WalFindFrame(x,y,z) 0 |
| @@ -46274,11 +46313,11 @@ | |
| 46274 | */ |
| 46275 | typedef struct Wal Wal; |
| 46276 | |
| 46277 | /* Open and close a connection to a write-ahead log. */ |
| 46278 | SQLITE_PRIVATE int sqlite3WalOpen(sqlite3_vfs*, sqlite3_file*, const char *, int, i64, Wal**); |
| 46279 | SQLITE_PRIVATE int sqlite3WalClose(Wal *pWal, int sync_flags, int, u8 *); |
| 46280 | |
| 46281 | /* Set the limiting size of a WAL file. */ |
| 46282 | SQLITE_PRIVATE void sqlite3WalLimit(Wal*, i64); |
| 46283 | |
| 46284 | /* Used by readers to open (lock) and close (unlock) a snapshot. A |
| @@ -46317,10 +46356,11 @@ | |
| 46317 | SQLITE_PRIVATE int sqlite3WalFrames(Wal *pWal, int, PgHdr *, Pgno, int, int); |
| 46318 | |
| 46319 | /* Copy pages from the log to the database file */ |
| 46320 | SQLITE_PRIVATE int sqlite3WalCheckpoint( |
| 46321 | Wal *pWal, /* Write-ahead log connection */ |
| 46322 | int eMode, /* One of PASSIVE, FULL and RESTART */ |
| 46323 | int (*xBusy)(void*), /* Function to call when busy */ |
| 46324 | void *pBusyArg, /* Context argument for xBusyHandler */ |
| 46325 | int sync_flags, /* Flags to sync db file with (or 0) */ |
| 46326 | int nBuf, /* Size of buffer nBuf */ |
| @@ -47161,13 +47201,14 @@ | |
| 47161 | /* |
| 47162 | ** Return true if this pager uses a write-ahead log instead of the usual |
| 47163 | ** rollback journal. Otherwise false. |
| 47164 | */ |
| 47165 | #ifndef SQLITE_OMIT_WAL |
| 47166 | static int pagerUseWal(Pager *pPager){ |
| 47167 | return (pPager->pWal!=0); |
| 47168 | } |
| 47169 | #else |
| 47170 | # define pagerUseWal(x) 0 |
| 47171 | # define pagerRollbackWal(x) 0 |
| 47172 | # define pagerWalFrames(v,w,x,y) 0 |
| 47173 | # define pagerOpenWalIfPresent(z) SQLITE_OK |
| @@ -50365,21 +50406,22 @@ | |
| 50365 | ** This function always succeeds. If a transaction is active an attempt |
| 50366 | ** is made to roll it back. If an error occurs during the rollback |
| 50367 | ** a hot journal may be left in the filesystem but no error is returned |
| 50368 | ** to the caller. |
| 50369 | */ |
| 50370 | SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager){ |
| 50371 | u8 *pTmp = (u8 *)pPager->pTmpSpace; |
| 50372 | |
| 50373 | assert( assert_pager_state(pPager) ); |
| 50374 | disable_simulated_io_errors(); |
| 50375 | sqlite3BeginBenignMalloc(); |
| 50376 | pagerFreeMapHdrs(pPager); |
| 50377 | /* pPager->errCode = 0; */ |
| 50378 | pPager->exclusiveMode = 0; |
| 50379 | #ifndef SQLITE_OMIT_WAL |
| 50380 | sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags, pPager->pageSize, pTmp); |
| 50381 | pPager->pWal = 0; |
| 50382 | #endif |
| 50383 | pager_reset(pPager); |
| 50384 | if( MEMDB ){ |
| 50385 | pager_unlock(pPager); |
| @@ -53538,14 +53580,20 @@ | |
| 53538 | ** "PRAGMA wal_blocking_checkpoint" or calls the sqlite3_wal_checkpoint() |
| 53539 | ** or wal_blocking_checkpoint() API functions. |
| 53540 | ** |
| 53541 | ** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART. |
| 53542 | */ |
| 53543 | SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, int eMode, int *pnLog, int *pnCkpt){ |
| 53544 | int rc = SQLITE_OK; |
| 53545 | if( pPager->pWal ){ |
| 53546 | rc = sqlite3WalCheckpoint(pPager->pWal, eMode, |
| 53547 | (eMode==SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler), |
| 53548 | pPager->pBusyHandlerArg, |
| 53549 | pPager->ckptSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace, |
| 53550 | pnLog, pnCkpt |
| 53551 | ); |
| @@ -53673,11 +53721,11 @@ | |
| 53673 | ** Before closing the log file, this function attempts to take an |
| 53674 | ** EXCLUSIVE lock on the database file. If this cannot be obtained, an |
| 53675 | ** error (SQLITE_BUSY) is returned and the log connection is not closed. |
| 53676 | ** If successful, the EXCLUSIVE lock is not released before returning. |
| 53677 | */ |
| 53678 | SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager){ |
| 53679 | int rc = SQLITE_OK; |
| 53680 | |
| 53681 | assert( pPager->journalMode==PAGER_JOURNALMODE_WAL ); |
| 53682 | |
| 53683 | /* If the log file is not already open, but does exist in the file-system, |
| @@ -53701,11 +53749,11 @@ | |
| 53701 | ** the database file, the log and log-summary files will be deleted. |
| 53702 | */ |
| 53703 | if( rc==SQLITE_OK && pPager->pWal ){ |
| 53704 | rc = pagerExclusiveLock(pPager); |
| 53705 | if( rc==SQLITE_OK ){ |
| 53706 | rc = sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags, |
| 53707 | pPager->pageSize, (u8*)pPager->pTmpSpace); |
| 53708 | pPager->pWal = 0; |
| 53709 | pagerFixMaplimit(pPager); |
| 53710 | if( rc && !pPager->exclusiveMode ) pagerUnlockDb(pPager, SHARED_LOCK); |
| 53711 | } |
| @@ -55484,10 +55532,11 @@ | |
| 55484 | ** checkpoint is running (in any other thread or process) at the same |
| 55485 | ** time. |
| 55486 | */ |
| 55487 | static int walCheckpoint( |
| 55488 | Wal *pWal, /* Wal connection */ |
| 55489 | int eMode, /* One of PASSIVE, FULL or RESTART */ |
| 55490 | int (*xBusy)(void*), /* Function to call when busy */ |
| 55491 | void *pBusyArg, /* Context argument for xBusyHandler */ |
| 55492 | int sync_flags, /* Flags for OsSync() (or 0) */ |
| 55493 | u8 *zBuf /* Temporary buffer to use */ |
| @@ -55578,10 +55627,14 @@ | |
| 55578 | |
| 55579 | /* Iterate through the contents of the WAL, copying data to the db file */ |
| 55580 | while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){ |
| 55581 | i64 iOffset; |
| 55582 | assert( walFramePgno(pWal, iFrame)==iDbpage ); |
| 55583 | if( iFrame<=nBackfill || iFrame>mxSafeFrame || iDbpage>mxPage ){ |
| 55584 | continue; |
| 55585 | } |
| 55586 | iOffset = walFrameOffset(iFrame, szPage) + WAL_FRAME_HDRSIZE; |
| 55587 | /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL file */ |
| @@ -55682,10 +55735,11 @@ | |
| 55682 | /* |
| 55683 | ** Close a connection to a log file. |
| 55684 | */ |
| 55685 | SQLITE_PRIVATE int sqlite3WalClose( |
| 55686 | Wal *pWal, /* Wal to close */ |
| 55687 | int sync_flags, /* Flags to pass to OsSync() (or 0) */ |
| 55688 | int nBuf, |
| 55689 | u8 *zBuf /* Buffer of at least nBuf bytes */ |
| 55690 | ){ |
| 55691 | int rc = SQLITE_OK; |
| @@ -55698,17 +55752,18 @@ | |
| 55698 | ** the database. In this case checkpoint the database and unlink both |
| 55699 | ** the wal and wal-index files. |
| 55700 | ** |
| 55701 | ** The EXCLUSIVE lock is not released before returning. |
| 55702 | */ |
| 55703 | rc = sqlite3OsLock(pWal->pDbFd, SQLITE_LOCK_EXCLUSIVE); |
| 55704 | if( rc==SQLITE_OK ){ |
| 55705 | if( pWal->exclusiveMode==WAL_NORMAL_MODE ){ |
| 55706 | pWal->exclusiveMode = WAL_EXCLUSIVE_MODE; |
| 55707 | } |
| 55708 | rc = sqlite3WalCheckpoint( |
| 55709 | pWal, SQLITE_CHECKPOINT_PASSIVE, 0, 0, sync_flags, nBuf, zBuf, 0, 0 |
| 55710 | ); |
| 55711 | if( rc==SQLITE_OK ){ |
| 55712 | int bPersist = -1; |
| 55713 | sqlite3OsFileControlHint( |
| 55714 | pWal->pDbFd, SQLITE_FCNTL_PERSIST_WAL, &bPersist |
| @@ -56952,10 +57007,11 @@ | |
| 56952 | ** If parameter xBusy is not NULL, it is a pointer to a busy-handler |
| 56953 | ** callback. In this case this function runs a blocking checkpoint. |
| 56954 | */ |
| 56955 | SQLITE_PRIVATE int sqlite3WalCheckpoint( |
| 56956 | Wal *pWal, /* Wal connection */ |
| 56957 | int eMode, /* PASSIVE, FULL, RESTART, or TRUNCATE */ |
| 56958 | int (*xBusy)(void*), /* Function to call when busy */ |
| 56959 | void *pBusyArg, /* Context argument for xBusyHandler */ |
| 56960 | int sync_flags, /* Flags to sync db file with (or 0) */ |
| 56961 | int nBuf, /* Size of temporary buffer */ |
| @@ -57026,11 +57082,11 @@ | |
| 57026 | if( rc==SQLITE_OK ){ |
| 57027 | |
| 57028 | if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){ |
| 57029 | rc = SQLITE_CORRUPT_BKPT; |
| 57030 | }else{ |
| 57031 | rc = walCheckpoint(pWal, eMode2, xBusy2, pBusyArg, sync_flags, zBuf); |
| 57032 | } |
| 57033 | |
| 57034 | /* If no error occurred, set the output variables. */ |
| 57035 | if( rc==SQLITE_OK || rc==SQLITE_BUSY ){ |
| 57036 | if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame; |
| @@ -58984,11 +59040,11 @@ | |
| 58984 | int bias, /* Bias search to the high end */ |
| 58985 | int *pRes /* Write search results here */ |
| 58986 | ){ |
| 58987 | int rc; /* Status code */ |
| 58988 | UnpackedRecord *pIdxKey; /* Unpacked index key */ |
| 58989 | char aSpace[200]; /* Temp space for pIdxKey - to avoid a malloc */ |
| 58990 | char *pFree = 0; |
| 58991 | |
| 58992 | if( pKey ){ |
| 58993 | assert( nKey==(i64)(int)nKey ); |
| 58994 | pIdxKey = sqlite3VdbeAllocUnpackedRecord( |
| @@ -60616,23 +60672,30 @@ | |
| 60616 | *ppBtree = p; |
| 60617 | |
| 60618 | btree_open_out: |
| 60619 | if( rc!=SQLITE_OK ){ |
| 60620 | if( pBt && pBt->pPager ){ |
| 60621 | sqlite3PagerClose(pBt->pPager); |
| 60622 | } |
| 60623 | sqlite3_free(pBt); |
| 60624 | sqlite3_free(p); |
| 60625 | *ppBtree = 0; |
| 60626 | }else{ |
| 60627 | /* If the B-Tree was successfully opened, set the pager-cache size to the |
| 60628 | ** default value. Except, when opening on an existing shared pager-cache, |
| 60629 | ** do not change the pager-cache size. |
| 60630 | */ |
| 60631 | if( sqlite3BtreeSchema(p, 0, 0)==0 ){ |
| 60632 | sqlite3PagerSetCachesize(p->pBt->pPager, SQLITE_DEFAULT_CACHE_SIZE); |
| 60633 | } |
| 60634 | } |
| 60635 | if( mutexOpen ){ |
| 60636 | assert( sqlite3_mutex_held(mutexOpen) ); |
| 60637 | sqlite3_mutex_leave(mutexOpen); |
| 60638 | } |
| @@ -60758,11 +60821,11 @@ | |
| 60758 | ** it without having to hold the mutex. |
| 60759 | ** |
| 60760 | ** Clean out and delete the BtShared object. |
| 60761 | */ |
| 60762 | assert( !pBt->pCursor ); |
| 60763 | sqlite3PagerClose(pBt->pPager); |
| 60764 | if( pBt->xFreeSchema && pBt->pSchema ){ |
| 60765 | pBt->xFreeSchema(pBt->pSchema); |
| 60766 | } |
| 60767 | sqlite3DbFree(0, pBt->pSchema); |
| 60768 | freeTempSpace(pBt); |
| @@ -62822,11 +62885,11 @@ | |
| 62822 | if( (eOp&0x01)==0 /* (1) */ |
| 62823 | && offset==0 /* (2) */ |
| 62824 | && (bEnd || a==ovflSize) /* (6) */ |
| 62825 | && pBt->inTransaction==TRANS_READ /* (4) */ |
| 62826 | && (fd = sqlite3PagerFile(pBt->pPager))->pMethods /* (3) */ |
| 62827 | && pBt->pPage1->aData[19]==0x01 /* (5) */ |
| 62828 | && &pBuf[-4]>=pBufStart /* (7) */ |
| 62829 | ){ |
| 62830 | u8 aSave[4]; |
| 62831 | u8 *aWrite = &pBuf[-4]; |
| 62832 | assert( aWrite>=pBufStart ); /* hence (7) */ |
| @@ -63078,13 +63141,16 @@ | |
| 63078 | } |
| 63079 | sqlite3BtreeClearCursor(pCur); |
| 63080 | } |
| 63081 | |
| 63082 | if( pCur->iPage>=0 ){ |
| 63083 | while( pCur->iPage ){ |
| 63084 | assert( pCur->apPage[pCur->iPage]!=0 ); |
| 63085 | releasePageNotNull(pCur->apPage[pCur->iPage--]); |
| 63086 | } |
| 63087 | }else if( pCur->pgnoRoot==0 ){ |
| 63088 | pCur->eState = CURSOR_INVALID; |
| 63089 | return SQLITE_OK; |
| 63090 | }else{ |
| @@ -63091,11 +63157,11 @@ | |
| 63091 | assert( pCur->iPage==(-1) ); |
| 63092 | rc = getAndInitPage(pCur->pBtree->pBt, pCur->pgnoRoot, &pCur->apPage[0], |
| 63093 | 0, pCur->curPagerFlags); |
| 63094 | if( rc!=SQLITE_OK ){ |
| 63095 | pCur->eState = CURSOR_INVALID; |
| 63096 | return rc; |
| 63097 | } |
| 63098 | pCur->iPage = 0; |
| 63099 | pCur->curIntKey = pCur->apPage[0]->intKey; |
| 63100 | } |
| 63101 | pRoot = pCur->apPage[0]; |
| @@ -63114,14 +63180,16 @@ | |
| 63114 | assert( pRoot->intKey==1 || pRoot->intKey==0 ); |
| 63115 | if( pRoot->isInit==0 || (pCur->pKeyInfo==0)!=pRoot->intKey ){ |
| 63116 | return SQLITE_CORRUPT_BKPT; |
| 63117 | } |
| 63118 | |
| 63119 | pCur->aiIdx[0] = 0; |
| 63120 | pCur->info.nSize = 0; |
| 63121 | pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidNKey|BTCF_ValidOvfl); |
| 63122 | |
| 63123 | if( pRoot->nCell>0 ){ |
| 63124 | pCur->eState = CURSOR_VALID; |
| 63125 | }else if( !pRoot->leaf ){ |
| 63126 | Pgno subpage; |
| 63127 | if( pRoot->pgno!=1 ) return SQLITE_CORRUPT_BKPT; |
| @@ -64321,12 +64389,10 @@ | |
| 64321 | nSrc = pX->nData; |
| 64322 | assert( pPage->intKeyLeaf ); /* fillInCell() only called for leaves */ |
| 64323 | nHeader += putVarint32(&pCell[nHeader], nPayload); |
| 64324 | nHeader += putVarint(&pCell[nHeader], *(u64*)&pX->nKey); |
| 64325 | }else{ |
| 64326 | assert( pX->nData==0 ); |
| 64327 | assert( pX->nZero==0 ); |
| 64328 | assert( pX->nKey<=0x7fffffff && pX->pKey!=0 ); |
| 64329 | nSrc = nPayload = (int)pX->nKey; |
| 64330 | pSrc = pX->pKey; |
| 64331 | nHeader += putVarint32(&pCell[nHeader], nPayload); |
| 64332 | } |
| @@ -67700,11 +67766,11 @@ | |
| 67700 | BtShared *pBt = p->pBt; |
| 67701 | sqlite3BtreeEnter(p); |
| 67702 | if( pBt->inTransaction!=TRANS_NONE ){ |
| 67703 | rc = SQLITE_LOCKED; |
| 67704 | }else{ |
| 67705 | rc = sqlite3PagerCheckpoint(pBt->pPager, eMode, pnLog, pnCkpt); |
| 67706 | } |
| 67707 | sqlite3BtreeLeave(p); |
| 67708 | } |
| 67709 | return rc; |
| 67710 | } |
| @@ -68022,26 +68088,20 @@ | |
| 68022 | */ |
| 68023 | static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){ |
| 68024 | int i = sqlite3FindDbName(pDb, zDb); |
| 68025 | |
| 68026 | if( i==1 ){ |
| 68027 | Parse *pParse; |
| 68028 | int rc = 0; |
| 68029 | pParse = sqlite3StackAllocZero(pErrorDb, sizeof(*pParse)); |
| 68030 | if( pParse==0 ){ |
| 68031 | sqlite3ErrorWithMsg(pErrorDb, SQLITE_NOMEM, "out of memory"); |
| 68032 | rc = SQLITE_NOMEM_BKPT; |
| 68033 | }else{ |
| 68034 | pParse->db = pDb; |
| 68035 | if( sqlite3OpenTempDatabase(pParse) ){ |
| 68036 | sqlite3ErrorWithMsg(pErrorDb, pParse->rc, "%s", pParse->zErrMsg); |
| 68037 | rc = SQLITE_ERROR; |
| 68038 | } |
| 68039 | sqlite3DbFree(pErrorDb, pParse->zErrMsg); |
| 68040 | sqlite3ParserReset(pParse); |
| 68041 | sqlite3StackFree(pErrorDb, pParse); |
| 68042 | } |
| 68043 | if( rc ){ |
| 68044 | return 0; |
| 68045 | } |
| 68046 | } |
| 68047 | |
| @@ -69041,10 +69101,11 @@ | |
| 69041 | assert( (pMem->flags&MEM_RowSet)==0 ); |
| 69042 | assert( EIGHT_BYTE_ALIGNMENT(pMem) ); |
| 69043 | |
| 69044 | |
| 69045 | if( sqlite3VdbeMemClearAndResize(pMem, nByte) ){ |
| 69046 | return SQLITE_NOMEM_BKPT; |
| 69047 | } |
| 69048 | |
| 69049 | /* For a Real or Integer, use sqlite3_snprintf() to produce the UTF-8 |
| 69050 | ** string representation of the value. Then, if the required encoding |
| @@ -69340,11 +69401,11 @@ | |
| 69340 | switch( aff ){ |
| 69341 | case SQLITE_AFF_BLOB: { /* Really a cast to BLOB */ |
| 69342 | if( (pMem->flags & MEM_Blob)==0 ){ |
| 69343 | sqlite3ValueApplyAffinity(pMem, SQLITE_AFF_TEXT, encoding); |
| 69344 | assert( pMem->flags & MEM_Str || pMem->db->mallocFailed ); |
| 69345 | MemSetTypeFlag(pMem, MEM_Blob); |
| 69346 | }else{ |
| 69347 | pMem->flags &= ~(MEM_TypeMask&~MEM_Blob); |
| 69348 | } |
| 69349 | break; |
| 69350 | } |
| @@ -70017,14 +70078,11 @@ | |
| 70017 | sqlite3_value *pVal = 0; |
| 70018 | int negInt = 1; |
| 70019 | const char *zNeg = ""; |
| 70020 | int rc = SQLITE_OK; |
| 70021 | |
| 70022 | if( !pExpr ){ |
| 70023 | *ppVal = 0; |
| 70024 | return SQLITE_OK; |
| 70025 | } |
| 70026 | while( (op = pExpr->op)==TK_UPLUS || op==TK_SPAN ) pExpr = pExpr->pLeft; |
| 70027 | if( NEVER(op==TK_REGISTER) ) op = pExpr->op2; |
| 70028 | |
| 70029 | /* Compressed expressions only appear when parsing the DEFAULT clause |
| 70030 | ** on a table column definition, and hence only when pCtx==0. This |
| @@ -70144,11 +70202,11 @@ | |
| 70144 | Expr *pExpr, /* The expression to evaluate */ |
| 70145 | u8 enc, /* Encoding to use */ |
| 70146 | u8 affinity, /* Affinity to use */ |
| 70147 | sqlite3_value **ppVal /* Write the new value here */ |
| 70148 | ){ |
| 70149 | return valueFromExpr(db, pExpr, enc, affinity, ppVal, 0); |
| 70150 | } |
| 70151 | |
| 70152 | #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 |
| 70153 | /* |
| 70154 | ** The implementation of the sqlite_record() function. This function accepts |
| @@ -70487,12 +70545,13 @@ | |
| 70487 | ** Create a new virtual database engine. |
| 70488 | */ |
| 70489 | SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(Parse *pParse){ |
| 70490 | sqlite3 *db = pParse->db; |
| 70491 | Vdbe *p; |
| 70492 | p = sqlite3DbMallocZero(db, sizeof(Vdbe) ); |
| 70493 | if( p==0 ) return 0; |
| 70494 | p->db = db; |
| 70495 | if( db->pVdbe ){ |
| 70496 | db->pVdbe->pPrev = p; |
| 70497 | } |
| 70498 | p->pNext = db->pVdbe; |
| @@ -70650,13 +70709,12 @@ | |
| 70650 | #endif |
| 70651 | #ifdef SQLITE_DEBUG |
| 70652 | if( p->db->flags & SQLITE_VdbeAddopTrace ){ |
| 70653 | int jj, kk; |
| 70654 | Parse *pParse = p->pParse; |
| 70655 | for(jj=kk=0; jj<SQLITE_N_COLCACHE; jj++){ |
| 70656 | struct yColCache *x = pParse->aColCache + jj; |
| 70657 | if( x->iLevel>pParse->iCacheLevel || x->iReg==0 ) continue; |
| 70658 | printf(" r[%d]={%d:%d}", x->iReg, x->iTable, x->iColumn); |
| 70659 | kk++; |
| 70660 | } |
| 70661 | if( kk ) printf("\n"); |
| 70662 | sqlite3VdbePrintOp(0, i, &p->aOp[i]); |
| @@ -70840,11 +70898,10 @@ | |
| 70840 | assert( j<p->nLabel ); |
| 70841 | assert( j>=0 ); |
| 70842 | if( p->aLabel ){ |
| 70843 | p->aLabel[j] = v->nOp; |
| 70844 | } |
| 70845 | p->iFixedOp = v->nOp - 1; |
| 70846 | } |
| 70847 | |
| 70848 | /* |
| 70849 | ** Mark the VDBE as one that can only be run one time. |
| 70850 | */ |
| @@ -71231,19 +71288,19 @@ | |
| 71231 | } |
| 71232 | SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe *p, u32 addr, int val){ |
| 71233 | sqlite3VdbeGetOp(p,addr)->p3 = val; |
| 71234 | } |
| 71235 | SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe *p, u8 p5){ |
| 71236 | if( !p->db->mallocFailed ) p->aOp[p->nOp-1].p5 = p5; |
| 71237 | } |
| 71238 | |
| 71239 | /* |
| 71240 | ** Change the P2 operand of instruction addr so that it points to |
| 71241 | ** the address of the next instruction to be coded. |
| 71242 | */ |
| 71243 | SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe *p, int addr){ |
| 71244 | p->pParse->iFixedOp = p->nOp - 1; |
| 71245 | sqlite3VdbeChangeP2(p, addr, p->nOp); |
| 71246 | } |
| 71247 | |
| 71248 | |
| 71249 | /* |
| @@ -71362,11 +71419,11 @@ | |
| 71362 | /* |
| 71363 | ** If the last opcode is "op" and it is not a jump destination, |
| 71364 | ** then remove it. Return true if and only if an opcode was removed. |
| 71365 | */ |
| 71366 | SQLITE_PRIVATE int sqlite3VdbeDeletePriorOpcode(Vdbe *p, u8 op){ |
| 71367 | if( (p->nOp-1)>(p->pParse->iFixedOp) && p->aOp[p->nOp-1].opcode==op ){ |
| 71368 | return sqlite3VdbeChangeToNoop(p, p->nOp-1); |
| 71369 | }else{ |
| 71370 | return 0; |
| 71371 | } |
| 71372 | } |
| @@ -71924,10 +71981,25 @@ | |
| 71924 | zCom |
| 71925 | ); |
| 71926 | fflush(pOut); |
| 71927 | } |
| 71928 | #endif |
| 71929 | |
| 71930 | /* |
| 71931 | ** Release an array of N Mem elements |
| 71932 | */ |
| 71933 | static void releaseMemArray(Mem *p, int N){ |
| @@ -72136,10 +72208,11 @@ | |
| 72136 | return SQLITE_ERROR; |
| 72137 | } |
| 72138 | pMem->flags = MEM_Str|MEM_Term; |
| 72139 | zP4 = displayP4(pOp, pMem->z, pMem->szMalloc); |
| 72140 | if( zP4!=pMem->z ){ |
| 72141 | sqlite3VdbeMemSetStr(pMem, zP4, -1, SQLITE_UTF8, 0); |
| 72142 | }else{ |
| 72143 | assert( pMem->z!=0 ); |
| 72144 | pMem->n = sqlite3Strlen30(pMem->z); |
| 72145 | pMem->enc = SQLITE_UTF8; |
| @@ -72278,11 +72351,11 @@ | |
| 72278 | SQLITE_PRIVATE void sqlite3VdbeRewind(Vdbe *p){ |
| 72279 | #if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) |
| 72280 | int i; |
| 72281 | #endif |
| 72282 | assert( p!=0 ); |
| 72283 | assert( p->magic==VDBE_MAGIC_INIT ); |
| 72284 | |
| 72285 | /* There should be at least one opcode. |
| 72286 | */ |
| 72287 | assert( p->nOp>0 ); |
| 72288 | |
| @@ -72367,14 +72440,11 @@ | |
| 72367 | n = ROUND8(sizeof(Op)*p->nOp); /* Bytes of opcode memory used */ |
| 72368 | x.pSpace = &((u8*)p->aOp)[n]; /* Unused opcode memory */ |
| 72369 | assert( EIGHT_BYTE_ALIGNMENT(x.pSpace) ); |
| 72370 | x.nFree = ROUNDDOWN8(pParse->szOpAlloc - n); /* Bytes of unused memory */ |
| 72371 | assert( x.nFree>=0 ); |
| 72372 | if( x.nFree>0 ){ |
| 72373 | memset(x.pSpace, 0, x.nFree); |
| 72374 | assert( EIGHT_BYTE_ALIGNMENT(&x.pSpace[x.nFree]) ); |
| 72375 | } |
| 72376 | |
| 72377 | resolveP2Values(p, &nArg); |
| 72378 | p->usesStmtJournal = (u8)(pParse->isMultiWrite && pParse->mayAbort); |
| 72379 | if( pParse->explain && nMem<10 ){ |
| 72380 | nMem = 10; |
| @@ -72399,34 +72469,34 @@ | |
| 72399 | p->apCsr = allocSpace(&x, p->apCsr, nCursor*sizeof(VdbeCursor*)); |
| 72400 | #ifdef SQLITE_ENABLE_STMT_SCANSTATUS |
| 72401 | p->anExec = allocSpace(&x, p->anExec, p->nOp*sizeof(i64)); |
| 72402 | #endif |
| 72403 | if( x.nNeeded==0 ) break; |
| 72404 | x.pSpace = p->pFree = sqlite3DbMallocZero(db, x.nNeeded); |
| 72405 | x.nFree = x.nNeeded; |
| 72406 | }while( !db->mallocFailed ); |
| 72407 | |
| 72408 | p->nCursor = nCursor; |
| 72409 | if( p->aVar ){ |
| 72410 | p->nVar = (ynVar)nVar; |
| 72411 | for(n=0; n<nVar; n++){ |
| 72412 | p->aVar[n].flags = MEM_Null; |
| 72413 | p->aVar[n].db = db; |
| 72414 | } |
| 72415 | } |
| 72416 | p->nzVar = pParse->nzVar; |
| 72417 | p->azVar = pParse->azVar; |
| 72418 | pParse->nzVar = 0; |
| 72419 | pParse->azVar = 0; |
| 72420 | if( p->aMem ){ |
| 72421 | p->nMem = nMem; |
| 72422 | for(n=0; n<nMem; n++){ |
| 72423 | p->aMem[n].flags = MEM_Undefined; |
| 72424 | p->aMem[n].db = db; |
| 72425 | } |
| 72426 | } |
| 72427 | p->explain = pParse->explain; |
| 72428 | sqlite3VdbeRewind(p); |
| 72429 | } |
| 72430 | |
| 72431 | /* |
| 72432 | ** Close a VDBE cursor and release all the resources that cursor |
| @@ -72574,17 +72644,13 @@ | |
| 72574 | |
| 72575 | releaseMemArray(p->aColName, p->nResColumn*COLNAME_N); |
| 72576 | sqlite3DbFree(db, p->aColName); |
| 72577 | n = nResColumn*COLNAME_N; |
| 72578 | p->nResColumn = (u16)nResColumn; |
| 72579 | p->aColName = pColName = (Mem*)sqlite3DbMallocZero(db, sizeof(Mem)*n ); |
| 72580 | if( p->aColName==0 ) return; |
| 72581 | while( n-- > 0 ){ |
| 72582 | pColName->flags = MEM_Null; |
| 72583 | pColName->db = p->db; |
| 72584 | pColName++; |
| 72585 | } |
| 72586 | } |
| 72587 | |
| 72588 | /* |
| 72589 | ** Set the name of the idx'th column to be returned by the SQL statement. |
| 72590 | ** zName must be a pointer to a nul terminated string. |
| @@ -73342,11 +73408,11 @@ | |
| 73342 | fclose(out); |
| 73343 | } |
| 73344 | } |
| 73345 | #endif |
| 73346 | p->iCurrentTime = 0; |
| 73347 | p->magic = VDBE_MAGIC_INIT; |
| 73348 | return p->rc & db->errMask; |
| 73349 | } |
| 73350 | |
| 73351 | /* |
| 73352 | ** Clean up and delete a VDBE after execution. Return an integer which is |
| @@ -73406,23 +73472,25 @@ | |
| 73406 | */ |
| 73407 | SQLITE_PRIVATE void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){ |
| 73408 | SubProgram *pSub, *pNext; |
| 73409 | int i; |
| 73410 | assert( p->db==0 || p->db==db ); |
| 73411 | releaseMemArray(p->aVar, p->nVar); |
| 73412 | releaseMemArray(p->aColName, p->nResColumn*COLNAME_N); |
| 73413 | for(pSub=p->pProgram; pSub; pSub=pNext){ |
| 73414 | pNext = pSub->pNext; |
| 73415 | vdbeFreeOpArray(db, pSub->aOp, pSub->nOp); |
| 73416 | sqlite3DbFree(db, pSub); |
| 73417 | } |
| 73418 | for(i=p->nzVar-1; i>=0; i--) sqlite3DbFree(db, p->azVar[i]); |
| 73419 | sqlite3DbFree(db, p->azVar); |
| 73420 | vdbeFreeOpArray(db, p->aOp, p->nOp); |
| 73421 | sqlite3DbFree(db, p->aColName); |
| 73422 | sqlite3DbFree(db, p->zSql); |
| 73423 | sqlite3DbFree(db, p->pFree); |
| 73424 | #ifdef SQLITE_ENABLE_STMT_SCANSTATUS |
| 73425 | for(i=0; i<p->nScan; i++){ |
| 73426 | sqlite3DbFree(db, p->aScan[i].zName); |
| 73427 | } |
| 73428 | sqlite3DbFree(db, p->aScan); |
| @@ -75073,11 +75141,11 @@ | |
| 75073 | preupdate.keyinfo.enc = ENC(db); |
| 75074 | preupdate.keyinfo.nField = pTab->nCol; |
| 75075 | preupdate.keyinfo.aSortOrder = (u8*)&fakeSortOrder; |
| 75076 | preupdate.iKey1 = iKey1; |
| 75077 | preupdate.iKey2 = iKey2; |
| 75078 | preupdate.iPKey = pTab->iPKey; |
| 75079 | |
| 75080 | db->pPreUpdate = &preupdate; |
| 75081 | db->xPreUpdateCallback(db->pPreUpdateArg, db, op, zDb, zTbl, iKey1, iKey2); |
| 75082 | db->pPreUpdate = 0; |
| 75083 | sqlite3DbFree(db, preupdate.aRecord); |
| @@ -76047,18 +76115,17 @@ | |
| 76047 | static Mem *columnMem(sqlite3_stmt *pStmt, int i){ |
| 76048 | Vdbe *pVm; |
| 76049 | Mem *pOut; |
| 76050 | |
| 76051 | pVm = (Vdbe *)pStmt; |
| 76052 | if( pVm && pVm->pResultSet!=0 && i<pVm->nResColumn && i>=0 ){ |
| 76053 | sqlite3_mutex_enter(pVm->db->mutex); |
| 76054 | pOut = &pVm->pResultSet[i]; |
| 76055 | }else{ |
| 76056 | if( pVm && ALWAYS(pVm->db) ){ |
| 76057 | sqlite3_mutex_enter(pVm->db->mutex); |
| 76058 | sqlite3Error(pVm->db, SQLITE_RANGE); |
| 76059 | } |
| 76060 | pOut = (Mem*)columnNullValue(); |
| 76061 | } |
| 76062 | return pOut; |
| 76063 | } |
| 76064 | |
| @@ -76087,10 +76154,12 @@ | |
| 76087 | ** SQLITE_NOMEM. The next call to _step() (if any) will return SQLITE_ERROR |
| 76088 | ** and _finalize() will return NOMEM. |
| 76089 | */ |
| 76090 | Vdbe *p = (Vdbe *)pStmt; |
| 76091 | if( p ){ |
| 76092 | p->rc = sqlite3ApiExit(p->db, p->rc); |
| 76093 | sqlite3_mutex_leave(p->db->mutex); |
| 76094 | } |
| 76095 | } |
| 76096 | |
| @@ -76663,11 +76732,11 @@ | |
| 76663 | /* |
| 76664 | ** Return true if the prepared statement is in need of being reset. |
| 76665 | */ |
| 76666 | SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt *pStmt){ |
| 76667 | Vdbe *v = (Vdbe*)pStmt; |
| 76668 | return v!=0 && v->pc>=0 && v->magic==VDBE_MAGIC_RUN; |
| 76669 | } |
| 76670 | |
| 76671 | /* |
| 76672 | ** Return a pointer to the next prepared statement after pStmt associated |
| 76673 | ** with database connection pDb. If pStmt is NULL, return the first |
| @@ -76804,13 +76873,18 @@ | |
| 76804 | } |
| 76805 | |
| 76806 | if( iIdx>=p->pUnpacked->nField ){ |
| 76807 | *ppValue = (sqlite3_value *)columnNullValue(); |
| 76808 | }else{ |
| 76809 | *ppValue = &p->pUnpacked->aMem[iIdx]; |
| 76810 | if( iIdx==p->iPKey ){ |
| 76811 | sqlite3VdbeMemSetInt64(*ppValue, p->iKey1); |
| 76812 | } |
| 76813 | } |
| 76814 | |
| 76815 | preupdate_old_out: |
| 76816 | sqlite3Error(db, rc); |
| @@ -76883,11 +76957,11 @@ | |
| 76883 | } |
| 76884 | if( iIdx>=pUnpack->nField ){ |
| 76885 | pMem = (sqlite3_value *)columnNullValue(); |
| 76886 | }else{ |
| 76887 | pMem = &pUnpack->aMem[iIdx]; |
| 76888 | if( iIdx==p->iPKey ){ |
| 76889 | sqlite3VdbeMemSetInt64(pMem, p->iKey2); |
| 76890 | } |
| 76891 | } |
| 76892 | }else{ |
| 76893 | /* For an UPDATE, memory cell (p->iNewReg+1+iIdx) contains the required |
| @@ -76904,11 +76978,11 @@ | |
| 76904 | } |
| 76905 | } |
| 76906 | assert( iIdx>=0 && iIdx<p->pCsr->nField ); |
| 76907 | pMem = &p->aNew[iIdx]; |
| 76908 | if( pMem->flags==0 ){ |
| 76909 | if( iIdx==p->iPKey ){ |
| 76910 | sqlite3VdbeMemSetInt64(pMem, p->iKey2); |
| 76911 | }else{ |
| 76912 | rc = sqlite3VdbeMemCopy(pMem, &p->v->aMem[p->iNewReg+1+iIdx]); |
| 76913 | if( rc!=SQLITE_OK ) goto preupdate_new_out; |
| 76914 | } |
| @@ -78415,15 +78489,17 @@ | |
| 78415 | u16 nullFlag; |
| 78416 | pOut = out2Prerelease(p, pOp); |
| 78417 | cnt = pOp->p3-pOp->p2; |
| 78418 | assert( pOp->p3<=(p->nMem+1 - p->nCursor) ); |
| 78419 | pOut->flags = nullFlag = pOp->p1 ? (MEM_Null|MEM_Cleared) : MEM_Null; |
| 78420 | while( cnt>0 ){ |
| 78421 | pOut++; |
| 78422 | memAboutToChange(p, pOut); |
| 78423 | sqlite3VdbeMemSetNull(pOut); |
| 78424 | pOut->flags = nullFlag; |
| 78425 | cnt--; |
| 78426 | } |
| 78427 | break; |
| 78428 | } |
| 78429 | |
| @@ -79280,12 +79356,11 @@ | |
| 79280 | ** or not both operands are null. |
| 79281 | */ |
| 79282 | assert( pOp->opcode==OP_Eq || pOp->opcode==OP_Ne ); |
| 79283 | assert( (flags1 & MEM_Cleared)==0 ); |
| 79284 | assert( (pOp->p5 & SQLITE_JUMPIFNULL)==0 ); |
| 79285 | if( (flags1&MEM_Null)!=0 |
| 79286 | && (flags3&MEM_Null)!=0 |
| 79287 | && (flags3&MEM_Cleared)==0 |
| 79288 | ){ |
| 79289 | res = 0; /* Operands are equal */ |
| 79290 | }else{ |
| 79291 | res = 1; /* Operands are not equal */ |
| @@ -80487,14 +80562,13 @@ | |
| 80487 | p->nStmtDefCons = db->nDeferredCons; |
| 80488 | p->nStmtDefImmCons = db->nDeferredImmCons; |
| 80489 | } |
| 80490 | |
| 80491 | /* Gather the schema version number for checking: |
| 80492 | ** IMPLEMENTATION-OF: R-32195-19465 The schema version is used by SQLite |
| 80493 | ** each time a query is executed to ensure that the internal cache of the |
| 80494 | ** schema used when compiling the SQL query matches the schema of the |
| 80495 | ** database against which the compiled query is actually executed. |
| 80496 | */ |
| 80497 | sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&iMeta); |
| 80498 | iGen = db->aDb[pOp->p1].pSchema->iGeneration; |
| 80499 | }else{ |
| 80500 | iGen = iMeta = 0; |
| @@ -81549,11 +81623,11 @@ | |
| 81549 | |
| 81550 | REGISTER_TRACE(pOp->p3, pMem); |
| 81551 | sqlite3VdbeMemIntegerify(pMem); |
| 81552 | assert( (pMem->flags & MEM_Int)!=0 ); /* mem(P3) holds an integer */ |
| 81553 | if( pMem->u.i==MAX_ROWID || pC->useRandomRowid ){ |
| 81554 | rc = SQLITE_FULL; /* IMP: R-12275-61338 */ |
| 81555 | goto abort_due_to_error; |
| 81556 | } |
| 81557 | if( v<pMem->u.i+1 ){ |
| 81558 | v = pMem->u.i + 1; |
| 81559 | } |
| @@ -81746,11 +81820,11 @@ | |
| 81746 | ** change count is incremented (otherwise not). |
| 81747 | ** |
| 81748 | ** P1 must not be pseudo-table. It has to be a real table with |
| 81749 | ** multiple rows. |
| 81750 | ** |
| 81751 | ** If P4 is not NULL then it points to a Table struture. In this case either |
| 81752 | ** the update or pre-update hook, or both, may be invoked. The P1 cursor must |
| 81753 | ** have been positioned using OP_NotFound prior to invoking this opcode in |
| 81754 | ** this case. Specifically, if one is configured, the pre-update hook is |
| 81755 | ** invoked if P4 is not NULL. The update-hook is invoked if one is configured, |
| 81756 | ** P4 is not NULL, and the OPFLAG_NCHANGE flag is set in P2. |
| @@ -82316,10 +82390,17 @@ | |
| 82316 | ** This flag avoids doing an extra seek. |
| 82317 | ** |
| 82318 | ** This instruction only works for indices. The equivalent instruction |
| 82319 | ** for tables is OP_Insert. |
| 82320 | */ |
| 82321 | case OP_SorterInsert: /* in2 */ |
| 82322 | case OP_IdxInsert: { /* in2 */ |
| 82323 | VdbeCursor *pC; |
| 82324 | BtreePayload x; |
| 82325 | |
| @@ -82337,13 +82418,10 @@ | |
| 82337 | if( pOp->opcode==OP_SorterInsert ){ |
| 82338 | rc = sqlite3VdbeSorterWrite(pC, pIn2); |
| 82339 | }else{ |
| 82340 | x.nKey = pIn2->n; |
| 82341 | x.pKey = pIn2->z; |
| 82342 | x.nData = 0; |
| 82343 | x.nZero = 0; |
| 82344 | x.pData = 0; |
| 82345 | rc = sqlite3BtreeInsert(pC->uc.pCursor, &x, pOp->p3, |
| 82346 | ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0) |
| 82347 | ); |
| 82348 | assert( pC->deferredMoveto==0 ); |
| 82349 | pC->cacheStatus = CACHE_STALE; |
| @@ -83547,11 +83625,11 @@ | |
| 83547 | /* If leaving WAL mode, close the log file. If successful, the call |
| 83548 | ** to PagerCloseWal() checkpoints and deletes the write-ahead-log |
| 83549 | ** file. An EXCLUSIVE lock may still be held on the database file |
| 83550 | ** after a successful return. |
| 83551 | */ |
| 83552 | rc = sqlite3PagerCloseWal(pPager); |
| 83553 | if( rc==SQLITE_OK ){ |
| 83554 | sqlite3PagerSetJournalMode(pPager, eNew); |
| 83555 | } |
| 83556 | }else if( eOld==PAGER_JOURNALMODE_MEMORY ){ |
| 83557 | /* Cannot transition directly from MEMORY to WAL. Use mode OFF |
| @@ -88036,11 +88114,13 @@ | |
| 88036 | static SQLITE_NOINLINE int walkExpr(Walker *pWalker, Expr *pExpr){ |
| 88037 | int rc; |
| 88038 | testcase( ExprHasProperty(pExpr, EP_TokenOnly) ); |
| 88039 | testcase( ExprHasProperty(pExpr, EP_Reduced) ); |
| 88040 | rc = pWalker->xExprCallback(pWalker, pExpr); |
| 88041 | if( rc || ExprHasProperty(pExpr,EP_TokenOnly) ) return rc & WRC_Abort; |
| 88042 | if( pExpr->pLeft && walkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort; |
| 88043 | if( pExpr->pRight && walkExpr(pWalker, pExpr->pRight) ) return WRC_Abort; |
| 88044 | if( ExprHasProperty(pExpr, EP_xIsSelect) ){ |
| 88045 | if( sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort; |
| 88046 | }else if( pExpr->x.pList ){ |
| @@ -88780,11 +88860,10 @@ | |
| 88780 | const char *zDb; |
| 88781 | Expr *pRight; |
| 88782 | |
| 88783 | /* if( pSrcList==0 ) break; */ |
| 88784 | notValid(pParse, pNC, "the \".\" operator", NC_IdxExpr); |
| 88785 | /*notValid(pParse, pNC, "the \".\" operator", NC_PartIdx|NC_IsCheck, 1);*/ |
| 88786 | pRight = pExpr->pRight; |
| 88787 | if( pRight->op==TK_ID ){ |
| 88788 | zDb = 0; |
| 88789 | zTable = pExpr->pLeft->u.zToken; |
| 88790 | zColumn = pRight->u.zToken; |
| @@ -88809,11 +88888,10 @@ | |
| 88809 | const char *zId; /* The function name. */ |
| 88810 | FuncDef *pDef; /* Information about the function */ |
| 88811 | u8 enc = ENC(pParse->db); /* The database encoding */ |
| 88812 | |
| 88813 | assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); |
| 88814 | notValid(pParse, pNC, "functions", NC_PartIdx); |
| 88815 | zId = pExpr->u.zToken; |
| 88816 | nId = sqlite3Strlen30(zId); |
| 88817 | pDef = sqlite3FindFunction(pParse->db, zId, n, enc, 0); |
| 88818 | if( pDef==0 ){ |
| 88819 | pDef = sqlite3FindFunction(pParse->db, zId, -2, enc, 0); |
| @@ -88869,11 +88947,12 @@ | |
| 88869 | } |
| 88870 | if( (pDef->funcFlags & SQLITE_FUNC_CONSTANT)==0 ){ |
| 88871 | /* Date/time functions that use 'now', and other functions like |
| 88872 | ** sqlite_version() that might change over time cannot be used |
| 88873 | ** in an index. */ |
| 88874 | notValid(pParse, pNC, "non-deterministic functions", NC_IdxExpr); |
| 88875 | } |
| 88876 | } |
| 88877 | if( is_agg && (pNC->ncFlags & NC_AllowAgg)==0 ){ |
| 88878 | sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId); |
| 88879 | pNC->nErr++; |
| @@ -90409,11 +90488,11 @@ | |
| 90409 | ** stored in u.zToken. Instead, the integer values is written |
| 90410 | ** into u.iValue and the EP_IntValue flag is set. No extra storage |
| 90411 | ** is allocated to hold the integer text and the dequote flag is ignored. |
| 90412 | */ |
| 90413 | SQLITE_PRIVATE Expr *sqlite3ExprAlloc( |
| 90414 | sqlite3 *db, /* Handle for sqlite3DbMallocZero() (may be null) */ |
| 90415 | int op, /* Expression opcode */ |
| 90416 | const Token *pToken, /* Token argument. Might be NULL */ |
| 90417 | int dequote /* True to dequote */ |
| 90418 | ){ |
| 90419 | Expr *pNew; |
| @@ -90627,40 +90706,40 @@ | |
| 90627 | ** Wildcards of the form ":aaa", "@aaa", or "$aaa" are assigned the same number |
| 90628 | ** as the previous instance of the same wildcard. Or if this is the first |
| 90629 | ** instance of the wildcard, the next sequential variable number is |
| 90630 | ** assigned. |
| 90631 | */ |
| 90632 | SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){ |
| 90633 | sqlite3 *db = pParse->db; |
| 90634 | const char *z; |
| 90635 | |
| 90636 | if( pExpr==0 ) return; |
| 90637 | assert( !ExprHasProperty(pExpr, EP_IntValue|EP_Reduced|EP_TokenOnly) ); |
| 90638 | z = pExpr->u.zToken; |
| 90639 | assert( z!=0 ); |
| 90640 | assert( z[0]!=0 ); |
| 90641 | if( z[1]==0 ){ |
| 90642 | /* Wildcard of the form "?". Assign the next variable number */ |
| 90643 | assert( z[0]=='?' ); |
| 90644 | pExpr->iColumn = (ynVar)(++pParse->nVar); |
| 90645 | }else{ |
| 90646 | ynVar x = 0; |
| 90647 | u32 n = sqlite3Strlen30(z); |
| 90648 | if( z[0]=='?' ){ |
| 90649 | /* Wildcard of the form "?nnn". Convert "nnn" to an integer and |
| 90650 | ** use it as the variable number */ |
| 90651 | i64 i; |
| 90652 | int bOk = 0==sqlite3Atoi64(&z[1], &i, n-1, SQLITE_UTF8); |
| 90653 | pExpr->iColumn = x = (ynVar)i; |
| 90654 | testcase( i==0 ); |
| 90655 | testcase( i==1 ); |
| 90656 | testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]-1 ); |
| 90657 | testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ); |
| 90658 | if( bOk==0 || i<1 || i>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){ |
| 90659 | sqlite3ErrorMsg(pParse, "variable number must be between ?1 and ?%d", |
| 90660 | db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]); |
| 90661 | x = 0; |
| 90662 | } |
| 90663 | if( i>pParse->nVar ){ |
| 90664 | pParse->nVar = (int)i; |
| 90665 | } |
| 90666 | }else{ |
| @@ -90667,37 +90746,35 @@ | |
| 90667 | /* Wildcards like ":aaa", "$aaa" or "@aaa". Reuse the same variable |
| 90668 | ** number as the prior appearance of the same name, or if the name |
| 90669 | ** has never appeared before, reuse the same variable number |
| 90670 | */ |
| 90671 | ynVar i; |
| 90672 | for(i=0; i<pParse->nzVar; i++){ |
| 90673 | if( pParse->azVar[i] && strcmp(pParse->azVar[i],z)==0 ){ |
| 90674 | pExpr->iColumn = x = (ynVar)i+1; |
| 90675 | break; |
| 90676 | } |
| 90677 | } |
| 90678 | if( x==0 ) x = pExpr->iColumn = (ynVar)(++pParse->nVar); |
| 90679 | } |
| 90680 | if( x>0 ){ |
| 90681 | if( x>pParse->nzVar ){ |
| 90682 | char **a; |
| 90683 | a = sqlite3DbRealloc(db, pParse->azVar, x*sizeof(a[0])); |
| 90684 | if( a==0 ){ |
| 90685 | assert( db->mallocFailed ); /* Error reported through mallocFailed */ |
| 90686 | return; |
| 90687 | } |
| 90688 | pParse->azVar = a; |
| 90689 | memset(&a[pParse->nzVar], 0, (x-pParse->nzVar)*sizeof(a[0])); |
| 90690 | pParse->nzVar = x; |
| 90691 | } |
| 90692 | if( z[0]!='?' || pParse->azVar[x-1]==0 ){ |
| 90693 | sqlite3DbFree(db, pParse->azVar[x-1]); |
| 90694 | pParse->azVar[x-1] = sqlite3DbStrNDup(db, z, n); |
| 90695 | } |
| 90696 | } |
| 90697 | } |
| 90698 | if( !pParse->nErr && pParse->nVar>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){ |
| 90699 | sqlite3ErrorMsg(pParse, "too many SQL variables"); |
| 90700 | } |
| 90701 | } |
| 90702 | |
| 90703 | /* |
| @@ -90705,22 +90782,29 @@ | |
| 90705 | */ |
| 90706 | static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){ |
| 90707 | assert( p!=0 ); |
| 90708 | /* Sanity check: Assert that the IntValue is non-negative if it exists */ |
| 90709 | assert( !ExprHasProperty(p, EP_IntValue) || p->u.iValue>=0 ); |
| 90710 | if( !ExprHasProperty(p, EP_TokenOnly) ){ |
| 90711 | /* The Expr.x union is never used at the same time as Expr.pRight */ |
| 90712 | assert( p->x.pList==0 || p->pRight==0 ); |
| 90713 | if( p->pLeft && p->op!=TK_SELECT_COLUMN ) sqlite3ExprDeleteNN(db, p->pLeft); |
| 90714 | sqlite3ExprDelete(db, p->pRight); |
| 90715 | if( ExprHasProperty(p, EP_MemToken) ) sqlite3DbFree(db, p->u.zToken); |
| 90716 | if( ExprHasProperty(p, EP_xIsSelect) ){ |
| 90717 | sqlite3SelectDelete(db, p->x.pSelect); |
| 90718 | }else{ |
| 90719 | sqlite3ExprListDelete(db, p->x.pList); |
| 90720 | } |
| 90721 | } |
| 90722 | if( !ExprHasProperty(p, EP_Static) ){ |
| 90723 | sqlite3DbFree(db, p); |
| 90724 | } |
| 90725 | } |
| 90726 | SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3 *db, Expr *p){ |
| @@ -90893,11 +90977,11 @@ | |
| 90893 | if( nToken ){ |
| 90894 | char *zToken = pNew->u.zToken = (char*)&zAlloc[nNewSize]; |
| 90895 | memcpy(zToken, p->u.zToken, nToken); |
| 90896 | } |
| 90897 | |
| 90898 | if( 0==((p->flags|pNew->flags) & EP_TokenOnly) ){ |
| 90899 | /* Fill in the pNew->x.pSelect or pNew->x.pList member. */ |
| 90900 | if( ExprHasProperty(p, EP_xIsSelect) ){ |
| 90901 | pNew->x.pSelect = sqlite3SelectDup(db, p->x.pSelect, dupFlags); |
| 90902 | }else{ |
| 90903 | pNew->x.pList = sqlite3ExprListDup(db, p->x.pList, dupFlags); |
| @@ -90905,21 +90989,21 @@ | |
| 90905 | } |
| 90906 | |
| 90907 | /* Fill in pNew->pLeft and pNew->pRight. */ |
| 90908 | if( ExprHasProperty(pNew, EP_Reduced|EP_TokenOnly) ){ |
| 90909 | zAlloc += dupedExprNodeSize(p, dupFlags); |
| 90910 | if( ExprHasProperty(pNew, EP_Reduced) ){ |
| 90911 | pNew->pLeft = p->pLeft ? |
| 90912 | exprDup(db, p->pLeft, EXPRDUP_REDUCE, &zAlloc) : 0; |
| 90913 | pNew->pRight = p->pRight ? |
| 90914 | exprDup(db, p->pRight, EXPRDUP_REDUCE, &zAlloc) : 0; |
| 90915 | } |
| 90916 | if( pzBuffer ){ |
| 90917 | *pzBuffer = zAlloc; |
| 90918 | } |
| 90919 | }else{ |
| 90920 | if( !ExprHasProperty(p, EP_TokenOnly) ){ |
| 90921 | if( pNew->op==TK_SELECT_COLUMN ){ |
| 90922 | pNew->pLeft = p->pLeft; |
| 90923 | }else{ |
| 90924 | pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0); |
| 90925 | } |
| @@ -92276,12 +92360,12 @@ | |
| 92276 | dest.eDest = SRT_Exists; |
| 92277 | sqlite3VdbeAddOp2(v, OP_Integer, 0, dest.iSDParm); |
| 92278 | VdbeComment((v, "Init EXISTS result")); |
| 92279 | } |
| 92280 | sqlite3ExprDelete(pParse->db, pSel->pLimit); |
| 92281 | pSel->pLimit = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, |
| 92282 | &sqlite3IntTokens[1]); |
| 92283 | pSel->iLimit = 0; |
| 92284 | pSel->selFlags &= ~SF_MultiValue; |
| 92285 | if( sqlite3Select(pParse, pSel, &dest) ){ |
| 92286 | return 0; |
| 92287 | } |
| @@ -92646,36 +92730,23 @@ | |
| 92646 | #endif |
| 92647 | } |
| 92648 | } |
| 92649 | } |
| 92650 | |
| 92651 | #if defined(SQLITE_DEBUG) |
| 92652 | /* |
| 92653 | ** Verify the consistency of the column cache |
| 92654 | */ |
| 92655 | static int cacheIsValid(Parse *pParse){ |
| 92656 | int i, n; |
| 92657 | for(i=n=0; i<SQLITE_N_COLCACHE; i++){ |
| 92658 | if( pParse->aColCache[i].iReg>0 ) n++; |
| 92659 | } |
| 92660 | return n==pParse->nColCache; |
| 92661 | } |
| 92662 | #endif |
| 92663 | |
| 92664 | /* |
| 92665 | ** Clear a cache entry. |
| 92666 | */ |
| 92667 | static void cacheEntryClear(Parse *pParse, struct yColCache *p){ |
| 92668 | if( p->tempReg ){ |
| 92669 | if( pParse->nTempReg<ArraySize(pParse->aTempReg) ){ |
| 92670 | pParse->aTempReg[pParse->nTempReg++] = p->iReg; |
| 92671 | } |
| 92672 | p->tempReg = 0; |
| 92673 | } |
| 92674 | p->iReg = 0; |
| 92675 | pParse->nColCache--; |
| 92676 | assert( pParse->db->mallocFailed || cacheIsValid(pParse) ); |
| 92677 | } |
| 92678 | |
| 92679 | |
| 92680 | /* |
| 92681 | ** Record in the column cache that a particular column from a |
| @@ -92701,64 +92772,52 @@ | |
| 92701 | ** |
| 92702 | ** Actually, the way the column cache is currently used, we are guaranteed |
| 92703 | ** that the object will never already be in cache. Verify this guarantee. |
| 92704 | */ |
| 92705 | #ifndef NDEBUG |
| 92706 | for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){ |
| 92707 | assert( p->iReg==0 || p->iTable!=iTab || p->iColumn!=iCol ); |
| 92708 | } |
| 92709 | #endif |
| 92710 | |
| 92711 | /* Find an empty slot and replace it */ |
| 92712 | for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){ |
| 92713 | if( p->iReg==0 ){ |
| 92714 | p->iLevel = pParse->iCacheLevel; |
| 92715 | p->iTable = iTab; |
| 92716 | p->iColumn = iCol; |
| 92717 | p->iReg = iReg; |
| 92718 | p->tempReg = 0; |
| 92719 | p->lru = pParse->iCacheCnt++; |
| 92720 | pParse->nColCache++; |
| 92721 | assert( pParse->db->mallocFailed || cacheIsValid(pParse) ); |
| 92722 | return; |
| 92723 | } |
| 92724 | } |
| 92725 | |
| 92726 | /* Replace the last recently used */ |
| 92727 | minLru = 0x7fffffff; |
| 92728 | idxLru = -1; |
| 92729 | for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){ |
| 92730 | if( p->lru<minLru ){ |
| 92731 | idxLru = i; |
| 92732 | minLru = p->lru; |
| 92733 | } |
| 92734 | } |
| 92735 | if( ALWAYS(idxLru>=0) ){ |
| 92736 | p = &pParse->aColCache[idxLru]; |
| 92737 | p->iLevel = pParse->iCacheLevel; |
| 92738 | p->iTable = iTab; |
| 92739 | p->iColumn = iCol; |
| 92740 | p->iReg = iReg; |
| 92741 | p->tempReg = 0; |
| 92742 | p->lru = pParse->iCacheCnt++; |
| 92743 | assert( cacheIsValid(pParse) ); |
| 92744 | return; |
| 92745 | } |
| 92746 | } |
| 92747 | |
| 92748 | /* |
| 92749 | ** Indicate that registers between iReg..iReg+nReg-1 are being overwritten. |
| 92750 | ** Purge the range of registers from the column cache. |
| 92751 | */ |
| 92752 | SQLITE_PRIVATE void sqlite3ExprCacheRemove(Parse *pParse, int iReg, int nReg){ |
| 92753 | struct yColCache *p; |
| 92754 | if( iReg<=0 || pParse->nColCache==0 ) return; |
| 92755 | p = &pParse->aColCache[SQLITE_N_COLCACHE-1]; |
| 92756 | while(1){ |
| 92757 | if( p->iReg >= iReg && p->iReg < iReg+nReg ) cacheEntryClear(pParse, p); |
| 92758 | if( p==pParse->aColCache ) break; |
| 92759 | p--; |
| 92760 | } |
| 92761 | } |
| 92762 | |
| 92763 | /* |
| 92764 | ** Remember the current column cache context. Any new entries added |
| @@ -92778,22 +92837,23 @@ | |
| 92778 | ** Remove from the column cache any entries that were added since the |
| 92779 | ** the previous sqlite3ExprCachePush operation. In other words, restore |
| 92780 | ** the cache to the state it was in prior the most recent Push. |
| 92781 | */ |
| 92782 | SQLITE_PRIVATE void sqlite3ExprCachePop(Parse *pParse){ |
| 92783 | int i; |
| 92784 | struct yColCache *p; |
| 92785 | assert( pParse->iCacheLevel>=1 ); |
| 92786 | pParse->iCacheLevel--; |
| 92787 | #ifdef SQLITE_DEBUG |
| 92788 | if( pParse->db->flags & SQLITE_VdbeAddopTrace ){ |
| 92789 | printf("POP to %d\n", pParse->iCacheLevel); |
| 92790 | } |
| 92791 | #endif |
| 92792 | for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){ |
| 92793 | if( p->iReg && p->iLevel>pParse->iCacheLevel ){ |
| 92794 | cacheEntryClear(pParse, p); |
| 92795 | } |
| 92796 | } |
| 92797 | } |
| 92798 | |
| 92799 | /* |
| @@ -92803,11 +92863,11 @@ | |
| 92803 | ** get them all. |
| 92804 | */ |
| 92805 | static void sqlite3ExprCachePinRegister(Parse *pParse, int iReg){ |
| 92806 | int i; |
| 92807 | struct yColCache *p; |
| 92808 | for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){ |
| 92809 | if( p->iReg==iReg ){ |
| 92810 | p->tempReg = 0; |
| 92811 | } |
| 92812 | } |
| 92813 | } |
| @@ -92881,12 +92941,12 @@ | |
| 92881 | ){ |
| 92882 | Vdbe *v = pParse->pVdbe; |
| 92883 | int i; |
| 92884 | struct yColCache *p; |
| 92885 | |
| 92886 | for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){ |
| 92887 | if( p->iReg>0 && p->iTable==iTable && p->iColumn==iColumn ){ |
| 92888 | p->lru = pParse->iCacheCnt++; |
| 92889 | sqlite3ExprCachePinRegister(pParse, p->iReg); |
| 92890 | return p->iReg; |
| 92891 | } |
| 92892 | } |
| @@ -92914,22 +92974,24 @@ | |
| 92914 | /* |
| 92915 | ** Clear all column cache entries. |
| 92916 | */ |
| 92917 | SQLITE_PRIVATE void sqlite3ExprCacheClear(Parse *pParse){ |
| 92918 | int i; |
| 92919 | struct yColCache *p; |
| 92920 | |
| 92921 | #if SQLITE_DEBUG |
| 92922 | if( pParse->db->flags & SQLITE_VdbeAddopTrace ){ |
| 92923 | printf("CLEAR\n"); |
| 92924 | } |
| 92925 | #endif |
| 92926 | for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){ |
| 92927 | if( p->iReg ){ |
| 92928 | cacheEntryClear(pParse, p); |
| 92929 | } |
| 92930 | } |
| 92931 | } |
| 92932 | |
| 92933 | /* |
| 92934 | ** Record the fact that an affinity change has occurred on iCount |
| 92935 | ** registers starting with iStart. |
| @@ -92957,11 +93019,11 @@ | |
| 92957 | ** and does not appear in a normal build. |
| 92958 | */ |
| 92959 | static int usedAsColumnCache(Parse *pParse, int iFrom, int iTo){ |
| 92960 | int i; |
| 92961 | struct yColCache *p; |
| 92962 | for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){ |
| 92963 | int r = p->iReg; |
| 92964 | if( r>=iFrom && r<=iTo ) return 1; /*NO_TEST*/ |
| 92965 | } |
| 92966 | return 0; |
| 92967 | } |
| @@ -94306,15 +94368,14 @@ | |
| 94306 | && (sqlite3ExprImpliesExpr(pE1, pE2->pLeft, iTab) |
| 94307 | || sqlite3ExprImpliesExpr(pE1, pE2->pRight, iTab) ) |
| 94308 | ){ |
| 94309 | return 1; |
| 94310 | } |
| 94311 | if( pE2->op==TK_NOTNULL |
| 94312 | && sqlite3ExprCompare(pE1->pLeft, pE2->pLeft, iTab)==0 |
| 94313 | && (pE1->op!=TK_ISNULL && pE1->op!=TK_IS) |
| 94314 | ){ |
| 94315 | return 1; |
| 94316 | } |
| 94317 | return 0; |
| 94318 | } |
| 94319 | |
| 94320 | /* |
| @@ -94653,11 +94714,11 @@ | |
| 94653 | */ |
| 94654 | SQLITE_PRIVATE void sqlite3ReleaseTempReg(Parse *pParse, int iReg){ |
| 94655 | if( iReg && pParse->nTempReg<ArraySize(pParse->aTempReg) ){ |
| 94656 | int i; |
| 94657 | struct yColCache *p; |
| 94658 | for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){ |
| 94659 | if( p->iReg==iReg ){ |
| 94660 | p->tempReg = 1; |
| 94661 | return; |
| 94662 | } |
| 94663 | } |
| @@ -97959,11 +98020,11 @@ | |
| 97959 | }else{ |
| 97960 | sqlite3ErrorMsg(pFix->pParse, "%s cannot use variables", pFix->zType); |
| 97961 | return 1; |
| 97962 | } |
| 97963 | } |
| 97964 | if( ExprHasProperty(pExpr, EP_TokenOnly) ) break; |
| 97965 | if( ExprHasProperty(pExpr, EP_xIsSelect) ){ |
| 97966 | if( sqlite3FixSelect(pFix, pExpr->x.pSelect) ) return 1; |
| 97967 | }else{ |
| 97968 | if( sqlite3FixExprList(pFix, pExpr->x.pList) ) return 1; |
| 97969 | } |
| @@ -98423,11 +98484,10 @@ | |
| 98423 | */ |
| 98424 | v = sqlite3GetVdbe(pParse); |
| 98425 | assert( !pParse->isMultiWrite |
| 98426 | || sqlite3VdbeAssertMayAbort(v, pParse->mayAbort)); |
| 98427 | if( v ){ |
| 98428 | while( sqlite3VdbeDeletePriorOpcode(v, OP_Close) ){} |
| 98429 | sqlite3VdbeAddOp0(v, OP_Halt); |
| 98430 | |
| 98431 | #if SQLITE_USER_AUTHENTICATION |
| 98432 | if( pParse->nTableLock>0 && db->init.busy==0 ){ |
| 98433 | sqlite3UserAuthInit(db); |
| @@ -98450,18 +98510,20 @@ | |
| 98450 | ){ |
| 98451 | int iDb, i; |
| 98452 | assert( sqlite3VdbeGetOp(v, 0)->opcode==OP_Init ); |
| 98453 | sqlite3VdbeJumpHere(v, 0); |
| 98454 | for(iDb=0; iDb<db->nDb; iDb++){ |
| 98455 | if( DbMaskTest(pParse->cookieMask, iDb)==0 ) continue; |
| 98456 | sqlite3VdbeUsesBtree(v, iDb); |
| 98457 | sqlite3VdbeAddOp4Int(v, |
| 98458 | OP_Transaction, /* Opcode */ |
| 98459 | iDb, /* P1 */ |
| 98460 | DbMaskTest(pParse->writeMask,iDb), /* P2 */ |
| 98461 | pParse->cookieValue[iDb], /* P3 */ |
| 98462 | db->aDb[iDb].pSchema->iGeneration /* P4 */ |
| 98463 | ); |
| 98464 | if( db->init.busy==0 ) sqlite3VdbeChangeP5(v, 1); |
| 98465 | VdbeComment((v, |
| 98466 | "usesStmtJournal=%d", pParse->mayAbort && pParse->isMultiWrite)); |
| 98467 | } |
| @@ -98508,20 +98570,10 @@ | |
| 98508 | sqlite3VdbeMakeReady(v, pParse); |
| 98509 | pParse->rc = SQLITE_DONE; |
| 98510 | }else{ |
| 98511 | pParse->rc = SQLITE_ERROR; |
| 98512 | } |
| 98513 | |
| 98514 | /* We are done with this Parse object. There is no need to de-initialize it */ |
| 98515 | #if 0 |
| 98516 | pParse->colNamesSet = 0; |
| 98517 | pParse->nTab = 0; |
| 98518 | pParse->nMem = 0; |
| 98519 | pParse->nSet = 0; |
| 98520 | pParse->nVar = 0; |
| 98521 | DbMaskZero(pParse->cookieMask); |
| 98522 | #endif |
| 98523 | } |
| 98524 | |
| 98525 | /* |
| 98526 | ** Run the parser and code generator recursively in order to generate |
| 98527 | ** code for the SQL statement given onto the end of the pParse context |
| @@ -98537,12 +98589,11 @@ | |
| 98537 | SQLITE_PRIVATE void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){ |
| 98538 | va_list ap; |
| 98539 | char *zSql; |
| 98540 | char *zErrMsg = 0; |
| 98541 | sqlite3 *db = pParse->db; |
| 98542 | # define SAVE_SZ (sizeof(Parse) - offsetof(Parse,nVar)) |
| 98543 | char saveBuf[SAVE_SZ]; |
| 98544 | |
| 98545 | if( pParse->nErr ) return; |
| 98546 | assert( pParse->nested<10 ); /* Nesting should only be of limited depth */ |
| 98547 | va_start(ap, zFormat); |
| 98548 | zSql = sqlite3VMPrintf(db, zFormat, ap); |
| @@ -98549,16 +98600,16 @@ | |
| 98549 | va_end(ap); |
| 98550 | if( zSql==0 ){ |
| 98551 | return; /* A malloc must have failed */ |
| 98552 | } |
| 98553 | pParse->nested++; |
| 98554 | memcpy(saveBuf, &pParse->nVar, SAVE_SZ); |
| 98555 | memset(&pParse->nVar, 0, SAVE_SZ); |
| 98556 | sqlite3RunParser(pParse, zSql, &zErrMsg); |
| 98557 | sqlite3DbFree(db, zErrMsg); |
| 98558 | sqlite3DbFree(db, zSql); |
| 98559 | memcpy(&pParse->nVar, saveBuf, SAVE_SZ); |
| 98560 | pParse->nested--; |
| 98561 | } |
| 98562 | |
| 98563 | #if SQLITE_USER_AUTHENTICATION |
| 98564 | /* |
| @@ -99735,10 +99786,13 @@ | |
| 99735 | ** This plan is not completely bullet-proof. It is possible for |
| 99736 | ** the schema to change multiple times and for the cookie to be |
| 99737 | ** set back to prior value. But schema changes are infrequent |
| 99738 | ** and the probability of hitting the same cookie value is only |
| 99739 | ** 1 chance in 2^32. So we're safe enough. |
| 99740 | */ |
| 99741 | SQLITE_PRIVATE void sqlite3ChangeCookie(Parse *pParse, int iDb){ |
| 99742 | sqlite3 *db = pParse->db; |
| 99743 | Vdbe *v = pParse->pVdbe; |
| 99744 | assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); |
| @@ -102318,19 +102372,17 @@ | |
| 102318 | ** will occur at the end of the top-level VDBE and will be generated |
| 102319 | ** later, by sqlite3FinishCoding(). |
| 102320 | */ |
| 102321 | SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse *pParse, int iDb){ |
| 102322 | Parse *pToplevel = sqlite3ParseToplevel(pParse); |
| 102323 | sqlite3 *db = pToplevel->db; |
| 102324 | |
| 102325 | assert( iDb>=0 && iDb<db->nDb ); |
| 102326 | assert( db->aDb[iDb].pBt!=0 || iDb==1 ); |
| 102327 | assert( iDb<SQLITE_MAX_ATTACHED+2 ); |
| 102328 | assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); |
| 102329 | if( DbMaskTest(pToplevel->cookieMask, iDb)==0 ){ |
| 102330 | DbMaskSet(pToplevel->cookieMask, iDb); |
| 102331 | pToplevel->cookieValue[iDb] = db->aDb[iDb].pSchema->schema_cookie; |
| 102332 | if( !OMIT_TEMPDB && iDb==1 ){ |
| 102333 | sqlite3OpenTempDatabase(pToplevel); |
| 102334 | } |
| 102335 | } |
| 102336 | } |
| @@ -107192,14 +107244,14 @@ | |
| 107192 | }else if( action==OE_SetDflt ){ |
| 107193 | Expr *pDflt = pFKey->pFrom->aCol[iFromCol].pDflt; |
| 107194 | if( pDflt ){ |
| 107195 | pNew = sqlite3ExprDup(db, pDflt, 0); |
| 107196 | }else{ |
| 107197 | pNew = sqlite3PExpr(pParse, TK_NULL, 0, 0, 0); |
| 107198 | } |
| 107199 | }else{ |
| 107200 | pNew = sqlite3PExpr(pParse, TK_NULL, 0, 0, 0); |
| 107201 | } |
| 107202 | pList = sqlite3ExprListAppend(pParse, pList, pNew); |
| 107203 | sqlite3ExprListSetName(pParse, pList, &tFromCol, 0); |
| 107204 | } |
| 107205 | } |
| @@ -109538,10 +109590,11 @@ | |
| 109538 | } |
| 109539 | if( emptySrcTest ) sqlite3VdbeJumpHere(v, emptySrcTest); |
| 109540 | sqlite3ReleaseTempReg(pParse, regRowid); |
| 109541 | sqlite3ReleaseTempReg(pParse, regData); |
| 109542 | if( emptyDestTest ){ |
| 109543 | sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_OK, 0); |
| 109544 | sqlite3VdbeJumpHere(v, emptyDestTest); |
| 109545 | sqlite3VdbeAddOp2(v, OP_Close, iDest, 0); |
| 109546 | return 0; |
| 109547 | }else{ |
| @@ -114034,22 +114087,18 @@ | |
| 114034 | int saveSqlFlag, /* True to copy SQL text into the sqlite3_stmt */ |
| 114035 | Vdbe *pReprepare, /* VM being reprepared */ |
| 114036 | sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ |
| 114037 | const char **pzTail /* OUT: End of parsed string */ |
| 114038 | ){ |
| 114039 | Parse *pParse; /* Parsing context */ |
| 114040 | char *zErrMsg = 0; /* Error message */ |
| 114041 | int rc = SQLITE_OK; /* Result code */ |
| 114042 | int i; /* Loop counter */ |
| 114043 | |
| 114044 | /* Allocate the parsing context */ |
| 114045 | pParse = sqlite3StackAllocZero(db, sizeof(*pParse)); |
| 114046 | if( pParse==0 ){ |
| 114047 | rc = SQLITE_NOMEM_BKPT; |
| 114048 | goto end_prepare; |
| 114049 | } |
| 114050 | pParse->pReprepare = pReprepare; |
| 114051 | assert( ppStmt && *ppStmt==0 ); |
| 114052 | /* assert( !db->mallocFailed ); // not true with SQLITE_USE_ALLOCA */ |
| 114053 | assert( sqlite3_mutex_held(db->mutex) ); |
| 114054 | |
| 114055 | /* Check to verify that it is possible to get a read lock on all |
| @@ -114089,12 +114138,11 @@ | |
| 114089 | } |
| 114090 | } |
| 114091 | |
| 114092 | sqlite3VtabUnlockList(db); |
| 114093 | |
| 114094 | pParse->db = db; |
| 114095 | pParse->nQueryLoop = 0; /* Logarithmic, so 0 really means 1 */ |
| 114096 | if( nBytes>=0 && (nBytes==0 || zSql[nBytes-1]!=0) ){ |
| 114097 | char *zSqlCopy; |
| 114098 | int mxLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH]; |
| 114099 | testcase( nBytes==mxLen ); |
| 114100 | testcase( nBytes==mxLen+1 ); |
| @@ -114103,65 +114151,65 @@ | |
| 114103 | rc = sqlite3ApiExit(db, SQLITE_TOOBIG); |
| 114104 | goto end_prepare; |
| 114105 | } |
| 114106 | zSqlCopy = sqlite3DbStrNDup(db, zSql, nBytes); |
| 114107 | if( zSqlCopy ){ |
| 114108 | sqlite3RunParser(pParse, zSqlCopy, &zErrMsg); |
| 114109 | pParse->zTail = &zSql[pParse->zTail-zSqlCopy]; |
| 114110 | sqlite3DbFree(db, zSqlCopy); |
| 114111 | }else{ |
| 114112 | pParse->zTail = &zSql[nBytes]; |
| 114113 | } |
| 114114 | }else{ |
| 114115 | sqlite3RunParser(pParse, zSql, &zErrMsg); |
| 114116 | } |
| 114117 | assert( 0==pParse->nQueryLoop ); |
| 114118 | |
| 114119 | if( pParse->rc==SQLITE_DONE ) pParse->rc = SQLITE_OK; |
| 114120 | if( pParse->checkSchema ){ |
| 114121 | schemaIsValid(pParse); |
| 114122 | } |
| 114123 | if( db->mallocFailed ){ |
| 114124 | pParse->rc = SQLITE_NOMEM_BKPT; |
| 114125 | } |
| 114126 | if( pzTail ){ |
| 114127 | *pzTail = pParse->zTail; |
| 114128 | } |
| 114129 | rc = pParse->rc; |
| 114130 | |
| 114131 | #ifndef SQLITE_OMIT_EXPLAIN |
| 114132 | if( rc==SQLITE_OK && pParse->pVdbe && pParse->explain ){ |
| 114133 | static const char * const azColName[] = { |
| 114134 | "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment", |
| 114135 | "selectid", "order", "from", "detail" |
| 114136 | }; |
| 114137 | int iFirst, mx; |
| 114138 | if( pParse->explain==2 ){ |
| 114139 | sqlite3VdbeSetNumCols(pParse->pVdbe, 4); |
| 114140 | iFirst = 8; |
| 114141 | mx = 12; |
| 114142 | }else{ |
| 114143 | sqlite3VdbeSetNumCols(pParse->pVdbe, 8); |
| 114144 | iFirst = 0; |
| 114145 | mx = 8; |
| 114146 | } |
| 114147 | for(i=iFirst; i<mx; i++){ |
| 114148 | sqlite3VdbeSetColName(pParse->pVdbe, i-iFirst, COLNAME_NAME, |
| 114149 | azColName[i], SQLITE_STATIC); |
| 114150 | } |
| 114151 | } |
| 114152 | #endif |
| 114153 | |
| 114154 | if( db->init.busy==0 ){ |
| 114155 | Vdbe *pVdbe = pParse->pVdbe; |
| 114156 | sqlite3VdbeSetSql(pVdbe, zSql, (int)(pParse->zTail-zSql), saveSqlFlag); |
| 114157 | } |
| 114158 | if( pParse->pVdbe && (rc!=SQLITE_OK || db->mallocFailed) ){ |
| 114159 | sqlite3VdbeFinalize(pParse->pVdbe); |
| 114160 | assert(!(*ppStmt)); |
| 114161 | }else{ |
| 114162 | *ppStmt = (sqlite3_stmt*)pParse->pVdbe; |
| 114163 | } |
| 114164 | |
| 114165 | if( zErrMsg ){ |
| 114166 | sqlite3ErrorWithMsg(db, rc, "%s", zErrMsg); |
| 114167 | sqlite3DbFree(db, zErrMsg); |
| @@ -114168,20 +114216,19 @@ | |
| 114168 | }else{ |
| 114169 | sqlite3Error(db, rc); |
| 114170 | } |
| 114171 | |
| 114172 | /* Delete any TriggerPrg structures allocated while parsing this statement. */ |
| 114173 | while( pParse->pTriggerPrg ){ |
| 114174 | TriggerPrg *pT = pParse->pTriggerPrg; |
| 114175 | pParse->pTriggerPrg = pT->pNext; |
| 114176 | sqlite3DbFree(db, pT); |
| 114177 | } |
| 114178 | |
| 114179 | end_prepare: |
| 114180 | |
| 114181 | sqlite3ParserReset(pParse); |
| 114182 | sqlite3StackFree(db, pParse); |
| 114183 | rc = sqlite3ApiExit(db, rc); |
| 114184 | assert( (rc&db->errMask)==rc ); |
| 114185 | return rc; |
| 114186 | } |
| 114187 | static int sqlite3LockAndPrepare( |
| @@ -115382,11 +115429,11 @@ | |
| 115382 | ** Allocate a KeyInfo object sufficient for an index of N key columns and |
| 115383 | ** X extra columns. |
| 115384 | */ |
| 115385 | SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N, int X){ |
| 115386 | int nExtra = (N+X)*(sizeof(CollSeq*)+1); |
| 115387 | KeyInfo *p = sqlite3DbMallocRaw(db, sizeof(KeyInfo) + nExtra); |
| 115388 | if( p ){ |
| 115389 | p->aSortOrder = (u8*)&p->aColl[N+X]; |
| 115390 | p->nField = (u16)N; |
| 115391 | p->nXField = (u16)X; |
| 115392 | p->enc = ENC(db); |
| @@ -118072,16 +118119,17 @@ | |
| 118072 | pWhere = sqlite3ExprDup(db, pSub->pWhere, 0); |
| 118073 | if( subqueryIsAgg ){ |
| 118074 | assert( pParent->pHaving==0 ); |
| 118075 | pParent->pHaving = pParent->pWhere; |
| 118076 | pParent->pWhere = pWhere; |
| 118077 | pParent->pHaving = sqlite3ExprAnd(db, pParent->pHaving, |
| 118078 | sqlite3ExprDup(db, pSub->pHaving, 0)); |
| 118079 | assert( pParent->pGroupBy==0 ); |
| 118080 | pParent->pGroupBy = sqlite3ExprListDup(db, pSub->pGroupBy, 0); |
| 118081 | }else{ |
| 118082 | pParent->pWhere = sqlite3ExprAnd(db, pParent->pWhere, pWhere); |
| 118083 | } |
| 118084 | substSelect(db, pParent, iParent, pSub->pEList, 0); |
| 118085 | |
| 118086 | /* The flattened query is distinct if either the inner or the |
| 118087 | ** outer query is distinct. |
| @@ -122381,11 +122429,11 @@ | |
| 122381 | } |
| 122382 | #endif |
| 122383 | |
| 122384 | sqlite3BtreeSetCacheSize(pTemp, db->aDb[iDb].pSchema->cache_size); |
| 122385 | sqlite3BtreeSetSpillSize(pTemp, sqlite3BtreeSetSpillSize(pMain,0)); |
| 122386 | sqlite3BtreeSetPagerFlags(pTemp, PAGER_SYNCHRONOUS_OFF); |
| 122387 | |
| 122388 | /* Begin a transaction and take an exclusive lock on the main database |
| 122389 | ** file. This is done before the sqlite3BtreeGetPageSize(pMain) call below, |
| 122390 | ** to ensure that we do not try to change the page-size on a WAL database. |
| 122391 | */ |
| @@ -124041,24 +124089,24 @@ | |
| 124041 | ** in prereqRight and prereqAll. The default is 64 bits, hence SQLite |
| 124042 | ** is only able to process joins with 64 or fewer tables. |
| 124043 | */ |
| 124044 | struct WhereTerm { |
| 124045 | Expr *pExpr; /* Pointer to the subexpression that is this term */ |
| 124046 | int iParent; /* Disable pWC->a[iParent] when this term disabled */ |
| 124047 | int leftCursor; /* Cursor number of X in "X <op> <expr>" */ |
| 124048 | int iField; /* Field in (?,?,?) IN (SELECT...) vector */ |
| 124049 | union { |
| 124050 | int leftColumn; /* Column number of X in "X <op> <expr>" */ |
| 124051 | WhereOrInfo *pOrInfo; /* Extra information if (eOperator & WO_OR)!=0 */ |
| 124052 | WhereAndInfo *pAndInfo; /* Extra information if (eOperator& WO_AND)!=0 */ |
| 124053 | } u; |
| 124054 | LogEst truthProb; /* Probability of truth for this expression */ |
| 124055 | u16 eOperator; /* A WO_xx value describing <op> */ |
| 124056 | u16 wtFlags; /* TERM_xxx bit flags. See below */ |
| 124057 | u8 nChild; /* Number of children that must disable us */ |
| 124058 | u8 eMatchOp; /* Op for vtab MATCH/LIKE/GLOB/REGEXP terms */ |
| 124059 | WhereClause *pWC; /* The clause this term is part of */ |
| 124060 | Bitmask prereqRight; /* Bitmask of tables used by pExpr->pRight */ |
| 124061 | Bitmask prereqAll; /* Bitmask of tables referenced by pExpr */ |
| 124062 | }; |
| 124063 | |
| 124064 | /* |
| @@ -124207,29 +124255,29 @@ | |
| 124207 | struct WhereInfo { |
| 124208 | Parse *pParse; /* Parsing and code generating context */ |
| 124209 | SrcList *pTabList; /* List of tables in the join */ |
| 124210 | ExprList *pOrderBy; /* The ORDER BY clause or NULL */ |
| 124211 | ExprList *pDistinctSet; /* DISTINCT over all these values */ |
| 124212 | WhereLoop *pLoops; /* List of all WhereLoop objects */ |
| 124213 | Bitmask revMask; /* Mask of ORDER BY terms that need reversing */ |
| 124214 | LogEst nRowOut; /* Estimated number of output rows */ |
| 124215 | LogEst iLimit; /* LIMIT if wctrlFlags has WHERE_USE_LIMIT */ |
| 124216 | u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */ |
| 124217 | i8 nOBSat; /* Number of ORDER BY terms satisfied by indices */ |
| 124218 | u8 sorted; /* True if really sorted (not just grouped) */ |
| 124219 | u8 eOnePass; /* ONEPASS_OFF, or _SINGLE, or _MULTI */ |
| 124220 | u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */ |
| 124221 | u8 eDistinct; /* One of the WHERE_DISTINCT_* values */ |
| 124222 | u8 nLevel; /* Number of nested loop */ |
| 124223 | u8 bOrderedInnerLoop; /* True if only the inner-most loop is ordered */ |
| 124224 | int iTop; /* The very beginning of the WHERE loop */ |
| 124225 | int iContinue; /* Jump here to continue with next record */ |
| 124226 | int iBreak; /* Jump here to break out of the loop */ |
| 124227 | int savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */ |
| 124228 | int aiCurOnePass[2]; /* OP_OpenWrite cursors for the ONEPASS opt */ |
| 124229 | WhereMaskSet sMaskSet; /* Map cursor numbers to bitmasks */ |
| 124230 | WhereClause sWC; /* Decomposition of the WHERE clause */ |
| 124231 | WhereLevel a[1]; /* Information about each nest loop in WHERE */ |
| 124232 | }; |
| 124233 | |
| 124234 | /* |
| 124235 | ** Private interfaces - callable only by other where.c routines. |
| @@ -124689,11 +124737,10 @@ | |
| 124689 | ** |
| 124690 | ** * the comparison will be performed with no affinity, or |
| 124691 | ** * the affinity change in zAff is guaranteed not to change the value. |
| 124692 | */ |
| 124693 | static void updateRangeAffinityStr( |
| 124694 | Parse *pParse, /* Parse context */ |
| 124695 | Expr *pRight, /* RHS of comparison */ |
| 124696 | int n, /* Number of vector elements in comparison */ |
| 124697 | char *zAff /* Affinity string to modify */ |
| 124698 | ){ |
| 124699 | int i; |
| @@ -125775,15 +125822,15 @@ | |
| 125775 | assert( (bRev & ~1)==0 ); |
| 125776 | pLevel->iLikeRepCntr <<=1; |
| 125777 | pLevel->iLikeRepCntr |= bRev ^ (pIdx->aSortOrder[nEq]==SQLITE_SO_DESC); |
| 125778 | } |
| 125779 | #endif |
| 125780 | if( pRangeStart==0 |
| 125781 | && (j = pIdx->aiColumn[nEq])>=0 |
| 125782 | && pIdx->pTable->aCol[j].notNull==0 |
| 125783 | ){ |
| 125784 | bSeekPastNull = 1; |
| 125785 | } |
| 125786 | } |
| 125787 | assert( pRangeEnd==0 || (pRangeEnd->wtFlags & TERM_VNULL)==0 ); |
| 125788 | |
| 125789 | /* If we are doing a reverse order scan on an ascending index, or |
| @@ -125829,11 +125876,11 @@ | |
| 125829 | ){ |
| 125830 | sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt); |
| 125831 | VdbeCoverage(v); |
| 125832 | } |
| 125833 | if( zStartAff ){ |
| 125834 | updateRangeAffinityStr(pParse, pRight, nBtm, &zStartAff[nEq]); |
| 125835 | } |
| 125836 | nConstraint += nBtm; |
| 125837 | testcase( pRangeStart->wtFlags & TERM_VIRTUAL ); |
| 125838 | if( sqlite3ExprIsVector(pRight)==0 ){ |
| 125839 | disableTerm(pLevel, pRangeStart); |
| @@ -125879,11 +125926,11 @@ | |
| 125879 | ){ |
| 125880 | sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt); |
| 125881 | VdbeCoverage(v); |
| 125882 | } |
| 125883 | if( zEndAff ){ |
| 125884 | updateRangeAffinityStr(pParse, pRight, nTop, zEndAff); |
| 125885 | codeApplyAffinity(pParse, regBase+nEq, nTop, zEndAff); |
| 125886 | }else{ |
| 125887 | assert( pParse->db->mallocFailed ); |
| 125888 | } |
| 125889 | nConstraint += nTop; |
| @@ -126315,11 +126362,11 @@ | |
| 126315 | ** and we are coding the t1 loop and the t2 loop has not yet coded, |
| 126316 | ** then we cannot use the "t1.a=t2.b" constraint, but we can code |
| 126317 | ** the implied "t1.a=123" constraint. |
| 126318 | */ |
| 126319 | for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){ |
| 126320 | Expr *pE, *pEAlt; |
| 126321 | WhereTerm *pAlt; |
| 126322 | if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue; |
| 126323 | if( (pTerm->eOperator & (WO_EQ|WO_IS))==0 ) continue; |
| 126324 | if( (pTerm->eOperator & WO_EQUIV)==0 ) continue; |
| 126325 | if( pTerm->leftCursor!=iCur ) continue; |
| @@ -126333,17 +126380,13 @@ | |
| 126333 | if( pAlt->wtFlags & (TERM_CODED) ) continue; |
| 126334 | testcase( pAlt->eOperator & WO_EQ ); |
| 126335 | testcase( pAlt->eOperator & WO_IS ); |
| 126336 | testcase( pAlt->eOperator & WO_IN ); |
| 126337 | VdbeModuleComment((v, "begin transitive constraint")); |
| 126338 | pEAlt = sqlite3StackAllocRaw(db, sizeof(*pEAlt)); |
| 126339 | if( pEAlt ){ |
| 126340 | *pEAlt = *pAlt->pExpr; |
| 126341 | pEAlt->pLeft = pE->pLeft; |
| 126342 | sqlite3ExprIfFalse(pParse, pEAlt, addrCont, SQLITE_JUMPIFNULL); |
| 126343 | sqlite3StackFree(db, pEAlt); |
| 126344 | } |
| 126345 | } |
| 126346 | |
| 126347 | /* For a LEFT OUTER JOIN, generate code that will record the fact that |
| 126348 | ** at least one row of the right table has matched the left table. |
| 126349 | */ |
| @@ -126448,11 +126491,10 @@ | |
| 126448 | memcpy(pWC->a, pOld, sizeof(pWC->a[0])*pWC->nTerm); |
| 126449 | if( pOld!=pWC->aStatic ){ |
| 126450 | sqlite3DbFree(db, pOld); |
| 126451 | } |
| 126452 | pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]); |
| 126453 | memset(&pWC->a[pWC->nTerm], 0, sizeof(pWC->a[0])*(pWC->nSlot-pWC->nTerm)); |
| 126454 | } |
| 126455 | pTerm = &pWC->a[idx = pWC->nTerm++]; |
| 126456 | if( p && ExprHasProperty(p, EP_Unlikely) ){ |
| 126457 | pTerm->truthProb = sqlite3LogEst(p->iTable) - 270; |
| 126458 | }else{ |
| @@ -126460,10 +126502,12 @@ | |
| 126460 | } |
| 126461 | pTerm->pExpr = sqlite3ExprSkipCollate(p); |
| 126462 | pTerm->wtFlags = wtFlags; |
| 126463 | pTerm->pWC = pWC; |
| 126464 | pTerm->iParent = -1; |
| 126465 | return idx; |
| 126466 | } |
| 126467 | |
| 126468 | /* |
| 126469 | ** Return TRUE if the given operator is one of the operators that is |
| @@ -127568,10 +127612,11 @@ | |
| 127568 | Expr *pNew; |
| 127569 | Expr *pLeft = sqlite3ExprForVectorField(pParse, pExpr->pLeft, i); |
| 127570 | Expr *pRight = sqlite3ExprForVectorField(pParse, pExpr->pRight, i); |
| 127571 | |
| 127572 | pNew = sqlite3PExpr(pParse, pExpr->op, pLeft, pRight, 0); |
| 127573 | idxNew = whereClauseInsert(pWC, pNew, TERM_DYNAMIC); |
| 127574 | exprAnalyze(pSrc, pWC, idxNew); |
| 127575 | } |
| 127576 | pTerm = &pWC->a[idxTerm]; |
| 127577 | pTerm->wtFlags = TERM_CODED|TERM_VIRTUAL; /* Disable the original */ |
| @@ -127618,11 +127663,11 @@ | |
| 127618 | int idxNew; |
| 127619 | WhereTerm *pNewTerm; |
| 127620 | |
| 127621 | pNewExpr = sqlite3PExpr(pParse, TK_GT, |
| 127622 | sqlite3ExprDup(db, pLeft, 0), |
| 127623 | sqlite3PExpr(pParse, TK_NULL, 0, 0, 0), 0); |
| 127624 | |
| 127625 | idxNew = whereClauseInsert(pWC, pNewExpr, |
| 127626 | TERM_VIRTUAL|TERM_DYNAMIC|TERM_VNULL); |
| 127627 | if( idxNew ){ |
| 127628 | pNewTerm = &pWC->a[idxNew]; |
| @@ -127796,11 +127841,11 @@ | |
| 127796 | if( k>=pTab->nCol ){ |
| 127797 | sqlite3ErrorMsg(pParse, "too many arguments on %s() - max %d", |
| 127798 | pTab->zName, j); |
| 127799 | return; |
| 127800 | } |
| 127801 | pColRef = sqlite3PExpr(pParse, TK_COLUMN, 0, 0, 0); |
| 127802 | if( pColRef==0 ) return; |
| 127803 | pColRef->iTable = pItem->iCursor; |
| 127804 | pColRef->iColumn = k++; |
| 127805 | pColRef->pTab = pTab; |
| 127806 | pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef, |
| @@ -128009,15 +128054,17 @@ | |
| 128009 | Expr *pX; /* An expression being tested */ |
| 128010 | WhereClause *pWC; /* Shorthand for pScan->pWC */ |
| 128011 | WhereTerm *pTerm; /* The term being tested */ |
| 128012 | int k = pScan->k; /* Where to start scanning */ |
| 128013 | |
| 128014 | while( pScan->iEquiv<=pScan->nEquiv ){ |
| 128015 | iCur = pScan->aiCur[pScan->iEquiv-1]; |
| 128016 | iColumn = pScan->aiColumn[pScan->iEquiv-1]; |
| 128017 | if( iColumn==XN_EXPR && pScan->pIdxExpr==0 ) return 0; |
| 128018 | while( (pWC = pScan->pWC)!=0 ){ |
| 128019 | for(pTerm=pWC->a+k; k<pWC->nTerm; k++, pTerm++){ |
| 128020 | if( pTerm->leftCursor==iCur |
| 128021 | && pTerm->u.leftColumn==iColumn |
| 128022 | && (iColumn!=XN_EXPR |
| 128023 | || sqlite3ExprCompare(pTerm->pExpr->pLeft,pScan->pIdxExpr,iCur)==0) |
| @@ -128063,19 +128110,21 @@ | |
| 128063 | && pX->iColumn==pScan->aiColumn[0] |
| 128064 | ){ |
| 128065 | testcase( pTerm->eOperator & WO_IS ); |
| 128066 | continue; |
| 128067 | } |
| 128068 | pScan->k = k+1; |
| 128069 | return pTerm; |
| 128070 | } |
| 128071 | } |
| 128072 | } |
| 128073 | pScan->pWC = pScan->pWC->pOuter; |
| 128074 | k = 0; |
| 128075 | } |
| 128076 | pScan->pWC = pScan->pOrigWC; |
| 128077 | k = 0; |
| 128078 | pScan->iEquiv++; |
| 128079 | } |
| 128080 | return 0; |
| 128081 | } |
| @@ -128105,28 +128154,28 @@ | |
| 128105 | int iCur, /* Cursor to scan for */ |
| 128106 | int iColumn, /* Column to scan for */ |
| 128107 | u32 opMask, /* Operator(s) to scan for */ |
| 128108 | Index *pIdx /* Must be compatible with this index */ |
| 128109 | ){ |
| 128110 | int j = 0; |
| 128111 | |
| 128112 | /* memset(pScan, 0, sizeof(*pScan)); */ |
| 128113 | pScan->pOrigWC = pWC; |
| 128114 | pScan->pWC = pWC; |
| 128115 | pScan->pIdxExpr = 0; |
| 128116 | if( pIdx ){ |
| 128117 | j = iColumn; |
| 128118 | iColumn = pIdx->aiColumn[j]; |
| 128119 | if( iColumn==XN_EXPR ) pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr; |
| 128120 | if( iColumn==pIdx->pTable->iPKey ) iColumn = XN_ROWID; |
| 128121 | } |
| 128122 | if( pIdx && iColumn>=0 ){ |
| 128123 | pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity; |
| 128124 | pScan->zCollName = pIdx->azColl[j]; |
| 128125 | }else{ |
| 128126 | pScan->idxaff = 0; |
| 128127 | pScan->zCollName = 0; |
| 128128 | } |
| 128129 | pScan->opMask = opMask; |
| 128130 | pScan->k = 0; |
| 128131 | pScan->aiCur[0] = iCur; |
| 128132 | pScan->aiColumn[0] = iColumn; |
| @@ -130034,11 +130083,11 @@ | |
| 130034 | ** CREATE INDEX ... ON (a, b, c, d, e) |
| 130035 | ** |
| 130036 | ** then this function would be invoked with nEq=1. The value returned in |
| 130037 | ** this case is 3. |
| 130038 | */ |
| 130039 | int whereRangeVectorLen( |
| 130040 | Parse *pParse, /* Parsing context */ |
| 130041 | int iCur, /* Cursor open on pIdx */ |
| 130042 | Index *pIdx, /* The index to be used for a inequality constraint */ |
| 130043 | int nEq, /* Number of prior equality constraints on same index */ |
| 130044 | WhereTerm *pTerm /* The vector inequality constraint */ |
| @@ -131480,11 +131529,11 @@ | |
| 131480 | if( rev ) *pRevMask |= MASKBIT(iLoop); |
| 131481 | revSet = 1; |
| 131482 | } |
| 131483 | } |
| 131484 | if( isMatch ){ |
| 131485 | if( iColumn<0 ){ |
| 131486 | testcase( distinctColumns==0 ); |
| 131487 | distinctColumns = 1; |
| 131488 | } |
| 131489 | obSat |= MASKBIT(i); |
| 131490 | }else{ |
| @@ -131935,17 +131984,24 @@ | |
| 131935 | }else{ |
| 131936 | pWInfo->nOBSat = pFrom->isOrdered; |
| 131937 | pWInfo->revMask = pFrom->revLoop; |
| 131938 | if( pWInfo->nOBSat<=0 ){ |
| 131939 | pWInfo->nOBSat = 0; |
| 131940 | if( nLoop>0 && (pFrom->aLoop[nLoop-1]->wsFlags & WHERE_ONEROW)==0 ){ |
| 131941 | Bitmask m = 0; |
| 131942 | int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pOrderBy, pFrom, |
| 131943 | WHERE_ORDERBY_LIMIT, nLoop-1, pFrom->aLoop[nLoop-1], &m); |
| 131944 | if( rc==pWInfo->pOrderBy->nExpr ){ |
| 131945 | pWInfo->bOrderedInnerLoop = 1; |
| 131946 | pWInfo->revMask = m; |
| 131947 | } |
| 131948 | } |
| 131949 | } |
| 131950 | } |
| 131951 | if( (pWInfo->wctrlFlags & WHERE_SORTBYGROUP) |
| @@ -132218,26 +132274,29 @@ | |
| 132218 | ** and the WhereMaskSet structure. Since WhereClause contains an 8-byte |
| 132219 | ** field (type Bitmask) it must be aligned on an 8-byte boundary on |
| 132220 | ** some architectures. Hence the ROUND8() below. |
| 132221 | */ |
| 132222 | nByteWInfo = ROUND8(sizeof(WhereInfo)+(nTabList-1)*sizeof(WhereLevel)); |
| 132223 | pWInfo = sqlite3DbMallocZero(db, nByteWInfo + sizeof(WhereLoop)); |
| 132224 | if( db->mallocFailed ){ |
| 132225 | sqlite3DbFree(db, pWInfo); |
| 132226 | pWInfo = 0; |
| 132227 | goto whereBeginError; |
| 132228 | } |
| 132229 | pWInfo->aiCurOnePass[0] = pWInfo->aiCurOnePass[1] = -1; |
| 132230 | pWInfo->nLevel = nTabList; |
| 132231 | pWInfo->pParse = pParse; |
| 132232 | pWInfo->pTabList = pTabList; |
| 132233 | pWInfo->pOrderBy = pOrderBy; |
| 132234 | pWInfo->pDistinctSet = pDistinctSet; |
| 132235 | pWInfo->iBreak = pWInfo->iContinue = sqlite3VdbeMakeLabel(v); |
| 132236 | pWInfo->wctrlFlags = wctrlFlags; |
| 132237 | pWInfo->iLimit = iAuxArg; |
| 132238 | pWInfo->savedNQueryLoop = pParse->nQueryLoop; |
| 132239 | assert( pWInfo->eOnePass==ONEPASS_OFF ); /* ONEPASS defaults to OFF */ |
| 132240 | pMaskSet = &pWInfo->sMaskSet; |
| 132241 | sWLB.pWInfo = pWInfo; |
| 132242 | sWLB.pWC = &pWInfo->sWC; |
| 132243 | sWLB.pNew = (WhereLoop*)(((char*)pWInfo)+nByteWInfo); |
| @@ -132661,17 +132720,19 @@ | |
| 132661 | pLevel->addrLikeRep); |
| 132662 | VdbeCoverage(v); |
| 132663 | } |
| 132664 | #endif |
| 132665 | if( pLevel->iLeftJoin ){ |
| 132666 | addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); VdbeCoverage(v); |
| 132667 | assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 |
| 132668 | || (pLoop->wsFlags & WHERE_INDEXED)!=0 ); |
| 132669 | if( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 ){ |
| 132670 | sqlite3VdbeAddOp1(v, OP_NullRow, pTabList->a[i].iCursor); |
| 132671 | } |
| 132672 | if( pLoop->wsFlags & WHERE_INDEXED ){ |
| 132673 | sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iIdxCur); |
| 132674 | } |
| 132675 | if( pLevel->op==OP_Return ){ |
| 132676 | sqlite3VdbeAddOp2(v, OP_Gosub, pLevel->p1, pLevel->addrFirst); |
| 132677 | }else{ |
| @@ -132844,19 +132905,10 @@ | |
| 132844 | struct LimitVal { |
| 132845 | Expr *pLimit; /* The LIMIT expression. NULL if there is no limit */ |
| 132846 | Expr *pOffset; /* The OFFSET expression. NULL if there is none */ |
| 132847 | }; |
| 132848 | |
| 132849 | /* |
| 132850 | ** An instance of this structure is used to store the LIKE, |
| 132851 | ** GLOB, NOT LIKE, and NOT GLOB operators. |
| 132852 | */ |
| 132853 | struct LikeOp { |
| 132854 | Token eOperator; /* "like" or "glob" or "regexp" */ |
| 132855 | int bNot; /* True if the NOT keyword is present */ |
| 132856 | }; |
| 132857 | |
| 132858 | /* |
| 132859 | ** An instance of the following structure describes the event of a |
| 132860 | ** TRIGGER. "a" is the event type, one of TK_UPDATE, TK_INSERT, |
| 132861 | ** TK_DELETE, or TK_INSTEAD. If the event is of the form |
| 132862 | ** |
| @@ -132864,15 +132916,10 @@ | |
| 132864 | ** |
| 132865 | ** Then the "b" IdList records the list "a,b,c". |
| 132866 | */ |
| 132867 | struct TrigEvent { int a; IdList * b; }; |
| 132868 | |
| 132869 | /* |
| 132870 | ** An instance of this structure holds the ATTACH key and the key type. |
| 132871 | */ |
| 132872 | struct AttachKey { int type; Token key; }; |
| 132873 | |
| 132874 | /* |
| 132875 | ** Disable lookaside memory allocation for objects that might be |
| 132876 | ** shared across database connections. |
| 132877 | */ |
| 132878 | static void disableLookaside(Parse *pParse){ |
| @@ -132915,11 +132962,28 @@ | |
| 132915 | /* Construct a new Expr object from a single identifier. Use the |
| 132916 | ** new Expr to populate pOut. Set the span of pOut to be the identifier |
| 132917 | ** that created the expression. |
| 132918 | */ |
| 132919 | static void spanExpr(ExprSpan *pOut, Parse *pParse, int op, Token t){ |
| 132920 | pOut->pExpr = sqlite3PExpr(pParse, op, 0, 0, &t); |
| 132921 | pOut->zStart = t.z; |
| 132922 | pOut->zEnd = &t.z[t.n]; |
| 132923 | } |
| 132924 | |
| 132925 | /* This routine constructs a binary expression node out of two ExprSpan |
| @@ -133078,11 +133142,10 @@ | |
| 133078 | Select* yy243; |
| 133079 | IdList* yy254; |
| 133080 | With* yy285; |
| 133081 | struct TrigEvent yy332; |
| 133082 | struct LimitVal yy354; |
| 133083 | struct LikeOp yy392; |
| 133084 | struct {int value; int mask;} yy497; |
| 133085 | } YYMINORTYPE; |
| 133086 | #ifndef YYSTACKDEPTH |
| 133087 | #define YYSTACKDEPTH 100 |
| 133088 | #endif |
| @@ -133090,19 +133153,19 @@ | |
| 133090 | #define sqlite3ParserARG_PDECL ,Parse *pParse |
| 133091 | #define sqlite3ParserARG_FETCH Parse *pParse = yypParser->pParse |
| 133092 | #define sqlite3ParserARG_STORE yypParser->pParse = pParse |
| 133093 | #define YYFALLBACK 1 |
| 133094 | #define YYNSTATE 456 |
| 133095 | #define YYNRULE 331 |
| 133096 | #define YY_MAX_SHIFT 455 |
| 133097 | #define YY_MIN_SHIFTREDUCE 667 |
| 133098 | #define YY_MAX_SHIFTREDUCE 997 |
| 133099 | #define YY_MIN_REDUCE 998 |
| 133100 | #define YY_MAX_REDUCE 1328 |
| 133101 | #define YY_ERROR_ACTION 1329 |
| 133102 | #define YY_ACCEPT_ACTION 1330 |
| 133103 | #define YY_NO_ACTION 1331 |
| 133104 | /************* End control #defines *******************************************/ |
| 133105 | |
| 133106 | /* Define the yytestcase() macro to be a no-op if is not already defined |
| 133107 | ** otherwise. |
| 133108 | ** |
| @@ -133170,170 +133233,169 @@ | |
| 133170 | ** yy_reduce_ofst[] For each state, the offset into yy_action for |
| 133171 | ** shifting non-terminals after a reduce. |
| 133172 | ** yy_default[] Default action for each state. |
| 133173 | ** |
| 133174 | *********** Begin parsing tables **********************************************/ |
| 133175 | #define YY_ACTTAB_COUNT (1571) |
| 133176 | static const YYACTIONTYPE yy_action[] = { |
| 133177 | /* 0 */ 325, 830, 351, 824, 5, 203, 203, 818, 99, 100, |
| 133178 | /* 10 */ 90, 840, 840, 852, 855, 844, 844, 97, 97, 98, |
| 133179 | /* 20 */ 98, 98, 98, 301, 96, 96, 96, 96, 95, 95, |
| 133180 | /* 30 */ 94, 94, 94, 93, 351, 325, 975, 975, 823, 823, |
| 133181 | /* 40 */ 823, 945, 354, 99, 100, 90, 840, 840, 852, 855, |
| 133182 | /* 50 */ 844, 844, 97, 97, 98, 98, 98, 98, 338, 96, |
| 133183 | /* 60 */ 96, 96, 96, 95, 95, 94, 94, 94, 93, 351, |
| 133184 | /* 70 */ 95, 95, 94, 94, 94, 93, 351, 790, 975, 975, |
| 133185 | /* 80 */ 325, 94, 94, 94, 93, 351, 791, 75, 99, 100, |
| 133186 | /* 90 */ 90, 840, 840, 852, 855, 844, 844, 97, 97, 98, |
| 133187 | /* 100 */ 98, 98, 98, 450, 96, 96, 96, 96, 95, 95, |
| 133188 | /* 110 */ 94, 94, 94, 93, 351, 1330, 155, 155, 2, 325, |
| 133189 | /* 120 */ 275, 146, 132, 52, 52, 93, 351, 99, 100, 90, |
| 133190 | /* 130 */ 840, 840, 852, 855, 844, 844, 97, 97, 98, 98, |
| 133191 | /* 140 */ 98, 98, 101, 96, 96, 96, 96, 95, 95, 94, |
| 133192 | /* 150 */ 94, 94, 93, 351, 956, 956, 325, 268, 428, 413, |
| 133193 | /* 160 */ 411, 61, 751, 751, 99, 100, 90, 840, 840, 852, |
| 133194 | /* 170 */ 855, 844, 844, 97, 97, 98, 98, 98, 98, 60, |
| 133195 | /* 180 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, |
| 133196 | /* 190 */ 351, 325, 270, 329, 273, 277, 957, 958, 250, 99, |
| 133197 | /* 200 */ 100, 90, 840, 840, 852, 855, 844, 844, 97, 97, |
| 133198 | /* 210 */ 98, 98, 98, 98, 301, 96, 96, 96, 96, 95, |
| 133199 | /* 220 */ 95, 94, 94, 94, 93, 351, 325, 936, 1323, 697, |
| 133200 | /* 230 */ 705, 1323, 242, 412, 99, 100, 90, 840, 840, 852, |
| 133201 | /* 240 */ 855, 844, 844, 97, 97, 98, 98, 98, 98, 347, |
| 133202 | /* 250 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, |
| 133203 | /* 260 */ 351, 325, 936, 1324, 384, 698, 1324, 381, 379, 99, |
| 133204 | /* 270 */ 100, 90, 840, 840, 852, 855, 844, 844, 97, 97, |
| 133205 | /* 280 */ 98, 98, 98, 98, 700, 96, 96, 96, 96, 95, |
| 133206 | /* 290 */ 95, 94, 94, 94, 93, 351, 325, 92, 89, 178, |
| 133207 | /* 300 */ 831, 934, 373, 699, 99, 100, 90, 840, 840, 852, |
| 133208 | /* 310 */ 855, 844, 844, 97, 97, 98, 98, 98, 98, 375, |
| 133209 | /* 320 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, |
| 133210 | /* 330 */ 351, 325, 1273, 945, 354, 817, 934, 738, 738, 99, |
| 133211 | /* 340 */ 100, 90, 840, 840, 852, 855, 844, 844, 97, 97, |
| 133212 | /* 350 */ 98, 98, 98, 98, 230, 96, 96, 96, 96, 95, |
| 133213 | /* 360 */ 95, 94, 94, 94, 93, 351, 325, 967, 227, 92, |
| 133214 | /* 370 */ 89, 178, 373, 300, 99, 100, 90, 840, 840, 852, |
| 133215 | /* 380 */ 855, 844, 844, 97, 97, 98, 98, 98, 98, 919, |
| 133216 | /* 390 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, |
| 133217 | /* 400 */ 351, 325, 449, 447, 447, 447, 147, 736, 736, 99, |
| 133218 | /* 410 */ 100, 90, 840, 840, 852, 855, 844, 844, 97, 97, |
| 133219 | /* 420 */ 98, 98, 98, 98, 296, 96, 96, 96, 96, 95, |
| 133220 | /* 430 */ 95, 94, 94, 94, 93, 351, 325, 419, 231, 956, |
| 133221 | /* 440 */ 956, 158, 25, 422, 99, 100, 90, 840, 840, 852, |
| 133222 | /* 450 */ 855, 844, 844, 97, 97, 98, 98, 98, 98, 450, |
| 133223 | /* 460 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, |
| 133224 | /* 470 */ 351, 443, 224, 224, 420, 956, 956, 960, 325, 52, |
| 133225 | /* 480 */ 52, 957, 958, 176, 415, 78, 99, 100, 90, 840, |
| 133226 | /* 490 */ 840, 852, 855, 844, 844, 97, 97, 98, 98, 98, |
| 133227 | /* 500 */ 98, 379, 96, 96, 96, 96, 95, 95, 94, 94, |
| 133228 | /* 510 */ 94, 93, 351, 325, 428, 418, 298, 957, 958, 960, |
| 133229 | /* 520 */ 81, 99, 88, 90, 840, 840, 852, 855, 844, 844, |
| 133230 | /* 530 */ 97, 97, 98, 98, 98, 98, 716, 96, 96, 96, |
| 133231 | /* 540 */ 96, 95, 95, 94, 94, 94, 93, 351, 325, 841, |
| 133232 | /* 550 */ 841, 853, 856, 994, 318, 343, 379, 100, 90, 840, |
| 133233 | /* 560 */ 840, 852, 855, 844, 844, 97, 97, 98, 98, 98, |
| 133234 | /* 570 */ 98, 450, 96, 96, 96, 96, 95, 95, 94, 94, |
| 133235 | /* 580 */ 94, 93, 351, 325, 350, 350, 350, 260, 377, 340, |
| 133236 | /* 590 */ 927, 52, 52, 90, 840, 840, 852, 855, 844, 844, |
| 133237 | /* 600 */ 97, 97, 98, 98, 98, 98, 361, 96, 96, 96, |
| 133238 | /* 610 */ 96, 95, 95, 94, 94, 94, 93, 351, 86, 445, |
| 133239 | /* 620 */ 845, 3, 1200, 361, 360, 378, 344, 812, 956, 956, |
| 133240 | /* 630 */ 1297, 86, 445, 728, 3, 212, 169, 287, 405, 282, |
| 133241 | /* 640 */ 404, 199, 232, 450, 300, 759, 83, 84, 280, 245, |
| 133242 | /* 650 */ 262, 365, 251, 85, 352, 352, 92, 89, 178, 83, |
| 133243 | /* 660 */ 84, 242, 412, 52, 52, 448, 85, 352, 352, 246, |
| 133244 | /* 670 */ 957, 958, 194, 455, 669, 402, 399, 398, 448, 243, |
| 133245 | /* 680 */ 221, 114, 434, 775, 361, 450, 397, 268, 746, 224, |
| 133246 | /* 690 */ 224, 132, 132, 198, 830, 434, 452, 451, 428, 427, |
| 133247 | /* 700 */ 818, 415, 733, 712, 132, 52, 52, 830, 268, 452, |
| 133248 | /* 710 */ 451, 733, 194, 818, 363, 402, 399, 398, 450, 1268, |
| 133249 | /* 720 */ 1268, 23, 956, 956, 86, 445, 397, 3, 228, 429, |
| 133250 | /* 730 */ 893, 823, 823, 823, 825, 19, 203, 719, 52, 52, |
| 133251 | /* 740 */ 428, 408, 439, 249, 823, 823, 823, 825, 19, 229, |
| 133252 | /* 750 */ 403, 153, 83, 84, 760, 177, 241, 450, 720, 85, |
| 133253 | /* 760 */ 352, 352, 120, 157, 957, 958, 58, 975, 409, 355, |
| 133254 | /* 770 */ 330, 448, 268, 428, 430, 320, 789, 32, 32, 86, |
| 133255 | /* 780 */ 445, 775, 3, 341, 98, 98, 98, 98, 434, 96, |
| 133256 | /* 790 */ 96, 96, 96, 95, 95, 94, 94, 94, 93, 351, |
| 133257 | /* 800 */ 830, 120, 452, 451, 812, 885, 818, 83, 84, 975, |
| 133258 | /* 810 */ 812, 132, 410, 918, 85, 352, 352, 132, 407, 788, |
| 133259 | /* 820 */ 956, 956, 92, 89, 178, 915, 448, 262, 370, 261, |
| 133260 | /* 830 */ 82, 912, 80, 262, 370, 261, 932, 823, 823, 823, |
| 133261 | /* 840 */ 825, 19, 257, 434, 96, 96, 96, 96, 95, 95, |
| 133262 | /* 850 */ 94, 94, 94, 93, 351, 830, 268, 452, 451, 956, |
| 133263 | /* 860 */ 956, 818, 957, 958, 120, 92, 89, 178, 943, 2, |
| 133264 | /* 870 */ 916, 963, 268, 1, 766, 76, 445, 761, 3, 707, |
| 133265 | /* 880 */ 899, 899, 387, 956, 956, 756, 917, 371, 739, 777, |
| 133266 | /* 890 */ 755, 907, 823, 823, 823, 825, 19, 883, 740, 450, |
| 133267 | /* 900 */ 24, 957, 958, 83, 84, 369, 956, 956, 708, 226, |
| 133268 | /* 910 */ 85, 352, 352, 745, 315, 314, 313, 215, 311, 10, |
| 133269 | /* 920 */ 10, 682, 448, 349, 348, 957, 958, 887, 776, 691, |
| 133270 | /* 930 */ 331, 956, 956, 337, 157, 450, 268, 103, 450, 434, |
| 133271 | /* 940 */ 450, 816, 310, 906, 887, 889, 321, 450, 957, 958, |
| 133272 | /* 950 */ 708, 830, 775, 452, 451, 10, 10, 818, 10, 10, |
| 133273 | /* 960 */ 52, 52, 171, 170, 180, 225, 248, 10, 10, 339, |
| 133274 | /* 970 */ 701, 701, 233, 957, 958, 247, 982, 741, 450, 956, |
| 133275 | /* 980 */ 956, 425, 157, 980, 685, 981, 182, 912, 823, 823, |
| 133276 | /* 990 */ 823, 825, 19, 183, 324, 423, 132, 181, 51, 51, |
| 133277 | /* 1000 */ 715, 349, 348, 394, 256, 887, 334, 915, 983, 983, |
| 133278 | /* 1010 */ 830, 417, 824, 234, 198, 234, 818, 268, 326, 382, |
| 133279 | /* 1020 */ 120, 957, 958, 264, 177, 98, 98, 98, 98, 91, |
| 133280 | /* 1030 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, |
| 133281 | /* 1040 */ 351, 816, 416, 371, 120, 359, 816, 823, 823, 823, |
| 133282 | /* 1050 */ 775, 299, 916, 450, 368, 197, 196, 195, 358, 200, |
| 133283 | /* 1060 */ 175, 380, 9, 9, 450, 1287, 875, 714, 917, 450, |
| 133284 | /* 1070 */ 433, 237, 450, 36, 36, 132, 253, 450, 255, 450, |
| 133285 | /* 1080 */ 117, 450, 809, 362, 37, 37, 983, 983, 450, 12, |
| 133286 | /* 1090 */ 12, 330, 27, 27, 446, 331, 280, 38, 38, 39, |
| 133287 | /* 1100 */ 39, 40, 40, 1207, 450, 816, 335, 356, 41, 41, |
| 133288 | /* 1110 */ 450, 336, 450, 695, 450, 120, 450, 332, 133, 450, |
| 133289 | /* 1120 */ 268, 450, 269, 450, 42, 42, 450, 816, 254, 450, |
| 133290 | /* 1130 */ 28, 28, 29, 29, 31, 31, 43, 43, 450, 44, |
| 133291 | /* 1140 */ 44, 45, 45, 11, 11, 450, 46, 46, 450, 105, |
| 133292 | /* 1150 */ 105, 450, 748, 713, 450, 695, 450, 910, 47, 47, |
| 133293 | /* 1160 */ 450, 267, 450, 415, 450, 48, 48, 450, 33, 33, |
| 133294 | /* 1170 */ 386, 49, 49, 450, 50, 50, 34, 34, 450, 172, |
| 133295 | /* 1180 */ 122, 122, 123, 123, 124, 124, 450, 56, 56, 450, |
| 133296 | /* 1190 */ 120, 450, 345, 35, 35, 450, 790, 450, 106, 106, |
| 133297 | /* 1200 */ 450, 74, 450, 974, 450, 791, 53, 53, 432, 107, |
| 133298 | /* 1210 */ 107, 108, 108, 450, 272, 104, 104, 121, 121, 450, |
| 133299 | /* 1220 */ 119, 119, 112, 112, 111, 111, 450, 317, 996, 450, |
| 133300 | /* 1230 */ 118, 450, 162, 109, 109, 317, 935, 450, 896, 110, |
| 133301 | /* 1240 */ 110, 450, 895, 744, 688, 436, 55, 55, 20, 57, |
| 133302 | /* 1250 */ 57, 54, 54, 440, 444, 756, 385, 26, 26, 274, |
| 133303 | /* 1260 */ 755, 30, 30, 21, 672, 673, 674, 223, 175, 931, |
| 133304 | /* 1270 */ 814, 372, 319, 202, 202, 882, 120, 120, 120, 374, |
| 133305 | /* 1280 */ 826, 710, 202, 72, 276, 263, 120, 120, 74, 395, |
| 133306 | /* 1290 */ 278, 286, 208, 74, 718, 717, 725, 726, 892, 892, |
| 133307 | /* 1300 */ 167, 997, 285, 753, 729, 784, 77, 878, 202, 997, |
| 133308 | /* 1310 */ 208, 693, 891, 891, 116, 281, 782, 882, 390, 815, |
| 133309 | /* 1320 */ 762, 773, 826, 431, 302, 303, 822, 218, 696, 289, |
| 133310 | /* 1330 */ 690, 291, 293, 679, 678, 680, 950, 159, 316, 7, |
| 133311 | /* 1340 */ 364, 252, 259, 804, 909, 376, 400, 295, 308, 173, |
| 133312 | /* 1350 */ 435, 953, 168, 991, 135, 205, 926, 924, 59, 988, |
| 133313 | /* 1360 */ 62, 284, 880, 333, 879, 712, 144, 156, 130, 72, |
| 133314 | /* 1370 */ 366, 367, 393, 185, 189, 160, 383, 67, 389, 266, |
| 133315 | /* 1380 */ 137, 894, 774, 219, 154, 139, 190, 140, 391, 271, |
| 133316 | /* 1390 */ 191, 141, 142, 801, 681, 148, 811, 342, 322, 192, |
| 133317 | /* 1400 */ 406, 732, 911, 874, 723, 731, 323, 710, 730, 71, |
| 133318 | /* 1410 */ 704, 204, 283, 703, 6, 79, 421, 702, 965, 770, |
| 133319 | /* 1420 */ 297, 346, 426, 102, 722, 288, 73, 424, 213, 951, |
| 133320 | /* 1430 */ 771, 438, 22, 290, 687, 769, 442, 453, 239, 217, |
| 133321 | /* 1440 */ 214, 668, 125, 353, 126, 216, 454, 166, 676, 115, |
| 133322 | /* 1450 */ 675, 235, 244, 179, 670, 357, 810, 113, 890, 888, |
| 133323 | /* 1460 */ 292, 136, 128, 752, 304, 768, 294, 305, 138, 742, |
| 133324 | /* 1470 */ 306, 307, 127, 184, 860, 258, 905, 145, 143, 238, |
| 133325 | /* 1480 */ 63, 64, 65, 66, 240, 129, 908, 186, 187, 904, |
| 133326 | /* 1490 */ 8, 13, 188, 265, 897, 149, 202, 985, 388, 684, |
| 133327 | /* 1500 */ 150, 161, 392, 285, 193, 279, 151, 396, 68, 14, |
| 133328 | /* 1510 */ 401, 15, 327, 721, 328, 134, 69, 70, 236, 131, |
| 133329 | /* 1520 */ 829, 828, 858, 750, 16, 201, 754, 4, 783, 220, |
| 133330 | /* 1530 */ 414, 174, 222, 152, 77, 778, 74, 17, 18, 873, |
| 133331 | /* 1540 */ 859, 857, 914, 862, 913, 207, 206, 940, 163, 437, |
| 133332 | /* 1550 */ 946, 941, 164, 209, 210, 441, 861, 165, 312, 827, |
| 133333 | /* 1560 */ 694, 87, 1000, 309, 211, 1000, 1000, 1000, 1000, 1289, |
| 133334 | /* 1570 */ 1288, |
| 133335 | }; |
| 133336 | static const YYCODETYPE yy_lookahead[] = { |
| 133337 | /* 0 */ 19, 95, 53, 97, 22, 24, 24, 101, 27, 28, |
| 133338 | /* 10 */ 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, |
| 133339 | /* 20 */ 39, 40, 41, 152, 43, 44, 45, 46, 47, 48, |
| @@ -133415,87 +133477,86 @@ | |
| 133415 | /* 780 */ 20, 124, 22, 111, 38, 39, 40, 41, 83, 43, |
| 133416 | /* 790 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, |
| 133417 | /* 800 */ 95, 196, 97, 98, 85, 152, 101, 47, 48, 97, |
| 133418 | /* 810 */ 85, 92, 207, 193, 54, 55, 56, 92, 49, 175, |
| 133419 | /* 820 */ 55, 56, 221, 222, 223, 12, 66, 108, 109, 110, |
| 133420 | /* 830 */ 137, 163, 139, 108, 109, 110, 152, 132, 133, 134, |
| 133421 | /* 840 */ 135, 136, 152, 83, 43, 44, 45, 46, 47, 48, |
| 133422 | /* 850 */ 49, 50, 51, 52, 53, 95, 152, 97, 98, 55, |
| 133423 | /* 860 */ 56, 101, 97, 98, 196, 221, 222, 223, 146, 147, |
| 133424 | /* 870 */ 57, 171, 152, 22, 213, 19, 20, 49, 22, 179, |
| 133425 | /* 880 */ 108, 109, 110, 55, 56, 116, 73, 219, 75, 124, |
| 133426 | /* 890 */ 121, 152, 132, 133, 134, 135, 136, 193, 85, 152, |
| 133427 | /* 900 */ 232, 97, 98, 47, 48, 237, 55, 56, 55, 5, |
| 133428 | /* 910 */ 54, 55, 56, 193, 10, 11, 12, 13, 14, 172, |
| 133429 | /* 920 */ 173, 17, 66, 47, 48, 97, 98, 152, 124, 166, |
| 133430 | /* 930 */ 167, 55, 56, 186, 152, 152, 152, 22, 152, 83, |
| 133431 | /* 940 */ 152, 152, 160, 152, 169, 170, 164, 152, 97, 98, |
| 133432 | /* 950 */ 97, 95, 26, 97, 98, 172, 173, 101, 172, 173, |
| 133433 | /* 960 */ 172, 173, 47, 48, 60, 22, 62, 172, 173, 186, |
| 133434 | /* 970 */ 55, 56, 186, 97, 98, 71, 100, 193, 152, 55, |
| 133435 | /* 980 */ 56, 186, 152, 107, 21, 109, 82, 163, 132, 133, |
| 133436 | /* 990 */ 134, 135, 136, 89, 164, 207, 92, 93, 172, 173, |
| 133437 | /* 1000 */ 181, 47, 48, 19, 16, 230, 217, 12, 132, 133, |
| 133438 | /* 1010 */ 95, 163, 97, 183, 30, 185, 101, 152, 114, 152, |
| 133439 | /* 1020 */ 196, 97, 98, 152, 98, 38, 39, 40, 41, 42, |
| 133440 | /* 1030 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, |
| 133441 | /* 1040 */ 53, 152, 152, 219, 196, 141, 152, 132, 133, 134, |
| 133442 | /* 1050 */ 124, 225, 57, 152, 91, 108, 109, 110, 193, 211, |
| 133443 | /* 1060 */ 212, 237, 172, 173, 152, 122, 103, 181, 73, 152, |
| 133444 | /* 1070 */ 75, 210, 152, 172, 173, 92, 88, 152, 90, 152, |
| 133445 | /* 1080 */ 22, 152, 163, 100, 172, 173, 132, 133, 152, 172, |
| 133446 | /* 1090 */ 173, 107, 172, 173, 166, 167, 112, 172, 173, 172, |
| 133447 | /* 1100 */ 173, 172, 173, 140, 152, 152, 217, 242, 172, 173, |
| 133448 | /* 1110 */ 152, 217, 152, 55, 152, 196, 152, 245, 246, 152, |
| 133449 | /* 1120 */ 152, 152, 152, 152, 172, 173, 152, 152, 140, 152, |
| 133450 | /* 1130 */ 172, 173, 172, 173, 172, 173, 172, 173, 152, 172, |
| 133451 | /* 1140 */ 173, 172, 173, 172, 173, 152, 172, 173, 152, 172, |
| 133452 | /* 1150 */ 173, 152, 195, 152, 152, 97, 152, 163, 172, 173, |
| 133453 | /* 1160 */ 152, 193, 152, 206, 152, 172, 173, 152, 172, 173, |
| 133454 | /* 1170 */ 217, 172, 173, 152, 172, 173, 172, 173, 152, 26, |
| 133455 | /* 1180 */ 172, 173, 172, 173, 172, 173, 152, 172, 173, 152, |
| 133456 | /* 1190 */ 196, 152, 217, 172, 173, 152, 61, 152, 172, 173, |
| 133457 | /* 1200 */ 152, 26, 152, 26, 152, 70, 172, 173, 191, 172, |
| 133458 | /* 1210 */ 173, 172, 173, 152, 152, 172, 173, 172, 173, 152, |
| 133459 | /* 1220 */ 172, 173, 172, 173, 172, 173, 152, 22, 23, 152, |
| 133460 | /* 1230 */ 22, 152, 24, 172, 173, 22, 23, 152, 59, 172, |
| 133461 | /* 1240 */ 173, 152, 63, 163, 163, 163, 172, 173, 22, 172, |
| 133462 | /* 1250 */ 173, 172, 173, 163, 163, 116, 77, 172, 173, 152, |
| 133463 | /* 1260 */ 121, 172, 173, 37, 7, 8, 9, 211, 212, 23, |
| 133464 | /* 1270 */ 23, 23, 26, 26, 26, 55, 196, 196, 196, 23, |
| 133465 | /* 1280 */ 55, 106, 26, 130, 152, 23, 196, 196, 26, 23, |
| 133466 | /* 1290 */ 23, 101, 26, 26, 100, 101, 7, 8, 132, 133, |
| 133467 | /* 1300 */ 123, 96, 112, 23, 152, 23, 26, 23, 26, 96, |
| 133468 | /* 1310 */ 26, 23, 132, 133, 26, 152, 152, 97, 234, 152, |
| 133469 | /* 1320 */ 152, 152, 97, 152, 152, 152, 152, 233, 152, 210, |
| 133470 | /* 1330 */ 152, 210, 210, 152, 152, 152, 152, 197, 150, 198, |
| 133471 | /* 1340 */ 214, 214, 239, 201, 201, 239, 176, 214, 200, 184, |
| 133472 | /* 1350 */ 227, 155, 198, 67, 243, 122, 159, 159, 240, 69, |
| 133473 | /* 1360 */ 240, 175, 175, 159, 175, 180, 22, 220, 27, 130, |
| 133474 | /* 1370 */ 18, 159, 18, 158, 158, 220, 159, 137, 74, 235, |
| 133475 | /* 1380 */ 189, 236, 159, 159, 22, 192, 158, 192, 177, 159, |
| 133476 | /* 1390 */ 158, 192, 192, 201, 159, 189, 189, 76, 177, 158, |
| 133477 | /* 1400 */ 107, 174, 201, 201, 182, 174, 177, 106, 174, 107, |
| 133478 | /* 1410 */ 174, 159, 174, 176, 22, 137, 125, 174, 174, 216, |
| 133479 | /* 1420 */ 159, 53, 126, 129, 182, 215, 128, 127, 25, 13, |
| 133480 | /* 1430 */ 216, 177, 26, 215, 162, 216, 177, 161, 229, 6, |
| 133481 | /* 1440 */ 153, 4, 165, 3, 165, 153, 151, 22, 151, 178, |
| 133482 | /* 1450 */ 151, 178, 142, 15, 151, 94, 120, 16, 23, 23, |
| 133483 | /* 1460 */ 215, 131, 111, 205, 204, 216, 215, 203, 123, 20, |
| 133484 | /* 1470 */ 202, 201, 165, 125, 224, 16, 1, 131, 123, 226, |
| 133485 | /* 1480 */ 37, 37, 37, 37, 229, 111, 56, 64, 122, 1, |
| 133486 | /* 1490 */ 5, 22, 107, 140, 80, 80, 26, 87, 72, 20, |
| 133487 | /* 1500 */ 107, 24, 19, 112, 105, 23, 22, 79, 22, 22, |
| 133488 | /* 1510 */ 79, 22, 249, 58, 249, 246, 22, 26, 79, 68, |
| 133489 | /* 1520 */ 23, 23, 23, 116, 22, 64, 23, 22, 56, 23, |
| 133490 | /* 1530 */ 26, 122, 23, 22, 26, 124, 26, 64, 64, 23, |
| 133491 | /* 1540 */ 23, 23, 23, 11, 23, 22, 26, 23, 22, 24, |
| 133492 | /* 1550 */ 1, 23, 22, 26, 122, 24, 23, 22, 15, 23, |
| 133493 | /* 1560 */ 23, 22, 251, 23, 122, 251, 251, 251, 251, 122, |
| 133494 | /* 1570 */ 122, |
| 133495 | }; |
| 133496 | #define YY_SHIFT_USE_DFLT (1571) |
| 133497 | #define YY_SHIFT_COUNT (455) |
| 133498 | #define YY_SHIFT_MIN (-94) |
| 133499 | #define YY_SHIFT_MAX (1549) |
| 133500 | static const short yy_shift_ofst[] = { |
| 133501 | /* 0 */ 40, 599, 904, 612, 760, 760, 760, 760, 725, -19, |
| @@ -133507,132 +133568,132 @@ | |
| 133507 | /* 60 */ 760, 760, 760, 760, 760, 760, 760, 760, 760, 760, |
| 133508 | /* 70 */ 760, 760, 760, 760, 760, 760, 760, 760, 760, 760, |
| 133509 | /* 80 */ 760, 760, 760, 760, 760, 760, 760, 760, 760, 760, |
| 133510 | /* 90 */ 856, 760, 760, 760, 760, 760, 760, 760, 760, 760, |
| 133511 | /* 100 */ 760, 760, 760, 760, 987, 746, 746, 746, 746, 746, |
| 133512 | /* 110 */ 801, 23, 32, 924, 963, 984, 954, 954, 924, 73, |
| 133513 | /* 120 */ 113, -51, 1571, 1571, 1571, 536, 536, 536, 99, 99, |
| 133514 | /* 130 */ 813, 813, 667, 205, 240, 924, 924, 924, 924, 924, |
| 133515 | /* 140 */ 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, |
| 133516 | /* 150 */ 924, 924, 924, 924, 924, 332, 983, 422, 422, 113, |
| 133517 | /* 160 */ 30, 30, 30, 30, 30, 30, 1571, 1571, 1571, 915, |
| 133518 | /* 170 */ -94, -94, 384, 613, 828, 420, 765, 804, 851, 924, |
| 133519 | /* 180 */ 924, 924, 924, 924, 924, 924, 924, 924, 924, 924, |
| 133520 | /* 190 */ 924, 924, 924, 924, 924, 672, 672, 672, 924, 924, |
| 133521 | /* 200 */ 657, 924, 924, 924, -18, 924, 924, 995, 924, 924, |
| 133522 | /* 210 */ 924, 924, 924, 924, 924, 924, 924, 924, 772, 1179, |
| 133523 | /* 220 */ 712, 712, 712, 926, 45, 769, 1257, 1153, 418, 418, |
| 133524 | /* 230 */ 569, 1153, 569, 1175, 607, 663, 1135, 418, 693, 1135, |
| 133525 | /* 240 */ 1135, 1177, 1139, 1208, 1286, 1233, 1233, 1290, 1290, 1233, |
| 133526 | /* 250 */ 1344, 1341, 1239, 1352, 1352, 1352, 1352, 1233, 1354, 1239, |
| 133527 | /* 260 */ 1344, 1341, 1341, 1239, 1233, 1354, 1240, 1304, 1233, 1233, |
| 133528 | /* 270 */ 1354, 1362, 1233, 1354, 1233, 1354, 1362, 1293, 1293, 1293, |
| 133529 | /* 280 */ 1321, 1362, 1293, 1301, 1293, 1321, 1293, 1293, 1291, 1302, |
| 133530 | /* 290 */ 1291, 1302, 1291, 1302, 1291, 1302, 1233, 1392, 1233, 1278, |
| 133531 | /* 300 */ 1362, 1368, 1368, 1362, 1294, 1296, 1298, 1300, 1239, 1403, |
| 133532 | /* 310 */ 1406, 1416, 1416, 1433, 1433, 1433, 1433, 1571, 1571, 1571, |
| 133533 | /* 320 */ 1571, 1571, 1571, 1571, 1571, 519, 988, 1205, 1213, 104, |
| 133534 | /* 330 */ 947, 1058, 1246, 1226, 1247, 1248, 1256, 1262, 1266, 1267, |
| 133535 | /* 340 */ 853, 1194, 1289, 1190, 1280, 1282, 1220, 1284, 1166, 1180, |
| 133536 | /* 350 */ 1288, 1225, 943, 1437, 1440, 1425, 1310, 1438, 1361, 1441, |
| 133537 | /* 360 */ 1435, 1436, 1336, 1330, 1351, 1345, 1449, 1348, 1459, 1475, |
| 133538 | /* 370 */ 1355, 1346, 1443, 1444, 1445, 1446, 1374, 1430, 1423, 1366, |
| 133539 | /* 380 */ 1488, 1485, 1469, 1385, 1353, 1414, 1470, 1415, 1410, 1426, |
| 133540 | /* 390 */ 1393, 1477, 1479, 1483, 1391, 1399, 1484, 1428, 1486, 1487, |
| 133541 | /* 400 */ 1482, 1489, 1431, 1455, 1494, 1439, 1451, 1497, 1498, 1499, |
| 133542 | /* 410 */ 1491, 1407, 1502, 1503, 1505, 1504, 1409, 1506, 1509, 1472, |
| 133543 | /* 420 */ 1461, 1511, 1411, 1508, 1473, 1510, 1474, 1516, 1508, 1517, |
| 133544 | /* 430 */ 1518, 1519, 1520, 1521, 1523, 1532, 1524, 1526, 1525, 1527, |
| 133545 | /* 440 */ 1528, 1530, 1531, 1527, 1533, 1535, 1536, 1537, 1539, 1432, |
| 133546 | /* 450 */ 1442, 1447, 1448, 1540, 1543, 1549, |
| 133547 | }; |
| 133548 | #define YY_REDUCE_USE_DFLT (-130) |
| 133549 | #define YY_REDUCE_COUNT (324) |
| 133550 | #define YY_REDUCE_MIN (-129) |
| 133551 | #define YY_REDUCE_MAX (1307) |
| 133552 | static const short yy_reduce_ofst[] = { |
| 133553 | /* 0 */ -29, 566, 525, 605, -49, 307, 491, 533, 668, 435, |
| 133554 | /* 10 */ 601, 644, 148, 747, 783, 786, 419, 788, 795, 826, |
| 133555 | /* 20 */ 454, 775, 830, 495, 824, 848, 76, 76, 76, 76, |
| 133556 | /* 30 */ 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, |
| 133557 | /* 40 */ 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, |
| 133558 | /* 50 */ 76, 76, 76, 76, 76, 76, 76, 76, 890, 901, |
| 133559 | /* 60 */ 912, 917, 920, 925, 927, 929, 936, 952, 958, 960, |
| 133560 | /* 70 */ 962, 964, 967, 969, 971, 974, 977, 986, 993, 996, |
| 133561 | /* 80 */ 999, 1002, 1004, 1008, 1010, 1012, 1015, 1021, 1026, 1034, |
| 133562 | /* 90 */ 1037, 1039, 1043, 1045, 1048, 1050, 1052, 1061, 1067, 1074, |
| 133563 | /* 100 */ 1077, 1079, 1085, 1089, 76, 76, 76, 76, 76, 76, |
| 133564 | /* 110 */ 76, 76, 76, 865, 36, 523, 235, 416, 782, 76, |
| 133565 | /* 120 */ 278, 76, 76, 76, 76, 700, 700, 700, 150, 220, |
| 133566 | /* 130 */ 147, 217, 221, 306, 306, 611, 5, 535, 556, 620, |
| 133567 | /* 140 */ 704, 720, 784, 116, 789, 349, 889, 894, 404, 953, |
| 133568 | /* 150 */ 968, -129, 975, 492, 62, 722, 919, 763, 928, 957, |
| 133569 | /* 160 */ 994, 1080, 1081, 1082, 1090, 1091, 872, 1056, 557, 57, |
| 133570 | /* 170 */ 112, 131, 167, 182, 250, 272, 291, 331, 364, 438, |
| 133571 | /* 180 */ 497, 517, 591, 653, 684, 690, 739, 791, 867, 871, |
| 133572 | /* 190 */ 970, 1062, 1107, 1132, 1152, 355, 819, 886, 1001, 1163, |
| 133573 | /* 200 */ 661, 1164, 1167, 1168, 861, 1169, 1171, 1017, 1172, 1173, |
| 133574 | /* 210 */ 1174, 250, 1176, 1178, 1181, 1182, 1183, 1184, 1084, 1094, |
| 133575 | /* 220 */ 1119, 1121, 1122, 661, 1140, 1141, 1188, 1142, 1126, 1127, |
| 133576 | /* 230 */ 1103, 1143, 1106, 1170, 1165, 1185, 1186, 1133, 1123, 1187, |
| 133577 | /* 240 */ 1189, 1148, 1154, 1196, 1111, 1197, 1198, 1118, 1120, 1204, |
| 133578 | /* 250 */ 1147, 1191, 1192, 1193, 1195, 1199, 1200, 1212, 1215, 1201, |
| 133579 | /* 260 */ 1155, 1206, 1207, 1202, 1217, 1216, 1145, 1144, 1223, 1224, |
| 133580 | /* 270 */ 1228, 1211, 1230, 1232, 1235, 1241, 1221, 1227, 1231, 1234, |
| 133581 | /* 280 */ 1222, 1229, 1236, 1237, 1238, 1242, 1243, 1244, 1203, 1210, |
| 133582 | /* 290 */ 1214, 1218, 1219, 1245, 1249, 1251, 1252, 1250, 1261, 1253, |
| 133583 | /* 300 */ 1254, 1209, 1255, 1259, 1258, 1260, 1264, 1268, 1270, 1272, |
| 133584 | /* 310 */ 1276, 1287, 1292, 1295, 1297, 1299, 1303, 1263, 1265, 1269, |
| 133585 | /* 320 */ 1277, 1279, 1271, 1273, 1307, |
| 133586 | }; |
| 133587 | static const YYACTIONTYPE yy_default[] = { |
| 133588 | /* 0 */ 1278, 1268, 1268, 1268, 1200, 1200, 1200, 1200, 1268, 1094, |
| 133589 | /* 10 */ 1123, 1123, 1252, 1329, 1329, 1329, 1329, 1329, 1329, 1199, |
| 133590 | /* 20 */ 1329, 1329, 1329, 1329, 1268, 1098, 1129, 1329, 1329, 1329, |
| 133591 | /* 30 */ 1329, 1201, 1202, 1329, 1329, 1329, 1251, 1253, 1139, 1138, |
| 133592 | /* 40 */ 1137, 1136, 1234, 1110, 1134, 1127, 1131, 1201, 1195, 1196, |
| 133593 | /* 50 */ 1194, 1198, 1202, 1329, 1130, 1164, 1179, 1163, 1329, 1329, |
| 133594 | /* 60 */ 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, |
| 133595 | /* 70 */ 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, |
| 133596 | /* 80 */ 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, |
| 133597 | /* 90 */ 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, |
| 133598 | /* 100 */ 1329, 1329, 1329, 1329, 1173, 1178, 1185, 1177, 1174, 1166, |
| 133599 | /* 110 */ 1165, 1167, 1168, 1329, 1017, 1065, 1329, 1329, 1329, 1169, |
| 133600 | /* 120 */ 1329, 1170, 1182, 1181, 1180, 1259, 1286, 1285, 1329, 1329, |
| 133601 | /* 130 */ 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, |
| 133602 | /* 140 */ 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, |
| 133603 | /* 150 */ 1329, 1329, 1329, 1329, 1329, 1278, 1268, 1023, 1023, 1329, |
| 133604 | /* 160 */ 1268, 1268, 1268, 1268, 1268, 1268, 1264, 1098, 1089, 1329, |
| 133605 | /* 170 */ 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, |
| 133606 | /* 180 */ 1256, 1254, 1329, 1215, 1329, 1329, 1329, 1329, 1329, 1329, |
| 133607 | /* 190 */ 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, |
| 133608 | /* 200 */ 1329, 1329, 1329, 1329, 1094, 1329, 1329, 1329, 1329, 1329, |
| 133609 | /* 210 */ 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1280, 1329, 1229, |
| 133610 | /* 220 */ 1094, 1094, 1094, 1096, 1078, 1088, 1002, 1133, 1112, 1112, |
| 133611 | /* 230 */ 1318, 1133, 1318, 1040, 1300, 1037, 1123, 1112, 1197, 1123, |
| 133612 | /* 240 */ 1123, 1095, 1088, 1329, 1321, 1103, 1103, 1320, 1320, 1103, |
| 133613 | /* 250 */ 1144, 1068, 1133, 1074, 1074, 1074, 1074, 1103, 1014, 1133, |
| 133614 | /* 260 */ 1144, 1068, 1068, 1133, 1103, 1014, 1233, 1315, 1103, 1103, |
| 133615 | /* 270 */ 1014, 1208, 1103, 1014, 1103, 1014, 1208, 1066, 1066, 1066, |
| 133616 | /* 280 */ 1055, 1208, 1066, 1040, 1066, 1055, 1066, 1066, 1116, 1111, |
| 133617 | /* 290 */ 1116, 1111, 1116, 1111, 1116, 1111, 1103, 1203, 1103, 1329, |
| 133618 | /* 300 */ 1208, 1212, 1212, 1208, 1128, 1117, 1126, 1124, 1133, 1020, |
| 133619 | /* 310 */ 1058, 1283, 1283, 1279, 1279, 1279, 1279, 1326, 1326, 1264, |
| 133620 | /* 320 */ 1295, 1295, 1042, 1042, 1295, 1329, 1329, 1329, 1329, 1329, |
| 133621 | /* 330 */ 1329, 1290, 1329, 1217, 1329, 1329, 1329, 1329, 1329, 1329, |
| 133622 | /* 340 */ 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, |
| 133623 | /* 350 */ 1329, 1329, 1150, 1329, 998, 1261, 1329, 1329, 1260, 1329, |
| 133624 | /* 360 */ 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, |
| 133625 | /* 370 */ 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1317, |
| 133626 | /* 380 */ 1329, 1329, 1329, 1329, 1329, 1329, 1232, 1231, 1329, 1329, |
| 133627 | /* 390 */ 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, |
| 133628 | /* 400 */ 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, |
| 133629 | /* 410 */ 1329, 1080, 1329, 1329, 1329, 1304, 1329, 1329, 1329, 1329, |
| 133630 | /* 420 */ 1329, 1329, 1329, 1125, 1329, 1118, 1329, 1329, 1308, 1329, |
| 133631 | /* 430 */ 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1329, 1270, |
| 133632 | /* 440 */ 1329, 1329, 1329, 1269, 1329, 1329, 1329, 1329, 1329, 1152, |
| 133633 | /* 450 */ 1329, 1151, 1155, 1329, 1008, 1329, |
| 133634 | }; |
| 133635 | /********** End of lemon-generated parsing tables *****************************/ |
| 133636 | |
| 133637 | /* The next table maps tokens (terminal symbols) into fallback tokens. |
| 133638 | ** If a construct like the following: |
| @@ -133862,11 +133923,11 @@ | |
| 133862 | "DEFERRABLE", "FOREIGN", "DROP", "UNION", |
| 133863 | "ALL", "EXCEPT", "INTERSECT", "SELECT", |
| 133864 | "VALUES", "DISTINCT", "DOT", "FROM", |
| 133865 | "JOIN", "USING", "ORDER", "GROUP", |
| 133866 | "HAVING", "LIMIT", "WHERE", "INTO", |
| 133867 | "INTEGER", "FLOAT", "BLOB", "VARIABLE", |
| 133868 | "CASE", "WHEN", "THEN", "ELSE", |
| 133869 | "INDEX", "ALTER", "ADD", "error", |
| 133870 | "input", "cmdlist", "ecmd", "explain", |
| 133871 | "cmdx", "cmd", "transtype", "trans_opt", |
| 133872 | "nm", "savepoint_opt", "create_table", "create_table_args", |
| @@ -134055,185 +134116,186 @@ | |
| 134055 | /* 151 */ "term ::= NULL", |
| 134056 | /* 152 */ "expr ::= ID|INDEXED", |
| 134057 | /* 153 */ "expr ::= JOIN_KW", |
| 134058 | /* 154 */ "expr ::= nm DOT nm", |
| 134059 | /* 155 */ "expr ::= nm DOT nm DOT nm", |
| 134060 | /* 156 */ "term ::= INTEGER|FLOAT|BLOB", |
| 134061 | /* 157 */ "term ::= STRING", |
| 134062 | /* 158 */ "expr ::= VARIABLE", |
| 134063 | /* 159 */ "expr ::= expr COLLATE ID|STRING", |
| 134064 | /* 160 */ "expr ::= CAST LP expr AS typetoken RP", |
| 134065 | /* 161 */ "expr ::= ID|INDEXED LP distinct exprlist RP", |
| 134066 | /* 162 */ "expr ::= ID|INDEXED LP STAR RP", |
| 134067 | /* 163 */ "term ::= CTIME_KW", |
| 134068 | /* 164 */ "expr ::= LP nexprlist COMMA expr RP", |
| 134069 | /* 165 */ "expr ::= expr AND expr", |
| 134070 | /* 166 */ "expr ::= expr OR expr", |
| 134071 | /* 167 */ "expr ::= expr LT|GT|GE|LE expr", |
| 134072 | /* 168 */ "expr ::= expr EQ|NE expr", |
| 134073 | /* 169 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr", |
| 134074 | /* 170 */ "expr ::= expr PLUS|MINUS expr", |
| 134075 | /* 171 */ "expr ::= expr STAR|SLASH|REM expr", |
| 134076 | /* 172 */ "expr ::= expr CONCAT expr", |
| 134077 | /* 173 */ "likeop ::= LIKE_KW|MATCH", |
| 134078 | /* 174 */ "likeop ::= NOT LIKE_KW|MATCH", |
| 134079 | /* 175 */ "expr ::= expr likeop expr", |
| 134080 | /* 176 */ "expr ::= expr likeop expr ESCAPE expr", |
| 134081 | /* 177 */ "expr ::= expr ISNULL|NOTNULL", |
| 134082 | /* 178 */ "expr ::= expr NOT NULL", |
| 134083 | /* 179 */ "expr ::= expr IS expr", |
| 134084 | /* 180 */ "expr ::= expr IS NOT expr", |
| 134085 | /* 181 */ "expr ::= NOT expr", |
| 134086 | /* 182 */ "expr ::= BITNOT expr", |
| 134087 | /* 183 */ "expr ::= MINUS expr", |
| 134088 | /* 184 */ "expr ::= PLUS expr", |
| 134089 | /* 185 */ "between_op ::= BETWEEN", |
| 134090 | /* 186 */ "between_op ::= NOT BETWEEN", |
| 134091 | /* 187 */ "expr ::= expr between_op expr AND expr", |
| 134092 | /* 188 */ "in_op ::= IN", |
| 134093 | /* 189 */ "in_op ::= NOT IN", |
| 134094 | /* 190 */ "expr ::= expr in_op LP exprlist RP", |
| 134095 | /* 191 */ "expr ::= LP select RP", |
| 134096 | /* 192 */ "expr ::= expr in_op LP select RP", |
| 134097 | /* 193 */ "expr ::= expr in_op nm dbnm paren_exprlist", |
| 134098 | /* 194 */ "expr ::= EXISTS LP select RP", |
| 134099 | /* 195 */ "expr ::= CASE case_operand case_exprlist case_else END", |
| 134100 | /* 196 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr", |
| 134101 | /* 197 */ "case_exprlist ::= WHEN expr THEN expr", |
| 134102 | /* 198 */ "case_else ::= ELSE expr", |
| 134103 | /* 199 */ "case_else ::=", |
| 134104 | /* 200 */ "case_operand ::= expr", |
| 134105 | /* 201 */ "case_operand ::=", |
| 134106 | /* 202 */ "exprlist ::=", |
| 134107 | /* 203 */ "nexprlist ::= nexprlist COMMA expr", |
| 134108 | /* 204 */ "nexprlist ::= expr", |
| 134109 | /* 205 */ "paren_exprlist ::=", |
| 134110 | /* 206 */ "paren_exprlist ::= LP exprlist RP", |
| 134111 | /* 207 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt", |
| 134112 | /* 208 */ "uniqueflag ::= UNIQUE", |
| 134113 | /* 209 */ "uniqueflag ::=", |
| 134114 | /* 210 */ "eidlist_opt ::=", |
| 134115 | /* 211 */ "eidlist_opt ::= LP eidlist RP", |
| 134116 | /* 212 */ "eidlist ::= eidlist COMMA nm collate sortorder", |
| 134117 | /* 213 */ "eidlist ::= nm collate sortorder", |
| 134118 | /* 214 */ "collate ::=", |
| 134119 | /* 215 */ "collate ::= COLLATE ID|STRING", |
| 134120 | /* 216 */ "cmd ::= DROP INDEX ifexists fullname", |
| 134121 | /* 217 */ "cmd ::= VACUUM", |
| 134122 | /* 218 */ "cmd ::= VACUUM nm", |
| 134123 | /* 219 */ "cmd ::= PRAGMA nm dbnm", |
| 134124 | /* 220 */ "cmd ::= PRAGMA nm dbnm EQ nmnum", |
| 134125 | /* 221 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP", |
| 134126 | /* 222 */ "cmd ::= PRAGMA nm dbnm EQ minus_num", |
| 134127 | /* 223 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP", |
| 134128 | /* 224 */ "plus_num ::= PLUS INTEGER|FLOAT", |
| 134129 | /* 225 */ "minus_num ::= MINUS INTEGER|FLOAT", |
| 134130 | /* 226 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END", |
| 134131 | /* 227 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause", |
| 134132 | /* 228 */ "trigger_time ::= BEFORE", |
| 134133 | /* 229 */ "trigger_time ::= AFTER", |
| 134134 | /* 230 */ "trigger_time ::= INSTEAD OF", |
| 134135 | /* 231 */ "trigger_time ::=", |
| 134136 | /* 232 */ "trigger_event ::= DELETE|INSERT", |
| 134137 | /* 233 */ "trigger_event ::= UPDATE", |
| 134138 | /* 234 */ "trigger_event ::= UPDATE OF idlist", |
| 134139 | /* 235 */ "when_clause ::=", |
| 134140 | /* 236 */ "when_clause ::= WHEN expr", |
| 134141 | /* 237 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI", |
| 134142 | /* 238 */ "trigger_cmd_list ::= trigger_cmd SEMI", |
| 134143 | /* 239 */ "trnm ::= nm DOT nm", |
| 134144 | /* 240 */ "tridxby ::= INDEXED BY nm", |
| 134145 | /* 241 */ "tridxby ::= NOT INDEXED", |
| 134146 | /* 242 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt", |
| 134147 | /* 243 */ "trigger_cmd ::= insert_cmd INTO trnm idlist_opt select", |
| 134148 | /* 244 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt", |
| 134149 | /* 245 */ "trigger_cmd ::= select", |
| 134150 | /* 246 */ "expr ::= RAISE LP IGNORE RP", |
| 134151 | /* 247 */ "expr ::= RAISE LP raisetype COMMA nm RP", |
| 134152 | /* 248 */ "raisetype ::= ROLLBACK", |
| 134153 | /* 249 */ "raisetype ::= ABORT", |
| 134154 | /* 250 */ "raisetype ::= FAIL", |
| 134155 | /* 251 */ "cmd ::= DROP TRIGGER ifexists fullname", |
| 134156 | /* 252 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", |
| 134157 | /* 253 */ "cmd ::= DETACH database_kw_opt expr", |
| 134158 | /* 254 */ "key_opt ::=", |
| 134159 | /* 255 */ "key_opt ::= KEY expr", |
| 134160 | /* 256 */ "cmd ::= REINDEX", |
| 134161 | /* 257 */ "cmd ::= REINDEX nm dbnm", |
| 134162 | /* 258 */ "cmd ::= ANALYZE", |
| 134163 | /* 259 */ "cmd ::= ANALYZE nm dbnm", |
| 134164 | /* 260 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", |
| 134165 | /* 261 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist", |
| 134166 | /* 262 */ "add_column_fullname ::= fullname", |
| 134167 | /* 263 */ "cmd ::= create_vtab", |
| 134168 | /* 264 */ "cmd ::= create_vtab LP vtabarglist RP", |
| 134169 | /* 265 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm", |
| 134170 | /* 266 */ "vtabarg ::=", |
| 134171 | /* 267 */ "vtabargtoken ::= ANY", |
| 134172 | /* 268 */ "vtabargtoken ::= lp anylist RP", |
| 134173 | /* 269 */ "lp ::= LP", |
| 134174 | /* 270 */ "with ::=", |
| 134175 | /* 271 */ "with ::= WITH wqlist", |
| 134176 | /* 272 */ "with ::= WITH RECURSIVE wqlist", |
| 134177 | /* 273 */ "wqlist ::= nm eidlist_opt AS LP select RP", |
| 134178 | /* 274 */ "wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP", |
| 134179 | /* 275 */ "input ::= cmdlist", |
| 134180 | /* 276 */ "cmdlist ::= cmdlist ecmd", |
| 134181 | /* 277 */ "cmdlist ::= ecmd", |
| 134182 | /* 278 */ "ecmd ::= SEMI", |
| 134183 | /* 279 */ "ecmd ::= explain cmdx SEMI", |
| 134184 | /* 280 */ "explain ::=", |
| 134185 | /* 281 */ "trans_opt ::=", |
| 134186 | /* 282 */ "trans_opt ::= TRANSACTION", |
| 134187 | /* 283 */ "trans_opt ::= TRANSACTION nm", |
| 134188 | /* 284 */ "savepoint_opt ::= SAVEPOINT", |
| 134189 | /* 285 */ "savepoint_opt ::=", |
| 134190 | /* 286 */ "cmd ::= create_table create_table_args", |
| 134191 | /* 287 */ "columnlist ::= columnlist COMMA columnname carglist", |
| 134192 | /* 288 */ "columnlist ::= columnname carglist", |
| 134193 | /* 289 */ "nm ::= ID|INDEXED", |
| 134194 | /* 290 */ "nm ::= STRING", |
| 134195 | /* 291 */ "nm ::= JOIN_KW", |
| 134196 | /* 292 */ "typetoken ::= typename", |
| 134197 | /* 293 */ "typename ::= ID|STRING", |
| 134198 | /* 294 */ "signed ::= plus_num", |
| 134199 | /* 295 */ "signed ::= minus_num", |
| 134200 | /* 296 */ "carglist ::= carglist ccons", |
| 134201 | /* 297 */ "carglist ::=", |
| 134202 | /* 298 */ "ccons ::= NULL onconf", |
| 134203 | /* 299 */ "conslist_opt ::= COMMA conslist", |
| 134204 | /* 300 */ "conslist ::= conslist tconscomma tcons", |
| 134205 | /* 301 */ "conslist ::= tcons", |
| 134206 | /* 302 */ "tconscomma ::=", |
| 134207 | /* 303 */ "defer_subclause_opt ::= defer_subclause", |
| 134208 | /* 304 */ "resolvetype ::= raisetype", |
| 134209 | /* 305 */ "selectnowith ::= oneselect", |
| 134210 | /* 306 */ "oneselect ::= values", |
| 134211 | /* 307 */ "sclp ::= selcollist COMMA", |
| 134212 | /* 308 */ "as ::= ID|STRING", |
| 134213 | /* 309 */ "expr ::= term", |
| 134214 | /* 310 */ "exprlist ::= nexprlist", |
| 134215 | /* 311 */ "nmnum ::= plus_num", |
| 134216 | /* 312 */ "nmnum ::= nm", |
| 134217 | /* 313 */ "nmnum ::= ON", |
| 134218 | /* 314 */ "nmnum ::= DELETE", |
| 134219 | /* 315 */ "nmnum ::= DEFAULT", |
| 134220 | /* 316 */ "plus_num ::= INTEGER|FLOAT", |
| 134221 | /* 317 */ "foreach_clause ::=", |
| 134222 | /* 318 */ "foreach_clause ::= FOR EACH ROW", |
| 134223 | /* 319 */ "trnm ::= nm", |
| 134224 | /* 320 */ "tridxby ::=", |
| 134225 | /* 321 */ "database_kw_opt ::= DATABASE", |
| 134226 | /* 322 */ "database_kw_opt ::=", |
| 134227 | /* 323 */ "kwcolumn_opt ::=", |
| 134228 | /* 324 */ "kwcolumn_opt ::= COLUMNKW", |
| 134229 | /* 325 */ "vtabarglist ::= vtabarg", |
| 134230 | /* 326 */ "vtabarglist ::= vtabarglist COMMA vtabarg", |
| 134231 | /* 327 */ "vtabarg ::= vtabarg vtabargtoken", |
| 134232 | /* 328 */ "anylist ::=", |
| 134233 | /* 329 */ "anylist ::= anylist LP anylist RP", |
| 134234 | /* 330 */ "anylist ::= anylist ANY", |
| 134235 | }; |
| 134236 | #endif /* NDEBUG */ |
| 134237 | |
| 134238 | |
| 134239 | #if YYSTACKDEPTH<=0 |
| @@ -134811,10 +134873,11 @@ | |
| 134811 | { 173, 1 }, |
| 134812 | { 173, 3 }, |
| 134813 | { 173, 5 }, |
| 134814 | { 172, 1 }, |
| 134815 | { 172, 1 }, |
| 134816 | { 173, 1 }, |
| 134817 | { 173, 3 }, |
| 134818 | { 173, 6 }, |
| 134819 | { 173, 5 }, |
| 134820 | { 173, 4 }, |
| @@ -135105,11 +135168,11 @@ | |
| 135105 | case 42: /* autoinc ::= */ yytestcase(yyruleno==42); |
| 135106 | case 57: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==57); |
| 135107 | case 67: /* defer_subclause_opt ::= */ yytestcase(yyruleno==67); |
| 135108 | case 76: /* ifexists ::= */ yytestcase(yyruleno==76); |
| 135109 | case 90: /* distinct ::= */ yytestcase(yyruleno==90); |
| 135110 | case 214: /* collate ::= */ yytestcase(yyruleno==214); |
| 135111 | {yymsp[1].minor.yy194 = 0;} |
| 135112 | break; |
| 135113 | case 17: /* ifnotexists ::= IF NOT EXISTS */ |
| 135114 | {yymsp[-2].minor.yy194 = 1;} |
| 135115 | break; |
| @@ -135249,13 +135312,13 @@ | |
| 135249 | case 144: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==144); |
| 135250 | {yymsp[-1].minor.yy194 = yymsp[0].minor.yy194;} |
| 135251 | break; |
| 135252 | case 58: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ |
| 135253 | case 75: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==75); |
| 135254 | case 186: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==186); |
| 135255 | case 189: /* in_op ::= NOT IN */ yytestcase(yyruleno==189); |
| 135256 | case 215: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==215); |
| 135257 | {yymsp[-1].minor.yy194 = 1;} |
| 135258 | break; |
| 135259 | case 59: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ |
| 135260 | {yymsp[-1].minor.yy194 = 0;} |
| 135261 | break; |
| @@ -135415,13 +135478,13 @@ | |
| 135415 | {yymsp[0].minor.yy194 = SF_All;} |
| 135416 | break; |
| 135417 | case 91: /* sclp ::= */ |
| 135418 | case 119: /* orderby_opt ::= */ yytestcase(yyruleno==119); |
| 135419 | case 126: /* groupby_opt ::= */ yytestcase(yyruleno==126); |
| 135420 | case 202: /* exprlist ::= */ yytestcase(yyruleno==202); |
| 135421 | case 205: /* paren_exprlist ::= */ yytestcase(yyruleno==205); |
| 135422 | case 210: /* eidlist_opt ::= */ yytestcase(yyruleno==210); |
| 135423 | {yymsp[1].minor.yy148 = 0;} |
| 135424 | break; |
| 135425 | case 92: /* selcollist ::= sclp expr as */ |
| 135426 | { |
| 135427 | yymsp[-2].minor.yy148 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy148, yymsp[-1].minor.yy190.pExpr); |
| @@ -135435,20 +135498,20 @@ | |
| 135435 | yymsp[-1].minor.yy148 = sqlite3ExprListAppend(pParse, yymsp[-1].minor.yy148, p); |
| 135436 | } |
| 135437 | break; |
| 135438 | case 94: /* selcollist ::= sclp nm DOT STAR */ |
| 135439 | { |
| 135440 | Expr *pRight = sqlite3PExpr(pParse, TK_ASTERISK, 0, 0, &yymsp[0].minor.yy0); |
| 135441 | Expr *pLeft = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0); |
| 135442 | Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0); |
| 135443 | yymsp[-3].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy148, pDot); |
| 135444 | } |
| 135445 | break; |
| 135446 | case 95: /* as ::= AS nm */ |
| 135447 | case 106: /* dbnm ::= DOT nm */ yytestcase(yyruleno==106); |
| 135448 | case 224: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==224); |
| 135449 | case 225: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==225); |
| 135450 | {yymsp[-1].minor.yy0 = yymsp[0].minor.yy0;} |
| 135451 | break; |
| 135452 | case 97: /* from ::= */ |
| 135453 | {yymsp[1].minor.yy185 = sqlite3DbMallocZero(pParse->db, sizeof(*yymsp[1].minor.yy185));} |
| 135454 | break; |
| @@ -135527,18 +135590,18 @@ | |
| 135527 | {yymsp[-3].minor.yy194 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/} |
| 135528 | break; |
| 135529 | case 112: /* on_opt ::= ON expr */ |
| 135530 | case 129: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==129); |
| 135531 | case 136: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==136); |
| 135532 | case 198: /* case_else ::= ELSE expr */ yytestcase(yyruleno==198); |
| 135533 | {yymsp[-1].minor.yy72 = yymsp[0].minor.yy190.pExpr;} |
| 135534 | break; |
| 135535 | case 113: /* on_opt ::= */ |
| 135536 | case 128: /* having_opt ::= */ yytestcase(yyruleno==128); |
| 135537 | case 135: /* where_opt ::= */ yytestcase(yyruleno==135); |
| 135538 | case 199: /* case_else ::= */ yytestcase(yyruleno==199); |
| 135539 | case 201: /* case_operand ::= */ yytestcase(yyruleno==201); |
| 135540 | {yymsp[1].minor.yy72 = 0;} |
| 135541 | break; |
| 135542 | case 115: /* indexed_opt ::= INDEXED BY nm */ |
| 135543 | {yymsp[-2].minor.yy0 = yymsp[0].minor.yy0;} |
| 135544 | break; |
| @@ -135650,41 +135713,51 @@ | |
| 135650 | break; |
| 135651 | case 150: /* expr ::= LP expr RP */ |
| 135652 | {spanSet(&yymsp[-2].minor.yy190,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-B*/ yymsp[-2].minor.yy190.pExpr = yymsp[-1].minor.yy190.pExpr;} |
| 135653 | break; |
| 135654 | case 151: /* term ::= NULL */ |
| 135655 | case 156: /* term ::= INTEGER|FLOAT|BLOB */ yytestcase(yyruleno==156); |
| 135656 | case 157: /* term ::= STRING */ yytestcase(yyruleno==157); |
| 135657 | {spanExpr(&yymsp[0].minor.yy190,pParse,yymsp[0].major,yymsp[0].minor.yy0);/*A-overwrites-X*/} |
| 135658 | break; |
| 135659 | case 152: /* expr ::= ID|INDEXED */ |
| 135660 | case 153: /* expr ::= JOIN_KW */ yytestcase(yyruleno==153); |
| 135661 | {spanExpr(&yymsp[0].minor.yy190,pParse,TK_ID,yymsp[0].minor.yy0); /*A-overwrites-X*/} |
| 135662 | break; |
| 135663 | case 154: /* expr ::= nm DOT nm */ |
| 135664 | { |
| 135665 | Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0); |
| 135666 | Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0); |
| 135667 | spanSet(&yymsp[-2].minor.yy190,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ |
| 135668 | yymsp[-2].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0); |
| 135669 | } |
| 135670 | break; |
| 135671 | case 155: /* expr ::= nm DOT nm DOT nm */ |
| 135672 | { |
| 135673 | Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-4].minor.yy0); |
| 135674 | Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0); |
| 135675 | Expr *temp3 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0); |
| 135676 | Expr *temp4 = sqlite3PExpr(pParse, TK_DOT, temp2, temp3, 0); |
| 135677 | spanSet(&yymsp[-4].minor.yy190,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ |
| 135678 | yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp4, 0); |
| 135679 | } |
| 135680 | break; |
| 135681 | case 158: /* expr ::= VARIABLE */ |
| 135682 | { |
| 135683 | if( !(yymsp[0].minor.yy0.z[0]=='#' && sqlite3Isdigit(yymsp[0].minor.yy0.z[1])) ){ |
| 135684 | spanExpr(&yymsp[0].minor.yy190, pParse, TK_VARIABLE, yymsp[0].minor.yy0); |
| 135685 | sqlite3ExprAssignVarNumber(pParse, yymsp[0].minor.yy190.pExpr); |
| 135686 | }else{ |
| 135687 | /* When doing a nested parse, one can include terms in an expression |
| 135688 | ** that look like this: #1 #2 ... These terms refer to registers |
| 135689 | ** in the virtual machine. #N is the N-th register. */ |
| 135690 | Token t = yymsp[0].minor.yy0; /*A-overwrites-X*/ |
| @@ -135692,29 +135765,29 @@ | |
| 135692 | spanSet(&yymsp[0].minor.yy190, &t, &t); |
| 135693 | if( pParse->nested==0 ){ |
| 135694 | sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &t); |
| 135695 | yymsp[0].minor.yy190.pExpr = 0; |
| 135696 | }else{ |
| 135697 | yymsp[0].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_REGISTER, 0, 0, &t); |
| 135698 | if( yymsp[0].minor.yy190.pExpr ) sqlite3GetInt32(&t.z[1], &yymsp[0].minor.yy190.pExpr->iTable); |
| 135699 | } |
| 135700 | } |
| 135701 | } |
| 135702 | break; |
| 135703 | case 159: /* expr ::= expr COLLATE ID|STRING */ |
| 135704 | { |
| 135705 | yymsp[-2].minor.yy190.pExpr = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy190.pExpr, &yymsp[0].minor.yy0, 1); |
| 135706 | yymsp[-2].minor.yy190.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; |
| 135707 | } |
| 135708 | break; |
| 135709 | case 160: /* expr ::= CAST LP expr AS typetoken RP */ |
| 135710 | { |
| 135711 | spanSet(&yymsp[-5].minor.yy190,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ |
| 135712 | yymsp[-5].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_CAST, yymsp[-3].minor.yy190.pExpr, 0, &yymsp[-1].minor.yy0); |
| 135713 | } |
| 135714 | break; |
| 135715 | case 161: /* expr ::= ID|INDEXED LP distinct exprlist RP */ |
| 135716 | { |
| 135717 | if( yymsp[-1].minor.yy148 && yymsp[-1].minor.yy148->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){ |
| 135718 | sqlite3ErrorMsg(pParse, "too many arguments on function %T", &yymsp[-4].minor.yy0); |
| 135719 | } |
| 135720 | yylhsminor.yy190.pExpr = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy148, &yymsp[-4].minor.yy0); |
| @@ -135723,25 +135796,25 @@ | |
| 135723 | yylhsminor.yy190.pExpr->flags |= EP_Distinct; |
| 135724 | } |
| 135725 | } |
| 135726 | yymsp[-4].minor.yy190 = yylhsminor.yy190; |
| 135727 | break; |
| 135728 | case 162: /* expr ::= ID|INDEXED LP STAR RP */ |
| 135729 | { |
| 135730 | yylhsminor.yy190.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0); |
| 135731 | spanSet(&yylhsminor.yy190,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); |
| 135732 | } |
| 135733 | yymsp[-3].minor.yy190 = yylhsminor.yy190; |
| 135734 | break; |
| 135735 | case 163: /* term ::= CTIME_KW */ |
| 135736 | { |
| 135737 | yylhsminor.yy190.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0); |
| 135738 | spanSet(&yylhsminor.yy190, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0); |
| 135739 | } |
| 135740 | yymsp[0].minor.yy190 = yylhsminor.yy190; |
| 135741 | break; |
| 135742 | case 164: /* expr ::= LP nexprlist COMMA expr RP */ |
| 135743 | { |
| 135744 | ExprList *pList = sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy148, yymsp[-1].minor.yy190.pExpr); |
| 135745 | yylhsminor.yy190.pExpr = sqlite3PExpr(pParse, TK_VECTOR, 0, 0, 0); |
| 135746 | if( yylhsminor.yy190.pExpr ){ |
| 135747 | yylhsminor.yy190.pExpr->x.pList = pList; |
| @@ -135750,82 +135823,86 @@ | |
| 135750 | sqlite3ExprListDelete(pParse->db, pList); |
| 135751 | } |
| 135752 | } |
| 135753 | yymsp[-4].minor.yy190 = yylhsminor.yy190; |
| 135754 | break; |
| 135755 | case 165: /* expr ::= expr AND expr */ |
| 135756 | case 166: /* expr ::= expr OR expr */ yytestcase(yyruleno==166); |
| 135757 | case 167: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==167); |
| 135758 | case 168: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==168); |
| 135759 | case 169: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==169); |
| 135760 | case 170: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==170); |
| 135761 | case 171: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==171); |
| 135762 | case 172: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==172); |
| 135763 | {spanBinaryExpr(pParse,yymsp[-1].major,&yymsp[-2].minor.yy190,&yymsp[0].minor.yy190);} |
| 135764 | break; |
| 135765 | case 173: /* likeop ::= LIKE_KW|MATCH */ |
| 135766 | {yymsp[0].minor.yy392.eOperator = yymsp[0].minor.yy0; yymsp[0].minor.yy392.bNot = 0;/*A-overwrites-X*/} |
| 135767 | break; |
| 135768 | case 174: /* likeop ::= NOT LIKE_KW|MATCH */ |
| 135769 | {yymsp[-1].minor.yy392.eOperator = yymsp[0].minor.yy0; yymsp[-1].minor.yy392.bNot = 1;} |
| 135770 | break; |
| 135771 | case 175: /* expr ::= expr likeop expr */ |
| 135772 | { |
| 135773 | ExprList *pList; |
| 135774 | pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy190.pExpr); |
| 135775 | pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy190.pExpr); |
| 135776 | yymsp[-2].minor.yy190.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy392.eOperator); |
| 135777 | exprNot(pParse, yymsp[-1].minor.yy392.bNot, &yymsp[-2].minor.yy190); |
| 135778 | yymsp[-2].minor.yy190.zEnd = yymsp[0].minor.yy190.zEnd; |
| 135779 | if( yymsp[-2].minor.yy190.pExpr ) yymsp[-2].minor.yy190.pExpr->flags |= EP_InfixFunc; |
| 135780 | } |
| 135781 | break; |
| 135782 | case 176: /* expr ::= expr likeop expr ESCAPE expr */ |
| 135783 | { |
| 135784 | ExprList *pList; |
| 135785 | pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy190.pExpr); |
| 135786 | pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy190.pExpr); |
| 135787 | pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy190.pExpr); |
| 135788 | yymsp[-4].minor.yy190.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy392.eOperator); |
| 135789 | exprNot(pParse, yymsp[-3].minor.yy392.bNot, &yymsp[-4].minor.yy190); |
| 135790 | yymsp[-4].minor.yy190.zEnd = yymsp[0].minor.yy190.zEnd; |
| 135791 | if( yymsp[-4].minor.yy190.pExpr ) yymsp[-4].minor.yy190.pExpr->flags |= EP_InfixFunc; |
| 135792 | } |
| 135793 | break; |
| 135794 | case 177: /* expr ::= expr ISNULL|NOTNULL */ |
| 135795 | {spanUnaryPostfix(pParse,yymsp[0].major,&yymsp[-1].minor.yy190,&yymsp[0].minor.yy0);} |
| 135796 | break; |
| 135797 | case 178: /* expr ::= expr NOT NULL */ |
| 135798 | {spanUnaryPostfix(pParse,TK_NOTNULL,&yymsp[-2].minor.yy190,&yymsp[0].minor.yy0);} |
| 135799 | break; |
| 135800 | case 179: /* expr ::= expr IS expr */ |
| 135801 | { |
| 135802 | spanBinaryExpr(pParse,TK_IS,&yymsp[-2].minor.yy190,&yymsp[0].minor.yy190); |
| 135803 | binaryToUnaryIfNull(pParse, yymsp[0].minor.yy190.pExpr, yymsp[-2].minor.yy190.pExpr, TK_ISNULL); |
| 135804 | } |
| 135805 | break; |
| 135806 | case 180: /* expr ::= expr IS NOT expr */ |
| 135807 | { |
| 135808 | spanBinaryExpr(pParse,TK_ISNOT,&yymsp[-3].minor.yy190,&yymsp[0].minor.yy190); |
| 135809 | binaryToUnaryIfNull(pParse, yymsp[0].minor.yy190.pExpr, yymsp[-3].minor.yy190.pExpr, TK_NOTNULL); |
| 135810 | } |
| 135811 | break; |
| 135812 | case 181: /* expr ::= NOT expr */ |
| 135813 | case 182: /* expr ::= BITNOT expr */ yytestcase(yyruleno==182); |
| 135814 | {spanUnaryPrefix(&yymsp[-1].minor.yy190,pParse,yymsp[-1].major,&yymsp[0].minor.yy190,&yymsp[-1].minor.yy0);/*A-overwrites-B*/} |
| 135815 | break; |
| 135816 | case 183: /* expr ::= MINUS expr */ |
| 135817 | {spanUnaryPrefix(&yymsp[-1].minor.yy190,pParse,TK_UMINUS,&yymsp[0].minor.yy190,&yymsp[-1].minor.yy0);/*A-overwrites-B*/} |
| 135818 | break; |
| 135819 | case 184: /* expr ::= PLUS expr */ |
| 135820 | {spanUnaryPrefix(&yymsp[-1].minor.yy190,pParse,TK_UPLUS,&yymsp[0].minor.yy190,&yymsp[-1].minor.yy0);/*A-overwrites-B*/} |
| 135821 | break; |
| 135822 | case 185: /* between_op ::= BETWEEN */ |
| 135823 | case 188: /* in_op ::= IN */ yytestcase(yyruleno==188); |
| 135824 | {yymsp[0].minor.yy194 = 0;} |
| 135825 | break; |
| 135826 | case 187: /* expr ::= expr between_op expr AND expr */ |
| 135827 | { |
| 135828 | ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy190.pExpr); |
| 135829 | pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy190.pExpr); |
| 135830 | yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy190.pExpr, 0, 0); |
| 135831 | if( yymsp[-4].minor.yy190.pExpr ){ |
| @@ -135835,11 +135912,11 @@ | |
| 135835 | } |
| 135836 | exprNot(pParse, yymsp[-3].minor.yy194, &yymsp[-4].minor.yy190); |
| 135837 | yymsp[-4].minor.yy190.zEnd = yymsp[0].minor.yy190.zEnd; |
| 135838 | } |
| 135839 | break; |
| 135840 | case 190: /* expr ::= expr in_op LP exprlist RP */ |
| 135841 | { |
| 135842 | if( yymsp[-1].minor.yy148==0 ){ |
| 135843 | /* Expressions of the form |
| 135844 | ** |
| 135845 | ** expr1 IN () |
| @@ -135888,26 +135965,26 @@ | |
| 135888 | exprNot(pParse, yymsp[-3].minor.yy194, &yymsp[-4].minor.yy190); |
| 135889 | } |
| 135890 | yymsp[-4].minor.yy190.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; |
| 135891 | } |
| 135892 | break; |
| 135893 | case 191: /* expr ::= LP select RP */ |
| 135894 | { |
| 135895 | spanSet(&yymsp[-2].minor.yy190,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-B*/ |
| 135896 | yymsp[-2].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0); |
| 135897 | sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy190.pExpr, yymsp[-1].minor.yy243); |
| 135898 | } |
| 135899 | break; |
| 135900 | case 192: /* expr ::= expr in_op LP select RP */ |
| 135901 | { |
| 135902 | yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy190.pExpr, 0, 0); |
| 135903 | sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy190.pExpr, yymsp[-1].minor.yy243); |
| 135904 | exprNot(pParse, yymsp[-3].minor.yy194, &yymsp[-4].minor.yy190); |
| 135905 | yymsp[-4].minor.yy190.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; |
| 135906 | } |
| 135907 | break; |
| 135908 | case 193: /* expr ::= expr in_op nm dbnm paren_exprlist */ |
| 135909 | { |
| 135910 | SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0); |
| 135911 | Select *pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0); |
| 135912 | if( yymsp[0].minor.yy148 ) sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, yymsp[0].minor.yy148); |
| 135913 | yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy190.pExpr, 0, 0); |
| @@ -135914,19 +135991,19 @@ | |
| 135914 | sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy190.pExpr, pSelect); |
| 135915 | exprNot(pParse, yymsp[-3].minor.yy194, &yymsp[-4].minor.yy190); |
| 135916 | yymsp[-4].minor.yy190.zEnd = yymsp[-1].minor.yy0.z ? &yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n] : &yymsp[-2].minor.yy0.z[yymsp[-2].minor.yy0.n]; |
| 135917 | } |
| 135918 | break; |
| 135919 | case 194: /* expr ::= EXISTS LP select RP */ |
| 135920 | { |
| 135921 | Expr *p; |
| 135922 | spanSet(&yymsp[-3].minor.yy190,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-B*/ |
| 135923 | p = yymsp[-3].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0); |
| 135924 | sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy243); |
| 135925 | } |
| 135926 | break; |
| 135927 | case 195: /* expr ::= CASE case_operand case_exprlist case_else END */ |
| 135928 | { |
| 135929 | spanSet(&yymsp[-4].minor.yy190,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-C*/ |
| 135930 | yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy72, 0, 0); |
| 135931 | if( yymsp[-4].minor.yy190.pExpr ){ |
| 135932 | yymsp[-4].minor.yy190.pExpr->x.pList = yymsp[-1].minor.yy72 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy148,yymsp[-1].minor.yy72) : yymsp[-2].minor.yy148; |
| @@ -135935,334 +136012,334 @@ | |
| 135935 | sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy148); |
| 135936 | sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy72); |
| 135937 | } |
| 135938 | } |
| 135939 | break; |
| 135940 | case 196: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */ |
| 135941 | { |
| 135942 | yymsp[-4].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy148, yymsp[-2].minor.yy190.pExpr); |
| 135943 | yymsp[-4].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy148, yymsp[0].minor.yy190.pExpr); |
| 135944 | } |
| 135945 | break; |
| 135946 | case 197: /* case_exprlist ::= WHEN expr THEN expr */ |
| 135947 | { |
| 135948 | yymsp[-3].minor.yy148 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy190.pExpr); |
| 135949 | yymsp[-3].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy148, yymsp[0].minor.yy190.pExpr); |
| 135950 | } |
| 135951 | break; |
| 135952 | case 200: /* case_operand ::= expr */ |
| 135953 | {yymsp[0].minor.yy72 = yymsp[0].minor.yy190.pExpr; /*A-overwrites-X*/} |
| 135954 | break; |
| 135955 | case 203: /* nexprlist ::= nexprlist COMMA expr */ |
| 135956 | {yymsp[-2].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy148,yymsp[0].minor.yy190.pExpr);} |
| 135957 | break; |
| 135958 | case 204: /* nexprlist ::= expr */ |
| 135959 | {yymsp[0].minor.yy148 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy190.pExpr); /*A-overwrites-Y*/} |
| 135960 | break; |
| 135961 | case 206: /* paren_exprlist ::= LP exprlist RP */ |
| 135962 | case 211: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==211); |
| 135963 | {yymsp[-2].minor.yy148 = yymsp[-1].minor.yy148;} |
| 135964 | break; |
| 135965 | case 207: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ |
| 135966 | { |
| 135967 | sqlite3CreateIndex(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, |
| 135968 | sqlite3SrcListAppend(pParse->db,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy148, yymsp[-10].minor.yy194, |
| 135969 | &yymsp[-11].minor.yy0, yymsp[0].minor.yy72, SQLITE_SO_ASC, yymsp[-8].minor.yy194, SQLITE_IDXTYPE_APPDEF); |
| 135970 | } |
| 135971 | break; |
| 135972 | case 208: /* uniqueflag ::= UNIQUE */ |
| 135973 | case 249: /* raisetype ::= ABORT */ yytestcase(yyruleno==249); |
| 135974 | {yymsp[0].minor.yy194 = OE_Abort;} |
| 135975 | break; |
| 135976 | case 209: /* uniqueflag ::= */ |
| 135977 | {yymsp[1].minor.yy194 = OE_None;} |
| 135978 | break; |
| 135979 | case 212: /* eidlist ::= eidlist COMMA nm collate sortorder */ |
| 135980 | { |
| 135981 | yymsp[-4].minor.yy148 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy148, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy194, yymsp[0].minor.yy194); |
| 135982 | } |
| 135983 | break; |
| 135984 | case 213: /* eidlist ::= nm collate sortorder */ |
| 135985 | { |
| 135986 | yymsp[-2].minor.yy148 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy194, yymsp[0].minor.yy194); /*A-overwrites-Y*/ |
| 135987 | } |
| 135988 | break; |
| 135989 | case 216: /* cmd ::= DROP INDEX ifexists fullname */ |
| 135990 | {sqlite3DropIndex(pParse, yymsp[0].minor.yy185, yymsp[-1].minor.yy194);} |
| 135991 | break; |
| 135992 | case 217: /* cmd ::= VACUUM */ |
| 135993 | {sqlite3Vacuum(pParse,0);} |
| 135994 | break; |
| 135995 | case 218: /* cmd ::= VACUUM nm */ |
| 135996 | {sqlite3Vacuum(pParse,&yymsp[0].minor.yy0);} |
| 135997 | break; |
| 135998 | case 219: /* cmd ::= PRAGMA nm dbnm */ |
| 135999 | {sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);} |
| 136000 | break; |
| 136001 | case 220: /* cmd ::= PRAGMA nm dbnm EQ nmnum */ |
| 136002 | {sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,0);} |
| 136003 | break; |
| 136004 | case 221: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */ |
| 136005 | {sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,0);} |
| 136006 | break; |
| 136007 | case 222: /* cmd ::= PRAGMA nm dbnm EQ minus_num */ |
| 136008 | {sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,1);} |
| 136009 | break; |
| 136010 | case 223: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */ |
| 136011 | {sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,1);} |
| 136012 | break; |
| 136013 | case 226: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ |
| 136014 | { |
| 136015 | Token all; |
| 136016 | all.z = yymsp[-3].minor.yy0.z; |
| 136017 | all.n = (int)(yymsp[0].minor.yy0.z - yymsp[-3].minor.yy0.z) + yymsp[0].minor.yy0.n; |
| 136018 | sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy145, &all); |
| 136019 | } |
| 136020 | break; |
| 136021 | case 227: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ |
| 136022 | { |
| 136023 | sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy194, yymsp[-4].minor.yy332.a, yymsp[-4].minor.yy332.b, yymsp[-2].minor.yy185, yymsp[0].minor.yy72, yymsp[-10].minor.yy194, yymsp[-8].minor.yy194); |
| 136024 | yymsp[-10].minor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0); /*A-overwrites-T*/ |
| 136025 | } |
| 136026 | break; |
| 136027 | case 228: /* trigger_time ::= BEFORE */ |
| 136028 | { yymsp[0].minor.yy194 = TK_BEFORE; } |
| 136029 | break; |
| 136030 | case 229: /* trigger_time ::= AFTER */ |
| 136031 | { yymsp[0].minor.yy194 = TK_AFTER; } |
| 136032 | break; |
| 136033 | case 230: /* trigger_time ::= INSTEAD OF */ |
| 136034 | { yymsp[-1].minor.yy194 = TK_INSTEAD;} |
| 136035 | break; |
| 136036 | case 231: /* trigger_time ::= */ |
| 136037 | { yymsp[1].minor.yy194 = TK_BEFORE; } |
| 136038 | break; |
| 136039 | case 232: /* trigger_event ::= DELETE|INSERT */ |
| 136040 | case 233: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==233); |
| 136041 | {yymsp[0].minor.yy332.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy332.b = 0;} |
| 136042 | break; |
| 136043 | case 234: /* trigger_event ::= UPDATE OF idlist */ |
| 136044 | {yymsp[-2].minor.yy332.a = TK_UPDATE; yymsp[-2].minor.yy332.b = yymsp[0].minor.yy254;} |
| 136045 | break; |
| 136046 | case 235: /* when_clause ::= */ |
| 136047 | case 254: /* key_opt ::= */ yytestcase(yyruleno==254); |
| 136048 | { yymsp[1].minor.yy72 = 0; } |
| 136049 | break; |
| 136050 | case 236: /* when_clause ::= WHEN expr */ |
| 136051 | case 255: /* key_opt ::= KEY expr */ yytestcase(yyruleno==255); |
| 136052 | { yymsp[-1].minor.yy72 = yymsp[0].minor.yy190.pExpr; } |
| 136053 | break; |
| 136054 | case 237: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ |
| 136055 | { |
| 136056 | assert( yymsp[-2].minor.yy145!=0 ); |
| 136057 | yymsp[-2].minor.yy145->pLast->pNext = yymsp[-1].minor.yy145; |
| 136058 | yymsp[-2].minor.yy145->pLast = yymsp[-1].minor.yy145; |
| 136059 | } |
| 136060 | break; |
| 136061 | case 238: /* trigger_cmd_list ::= trigger_cmd SEMI */ |
| 136062 | { |
| 136063 | assert( yymsp[-1].minor.yy145!=0 ); |
| 136064 | yymsp[-1].minor.yy145->pLast = yymsp[-1].minor.yy145; |
| 136065 | } |
| 136066 | break; |
| 136067 | case 239: /* trnm ::= nm DOT nm */ |
| 136068 | { |
| 136069 | yymsp[-2].minor.yy0 = yymsp[0].minor.yy0; |
| 136070 | sqlite3ErrorMsg(pParse, |
| 136071 | "qualified table names are not allowed on INSERT, UPDATE, and DELETE " |
| 136072 | "statements within triggers"); |
| 136073 | } |
| 136074 | break; |
| 136075 | case 240: /* tridxby ::= INDEXED BY nm */ |
| 136076 | { |
| 136077 | sqlite3ErrorMsg(pParse, |
| 136078 | "the INDEXED BY clause is not allowed on UPDATE or DELETE statements " |
| 136079 | "within triggers"); |
| 136080 | } |
| 136081 | break; |
| 136082 | case 241: /* tridxby ::= NOT INDEXED */ |
| 136083 | { |
| 136084 | sqlite3ErrorMsg(pParse, |
| 136085 | "the NOT INDEXED clause is not allowed on UPDATE or DELETE statements " |
| 136086 | "within triggers"); |
| 136087 | } |
| 136088 | break; |
| 136089 | case 242: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt */ |
| 136090 | {yymsp[-6].minor.yy145 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-4].minor.yy0, yymsp[-1].minor.yy148, yymsp[0].minor.yy72, yymsp[-5].minor.yy194);} |
| 136091 | break; |
| 136092 | case 243: /* trigger_cmd ::= insert_cmd INTO trnm idlist_opt select */ |
| 136093 | {yymsp[-4].minor.yy145 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy254, yymsp[0].minor.yy243, yymsp[-4].minor.yy194);/*A-overwrites-R*/} |
| 136094 | break; |
| 136095 | case 244: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt */ |
| 136096 | {yymsp[-4].minor.yy145 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[0].minor.yy72);} |
| 136097 | break; |
| 136098 | case 245: /* trigger_cmd ::= select */ |
| 136099 | {yymsp[0].minor.yy145 = sqlite3TriggerSelectStep(pParse->db, yymsp[0].minor.yy243); /*A-overwrites-X*/} |
| 136100 | break; |
| 136101 | case 246: /* expr ::= RAISE LP IGNORE RP */ |
| 136102 | { |
| 136103 | spanSet(&yymsp[-3].minor.yy190,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ |
| 136104 | yymsp[-3].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, 0); |
| 136105 | if( yymsp[-3].minor.yy190.pExpr ){ |
| 136106 | yymsp[-3].minor.yy190.pExpr->affinity = OE_Ignore; |
| 136107 | } |
| 136108 | } |
| 136109 | break; |
| 136110 | case 247: /* expr ::= RAISE LP raisetype COMMA nm RP */ |
| 136111 | { |
| 136112 | spanSet(&yymsp[-5].minor.yy190,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ |
| 136113 | yymsp[-5].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &yymsp[-1].minor.yy0); |
| 136114 | if( yymsp[-5].minor.yy190.pExpr ) { |
| 136115 | yymsp[-5].minor.yy190.pExpr->affinity = (char)yymsp[-3].minor.yy194; |
| 136116 | } |
| 136117 | } |
| 136118 | break; |
| 136119 | case 248: /* raisetype ::= ROLLBACK */ |
| 136120 | {yymsp[0].minor.yy194 = OE_Rollback;} |
| 136121 | break; |
| 136122 | case 250: /* raisetype ::= FAIL */ |
| 136123 | {yymsp[0].minor.yy194 = OE_Fail;} |
| 136124 | break; |
| 136125 | case 251: /* cmd ::= DROP TRIGGER ifexists fullname */ |
| 136126 | { |
| 136127 | sqlite3DropTrigger(pParse,yymsp[0].minor.yy185,yymsp[-1].minor.yy194); |
| 136128 | } |
| 136129 | break; |
| 136130 | case 252: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ |
| 136131 | { |
| 136132 | sqlite3Attach(pParse, yymsp[-3].minor.yy190.pExpr, yymsp[-1].minor.yy190.pExpr, yymsp[0].minor.yy72); |
| 136133 | } |
| 136134 | break; |
| 136135 | case 253: /* cmd ::= DETACH database_kw_opt expr */ |
| 136136 | { |
| 136137 | sqlite3Detach(pParse, yymsp[0].minor.yy190.pExpr); |
| 136138 | } |
| 136139 | break; |
| 136140 | case 256: /* cmd ::= REINDEX */ |
| 136141 | {sqlite3Reindex(pParse, 0, 0);} |
| 136142 | break; |
| 136143 | case 257: /* cmd ::= REINDEX nm dbnm */ |
| 136144 | {sqlite3Reindex(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} |
| 136145 | break; |
| 136146 | case 258: /* cmd ::= ANALYZE */ |
| 136147 | {sqlite3Analyze(pParse, 0, 0);} |
| 136148 | break; |
| 136149 | case 259: /* cmd ::= ANALYZE nm dbnm */ |
| 136150 | {sqlite3Analyze(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} |
| 136151 | break; |
| 136152 | case 260: /* cmd ::= ALTER TABLE fullname RENAME TO nm */ |
| 136153 | { |
| 136154 | sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy185,&yymsp[0].minor.yy0); |
| 136155 | } |
| 136156 | break; |
| 136157 | case 261: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ |
| 136158 | { |
| 136159 | yymsp[-1].minor.yy0.n = (int)(pParse->sLastToken.z-yymsp[-1].minor.yy0.z) + pParse->sLastToken.n; |
| 136160 | sqlite3AlterFinishAddColumn(pParse, &yymsp[-1].minor.yy0); |
| 136161 | } |
| 136162 | break; |
| 136163 | case 262: /* add_column_fullname ::= fullname */ |
| 136164 | { |
| 136165 | disableLookaside(pParse); |
| 136166 | sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy185); |
| 136167 | } |
| 136168 | break; |
| 136169 | case 263: /* cmd ::= create_vtab */ |
| 136170 | {sqlite3VtabFinishParse(pParse,0);} |
| 136171 | break; |
| 136172 | case 264: /* cmd ::= create_vtab LP vtabarglist RP */ |
| 136173 | {sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);} |
| 136174 | break; |
| 136175 | case 265: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ |
| 136176 | { |
| 136177 | sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy194); |
| 136178 | } |
| 136179 | break; |
| 136180 | case 266: /* vtabarg ::= */ |
| 136181 | {sqlite3VtabArgInit(pParse);} |
| 136182 | break; |
| 136183 | case 267: /* vtabargtoken ::= ANY */ |
| 136184 | case 268: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==268); |
| 136185 | case 269: /* lp ::= LP */ yytestcase(yyruleno==269); |
| 136186 | {sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);} |
| 136187 | break; |
| 136188 | case 270: /* with ::= */ |
| 136189 | {yymsp[1].minor.yy285 = 0;} |
| 136190 | break; |
| 136191 | case 271: /* with ::= WITH wqlist */ |
| 136192 | { yymsp[-1].minor.yy285 = yymsp[0].minor.yy285; } |
| 136193 | break; |
| 136194 | case 272: /* with ::= WITH RECURSIVE wqlist */ |
| 136195 | { yymsp[-2].minor.yy285 = yymsp[0].minor.yy285; } |
| 136196 | break; |
| 136197 | case 273: /* wqlist ::= nm eidlist_opt AS LP select RP */ |
| 136198 | { |
| 136199 | yymsp[-5].minor.yy285 = sqlite3WithAdd(pParse, 0, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy148, yymsp[-1].minor.yy243); /*A-overwrites-X*/ |
| 136200 | } |
| 136201 | break; |
| 136202 | case 274: /* wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */ |
| 136203 | { |
| 136204 | yymsp[-7].minor.yy285 = sqlite3WithAdd(pParse, yymsp[-7].minor.yy285, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy148, yymsp[-1].minor.yy243); |
| 136205 | } |
| 136206 | break; |
| 136207 | default: |
| 136208 | /* (275) input ::= cmdlist */ yytestcase(yyruleno==275); |
| 136209 | /* (276) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==276); |
| 136210 | /* (277) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=277); |
| 136211 | /* (278) ecmd ::= SEMI */ yytestcase(yyruleno==278); |
| 136212 | /* (279) ecmd ::= explain cmdx SEMI */ yytestcase(yyruleno==279); |
| 136213 | /* (280) explain ::= */ yytestcase(yyruleno==280); |
| 136214 | /* (281) trans_opt ::= */ yytestcase(yyruleno==281); |
| 136215 | /* (282) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==282); |
| 136216 | /* (283) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==283); |
| 136217 | /* (284) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==284); |
| 136218 | /* (285) savepoint_opt ::= */ yytestcase(yyruleno==285); |
| 136219 | /* (286) cmd ::= create_table create_table_args */ yytestcase(yyruleno==286); |
| 136220 | /* (287) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==287); |
| 136221 | /* (288) columnlist ::= columnname carglist */ yytestcase(yyruleno==288); |
| 136222 | /* (289) nm ::= ID|INDEXED */ yytestcase(yyruleno==289); |
| 136223 | /* (290) nm ::= STRING */ yytestcase(yyruleno==290); |
| 136224 | /* (291) nm ::= JOIN_KW */ yytestcase(yyruleno==291); |
| 136225 | /* (292) typetoken ::= typename */ yytestcase(yyruleno==292); |
| 136226 | /* (293) typename ::= ID|STRING */ yytestcase(yyruleno==293); |
| 136227 | /* (294) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=294); |
| 136228 | /* (295) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=295); |
| 136229 | /* (296) carglist ::= carglist ccons */ yytestcase(yyruleno==296); |
| 136230 | /* (297) carglist ::= */ yytestcase(yyruleno==297); |
| 136231 | /* (298) ccons ::= NULL onconf */ yytestcase(yyruleno==298); |
| 136232 | /* (299) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==299); |
| 136233 | /* (300) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==300); |
| 136234 | /* (301) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=301); |
| 136235 | /* (302) tconscomma ::= */ yytestcase(yyruleno==302); |
| 136236 | /* (303) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=303); |
| 136237 | /* (304) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=304); |
| 136238 | /* (305) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=305); |
| 136239 | /* (306) oneselect ::= values */ yytestcase(yyruleno==306); |
| 136240 | /* (307) sclp ::= selcollist COMMA */ yytestcase(yyruleno==307); |
| 136241 | /* (308) as ::= ID|STRING */ yytestcase(yyruleno==308); |
| 136242 | /* (309) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=309); |
| 136243 | /* (310) exprlist ::= nexprlist */ yytestcase(yyruleno==310); |
| 136244 | /* (311) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=311); |
| 136245 | /* (312) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=312); |
| 136246 | /* (313) nmnum ::= ON */ yytestcase(yyruleno==313); |
| 136247 | /* (314) nmnum ::= DELETE */ yytestcase(yyruleno==314); |
| 136248 | /* (315) nmnum ::= DEFAULT */ yytestcase(yyruleno==315); |
| 136249 | /* (316) plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==316); |
| 136250 | /* (317) foreach_clause ::= */ yytestcase(yyruleno==317); |
| 136251 | /* (318) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==318); |
| 136252 | /* (319) trnm ::= nm */ yytestcase(yyruleno==319); |
| 136253 | /* (320) tridxby ::= */ yytestcase(yyruleno==320); |
| 136254 | /* (321) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==321); |
| 136255 | /* (322) database_kw_opt ::= */ yytestcase(yyruleno==322); |
| 136256 | /* (323) kwcolumn_opt ::= */ yytestcase(yyruleno==323); |
| 136257 | /* (324) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==324); |
| 136258 | /* (325) vtabarglist ::= vtabarg */ yytestcase(yyruleno==325); |
| 136259 | /* (326) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==326); |
| 136260 | /* (327) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==327); |
| 136261 | /* (328) anylist ::= */ yytestcase(yyruleno==328); |
| 136262 | /* (329) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==329); |
| 136263 | /* (330) anylist ::= anylist ANY */ yytestcase(yyruleno==330); |
| 136264 | break; |
| 136265 | /********** End reduce actions ************************************************/ |
| 136266 | }; |
| 136267 | assert( yyruleno<sizeof(yyRuleInfo)/sizeof(yyRuleInfo[0]) ); |
| 136268 | yygoto = yyRuleInfo[yyruleno].lhs; |
| @@ -136449,11 +136526,11 @@ | |
| 136449 | } |
| 136450 | #endif |
| 136451 | yy_destructor(yypParser, (YYCODETYPE)yymajor, &yyminorunion); |
| 136452 | yymajor = YYNOCODE; |
| 136453 | }else{ |
| 136454 | while( yypParser->yytos >= &yypParser->yystack |
| 136455 | && yymx != YYERRORSYMBOL |
| 136456 | && (yyact = yy_find_reduce_action( |
| 136457 | yypParser->yytos->stateno, |
| 136458 | YYERRORSYMBOL)) >= YY_MIN_REDUCE |
| 136459 | ){ |
| @@ -138617,10 +138694,11 @@ | |
| 138617 | } aFlagOp[] = { |
| 138618 | { SQLITE_DBCONFIG_ENABLE_FKEY, SQLITE_ForeignKeys }, |
| 138619 | { SQLITE_DBCONFIG_ENABLE_TRIGGER, SQLITE_EnableTrigger }, |
| 138620 | { SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER, SQLITE_Fts3Tokenizer }, |
| 138621 | { SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, SQLITE_LoadExtension }, |
| 138622 | }; |
| 138623 | unsigned int i; |
| 138624 | rc = SQLITE_ERROR; /* IMP: R-42790-23372 */ |
| 138625 | for(i=0; i<ArraySize(aFlagOp); i++){ |
| 138626 | if( aFlagOp[i].op==op ){ |
| @@ -139913,10 +139991,17 @@ | |
| 139913 | db->busyHandler.nBusy = 0; |
| 139914 | rc = sqlite3Checkpoint(db, iDb, eMode, pnLog, pnCkpt); |
| 139915 | sqlite3Error(db, rc); |
| 139916 | } |
| 139917 | rc = sqlite3ApiExit(db, rc); |
| 139918 | sqlite3_mutex_leave(db->mutex); |
| 139919 | return rc; |
| 139920 | #endif |
| 139921 | } |
| 139922 | |
| @@ -140415,10 +140500,11 @@ | |
| 140415 | int octet = (sqlite3HexToInt(zUri[iIn++]) << 4); |
| 140416 | octet += sqlite3HexToInt(zUri[iIn++]); |
| 140417 | |
| 140418 | assert( octet>=0 && octet<256 ); |
| 140419 | if( octet==0 ){ |
| 140420 | /* This branch is taken when "%00" appears within the URI. In this |
| 140421 | ** case we ignore all text in the remainder of the path, name or |
| 140422 | ** value currently being parsed. So ignore the current character |
| 140423 | ** and skip to the next "?", "=" or "&", as appropriate. */ |
| 140424 | while( (c = zUri[iIn])!=0 && c!='#' |
| @@ -140427,10 +140513,16 @@ | |
| 140427 | && (eState!=2 || c!='&') |
| 140428 | ){ |
| 140429 | iIn++; |
| 140430 | } |
| 140431 | continue; |
| 140432 | } |
| 140433 | c = octet; |
| 140434 | }else if( eState==1 && (c=='&' || c=='=') ){ |
| 140435 | if( zFile[iOut-1]==0 ){ |
| 140436 | /* An empty option name. Ignore this option altogether. */ |
| @@ -164306,14 +164398,16 @@ | |
| 164306 | char *zSql; |
| 164307 | sqlite3_stmt *p; |
| 164308 | int rc; |
| 164309 | i64 nRow = 0; |
| 164310 | |
| 164311 | if( sqlite3_table_column_metadata(db,pRtree->zDb,"sqlite_stat1", |
| 164312 | 0,0,0,0,0,0)==SQLITE_ERROR ){ |
| 164313 | pRtree->nRowEst = RTREE_DEFAULT_ROWEST; |
| 164314 | return SQLITE_OK; |
| 164315 | } |
| 164316 | zSql = sqlite3_mprintf(zFmt, pRtree->zDb, pRtree->zName); |
| 164317 | if( zSql==0 ){ |
| 164318 | rc = SQLITE_NOMEM; |
| 164319 | }else{ |
| @@ -165210,11 +165304,11 @@ | |
| 165210 | ** of the locale to use. Passing an empty string ("") or SQL NULL value |
| 165211 | ** as the second argument is the same as invoking the 1 argument version |
| 165212 | ** of upper() or lower(). |
| 165213 | ** |
| 165214 | ** lower('I', 'en_us') -> 'i' |
| 165215 | ** lower('I', 'tr_tr') -> 'ı' (small dotless i) |
| 165216 | ** |
| 165217 | ** http://www.icu-project.org/userguide/posix.html#case_mappings |
| 165218 | */ |
| 165219 | static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){ |
| 165220 | const UChar *zInput; /* Pointer to input string */ |
| @@ -181140,11 +181234,11 @@ | |
| 181140 | } |
| 181141 | #endif |
| 181142 | fts5yy_destructor(fts5yypParser, (fts5YYCODETYPE)fts5yymajor, &fts5yyminorunion); |
| 181143 | fts5yymajor = fts5YYNOCODE; |
| 181144 | }else{ |
| 181145 | while( fts5yypParser->fts5yytos >= &fts5yypParser->fts5yystack |
| 181146 | && fts5yymx != fts5YYERRORSYMBOL |
| 181147 | && (fts5yyact = fts5yy_find_reduce_action( |
| 181148 | fts5yypParser->fts5yytos->stateno, |
| 181149 | fts5YYERRORSYMBOL)) >= fts5YY_MIN_REDUCE |
| 181150 | ){ |
| @@ -181506,10 +181600,13 @@ | |
| 181506 | int nToken, /* Size of token in bytes */ |
| 181507 | int iStartOff, /* Start offset of token */ |
| 181508 | int iEndOff /* End offset of token */ |
| 181509 | ){ |
| 181510 | int rc = SQLITE_OK; |
| 181511 | |
| 181512 | if( (tflags & FTS5_TOKEN_COLOCATED)==0 ){ |
| 181513 | Fts5SFinder *p = (Fts5SFinder*)pContext; |
| 181514 | if( p->iPos>0 ){ |
| 181515 | int i; |
| @@ -181662,11 +181759,10 @@ | |
| 181662 | for(jj=0; jj<(sFinder.nFirst-1); jj++){ |
| 181663 | if( sFinder.aFirst[jj+1]>io ) break; |
| 181664 | } |
| 181665 | |
| 181666 | if( sFinder.aFirst[jj]<io ){ |
| 181667 | int nScore; |
| 181668 | memset(aSeen, 0, nPhrase); |
| 181669 | rc = fts5SnippetScore(pApi, pFts, nDocsize, aSeen, i, |
| 181670 | sFinder.aFirst[jj], nToken, &nScore, 0 |
| 181671 | ); |
| 181672 | |
| @@ -195597,11 +195693,11 @@ | |
| 195597 | int nArg, /* Number of args */ |
| 195598 | sqlite3_value **apUnused /* Function arguments */ |
| 195599 | ){ |
| 195600 | assert( nArg==0 ); |
| 195601 | UNUSED_PARAM2(nArg, apUnused); |
| 195602 | sqlite3_result_text(pCtx, "fts5: 2016-09-21 19:43:34 0741812d7fcd558479e4849fbb3ba8d03738d018", -1, SQLITE_TRANSIENT); |
| 195603 | } |
| 195604 | |
| 195605 | static int fts5Init(sqlite3 *db){ |
| 195606 | static const sqlite3_module fts5Mod = { |
| 195607 | /* iVersion */ 2, |
| 195608 |
| --- src/sqlite3.c | |
| +++ src/sqlite3.c | |
| @@ -1,8 +1,8 @@ | |
| 1 | /****************************************************************************** |
| 2 | ** This file is an amalgamation of many separate C source files from SQLite |
| 3 | ** version 3.16.0. By combining all the individual C code files into this |
| 4 | ** single large file, the entire code can be compiled as a single translation |
| 5 | ** unit. This allows many compilers to do optimizations that would not be |
| 6 | ** possible if the files were compiled separately. Performance improvements |
| 7 | ** of 5% or more are commonly seen when SQLite is compiled as a single |
| 8 | ** translation unit. |
| @@ -379,13 +379,13 @@ | |
| 379 | ** |
| 380 | ** See also: [sqlite3_libversion()], |
| 381 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 382 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 383 | */ |
| 384 | #define SQLITE_VERSION "3.16.0" |
| 385 | #define SQLITE_VERSION_NUMBER 3016000 |
| 386 | #define SQLITE_SOURCE_ID "2016-11-02 14:50:19 3028845329c9b7acdec2ec8b01d00d782347454c" |
| 387 | |
| 388 | /* |
| 389 | ** CAPI3REF: Run-Time Library Version Numbers |
| 390 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 391 | ** |
| @@ -1235,10 +1235,16 @@ | |
| 1235 | ** <li>[[SQLITE_FCNTL_HAS_MOVED]] |
| 1236 | ** The [SQLITE_FCNTL_HAS_MOVED] file control interprets its argument as a |
| 1237 | ** pointer to an integer and it writes a boolean into that integer depending |
| 1238 | ** on whether or not the file has been renamed, moved, or deleted since it |
| 1239 | ** was first opened. |
| 1240 | ** |
| 1241 | ** <li>[[SQLITE_FCNTL_WIN32_GET_HANDLE]] |
| 1242 | ** The [SQLITE_FCNTL_WIN32_GET_HANDLE] opcode can be used to obtain the |
| 1243 | ** underlying native file handle associated with a file handle. This file |
| 1244 | ** control interprets its argument as a pointer to a native file handle and |
| 1245 | ** writes the resulting value there. |
| 1246 | ** |
| 1247 | ** <li>[[SQLITE_FCNTL_WIN32_SET_HANDLE]] |
| 1248 | ** The [SQLITE_FCNTL_WIN32_SET_HANDLE] opcode is used for debugging. This |
| 1249 | ** opcode causes the xFileControl method to swap the file handle with the one |
| 1250 | ** pointed to by the pArg argument. This capability is used during testing |
| @@ -1286,10 +1292,12 @@ | |
| 1292 | #define SQLITE_FCNTL_WAL_BLOCK 24 |
| 1293 | #define SQLITE_FCNTL_ZIPVFS 25 |
| 1294 | #define SQLITE_FCNTL_RBU 26 |
| 1295 | #define SQLITE_FCNTL_VFS_POINTER 27 |
| 1296 | #define SQLITE_FCNTL_JOURNAL_POINTER 28 |
| 1297 | #define SQLITE_FCNTL_WIN32_GET_HANDLE 29 |
| 1298 | #define SQLITE_FCNTL_PDB 30 |
| 1299 | |
| 1300 | /* deprecated names */ |
| 1301 | #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE |
| 1302 | #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE |
| 1303 | #define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO |
| @@ -2238,18 +2246,31 @@ | |
| 2246 | ** does not make a copy of the new main schema name string, so the application |
| 2247 | ** must ensure that the argument passed into this DBCONFIG option is unchanged |
| 2248 | ** until after the database connection closes. |
| 2249 | ** </dd> |
| 2250 | ** |
| 2251 | ** <dt>SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE</dt> |
| 2252 | ** <dd> Usually, when a database in wal mode is closed or detached from a |
| 2253 | ** database handle, SQLite checks if this will mean that there are now no |
| 2254 | ** connections at all to the database. If so, it performs a checkpoint |
| 2255 | ** operation before closing the connection. This option may be used to |
| 2256 | ** override this behaviour. The first parameter passed to this operation |
| 2257 | ** is an integer - non-zero to disable checkpoints-on-close, or zero (the |
| 2258 | ** default) to enable them. The second parameter is a pointer to an integer |
| 2259 | ** into which is written 0 or 1 to indicate whether checkpoints-on-close |
| 2260 | ** have been disabled - 0 if they are not disabled, 1 if they are. |
| 2261 | ** </dd> |
| 2262 | ** |
| 2263 | ** </dl> |
| 2264 | */ |
| 2265 | #define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */ |
| 2266 | #define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */ |
| 2267 | #define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */ |
| 2268 | #define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */ |
| 2269 | #define SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1004 /* int int* */ |
| 2270 | #define SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1005 /* int int* */ |
| 2271 | #define SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE 1006 /* int int* */ |
| 2272 | |
| 2273 | |
| 2274 | /* |
| 2275 | ** CAPI3REF: Enable Or Disable Extended Result Codes |
| 2276 | ** METHOD: sqlite3 |
| @@ -8915,11 +8936,11 @@ | |
| 8936 | |
| 8937 | /* |
| 8938 | ** CAPI3REF: Set a table filter on a Session Object. |
| 8939 | ** |
| 8940 | ** The second argument (xFilter) is the "filter callback". For changes to rows |
| 8941 | ** in tables that are not attached to the Session object, the filter is called |
| 8942 | ** to determine whether changes to the table's rows should be tracked or not. |
| 8943 | ** If xFilter returns 0, changes is not tracked. Note that once a table is |
| 8944 | ** attached, xFilter will not be called again. |
| 8945 | */ |
| 8946 | void sqlite3session_table_filter( |
| @@ -9181,11 +9202,11 @@ | |
| 9202 | ** Assuming the changeset blob was created by one of the |
| 9203 | ** [sqlite3session_changeset()], [sqlite3changeset_concat()] or |
| 9204 | ** [sqlite3changeset_invert()] functions, all changes within the changeset |
| 9205 | ** that apply to a single table are grouped together. This means that when |
| 9206 | ** an application iterates through a changeset using an iterator created by |
| 9207 | ** this function, all changes that relate to a single table are visited |
| 9208 | ** consecutively. There is no chance that the iterator will visit a change |
| 9209 | ** the applies to table X, then one for table Y, and then later on visit |
| 9210 | ** another change for table X. |
| 9211 | */ |
| 9212 | int sqlite3changeset_start( |
| @@ -9268,11 +9289,11 @@ | |
| 9289 | ** If successful, *pabPK is set to point to an array of nCol entries, where |
| 9290 | ** nCol is the number of columns in the table. Elements of *pabPK are set to |
| 9291 | ** 0x01 if the corresponding column is part of the tables primary key, or |
| 9292 | ** 0x00 if it is not. |
| 9293 | ** |
| 9294 | ** If argument pnCol is not NULL, then *pnCol is set to the number of columns |
| 9295 | ** in the table. |
| 9296 | ** |
| 9297 | ** If this function is called when the iterator does not point to a valid |
| 9298 | ** entry, SQLITE_MISUSE is returned and the output variables zeroed. Otherwise, |
| 9299 | ** SQLITE_OK is returned and the output variables populated as described |
| @@ -9543,11 +9564,11 @@ | |
| 9564 | ** Rows within the changeset and changegroup are identified by the values in |
| 9565 | ** their PRIMARY KEY columns. A change in the changeset is considered to |
| 9566 | ** apply to the same row as a change already present in the changegroup if |
| 9567 | ** the two rows have the same primary key. |
| 9568 | ** |
| 9569 | ** Changes to rows that do not already appear in the changegroup are |
| 9570 | ** simply copied into it. Or, if both the new changeset and the changegroup |
| 9571 | ** contain changes that apply to a single row, the final contents of the |
| 9572 | ** changegroup depends on the type of each change, as follows: |
| 9573 | ** |
| 9574 | ** <table border=1 style="margin-left:8ex;margin-right:8ex"> |
| @@ -11411,13 +11432,13 @@ | |
| 11432 | #define TK_GROUP 127 |
| 11433 | #define TK_HAVING 128 |
| 11434 | #define TK_LIMIT 129 |
| 11435 | #define TK_WHERE 130 |
| 11436 | #define TK_INTO 131 |
| 11437 | #define TK_FLOAT 132 |
| 11438 | #define TK_BLOB 133 |
| 11439 | #define TK_INTEGER 134 |
| 11440 | #define TK_VARIABLE 135 |
| 11441 | #define TK_CASE 136 |
| 11442 | #define TK_WHEN 137 |
| 11443 | #define TK_THEN 138 |
| 11444 | #define TK_ELSE 139 |
| @@ -12675,19 +12696,19 @@ | |
| 12696 | #define OP_SorterData 120 /* synopsis: r[P2]=data */ |
| 12697 | #define OP_RowKey 121 /* synopsis: r[P2]=key */ |
| 12698 | #define OP_RowData 122 /* synopsis: r[P2]=data */ |
| 12699 | #define OP_Rowid 123 /* synopsis: r[P2]=rowid */ |
| 12700 | #define OP_NullRow 124 |
| 12701 | #define OP_SorterInsert 125 /* synopsis: key=r[P2] */ |
| 12702 | #define OP_IdxInsert 126 /* synopsis: key=r[P2] */ |
| 12703 | #define OP_IdxDelete 127 /* synopsis: key=r[P2@P3] */ |
| 12704 | #define OP_Seek 128 /* synopsis: Move P3 to P1.rowid */ |
| 12705 | #define OP_IdxRowid 129 /* synopsis: r[P2]=rowid */ |
| 12706 | #define OP_Destroy 130 |
| 12707 | #define OP_Clear 131 |
| 12708 | #define OP_Real 132 /* same as TK_FLOAT, synopsis: r[P2]=P4 */ |
| 12709 | #define OP_ResetSorter 133 |
| 12710 | #define OP_CreateIndex 134 /* synopsis: r[P2]=root iDb=P1 */ |
| 12711 | #define OP_CreateTable 135 /* synopsis: r[P2]=root iDb=P1 */ |
| 12712 | #define OP_ParseSchema 136 |
| 12713 | #define OP_LoadAnalysis 137 |
| 12714 | #define OP_DropTable 138 |
| @@ -12741,11 +12762,11 @@ | |
| 12762 | /* 88 */ 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00,\ |
| 12763 | /* 96 */ 0x00, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,\ |
| 12764 | /* 104 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ |
| 12765 | /* 112 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,\ |
| 12766 | /* 120 */ 0x00, 0x00, 0x00, 0x10, 0x00, 0x04, 0x04, 0x00,\ |
| 12767 | /* 128 */ 0x00, 0x10, 0x10, 0x00, 0x10, 0x00, 0x10, 0x10,\ |
| 12768 | /* 136 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x10,\ |
| 12769 | /* 144 */ 0x00, 0x04, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00,\ |
| 12770 | /* 152 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10,\ |
| 12771 | /* 160 */ 0x00, 0x00, 0x00,} |
| 12772 | |
| @@ -13030,11 +13051,11 @@ | |
| 13051 | int, |
| 13052 | int, |
| 13053 | int, |
| 13054 | void(*)(DbPage*) |
| 13055 | ); |
| 13056 | SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3*); |
| 13057 | SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager*, int, unsigned char*); |
| 13058 | |
| 13059 | /* Functions used to configure a Pager object. */ |
| 13060 | SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(Pager*, int(*)(void *), void *); |
| 13061 | SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager*, u32*, int); |
| @@ -13081,19 +13102,22 @@ | |
| 13102 | SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int n); |
| 13103 | SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint); |
| 13104 | SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager); |
| 13105 | |
| 13106 | #ifndef SQLITE_OMIT_WAL |
| 13107 | SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, sqlite3*, int, int*, int*); |
| 13108 | SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager); |
| 13109 | SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager); |
| 13110 | SQLITE_PRIVATE int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen); |
| 13111 | SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager, sqlite3*); |
| 13112 | SQLITE_PRIVATE int sqlite3PagerUseWal(Pager *pPager); |
| 13113 | # ifdef SQLITE_ENABLE_SNAPSHOT |
| 13114 | SQLITE_PRIVATE int sqlite3PagerSnapshotGet(Pager *pPager, sqlite3_snapshot **ppSnapshot); |
| 13115 | SQLITE_PRIVATE int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSnapshot); |
| 13116 | # endif |
| 13117 | #else |
| 13118 | # define sqlite3PagerUseWal(x) 0 |
| 13119 | #endif |
| 13120 | |
| 13121 | #ifdef SQLITE_ENABLE_ZIPVFS |
| 13122 | SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager); |
| 13123 | #endif |
| @@ -14060,10 +14084,11 @@ | |
| 14084 | #define SQLITE_QueryOnly 0x04000000 /* Disable database changes */ |
| 14085 | #define SQLITE_VdbeEQP 0x08000000 /* Debug EXPLAIN QUERY PLAN */ |
| 14086 | #define SQLITE_Vacuum 0x10000000 /* Currently in a VACUUM */ |
| 14087 | #define SQLITE_CellSizeCk 0x20000000 /* Check btree cell sizes on load */ |
| 14088 | #define SQLITE_Fts3Tokenizer 0x40000000 /* Enable fts3_tokenizer(2) */ |
| 14089 | #define SQLITE_NoCkptOnClose 0x80000000 /* No checkpoint on close()/DETACH */ |
| 14090 | |
| 14091 | |
| 14092 | /* |
| 14093 | ** Bits of the sqlite3.dbOptFlags field that are used by the |
| 14094 | ** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface to |
| @@ -14963,10 +14988,11 @@ | |
| 14988 | #define EP_Unlikely 0x040000 /* unlikely() or likelihood() function */ |
| 14989 | #define EP_ConstFunc 0x080000 /* A SQLITE_FUNC_CONSTANT or _SLOCHNG function */ |
| 14990 | #define EP_CanBeNull 0x100000 /* Can be null despite NOT NULL constraint */ |
| 14991 | #define EP_Subquery 0x200000 /* Tree contains a TK_SELECT operator */ |
| 14992 | #define EP_Alias 0x400000 /* Is an alias for a result set column */ |
| 14993 | #define EP_Leaf 0x800000 /* Expr.pLeft, .pRight, .u.pSelect all NULL */ |
| 14994 | |
| 14995 | /* |
| 14996 | ** Combinations of two or more EP_* flags |
| 14997 | */ |
| 14998 | #define EP_Propagate (EP_Collate|EP_Subquery) /* Propagate these bits up tree */ |
| @@ -15514,39 +15540,27 @@ | |
| 15540 | u8 mayAbort; /* True if statement may throw an ABORT exception */ |
| 15541 | u8 hasCompound; /* Need to invoke convertCompoundSelectToSubquery() */ |
| 15542 | u8 okConstFactor; /* OK to factor out constants */ |
| 15543 | u8 disableLookaside; /* Number of times lookaside has been disabled */ |
| 15544 | u8 nColCache; /* Number of entries in aColCache[] */ |
| 15545 | int nRangeReg; /* Size of the temporary register block */ |
| 15546 | int iRangeReg; /* First register in temporary register block */ |
| 15547 | int nErr; /* Number of errors seen */ |
| 15548 | int nTab; /* Number of previously allocated VDBE cursors */ |
| 15549 | int nMem; /* Number of memory cells used so far */ |
| 15550 | int nOpAlloc; /* Number of slots allocated for Vdbe.aOp[] */ |
| 15551 | int szOpAlloc; /* Bytes of memory space allocated for Vdbe.aOp[] */ |
| 15552 | int ckBase; /* Base register of data during check constraints */ |
| 15553 | int iSelfTab; /* Table of an index whose exprs are being coded */ |
| 15554 | int iCacheLevel; /* ColCache valid when aColCache[].iLevel<=iCacheLevel */ |
| 15555 | int iCacheCnt; /* Counter used to generate aColCache[].lru values */ |
| 15556 | int nLabel; /* Number of labels used */ |
| 15557 | int *aLabel; /* Space to hold the labels */ |
| 15558 | ExprList *pConstExpr;/* Constant expressions */ |
| 15559 | Token constraintName;/* Name of the constraint currently being parsed */ |
| 15560 | yDbMask writeMask; /* Start a write transaction on these databases */ |
| 15561 | yDbMask cookieMask; /* Bitmask of schema verified databases */ |
| 15562 | int regRowid; /* Register holding rowid of CREATE TABLE entry */ |
| 15563 | int regRoot; /* Register holding root page number for new objects */ |
| 15564 | int nMaxArg; /* Max args passed to user function by sub-program */ |
| 15565 | #if SELECTTRACE_ENABLED |
| 15566 | int nSelect; /* Number of SELECT statements seen */ |
| @@ -15555,21 +15569,38 @@ | |
| 15569 | #ifndef SQLITE_OMIT_SHARED_CACHE |
| 15570 | int nTableLock; /* Number of locks in aTableLock */ |
| 15571 | TableLock *aTableLock; /* Required table locks for shared-cache mode */ |
| 15572 | #endif |
| 15573 | AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters */ |
| 15574 | Parse *pToplevel; /* Parse structure for main program (or NULL) */ |
| 15575 | Table *pTriggerTab; /* Table triggers are being coded for */ |
| 15576 | int addrCrTab; /* Address of OP_CreateTable opcode on CREATE TABLE */ |
| 15577 | u32 nQueryLoop; /* Est number of iterations of a query (10*log2(N)) */ |
| 15578 | u32 oldmask; /* Mask of old.* columns referenced */ |
| 15579 | u32 newmask; /* Mask of new.* columns referenced */ |
| 15580 | u8 eTriggerOp; /* TK_UPDATE, TK_INSERT or TK_DELETE */ |
| 15581 | u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */ |
| 15582 | u8 disableTriggers; /* True to disable triggers */ |
| 15583 | |
| 15584 | /************************************************************************** |
| 15585 | ** Fields above must be initialized to zero. The fields that follow, |
| 15586 | ** down to the beginning of the recursive section, do not need to be |
| 15587 | ** initialized as they will be set before being used. The boundary is |
| 15588 | ** determined by offsetof(Parse,aColCache). |
| 15589 | **************************************************************************/ |
| 15590 | |
| 15591 | struct yColCache { |
| 15592 | int iTable; /* Table cursor number */ |
| 15593 | i16 iColumn; /* Table column number */ |
| 15594 | u8 tempReg; /* iReg is a temp register that needs to be freed */ |
| 15595 | int iLevel; /* Nesting level */ |
| 15596 | int iReg; /* Reg with value of this column. 0 means none. */ |
| 15597 | int lru; /* Least recently used entry has the smallest value */ |
| 15598 | } aColCache[SQLITE_N_COLCACHE]; /* One for each column cache entry */ |
| 15599 | int aTempReg[8]; /* Holding area for temporary registers */ |
| 15600 | Token sNameToken; /* Token with unqualified schema object name */ |
| 15601 | Token sLastToken; /* The last token parsed */ |
| 15602 | |
| 15603 | /************************************************************************ |
| 15604 | ** Above is constant between recursions. Below is reset before and after |
| 15605 | ** each recursion. The boundary between these two regions is determined |
| 15606 | ** using offsetof(Parse,nVar) so the nVar field must be the first field |
| @@ -15582,11 +15613,10 @@ | |
| 15613 | u8 explain; /* True if the EXPLAIN flag is found on the query */ |
| 15614 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 15615 | u8 declareVtab; /* True if inside sqlite3_declare_vtab() */ |
| 15616 | int nVtabLock; /* Number of virtual tables to lock */ |
| 15617 | #endif |
| 15618 | int nHeight; /* Expression tree height of current sub-select */ |
| 15619 | #ifndef SQLITE_OMIT_EXPLAIN |
| 15620 | int iSelectId; /* ID of current select for EXPLAIN output */ |
| 15621 | int iNextSelectId; /* Next available select ID for EXPLAIN output */ |
| 15622 | #endif |
| @@ -15594,12 +15624,10 @@ | |
| 15624 | Vdbe *pReprepare; /* VM being reprepared (sqlite3Reprepare()) */ |
| 15625 | const char *zTail; /* All SQL text past the last semicolon parsed */ |
| 15626 | Table *pNewTable; /* A table being constructed by CREATE TABLE */ |
| 15627 | Trigger *pNewTrigger; /* Trigger under construct by a CREATE TRIGGER */ |
| 15628 | const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */ |
| 15629 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 15630 | Token sArg; /* Complete text of a module argument */ |
| 15631 | Table **apVtabLock; /* Pointer to virtual tables needing locking */ |
| 15632 | #endif |
| 15633 | Table *pZombieTab; /* List of Table objects to delete after code gen */ |
| @@ -15606,10 +15634,18 @@ | |
| 15634 | TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */ |
| 15635 | With *pWith; /* Current WITH clause, or NULL */ |
| 15636 | With *pWithToFree; /* Free this WITH object at the end of the parse */ |
| 15637 | }; |
| 15638 | |
| 15639 | /* |
| 15640 | ** Sizes and pointers of various parts of the Parse object. |
| 15641 | */ |
| 15642 | #define PARSE_HDR_SZ offsetof(Parse,aColCache) /* Recursive part w/o aColCache*/ |
| 15643 | #define PARSE_RECURSE_SZ offsetof(Parse,nVar) /* Recursive part */ |
| 15644 | #define PARSE_TAIL_SZ (sizeof(Parse)-PARSE_RECURSE_SZ) /* Non-recursive part */ |
| 15645 | #define PARSE_TAIL(X) (((char*)(X))+PARSE_RECURSE_SZ) /* Pointer to tail */ |
| 15646 | |
| 15647 | /* |
| 15648 | ** Return true if currently inside an sqlite3_declare_vtab() call. |
| 15649 | */ |
| 15650 | #ifdef SQLITE_OMIT_VIRTUALTABLE |
| 15651 | #define IN_DECLARE_VTAB 0 |
| @@ -16169,11 +16205,11 @@ | |
| 16205 | SQLITE_PRIVATE void sqlite3ExprAttachSubtrees(sqlite3*,Expr*,Expr*,Expr*); |
| 16206 | SQLITE_PRIVATE Expr *sqlite3PExpr(Parse*, int, Expr*, Expr*, const Token*); |
| 16207 | SQLITE_PRIVATE void sqlite3PExprAddSelect(Parse*, Expr*, Select*); |
| 16208 | SQLITE_PRIVATE Expr *sqlite3ExprAnd(sqlite3*,Expr*, Expr*); |
| 16209 | SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*); |
| 16210 | SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse*, Expr*, u32); |
| 16211 | SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3*, Expr*); |
| 16212 | SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*); |
| 16213 | SQLITE_PRIVATE ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*); |
| 16214 | SQLITE_PRIVATE void sqlite3ExprListSetSortOrder(ExprList*,int); |
| 16215 | SQLITE_PRIVATE void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int); |
| @@ -16989,20 +17025,17 @@ | |
| 17025 | ** If x is a lower-case ASCII character, then its upper-case equivalent |
| 17026 | ** is (x - 0x20). Therefore toupper() can be implemented as: |
| 17027 | ** |
| 17028 | ** (x & ~(map[x]&0x20)) |
| 17029 | ** |
| 17030 | ** The equivalent of tolower() is implemented using the sqlite3UpperToLower[] |
| 17031 | ** array. tolower() is used more often than toupper() by SQLite. |
| 17032 | ** |
| 17033 | ** Bit 0x40 is set if the character is non-alphanumeric and can be used in an |
| 17034 | ** SQLite identifier. Identifiers are alphanumerics, "_", "$", and any |
| 17035 | ** non-ASCII UTF character. Hence the test for whether or not a character is |
| 17036 | ** part of an identifier is 0x46. |
| 17037 | */ |
| 17038 | #ifdef SQLITE_ASCII |
| 17039 | SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[256] = { |
| 17040 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 00..07 ........ */ |
| 17041 | 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, /* 08..0f ........ */ |
| @@ -17071,11 +17104,11 @@ | |
| 17104 | #ifndef SQLITE_SORTER_PMASZ |
| 17105 | # define SQLITE_SORTER_PMASZ 250 |
| 17106 | #endif |
| 17107 | |
| 17108 | /* Statement journals spill to disk when their size exceeds the following |
| 17109 | ** threshold (in bytes). 0 means that statement journals are created and |
| 17110 | ** written to disk immediately (the default behavior for SQLite versions |
| 17111 | ** before 3.12.0). -1 means always keep the entire statement journal in |
| 17112 | ** memory. (The statement journal is also always held entirely in memory |
| 17113 | ** if journal_mode=MEMORY or if temp_store=MEMORY, regardless of this |
| 17114 | ** setting.) |
| @@ -17159,11 +17192,11 @@ | |
| 17192 | |
| 17193 | /* |
| 17194 | ** The value of the "pending" byte must be 0x40000000 (1 byte past the |
| 17195 | ** 1-gibabyte boundary) in a compatible database. SQLite never uses |
| 17196 | ** the database page that contains the pending byte. It never attempts |
| 17197 | ** to read or write that page. The pending byte page is set aside |
| 17198 | ** for use by the VFS layers as space for managing file locks. |
| 17199 | ** |
| 17200 | ** During testing, it is often desirable to move the pending byte to |
| 17201 | ** a different position in the file. This allows code that has to |
| 17202 | ** deal with the pending byte to run on files that are much smaller |
| @@ -17260,10 +17293,13 @@ | |
| 17293 | #if SQLITE_DEFAULT_LOCKING_MODE |
| 17294 | "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE), |
| 17295 | #endif |
| 17296 | #if defined(SQLITE_DEFAULT_MMAP_SIZE) && !defined(SQLITE_DEFAULT_MMAP_SIZE_xc) |
| 17297 | "DEFAULT_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_MMAP_SIZE), |
| 17298 | #endif |
| 17299 | #if SQLITE_DIRECT_OVERFLOW_READ |
| 17300 | "DIRECT_OVERFLOW_READ", |
| 17301 | #endif |
| 17302 | #if SQLITE_DISABLE_DIRSYNC |
| 17303 | "DISABLE_DIRSYNC", |
| 17304 | #endif |
| 17305 | #if SQLITE_DISABLE_LFS |
| @@ -17346,10 +17382,13 @@ | |
| 17382 | #if SQLITE_ENABLE_UNLOCK_NOTIFY |
| 17383 | "ENABLE_UNLOCK_NOTIFY", |
| 17384 | #endif |
| 17385 | #if SQLITE_ENABLE_UPDATE_DELETE_LIMIT |
| 17386 | "ENABLE_UPDATE_DELETE_LIMIT", |
| 17387 | #endif |
| 17388 | #if defined(SQLITE_ENABLE_URI_00_ERROR) |
| 17389 | "ENABLE_URI_00_ERROR", |
| 17390 | #endif |
| 17391 | #if SQLITE_HAS_CODEC |
| 17392 | "HAS_CODEC", |
| 17393 | #endif |
| 17394 | #if HAVE_ISNAN || SQLITE_HAVE_ISNAN |
| @@ -17719,13 +17758,10 @@ | |
| 17758 | typedef unsigned Bool; |
| 17759 | |
| 17760 | /* Opaque type used by code in vdbesort.c */ |
| 17761 | typedef struct VdbeSorter VdbeSorter; |
| 17762 | |
| 17763 | /* Elements of the linked list at Vdbe.pAuxData */ |
| 17764 | typedef struct AuxData AuxData; |
| 17765 | |
| 17766 | /* Types of VDBE cursors */ |
| 17767 | #define CURTYPE_BTREE 0 |
| @@ -17796,10 +17832,16 @@ | |
| 17832 | /* 2*nField extra array elements allocated for aType[], beyond the one |
| 17833 | ** static element declared in the structure. nField total array slots for |
| 17834 | ** aType[] and nField+1 array slots for aOffset[] */ |
| 17835 | }; |
| 17836 | |
| 17837 | |
| 17838 | /* |
| 17839 | ** A value for VdbeCursor.cacheStatus that means the cache is always invalid. |
| 17840 | */ |
| 17841 | #define CACHE_STALE 0 |
| 17842 | |
| 17843 | /* |
| 17844 | ** When a sub-program is executed (OP_Program), a structure of this type |
| 17845 | ** is allocated to store the current value of the program counter, as |
| 17846 | ** well as the current memory cell array and various other frame specific |
| 17847 | ** values stored in the Vdbe struct. When the sub-program is finished, |
| @@ -17840,15 +17882,10 @@ | |
| 17882 | int nDbChange; /* Value of db->nChange */ |
| 17883 | }; |
| 17884 | |
| 17885 | #define VdbeFrameMem(p) ((Mem *)&((u8 *)p)[ROUND8(sizeof(VdbeFrame))]) |
| 17886 | |
| 17887 | /* |
| 17888 | ** Internally, the vdbe manipulates nearly all SQL values as Mem |
| 17889 | ** structures. Each Mem struct may cache multiple representations (string, |
| 17890 | ** integer etc.) of the same value. |
| 17891 | */ |
| @@ -17985,22 +18022,10 @@ | |
| 18022 | u8 fErrorOrAux; /* isError!=0 or pVdbe->pAuxData modified */ |
| 18023 | u8 argc; /* Number of arguments */ |
| 18024 | sqlite3_value *argv[1]; /* Argument set */ |
| 18025 | }; |
| 18026 | |
| 18027 | /* A bitfield type for use inside of structures. Always follow with :N where |
| 18028 | ** N is the number of bits. |
| 18029 | */ |
| 18030 | typedef unsigned bft; /* Bit Field Type */ |
| 18031 | |
| @@ -18021,57 +18046,61 @@ | |
| 18046 | ** The "sqlite3_stmt" structure pointer that is returned by sqlite3_prepare() |
| 18047 | ** is really a pointer to an instance of this structure. |
| 18048 | */ |
| 18049 | struct Vdbe { |
| 18050 | sqlite3 *db; /* The database connection that owns this statement */ |
| 18051 | Vdbe *pPrev,*pNext; /* Linked list of VDBEs with the same Vdbe.db */ |
| 18052 | Parse *pParse; /* Parsing context used to create this Vdbe */ |
| 18053 | ynVar nVar; /* Number of entries in aVar[] */ |
| 18054 | ynVar nzVar; /* Number of entries in azVar[] */ |
| 18055 | u32 magic; /* Magic number for sanity checking */ |
| 18056 | int nMem; /* Number of memory locations currently allocated */ |
| 18057 | int nCursor; /* Number of slots in apCsr[] */ |
| 18058 | u32 cacheCtr; /* VdbeCursor row cache generation counter */ |
| 18059 | int pc; /* The program counter */ |
| 18060 | int rc; /* Value to return */ |
| 18061 | int nChange; /* Number of db changes made since last reset */ |
| 18062 | int iStatement; /* Statement number (or 0 if has not opened stmt) */ |
| 18063 | i64 iCurrentTime; /* Value of julianday('now') for this statement */ |
| 18064 | i64 nFkConstraint; /* Number of imm. FK constraints this VM */ |
| 18065 | i64 nStmtDefCons; /* Number of def. constraints when stmt started */ |
| 18066 | i64 nStmtDefImmCons; /* Number of def. imm constraints when stmt started */ |
| 18067 | |
| 18068 | /* When allocating a new Vdbe object, all of the fields below should be |
| 18069 | ** initialized to zero or NULL */ |
| 18070 | |
| 18071 | Op *aOp; /* Space to hold the virtual machine's program */ |
| 18072 | Mem *aMem; /* The memory locations */ |
| 18073 | Mem **apArg; /* Arguments to currently executing user function */ |
| 18074 | Mem *aColName; /* Column names to return */ |
| 18075 | Mem *pResultSet; /* Pointer to an array of results */ |
| 18076 | char *zErrMsg; /* Error message written here */ |
| 18077 | VdbeCursor **apCsr; /* One element of this array for each open cursor */ |
| 18078 | Mem *aVar; /* Values for the OP_Variable opcode. */ |
| 18079 | char **azVar; /* Name of variables */ |
| 18080 | #ifndef SQLITE_OMIT_TRACE |
| 18081 | i64 startTime; /* Time when query started - used for profiling */ |
| 18082 | #endif |
| 18083 | int nOp; /* Number of instructions in the program */ |
| 18084 | #ifdef SQLITE_DEBUG |
| 18085 | int rcApp; /* errcode set by sqlite3_result_error_code() */ |
| 18086 | #endif |
| 18087 | u16 nResColumn; /* Number of columns in one row of the result set */ |
| 18088 | u8 errorAction; /* Recovery action to do in case of an error */ |
| 18089 | u8 minWriteFileFormat; /* Minimum file format for writable database files */ |
| 18090 | bft expired:1; /* True if the VM needs to be recompiled */ |
| 18091 | bft doingRerun:1; /* True if rerunning after an auto-reprepare */ |
| 18092 | bft explain:2; /* True if EXPLAIN present on SQL command */ |
| 18093 | bft changeCntOn:1; /* True to update the change-counter */ |
| 18094 | bft runOnlyOnce:1; /* Automatically expire on reset */ |
| 18095 | bft usesStmtJournal:1; /* True if uses a statement journal */ |
| 18096 | bft readOnly:1; /* True for statements that do not write */ |
| 18097 | bft bIsReader:1; /* True for statements that read */ |
| 18098 | bft isPrepareV2:1; /* True if prepared with prepare_v2() */ |
| 18099 | yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */ |
| 18100 | yDbMask lockMask; /* Subset of btreeMask that requires a lock */ |
| 18101 | u32 aCounter[5]; /* Counters used by sqlite3_stmt_status() */ |
| 18102 | char *zSql; /* Text of the SQL statement that generated this */ |
| 18103 | void *pFree; /* Free this when deleting the vdbe */ |
| 18104 | VdbeFrame *pFrame; /* Parent frame */ |
| 18105 | VdbeFrame *pDelFrame; /* List of frame objects to free on VM reset */ |
| 18106 | int nFrame; /* Number of frames in pFrame list */ |
| @@ -18086,14 +18115,15 @@ | |
| 18115 | }; |
| 18116 | |
| 18117 | /* |
| 18118 | ** The following are allowed values for Vdbe.magic |
| 18119 | */ |
| 18120 | #define VDBE_MAGIC_INIT 0x16bceaa5 /* Building a VDBE program */ |
| 18121 | #define VDBE_MAGIC_RUN 0x2df20da3 /* VDBE is ready to execute */ |
| 18122 | #define VDBE_MAGIC_HALT 0x319c2973 /* VDBE has completed execution */ |
| 18123 | #define VDBE_MAGIC_RESET 0x48fa9f76 /* Reset and ready to run again */ |
| 18124 | #define VDBE_MAGIC_DEAD 0x5606c3c8 /* The VDBE has been deallocated */ |
| 18125 | |
| 18126 | /* |
| 18127 | ** Structure used to store the context required by the |
| 18128 | ** sqlite3_preupdate_*() API functions. |
| 18129 | */ |
| @@ -18106,12 +18136,12 @@ | |
| 18136 | UnpackedRecord *pUnpacked; /* Unpacked version of aRecord[] */ |
| 18137 | UnpackedRecord *pNewUnpacked; /* Unpacked version of new.* record */ |
| 18138 | int iNewReg; /* Register for new.* values */ |
| 18139 | i64 iKey1; /* First key value passed to hook */ |
| 18140 | i64 iKey2; /* Second key value passed to hook */ |
| 18141 | Mem *aNew; /* Array of new.* values */ |
| 18142 | Table *pTab; /* Schema object being upated */ |
| 18143 | }; |
| 18144 | |
| 18145 | /* |
| 18146 | ** Function prototypes |
| 18147 | */ |
| @@ -24599,13 +24629,12 @@ | |
| 24629 | char *zNew; |
| 24630 | size_t n; |
| 24631 | if( z==0 ){ |
| 24632 | return 0; |
| 24633 | } |
| 24634 | n = strlen(z) + 1; |
| 24635 | zNew = sqlite3DbMallocRaw(db, n); |
| 24636 | if( zNew ){ |
| 24637 | memcpy(zNew, z, n); |
| 24638 | } |
| 24639 | return zNew; |
| 24640 | } |
| @@ -28775,11 +28804,15 @@ | |
| 28804 | */ |
| 28805 | static unsigned int strHash(const char *z){ |
| 28806 | unsigned int h = 0; |
| 28807 | unsigned char c; |
| 28808 | while( (c = (unsigned char)*z++)!=0 ){ /*OPTIMIZATION-IF-TRUE*/ |
| 28809 | /* Knuth multiplicative hashing. (Sorting & Searching, p. 510). |
| 28810 | ** 0x9e3779b1 is 2654435761 which is the closest prime number to |
| 28811 | ** (2**32)*golden_ratio, where golden_ratio = (sqrt(5) - 1)/2. */ |
| 28812 | h += sqlite3UpperToLower[c]; |
| 28813 | h *= 0x9e3779b1; |
| 28814 | } |
| 28815 | return h; |
| 28816 | } |
| 28817 | |
| 28818 | |
| @@ -29124,19 +29157,19 @@ | |
| 29157 | /* 120 */ "SorterData" OpHelp("r[P2]=data"), |
| 29158 | /* 121 */ "RowKey" OpHelp("r[P2]=key"), |
| 29159 | /* 122 */ "RowData" OpHelp("r[P2]=data"), |
| 29160 | /* 123 */ "Rowid" OpHelp("r[P2]=rowid"), |
| 29161 | /* 124 */ "NullRow" OpHelp(""), |
| 29162 | /* 125 */ "SorterInsert" OpHelp("key=r[P2]"), |
| 29163 | /* 126 */ "IdxInsert" OpHelp("key=r[P2]"), |
| 29164 | /* 127 */ "IdxDelete" OpHelp("key=r[P2@P3]"), |
| 29165 | /* 128 */ "Seek" OpHelp("Move P3 to P1.rowid"), |
| 29166 | /* 129 */ "IdxRowid" OpHelp("r[P2]=rowid"), |
| 29167 | /* 130 */ "Destroy" OpHelp(""), |
| 29168 | /* 131 */ "Clear" OpHelp(""), |
| 29169 | /* 132 */ "Real" OpHelp("r[P2]=P4"), |
| 29170 | /* 133 */ "ResetSorter" OpHelp(""), |
| 29171 | /* 134 */ "CreateIndex" OpHelp("r[P2]=root iDb=P1"), |
| 29172 | /* 135 */ "CreateTable" OpHelp("r[P2]=root iDb=P1"), |
| 29173 | /* 136 */ "ParseSchema" OpHelp(""), |
| 29174 | /* 137 */ "LoadAnalysis" OpHelp(""), |
| 29175 | /* 138 */ "DropTable" OpHelp(""), |
| @@ -40671,10 +40704,16 @@ | |
| 40704 | a[1] = winIoerrRetryDelay; |
| 40705 | } |
| 40706 | OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); |
| 40707 | return SQLITE_OK; |
| 40708 | } |
| 40709 | case SQLITE_FCNTL_WIN32_GET_HANDLE: { |
| 40710 | LPHANDLE phFile = (LPHANDLE)pArg; |
| 40711 | *phFile = pFile->h; |
| 40712 | OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); |
| 40713 | return SQLITE_OK; |
| 40714 | } |
| 40715 | #ifdef SQLITE_TEST |
| 40716 | case SQLITE_FCNTL_WIN32_SET_HANDLE: { |
| 40717 | LPHANDLE phFile = (LPHANDLE)pArg; |
| 40718 | HANDLE hOldFile = pFile->h; |
| 40719 | pFile->h = *phFile; |
| @@ -44018,11 +44057,11 @@ | |
| 44057 | ){ |
| 44058 | PgHdr *pPgHdr; |
| 44059 | assert( pPage!=0 ); |
| 44060 | pPgHdr = (PgHdr*)pPage->pExtra; |
| 44061 | assert( pPgHdr->pPage==0 ); |
| 44062 | memset(&pPgHdr->pDirty, 0, sizeof(PgHdr) - offsetof(PgHdr,pDirty)); |
| 44063 | pPgHdr->pPage = pPage; |
| 44064 | pPgHdr->pData = pPage->pBuf; |
| 44065 | pPgHdr->pExtra = (void *)&pPgHdr[1]; |
| 44066 | memset(pPgHdr->pExtra, 0, pCache->szExtra); |
| 44067 | pPgHdr->pCache = pCache; |
| @@ -44712,11 +44751,11 @@ | |
| 44751 | szBulk = pCache->szAlloc * (i64)pcache1.nInitPage; |
| 44752 | }else{ |
| 44753 | szBulk = -1024 * (i64)pcache1.nInitPage; |
| 44754 | } |
| 44755 | if( szBulk > pCache->szAlloc*(i64)pCache->nMax ){ |
| 44756 | szBulk = pCache->szAlloc*(i64)pCache->nMax; |
| 44757 | } |
| 44758 | zBulk = pCache->pBulk = sqlite3Malloc( szBulk ); |
| 44759 | sqlite3EndBenignMalloc(); |
| 44760 | if( zBulk ){ |
| 44761 | int nBulk = sqlite3MallocSize(zBulk)/pCache->szAlloc; |
| @@ -46246,21 +46285,21 @@ | |
| 46285 | #define SQLITE_SYNC_MASK 0x13 /* Mask off the SQLITE_SYNC_* values */ |
| 46286 | |
| 46287 | #ifdef SQLITE_OMIT_WAL |
| 46288 | # define sqlite3WalOpen(x,y,z) 0 |
| 46289 | # define sqlite3WalLimit(x,y) |
| 46290 | # define sqlite3WalClose(v,w,x,y,z) 0 |
| 46291 | # define sqlite3WalBeginReadTransaction(y,z) 0 |
| 46292 | # define sqlite3WalEndReadTransaction(z) |
| 46293 | # define sqlite3WalDbsize(y) 0 |
| 46294 | # define sqlite3WalBeginWriteTransaction(y) 0 |
| 46295 | # define sqlite3WalEndWriteTransaction(x) 0 |
| 46296 | # define sqlite3WalUndo(x,y,z) 0 |
| 46297 | # define sqlite3WalSavepoint(y,z) |
| 46298 | # define sqlite3WalSavepointUndo(y,z) 0 |
| 46299 | # define sqlite3WalFrames(u,v,w,x,y,z) 0 |
| 46300 | # define sqlite3WalCheckpoint(q,r,s,t,u,v,w,x,y,z) 0 |
| 46301 | # define sqlite3WalCallback(z) 0 |
| 46302 | # define sqlite3WalExclusiveMode(y,z) 0 |
| 46303 | # define sqlite3WalHeapMemory(z) 0 |
| 46304 | # define sqlite3WalFramesize(z) 0 |
| 46305 | # define sqlite3WalFindFrame(x,y,z) 0 |
| @@ -46274,11 +46313,11 @@ | |
| 46313 | */ |
| 46314 | typedef struct Wal Wal; |
| 46315 | |
| 46316 | /* Open and close a connection to a write-ahead log. */ |
| 46317 | SQLITE_PRIVATE int sqlite3WalOpen(sqlite3_vfs*, sqlite3_file*, const char *, int, i64, Wal**); |
| 46318 | SQLITE_PRIVATE int sqlite3WalClose(Wal *pWal, sqlite3*, int sync_flags, int, u8 *); |
| 46319 | |
| 46320 | /* Set the limiting size of a WAL file. */ |
| 46321 | SQLITE_PRIVATE void sqlite3WalLimit(Wal*, i64); |
| 46322 | |
| 46323 | /* Used by readers to open (lock) and close (unlock) a snapshot. A |
| @@ -46317,10 +46356,11 @@ | |
| 46356 | SQLITE_PRIVATE int sqlite3WalFrames(Wal *pWal, int, PgHdr *, Pgno, int, int); |
| 46357 | |
| 46358 | /* Copy pages from the log to the database file */ |
| 46359 | SQLITE_PRIVATE int sqlite3WalCheckpoint( |
| 46360 | Wal *pWal, /* Write-ahead log connection */ |
| 46361 | sqlite3 *db, /* Check this handle's interrupt flag */ |
| 46362 | int eMode, /* One of PASSIVE, FULL and RESTART */ |
| 46363 | int (*xBusy)(void*), /* Function to call when busy */ |
| 46364 | void *pBusyArg, /* Context argument for xBusyHandler */ |
| 46365 | int sync_flags, /* Flags to sync db file with (or 0) */ |
| 46366 | int nBuf, /* Size of buffer nBuf */ |
| @@ -47161,13 +47201,14 @@ | |
| 47201 | /* |
| 47202 | ** Return true if this pager uses a write-ahead log instead of the usual |
| 47203 | ** rollback journal. Otherwise false. |
| 47204 | */ |
| 47205 | #ifndef SQLITE_OMIT_WAL |
| 47206 | SQLITE_PRIVATE int sqlite3PagerUseWal(Pager *pPager){ |
| 47207 | return (pPager->pWal!=0); |
| 47208 | } |
| 47209 | # define pagerUseWal(x) sqlite3PagerUseWal(x) |
| 47210 | #else |
| 47211 | # define pagerUseWal(x) 0 |
| 47212 | # define pagerRollbackWal(x) 0 |
| 47213 | # define pagerWalFrames(v,w,x,y) 0 |
| 47214 | # define pagerOpenWalIfPresent(z) SQLITE_OK |
| @@ -50365,21 +50406,22 @@ | |
| 50406 | ** This function always succeeds. If a transaction is active an attempt |
| 50407 | ** is made to roll it back. If an error occurs during the rollback |
| 50408 | ** a hot journal may be left in the filesystem but no error is returned |
| 50409 | ** to the caller. |
| 50410 | */ |
| 50411 | SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3 *db){ |
| 50412 | u8 *pTmp = (u8 *)pPager->pTmpSpace; |
| 50413 | |
| 50414 | assert( db || pagerUseWal(pPager)==0 ); |
| 50415 | assert( assert_pager_state(pPager) ); |
| 50416 | disable_simulated_io_errors(); |
| 50417 | sqlite3BeginBenignMalloc(); |
| 50418 | pagerFreeMapHdrs(pPager); |
| 50419 | /* pPager->errCode = 0; */ |
| 50420 | pPager->exclusiveMode = 0; |
| 50421 | #ifndef SQLITE_OMIT_WAL |
| 50422 | sqlite3WalClose(pPager->pWal,db,pPager->ckptSyncFlags,pPager->pageSize,pTmp); |
| 50423 | pPager->pWal = 0; |
| 50424 | #endif |
| 50425 | pager_reset(pPager); |
| 50426 | if( MEMDB ){ |
| 50427 | pager_unlock(pPager); |
| @@ -53538,14 +53580,20 @@ | |
| 53580 | ** "PRAGMA wal_blocking_checkpoint" or calls the sqlite3_wal_checkpoint() |
| 53581 | ** or wal_blocking_checkpoint() API functions. |
| 53582 | ** |
| 53583 | ** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART. |
| 53584 | */ |
| 53585 | SQLITE_PRIVATE int sqlite3PagerCheckpoint( |
| 53586 | Pager *pPager, /* Checkpoint on this pager */ |
| 53587 | sqlite3 *db, /* Db handle used to check for interrupts */ |
| 53588 | int eMode, /* Type of checkpoint */ |
| 53589 | int *pnLog, /* OUT: Final number of frames in log */ |
| 53590 | int *pnCkpt /* OUT: Final number of checkpointed frames */ |
| 53591 | ){ |
| 53592 | int rc = SQLITE_OK; |
| 53593 | if( pPager->pWal ){ |
| 53594 | rc = sqlite3WalCheckpoint(pPager->pWal, db, eMode, |
| 53595 | (eMode==SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler), |
| 53596 | pPager->pBusyHandlerArg, |
| 53597 | pPager->ckptSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace, |
| 53598 | pnLog, pnCkpt |
| 53599 | ); |
| @@ -53673,11 +53721,11 @@ | |
| 53721 | ** Before closing the log file, this function attempts to take an |
| 53722 | ** EXCLUSIVE lock on the database file. If this cannot be obtained, an |
| 53723 | ** error (SQLITE_BUSY) is returned and the log connection is not closed. |
| 53724 | ** If successful, the EXCLUSIVE lock is not released before returning. |
| 53725 | */ |
| 53726 | SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager, sqlite3 *db){ |
| 53727 | int rc = SQLITE_OK; |
| 53728 | |
| 53729 | assert( pPager->journalMode==PAGER_JOURNALMODE_WAL ); |
| 53730 | |
| 53731 | /* If the log file is not already open, but does exist in the file-system, |
| @@ -53701,11 +53749,11 @@ | |
| 53749 | ** the database file, the log and log-summary files will be deleted. |
| 53750 | */ |
| 53751 | if( rc==SQLITE_OK && pPager->pWal ){ |
| 53752 | rc = pagerExclusiveLock(pPager); |
| 53753 | if( rc==SQLITE_OK ){ |
| 53754 | rc = sqlite3WalClose(pPager->pWal, db, pPager->ckptSyncFlags, |
| 53755 | pPager->pageSize, (u8*)pPager->pTmpSpace); |
| 53756 | pPager->pWal = 0; |
| 53757 | pagerFixMaplimit(pPager); |
| 53758 | if( rc && !pPager->exclusiveMode ) pagerUnlockDb(pPager, SHARED_LOCK); |
| 53759 | } |
| @@ -55484,10 +55532,11 @@ | |
| 55532 | ** checkpoint is running (in any other thread or process) at the same |
| 55533 | ** time. |
| 55534 | */ |
| 55535 | static int walCheckpoint( |
| 55536 | Wal *pWal, /* Wal connection */ |
| 55537 | sqlite3 *db, /* Check for interrupts on this handle */ |
| 55538 | int eMode, /* One of PASSIVE, FULL or RESTART */ |
| 55539 | int (*xBusy)(void*), /* Function to call when busy */ |
| 55540 | void *pBusyArg, /* Context argument for xBusyHandler */ |
| 55541 | int sync_flags, /* Flags for OsSync() (or 0) */ |
| 55542 | u8 *zBuf /* Temporary buffer to use */ |
| @@ -55578,10 +55627,14 @@ | |
| 55627 | |
| 55628 | /* Iterate through the contents of the WAL, copying data to the db file */ |
| 55629 | while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){ |
| 55630 | i64 iOffset; |
| 55631 | assert( walFramePgno(pWal, iFrame)==iDbpage ); |
| 55632 | if( db->u1.isInterrupted ){ |
| 55633 | rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_INTERRUPT; |
| 55634 | break; |
| 55635 | } |
| 55636 | if( iFrame<=nBackfill || iFrame>mxSafeFrame || iDbpage>mxPage ){ |
| 55637 | continue; |
| 55638 | } |
| 55639 | iOffset = walFrameOffset(iFrame, szPage) + WAL_FRAME_HDRSIZE; |
| 55640 | /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL file */ |
| @@ -55682,10 +55735,11 @@ | |
| 55735 | /* |
| 55736 | ** Close a connection to a log file. |
| 55737 | */ |
| 55738 | SQLITE_PRIVATE int sqlite3WalClose( |
| 55739 | Wal *pWal, /* Wal to close */ |
| 55740 | sqlite3 *db, /* For interrupt flag */ |
| 55741 | int sync_flags, /* Flags to pass to OsSync() (or 0) */ |
| 55742 | int nBuf, |
| 55743 | u8 *zBuf /* Buffer of at least nBuf bytes */ |
| 55744 | ){ |
| 55745 | int rc = SQLITE_OK; |
| @@ -55698,17 +55752,18 @@ | |
| 55752 | ** the database. In this case checkpoint the database and unlink both |
| 55753 | ** the wal and wal-index files. |
| 55754 | ** |
| 55755 | ** The EXCLUSIVE lock is not released before returning. |
| 55756 | */ |
| 55757 | if( (db->flags & SQLITE_NoCkptOnClose)==0 |
| 55758 | && SQLITE_OK==(rc = sqlite3OsLock(pWal->pDbFd, SQLITE_LOCK_EXCLUSIVE)) |
| 55759 | ){ |
| 55760 | if( pWal->exclusiveMode==WAL_NORMAL_MODE ){ |
| 55761 | pWal->exclusiveMode = WAL_EXCLUSIVE_MODE; |
| 55762 | } |
| 55763 | rc = sqlite3WalCheckpoint(pWal, db, |
| 55764 | SQLITE_CHECKPOINT_PASSIVE, 0, 0, sync_flags, nBuf, zBuf, 0, 0 |
| 55765 | ); |
| 55766 | if( rc==SQLITE_OK ){ |
| 55767 | int bPersist = -1; |
| 55768 | sqlite3OsFileControlHint( |
| 55769 | pWal->pDbFd, SQLITE_FCNTL_PERSIST_WAL, &bPersist |
| @@ -56952,10 +57007,11 @@ | |
| 57007 | ** If parameter xBusy is not NULL, it is a pointer to a busy-handler |
| 57008 | ** callback. In this case this function runs a blocking checkpoint. |
| 57009 | */ |
| 57010 | SQLITE_PRIVATE int sqlite3WalCheckpoint( |
| 57011 | Wal *pWal, /* Wal connection */ |
| 57012 | sqlite3 *db, /* Check this handle's interrupt flag */ |
| 57013 | int eMode, /* PASSIVE, FULL, RESTART, or TRUNCATE */ |
| 57014 | int (*xBusy)(void*), /* Function to call when busy */ |
| 57015 | void *pBusyArg, /* Context argument for xBusyHandler */ |
| 57016 | int sync_flags, /* Flags to sync db file with (or 0) */ |
| 57017 | int nBuf, /* Size of temporary buffer */ |
| @@ -57026,11 +57082,11 @@ | |
| 57082 | if( rc==SQLITE_OK ){ |
| 57083 | |
| 57084 | if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){ |
| 57085 | rc = SQLITE_CORRUPT_BKPT; |
| 57086 | }else{ |
| 57087 | rc = walCheckpoint(pWal, db, eMode2, xBusy2, pBusyArg, sync_flags, zBuf); |
| 57088 | } |
| 57089 | |
| 57090 | /* If no error occurred, set the output variables. */ |
| 57091 | if( rc==SQLITE_OK || rc==SQLITE_BUSY ){ |
| 57092 | if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame; |
| @@ -58984,11 +59040,11 @@ | |
| 59040 | int bias, /* Bias search to the high end */ |
| 59041 | int *pRes /* Write search results here */ |
| 59042 | ){ |
| 59043 | int rc; /* Status code */ |
| 59044 | UnpackedRecord *pIdxKey; /* Unpacked index key */ |
| 59045 | char aSpace[384]; /* Temp space for pIdxKey - to avoid a malloc */ |
| 59046 | char *pFree = 0; |
| 59047 | |
| 59048 | if( pKey ){ |
| 59049 | assert( nKey==(i64)(int)nKey ); |
| 59050 | pIdxKey = sqlite3VdbeAllocUnpackedRecord( |
| @@ -60616,23 +60672,30 @@ | |
| 60672 | *ppBtree = p; |
| 60673 | |
| 60674 | btree_open_out: |
| 60675 | if( rc!=SQLITE_OK ){ |
| 60676 | if( pBt && pBt->pPager ){ |
| 60677 | sqlite3PagerClose(pBt->pPager, 0); |
| 60678 | } |
| 60679 | sqlite3_free(pBt); |
| 60680 | sqlite3_free(p); |
| 60681 | *ppBtree = 0; |
| 60682 | }else{ |
| 60683 | sqlite3_file *pFile; |
| 60684 | |
| 60685 | /* If the B-Tree was successfully opened, set the pager-cache size to the |
| 60686 | ** default value. Except, when opening on an existing shared pager-cache, |
| 60687 | ** do not change the pager-cache size. |
| 60688 | */ |
| 60689 | if( sqlite3BtreeSchema(p, 0, 0)==0 ){ |
| 60690 | sqlite3PagerSetCachesize(p->pBt->pPager, SQLITE_DEFAULT_CACHE_SIZE); |
| 60691 | } |
| 60692 | |
| 60693 | pFile = sqlite3PagerFile(pBt->pPager); |
| 60694 | if( pFile->pMethods ){ |
| 60695 | sqlite3OsFileControlHint(pFile, SQLITE_FCNTL_PDB, (void*)&pBt->db); |
| 60696 | } |
| 60697 | } |
| 60698 | if( mutexOpen ){ |
| 60699 | assert( sqlite3_mutex_held(mutexOpen) ); |
| 60700 | sqlite3_mutex_leave(mutexOpen); |
| 60701 | } |
| @@ -60758,11 +60821,11 @@ | |
| 60821 | ** it without having to hold the mutex. |
| 60822 | ** |
| 60823 | ** Clean out and delete the BtShared object. |
| 60824 | */ |
| 60825 | assert( !pBt->pCursor ); |
| 60826 | sqlite3PagerClose(pBt->pPager, p->db); |
| 60827 | if( pBt->xFreeSchema && pBt->pSchema ){ |
| 60828 | pBt->xFreeSchema(pBt->pSchema); |
| 60829 | } |
| 60830 | sqlite3DbFree(0, pBt->pSchema); |
| 60831 | freeTempSpace(pBt); |
| @@ -62822,11 +62885,11 @@ | |
| 62885 | if( (eOp&0x01)==0 /* (1) */ |
| 62886 | && offset==0 /* (2) */ |
| 62887 | && (bEnd || a==ovflSize) /* (6) */ |
| 62888 | && pBt->inTransaction==TRANS_READ /* (4) */ |
| 62889 | && (fd = sqlite3PagerFile(pBt->pPager))->pMethods /* (3) */ |
| 62890 | && 0==sqlite3PagerUseWal(pBt->pPager) /* (5) */ |
| 62891 | && &pBuf[-4]>=pBufStart /* (7) */ |
| 62892 | ){ |
| 62893 | u8 aSave[4]; |
| 62894 | u8 *aWrite = &pBuf[-4]; |
| 62895 | assert( aWrite>=pBufStart ); /* hence (7) */ |
| @@ -63078,13 +63141,16 @@ | |
| 63141 | } |
| 63142 | sqlite3BtreeClearCursor(pCur); |
| 63143 | } |
| 63144 | |
| 63145 | if( pCur->iPage>=0 ){ |
| 63146 | if( pCur->iPage ){ |
| 63147 | do{ |
| 63148 | assert( pCur->apPage[pCur->iPage]!=0 ); |
| 63149 | releasePageNotNull(pCur->apPage[pCur->iPage--]); |
| 63150 | }while( pCur->iPage); |
| 63151 | goto skip_init; |
| 63152 | } |
| 63153 | }else if( pCur->pgnoRoot==0 ){ |
| 63154 | pCur->eState = CURSOR_INVALID; |
| 63155 | return SQLITE_OK; |
| 63156 | }else{ |
| @@ -63091,11 +63157,11 @@ | |
| 63157 | assert( pCur->iPage==(-1) ); |
| 63158 | rc = getAndInitPage(pCur->pBtree->pBt, pCur->pgnoRoot, &pCur->apPage[0], |
| 63159 | 0, pCur->curPagerFlags); |
| 63160 | if( rc!=SQLITE_OK ){ |
| 63161 | pCur->eState = CURSOR_INVALID; |
| 63162 | return rc; |
| 63163 | } |
| 63164 | pCur->iPage = 0; |
| 63165 | pCur->curIntKey = pCur->apPage[0]->intKey; |
| 63166 | } |
| 63167 | pRoot = pCur->apPage[0]; |
| @@ -63114,14 +63180,16 @@ | |
| 63180 | assert( pRoot->intKey==1 || pRoot->intKey==0 ); |
| 63181 | if( pRoot->isInit==0 || (pCur->pKeyInfo==0)!=pRoot->intKey ){ |
| 63182 | return SQLITE_CORRUPT_BKPT; |
| 63183 | } |
| 63184 | |
| 63185 | skip_init: |
| 63186 | pCur->aiIdx[0] = 0; |
| 63187 | pCur->info.nSize = 0; |
| 63188 | pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidNKey|BTCF_ValidOvfl); |
| 63189 | |
| 63190 | pRoot = pCur->apPage[0]; |
| 63191 | if( pRoot->nCell>0 ){ |
| 63192 | pCur->eState = CURSOR_VALID; |
| 63193 | }else if( !pRoot->leaf ){ |
| 63194 | Pgno subpage; |
| 63195 | if( pRoot->pgno!=1 ) return SQLITE_CORRUPT_BKPT; |
| @@ -64321,12 +64389,10 @@ | |
| 64389 | nSrc = pX->nData; |
| 64390 | assert( pPage->intKeyLeaf ); /* fillInCell() only called for leaves */ |
| 64391 | nHeader += putVarint32(&pCell[nHeader], nPayload); |
| 64392 | nHeader += putVarint(&pCell[nHeader], *(u64*)&pX->nKey); |
| 64393 | }else{ |
| 64394 | assert( pX->nKey<=0x7fffffff && pX->pKey!=0 ); |
| 64395 | nSrc = nPayload = (int)pX->nKey; |
| 64396 | pSrc = pX->pKey; |
| 64397 | nHeader += putVarint32(&pCell[nHeader], nPayload); |
| 64398 | } |
| @@ -67700,11 +67766,11 @@ | |
| 67766 | BtShared *pBt = p->pBt; |
| 67767 | sqlite3BtreeEnter(p); |
| 67768 | if( pBt->inTransaction!=TRANS_NONE ){ |
| 67769 | rc = SQLITE_LOCKED; |
| 67770 | }else{ |
| 67771 | rc = sqlite3PagerCheckpoint(pBt->pPager, p->db, eMode, pnLog, pnCkpt); |
| 67772 | } |
| 67773 | sqlite3BtreeLeave(p); |
| 67774 | } |
| 67775 | return rc; |
| 67776 | } |
| @@ -68022,26 +68088,20 @@ | |
| 68088 | */ |
| 68089 | static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){ |
| 68090 | int i = sqlite3FindDbName(pDb, zDb); |
| 68091 | |
| 68092 | if( i==1 ){ |
| 68093 | Parse sParse; |
| 68094 | int rc = 0; |
| 68095 | memset(&sParse, 0, sizeof(sParse)); |
| 68096 | sParse.db = pDb; |
| 68097 | if( sqlite3OpenTempDatabase(&sParse) ){ |
| 68098 | sqlite3ErrorWithMsg(pErrorDb, sParse.rc, "%s", sParse.zErrMsg); |
| 68099 | rc = SQLITE_ERROR; |
| 68100 | } |
| 68101 | sqlite3DbFree(pErrorDb, sParse.zErrMsg); |
| 68102 | sqlite3ParserReset(&sParse); |
| 68103 | if( rc ){ |
| 68104 | return 0; |
| 68105 | } |
| 68106 | } |
| 68107 | |
| @@ -69041,10 +69101,11 @@ | |
| 69101 | assert( (pMem->flags&MEM_RowSet)==0 ); |
| 69102 | assert( EIGHT_BYTE_ALIGNMENT(pMem) ); |
| 69103 | |
| 69104 | |
| 69105 | if( sqlite3VdbeMemClearAndResize(pMem, nByte) ){ |
| 69106 | pMem->enc = 0; |
| 69107 | return SQLITE_NOMEM_BKPT; |
| 69108 | } |
| 69109 | |
| 69110 | /* For a Real or Integer, use sqlite3_snprintf() to produce the UTF-8 |
| 69111 | ** string representation of the value. Then, if the required encoding |
| @@ -69340,11 +69401,11 @@ | |
| 69401 | switch( aff ){ |
| 69402 | case SQLITE_AFF_BLOB: { /* Really a cast to BLOB */ |
| 69403 | if( (pMem->flags & MEM_Blob)==0 ){ |
| 69404 | sqlite3ValueApplyAffinity(pMem, SQLITE_AFF_TEXT, encoding); |
| 69405 | assert( pMem->flags & MEM_Str || pMem->db->mallocFailed ); |
| 69406 | if( pMem->flags & MEM_Str ) MemSetTypeFlag(pMem, MEM_Blob); |
| 69407 | }else{ |
| 69408 | pMem->flags &= ~(MEM_TypeMask&~MEM_Blob); |
| 69409 | } |
| 69410 | break; |
| 69411 | } |
| @@ -70017,14 +70078,11 @@ | |
| 70078 | sqlite3_value *pVal = 0; |
| 70079 | int negInt = 1; |
| 70080 | const char *zNeg = ""; |
| 70081 | int rc = SQLITE_OK; |
| 70082 | |
| 70083 | assert( pExpr!=0 ); |
| 70084 | while( (op = pExpr->op)==TK_UPLUS || op==TK_SPAN ) pExpr = pExpr->pLeft; |
| 70085 | if( NEVER(op==TK_REGISTER) ) op = pExpr->op2; |
| 70086 | |
| 70087 | /* Compressed expressions only appear when parsing the DEFAULT clause |
| 70088 | ** on a table column definition, and hence only when pCtx==0. This |
| @@ -70144,11 +70202,11 @@ | |
| 70202 | Expr *pExpr, /* The expression to evaluate */ |
| 70203 | u8 enc, /* Encoding to use */ |
| 70204 | u8 affinity, /* Affinity to use */ |
| 70205 | sqlite3_value **ppVal /* Write the new value here */ |
| 70206 | ){ |
| 70207 | return pExpr ? valueFromExpr(db, pExpr, enc, affinity, ppVal, 0) : 0; |
| 70208 | } |
| 70209 | |
| 70210 | #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 |
| 70211 | /* |
| 70212 | ** The implementation of the sqlite_record() function. This function accepts |
| @@ -70487,12 +70545,13 @@ | |
| 70545 | ** Create a new virtual database engine. |
| 70546 | */ |
| 70547 | SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(Parse *pParse){ |
| 70548 | sqlite3 *db = pParse->db; |
| 70549 | Vdbe *p; |
| 70550 | p = sqlite3DbMallocRawNN(db, sizeof(Vdbe) ); |
| 70551 | if( p==0 ) return 0; |
| 70552 | memset(&p->aOp, 0, sizeof(Vdbe)-offsetof(Vdbe,aOp)); |
| 70553 | p->db = db; |
| 70554 | if( db->pVdbe ){ |
| 70555 | db->pVdbe->pPrev = p; |
| 70556 | } |
| 70557 | p->pNext = db->pVdbe; |
| @@ -70650,13 +70709,12 @@ | |
| 70709 | #endif |
| 70710 | #ifdef SQLITE_DEBUG |
| 70711 | if( p->db->flags & SQLITE_VdbeAddopTrace ){ |
| 70712 | int jj, kk; |
| 70713 | Parse *pParse = p->pParse; |
| 70714 | for(jj=kk=0; jj<pParse->nColCache; jj++){ |
| 70715 | struct yColCache *x = pParse->aColCache + jj; |
| 70716 | printf(" r[%d]={%d:%d}", x->iReg, x->iTable, x->iColumn); |
| 70717 | kk++; |
| 70718 | } |
| 70719 | if( kk ) printf("\n"); |
| 70720 | sqlite3VdbePrintOp(0, i, &p->aOp[i]); |
| @@ -70840,11 +70898,10 @@ | |
| 70898 | assert( j<p->nLabel ); |
| 70899 | assert( j>=0 ); |
| 70900 | if( p->aLabel ){ |
| 70901 | p->aLabel[j] = v->nOp; |
| 70902 | } |
| 70903 | } |
| 70904 | |
| 70905 | /* |
| 70906 | ** Mark the VDBE as one that can only be run one time. |
| 70907 | */ |
| @@ -71231,19 +71288,19 @@ | |
| 71288 | } |
| 71289 | SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe *p, u32 addr, int val){ |
| 71290 | sqlite3VdbeGetOp(p,addr)->p3 = val; |
| 71291 | } |
| 71292 | SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe *p, u8 p5){ |
| 71293 | assert( p->nOp>0 || p->db->mallocFailed ); |
| 71294 | if( p->nOp>0 ) p->aOp[p->nOp-1].p5 = p5; |
| 71295 | } |
| 71296 | |
| 71297 | /* |
| 71298 | ** Change the P2 operand of instruction addr so that it points to |
| 71299 | ** the address of the next instruction to be coded. |
| 71300 | */ |
| 71301 | SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe *p, int addr){ |
| 71302 | sqlite3VdbeChangeP2(p, addr, p->nOp); |
| 71303 | } |
| 71304 | |
| 71305 | |
| 71306 | /* |
| @@ -71362,11 +71419,11 @@ | |
| 71419 | /* |
| 71420 | ** If the last opcode is "op" and it is not a jump destination, |
| 71421 | ** then remove it. Return true if and only if an opcode was removed. |
| 71422 | */ |
| 71423 | SQLITE_PRIVATE int sqlite3VdbeDeletePriorOpcode(Vdbe *p, u8 op){ |
| 71424 | if( p->nOp>0 && p->aOp[p->nOp-1].opcode==op ){ |
| 71425 | return sqlite3VdbeChangeToNoop(p, p->nOp-1); |
| 71426 | }else{ |
| 71427 | return 0; |
| 71428 | } |
| 71429 | } |
| @@ -71924,10 +71981,25 @@ | |
| 71981 | zCom |
| 71982 | ); |
| 71983 | fflush(pOut); |
| 71984 | } |
| 71985 | #endif |
| 71986 | |
| 71987 | /* |
| 71988 | ** Initialize an array of N Mem element. |
| 71989 | */ |
| 71990 | static void initMemArray(Mem *p, int N, sqlite3 *db, u16 flags){ |
| 71991 | while( (N--)>0 ){ |
| 71992 | p->db = db; |
| 71993 | p->flags = flags; |
| 71994 | p->szMalloc = 0; |
| 71995 | #ifdef SQLITE_DEBUG |
| 71996 | p->pScopyFrom = 0; |
| 71997 | #endif |
| 71998 | p++; |
| 71999 | } |
| 72000 | } |
| 72001 | |
| 72002 | /* |
| 72003 | ** Release an array of N Mem elements |
| 72004 | */ |
| 72005 | static void releaseMemArray(Mem *p, int N){ |
| @@ -72136,10 +72208,11 @@ | |
| 72208 | return SQLITE_ERROR; |
| 72209 | } |
| 72210 | pMem->flags = MEM_Str|MEM_Term; |
| 72211 | zP4 = displayP4(pOp, pMem->z, pMem->szMalloc); |
| 72212 | if( zP4!=pMem->z ){ |
| 72213 | pMem->n = 0; |
| 72214 | sqlite3VdbeMemSetStr(pMem, zP4, -1, SQLITE_UTF8, 0); |
| 72215 | }else{ |
| 72216 | assert( pMem->z!=0 ); |
| 72217 | pMem->n = sqlite3Strlen30(pMem->z); |
| 72218 | pMem->enc = SQLITE_UTF8; |
| @@ -72278,11 +72351,11 @@ | |
| 72351 | SQLITE_PRIVATE void sqlite3VdbeRewind(Vdbe *p){ |
| 72352 | #if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) |
| 72353 | int i; |
| 72354 | #endif |
| 72355 | assert( p!=0 ); |
| 72356 | assert( p->magic==VDBE_MAGIC_INIT || p->magic==VDBE_MAGIC_RESET ); |
| 72357 | |
| 72358 | /* There should be at least one opcode. |
| 72359 | */ |
| 72360 | assert( p->nOp>0 ); |
| 72361 | |
| @@ -72367,14 +72440,11 @@ | |
| 72440 | n = ROUND8(sizeof(Op)*p->nOp); /* Bytes of opcode memory used */ |
| 72441 | x.pSpace = &((u8*)p->aOp)[n]; /* Unused opcode memory */ |
| 72442 | assert( EIGHT_BYTE_ALIGNMENT(x.pSpace) ); |
| 72443 | x.nFree = ROUNDDOWN8(pParse->szOpAlloc - n); /* Bytes of unused memory */ |
| 72444 | assert( x.nFree>=0 ); |
| 72445 | assert( EIGHT_BYTE_ALIGNMENT(&x.pSpace[x.nFree]) ); |
| 72446 | |
| 72447 | resolveP2Values(p, &nArg); |
| 72448 | p->usesStmtJournal = (u8)(pParse->isMultiWrite && pParse->mayAbort); |
| 72449 | if( pParse->explain && nMem<10 ){ |
| 72450 | nMem = 10; |
| @@ -72399,34 +72469,34 @@ | |
| 72469 | p->apCsr = allocSpace(&x, p->apCsr, nCursor*sizeof(VdbeCursor*)); |
| 72470 | #ifdef SQLITE_ENABLE_STMT_SCANSTATUS |
| 72471 | p->anExec = allocSpace(&x, p->anExec, p->nOp*sizeof(i64)); |
| 72472 | #endif |
| 72473 | if( x.nNeeded==0 ) break; |
| 72474 | x.pSpace = p->pFree = sqlite3DbMallocRawNN(db, x.nNeeded); |
| 72475 | x.nFree = x.nNeeded; |
| 72476 | }while( !db->mallocFailed ); |
| 72477 | |
| 72478 | p->nzVar = pParse->nzVar; |
| 72479 | p->azVar = pParse->azVar; |
| 72480 | pParse->nzVar = 0; |
| 72481 | pParse->azVar = 0; |
| 72482 | p->explain = pParse->explain; |
| 72483 | if( db->mallocFailed ){ |
| 72484 | p->nVar = 0; |
| 72485 | p->nCursor = 0; |
| 72486 | p->nMem = 0; |
| 72487 | }else{ |
| 72488 | p->nCursor = nCursor; |
| 72489 | p->nVar = (ynVar)nVar; |
| 72490 | initMemArray(p->aVar, nVar, db, MEM_Null); |
| 72491 | p->nMem = nMem; |
| 72492 | initMemArray(p->aMem, nMem, db, MEM_Undefined); |
| 72493 | memset(p->apCsr, 0, nCursor*sizeof(VdbeCursor*)); |
| 72494 | #ifdef SQLITE_ENABLE_STMT_SCANSTATUS |
| 72495 | memset(p->anExec, 0, p->nOp*sizeof(i64)); |
| 72496 | #endif |
| 72497 | } |
| 72498 | sqlite3VdbeRewind(p); |
| 72499 | } |
| 72500 | |
| 72501 | /* |
| 72502 | ** Close a VDBE cursor and release all the resources that cursor |
| @@ -72574,17 +72644,13 @@ | |
| 72644 | |
| 72645 | releaseMemArray(p->aColName, p->nResColumn*COLNAME_N); |
| 72646 | sqlite3DbFree(db, p->aColName); |
| 72647 | n = nResColumn*COLNAME_N; |
| 72648 | p->nResColumn = (u16)nResColumn; |
| 72649 | p->aColName = pColName = (Mem*)sqlite3DbMallocRawNN(db, sizeof(Mem)*n ); |
| 72650 | if( p->aColName==0 ) return; |
| 72651 | initMemArray(p->aColName, n, p->db, MEM_Null); |
| 72652 | } |
| 72653 | |
| 72654 | /* |
| 72655 | ** Set the name of the idx'th column to be returned by the SQL statement. |
| 72656 | ** zName must be a pointer to a nul terminated string. |
| @@ -73342,11 +73408,11 @@ | |
| 73408 | fclose(out); |
| 73409 | } |
| 73410 | } |
| 73411 | #endif |
| 73412 | p->iCurrentTime = 0; |
| 73413 | p->magic = VDBE_MAGIC_RESET; |
| 73414 | return p->rc & db->errMask; |
| 73415 | } |
| 73416 | |
| 73417 | /* |
| 73418 | ** Clean up and delete a VDBE after execution. Return an integer which is |
| @@ -73406,23 +73472,25 @@ | |
| 73472 | */ |
| 73473 | SQLITE_PRIVATE void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){ |
| 73474 | SubProgram *pSub, *pNext; |
| 73475 | int i; |
| 73476 | assert( p->db==0 || p->db==db ); |
| 73477 | releaseMemArray(p->aColName, p->nResColumn*COLNAME_N); |
| 73478 | for(pSub=p->pProgram; pSub; pSub=pNext){ |
| 73479 | pNext = pSub->pNext; |
| 73480 | vdbeFreeOpArray(db, pSub->aOp, pSub->nOp); |
| 73481 | sqlite3DbFree(db, pSub); |
| 73482 | } |
| 73483 | if( p->magic!=VDBE_MAGIC_INIT ){ |
| 73484 | releaseMemArray(p->aVar, p->nVar); |
| 73485 | for(i=p->nzVar-1; i>=0; i--) sqlite3DbFree(db, p->azVar[i]); |
| 73486 | sqlite3DbFree(db, p->azVar); |
| 73487 | sqlite3DbFree(db, p->pFree); |
| 73488 | } |
| 73489 | vdbeFreeOpArray(db, p->aOp, p->nOp); |
| 73490 | sqlite3DbFree(db, p->aColName); |
| 73491 | sqlite3DbFree(db, p->zSql); |
| 73492 | #ifdef SQLITE_ENABLE_STMT_SCANSTATUS |
| 73493 | for(i=0; i<p->nScan; i++){ |
| 73494 | sqlite3DbFree(db, p->aScan[i].zName); |
| 73495 | } |
| 73496 | sqlite3DbFree(db, p->aScan); |
| @@ -75073,11 +75141,11 @@ | |
| 75141 | preupdate.keyinfo.enc = ENC(db); |
| 75142 | preupdate.keyinfo.nField = pTab->nCol; |
| 75143 | preupdate.keyinfo.aSortOrder = (u8*)&fakeSortOrder; |
| 75144 | preupdate.iKey1 = iKey1; |
| 75145 | preupdate.iKey2 = iKey2; |
| 75146 | preupdate.pTab = pTab; |
| 75147 | |
| 75148 | db->pPreUpdate = &preupdate; |
| 75149 | db->xPreUpdateCallback(db->pPreUpdateArg, db, op, zDb, zTbl, iKey1, iKey2); |
| 75150 | db->pPreUpdate = 0; |
| 75151 | sqlite3DbFree(db, preupdate.aRecord); |
| @@ -76047,18 +76115,17 @@ | |
| 76115 | static Mem *columnMem(sqlite3_stmt *pStmt, int i){ |
| 76116 | Vdbe *pVm; |
| 76117 | Mem *pOut; |
| 76118 | |
| 76119 | pVm = (Vdbe *)pStmt; |
| 76120 | if( pVm==0 ) return (Mem*)columnNullValue(); |
| 76121 | assert( pVm->db ); |
| 76122 | sqlite3_mutex_enter(pVm->db->mutex); |
| 76123 | if( pVm->pResultSet!=0 && i<pVm->nResColumn && i>=0 ){ |
| 76124 | pOut = &pVm->pResultSet[i]; |
| 76125 | }else{ |
| 76126 | sqlite3Error(pVm->db, SQLITE_RANGE); |
| 76127 | pOut = (Mem*)columnNullValue(); |
| 76128 | } |
| 76129 | return pOut; |
| 76130 | } |
| 76131 | |
| @@ -76087,10 +76154,12 @@ | |
| 76154 | ** SQLITE_NOMEM. The next call to _step() (if any) will return SQLITE_ERROR |
| 76155 | ** and _finalize() will return NOMEM. |
| 76156 | */ |
| 76157 | Vdbe *p = (Vdbe *)pStmt; |
| 76158 | if( p ){ |
| 76159 | assert( p->db!=0 ); |
| 76160 | assert( sqlite3_mutex_held(p->db->mutex) ); |
| 76161 | p->rc = sqlite3ApiExit(p->db, p->rc); |
| 76162 | sqlite3_mutex_leave(p->db->mutex); |
| 76163 | } |
| 76164 | } |
| 76165 | |
| @@ -76663,11 +76732,11 @@ | |
| 76732 | /* |
| 76733 | ** Return true if the prepared statement is in need of being reset. |
| 76734 | */ |
| 76735 | SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt *pStmt){ |
| 76736 | Vdbe *v = (Vdbe*)pStmt; |
| 76737 | return v!=0 && v->magic==VDBE_MAGIC_RUN && v->pc>=0; |
| 76738 | } |
| 76739 | |
| 76740 | /* |
| 76741 | ** Return a pointer to the next prepared statement after pStmt associated |
| 76742 | ** with database connection pDb. If pStmt is NULL, return the first |
| @@ -76804,13 +76873,18 @@ | |
| 76873 | } |
| 76874 | |
| 76875 | if( iIdx>=p->pUnpacked->nField ){ |
| 76876 | *ppValue = (sqlite3_value *)columnNullValue(); |
| 76877 | }else{ |
| 76878 | Mem *pMem = *ppValue = &p->pUnpacked->aMem[iIdx]; |
| 76879 | *ppValue = &p->pUnpacked->aMem[iIdx]; |
| 76880 | if( iIdx==p->pTab->iPKey ){ |
| 76881 | sqlite3VdbeMemSetInt64(pMem, p->iKey1); |
| 76882 | }else if( p->pTab->aCol[iIdx].affinity==SQLITE_AFF_REAL ){ |
| 76883 | if( pMem->flags & MEM_Int ){ |
| 76884 | sqlite3VdbeMemRealify(pMem); |
| 76885 | } |
| 76886 | } |
| 76887 | } |
| 76888 | |
| 76889 | preupdate_old_out: |
| 76890 | sqlite3Error(db, rc); |
| @@ -76883,11 +76957,11 @@ | |
| 76957 | } |
| 76958 | if( iIdx>=pUnpack->nField ){ |
| 76959 | pMem = (sqlite3_value *)columnNullValue(); |
| 76960 | }else{ |
| 76961 | pMem = &pUnpack->aMem[iIdx]; |
| 76962 | if( iIdx==p->pTab->iPKey ){ |
| 76963 | sqlite3VdbeMemSetInt64(pMem, p->iKey2); |
| 76964 | } |
| 76965 | } |
| 76966 | }else{ |
| 76967 | /* For an UPDATE, memory cell (p->iNewReg+1+iIdx) contains the required |
| @@ -76904,11 +76978,11 @@ | |
| 76978 | } |
| 76979 | } |
| 76980 | assert( iIdx>=0 && iIdx<p->pCsr->nField ); |
| 76981 | pMem = &p->aNew[iIdx]; |
| 76982 | if( pMem->flags==0 ){ |
| 76983 | if( iIdx==p->pTab->iPKey ){ |
| 76984 | sqlite3VdbeMemSetInt64(pMem, p->iKey2); |
| 76985 | }else{ |
| 76986 | rc = sqlite3VdbeMemCopy(pMem, &p->v->aMem[p->iNewReg+1+iIdx]); |
| 76987 | if( rc!=SQLITE_OK ) goto preupdate_new_out; |
| 76988 | } |
| @@ -78415,15 +78489,17 @@ | |
| 78489 | u16 nullFlag; |
| 78490 | pOut = out2Prerelease(p, pOp); |
| 78491 | cnt = pOp->p3-pOp->p2; |
| 78492 | assert( pOp->p3<=(p->nMem+1 - p->nCursor) ); |
| 78493 | pOut->flags = nullFlag = pOp->p1 ? (MEM_Null|MEM_Cleared) : MEM_Null; |
| 78494 | pOut->n = 0; |
| 78495 | while( cnt>0 ){ |
| 78496 | pOut++; |
| 78497 | memAboutToChange(p, pOut); |
| 78498 | sqlite3VdbeMemSetNull(pOut); |
| 78499 | pOut->flags = nullFlag; |
| 78500 | pOut->n = 0; |
| 78501 | cnt--; |
| 78502 | } |
| 78503 | break; |
| 78504 | } |
| 78505 | |
| @@ -79280,12 +79356,11 @@ | |
| 79356 | ** or not both operands are null. |
| 79357 | */ |
| 79358 | assert( pOp->opcode==OP_Eq || pOp->opcode==OP_Ne ); |
| 79359 | assert( (flags1 & MEM_Cleared)==0 ); |
| 79360 | assert( (pOp->p5 & SQLITE_JUMPIFNULL)==0 ); |
| 79361 | if( (flags1&flags3&MEM_Null)!=0 |
| 79362 | && (flags3&MEM_Cleared)==0 |
| 79363 | ){ |
| 79364 | res = 0; /* Operands are equal */ |
| 79365 | }else{ |
| 79366 | res = 1; /* Operands are not equal */ |
| @@ -80487,14 +80562,13 @@ | |
| 80562 | p->nStmtDefCons = db->nDeferredCons; |
| 80563 | p->nStmtDefImmCons = db->nDeferredImmCons; |
| 80564 | } |
| 80565 | |
| 80566 | /* Gather the schema version number for checking: |
| 80567 | ** IMPLEMENTATION-OF: R-03189-51135 As each SQL statement runs, the schema |
| 80568 | ** version is checked to ensure that the schema has not changed since the |
| 80569 | ** SQL statement was prepared. |
| 80570 | */ |
| 80571 | sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&iMeta); |
| 80572 | iGen = db->aDb[pOp->p1].pSchema->iGeneration; |
| 80573 | }else{ |
| 80574 | iGen = iMeta = 0; |
| @@ -81549,11 +81623,11 @@ | |
| 81623 | |
| 81624 | REGISTER_TRACE(pOp->p3, pMem); |
| 81625 | sqlite3VdbeMemIntegerify(pMem); |
| 81626 | assert( (pMem->flags & MEM_Int)!=0 ); /* mem(P3) holds an integer */ |
| 81627 | if( pMem->u.i==MAX_ROWID || pC->useRandomRowid ){ |
| 81628 | rc = SQLITE_FULL; /* IMP: R-17817-00630 */ |
| 81629 | goto abort_due_to_error; |
| 81630 | } |
| 81631 | if( v<pMem->u.i+1 ){ |
| 81632 | v = pMem->u.i + 1; |
| 81633 | } |
| @@ -81746,11 +81820,11 @@ | |
| 81820 | ** change count is incremented (otherwise not). |
| 81821 | ** |
| 81822 | ** P1 must not be pseudo-table. It has to be a real table with |
| 81823 | ** multiple rows. |
| 81824 | ** |
| 81825 | ** If P4 is not NULL then it points to a Table object. In this case either |
| 81826 | ** the update or pre-update hook, or both, may be invoked. The P1 cursor must |
| 81827 | ** have been positioned using OP_NotFound prior to invoking this opcode in |
| 81828 | ** this case. Specifically, if one is configured, the pre-update hook is |
| 81829 | ** invoked if P4 is not NULL. The update-hook is invoked if one is configured, |
| 81830 | ** P4 is not NULL, and the OPFLAG_NCHANGE flag is set in P2. |
| @@ -82316,10 +82390,17 @@ | |
| 82390 | ** This flag avoids doing an extra seek. |
| 82391 | ** |
| 82392 | ** This instruction only works for indices. The equivalent instruction |
| 82393 | ** for tables is OP_Insert. |
| 82394 | */ |
| 82395 | /* Opcode: SorterInsert P1 P2 * * * |
| 82396 | ** Synopsis: key=r[P2] |
| 82397 | ** |
| 82398 | ** Register P2 holds an SQL index key made using the |
| 82399 | ** MakeRecord instructions. This opcode writes that key |
| 82400 | ** into the sorter P1. Data for the entry is nil. |
| 82401 | */ |
| 82402 | case OP_SorterInsert: /* in2 */ |
| 82403 | case OP_IdxInsert: { /* in2 */ |
| 82404 | VdbeCursor *pC; |
| 82405 | BtreePayload x; |
| 82406 | |
| @@ -82337,13 +82418,10 @@ | |
| 82418 | if( pOp->opcode==OP_SorterInsert ){ |
| 82419 | rc = sqlite3VdbeSorterWrite(pC, pIn2); |
| 82420 | }else{ |
| 82421 | x.nKey = pIn2->n; |
| 82422 | x.pKey = pIn2->z; |
| 82423 | rc = sqlite3BtreeInsert(pC->uc.pCursor, &x, pOp->p3, |
| 82424 | ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0) |
| 82425 | ); |
| 82426 | assert( pC->deferredMoveto==0 ); |
| 82427 | pC->cacheStatus = CACHE_STALE; |
| @@ -83547,11 +83625,11 @@ | |
| 83625 | /* If leaving WAL mode, close the log file. If successful, the call |
| 83626 | ** to PagerCloseWal() checkpoints and deletes the write-ahead-log |
| 83627 | ** file. An EXCLUSIVE lock may still be held on the database file |
| 83628 | ** after a successful return. |
| 83629 | */ |
| 83630 | rc = sqlite3PagerCloseWal(pPager, db); |
| 83631 | if( rc==SQLITE_OK ){ |
| 83632 | sqlite3PagerSetJournalMode(pPager, eNew); |
| 83633 | } |
| 83634 | }else if( eOld==PAGER_JOURNALMODE_MEMORY ){ |
| 83635 | /* Cannot transition directly from MEMORY to WAL. Use mode OFF |
| @@ -88036,11 +88114,13 @@ | |
| 88114 | static SQLITE_NOINLINE int walkExpr(Walker *pWalker, Expr *pExpr){ |
| 88115 | int rc; |
| 88116 | testcase( ExprHasProperty(pExpr, EP_TokenOnly) ); |
| 88117 | testcase( ExprHasProperty(pExpr, EP_Reduced) ); |
| 88118 | rc = pWalker->xExprCallback(pWalker, pExpr); |
| 88119 | if( rc || ExprHasProperty(pExpr,(EP_TokenOnly|EP_Leaf)) ){ |
| 88120 | return rc & WRC_Abort; |
| 88121 | } |
| 88122 | if( pExpr->pLeft && walkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort; |
| 88123 | if( pExpr->pRight && walkExpr(pWalker, pExpr->pRight) ) return WRC_Abort; |
| 88124 | if( ExprHasProperty(pExpr, EP_xIsSelect) ){ |
| 88125 | if( sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort; |
| 88126 | }else if( pExpr->x.pList ){ |
| @@ -88780,11 +88860,10 @@ | |
| 88860 | const char *zDb; |
| 88861 | Expr *pRight; |
| 88862 | |
| 88863 | /* if( pSrcList==0 ) break; */ |
| 88864 | notValid(pParse, pNC, "the \".\" operator", NC_IdxExpr); |
| 88865 | pRight = pExpr->pRight; |
| 88866 | if( pRight->op==TK_ID ){ |
| 88867 | zDb = 0; |
| 88868 | zTable = pExpr->pLeft->u.zToken; |
| 88869 | zColumn = pRight->u.zToken; |
| @@ -88809,11 +88888,10 @@ | |
| 88888 | const char *zId; /* The function name. */ |
| 88889 | FuncDef *pDef; /* Information about the function */ |
| 88890 | u8 enc = ENC(pParse->db); /* The database encoding */ |
| 88891 | |
| 88892 | assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); |
| 88893 | zId = pExpr->u.zToken; |
| 88894 | nId = sqlite3Strlen30(zId); |
| 88895 | pDef = sqlite3FindFunction(pParse->db, zId, n, enc, 0); |
| 88896 | if( pDef==0 ){ |
| 88897 | pDef = sqlite3FindFunction(pParse->db, zId, -2, enc, 0); |
| @@ -88869,11 +88947,12 @@ | |
| 88947 | } |
| 88948 | if( (pDef->funcFlags & SQLITE_FUNC_CONSTANT)==0 ){ |
| 88949 | /* Date/time functions that use 'now', and other functions like |
| 88950 | ** sqlite_version() that might change over time cannot be used |
| 88951 | ** in an index. */ |
| 88952 | notValid(pParse, pNC, "non-deterministic functions", |
| 88953 | NC_IdxExpr|NC_PartIdx); |
| 88954 | } |
| 88955 | } |
| 88956 | if( is_agg && (pNC->ncFlags & NC_AllowAgg)==0 ){ |
| 88957 | sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId); |
| 88958 | pNC->nErr++; |
| @@ -90409,11 +90488,11 @@ | |
| 90488 | ** stored in u.zToken. Instead, the integer values is written |
| 90489 | ** into u.iValue and the EP_IntValue flag is set. No extra storage |
| 90490 | ** is allocated to hold the integer text and the dequote flag is ignored. |
| 90491 | */ |
| 90492 | SQLITE_PRIVATE Expr *sqlite3ExprAlloc( |
| 90493 | sqlite3 *db, /* Handle for sqlite3DbMallocRawNN() */ |
| 90494 | int op, /* Expression opcode */ |
| 90495 | const Token *pToken, /* Token argument. Might be NULL */ |
| 90496 | int dequote /* True to dequote */ |
| 90497 | ){ |
| 90498 | Expr *pNew; |
| @@ -90627,40 +90706,40 @@ | |
| 90706 | ** Wildcards of the form ":aaa", "@aaa", or "$aaa" are assigned the same number |
| 90707 | ** as the previous instance of the same wildcard. Or if this is the first |
| 90708 | ** instance of the wildcard, the next sequential variable number is |
| 90709 | ** assigned. |
| 90710 | */ |
| 90711 | SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr, u32 n){ |
| 90712 | sqlite3 *db = pParse->db; |
| 90713 | const char *z; |
| 90714 | |
| 90715 | if( pExpr==0 ) return; |
| 90716 | assert( !ExprHasProperty(pExpr, EP_IntValue|EP_Reduced|EP_TokenOnly) ); |
| 90717 | z = pExpr->u.zToken; |
| 90718 | assert( z!=0 ); |
| 90719 | assert( z[0]!=0 ); |
| 90720 | assert( n==sqlite3Strlen30(z) ); |
| 90721 | if( z[1]==0 ){ |
| 90722 | /* Wildcard of the form "?". Assign the next variable number */ |
| 90723 | assert( z[0]=='?' ); |
| 90724 | pExpr->iColumn = (ynVar)(++pParse->nVar); |
| 90725 | }else{ |
| 90726 | ynVar x; |
| 90727 | if( z[0]=='?' ){ |
| 90728 | /* Wildcard of the form "?nnn". Convert "nnn" to an integer and |
| 90729 | ** use it as the variable number */ |
| 90730 | i64 i; |
| 90731 | int bOk = 0==sqlite3Atoi64(&z[1], &i, n-1, SQLITE_UTF8); |
| 90732 | x = (ynVar)i; |
| 90733 | testcase( i==0 ); |
| 90734 | testcase( i==1 ); |
| 90735 | testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]-1 ); |
| 90736 | testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ); |
| 90737 | if( bOk==0 || i<1 || i>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){ |
| 90738 | sqlite3ErrorMsg(pParse, "variable number must be between ?1 and ?%d", |
| 90739 | db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]); |
| 90740 | return; |
| 90741 | } |
| 90742 | if( i>pParse->nVar ){ |
| 90743 | pParse->nVar = (int)i; |
| 90744 | } |
| 90745 | }else{ |
| @@ -90667,37 +90746,35 @@ | |
| 90746 | /* Wildcards like ":aaa", "$aaa" or "@aaa". Reuse the same variable |
| 90747 | ** number as the prior appearance of the same name, or if the name |
| 90748 | ** has never appeared before, reuse the same variable number |
| 90749 | */ |
| 90750 | ynVar i; |
| 90751 | for(i=x=0; i<pParse->nzVar; i++){ |
| 90752 | if( pParse->azVar[i] && strcmp(pParse->azVar[i],z)==0 ){ |
| 90753 | x = (ynVar)i+1; |
| 90754 | break; |
| 90755 | } |
| 90756 | } |
| 90757 | if( x==0 ) x = (ynVar)(++pParse->nVar); |
| 90758 | } |
| 90759 | pExpr->iColumn = x; |
| 90760 | if( x>pParse->nzVar ){ |
| 90761 | char **a; |
| 90762 | a = sqlite3DbRealloc(db, pParse->azVar, x*sizeof(a[0])); |
| 90763 | if( a==0 ){ |
| 90764 | assert( db->mallocFailed ); /* Error reported through mallocFailed */ |
| 90765 | return; |
| 90766 | } |
| 90767 | pParse->azVar = a; |
| 90768 | memset(&a[pParse->nzVar], 0, (x-pParse->nzVar)*sizeof(a[0])); |
| 90769 | pParse->nzVar = x; |
| 90770 | } |
| 90771 | if( pParse->azVar[x-1]==0 ){ |
| 90772 | pParse->azVar[x-1] = sqlite3DbStrNDup(db, z, n); |
| 90773 | } |
| 90774 | } |
| 90775 | if( pParse->nVar>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){ |
| 90776 | sqlite3ErrorMsg(pParse, "too many SQL variables"); |
| 90777 | } |
| 90778 | } |
| 90779 | |
| 90780 | /* |
| @@ -90705,22 +90782,29 @@ | |
| 90782 | */ |
| 90783 | static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){ |
| 90784 | assert( p!=0 ); |
| 90785 | /* Sanity check: Assert that the IntValue is non-negative if it exists */ |
| 90786 | assert( !ExprHasProperty(p, EP_IntValue) || p->u.iValue>=0 ); |
| 90787 | #ifdef SQLITE_DEBUG |
| 90788 | if( ExprHasProperty(p, EP_Leaf) && !ExprHasProperty(p, EP_TokenOnly) ){ |
| 90789 | assert( p->pLeft==0 ); |
| 90790 | assert( p->pRight==0 ); |
| 90791 | assert( p->x.pSelect==0 ); |
| 90792 | } |
| 90793 | #endif |
| 90794 | if( !ExprHasProperty(p, (EP_TokenOnly|EP_Leaf)) ){ |
| 90795 | /* The Expr.x union is never used at the same time as Expr.pRight */ |
| 90796 | assert( p->x.pList==0 || p->pRight==0 ); |
| 90797 | if( p->pLeft && p->op!=TK_SELECT_COLUMN ) sqlite3ExprDeleteNN(db, p->pLeft); |
| 90798 | sqlite3ExprDelete(db, p->pRight); |
| 90799 | if( ExprHasProperty(p, EP_xIsSelect) ){ |
| 90800 | sqlite3SelectDelete(db, p->x.pSelect); |
| 90801 | }else{ |
| 90802 | sqlite3ExprListDelete(db, p->x.pList); |
| 90803 | } |
| 90804 | } |
| 90805 | if( ExprHasProperty(p, EP_MemToken) ) sqlite3DbFree(db, p->u.zToken); |
| 90806 | if( !ExprHasProperty(p, EP_Static) ){ |
| 90807 | sqlite3DbFree(db, p); |
| 90808 | } |
| 90809 | } |
| 90810 | SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3 *db, Expr *p){ |
| @@ -90893,11 +90977,11 @@ | |
| 90977 | if( nToken ){ |
| 90978 | char *zToken = pNew->u.zToken = (char*)&zAlloc[nNewSize]; |
| 90979 | memcpy(zToken, p->u.zToken, nToken); |
| 90980 | } |
| 90981 | |
| 90982 | if( 0==((p->flags|pNew->flags) & (EP_TokenOnly|EP_Leaf)) ){ |
| 90983 | /* Fill in the pNew->x.pSelect or pNew->x.pList member. */ |
| 90984 | if( ExprHasProperty(p, EP_xIsSelect) ){ |
| 90985 | pNew->x.pSelect = sqlite3SelectDup(db, p->x.pSelect, dupFlags); |
| 90986 | }else{ |
| 90987 | pNew->x.pList = sqlite3ExprListDup(db, p->x.pList, dupFlags); |
| @@ -90905,21 +90989,21 @@ | |
| 90989 | } |
| 90990 | |
| 90991 | /* Fill in pNew->pLeft and pNew->pRight. */ |
| 90992 | if( ExprHasProperty(pNew, EP_Reduced|EP_TokenOnly) ){ |
| 90993 | zAlloc += dupedExprNodeSize(p, dupFlags); |
| 90994 | if( !ExprHasProperty(pNew, EP_TokenOnly|EP_Leaf) ){ |
| 90995 | pNew->pLeft = p->pLeft ? |
| 90996 | exprDup(db, p->pLeft, EXPRDUP_REDUCE, &zAlloc) : 0; |
| 90997 | pNew->pRight = p->pRight ? |
| 90998 | exprDup(db, p->pRight, EXPRDUP_REDUCE, &zAlloc) : 0; |
| 90999 | } |
| 91000 | if( pzBuffer ){ |
| 91001 | *pzBuffer = zAlloc; |
| 91002 | } |
| 91003 | }else{ |
| 91004 | if( !ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){ |
| 91005 | if( pNew->op==TK_SELECT_COLUMN ){ |
| 91006 | pNew->pLeft = p->pLeft; |
| 91007 | }else{ |
| 91008 | pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0); |
| 91009 | } |
| @@ -92276,12 +92360,12 @@ | |
| 92360 | dest.eDest = SRT_Exists; |
| 92361 | sqlite3VdbeAddOp2(v, OP_Integer, 0, dest.iSDParm); |
| 92362 | VdbeComment((v, "Init EXISTS result")); |
| 92363 | } |
| 92364 | sqlite3ExprDelete(pParse->db, pSel->pLimit); |
| 92365 | pSel->pLimit = sqlite3ExprAlloc(pParse->db, TK_INTEGER, |
| 92366 | &sqlite3IntTokens[1], 0); |
| 92367 | pSel->iLimit = 0; |
| 92368 | pSel->selFlags &= ~SF_MultiValue; |
| 92369 | if( sqlite3Select(pParse, pSel, &dest) ){ |
| 92370 | return 0; |
| 92371 | } |
| @@ -92646,36 +92730,23 @@ | |
| 92730 | #endif |
| 92731 | } |
| 92732 | } |
| 92733 | } |
| 92734 | |
| 92735 | /* |
| 92736 | ** Erase column-cache entry number i |
| 92737 | */ |
| 92738 | static void cacheEntryClear(Parse *pParse, int i){ |
| 92739 | if( pParse->aColCache[i].tempReg ){ |
| 92740 | if( pParse->nTempReg<ArraySize(pParse->aTempReg) ){ |
| 92741 | pParse->aTempReg[pParse->nTempReg++] = pParse->aColCache[i].iReg; |
| 92742 | } |
| 92743 | } |
| 92744 | pParse->nColCache--; |
| 92745 | if( i<pParse->nColCache ){ |
| 92746 | pParse->aColCache[i] = pParse->aColCache[pParse->nColCache]; |
| 92747 | } |
| 92748 | } |
| 92749 | |
| 92750 | |
| 92751 | /* |
| 92752 | ** Record in the column cache that a particular column from a |
| @@ -92701,64 +92772,52 @@ | |
| 92772 | ** |
| 92773 | ** Actually, the way the column cache is currently used, we are guaranteed |
| 92774 | ** that the object will never already be in cache. Verify this guarantee. |
| 92775 | */ |
| 92776 | #ifndef NDEBUG |
| 92777 | for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){ |
| 92778 | assert( p->iTable!=iTab || p->iColumn!=iCol ); |
| 92779 | } |
| 92780 | #endif |
| 92781 | |
| 92782 | /* If the cache is already full, delete the least recently used entry */ |
| 92783 | if( pParse->nColCache>=SQLITE_N_COLCACHE ){ |
| 92784 | minLru = 0x7fffffff; |
| 92785 | idxLru = -1; |
| 92786 | for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){ |
| 92787 | if( p->lru<minLru ){ |
| 92788 | idxLru = i; |
| 92789 | minLru = p->lru; |
| 92790 | } |
| 92791 | } |
| 92792 | p = &pParse->aColCache[idxLru]; |
| 92793 | }else{ |
| 92794 | p = &pParse->aColCache[pParse->nColCache++]; |
| 92795 | } |
| 92796 | |
| 92797 | /* Add the new entry to the end of the cache */ |
| 92798 | p->iLevel = pParse->iCacheLevel; |
| 92799 | p->iTable = iTab; |
| 92800 | p->iColumn = iCol; |
| 92801 | p->iReg = iReg; |
| 92802 | p->tempReg = 0; |
| 92803 | p->lru = pParse->iCacheCnt++; |
| 92804 | } |
| 92805 | |
| 92806 | /* |
| 92807 | ** Indicate that registers between iReg..iReg+nReg-1 are being overwritten. |
| 92808 | ** Purge the range of registers from the column cache. |
| 92809 | */ |
| 92810 | SQLITE_PRIVATE void sqlite3ExprCacheRemove(Parse *pParse, int iReg, int nReg){ |
| 92811 | int i = 0; |
| 92812 | while( i<pParse->nColCache ){ |
| 92813 | struct yColCache *p = &pParse->aColCache[i]; |
| 92814 | if( p->iReg >= iReg && p->iReg < iReg+nReg ){ |
| 92815 | cacheEntryClear(pParse, i); |
| 92816 | }else{ |
| 92817 | i++; |
| 92818 | } |
| 92819 | } |
| 92820 | } |
| 92821 | |
| 92822 | /* |
| 92823 | ** Remember the current column cache context. Any new entries added |
| @@ -92778,22 +92837,23 @@ | |
| 92837 | ** Remove from the column cache any entries that were added since the |
| 92838 | ** the previous sqlite3ExprCachePush operation. In other words, restore |
| 92839 | ** the cache to the state it was in prior the most recent Push. |
| 92840 | */ |
| 92841 | SQLITE_PRIVATE void sqlite3ExprCachePop(Parse *pParse){ |
| 92842 | int i = 0; |
| 92843 | assert( pParse->iCacheLevel>=1 ); |
| 92844 | pParse->iCacheLevel--; |
| 92845 | #ifdef SQLITE_DEBUG |
| 92846 | if( pParse->db->flags & SQLITE_VdbeAddopTrace ){ |
| 92847 | printf("POP to %d\n", pParse->iCacheLevel); |
| 92848 | } |
| 92849 | #endif |
| 92850 | while( i<pParse->nColCache ){ |
| 92851 | if( pParse->aColCache[i].iLevel>pParse->iCacheLevel ){ |
| 92852 | cacheEntryClear(pParse, i); |
| 92853 | }else{ |
| 92854 | i++; |
| 92855 | } |
| 92856 | } |
| 92857 | } |
| 92858 | |
| 92859 | /* |
| @@ -92803,11 +92863,11 @@ | |
| 92863 | ** get them all. |
| 92864 | */ |
| 92865 | static void sqlite3ExprCachePinRegister(Parse *pParse, int iReg){ |
| 92866 | int i; |
| 92867 | struct yColCache *p; |
| 92868 | for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){ |
| 92869 | if( p->iReg==iReg ){ |
| 92870 | p->tempReg = 0; |
| 92871 | } |
| 92872 | } |
| 92873 | } |
| @@ -92881,12 +92941,12 @@ | |
| 92941 | ){ |
| 92942 | Vdbe *v = pParse->pVdbe; |
| 92943 | int i; |
| 92944 | struct yColCache *p; |
| 92945 | |
| 92946 | for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){ |
| 92947 | if( p->iTable==iTable && p->iColumn==iColumn ){ |
| 92948 | p->lru = pParse->iCacheCnt++; |
| 92949 | sqlite3ExprCachePinRegister(pParse, p->iReg); |
| 92950 | return p->iReg; |
| 92951 | } |
| 92952 | } |
| @@ -92914,22 +92974,24 @@ | |
| 92974 | /* |
| 92975 | ** Clear all column cache entries. |
| 92976 | */ |
| 92977 | SQLITE_PRIVATE void sqlite3ExprCacheClear(Parse *pParse){ |
| 92978 | int i; |
| 92979 | |
| 92980 | #if SQLITE_DEBUG |
| 92981 | if( pParse->db->flags & SQLITE_VdbeAddopTrace ){ |
| 92982 | printf("CLEAR\n"); |
| 92983 | } |
| 92984 | #endif |
| 92985 | for(i=0; i<pParse->nColCache; i++){ |
| 92986 | if( pParse->aColCache[i].tempReg |
| 92987 | && pParse->nTempReg<ArraySize(pParse->aTempReg) |
| 92988 | ){ |
| 92989 | pParse->aTempReg[pParse->nTempReg++] = pParse->aColCache[i].iReg; |
| 92990 | } |
| 92991 | } |
| 92992 | pParse->nColCache = 0; |
| 92993 | } |
| 92994 | |
| 92995 | /* |
| 92996 | ** Record the fact that an affinity change has occurred on iCount |
| 92997 | ** registers starting with iStart. |
| @@ -92957,11 +93019,11 @@ | |
| 93019 | ** and does not appear in a normal build. |
| 93020 | */ |
| 93021 | static int usedAsColumnCache(Parse *pParse, int iFrom, int iTo){ |
| 93022 | int i; |
| 93023 | struct yColCache *p; |
| 93024 | for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){ |
| 93025 | int r = p->iReg; |
| 93026 | if( r>=iFrom && r<=iTo ) return 1; /*NO_TEST*/ |
| 93027 | } |
| 93028 | return 0; |
| 93029 | } |
| @@ -94306,15 +94368,14 @@ | |
| 94368 | && (sqlite3ExprImpliesExpr(pE1, pE2->pLeft, iTab) |
| 94369 | || sqlite3ExprImpliesExpr(pE1, pE2->pRight, iTab) ) |
| 94370 | ){ |
| 94371 | return 1; |
| 94372 | } |
| 94373 | if( pE2->op==TK_NOTNULL && pE1->op!=TK_ISNULL && pE1->op!=TK_IS ){ |
| 94374 | Expr *pX = sqlite3ExprSkipCollate(pE1->pLeft); |
| 94375 | testcase( pX!=pE1->pLeft ); |
| 94376 | if( sqlite3ExprCompare(pX, pE2->pLeft, iTab)==0 ) return 1; |
| 94377 | } |
| 94378 | return 0; |
| 94379 | } |
| 94380 | |
| 94381 | /* |
| @@ -94653,11 +94714,11 @@ | |
| 94714 | */ |
| 94715 | SQLITE_PRIVATE void sqlite3ReleaseTempReg(Parse *pParse, int iReg){ |
| 94716 | if( iReg && pParse->nTempReg<ArraySize(pParse->aTempReg) ){ |
| 94717 | int i; |
| 94718 | struct yColCache *p; |
| 94719 | for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){ |
| 94720 | if( p->iReg==iReg ){ |
| 94721 | p->tempReg = 1; |
| 94722 | return; |
| 94723 | } |
| 94724 | } |
| @@ -97959,11 +98020,11 @@ | |
| 98020 | }else{ |
| 98021 | sqlite3ErrorMsg(pFix->pParse, "%s cannot use variables", pFix->zType); |
| 98022 | return 1; |
| 98023 | } |
| 98024 | } |
| 98025 | if( ExprHasProperty(pExpr, EP_TokenOnly|EP_Leaf) ) break; |
| 98026 | if( ExprHasProperty(pExpr, EP_xIsSelect) ){ |
| 98027 | if( sqlite3FixSelect(pFix, pExpr->x.pSelect) ) return 1; |
| 98028 | }else{ |
| 98029 | if( sqlite3FixExprList(pFix, pExpr->x.pList) ) return 1; |
| 98030 | } |
| @@ -98423,11 +98484,10 @@ | |
| 98484 | */ |
| 98485 | v = sqlite3GetVdbe(pParse); |
| 98486 | assert( !pParse->isMultiWrite |
| 98487 | || sqlite3VdbeAssertMayAbort(v, pParse->mayAbort)); |
| 98488 | if( v ){ |
| 98489 | sqlite3VdbeAddOp0(v, OP_Halt); |
| 98490 | |
| 98491 | #if SQLITE_USER_AUTHENTICATION |
| 98492 | if( pParse->nTableLock>0 && db->init.busy==0 ){ |
| 98493 | sqlite3UserAuthInit(db); |
| @@ -98450,18 +98510,20 @@ | |
| 98510 | ){ |
| 98511 | int iDb, i; |
| 98512 | assert( sqlite3VdbeGetOp(v, 0)->opcode==OP_Init ); |
| 98513 | sqlite3VdbeJumpHere(v, 0); |
| 98514 | for(iDb=0; iDb<db->nDb; iDb++){ |
| 98515 | Schema *pSchema; |
| 98516 | if( DbMaskTest(pParse->cookieMask, iDb)==0 ) continue; |
| 98517 | sqlite3VdbeUsesBtree(v, iDb); |
| 98518 | pSchema = db->aDb[iDb].pSchema; |
| 98519 | sqlite3VdbeAddOp4Int(v, |
| 98520 | OP_Transaction, /* Opcode */ |
| 98521 | iDb, /* P1 */ |
| 98522 | DbMaskTest(pParse->writeMask,iDb), /* P2 */ |
| 98523 | pSchema->schema_cookie, /* P3 */ |
| 98524 | pSchema->iGeneration /* P4 */ |
| 98525 | ); |
| 98526 | if( db->init.busy==0 ) sqlite3VdbeChangeP5(v, 1); |
| 98527 | VdbeComment((v, |
| 98528 | "usesStmtJournal=%d", pParse->mayAbort && pParse->isMultiWrite)); |
| 98529 | } |
| @@ -98508,20 +98570,10 @@ | |
| 98570 | sqlite3VdbeMakeReady(v, pParse); |
| 98571 | pParse->rc = SQLITE_DONE; |
| 98572 | }else{ |
| 98573 | pParse->rc = SQLITE_ERROR; |
| 98574 | } |
| 98575 | } |
| 98576 | |
| 98577 | /* |
| 98578 | ** Run the parser and code generator recursively in order to generate |
| 98579 | ** code for the SQL statement given onto the end of the pParse context |
| @@ -98537,12 +98589,11 @@ | |
| 98589 | SQLITE_PRIVATE void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){ |
| 98590 | va_list ap; |
| 98591 | char *zSql; |
| 98592 | char *zErrMsg = 0; |
| 98593 | sqlite3 *db = pParse->db; |
| 98594 | char saveBuf[PARSE_TAIL_SZ]; |
| 98595 | |
| 98596 | if( pParse->nErr ) return; |
| 98597 | assert( pParse->nested<10 ); /* Nesting should only be of limited depth */ |
| 98598 | va_start(ap, zFormat); |
| 98599 | zSql = sqlite3VMPrintf(db, zFormat, ap); |
| @@ -98549,16 +98600,16 @@ | |
| 98600 | va_end(ap); |
| 98601 | if( zSql==0 ){ |
| 98602 | return; /* A malloc must have failed */ |
| 98603 | } |
| 98604 | pParse->nested++; |
| 98605 | memcpy(saveBuf, PARSE_TAIL(pParse), PARSE_TAIL_SZ); |
| 98606 | memset(PARSE_TAIL(pParse), 0, PARSE_TAIL_SZ); |
| 98607 | sqlite3RunParser(pParse, zSql, &zErrMsg); |
| 98608 | sqlite3DbFree(db, zErrMsg); |
| 98609 | sqlite3DbFree(db, zSql); |
| 98610 | memcpy(PARSE_TAIL(pParse), saveBuf, PARSE_TAIL_SZ); |
| 98611 | pParse->nested--; |
| 98612 | } |
| 98613 | |
| 98614 | #if SQLITE_USER_AUTHENTICATION |
| 98615 | /* |
| @@ -99735,10 +99786,13 @@ | |
| 99786 | ** This plan is not completely bullet-proof. It is possible for |
| 99787 | ** the schema to change multiple times and for the cookie to be |
| 99788 | ** set back to prior value. But schema changes are infrequent |
| 99789 | ** and the probability of hitting the same cookie value is only |
| 99790 | ** 1 chance in 2^32. So we're safe enough. |
| 99791 | ** |
| 99792 | ** IMPLEMENTATION-OF: R-34230-56049 SQLite automatically increments |
| 99793 | ** the schema-version whenever the schema changes. |
| 99794 | */ |
| 99795 | SQLITE_PRIVATE void sqlite3ChangeCookie(Parse *pParse, int iDb){ |
| 99796 | sqlite3 *db = pParse->db; |
| 99797 | Vdbe *v = pParse->pVdbe; |
| 99798 | assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); |
| @@ -102318,19 +102372,17 @@ | |
| 102372 | ** will occur at the end of the top-level VDBE and will be generated |
| 102373 | ** later, by sqlite3FinishCoding(). |
| 102374 | */ |
| 102375 | SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse *pParse, int iDb){ |
| 102376 | Parse *pToplevel = sqlite3ParseToplevel(pParse); |
| 102377 | |
| 102378 | assert( iDb>=0 && iDb<pParse->db->nDb ); |
| 102379 | assert( pParse->db->aDb[iDb].pBt!=0 || iDb==1 ); |
| 102380 | assert( iDb<SQLITE_MAX_ATTACHED+2 ); |
| 102381 | assert( sqlite3SchemaMutexHeld(pParse->db, iDb, 0) ); |
| 102382 | if( DbMaskTest(pToplevel->cookieMask, iDb)==0 ){ |
| 102383 | DbMaskSet(pToplevel->cookieMask, iDb); |
| 102384 | if( !OMIT_TEMPDB && iDb==1 ){ |
| 102385 | sqlite3OpenTempDatabase(pToplevel); |
| 102386 | } |
| 102387 | } |
| 102388 | } |
| @@ -107192,14 +107244,14 @@ | |
| 107244 | }else if( action==OE_SetDflt ){ |
| 107245 | Expr *pDflt = pFKey->pFrom->aCol[iFromCol].pDflt; |
| 107246 | if( pDflt ){ |
| 107247 | pNew = sqlite3ExprDup(db, pDflt, 0); |
| 107248 | }else{ |
| 107249 | pNew = sqlite3ExprAlloc(db, TK_NULL, 0, 0); |
| 107250 | } |
| 107251 | }else{ |
| 107252 | pNew = sqlite3ExprAlloc(db, TK_NULL, 0, 0); |
| 107253 | } |
| 107254 | pList = sqlite3ExprListAppend(pParse, pList, pNew); |
| 107255 | sqlite3ExprListSetName(pParse, pList, &tFromCol, 0); |
| 107256 | } |
| 107257 | } |
| @@ -109538,10 +109590,11 @@ | |
| 109590 | } |
| 109591 | if( emptySrcTest ) sqlite3VdbeJumpHere(v, emptySrcTest); |
| 109592 | sqlite3ReleaseTempReg(pParse, regRowid); |
| 109593 | sqlite3ReleaseTempReg(pParse, regData); |
| 109594 | if( emptyDestTest ){ |
| 109595 | sqlite3AutoincrementEnd(pParse); |
| 109596 | sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_OK, 0); |
| 109597 | sqlite3VdbeJumpHere(v, emptyDestTest); |
| 109598 | sqlite3VdbeAddOp2(v, OP_Close, iDest, 0); |
| 109599 | return 0; |
| 109600 | }else{ |
| @@ -114034,22 +114087,18 @@ | |
| 114087 | int saveSqlFlag, /* True to copy SQL text into the sqlite3_stmt */ |
| 114088 | Vdbe *pReprepare, /* VM being reprepared */ |
| 114089 | sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ |
| 114090 | const char **pzTail /* OUT: End of parsed string */ |
| 114091 | ){ |
| 114092 | char *zErrMsg = 0; /* Error message */ |
| 114093 | int rc = SQLITE_OK; /* Result code */ |
| 114094 | int i; /* Loop counter */ |
| 114095 | Parse sParse; /* Parsing context */ |
| 114096 | |
| 114097 | memset(&sParse, 0, PARSE_HDR_SZ); |
| 114098 | memset(PARSE_TAIL(&sParse), 0, PARSE_TAIL_SZ); |
| 114099 | sParse.pReprepare = pReprepare; |
| 114100 | assert( ppStmt && *ppStmt==0 ); |
| 114101 | /* assert( !db->mallocFailed ); // not true with SQLITE_USE_ALLOCA */ |
| 114102 | assert( sqlite3_mutex_held(db->mutex) ); |
| 114103 | |
| 114104 | /* Check to verify that it is possible to get a read lock on all |
| @@ -114089,12 +114138,11 @@ | |
| 114138 | } |
| 114139 | } |
| 114140 | |
| 114141 | sqlite3VtabUnlockList(db); |
| 114142 | |
| 114143 | sParse.db = db; |
| 114144 | if( nBytes>=0 && (nBytes==0 || zSql[nBytes-1]!=0) ){ |
| 114145 | char *zSqlCopy; |
| 114146 | int mxLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH]; |
| 114147 | testcase( nBytes==mxLen ); |
| 114148 | testcase( nBytes==mxLen+1 ); |
| @@ -114103,65 +114151,65 @@ | |
| 114151 | rc = sqlite3ApiExit(db, SQLITE_TOOBIG); |
| 114152 | goto end_prepare; |
| 114153 | } |
| 114154 | zSqlCopy = sqlite3DbStrNDup(db, zSql, nBytes); |
| 114155 | if( zSqlCopy ){ |
| 114156 | sqlite3RunParser(&sParse, zSqlCopy, &zErrMsg); |
| 114157 | sParse.zTail = &zSql[sParse.zTail-zSqlCopy]; |
| 114158 | sqlite3DbFree(db, zSqlCopy); |
| 114159 | }else{ |
| 114160 | sParse.zTail = &zSql[nBytes]; |
| 114161 | } |
| 114162 | }else{ |
| 114163 | sqlite3RunParser(&sParse, zSql, &zErrMsg); |
| 114164 | } |
| 114165 | assert( 0==sParse.nQueryLoop ); |
| 114166 | |
| 114167 | if( sParse.rc==SQLITE_DONE ) sParse.rc = SQLITE_OK; |
| 114168 | if( sParse.checkSchema ){ |
| 114169 | schemaIsValid(&sParse); |
| 114170 | } |
| 114171 | if( db->mallocFailed ){ |
| 114172 | sParse.rc = SQLITE_NOMEM_BKPT; |
| 114173 | } |
| 114174 | if( pzTail ){ |
| 114175 | *pzTail = sParse.zTail; |
| 114176 | } |
| 114177 | rc = sParse.rc; |
| 114178 | |
| 114179 | #ifndef SQLITE_OMIT_EXPLAIN |
| 114180 | if( rc==SQLITE_OK && sParse.pVdbe && sParse.explain ){ |
| 114181 | static const char * const azColName[] = { |
| 114182 | "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment", |
| 114183 | "selectid", "order", "from", "detail" |
| 114184 | }; |
| 114185 | int iFirst, mx; |
| 114186 | if( sParse.explain==2 ){ |
| 114187 | sqlite3VdbeSetNumCols(sParse.pVdbe, 4); |
| 114188 | iFirst = 8; |
| 114189 | mx = 12; |
| 114190 | }else{ |
| 114191 | sqlite3VdbeSetNumCols(sParse.pVdbe, 8); |
| 114192 | iFirst = 0; |
| 114193 | mx = 8; |
| 114194 | } |
| 114195 | for(i=iFirst; i<mx; i++){ |
| 114196 | sqlite3VdbeSetColName(sParse.pVdbe, i-iFirst, COLNAME_NAME, |
| 114197 | azColName[i], SQLITE_STATIC); |
| 114198 | } |
| 114199 | } |
| 114200 | #endif |
| 114201 | |
| 114202 | if( db->init.busy==0 ){ |
| 114203 | Vdbe *pVdbe = sParse.pVdbe; |
| 114204 | sqlite3VdbeSetSql(pVdbe, zSql, (int)(sParse.zTail-zSql), saveSqlFlag); |
| 114205 | } |
| 114206 | if( sParse.pVdbe && (rc!=SQLITE_OK || db->mallocFailed) ){ |
| 114207 | sqlite3VdbeFinalize(sParse.pVdbe); |
| 114208 | assert(!(*ppStmt)); |
| 114209 | }else{ |
| 114210 | *ppStmt = (sqlite3_stmt*)sParse.pVdbe; |
| 114211 | } |
| 114212 | |
| 114213 | if( zErrMsg ){ |
| 114214 | sqlite3ErrorWithMsg(db, rc, "%s", zErrMsg); |
| 114215 | sqlite3DbFree(db, zErrMsg); |
| @@ -114168,20 +114216,19 @@ | |
| 114216 | }else{ |
| 114217 | sqlite3Error(db, rc); |
| 114218 | } |
| 114219 | |
| 114220 | /* Delete any TriggerPrg structures allocated while parsing this statement. */ |
| 114221 | while( sParse.pTriggerPrg ){ |
| 114222 | TriggerPrg *pT = sParse.pTriggerPrg; |
| 114223 | sParse.pTriggerPrg = pT->pNext; |
| 114224 | sqlite3DbFree(db, pT); |
| 114225 | } |
| 114226 | |
| 114227 | end_prepare: |
| 114228 | |
| 114229 | sqlite3ParserReset(&sParse); |
| 114230 | rc = sqlite3ApiExit(db, rc); |
| 114231 | assert( (rc&db->errMask)==rc ); |
| 114232 | return rc; |
| 114233 | } |
| 114234 | static int sqlite3LockAndPrepare( |
| @@ -115382,11 +115429,11 @@ | |
| 115429 | ** Allocate a KeyInfo object sufficient for an index of N key columns and |
| 115430 | ** X extra columns. |
| 115431 | */ |
| 115432 | SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N, int X){ |
| 115433 | int nExtra = (N+X)*(sizeof(CollSeq*)+1); |
| 115434 | KeyInfo *p = sqlite3DbMallocRawNN(db, sizeof(KeyInfo) + nExtra); |
| 115435 | if( p ){ |
| 115436 | p->aSortOrder = (u8*)&p->aColl[N+X]; |
| 115437 | p->nField = (u16)N; |
| 115438 | p->nXField = (u16)X; |
| 115439 | p->enc = ENC(db); |
| @@ -118072,16 +118119,17 @@ | |
| 118119 | pWhere = sqlite3ExprDup(db, pSub->pWhere, 0); |
| 118120 | if( subqueryIsAgg ){ |
| 118121 | assert( pParent->pHaving==0 ); |
| 118122 | pParent->pHaving = pParent->pWhere; |
| 118123 | pParent->pWhere = pWhere; |
| 118124 | pParent->pHaving = sqlite3ExprAnd(db, |
| 118125 | sqlite3ExprDup(db, pSub->pHaving, 0), pParent->pHaving |
| 118126 | ); |
| 118127 | assert( pParent->pGroupBy==0 ); |
| 118128 | pParent->pGroupBy = sqlite3ExprListDup(db, pSub->pGroupBy, 0); |
| 118129 | }else{ |
| 118130 | pParent->pWhere = sqlite3ExprAnd(db, pWhere, pParent->pWhere); |
| 118131 | } |
| 118132 | substSelect(db, pParent, iParent, pSub->pEList, 0); |
| 118133 | |
| 118134 | /* The flattened query is distinct if either the inner or the |
| 118135 | ** outer query is distinct. |
| @@ -122381,11 +122429,11 @@ | |
| 122429 | } |
| 122430 | #endif |
| 122431 | |
| 122432 | sqlite3BtreeSetCacheSize(pTemp, db->aDb[iDb].pSchema->cache_size); |
| 122433 | sqlite3BtreeSetSpillSize(pTemp, sqlite3BtreeSetSpillSize(pMain,0)); |
| 122434 | sqlite3BtreeSetPagerFlags(pTemp, PAGER_SYNCHRONOUS_OFF|PAGER_CACHESPILL); |
| 122435 | |
| 122436 | /* Begin a transaction and take an exclusive lock on the main database |
| 122437 | ** file. This is done before the sqlite3BtreeGetPageSize(pMain) call below, |
| 122438 | ** to ensure that we do not try to change the page-size on a WAL database. |
| 122439 | */ |
| @@ -124041,24 +124089,24 @@ | |
| 124089 | ** in prereqRight and prereqAll. The default is 64 bits, hence SQLite |
| 124090 | ** is only able to process joins with 64 or fewer tables. |
| 124091 | */ |
| 124092 | struct WhereTerm { |
| 124093 | Expr *pExpr; /* Pointer to the subexpression that is this term */ |
| 124094 | WhereClause *pWC; /* The clause this term is part of */ |
| 124095 | LogEst truthProb; /* Probability of truth for this expression */ |
| 124096 | u16 wtFlags; /* TERM_xxx bit flags. See below */ |
| 124097 | u16 eOperator; /* A WO_xx value describing <op> */ |
| 124098 | u8 nChild; /* Number of children that must disable us */ |
| 124099 | u8 eMatchOp; /* Op for vtab MATCH/LIKE/GLOB/REGEXP terms */ |
| 124100 | int iParent; /* Disable pWC->a[iParent] when this term disabled */ |
| 124101 | int leftCursor; /* Cursor number of X in "X <op> <expr>" */ |
| 124102 | int iField; /* Field in (?,?,?) IN (SELECT...) vector */ |
| 124103 | union { |
| 124104 | int leftColumn; /* Column number of X in "X <op> <expr>" */ |
| 124105 | WhereOrInfo *pOrInfo; /* Extra information if (eOperator & WO_OR)!=0 */ |
| 124106 | WhereAndInfo *pAndInfo; /* Extra information if (eOperator& WO_AND)!=0 */ |
| 124107 | } u; |
| 124108 | Bitmask prereqRight; /* Bitmask of tables used by pExpr->pRight */ |
| 124109 | Bitmask prereqAll; /* Bitmask of tables referenced by pExpr */ |
| 124110 | }; |
| 124111 | |
| 124112 | /* |
| @@ -124207,29 +124255,29 @@ | |
| 124255 | struct WhereInfo { |
| 124256 | Parse *pParse; /* Parsing and code generating context */ |
| 124257 | SrcList *pTabList; /* List of tables in the join */ |
| 124258 | ExprList *pOrderBy; /* The ORDER BY clause or NULL */ |
| 124259 | ExprList *pDistinctSet; /* DISTINCT over all these values */ |
| 124260 | LogEst iLimit; /* LIMIT if wctrlFlags has WHERE_USE_LIMIT */ |
| 124261 | int aiCurOnePass[2]; /* OP_OpenWrite cursors for the ONEPASS opt */ |
| 124262 | int iContinue; /* Jump here to continue with next record */ |
| 124263 | int iBreak; /* Jump here to break out of the loop */ |
| 124264 | int savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */ |
| 124265 | u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */ |
| 124266 | u8 nLevel; /* Number of nested loop */ |
| 124267 | i8 nOBSat; /* Number of ORDER BY terms satisfied by indices */ |
| 124268 | u8 sorted; /* True if really sorted (not just grouped) */ |
| 124269 | u8 eOnePass; /* ONEPASS_OFF, or _SINGLE, or _MULTI */ |
| 124270 | u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */ |
| 124271 | u8 eDistinct; /* One of the WHERE_DISTINCT_* values */ |
| 124272 | u8 bOrderedInnerLoop; /* True if only the inner-most loop is ordered */ |
| 124273 | int iTop; /* The very beginning of the WHERE loop */ |
| 124274 | WhereLoop *pLoops; /* List of all WhereLoop objects */ |
| 124275 | Bitmask revMask; /* Mask of ORDER BY terms that need reversing */ |
| 124276 | LogEst nRowOut; /* Estimated number of output rows */ |
| 124277 | WhereClause sWC; /* Decomposition of the WHERE clause */ |
| 124278 | WhereMaskSet sMaskSet; /* Map cursor numbers to bitmasks */ |
| 124279 | WhereLevel a[1]; /* Information about each nest loop in WHERE */ |
| 124280 | }; |
| 124281 | |
| 124282 | /* |
| 124283 | ** Private interfaces - callable only by other where.c routines. |
| @@ -124689,11 +124737,10 @@ | |
| 124737 | ** |
| 124738 | ** * the comparison will be performed with no affinity, or |
| 124739 | ** * the affinity change in zAff is guaranteed not to change the value. |
| 124740 | */ |
| 124741 | static void updateRangeAffinityStr( |
| 124742 | Expr *pRight, /* RHS of comparison */ |
| 124743 | int n, /* Number of vector elements in comparison */ |
| 124744 | char *zAff /* Affinity string to modify */ |
| 124745 | ){ |
| 124746 | int i; |
| @@ -125775,15 +125822,15 @@ | |
| 125822 | assert( (bRev & ~1)==0 ); |
| 125823 | pLevel->iLikeRepCntr <<=1; |
| 125824 | pLevel->iLikeRepCntr |= bRev ^ (pIdx->aSortOrder[nEq]==SQLITE_SO_DESC); |
| 125825 | } |
| 125826 | #endif |
| 125827 | if( pRangeStart==0 ){ |
| 125828 | j = pIdx->aiColumn[nEq]; |
| 125829 | if( (j>=0 && pIdx->pTable->aCol[j].notNull==0) || j==XN_EXPR ){ |
| 125830 | bSeekPastNull = 1; |
| 125831 | } |
| 125832 | } |
| 125833 | } |
| 125834 | assert( pRangeEnd==0 || (pRangeEnd->wtFlags & TERM_VNULL)==0 ); |
| 125835 | |
| 125836 | /* If we are doing a reverse order scan on an ascending index, or |
| @@ -125829,11 +125876,11 @@ | |
| 125876 | ){ |
| 125877 | sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt); |
| 125878 | VdbeCoverage(v); |
| 125879 | } |
| 125880 | if( zStartAff ){ |
| 125881 | updateRangeAffinityStr(pRight, nBtm, &zStartAff[nEq]); |
| 125882 | } |
| 125883 | nConstraint += nBtm; |
| 125884 | testcase( pRangeStart->wtFlags & TERM_VIRTUAL ); |
| 125885 | if( sqlite3ExprIsVector(pRight)==0 ){ |
| 125886 | disableTerm(pLevel, pRangeStart); |
| @@ -125879,11 +125926,11 @@ | |
| 125926 | ){ |
| 125927 | sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt); |
| 125928 | VdbeCoverage(v); |
| 125929 | } |
| 125930 | if( zEndAff ){ |
| 125931 | updateRangeAffinityStr(pRight, nTop, zEndAff); |
| 125932 | codeApplyAffinity(pParse, regBase+nEq, nTop, zEndAff); |
| 125933 | }else{ |
| 125934 | assert( pParse->db->mallocFailed ); |
| 125935 | } |
| 125936 | nConstraint += nTop; |
| @@ -126315,11 +126362,11 @@ | |
| 126362 | ** and we are coding the t1 loop and the t2 loop has not yet coded, |
| 126363 | ** then we cannot use the "t1.a=t2.b" constraint, but we can code |
| 126364 | ** the implied "t1.a=123" constraint. |
| 126365 | */ |
| 126366 | for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){ |
| 126367 | Expr *pE, sEAlt; |
| 126368 | WhereTerm *pAlt; |
| 126369 | if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue; |
| 126370 | if( (pTerm->eOperator & (WO_EQ|WO_IS))==0 ) continue; |
| 126371 | if( (pTerm->eOperator & WO_EQUIV)==0 ) continue; |
| 126372 | if( pTerm->leftCursor!=iCur ) continue; |
| @@ -126333,17 +126380,13 @@ | |
| 126380 | if( pAlt->wtFlags & (TERM_CODED) ) continue; |
| 126381 | testcase( pAlt->eOperator & WO_EQ ); |
| 126382 | testcase( pAlt->eOperator & WO_IS ); |
| 126383 | testcase( pAlt->eOperator & WO_IN ); |
| 126384 | VdbeModuleComment((v, "begin transitive constraint")); |
| 126385 | sEAlt = *pAlt->pExpr; |
| 126386 | sEAlt.pLeft = pE->pLeft; |
| 126387 | sqlite3ExprIfFalse(pParse, &sEAlt, addrCont, SQLITE_JUMPIFNULL); |
| 126388 | } |
| 126389 | |
| 126390 | /* For a LEFT OUTER JOIN, generate code that will record the fact that |
| 126391 | ** at least one row of the right table has matched the left table. |
| 126392 | */ |
| @@ -126448,11 +126491,10 @@ | |
| 126491 | memcpy(pWC->a, pOld, sizeof(pWC->a[0])*pWC->nTerm); |
| 126492 | if( pOld!=pWC->aStatic ){ |
| 126493 | sqlite3DbFree(db, pOld); |
| 126494 | } |
| 126495 | pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]); |
| 126496 | } |
| 126497 | pTerm = &pWC->a[idx = pWC->nTerm++]; |
| 126498 | if( p && ExprHasProperty(p, EP_Unlikely) ){ |
| 126499 | pTerm->truthProb = sqlite3LogEst(p->iTable) - 270; |
| 126500 | }else{ |
| @@ -126460,10 +126502,12 @@ | |
| 126502 | } |
| 126503 | pTerm->pExpr = sqlite3ExprSkipCollate(p); |
| 126504 | pTerm->wtFlags = wtFlags; |
| 126505 | pTerm->pWC = pWC; |
| 126506 | pTerm->iParent = -1; |
| 126507 | memset(&pTerm->eOperator, 0, |
| 126508 | sizeof(WhereTerm) - offsetof(WhereTerm,eOperator)); |
| 126509 | return idx; |
| 126510 | } |
| 126511 | |
| 126512 | /* |
| 126513 | ** Return TRUE if the given operator is one of the operators that is |
| @@ -127568,10 +127612,11 @@ | |
| 127612 | Expr *pNew; |
| 127613 | Expr *pLeft = sqlite3ExprForVectorField(pParse, pExpr->pLeft, i); |
| 127614 | Expr *pRight = sqlite3ExprForVectorField(pParse, pExpr->pRight, i); |
| 127615 | |
| 127616 | pNew = sqlite3PExpr(pParse, pExpr->op, pLeft, pRight, 0); |
| 127617 | transferJoinMarkings(pNew, pExpr); |
| 127618 | idxNew = whereClauseInsert(pWC, pNew, TERM_DYNAMIC); |
| 127619 | exprAnalyze(pSrc, pWC, idxNew); |
| 127620 | } |
| 127621 | pTerm = &pWC->a[idxTerm]; |
| 127622 | pTerm->wtFlags = TERM_CODED|TERM_VIRTUAL; /* Disable the original */ |
| @@ -127618,11 +127663,11 @@ | |
| 127663 | int idxNew; |
| 127664 | WhereTerm *pNewTerm; |
| 127665 | |
| 127666 | pNewExpr = sqlite3PExpr(pParse, TK_GT, |
| 127667 | sqlite3ExprDup(db, pLeft, 0), |
| 127668 | sqlite3ExprAlloc(db, TK_NULL, 0, 0), 0); |
| 127669 | |
| 127670 | idxNew = whereClauseInsert(pWC, pNewExpr, |
| 127671 | TERM_VIRTUAL|TERM_DYNAMIC|TERM_VNULL); |
| 127672 | if( idxNew ){ |
| 127673 | pNewTerm = &pWC->a[idxNew]; |
| @@ -127796,11 +127841,11 @@ | |
| 127841 | if( k>=pTab->nCol ){ |
| 127842 | sqlite3ErrorMsg(pParse, "too many arguments on %s() - max %d", |
| 127843 | pTab->zName, j); |
| 127844 | return; |
| 127845 | } |
| 127846 | pColRef = sqlite3ExprAlloc(pParse->db, TK_COLUMN, 0, 0); |
| 127847 | if( pColRef==0 ) return; |
| 127848 | pColRef->iTable = pItem->iCursor; |
| 127849 | pColRef->iColumn = k++; |
| 127850 | pColRef->pTab = pTab; |
| 127851 | pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef, |
| @@ -128009,15 +128054,17 @@ | |
| 128054 | Expr *pX; /* An expression being tested */ |
| 128055 | WhereClause *pWC; /* Shorthand for pScan->pWC */ |
| 128056 | WhereTerm *pTerm; /* The term being tested */ |
| 128057 | int k = pScan->k; /* Where to start scanning */ |
| 128058 | |
| 128059 | assert( pScan->iEquiv<=pScan->nEquiv ); |
| 128060 | pWC = pScan->pWC; |
| 128061 | while(1){ |
| 128062 | iColumn = pScan->aiColumn[pScan->iEquiv-1]; |
| 128063 | iCur = pScan->aiCur[pScan->iEquiv-1]; |
| 128064 | assert( pWC!=0 ); |
| 128065 | do{ |
| 128066 | for(pTerm=pWC->a+k; k<pWC->nTerm; k++, pTerm++){ |
| 128067 | if( pTerm->leftCursor==iCur |
| 128068 | && pTerm->u.leftColumn==iColumn |
| 128069 | && (iColumn!=XN_EXPR |
| 128070 | || sqlite3ExprCompare(pTerm->pExpr->pLeft,pScan->pIdxExpr,iCur)==0) |
| @@ -128063,19 +128110,21 @@ | |
| 128110 | && pX->iColumn==pScan->aiColumn[0] |
| 128111 | ){ |
| 128112 | testcase( pTerm->eOperator & WO_IS ); |
| 128113 | continue; |
| 128114 | } |
| 128115 | pScan->pWC = pWC; |
| 128116 | pScan->k = k+1; |
| 128117 | return pTerm; |
| 128118 | } |
| 128119 | } |
| 128120 | } |
| 128121 | pWC = pWC->pOuter; |
| 128122 | k = 0; |
| 128123 | }while( pWC!=0 ); |
| 128124 | if( pScan->iEquiv>=pScan->nEquiv ) break; |
| 128125 | pWC = pScan->pOrigWC; |
| 128126 | k = 0; |
| 128127 | pScan->iEquiv++; |
| 128128 | } |
| 128129 | return 0; |
| 128130 | } |
| @@ -128105,28 +128154,28 @@ | |
| 128154 | int iCur, /* Cursor to scan for */ |
| 128155 | int iColumn, /* Column to scan for */ |
| 128156 | u32 opMask, /* Operator(s) to scan for */ |
| 128157 | Index *pIdx /* Must be compatible with this index */ |
| 128158 | ){ |
| 128159 | pScan->pOrigWC = pWC; |
| 128160 | pScan->pWC = pWC; |
| 128161 | pScan->pIdxExpr = 0; |
| 128162 | pScan->idxaff = 0; |
| 128163 | pScan->zCollName = 0; |
| 128164 | if( pIdx ){ |
| 128165 | int j = iColumn; |
| 128166 | iColumn = pIdx->aiColumn[j]; |
| 128167 | if( iColumn==XN_EXPR ){ |
| 128168 | pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr; |
| 128169 | }else if( iColumn==pIdx->pTable->iPKey ){ |
| 128170 | iColumn = XN_ROWID; |
| 128171 | }else if( iColumn>=0 ){ |
| 128172 | pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity; |
| 128173 | pScan->zCollName = pIdx->azColl[j]; |
| 128174 | } |
| 128175 | }else if( iColumn==XN_EXPR ){ |
| 128176 | return 0; |
| 128177 | } |
| 128178 | pScan->opMask = opMask; |
| 128179 | pScan->k = 0; |
| 128180 | pScan->aiCur[0] = iCur; |
| 128181 | pScan->aiColumn[0] = iColumn; |
| @@ -130034,11 +130083,11 @@ | |
| 130083 | ** CREATE INDEX ... ON (a, b, c, d, e) |
| 130084 | ** |
| 130085 | ** then this function would be invoked with nEq=1. The value returned in |
| 130086 | ** this case is 3. |
| 130087 | */ |
| 130088 | static int whereRangeVectorLen( |
| 130089 | Parse *pParse, /* Parsing context */ |
| 130090 | int iCur, /* Cursor open on pIdx */ |
| 130091 | Index *pIdx, /* The index to be used for a inequality constraint */ |
| 130092 | int nEq, /* Number of prior equality constraints on same index */ |
| 130093 | WhereTerm *pTerm /* The vector inequality constraint */ |
| @@ -131480,11 +131529,11 @@ | |
| 131529 | if( rev ) *pRevMask |= MASKBIT(iLoop); |
| 131530 | revSet = 1; |
| 131531 | } |
| 131532 | } |
| 131533 | if( isMatch ){ |
| 131534 | if( iColumn==XN_ROWID ){ |
| 131535 | testcase( distinctColumns==0 ); |
| 131536 | distinctColumns = 1; |
| 131537 | } |
| 131538 | obSat |= MASKBIT(i); |
| 131539 | }else{ |
| @@ -131935,17 +131984,24 @@ | |
| 131984 | }else{ |
| 131985 | pWInfo->nOBSat = pFrom->isOrdered; |
| 131986 | pWInfo->revMask = pFrom->revLoop; |
| 131987 | if( pWInfo->nOBSat<=0 ){ |
| 131988 | pWInfo->nOBSat = 0; |
| 131989 | if( nLoop>0 ){ |
| 131990 | u32 wsFlags = pFrom->aLoop[nLoop-1]->wsFlags; |
| 131991 | if( (wsFlags & WHERE_ONEROW)==0 |
| 131992 | && (wsFlags&(WHERE_IPK|WHERE_COLUMN_IN))!=(WHERE_IPK|WHERE_COLUMN_IN) |
| 131993 | ){ |
| 131994 | Bitmask m = 0; |
| 131995 | int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pOrderBy, pFrom, |
| 131996 | WHERE_ORDERBY_LIMIT, nLoop-1, pFrom->aLoop[nLoop-1], &m); |
| 131997 | testcase( wsFlags & WHERE_IPK ); |
| 131998 | testcase( wsFlags & WHERE_COLUMN_IN ); |
| 131999 | if( rc==pWInfo->pOrderBy->nExpr ){ |
| 132000 | pWInfo->bOrderedInnerLoop = 1; |
| 132001 | pWInfo->revMask = m; |
| 132002 | } |
| 132003 | } |
| 132004 | } |
| 132005 | } |
| 132006 | } |
| 132007 | if( (pWInfo->wctrlFlags & WHERE_SORTBYGROUP) |
| @@ -132218,26 +132274,29 @@ | |
| 132274 | ** and the WhereMaskSet structure. Since WhereClause contains an 8-byte |
| 132275 | ** field (type Bitmask) it must be aligned on an 8-byte boundary on |
| 132276 | ** some architectures. Hence the ROUND8() below. |
| 132277 | */ |
| 132278 | nByteWInfo = ROUND8(sizeof(WhereInfo)+(nTabList-1)*sizeof(WhereLevel)); |
| 132279 | pWInfo = sqlite3DbMallocRawNN(db, nByteWInfo + sizeof(WhereLoop)); |
| 132280 | if( db->mallocFailed ){ |
| 132281 | sqlite3DbFree(db, pWInfo); |
| 132282 | pWInfo = 0; |
| 132283 | goto whereBeginError; |
| 132284 | } |
| 132285 | pWInfo->pParse = pParse; |
| 132286 | pWInfo->pTabList = pTabList; |
| 132287 | pWInfo->pOrderBy = pOrderBy; |
| 132288 | pWInfo->pDistinctSet = pDistinctSet; |
| 132289 | pWInfo->aiCurOnePass[0] = pWInfo->aiCurOnePass[1] = -1; |
| 132290 | pWInfo->nLevel = nTabList; |
| 132291 | pWInfo->iBreak = pWInfo->iContinue = sqlite3VdbeMakeLabel(v); |
| 132292 | pWInfo->wctrlFlags = wctrlFlags; |
| 132293 | pWInfo->iLimit = iAuxArg; |
| 132294 | pWInfo->savedNQueryLoop = pParse->nQueryLoop; |
| 132295 | memset(&pWInfo->nOBSat, 0, |
| 132296 | offsetof(WhereInfo,sWC) - offsetof(WhereInfo,nOBSat)); |
| 132297 | memset(&pWInfo->a[0], 0, sizeof(WhereLoop)+nTabList*sizeof(WhereLevel)); |
| 132298 | assert( pWInfo->eOnePass==ONEPASS_OFF ); /* ONEPASS defaults to OFF */ |
| 132299 | pMaskSet = &pWInfo->sMaskSet; |
| 132300 | sWLB.pWInfo = pWInfo; |
| 132301 | sWLB.pWC = &pWInfo->sWC; |
| 132302 | sWLB.pNew = (WhereLoop*)(((char*)pWInfo)+nByteWInfo); |
| @@ -132661,17 +132720,19 @@ | |
| 132720 | pLevel->addrLikeRep); |
| 132721 | VdbeCoverage(v); |
| 132722 | } |
| 132723 | #endif |
| 132724 | if( pLevel->iLeftJoin ){ |
| 132725 | int ws = pLoop->wsFlags; |
| 132726 | addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); VdbeCoverage(v); |
| 132727 | assert( (ws & WHERE_IDX_ONLY)==0 || (ws & WHERE_INDEXED)!=0 ); |
| 132728 | if( (ws & WHERE_IDX_ONLY)==0 ){ |
| 132729 | sqlite3VdbeAddOp1(v, OP_NullRow, pTabList->a[i].iCursor); |
| 132730 | } |
| 132731 | if( (ws & WHERE_INDEXED) |
| 132732 | || ((ws & WHERE_MULTI_OR) && pLevel->u.pCovidx) |
| 132733 | ){ |
| 132734 | sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iIdxCur); |
| 132735 | } |
| 132736 | if( pLevel->op==OP_Return ){ |
| 132737 | sqlite3VdbeAddOp2(v, OP_Gosub, pLevel->p1, pLevel->addrFirst); |
| 132738 | }else{ |
| @@ -132844,19 +132905,10 @@ | |
| 132905 | struct LimitVal { |
| 132906 | Expr *pLimit; /* The LIMIT expression. NULL if there is no limit */ |
| 132907 | Expr *pOffset; /* The OFFSET expression. NULL if there is none */ |
| 132908 | }; |
| 132909 | |
| 132910 | /* |
| 132911 | ** An instance of the following structure describes the event of a |
| 132912 | ** TRIGGER. "a" is the event type, one of TK_UPDATE, TK_INSERT, |
| 132913 | ** TK_DELETE, or TK_INSTEAD. If the event is of the form |
| 132914 | ** |
| @@ -132864,15 +132916,10 @@ | |
| 132916 | ** |
| 132917 | ** Then the "b" IdList records the list "a,b,c". |
| 132918 | */ |
| 132919 | struct TrigEvent { int a; IdList * b; }; |
| 132920 | |
| 132921 | /* |
| 132922 | ** Disable lookaside memory allocation for objects that might be |
| 132923 | ** shared across database connections. |
| 132924 | */ |
| 132925 | static void disableLookaside(Parse *pParse){ |
| @@ -132915,11 +132962,28 @@ | |
| 132962 | /* Construct a new Expr object from a single identifier. Use the |
| 132963 | ** new Expr to populate pOut. Set the span of pOut to be the identifier |
| 132964 | ** that created the expression. |
| 132965 | */ |
| 132966 | static void spanExpr(ExprSpan *pOut, Parse *pParse, int op, Token t){ |
| 132967 | Expr *p = sqlite3DbMallocRawNN(pParse->db, sizeof(Expr)+t.n+1); |
| 132968 | if( p ){ |
| 132969 | memset(p, 0, sizeof(Expr)); |
| 132970 | p->op = (u8)op; |
| 132971 | p->flags = EP_Leaf; |
| 132972 | p->iAgg = -1; |
| 132973 | p->u.zToken = (char*)&p[1]; |
| 132974 | memcpy(p->u.zToken, t.z, t.n); |
| 132975 | p->u.zToken[t.n] = 0; |
| 132976 | if( sqlite3Isquote(p->u.zToken[0]) ){ |
| 132977 | if( p->u.zToken[0]=='"' ) p->flags |= EP_DblQuoted; |
| 132978 | sqlite3Dequote(p->u.zToken); |
| 132979 | } |
| 132980 | #if SQLITE_MAX_EXPR_DEPTH>0 |
| 132981 | p->nHeight = 1; |
| 132982 | #endif |
| 132983 | } |
| 132984 | pOut->pExpr = p; |
| 132985 | pOut->zStart = t.z; |
| 132986 | pOut->zEnd = &t.z[t.n]; |
| 132987 | } |
| 132988 | |
| 132989 | /* This routine constructs a binary expression node out of two ExprSpan |
| @@ -133078,11 +133142,10 @@ | |
| 133142 | Select* yy243; |
| 133143 | IdList* yy254; |
| 133144 | With* yy285; |
| 133145 | struct TrigEvent yy332; |
| 133146 | struct LimitVal yy354; |
| 133147 | struct {int value; int mask;} yy497; |
| 133148 | } YYMINORTYPE; |
| 133149 | #ifndef YYSTACKDEPTH |
| 133150 | #define YYSTACKDEPTH 100 |
| 133151 | #endif |
| @@ -133090,19 +133153,19 @@ | |
| 133153 | #define sqlite3ParserARG_PDECL ,Parse *pParse |
| 133154 | #define sqlite3ParserARG_FETCH Parse *pParse = yypParser->pParse |
| 133155 | #define sqlite3ParserARG_STORE yypParser->pParse = pParse |
| 133156 | #define YYFALLBACK 1 |
| 133157 | #define YYNSTATE 456 |
| 133158 | #define YYNRULE 332 |
| 133159 | #define YY_MAX_SHIFT 455 |
| 133160 | #define YY_MIN_SHIFTREDUCE 668 |
| 133161 | #define YY_MAX_SHIFTREDUCE 999 |
| 133162 | #define YY_MIN_REDUCE 1000 |
| 133163 | #define YY_MAX_REDUCE 1331 |
| 133164 | #define YY_ERROR_ACTION 1332 |
| 133165 | #define YY_ACCEPT_ACTION 1333 |
| 133166 | #define YY_NO_ACTION 1334 |
| 133167 | /************* End control #defines *******************************************/ |
| 133168 | |
| 133169 | /* Define the yytestcase() macro to be a no-op if is not already defined |
| 133170 | ** otherwise. |
| 133171 | ** |
| @@ -133170,170 +133233,169 @@ | |
| 133233 | ** yy_reduce_ofst[] For each state, the offset into yy_action for |
| 133234 | ** shifting non-terminals after a reduce. |
| 133235 | ** yy_default[] Default action for each state. |
| 133236 | ** |
| 133237 | *********** Begin parsing tables **********************************************/ |
| 133238 | #define YY_ACTTAB_COUNT (1567) |
| 133239 | static const YYACTIONTYPE yy_action[] = { |
| 133240 | /* 0 */ 325, 832, 351, 825, 5, 203, 203, 819, 99, 100, |
| 133241 | /* 10 */ 90, 842, 842, 854, 857, 846, 846, 97, 97, 98, |
| 133242 | /* 20 */ 98, 98, 98, 301, 96, 96, 96, 96, 95, 95, |
| 133243 | /* 30 */ 94, 94, 94, 93, 351, 325, 977, 977, 824, 824, |
| 133244 | /* 40 */ 826, 947, 354, 99, 100, 90, 842, 842, 854, 857, |
| 133245 | /* 50 */ 846, 846, 97, 97, 98, 98, 98, 98, 338, 96, |
| 133246 | /* 60 */ 96, 96, 96, 95, 95, 94, 94, 94, 93, 351, |
| 133247 | /* 70 */ 95, 95, 94, 94, 94, 93, 351, 791, 977, 977, |
| 133248 | /* 80 */ 325, 94, 94, 94, 93, 351, 792, 75, 99, 100, |
| 133249 | /* 90 */ 90, 842, 842, 854, 857, 846, 846, 97, 97, 98, |
| 133250 | /* 100 */ 98, 98, 98, 450, 96, 96, 96, 96, 95, 95, |
| 133251 | /* 110 */ 94, 94, 94, 93, 351, 1333, 155, 155, 2, 325, |
| 133252 | /* 120 */ 275, 146, 132, 52, 52, 93, 351, 99, 100, 90, |
| 133253 | /* 130 */ 842, 842, 854, 857, 846, 846, 97, 97, 98, 98, |
| 133254 | /* 140 */ 98, 98, 101, 96, 96, 96, 96, 95, 95, 94, |
| 133255 | /* 150 */ 94, 94, 93, 351, 958, 958, 325, 268, 428, 413, |
| 133256 | /* 160 */ 411, 61, 752, 752, 99, 100, 90, 842, 842, 854, |
| 133257 | /* 170 */ 857, 846, 846, 97, 97, 98, 98, 98, 98, 60, |
| 133258 | /* 180 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, |
| 133259 | /* 190 */ 351, 325, 270, 329, 273, 277, 959, 960, 250, 99, |
| 133260 | /* 200 */ 100, 90, 842, 842, 854, 857, 846, 846, 97, 97, |
| 133261 | /* 210 */ 98, 98, 98, 98, 301, 96, 96, 96, 96, 95, |
| 133262 | /* 220 */ 95, 94, 94, 94, 93, 351, 325, 938, 1326, 698, |
| 133263 | /* 230 */ 706, 1326, 242, 412, 99, 100, 90, 842, 842, 854, |
| 133264 | /* 240 */ 857, 846, 846, 97, 97, 98, 98, 98, 98, 347, |
| 133265 | /* 250 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, |
| 133266 | /* 260 */ 351, 325, 938, 1327, 384, 699, 1327, 381, 379, 99, |
| 133267 | /* 270 */ 100, 90, 842, 842, 854, 857, 846, 846, 97, 97, |
| 133268 | /* 280 */ 98, 98, 98, 98, 701, 96, 96, 96, 96, 95, |
| 133269 | /* 290 */ 95, 94, 94, 94, 93, 351, 325, 92, 89, 178, |
| 133270 | /* 300 */ 833, 936, 373, 700, 99, 100, 90, 842, 842, 854, |
| 133271 | /* 310 */ 857, 846, 846, 97, 97, 98, 98, 98, 98, 375, |
| 133272 | /* 320 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, |
| 133273 | /* 330 */ 351, 325, 1276, 947, 354, 818, 936, 739, 739, 99, |
| 133274 | /* 340 */ 100, 90, 842, 842, 854, 857, 846, 846, 97, 97, |
| 133275 | /* 350 */ 98, 98, 98, 98, 230, 96, 96, 96, 96, 95, |
| 133276 | /* 360 */ 95, 94, 94, 94, 93, 351, 325, 969, 227, 92, |
| 133277 | /* 370 */ 89, 178, 373, 300, 99, 100, 90, 842, 842, 854, |
| 133278 | /* 380 */ 857, 846, 846, 97, 97, 98, 98, 98, 98, 921, |
| 133279 | /* 390 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, |
| 133280 | /* 400 */ 351, 325, 449, 447, 447, 447, 147, 737, 737, 99, |
| 133281 | /* 410 */ 100, 90, 842, 842, 854, 857, 846, 846, 97, 97, |
| 133282 | /* 420 */ 98, 98, 98, 98, 296, 96, 96, 96, 96, 95, |
| 133283 | /* 430 */ 95, 94, 94, 94, 93, 351, 325, 419, 231, 958, |
| 133284 | /* 440 */ 958, 158, 25, 422, 99, 100, 90, 842, 842, 854, |
| 133285 | /* 450 */ 857, 846, 846, 97, 97, 98, 98, 98, 98, 450, |
| 133286 | /* 460 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, |
| 133287 | /* 470 */ 351, 443, 224, 224, 420, 958, 958, 962, 325, 52, |
| 133288 | /* 480 */ 52, 959, 960, 176, 415, 78, 99, 100, 90, 842, |
| 133289 | /* 490 */ 842, 854, 857, 846, 846, 97, 97, 98, 98, 98, |
| 133290 | /* 500 */ 98, 379, 96, 96, 96, 96, 95, 95, 94, 94, |
| 133291 | /* 510 */ 94, 93, 351, 325, 428, 418, 298, 959, 960, 962, |
| 133292 | /* 520 */ 81, 99, 88, 90, 842, 842, 854, 857, 846, 846, |
| 133293 | /* 530 */ 97, 97, 98, 98, 98, 98, 717, 96, 96, 96, |
| 133294 | /* 540 */ 96, 95, 95, 94, 94, 94, 93, 351, 325, 843, |
| 133295 | /* 550 */ 843, 855, 858, 996, 318, 343, 379, 100, 90, 842, |
| 133296 | /* 560 */ 842, 854, 857, 846, 846, 97, 97, 98, 98, 98, |
| 133297 | /* 570 */ 98, 450, 96, 96, 96, 96, 95, 95, 94, 94, |
| 133298 | /* 580 */ 94, 93, 351, 325, 350, 350, 350, 260, 377, 340, |
| 133299 | /* 590 */ 929, 52, 52, 90, 842, 842, 854, 857, 846, 846, |
| 133300 | /* 600 */ 97, 97, 98, 98, 98, 98, 361, 96, 96, 96, |
| 133301 | /* 610 */ 96, 95, 95, 94, 94, 94, 93, 351, 86, 445, |
| 133302 | /* 620 */ 847, 3, 1203, 361, 360, 378, 344, 813, 958, 958, |
| 133303 | /* 630 */ 1300, 86, 445, 729, 3, 212, 169, 287, 405, 282, |
| 133304 | /* 640 */ 404, 199, 232, 450, 300, 760, 83, 84, 280, 245, |
| 133305 | /* 650 */ 262, 365, 251, 85, 352, 352, 92, 89, 178, 83, |
| 133306 | /* 660 */ 84, 242, 412, 52, 52, 448, 85, 352, 352, 246, |
| 133307 | /* 670 */ 959, 960, 194, 455, 670, 402, 399, 398, 448, 243, |
| 133308 | /* 680 */ 221, 114, 434, 776, 361, 450, 397, 268, 747, 224, |
| 133309 | /* 690 */ 224, 132, 132, 198, 832, 434, 452, 451, 428, 427, |
| 133310 | /* 700 */ 819, 415, 734, 713, 132, 52, 52, 832, 268, 452, |
| 133311 | /* 710 */ 451, 734, 194, 819, 363, 402, 399, 398, 450, 1271, |
| 133312 | /* 720 */ 1271, 23, 958, 958, 86, 445, 397, 3, 228, 429, |
| 133313 | /* 730 */ 895, 824, 824, 826, 827, 19, 203, 720, 52, 52, |
| 133314 | /* 740 */ 428, 408, 439, 249, 824, 824, 826, 827, 19, 229, |
| 133315 | /* 750 */ 403, 153, 83, 84, 761, 177, 241, 450, 721, 85, |
| 133316 | /* 760 */ 352, 352, 120, 157, 959, 960, 58, 977, 409, 355, |
| 133317 | /* 770 */ 330, 448, 268, 428, 430, 320, 790, 32, 32, 86, |
| 133318 | /* 780 */ 445, 776, 3, 341, 98, 98, 98, 98, 434, 96, |
| 133319 | /* 790 */ 96, 96, 96, 95, 95, 94, 94, 94, 93, 351, |
| 133320 | /* 800 */ 832, 120, 452, 451, 813, 887, 819, 83, 84, 977, |
| 133321 | /* 810 */ 813, 132, 410, 920, 85, 352, 352, 132, 407, 789, |
| 133322 | /* 820 */ 958, 958, 92, 89, 178, 917, 448, 262, 370, 261, |
| 133323 | /* 830 */ 82, 914, 80, 262, 370, 261, 776, 824, 824, 826, |
| 133324 | /* 840 */ 827, 19, 934, 434, 96, 96, 96, 96, 95, 95, |
| 133325 | /* 850 */ 94, 94, 94, 93, 351, 832, 74, 452, 451, 958, |
| 133326 | /* 860 */ 958, 819, 959, 960, 120, 92, 89, 178, 945, 2, |
| 133327 | /* 870 */ 918, 965, 268, 1, 976, 76, 445, 762, 3, 708, |
| 133328 | /* 880 */ 901, 901, 387, 958, 958, 757, 919, 371, 740, 778, |
| 133329 | /* 890 */ 756, 257, 824, 824, 826, 827, 19, 417, 741, 450, |
| 133330 | /* 900 */ 24, 959, 960, 83, 84, 369, 958, 958, 177, 226, |
| 133331 | /* 910 */ 85, 352, 352, 885, 315, 314, 313, 215, 311, 10, |
| 133332 | /* 920 */ 10, 683, 448, 349, 348, 959, 960, 909, 777, 157, |
| 133333 | /* 930 */ 120, 958, 958, 337, 776, 416, 711, 310, 450, 434, |
| 133334 | /* 940 */ 450, 321, 450, 791, 103, 200, 175, 450, 959, 960, |
| 133335 | /* 950 */ 908, 832, 792, 452, 451, 9, 9, 819, 10, 10, |
| 133336 | /* 960 */ 52, 52, 51, 51, 180, 716, 248, 10, 10, 171, |
| 133337 | /* 970 */ 170, 167, 339, 959, 960, 247, 984, 702, 702, 450, |
| 133338 | /* 980 */ 715, 233, 686, 982, 889, 983, 182, 914, 824, 824, |
| 133339 | /* 990 */ 826, 827, 19, 183, 256, 423, 132, 181, 394, 10, |
| 133340 | /* 1000 */ 10, 889, 891, 749, 958, 958, 917, 268, 985, 198, |
| 133341 | /* 1010 */ 985, 349, 348, 425, 415, 299, 817, 832, 326, 825, |
| 133342 | /* 1020 */ 120, 332, 133, 819, 268, 98, 98, 98, 98, 91, |
| 133343 | /* 1030 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, |
| 133344 | /* 1040 */ 351, 157, 810, 371, 382, 359, 959, 960, 358, 268, |
| 133345 | /* 1050 */ 450, 918, 368, 324, 824, 824, 826, 450, 709, 450, |
| 133346 | /* 1060 */ 264, 380, 889, 450, 877, 746, 253, 919, 255, 433, |
| 133347 | /* 1070 */ 36, 36, 234, 450, 234, 120, 269, 37, 37, 12, |
| 133348 | /* 1080 */ 12, 334, 272, 27, 27, 450, 330, 118, 450, 162, |
| 133349 | /* 1090 */ 742, 280, 450, 38, 38, 450, 985, 356, 985, 450, |
| 133350 | /* 1100 */ 709, 1210, 450, 132, 450, 39, 39, 450, 40, 40, |
| 133351 | /* 1110 */ 450, 362, 41, 41, 450, 42, 42, 450, 254, 28, |
| 133352 | /* 1120 */ 28, 450, 29, 29, 31, 31, 450, 43, 43, 450, |
| 133353 | /* 1130 */ 44, 44, 450, 714, 45, 45, 450, 11, 11, 767, |
| 133354 | /* 1140 */ 450, 46, 46, 450, 268, 450, 105, 105, 450, 47, |
| 133355 | /* 1150 */ 47, 450, 48, 48, 450, 237, 33, 33, 450, 172, |
| 133356 | /* 1160 */ 49, 49, 450, 50, 50, 34, 34, 274, 122, 122, |
| 133357 | /* 1170 */ 450, 123, 123, 450, 124, 124, 450, 898, 56, 56, |
| 133358 | /* 1180 */ 450, 897, 35, 35, 450, 267, 450, 817, 450, 817, |
| 133359 | /* 1190 */ 106, 106, 450, 53, 53, 385, 107, 107, 450, 817, |
| 133360 | /* 1200 */ 108, 108, 817, 450, 104, 104, 121, 121, 119, 119, |
| 133361 | /* 1210 */ 450, 117, 112, 112, 450, 276, 450, 225, 111, 111, |
| 133362 | /* 1220 */ 450, 730, 450, 109, 109, 450, 673, 674, 675, 912, |
| 133363 | /* 1230 */ 110, 110, 317, 998, 55, 55, 57, 57, 692, 331, |
| 133364 | /* 1240 */ 54, 54, 26, 26, 696, 30, 30, 317, 937, 197, |
| 133365 | /* 1250 */ 196, 195, 335, 281, 336, 446, 331, 745, 689, 436, |
| 133366 | /* 1260 */ 440, 444, 120, 72, 386, 223, 175, 345, 757, 933, |
| 133367 | /* 1270 */ 20, 286, 319, 756, 815, 372, 374, 202, 202, 202, |
| 133368 | /* 1280 */ 263, 395, 285, 74, 208, 21, 696, 719, 718, 884, |
| 133369 | /* 1290 */ 120, 120, 120, 120, 120, 754, 278, 828, 77, 74, |
| 133370 | /* 1300 */ 726, 727, 785, 783, 880, 202, 999, 208, 894, 893, |
| 133371 | /* 1310 */ 894, 893, 694, 816, 763, 116, 774, 1290, 431, 432, |
| 133372 | /* 1320 */ 302, 999, 390, 303, 823, 697, 691, 680, 159, 289, |
| 133373 | /* 1330 */ 679, 884, 681, 952, 291, 218, 293, 7, 316, 828, |
| 133374 | /* 1340 */ 173, 805, 259, 364, 252, 911, 376, 713, 295, 435, |
| 133375 | /* 1350 */ 308, 168, 955, 993, 135, 400, 990, 284, 882, 881, |
| 133376 | /* 1360 */ 205, 928, 926, 59, 333, 62, 144, 156, 130, 72, |
| 133377 | /* 1370 */ 802, 366, 367, 393, 137, 185, 189, 160, 139, 383, |
| 133378 | /* 1380 */ 67, 896, 140, 141, 142, 148, 389, 812, 775, 266, |
| 133379 | /* 1390 */ 219, 190, 154, 391, 913, 876, 271, 406, 191, 322, |
| 133380 | /* 1400 */ 682, 733, 192, 342, 732, 724, 731, 711, 723, 421, |
| 133381 | /* 1410 */ 705, 71, 323, 6, 204, 771, 288, 79, 297, 346, |
| 133382 | /* 1420 */ 772, 704, 290, 283, 703, 770, 292, 294, 967, 239, |
| 133383 | /* 1430 */ 769, 102, 862, 438, 426, 240, 424, 442, 73, 213, |
| 133384 | /* 1440 */ 688, 238, 22, 453, 953, 214, 217, 216, 454, 677, |
| 133385 | /* 1450 */ 676, 671, 753, 125, 115, 235, 126, 669, 353, 166, |
| 133386 | /* 1460 */ 127, 244, 179, 357, 306, 304, 305, 307, 113, 892, |
| 133387 | /* 1470 */ 327, 890, 811, 328, 134, 128, 136, 138, 743, 258, |
| 133388 | /* 1480 */ 907, 184, 143, 129, 910, 186, 63, 64, 145, 187, |
| 133389 | /* 1490 */ 906, 65, 8, 66, 13, 188, 202, 899, 265, 149, |
| 133390 | /* 1500 */ 987, 388, 150, 685, 161, 392, 285, 193, 279, 396, |
| 133391 | /* 1510 */ 151, 401, 68, 14, 15, 722, 69, 236, 831, 131, |
| 133392 | /* 1520 */ 830, 860, 70, 751, 16, 414, 755, 4, 174, 220, |
| 133393 | /* 1530 */ 222, 784, 201, 152, 779, 77, 74, 17, 18, 875, |
| 133394 | /* 1540 */ 861, 859, 916, 864, 915, 207, 206, 942, 163, 437, |
| 133395 | /* 1550 */ 948, 943, 164, 209, 1002, 441, 863, 165, 210, 829, |
| 133396 | /* 1560 */ 695, 87, 312, 211, 1292, 1291, 309, |
| 133397 | }; |
| 133398 | static const YYCODETYPE yy_lookahead[] = { |
| 133399 | /* 0 */ 19, 95, 53, 97, 22, 24, 24, 101, 27, 28, |
| 133400 | /* 10 */ 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, |
| 133401 | /* 20 */ 39, 40, 41, 152, 43, 44, 45, 46, 47, 48, |
| @@ -133415,87 +133477,86 @@ | |
| 133477 | /* 780 */ 20, 124, 22, 111, 38, 39, 40, 41, 83, 43, |
| 133478 | /* 790 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, |
| 133479 | /* 800 */ 95, 196, 97, 98, 85, 152, 101, 47, 48, 97, |
| 133480 | /* 810 */ 85, 92, 207, 193, 54, 55, 56, 92, 49, 175, |
| 133481 | /* 820 */ 55, 56, 221, 222, 223, 12, 66, 108, 109, 110, |
| 133482 | /* 830 */ 137, 163, 139, 108, 109, 110, 26, 132, 133, 134, |
| 133483 | /* 840 */ 135, 136, 152, 83, 43, 44, 45, 46, 47, 48, |
| 133484 | /* 850 */ 49, 50, 51, 52, 53, 95, 26, 97, 98, 55, |
| 133485 | /* 860 */ 56, 101, 97, 98, 196, 221, 222, 223, 146, 147, |
| 133486 | /* 870 */ 57, 171, 152, 22, 26, 19, 20, 49, 22, 179, |
| 133487 | /* 880 */ 108, 109, 110, 55, 56, 116, 73, 219, 75, 124, |
| 133488 | /* 890 */ 121, 152, 132, 133, 134, 135, 136, 163, 85, 152, |
| 133489 | /* 900 */ 232, 97, 98, 47, 48, 237, 55, 56, 98, 5, |
| 133490 | /* 910 */ 54, 55, 56, 193, 10, 11, 12, 13, 14, 172, |
| 133491 | /* 920 */ 173, 17, 66, 47, 48, 97, 98, 152, 124, 152, |
| 133492 | /* 930 */ 196, 55, 56, 186, 124, 152, 106, 160, 152, 83, |
| 133493 | /* 940 */ 152, 164, 152, 61, 22, 211, 212, 152, 97, 98, |
| 133494 | /* 950 */ 152, 95, 70, 97, 98, 172, 173, 101, 172, 173, |
| 133495 | /* 960 */ 172, 173, 172, 173, 60, 181, 62, 172, 173, 47, |
| 133496 | /* 970 */ 48, 123, 186, 97, 98, 71, 100, 55, 56, 152, |
| 133497 | /* 980 */ 181, 186, 21, 107, 152, 109, 82, 163, 132, 133, |
| 133498 | /* 990 */ 134, 135, 136, 89, 16, 207, 92, 93, 19, 172, |
| 133499 | /* 1000 */ 173, 169, 170, 195, 55, 56, 12, 152, 132, 30, |
| 133500 | /* 1010 */ 134, 47, 48, 186, 206, 225, 152, 95, 114, 97, |
| 133501 | /* 1020 */ 196, 245, 246, 101, 152, 38, 39, 40, 41, 42, |
| 133502 | /* 1030 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, |
| 133503 | /* 1040 */ 53, 152, 163, 219, 152, 141, 97, 98, 193, 152, |
| 133504 | /* 1050 */ 152, 57, 91, 164, 132, 133, 134, 152, 55, 152, |
| 133505 | /* 1060 */ 152, 237, 230, 152, 103, 193, 88, 73, 90, 75, |
| 133506 | /* 1070 */ 172, 173, 183, 152, 185, 196, 152, 172, 173, 172, |
| 133507 | /* 1080 */ 173, 217, 152, 172, 173, 152, 107, 22, 152, 24, |
| 133508 | /* 1090 */ 193, 112, 152, 172, 173, 152, 132, 242, 134, 152, |
| 133509 | /* 1100 */ 97, 140, 152, 92, 152, 172, 173, 152, 172, 173, |
| 133510 | /* 1110 */ 152, 100, 172, 173, 152, 172, 173, 152, 140, 172, |
| 133511 | /* 1120 */ 173, 152, 172, 173, 172, 173, 152, 172, 173, 152, |
| 133512 | /* 1130 */ 172, 173, 152, 152, 172, 173, 152, 172, 173, 213, |
| 133513 | /* 1140 */ 152, 172, 173, 152, 152, 152, 172, 173, 152, 172, |
| 133514 | /* 1150 */ 173, 152, 172, 173, 152, 210, 172, 173, 152, 26, |
| 133515 | /* 1160 */ 172, 173, 152, 172, 173, 172, 173, 152, 172, 173, |
| 133516 | /* 1170 */ 152, 172, 173, 152, 172, 173, 152, 59, 172, 173, |
| 133517 | /* 1180 */ 152, 63, 172, 173, 152, 193, 152, 152, 152, 152, |
| 133518 | /* 1190 */ 172, 173, 152, 172, 173, 77, 172, 173, 152, 152, |
| 133519 | /* 1200 */ 172, 173, 152, 152, 172, 173, 172, 173, 172, 173, |
| 133520 | /* 1210 */ 152, 22, 172, 173, 152, 152, 152, 22, 172, 173, |
| 133521 | /* 1220 */ 152, 152, 152, 172, 173, 152, 7, 8, 9, 163, |
| 133522 | /* 1230 */ 172, 173, 22, 23, 172, 173, 172, 173, 166, 167, |
| 133523 | /* 1240 */ 172, 173, 172, 173, 55, 172, 173, 22, 23, 108, |
| 133524 | /* 1250 */ 109, 110, 217, 152, 217, 166, 167, 163, 163, 163, |
| 133525 | /* 1260 */ 163, 163, 196, 130, 217, 211, 212, 217, 116, 23, |
| 133526 | /* 1270 */ 22, 101, 26, 121, 23, 23, 23, 26, 26, 26, |
| 133527 | /* 1280 */ 23, 23, 112, 26, 26, 37, 97, 100, 101, 55, |
| 133528 | /* 1290 */ 196, 196, 196, 196, 196, 23, 23, 55, 26, 26, |
| 133529 | /* 1300 */ 7, 8, 23, 152, 23, 26, 96, 26, 132, 132, |
| 133530 | /* 1310 */ 134, 134, 23, 152, 152, 26, 152, 122, 152, 191, |
| 133531 | /* 1320 */ 152, 96, 234, 152, 152, 152, 152, 152, 197, 210, |
| 133532 | /* 1330 */ 152, 97, 152, 152, 210, 233, 210, 198, 150, 97, |
| 133533 | /* 1340 */ 184, 201, 239, 214, 214, 201, 239, 180, 214, 227, |
| 133534 | /* 1350 */ 200, 198, 155, 67, 243, 176, 69, 175, 175, 175, |
| 133535 | /* 1360 */ 122, 159, 159, 240, 159, 240, 22, 220, 27, 130, |
| 133536 | /* 1370 */ 201, 18, 159, 18, 189, 158, 158, 220, 192, 159, |
| 133537 | /* 1380 */ 137, 236, 192, 192, 192, 189, 74, 189, 159, 235, |
| 133538 | /* 1390 */ 159, 158, 22, 177, 201, 201, 159, 107, 158, 177, |
| 133539 | /* 1400 */ 159, 174, 158, 76, 174, 182, 174, 106, 182, 125, |
| 133540 | /* 1410 */ 174, 107, 177, 22, 159, 216, 215, 137, 159, 53, |
| 133541 | /* 1420 */ 216, 176, 215, 174, 174, 216, 215, 215, 174, 229, |
| 133542 | /* 1430 */ 216, 129, 224, 177, 126, 229, 127, 177, 128, 25, |
| 133543 | /* 1440 */ 162, 226, 26, 161, 13, 153, 6, 153, 151, 151, |
| 133544 | /* 1450 */ 151, 151, 205, 165, 178, 178, 165, 4, 3, 22, |
| 133545 | /* 1460 */ 165, 142, 15, 94, 202, 204, 203, 201, 16, 23, |
| 133546 | /* 1470 */ 249, 23, 120, 249, 246, 111, 131, 123, 20, 16, |
| 133547 | /* 1480 */ 1, 125, 123, 111, 56, 64, 37, 37, 131, 122, |
| 133548 | /* 1490 */ 1, 37, 5, 37, 22, 107, 26, 80, 140, 80, |
| 133549 | /* 1500 */ 87, 72, 107, 20, 24, 19, 112, 105, 23, 79, |
| 133550 | /* 1510 */ 22, 79, 22, 22, 22, 58, 22, 79, 23, 68, |
| 133551 | /* 1520 */ 23, 23, 26, 116, 22, 26, 23, 22, 122, 23, |
| 133552 | /* 1530 */ 23, 56, 64, 22, 124, 26, 26, 64, 64, 23, |
| 133553 | /* 1540 */ 23, 23, 23, 11, 23, 22, 26, 23, 22, 24, |
| 133554 | /* 1550 */ 1, 23, 22, 26, 251, 24, 23, 22, 122, 23, |
| 133555 | /* 1560 */ 23, 22, 15, 122, 122, 122, 23, |
| 133556 | }; |
| 133557 | #define YY_SHIFT_USE_DFLT (1567) |
| 133558 | #define YY_SHIFT_COUNT (455) |
| 133559 | #define YY_SHIFT_MIN (-94) |
| 133560 | #define YY_SHIFT_MAX (1549) |
| 133561 | static const short yy_shift_ofst[] = { |
| 133562 | /* 0 */ 40, 599, 904, 612, 760, 760, 760, 760, 725, -19, |
| @@ -133507,132 +133568,132 @@ | |
| 133568 | /* 60 */ 760, 760, 760, 760, 760, 760, 760, 760, 760, 760, |
| 133569 | /* 70 */ 760, 760, 760, 760, 760, 760, 760, 760, 760, 760, |
| 133570 | /* 80 */ 760, 760, 760, 760, 760, 760, 760, 760, 760, 760, |
| 133571 | /* 90 */ 856, 760, 760, 760, 760, 760, 760, 760, 760, 760, |
| 133572 | /* 100 */ 760, 760, 760, 760, 987, 746, 746, 746, 746, 746, |
| 133573 | /* 110 */ 801, 23, 32, 949, 961, 979, 964, 964, 949, 73, |
| 133574 | /* 120 */ 113, -51, 1567, 1567, 1567, 536, 536, 536, 99, 99, |
| 133575 | /* 130 */ 813, 813, 667, 205, 240, 949, 949, 949, 949, 949, |
| 133576 | /* 140 */ 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, |
| 133577 | /* 150 */ 949, 949, 949, 949, 949, 332, 1011, 422, 422, 113, |
| 133578 | /* 160 */ 30, 30, 30, 30, 30, 30, 1567, 1567, 1567, 922, |
| 133579 | /* 170 */ -94, -94, 384, 613, 828, 420, 765, 804, 851, 949, |
| 133580 | /* 180 */ 949, 949, 949, 949, 949, 949, 949, 949, 949, 949, |
| 133581 | /* 190 */ 949, 949, 949, 949, 949, 672, 672, 672, 949, 949, |
| 133582 | /* 200 */ 657, 949, 949, 949, -18, 949, 949, 994, 949, 949, |
| 133583 | /* 210 */ 949, 949, 949, 949, 949, 949, 949, 949, 772, 1118, |
| 133584 | /* 220 */ 712, 712, 712, 810, 45, 769, 1219, 1133, 418, 418, |
| 133585 | /* 230 */ 569, 1133, 569, 830, 607, 663, 882, 418, 693, 882, |
| 133586 | /* 240 */ 882, 848, 1152, 1065, 1286, 1238, 1238, 1287, 1287, 1238, |
| 133587 | /* 250 */ 1344, 1341, 1239, 1353, 1353, 1353, 1353, 1238, 1355, 1239, |
| 133588 | /* 260 */ 1344, 1341, 1341, 1239, 1238, 1355, 1243, 1312, 1238, 1238, |
| 133589 | /* 270 */ 1355, 1370, 1238, 1355, 1238, 1355, 1370, 1290, 1290, 1290, |
| 133590 | /* 280 */ 1327, 1370, 1290, 1301, 1290, 1327, 1290, 1290, 1284, 1304, |
| 133591 | /* 290 */ 1284, 1304, 1284, 1304, 1284, 1304, 1238, 1391, 1238, 1280, |
| 133592 | /* 300 */ 1370, 1366, 1366, 1370, 1302, 1308, 1310, 1309, 1239, 1414, |
| 133593 | /* 310 */ 1416, 1431, 1431, 1440, 1440, 1440, 1440, 1567, 1567, 1567, |
| 133594 | /* 320 */ 1567, 1567, 1567, 1567, 1567, 519, 978, 1210, 1225, 104, |
| 133595 | /* 330 */ 1141, 1189, 1246, 1248, 1251, 1252, 1253, 1257, 1258, 1273, |
| 133596 | /* 340 */ 1003, 1187, 1293, 1170, 1272, 1279, 1234, 1281, 1176, 1177, |
| 133597 | /* 350 */ 1289, 1242, 1195, 1453, 1455, 1437, 1319, 1447, 1369, 1452, |
| 133598 | /* 360 */ 1446, 1448, 1352, 1345, 1364, 1354, 1458, 1356, 1463, 1479, |
| 133599 | /* 370 */ 1359, 1357, 1449, 1450, 1454, 1456, 1372, 1428, 1421, 1367, |
| 133600 | /* 380 */ 1489, 1487, 1472, 1388, 1358, 1417, 1470, 1419, 1413, 1429, |
| 133601 | /* 390 */ 1395, 1480, 1483, 1486, 1394, 1402, 1488, 1430, 1490, 1491, |
| 133602 | /* 400 */ 1485, 1492, 1432, 1457, 1494, 1438, 1451, 1495, 1497, 1498, |
| 133603 | /* 410 */ 1496, 1407, 1502, 1503, 1505, 1499, 1406, 1506, 1507, 1475, |
| 133604 | /* 420 */ 1468, 1511, 1410, 1509, 1473, 1510, 1474, 1516, 1509, 1517, |
| 133605 | /* 430 */ 1518, 1519, 1520, 1521, 1523, 1532, 1524, 1526, 1525, 1527, |
| 133606 | /* 440 */ 1528, 1530, 1531, 1527, 1533, 1535, 1536, 1537, 1539, 1436, |
| 133607 | /* 450 */ 1441, 1442, 1443, 1543, 1547, 1549, |
| 133608 | }; |
| 133609 | #define YY_REDUCE_USE_DFLT (-130) |
| 133610 | #define YY_REDUCE_COUNT (324) |
| 133611 | #define YY_REDUCE_MIN (-129) |
| 133612 | #define YY_REDUCE_MAX (1300) |
| 133613 | static const short yy_reduce_ofst[] = { |
| 133614 | /* 0 */ -29, 566, 525, 605, -49, 307, 491, 533, 668, 435, |
| 133615 | /* 10 */ 601, 644, 148, 747, 786, 795, 419, 788, 827, 790, |
| 133616 | /* 20 */ 454, 832, 889, 495, 824, 734, 76, 76, 76, 76, |
| 133617 | /* 30 */ 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, |
| 133618 | /* 40 */ 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, |
| 133619 | /* 50 */ 76, 76, 76, 76, 76, 76, 76, 76, 783, 898, |
| 133620 | /* 60 */ 905, 907, 911, 921, 933, 936, 940, 943, 947, 950, |
| 133621 | /* 70 */ 952, 955, 958, 962, 965, 969, 974, 977, 980, 984, |
| 133622 | /* 80 */ 988, 991, 993, 996, 999, 1002, 1006, 1010, 1018, 1021, |
| 133623 | /* 90 */ 1024, 1028, 1032, 1034, 1036, 1040, 1046, 1051, 1058, 1062, |
| 133624 | /* 100 */ 1064, 1068, 1070, 1073, 76, 76, 76, 76, 76, 76, |
| 133625 | /* 110 */ 76, 76, 76, 855, 36, 523, 235, 416, 777, 76, |
| 133626 | /* 120 */ 278, 76, 76, 76, 76, 700, 700, 700, 150, 220, |
| 133627 | /* 130 */ 147, 217, 221, 306, 306, 611, 5, 535, 556, 620, |
| 133628 | /* 140 */ 720, 872, 897, 116, 864, 349, 1035, 1037, 404, 1047, |
| 133629 | /* 150 */ 992, -129, 1050, 492, 62, 722, 879, 1072, 1089, 808, |
| 133630 | /* 160 */ 1066, 1094, 1095, 1096, 1097, 1098, 776, 1054, 557, 57, |
| 133631 | /* 170 */ 112, 131, 167, 182, 250, 272, 291, 331, 364, 438, |
| 133632 | /* 180 */ 497, 517, 591, 653, 690, 739, 775, 798, 892, 908, |
| 133633 | /* 190 */ 924, 930, 1015, 1063, 1069, 355, 784, 799, 981, 1101, |
| 133634 | /* 200 */ 926, 1151, 1161, 1162, 945, 1164, 1166, 1128, 1168, 1171, |
| 133635 | /* 210 */ 1172, 250, 1173, 1174, 1175, 1178, 1180, 1181, 1088, 1102, |
| 133636 | /* 220 */ 1119, 1124, 1126, 926, 1131, 1139, 1188, 1140, 1129, 1130, |
| 133637 | /* 230 */ 1103, 1144, 1107, 1179, 1156, 1167, 1182, 1134, 1122, 1183, |
| 133638 | /* 240 */ 1184, 1150, 1153, 1197, 1111, 1202, 1203, 1123, 1125, 1205, |
| 133639 | /* 250 */ 1147, 1185, 1169, 1186, 1190, 1191, 1192, 1213, 1217, 1193, |
| 133640 | /* 260 */ 1157, 1196, 1198, 1194, 1220, 1218, 1145, 1154, 1229, 1231, |
| 133641 | /* 270 */ 1233, 1216, 1237, 1240, 1241, 1244, 1222, 1227, 1230, 1232, |
| 133642 | /* 280 */ 1223, 1235, 1236, 1245, 1249, 1226, 1250, 1254, 1199, 1201, |
| 133643 | /* 290 */ 1204, 1207, 1209, 1211, 1214, 1212, 1255, 1208, 1259, 1215, |
| 133644 | /* 300 */ 1256, 1200, 1206, 1260, 1247, 1261, 1263, 1262, 1266, 1278, |
| 133645 | /* 310 */ 1282, 1292, 1294, 1297, 1298, 1299, 1300, 1221, 1224, 1228, |
| 133646 | /* 320 */ 1288, 1291, 1276, 1277, 1295, |
| 133647 | }; |
| 133648 | static const YYACTIONTYPE yy_default[] = { |
| 133649 | /* 0 */ 1281, 1271, 1271, 1271, 1203, 1203, 1203, 1203, 1271, 1096, |
| 133650 | /* 10 */ 1125, 1125, 1255, 1332, 1332, 1332, 1332, 1332, 1332, 1202, |
| 133651 | /* 20 */ 1332, 1332, 1332, 1332, 1271, 1100, 1131, 1332, 1332, 1332, |
| 133652 | /* 30 */ 1332, 1204, 1205, 1332, 1332, 1332, 1254, 1256, 1141, 1140, |
| 133653 | /* 40 */ 1139, 1138, 1237, 1112, 1136, 1129, 1133, 1204, 1198, 1199, |
| 133654 | /* 50 */ 1197, 1201, 1205, 1332, 1132, 1167, 1182, 1166, 1332, 1332, |
| 133655 | /* 60 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, |
| 133656 | /* 70 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, |
| 133657 | /* 80 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, |
| 133658 | /* 90 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, |
| 133659 | /* 100 */ 1332, 1332, 1332, 1332, 1176, 1181, 1188, 1180, 1177, 1169, |
| 133660 | /* 110 */ 1168, 1170, 1171, 1332, 1019, 1067, 1332, 1332, 1332, 1172, |
| 133661 | /* 120 */ 1332, 1173, 1185, 1184, 1183, 1262, 1289, 1288, 1332, 1332, |
| 133662 | /* 130 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, |
| 133663 | /* 140 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, |
| 133664 | /* 150 */ 1332, 1332, 1332, 1332, 1332, 1281, 1271, 1025, 1025, 1332, |
| 133665 | /* 160 */ 1271, 1271, 1271, 1271, 1271, 1271, 1267, 1100, 1091, 1332, |
| 133666 | /* 170 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, |
| 133667 | /* 180 */ 1259, 1257, 1332, 1218, 1332, 1332, 1332, 1332, 1332, 1332, |
| 133668 | /* 190 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, |
| 133669 | /* 200 */ 1332, 1332, 1332, 1332, 1096, 1332, 1332, 1332, 1332, 1332, |
| 133670 | /* 210 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1283, 1332, 1232, |
| 133671 | /* 220 */ 1096, 1096, 1096, 1098, 1080, 1090, 1004, 1135, 1114, 1114, |
| 133672 | /* 230 */ 1321, 1135, 1321, 1042, 1303, 1039, 1125, 1114, 1200, 1125, |
| 133673 | /* 240 */ 1125, 1097, 1090, 1332, 1324, 1105, 1105, 1323, 1323, 1105, |
| 133674 | /* 250 */ 1146, 1070, 1135, 1076, 1076, 1076, 1076, 1105, 1016, 1135, |
| 133675 | /* 260 */ 1146, 1070, 1070, 1135, 1105, 1016, 1236, 1318, 1105, 1105, |
| 133676 | /* 270 */ 1016, 1211, 1105, 1016, 1105, 1016, 1211, 1068, 1068, 1068, |
| 133677 | /* 280 */ 1057, 1211, 1068, 1042, 1068, 1057, 1068, 1068, 1118, 1113, |
| 133678 | /* 290 */ 1118, 1113, 1118, 1113, 1118, 1113, 1105, 1206, 1105, 1332, |
| 133679 | /* 300 */ 1211, 1215, 1215, 1211, 1130, 1119, 1128, 1126, 1135, 1022, |
| 133680 | /* 310 */ 1060, 1286, 1286, 1282, 1282, 1282, 1282, 1329, 1329, 1267, |
| 133681 | /* 320 */ 1298, 1298, 1044, 1044, 1298, 1332, 1332, 1332, 1332, 1332, |
| 133682 | /* 330 */ 1332, 1293, 1332, 1220, 1332, 1332, 1332, 1332, 1332, 1332, |
| 133683 | /* 340 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, |
| 133684 | /* 350 */ 1332, 1332, 1152, 1332, 1000, 1264, 1332, 1332, 1263, 1332, |
| 133685 | /* 360 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, |
| 133686 | /* 370 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1320, |
| 133687 | /* 380 */ 1332, 1332, 1332, 1332, 1332, 1332, 1235, 1234, 1332, 1332, |
| 133688 | /* 390 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, |
| 133689 | /* 400 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, |
| 133690 | /* 410 */ 1332, 1082, 1332, 1332, 1332, 1307, 1332, 1332, 1332, 1332, |
| 133691 | /* 420 */ 1332, 1332, 1332, 1127, 1332, 1120, 1332, 1332, 1311, 1332, |
| 133692 | /* 430 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1273, |
| 133693 | /* 440 */ 1332, 1332, 1332, 1272, 1332, 1332, 1332, 1332, 1332, 1154, |
| 133694 | /* 450 */ 1332, 1153, 1157, 1332, 1010, 1332, |
| 133695 | }; |
| 133696 | /********** End of lemon-generated parsing tables *****************************/ |
| 133697 | |
| 133698 | /* The next table maps tokens (terminal symbols) into fallback tokens. |
| 133699 | ** If a construct like the following: |
| @@ -133862,11 +133923,11 @@ | |
| 133923 | "DEFERRABLE", "FOREIGN", "DROP", "UNION", |
| 133924 | "ALL", "EXCEPT", "INTERSECT", "SELECT", |
| 133925 | "VALUES", "DISTINCT", "DOT", "FROM", |
| 133926 | "JOIN", "USING", "ORDER", "GROUP", |
| 133927 | "HAVING", "LIMIT", "WHERE", "INTO", |
| 133928 | "FLOAT", "BLOB", "INTEGER", "VARIABLE", |
| 133929 | "CASE", "WHEN", "THEN", "ELSE", |
| 133930 | "INDEX", "ALTER", "ADD", "error", |
| 133931 | "input", "cmdlist", "ecmd", "explain", |
| 133932 | "cmdx", "cmd", "transtype", "trans_opt", |
| 133933 | "nm", "savepoint_opt", "create_table", "create_table_args", |
| @@ -134055,185 +134116,186 @@ | |
| 134116 | /* 151 */ "term ::= NULL", |
| 134117 | /* 152 */ "expr ::= ID|INDEXED", |
| 134118 | /* 153 */ "expr ::= JOIN_KW", |
| 134119 | /* 154 */ "expr ::= nm DOT nm", |
| 134120 | /* 155 */ "expr ::= nm DOT nm DOT nm", |
| 134121 | /* 156 */ "term ::= FLOAT|BLOB", |
| 134122 | /* 157 */ "term ::= STRING", |
| 134123 | /* 158 */ "term ::= INTEGER", |
| 134124 | /* 159 */ "expr ::= VARIABLE", |
| 134125 | /* 160 */ "expr ::= expr COLLATE ID|STRING", |
| 134126 | /* 161 */ "expr ::= CAST LP expr AS typetoken RP", |
| 134127 | /* 162 */ "expr ::= ID|INDEXED LP distinct exprlist RP", |
| 134128 | /* 163 */ "expr ::= ID|INDEXED LP STAR RP", |
| 134129 | /* 164 */ "term ::= CTIME_KW", |
| 134130 | /* 165 */ "expr ::= LP nexprlist COMMA expr RP", |
| 134131 | /* 166 */ "expr ::= expr AND expr", |
| 134132 | /* 167 */ "expr ::= expr OR expr", |
| 134133 | /* 168 */ "expr ::= expr LT|GT|GE|LE expr", |
| 134134 | /* 169 */ "expr ::= expr EQ|NE expr", |
| 134135 | /* 170 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr", |
| 134136 | /* 171 */ "expr ::= expr PLUS|MINUS expr", |
| 134137 | /* 172 */ "expr ::= expr STAR|SLASH|REM expr", |
| 134138 | /* 173 */ "expr ::= expr CONCAT expr", |
| 134139 | /* 174 */ "likeop ::= LIKE_KW|MATCH", |
| 134140 | /* 175 */ "likeop ::= NOT LIKE_KW|MATCH", |
| 134141 | /* 176 */ "expr ::= expr likeop expr", |
| 134142 | /* 177 */ "expr ::= expr likeop expr ESCAPE expr", |
| 134143 | /* 178 */ "expr ::= expr ISNULL|NOTNULL", |
| 134144 | /* 179 */ "expr ::= expr NOT NULL", |
| 134145 | /* 180 */ "expr ::= expr IS expr", |
| 134146 | /* 181 */ "expr ::= expr IS NOT expr", |
| 134147 | /* 182 */ "expr ::= NOT expr", |
| 134148 | /* 183 */ "expr ::= BITNOT expr", |
| 134149 | /* 184 */ "expr ::= MINUS expr", |
| 134150 | /* 185 */ "expr ::= PLUS expr", |
| 134151 | /* 186 */ "between_op ::= BETWEEN", |
| 134152 | /* 187 */ "between_op ::= NOT BETWEEN", |
| 134153 | /* 188 */ "expr ::= expr between_op expr AND expr", |
| 134154 | /* 189 */ "in_op ::= IN", |
| 134155 | /* 190 */ "in_op ::= NOT IN", |
| 134156 | /* 191 */ "expr ::= expr in_op LP exprlist RP", |
| 134157 | /* 192 */ "expr ::= LP select RP", |
| 134158 | /* 193 */ "expr ::= expr in_op LP select RP", |
| 134159 | /* 194 */ "expr ::= expr in_op nm dbnm paren_exprlist", |
| 134160 | /* 195 */ "expr ::= EXISTS LP select RP", |
| 134161 | /* 196 */ "expr ::= CASE case_operand case_exprlist case_else END", |
| 134162 | /* 197 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr", |
| 134163 | /* 198 */ "case_exprlist ::= WHEN expr THEN expr", |
| 134164 | /* 199 */ "case_else ::= ELSE expr", |
| 134165 | /* 200 */ "case_else ::=", |
| 134166 | /* 201 */ "case_operand ::= expr", |
| 134167 | /* 202 */ "case_operand ::=", |
| 134168 | /* 203 */ "exprlist ::=", |
| 134169 | /* 204 */ "nexprlist ::= nexprlist COMMA expr", |
| 134170 | /* 205 */ "nexprlist ::= expr", |
| 134171 | /* 206 */ "paren_exprlist ::=", |
| 134172 | /* 207 */ "paren_exprlist ::= LP exprlist RP", |
| 134173 | /* 208 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt", |
| 134174 | /* 209 */ "uniqueflag ::= UNIQUE", |
| 134175 | /* 210 */ "uniqueflag ::=", |
| 134176 | /* 211 */ "eidlist_opt ::=", |
| 134177 | /* 212 */ "eidlist_opt ::= LP eidlist RP", |
| 134178 | /* 213 */ "eidlist ::= eidlist COMMA nm collate sortorder", |
| 134179 | /* 214 */ "eidlist ::= nm collate sortorder", |
| 134180 | /* 215 */ "collate ::=", |
| 134181 | /* 216 */ "collate ::= COLLATE ID|STRING", |
| 134182 | /* 217 */ "cmd ::= DROP INDEX ifexists fullname", |
| 134183 | /* 218 */ "cmd ::= VACUUM", |
| 134184 | /* 219 */ "cmd ::= VACUUM nm", |
| 134185 | /* 220 */ "cmd ::= PRAGMA nm dbnm", |
| 134186 | /* 221 */ "cmd ::= PRAGMA nm dbnm EQ nmnum", |
| 134187 | /* 222 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP", |
| 134188 | /* 223 */ "cmd ::= PRAGMA nm dbnm EQ minus_num", |
| 134189 | /* 224 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP", |
| 134190 | /* 225 */ "plus_num ::= PLUS INTEGER|FLOAT", |
| 134191 | /* 226 */ "minus_num ::= MINUS INTEGER|FLOAT", |
| 134192 | /* 227 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END", |
| 134193 | /* 228 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause", |
| 134194 | /* 229 */ "trigger_time ::= BEFORE", |
| 134195 | /* 230 */ "trigger_time ::= AFTER", |
| 134196 | /* 231 */ "trigger_time ::= INSTEAD OF", |
| 134197 | /* 232 */ "trigger_time ::=", |
| 134198 | /* 233 */ "trigger_event ::= DELETE|INSERT", |
| 134199 | /* 234 */ "trigger_event ::= UPDATE", |
| 134200 | /* 235 */ "trigger_event ::= UPDATE OF idlist", |
| 134201 | /* 236 */ "when_clause ::=", |
| 134202 | /* 237 */ "when_clause ::= WHEN expr", |
| 134203 | /* 238 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI", |
| 134204 | /* 239 */ "trigger_cmd_list ::= trigger_cmd SEMI", |
| 134205 | /* 240 */ "trnm ::= nm DOT nm", |
| 134206 | /* 241 */ "tridxby ::= INDEXED BY nm", |
| 134207 | /* 242 */ "tridxby ::= NOT INDEXED", |
| 134208 | /* 243 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt", |
| 134209 | /* 244 */ "trigger_cmd ::= insert_cmd INTO trnm idlist_opt select", |
| 134210 | /* 245 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt", |
| 134211 | /* 246 */ "trigger_cmd ::= select", |
| 134212 | /* 247 */ "expr ::= RAISE LP IGNORE RP", |
| 134213 | /* 248 */ "expr ::= RAISE LP raisetype COMMA nm RP", |
| 134214 | /* 249 */ "raisetype ::= ROLLBACK", |
| 134215 | /* 250 */ "raisetype ::= ABORT", |
| 134216 | /* 251 */ "raisetype ::= FAIL", |
| 134217 | /* 252 */ "cmd ::= DROP TRIGGER ifexists fullname", |
| 134218 | /* 253 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", |
| 134219 | /* 254 */ "cmd ::= DETACH database_kw_opt expr", |
| 134220 | /* 255 */ "key_opt ::=", |
| 134221 | /* 256 */ "key_opt ::= KEY expr", |
| 134222 | /* 257 */ "cmd ::= REINDEX", |
| 134223 | /* 258 */ "cmd ::= REINDEX nm dbnm", |
| 134224 | /* 259 */ "cmd ::= ANALYZE", |
| 134225 | /* 260 */ "cmd ::= ANALYZE nm dbnm", |
| 134226 | /* 261 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", |
| 134227 | /* 262 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist", |
| 134228 | /* 263 */ "add_column_fullname ::= fullname", |
| 134229 | /* 264 */ "cmd ::= create_vtab", |
| 134230 | /* 265 */ "cmd ::= create_vtab LP vtabarglist RP", |
| 134231 | /* 266 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm", |
| 134232 | /* 267 */ "vtabarg ::=", |
| 134233 | /* 268 */ "vtabargtoken ::= ANY", |
| 134234 | /* 269 */ "vtabargtoken ::= lp anylist RP", |
| 134235 | /* 270 */ "lp ::= LP", |
| 134236 | /* 271 */ "with ::=", |
| 134237 | /* 272 */ "with ::= WITH wqlist", |
| 134238 | /* 273 */ "with ::= WITH RECURSIVE wqlist", |
| 134239 | /* 274 */ "wqlist ::= nm eidlist_opt AS LP select RP", |
| 134240 | /* 275 */ "wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP", |
| 134241 | /* 276 */ "input ::= cmdlist", |
| 134242 | /* 277 */ "cmdlist ::= cmdlist ecmd", |
| 134243 | /* 278 */ "cmdlist ::= ecmd", |
| 134244 | /* 279 */ "ecmd ::= SEMI", |
| 134245 | /* 280 */ "ecmd ::= explain cmdx SEMI", |
| 134246 | /* 281 */ "explain ::=", |
| 134247 | /* 282 */ "trans_opt ::=", |
| 134248 | /* 283 */ "trans_opt ::= TRANSACTION", |
| 134249 | /* 284 */ "trans_opt ::= TRANSACTION nm", |
| 134250 | /* 285 */ "savepoint_opt ::= SAVEPOINT", |
| 134251 | /* 286 */ "savepoint_opt ::=", |
| 134252 | /* 287 */ "cmd ::= create_table create_table_args", |
| 134253 | /* 288 */ "columnlist ::= columnlist COMMA columnname carglist", |
| 134254 | /* 289 */ "columnlist ::= columnname carglist", |
| 134255 | /* 290 */ "nm ::= ID|INDEXED", |
| 134256 | /* 291 */ "nm ::= STRING", |
| 134257 | /* 292 */ "nm ::= JOIN_KW", |
| 134258 | /* 293 */ "typetoken ::= typename", |
| 134259 | /* 294 */ "typename ::= ID|STRING", |
| 134260 | /* 295 */ "signed ::= plus_num", |
| 134261 | /* 296 */ "signed ::= minus_num", |
| 134262 | /* 297 */ "carglist ::= carglist ccons", |
| 134263 | /* 298 */ "carglist ::=", |
| 134264 | /* 299 */ "ccons ::= NULL onconf", |
| 134265 | /* 300 */ "conslist_opt ::= COMMA conslist", |
| 134266 | /* 301 */ "conslist ::= conslist tconscomma tcons", |
| 134267 | /* 302 */ "conslist ::= tcons", |
| 134268 | /* 303 */ "tconscomma ::=", |
| 134269 | /* 304 */ "defer_subclause_opt ::= defer_subclause", |
| 134270 | /* 305 */ "resolvetype ::= raisetype", |
| 134271 | /* 306 */ "selectnowith ::= oneselect", |
| 134272 | /* 307 */ "oneselect ::= values", |
| 134273 | /* 308 */ "sclp ::= selcollist COMMA", |
| 134274 | /* 309 */ "as ::= ID|STRING", |
| 134275 | /* 310 */ "expr ::= term", |
| 134276 | /* 311 */ "exprlist ::= nexprlist", |
| 134277 | /* 312 */ "nmnum ::= plus_num", |
| 134278 | /* 313 */ "nmnum ::= nm", |
| 134279 | /* 314 */ "nmnum ::= ON", |
| 134280 | /* 315 */ "nmnum ::= DELETE", |
| 134281 | /* 316 */ "nmnum ::= DEFAULT", |
| 134282 | /* 317 */ "plus_num ::= INTEGER|FLOAT", |
| 134283 | /* 318 */ "foreach_clause ::=", |
| 134284 | /* 319 */ "foreach_clause ::= FOR EACH ROW", |
| 134285 | /* 320 */ "trnm ::= nm", |
| 134286 | /* 321 */ "tridxby ::=", |
| 134287 | /* 322 */ "database_kw_opt ::= DATABASE", |
| 134288 | /* 323 */ "database_kw_opt ::=", |
| 134289 | /* 324 */ "kwcolumn_opt ::=", |
| 134290 | /* 325 */ "kwcolumn_opt ::= COLUMNKW", |
| 134291 | /* 326 */ "vtabarglist ::= vtabarg", |
| 134292 | /* 327 */ "vtabarglist ::= vtabarglist COMMA vtabarg", |
| 134293 | /* 328 */ "vtabarg ::= vtabarg vtabargtoken", |
| 134294 | /* 329 */ "anylist ::=", |
| 134295 | /* 330 */ "anylist ::= anylist LP anylist RP", |
| 134296 | /* 331 */ "anylist ::= anylist ANY", |
| 134297 | }; |
| 134298 | #endif /* NDEBUG */ |
| 134299 | |
| 134300 | |
| 134301 | #if YYSTACKDEPTH<=0 |
| @@ -134811,10 +134873,11 @@ | |
| 134873 | { 173, 1 }, |
| 134874 | { 173, 3 }, |
| 134875 | { 173, 5 }, |
| 134876 | { 172, 1 }, |
| 134877 | { 172, 1 }, |
| 134878 | { 172, 1 }, |
| 134879 | { 173, 1 }, |
| 134880 | { 173, 3 }, |
| 134881 | { 173, 6 }, |
| 134882 | { 173, 5 }, |
| 134883 | { 173, 4 }, |
| @@ -135105,11 +135168,11 @@ | |
| 135168 | case 42: /* autoinc ::= */ yytestcase(yyruleno==42); |
| 135169 | case 57: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==57); |
| 135170 | case 67: /* defer_subclause_opt ::= */ yytestcase(yyruleno==67); |
| 135171 | case 76: /* ifexists ::= */ yytestcase(yyruleno==76); |
| 135172 | case 90: /* distinct ::= */ yytestcase(yyruleno==90); |
| 135173 | case 215: /* collate ::= */ yytestcase(yyruleno==215); |
| 135174 | {yymsp[1].minor.yy194 = 0;} |
| 135175 | break; |
| 135176 | case 17: /* ifnotexists ::= IF NOT EXISTS */ |
| 135177 | {yymsp[-2].minor.yy194 = 1;} |
| 135178 | break; |
| @@ -135249,13 +135312,13 @@ | |
| 135312 | case 144: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==144); |
| 135313 | {yymsp[-1].minor.yy194 = yymsp[0].minor.yy194;} |
| 135314 | break; |
| 135315 | case 58: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ |
| 135316 | case 75: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==75); |
| 135317 | case 187: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==187); |
| 135318 | case 190: /* in_op ::= NOT IN */ yytestcase(yyruleno==190); |
| 135319 | case 216: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==216); |
| 135320 | {yymsp[-1].minor.yy194 = 1;} |
| 135321 | break; |
| 135322 | case 59: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ |
| 135323 | {yymsp[-1].minor.yy194 = 0;} |
| 135324 | break; |
| @@ -135415,13 +135478,13 @@ | |
| 135478 | {yymsp[0].minor.yy194 = SF_All;} |
| 135479 | break; |
| 135480 | case 91: /* sclp ::= */ |
| 135481 | case 119: /* orderby_opt ::= */ yytestcase(yyruleno==119); |
| 135482 | case 126: /* groupby_opt ::= */ yytestcase(yyruleno==126); |
| 135483 | case 203: /* exprlist ::= */ yytestcase(yyruleno==203); |
| 135484 | case 206: /* paren_exprlist ::= */ yytestcase(yyruleno==206); |
| 135485 | case 211: /* eidlist_opt ::= */ yytestcase(yyruleno==211); |
| 135486 | {yymsp[1].minor.yy148 = 0;} |
| 135487 | break; |
| 135488 | case 92: /* selcollist ::= sclp expr as */ |
| 135489 | { |
| 135490 | yymsp[-2].minor.yy148 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy148, yymsp[-1].minor.yy190.pExpr); |
| @@ -135435,20 +135498,20 @@ | |
| 135498 | yymsp[-1].minor.yy148 = sqlite3ExprListAppend(pParse, yymsp[-1].minor.yy148, p); |
| 135499 | } |
| 135500 | break; |
| 135501 | case 94: /* selcollist ::= sclp nm DOT STAR */ |
| 135502 | { |
| 135503 | Expr *pRight = sqlite3PExpr(pParse, TK_ASTERISK, 0, 0, 0); |
| 135504 | Expr *pLeft = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0); |
| 135505 | Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0); |
| 135506 | yymsp[-3].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy148, pDot); |
| 135507 | } |
| 135508 | break; |
| 135509 | case 95: /* as ::= AS nm */ |
| 135510 | case 106: /* dbnm ::= DOT nm */ yytestcase(yyruleno==106); |
| 135511 | case 225: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==225); |
| 135512 | case 226: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==226); |
| 135513 | {yymsp[-1].minor.yy0 = yymsp[0].minor.yy0;} |
| 135514 | break; |
| 135515 | case 97: /* from ::= */ |
| 135516 | {yymsp[1].minor.yy185 = sqlite3DbMallocZero(pParse->db, sizeof(*yymsp[1].minor.yy185));} |
| 135517 | break; |
| @@ -135527,18 +135590,18 @@ | |
| 135590 | {yymsp[-3].minor.yy194 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/} |
| 135591 | break; |
| 135592 | case 112: /* on_opt ::= ON expr */ |
| 135593 | case 129: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==129); |
| 135594 | case 136: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==136); |
| 135595 | case 199: /* case_else ::= ELSE expr */ yytestcase(yyruleno==199); |
| 135596 | {yymsp[-1].minor.yy72 = yymsp[0].minor.yy190.pExpr;} |
| 135597 | break; |
| 135598 | case 113: /* on_opt ::= */ |
| 135599 | case 128: /* having_opt ::= */ yytestcase(yyruleno==128); |
| 135600 | case 135: /* where_opt ::= */ yytestcase(yyruleno==135); |
| 135601 | case 200: /* case_else ::= */ yytestcase(yyruleno==200); |
| 135602 | case 202: /* case_operand ::= */ yytestcase(yyruleno==202); |
| 135603 | {yymsp[1].minor.yy72 = 0;} |
| 135604 | break; |
| 135605 | case 115: /* indexed_opt ::= INDEXED BY nm */ |
| 135606 | {yymsp[-2].minor.yy0 = yymsp[0].minor.yy0;} |
| 135607 | break; |
| @@ -135650,41 +135713,51 @@ | |
| 135713 | break; |
| 135714 | case 150: /* expr ::= LP expr RP */ |
| 135715 | {spanSet(&yymsp[-2].minor.yy190,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-B*/ yymsp[-2].minor.yy190.pExpr = yymsp[-1].minor.yy190.pExpr;} |
| 135716 | break; |
| 135717 | case 151: /* term ::= NULL */ |
| 135718 | case 156: /* term ::= FLOAT|BLOB */ yytestcase(yyruleno==156); |
| 135719 | case 157: /* term ::= STRING */ yytestcase(yyruleno==157); |
| 135720 | {spanExpr(&yymsp[0].minor.yy190,pParse,yymsp[0].major,yymsp[0].minor.yy0);/*A-overwrites-X*/} |
| 135721 | break; |
| 135722 | case 152: /* expr ::= ID|INDEXED */ |
| 135723 | case 153: /* expr ::= JOIN_KW */ yytestcase(yyruleno==153); |
| 135724 | {spanExpr(&yymsp[0].minor.yy190,pParse,TK_ID,yymsp[0].minor.yy0); /*A-overwrites-X*/} |
| 135725 | break; |
| 135726 | case 154: /* expr ::= nm DOT nm */ |
| 135727 | { |
| 135728 | Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1); |
| 135729 | Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[0].minor.yy0, 1); |
| 135730 | spanSet(&yymsp[-2].minor.yy190,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ |
| 135731 | yymsp[-2].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0); |
| 135732 | } |
| 135733 | break; |
| 135734 | case 155: /* expr ::= nm DOT nm DOT nm */ |
| 135735 | { |
| 135736 | Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-4].minor.yy0, 1); |
| 135737 | Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1); |
| 135738 | Expr *temp3 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[0].minor.yy0, 1); |
| 135739 | Expr *temp4 = sqlite3PExpr(pParse, TK_DOT, temp2, temp3, 0); |
| 135740 | spanSet(&yymsp[-4].minor.yy190,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ |
| 135741 | yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp4, 0); |
| 135742 | } |
| 135743 | break; |
| 135744 | case 158: /* term ::= INTEGER */ |
| 135745 | { |
| 135746 | yylhsminor.yy190.pExpr = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &yymsp[0].minor.yy0, 1); |
| 135747 | yylhsminor.yy190.zStart = yymsp[0].minor.yy0.z; |
| 135748 | yylhsminor.yy190.zEnd = yymsp[0].minor.yy0.z + yymsp[0].minor.yy0.n; |
| 135749 | if( yylhsminor.yy190.pExpr ) yylhsminor.yy190.pExpr->flags |= EP_Leaf; |
| 135750 | } |
| 135751 | yymsp[0].minor.yy190 = yylhsminor.yy190; |
| 135752 | break; |
| 135753 | case 159: /* expr ::= VARIABLE */ |
| 135754 | { |
| 135755 | if( !(yymsp[0].minor.yy0.z[0]=='#' && sqlite3Isdigit(yymsp[0].minor.yy0.z[1])) ){ |
| 135756 | u32 n = yymsp[0].minor.yy0.n; |
| 135757 | spanExpr(&yymsp[0].minor.yy190, pParse, TK_VARIABLE, yymsp[0].minor.yy0); |
| 135758 | sqlite3ExprAssignVarNumber(pParse, yymsp[0].minor.yy190.pExpr, n); |
| 135759 | }else{ |
| 135760 | /* When doing a nested parse, one can include terms in an expression |
| 135761 | ** that look like this: #1 #2 ... These terms refer to registers |
| 135762 | ** in the virtual machine. #N is the N-th register. */ |
| 135763 | Token t = yymsp[0].minor.yy0; /*A-overwrites-X*/ |
| @@ -135692,29 +135765,29 @@ | |
| 135765 | spanSet(&yymsp[0].minor.yy190, &t, &t); |
| 135766 | if( pParse->nested==0 ){ |
| 135767 | sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &t); |
| 135768 | yymsp[0].minor.yy190.pExpr = 0; |
| 135769 | }else{ |
| 135770 | yymsp[0].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_REGISTER, 0, 0, 0); |
| 135771 | if( yymsp[0].minor.yy190.pExpr ) sqlite3GetInt32(&t.z[1], &yymsp[0].minor.yy190.pExpr->iTable); |
| 135772 | } |
| 135773 | } |
| 135774 | } |
| 135775 | break; |
| 135776 | case 160: /* expr ::= expr COLLATE ID|STRING */ |
| 135777 | { |
| 135778 | yymsp[-2].minor.yy190.pExpr = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy190.pExpr, &yymsp[0].minor.yy0, 1); |
| 135779 | yymsp[-2].minor.yy190.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; |
| 135780 | } |
| 135781 | break; |
| 135782 | case 161: /* expr ::= CAST LP expr AS typetoken RP */ |
| 135783 | { |
| 135784 | spanSet(&yymsp[-5].minor.yy190,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ |
| 135785 | yymsp[-5].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_CAST, yymsp[-3].minor.yy190.pExpr, 0, &yymsp[-1].minor.yy0); |
| 135786 | } |
| 135787 | break; |
| 135788 | case 162: /* expr ::= ID|INDEXED LP distinct exprlist RP */ |
| 135789 | { |
| 135790 | if( yymsp[-1].minor.yy148 && yymsp[-1].minor.yy148->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){ |
| 135791 | sqlite3ErrorMsg(pParse, "too many arguments on function %T", &yymsp[-4].minor.yy0); |
| 135792 | } |
| 135793 | yylhsminor.yy190.pExpr = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy148, &yymsp[-4].minor.yy0); |
| @@ -135723,25 +135796,25 @@ | |
| 135796 | yylhsminor.yy190.pExpr->flags |= EP_Distinct; |
| 135797 | } |
| 135798 | } |
| 135799 | yymsp[-4].minor.yy190 = yylhsminor.yy190; |
| 135800 | break; |
| 135801 | case 163: /* expr ::= ID|INDEXED LP STAR RP */ |
| 135802 | { |
| 135803 | yylhsminor.yy190.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0); |
| 135804 | spanSet(&yylhsminor.yy190,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); |
| 135805 | } |
| 135806 | yymsp[-3].minor.yy190 = yylhsminor.yy190; |
| 135807 | break; |
| 135808 | case 164: /* term ::= CTIME_KW */ |
| 135809 | { |
| 135810 | yylhsminor.yy190.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0); |
| 135811 | spanSet(&yylhsminor.yy190, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0); |
| 135812 | } |
| 135813 | yymsp[0].minor.yy190 = yylhsminor.yy190; |
| 135814 | break; |
| 135815 | case 165: /* expr ::= LP nexprlist COMMA expr RP */ |
| 135816 | { |
| 135817 | ExprList *pList = sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy148, yymsp[-1].minor.yy190.pExpr); |
| 135818 | yylhsminor.yy190.pExpr = sqlite3PExpr(pParse, TK_VECTOR, 0, 0, 0); |
| 135819 | if( yylhsminor.yy190.pExpr ){ |
| 135820 | yylhsminor.yy190.pExpr->x.pList = pList; |
| @@ -135750,82 +135823,86 @@ | |
| 135823 | sqlite3ExprListDelete(pParse->db, pList); |
| 135824 | } |
| 135825 | } |
| 135826 | yymsp[-4].minor.yy190 = yylhsminor.yy190; |
| 135827 | break; |
| 135828 | case 166: /* expr ::= expr AND expr */ |
| 135829 | case 167: /* expr ::= expr OR expr */ yytestcase(yyruleno==167); |
| 135830 | case 168: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==168); |
| 135831 | case 169: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==169); |
| 135832 | case 170: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==170); |
| 135833 | case 171: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==171); |
| 135834 | case 172: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==172); |
| 135835 | case 173: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==173); |
| 135836 | {spanBinaryExpr(pParse,yymsp[-1].major,&yymsp[-2].minor.yy190,&yymsp[0].minor.yy190);} |
| 135837 | break; |
| 135838 | case 174: /* likeop ::= LIKE_KW|MATCH */ |
| 135839 | {yymsp[0].minor.yy0=yymsp[0].minor.yy0;/*A-overwrites-X*/} |
| 135840 | break; |
| 135841 | case 175: /* likeop ::= NOT LIKE_KW|MATCH */ |
| 135842 | {yymsp[-1].minor.yy0=yymsp[0].minor.yy0; yymsp[-1].minor.yy0.n|=0x80000000; /*yymsp[-1].minor.yy0-overwrite-yymsp[0].minor.yy0*/} |
| 135843 | break; |
| 135844 | case 176: /* expr ::= expr likeop expr */ |
| 135845 | { |
| 135846 | ExprList *pList; |
| 135847 | int bNot = yymsp[-1].minor.yy0.n & 0x80000000; |
| 135848 | yymsp[-1].minor.yy0.n &= 0x7fffffff; |
| 135849 | pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy190.pExpr); |
| 135850 | pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy190.pExpr); |
| 135851 | yymsp[-2].minor.yy190.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0); |
| 135852 | exprNot(pParse, bNot, &yymsp[-2].minor.yy190); |
| 135853 | yymsp[-2].minor.yy190.zEnd = yymsp[0].minor.yy190.zEnd; |
| 135854 | if( yymsp[-2].minor.yy190.pExpr ) yymsp[-2].minor.yy190.pExpr->flags |= EP_InfixFunc; |
| 135855 | } |
| 135856 | break; |
| 135857 | case 177: /* expr ::= expr likeop expr ESCAPE expr */ |
| 135858 | { |
| 135859 | ExprList *pList; |
| 135860 | int bNot = yymsp[-3].minor.yy0.n & 0x80000000; |
| 135861 | yymsp[-3].minor.yy0.n &= 0x7fffffff; |
| 135862 | pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy190.pExpr); |
| 135863 | pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy190.pExpr); |
| 135864 | pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy190.pExpr); |
| 135865 | yymsp[-4].minor.yy190.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy0); |
| 135866 | exprNot(pParse, bNot, &yymsp[-4].minor.yy190); |
| 135867 | yymsp[-4].minor.yy190.zEnd = yymsp[0].minor.yy190.zEnd; |
| 135868 | if( yymsp[-4].minor.yy190.pExpr ) yymsp[-4].minor.yy190.pExpr->flags |= EP_InfixFunc; |
| 135869 | } |
| 135870 | break; |
| 135871 | case 178: /* expr ::= expr ISNULL|NOTNULL */ |
| 135872 | {spanUnaryPostfix(pParse,yymsp[0].major,&yymsp[-1].minor.yy190,&yymsp[0].minor.yy0);} |
| 135873 | break; |
| 135874 | case 179: /* expr ::= expr NOT NULL */ |
| 135875 | {spanUnaryPostfix(pParse,TK_NOTNULL,&yymsp[-2].minor.yy190,&yymsp[0].minor.yy0);} |
| 135876 | break; |
| 135877 | case 180: /* expr ::= expr IS expr */ |
| 135878 | { |
| 135879 | spanBinaryExpr(pParse,TK_IS,&yymsp[-2].minor.yy190,&yymsp[0].minor.yy190); |
| 135880 | binaryToUnaryIfNull(pParse, yymsp[0].minor.yy190.pExpr, yymsp[-2].minor.yy190.pExpr, TK_ISNULL); |
| 135881 | } |
| 135882 | break; |
| 135883 | case 181: /* expr ::= expr IS NOT expr */ |
| 135884 | { |
| 135885 | spanBinaryExpr(pParse,TK_ISNOT,&yymsp[-3].minor.yy190,&yymsp[0].minor.yy190); |
| 135886 | binaryToUnaryIfNull(pParse, yymsp[0].minor.yy190.pExpr, yymsp[-3].minor.yy190.pExpr, TK_NOTNULL); |
| 135887 | } |
| 135888 | break; |
| 135889 | case 182: /* expr ::= NOT expr */ |
| 135890 | case 183: /* expr ::= BITNOT expr */ yytestcase(yyruleno==183); |
| 135891 | {spanUnaryPrefix(&yymsp[-1].minor.yy190,pParse,yymsp[-1].major,&yymsp[0].minor.yy190,&yymsp[-1].minor.yy0);/*A-overwrites-B*/} |
| 135892 | break; |
| 135893 | case 184: /* expr ::= MINUS expr */ |
| 135894 | {spanUnaryPrefix(&yymsp[-1].minor.yy190,pParse,TK_UMINUS,&yymsp[0].minor.yy190,&yymsp[-1].minor.yy0);/*A-overwrites-B*/} |
| 135895 | break; |
| 135896 | case 185: /* expr ::= PLUS expr */ |
| 135897 | {spanUnaryPrefix(&yymsp[-1].minor.yy190,pParse,TK_UPLUS,&yymsp[0].minor.yy190,&yymsp[-1].minor.yy0);/*A-overwrites-B*/} |
| 135898 | break; |
| 135899 | case 186: /* between_op ::= BETWEEN */ |
| 135900 | case 189: /* in_op ::= IN */ yytestcase(yyruleno==189); |
| 135901 | {yymsp[0].minor.yy194 = 0;} |
| 135902 | break; |
| 135903 | case 188: /* expr ::= expr between_op expr AND expr */ |
| 135904 | { |
| 135905 | ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy190.pExpr); |
| 135906 | pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy190.pExpr); |
| 135907 | yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy190.pExpr, 0, 0); |
| 135908 | if( yymsp[-4].minor.yy190.pExpr ){ |
| @@ -135835,11 +135912,11 @@ | |
| 135912 | } |
| 135913 | exprNot(pParse, yymsp[-3].minor.yy194, &yymsp[-4].minor.yy190); |
| 135914 | yymsp[-4].minor.yy190.zEnd = yymsp[0].minor.yy190.zEnd; |
| 135915 | } |
| 135916 | break; |
| 135917 | case 191: /* expr ::= expr in_op LP exprlist RP */ |
| 135918 | { |
| 135919 | if( yymsp[-1].minor.yy148==0 ){ |
| 135920 | /* Expressions of the form |
| 135921 | ** |
| 135922 | ** expr1 IN () |
| @@ -135888,26 +135965,26 @@ | |
| 135965 | exprNot(pParse, yymsp[-3].minor.yy194, &yymsp[-4].minor.yy190); |
| 135966 | } |
| 135967 | yymsp[-4].minor.yy190.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; |
| 135968 | } |
| 135969 | break; |
| 135970 | case 192: /* expr ::= LP select RP */ |
| 135971 | { |
| 135972 | spanSet(&yymsp[-2].minor.yy190,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-B*/ |
| 135973 | yymsp[-2].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0); |
| 135974 | sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy190.pExpr, yymsp[-1].minor.yy243); |
| 135975 | } |
| 135976 | break; |
| 135977 | case 193: /* expr ::= expr in_op LP select RP */ |
| 135978 | { |
| 135979 | yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy190.pExpr, 0, 0); |
| 135980 | sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy190.pExpr, yymsp[-1].minor.yy243); |
| 135981 | exprNot(pParse, yymsp[-3].minor.yy194, &yymsp[-4].minor.yy190); |
| 135982 | yymsp[-4].minor.yy190.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; |
| 135983 | } |
| 135984 | break; |
| 135985 | case 194: /* expr ::= expr in_op nm dbnm paren_exprlist */ |
| 135986 | { |
| 135987 | SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0); |
| 135988 | Select *pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0); |
| 135989 | if( yymsp[0].minor.yy148 ) sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, yymsp[0].minor.yy148); |
| 135990 | yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy190.pExpr, 0, 0); |
| @@ -135914,19 +135991,19 @@ | |
| 135991 | sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy190.pExpr, pSelect); |
| 135992 | exprNot(pParse, yymsp[-3].minor.yy194, &yymsp[-4].minor.yy190); |
| 135993 | yymsp[-4].minor.yy190.zEnd = yymsp[-1].minor.yy0.z ? &yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n] : &yymsp[-2].minor.yy0.z[yymsp[-2].minor.yy0.n]; |
| 135994 | } |
| 135995 | break; |
| 135996 | case 195: /* expr ::= EXISTS LP select RP */ |
| 135997 | { |
| 135998 | Expr *p; |
| 135999 | spanSet(&yymsp[-3].minor.yy190,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-B*/ |
| 136000 | p = yymsp[-3].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0); |
| 136001 | sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy243); |
| 136002 | } |
| 136003 | break; |
| 136004 | case 196: /* expr ::= CASE case_operand case_exprlist case_else END */ |
| 136005 | { |
| 136006 | spanSet(&yymsp[-4].minor.yy190,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-C*/ |
| 136007 | yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy72, 0, 0); |
| 136008 | if( yymsp[-4].minor.yy190.pExpr ){ |
| 136009 | yymsp[-4].minor.yy190.pExpr->x.pList = yymsp[-1].minor.yy72 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy148,yymsp[-1].minor.yy72) : yymsp[-2].minor.yy148; |
| @@ -135935,334 +136012,334 @@ | |
| 136012 | sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy148); |
| 136013 | sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy72); |
| 136014 | } |
| 136015 | } |
| 136016 | break; |
| 136017 | case 197: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */ |
| 136018 | { |
| 136019 | yymsp[-4].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy148, yymsp[-2].minor.yy190.pExpr); |
| 136020 | yymsp[-4].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy148, yymsp[0].minor.yy190.pExpr); |
| 136021 | } |
| 136022 | break; |
| 136023 | case 198: /* case_exprlist ::= WHEN expr THEN expr */ |
| 136024 | { |
| 136025 | yymsp[-3].minor.yy148 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy190.pExpr); |
| 136026 | yymsp[-3].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy148, yymsp[0].minor.yy190.pExpr); |
| 136027 | } |
| 136028 | break; |
| 136029 | case 201: /* case_operand ::= expr */ |
| 136030 | {yymsp[0].minor.yy72 = yymsp[0].minor.yy190.pExpr; /*A-overwrites-X*/} |
| 136031 | break; |
| 136032 | case 204: /* nexprlist ::= nexprlist COMMA expr */ |
| 136033 | {yymsp[-2].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy148,yymsp[0].minor.yy190.pExpr);} |
| 136034 | break; |
| 136035 | case 205: /* nexprlist ::= expr */ |
| 136036 | {yymsp[0].minor.yy148 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy190.pExpr); /*A-overwrites-Y*/} |
| 136037 | break; |
| 136038 | case 207: /* paren_exprlist ::= LP exprlist RP */ |
| 136039 | case 212: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==212); |
| 136040 | {yymsp[-2].minor.yy148 = yymsp[-1].minor.yy148;} |
| 136041 | break; |
| 136042 | case 208: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ |
| 136043 | { |
| 136044 | sqlite3CreateIndex(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, |
| 136045 | sqlite3SrcListAppend(pParse->db,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy148, yymsp[-10].minor.yy194, |
| 136046 | &yymsp[-11].minor.yy0, yymsp[0].minor.yy72, SQLITE_SO_ASC, yymsp[-8].minor.yy194, SQLITE_IDXTYPE_APPDEF); |
| 136047 | } |
| 136048 | break; |
| 136049 | case 209: /* uniqueflag ::= UNIQUE */ |
| 136050 | case 250: /* raisetype ::= ABORT */ yytestcase(yyruleno==250); |
| 136051 | {yymsp[0].minor.yy194 = OE_Abort;} |
| 136052 | break; |
| 136053 | case 210: /* uniqueflag ::= */ |
| 136054 | {yymsp[1].minor.yy194 = OE_None;} |
| 136055 | break; |
| 136056 | case 213: /* eidlist ::= eidlist COMMA nm collate sortorder */ |
| 136057 | { |
| 136058 | yymsp[-4].minor.yy148 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy148, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy194, yymsp[0].minor.yy194); |
| 136059 | } |
| 136060 | break; |
| 136061 | case 214: /* eidlist ::= nm collate sortorder */ |
| 136062 | { |
| 136063 | yymsp[-2].minor.yy148 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy194, yymsp[0].minor.yy194); /*A-overwrites-Y*/ |
| 136064 | } |
| 136065 | break; |
| 136066 | case 217: /* cmd ::= DROP INDEX ifexists fullname */ |
| 136067 | {sqlite3DropIndex(pParse, yymsp[0].minor.yy185, yymsp[-1].minor.yy194);} |
| 136068 | break; |
| 136069 | case 218: /* cmd ::= VACUUM */ |
| 136070 | {sqlite3Vacuum(pParse,0);} |
| 136071 | break; |
| 136072 | case 219: /* cmd ::= VACUUM nm */ |
| 136073 | {sqlite3Vacuum(pParse,&yymsp[0].minor.yy0);} |
| 136074 | break; |
| 136075 | case 220: /* cmd ::= PRAGMA nm dbnm */ |
| 136076 | {sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);} |
| 136077 | break; |
| 136078 | case 221: /* cmd ::= PRAGMA nm dbnm EQ nmnum */ |
| 136079 | {sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,0);} |
| 136080 | break; |
| 136081 | case 222: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */ |
| 136082 | {sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,0);} |
| 136083 | break; |
| 136084 | case 223: /* cmd ::= PRAGMA nm dbnm EQ minus_num */ |
| 136085 | {sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,1);} |
| 136086 | break; |
| 136087 | case 224: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */ |
| 136088 | {sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,1);} |
| 136089 | break; |
| 136090 | case 227: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ |
| 136091 | { |
| 136092 | Token all; |
| 136093 | all.z = yymsp[-3].minor.yy0.z; |
| 136094 | all.n = (int)(yymsp[0].minor.yy0.z - yymsp[-3].minor.yy0.z) + yymsp[0].minor.yy0.n; |
| 136095 | sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy145, &all); |
| 136096 | } |
| 136097 | break; |
| 136098 | case 228: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ |
| 136099 | { |
| 136100 | sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy194, yymsp[-4].minor.yy332.a, yymsp[-4].minor.yy332.b, yymsp[-2].minor.yy185, yymsp[0].minor.yy72, yymsp[-10].minor.yy194, yymsp[-8].minor.yy194); |
| 136101 | yymsp[-10].minor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0); /*A-overwrites-T*/ |
| 136102 | } |
| 136103 | break; |
| 136104 | case 229: /* trigger_time ::= BEFORE */ |
| 136105 | { yymsp[0].minor.yy194 = TK_BEFORE; } |
| 136106 | break; |
| 136107 | case 230: /* trigger_time ::= AFTER */ |
| 136108 | { yymsp[0].minor.yy194 = TK_AFTER; } |
| 136109 | break; |
| 136110 | case 231: /* trigger_time ::= INSTEAD OF */ |
| 136111 | { yymsp[-1].minor.yy194 = TK_INSTEAD;} |
| 136112 | break; |
| 136113 | case 232: /* trigger_time ::= */ |
| 136114 | { yymsp[1].minor.yy194 = TK_BEFORE; } |
| 136115 | break; |
| 136116 | case 233: /* trigger_event ::= DELETE|INSERT */ |
| 136117 | case 234: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==234); |
| 136118 | {yymsp[0].minor.yy332.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy332.b = 0;} |
| 136119 | break; |
| 136120 | case 235: /* trigger_event ::= UPDATE OF idlist */ |
| 136121 | {yymsp[-2].minor.yy332.a = TK_UPDATE; yymsp[-2].minor.yy332.b = yymsp[0].minor.yy254;} |
| 136122 | break; |
| 136123 | case 236: /* when_clause ::= */ |
| 136124 | case 255: /* key_opt ::= */ yytestcase(yyruleno==255); |
| 136125 | { yymsp[1].minor.yy72 = 0; } |
| 136126 | break; |
| 136127 | case 237: /* when_clause ::= WHEN expr */ |
| 136128 | case 256: /* key_opt ::= KEY expr */ yytestcase(yyruleno==256); |
| 136129 | { yymsp[-1].minor.yy72 = yymsp[0].minor.yy190.pExpr; } |
| 136130 | break; |
| 136131 | case 238: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ |
| 136132 | { |
| 136133 | assert( yymsp[-2].minor.yy145!=0 ); |
| 136134 | yymsp[-2].minor.yy145->pLast->pNext = yymsp[-1].minor.yy145; |
| 136135 | yymsp[-2].minor.yy145->pLast = yymsp[-1].minor.yy145; |
| 136136 | } |
| 136137 | break; |
| 136138 | case 239: /* trigger_cmd_list ::= trigger_cmd SEMI */ |
| 136139 | { |
| 136140 | assert( yymsp[-1].minor.yy145!=0 ); |
| 136141 | yymsp[-1].minor.yy145->pLast = yymsp[-1].minor.yy145; |
| 136142 | } |
| 136143 | break; |
| 136144 | case 240: /* trnm ::= nm DOT nm */ |
| 136145 | { |
| 136146 | yymsp[-2].minor.yy0 = yymsp[0].minor.yy0; |
| 136147 | sqlite3ErrorMsg(pParse, |
| 136148 | "qualified table names are not allowed on INSERT, UPDATE, and DELETE " |
| 136149 | "statements within triggers"); |
| 136150 | } |
| 136151 | break; |
| 136152 | case 241: /* tridxby ::= INDEXED BY nm */ |
| 136153 | { |
| 136154 | sqlite3ErrorMsg(pParse, |
| 136155 | "the INDEXED BY clause is not allowed on UPDATE or DELETE statements " |
| 136156 | "within triggers"); |
| 136157 | } |
| 136158 | break; |
| 136159 | case 242: /* tridxby ::= NOT INDEXED */ |
| 136160 | { |
| 136161 | sqlite3ErrorMsg(pParse, |
| 136162 | "the NOT INDEXED clause is not allowed on UPDATE or DELETE statements " |
| 136163 | "within triggers"); |
| 136164 | } |
| 136165 | break; |
| 136166 | case 243: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt */ |
| 136167 | {yymsp[-6].minor.yy145 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-4].minor.yy0, yymsp[-1].minor.yy148, yymsp[0].minor.yy72, yymsp[-5].minor.yy194);} |
| 136168 | break; |
| 136169 | case 244: /* trigger_cmd ::= insert_cmd INTO trnm idlist_opt select */ |
| 136170 | {yymsp[-4].minor.yy145 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy254, yymsp[0].minor.yy243, yymsp[-4].minor.yy194);/*A-overwrites-R*/} |
| 136171 | break; |
| 136172 | case 245: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt */ |
| 136173 | {yymsp[-4].minor.yy145 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[0].minor.yy72);} |
| 136174 | break; |
| 136175 | case 246: /* trigger_cmd ::= select */ |
| 136176 | {yymsp[0].minor.yy145 = sqlite3TriggerSelectStep(pParse->db, yymsp[0].minor.yy243); /*A-overwrites-X*/} |
| 136177 | break; |
| 136178 | case 247: /* expr ::= RAISE LP IGNORE RP */ |
| 136179 | { |
| 136180 | spanSet(&yymsp[-3].minor.yy190,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ |
| 136181 | yymsp[-3].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, 0); |
| 136182 | if( yymsp[-3].minor.yy190.pExpr ){ |
| 136183 | yymsp[-3].minor.yy190.pExpr->affinity = OE_Ignore; |
| 136184 | } |
| 136185 | } |
| 136186 | break; |
| 136187 | case 248: /* expr ::= RAISE LP raisetype COMMA nm RP */ |
| 136188 | { |
| 136189 | spanSet(&yymsp[-5].minor.yy190,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ |
| 136190 | yymsp[-5].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &yymsp[-1].minor.yy0); |
| 136191 | if( yymsp[-5].minor.yy190.pExpr ) { |
| 136192 | yymsp[-5].minor.yy190.pExpr->affinity = (char)yymsp[-3].minor.yy194; |
| 136193 | } |
| 136194 | } |
| 136195 | break; |
| 136196 | case 249: /* raisetype ::= ROLLBACK */ |
| 136197 | {yymsp[0].minor.yy194 = OE_Rollback;} |
| 136198 | break; |
| 136199 | case 251: /* raisetype ::= FAIL */ |
| 136200 | {yymsp[0].minor.yy194 = OE_Fail;} |
| 136201 | break; |
| 136202 | case 252: /* cmd ::= DROP TRIGGER ifexists fullname */ |
| 136203 | { |
| 136204 | sqlite3DropTrigger(pParse,yymsp[0].minor.yy185,yymsp[-1].minor.yy194); |
| 136205 | } |
| 136206 | break; |
| 136207 | case 253: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ |
| 136208 | { |
| 136209 | sqlite3Attach(pParse, yymsp[-3].minor.yy190.pExpr, yymsp[-1].minor.yy190.pExpr, yymsp[0].minor.yy72); |
| 136210 | } |
| 136211 | break; |
| 136212 | case 254: /* cmd ::= DETACH database_kw_opt expr */ |
| 136213 | { |
| 136214 | sqlite3Detach(pParse, yymsp[0].minor.yy190.pExpr); |
| 136215 | } |
| 136216 | break; |
| 136217 | case 257: /* cmd ::= REINDEX */ |
| 136218 | {sqlite3Reindex(pParse, 0, 0);} |
| 136219 | break; |
| 136220 | case 258: /* cmd ::= REINDEX nm dbnm */ |
| 136221 | {sqlite3Reindex(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} |
| 136222 | break; |
| 136223 | case 259: /* cmd ::= ANALYZE */ |
| 136224 | {sqlite3Analyze(pParse, 0, 0);} |
| 136225 | break; |
| 136226 | case 260: /* cmd ::= ANALYZE nm dbnm */ |
| 136227 | {sqlite3Analyze(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} |
| 136228 | break; |
| 136229 | case 261: /* cmd ::= ALTER TABLE fullname RENAME TO nm */ |
| 136230 | { |
| 136231 | sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy185,&yymsp[0].minor.yy0); |
| 136232 | } |
| 136233 | break; |
| 136234 | case 262: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ |
| 136235 | { |
| 136236 | yymsp[-1].minor.yy0.n = (int)(pParse->sLastToken.z-yymsp[-1].minor.yy0.z) + pParse->sLastToken.n; |
| 136237 | sqlite3AlterFinishAddColumn(pParse, &yymsp[-1].minor.yy0); |
| 136238 | } |
| 136239 | break; |
| 136240 | case 263: /* add_column_fullname ::= fullname */ |
| 136241 | { |
| 136242 | disableLookaside(pParse); |
| 136243 | sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy185); |
| 136244 | } |
| 136245 | break; |
| 136246 | case 264: /* cmd ::= create_vtab */ |
| 136247 | {sqlite3VtabFinishParse(pParse,0);} |
| 136248 | break; |
| 136249 | case 265: /* cmd ::= create_vtab LP vtabarglist RP */ |
| 136250 | {sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);} |
| 136251 | break; |
| 136252 | case 266: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ |
| 136253 | { |
| 136254 | sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy194); |
| 136255 | } |
| 136256 | break; |
| 136257 | case 267: /* vtabarg ::= */ |
| 136258 | {sqlite3VtabArgInit(pParse);} |
| 136259 | break; |
| 136260 | case 268: /* vtabargtoken ::= ANY */ |
| 136261 | case 269: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==269); |
| 136262 | case 270: /* lp ::= LP */ yytestcase(yyruleno==270); |
| 136263 | {sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);} |
| 136264 | break; |
| 136265 | case 271: /* with ::= */ |
| 136266 | {yymsp[1].minor.yy285 = 0;} |
| 136267 | break; |
| 136268 | case 272: /* with ::= WITH wqlist */ |
| 136269 | { yymsp[-1].minor.yy285 = yymsp[0].minor.yy285; } |
| 136270 | break; |
| 136271 | case 273: /* with ::= WITH RECURSIVE wqlist */ |
| 136272 | { yymsp[-2].minor.yy285 = yymsp[0].minor.yy285; } |
| 136273 | break; |
| 136274 | case 274: /* wqlist ::= nm eidlist_opt AS LP select RP */ |
| 136275 | { |
| 136276 | yymsp[-5].minor.yy285 = sqlite3WithAdd(pParse, 0, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy148, yymsp[-1].minor.yy243); /*A-overwrites-X*/ |
| 136277 | } |
| 136278 | break; |
| 136279 | case 275: /* wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */ |
| 136280 | { |
| 136281 | yymsp[-7].minor.yy285 = sqlite3WithAdd(pParse, yymsp[-7].minor.yy285, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy148, yymsp[-1].minor.yy243); |
| 136282 | } |
| 136283 | break; |
| 136284 | default: |
| 136285 | /* (276) input ::= cmdlist */ yytestcase(yyruleno==276); |
| 136286 | /* (277) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==277); |
| 136287 | /* (278) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=278); |
| 136288 | /* (279) ecmd ::= SEMI */ yytestcase(yyruleno==279); |
| 136289 | /* (280) ecmd ::= explain cmdx SEMI */ yytestcase(yyruleno==280); |
| 136290 | /* (281) explain ::= */ yytestcase(yyruleno==281); |
| 136291 | /* (282) trans_opt ::= */ yytestcase(yyruleno==282); |
| 136292 | /* (283) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==283); |
| 136293 | /* (284) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==284); |
| 136294 | /* (285) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==285); |
| 136295 | /* (286) savepoint_opt ::= */ yytestcase(yyruleno==286); |
| 136296 | /* (287) cmd ::= create_table create_table_args */ yytestcase(yyruleno==287); |
| 136297 | /* (288) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==288); |
| 136298 | /* (289) columnlist ::= columnname carglist */ yytestcase(yyruleno==289); |
| 136299 | /* (290) nm ::= ID|INDEXED */ yytestcase(yyruleno==290); |
| 136300 | /* (291) nm ::= STRING */ yytestcase(yyruleno==291); |
| 136301 | /* (292) nm ::= JOIN_KW */ yytestcase(yyruleno==292); |
| 136302 | /* (293) typetoken ::= typename */ yytestcase(yyruleno==293); |
| 136303 | /* (294) typename ::= ID|STRING */ yytestcase(yyruleno==294); |
| 136304 | /* (295) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=295); |
| 136305 | /* (296) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=296); |
| 136306 | /* (297) carglist ::= carglist ccons */ yytestcase(yyruleno==297); |
| 136307 | /* (298) carglist ::= */ yytestcase(yyruleno==298); |
| 136308 | /* (299) ccons ::= NULL onconf */ yytestcase(yyruleno==299); |
| 136309 | /* (300) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==300); |
| 136310 | /* (301) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==301); |
| 136311 | /* (302) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=302); |
| 136312 | /* (303) tconscomma ::= */ yytestcase(yyruleno==303); |
| 136313 | /* (304) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=304); |
| 136314 | /* (305) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=305); |
| 136315 | /* (306) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=306); |
| 136316 | /* (307) oneselect ::= values */ yytestcase(yyruleno==307); |
| 136317 | /* (308) sclp ::= selcollist COMMA */ yytestcase(yyruleno==308); |
| 136318 | /* (309) as ::= ID|STRING */ yytestcase(yyruleno==309); |
| 136319 | /* (310) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=310); |
| 136320 | /* (311) exprlist ::= nexprlist */ yytestcase(yyruleno==311); |
| 136321 | /* (312) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=312); |
| 136322 | /* (313) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=313); |
| 136323 | /* (314) nmnum ::= ON */ yytestcase(yyruleno==314); |
| 136324 | /* (315) nmnum ::= DELETE */ yytestcase(yyruleno==315); |
| 136325 | /* (316) nmnum ::= DEFAULT */ yytestcase(yyruleno==316); |
| 136326 | /* (317) plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==317); |
| 136327 | /* (318) foreach_clause ::= */ yytestcase(yyruleno==318); |
| 136328 | /* (319) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==319); |
| 136329 | /* (320) trnm ::= nm */ yytestcase(yyruleno==320); |
| 136330 | /* (321) tridxby ::= */ yytestcase(yyruleno==321); |
| 136331 | /* (322) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==322); |
| 136332 | /* (323) database_kw_opt ::= */ yytestcase(yyruleno==323); |
| 136333 | /* (324) kwcolumn_opt ::= */ yytestcase(yyruleno==324); |
| 136334 | /* (325) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==325); |
| 136335 | /* (326) vtabarglist ::= vtabarg */ yytestcase(yyruleno==326); |
| 136336 | /* (327) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==327); |
| 136337 | /* (328) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==328); |
| 136338 | /* (329) anylist ::= */ yytestcase(yyruleno==329); |
| 136339 | /* (330) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==330); |
| 136340 | /* (331) anylist ::= anylist ANY */ yytestcase(yyruleno==331); |
| 136341 | break; |
| 136342 | /********** End reduce actions ************************************************/ |
| 136343 | }; |
| 136344 | assert( yyruleno<sizeof(yyRuleInfo)/sizeof(yyRuleInfo[0]) ); |
| 136345 | yygoto = yyRuleInfo[yyruleno].lhs; |
| @@ -136449,11 +136526,11 @@ | |
| 136526 | } |
| 136527 | #endif |
| 136528 | yy_destructor(yypParser, (YYCODETYPE)yymajor, &yyminorunion); |
| 136529 | yymajor = YYNOCODE; |
| 136530 | }else{ |
| 136531 | while( yypParser->yytos >= yypParser->yystack |
| 136532 | && yymx != YYERRORSYMBOL |
| 136533 | && (yyact = yy_find_reduce_action( |
| 136534 | yypParser->yytos->stateno, |
| 136535 | YYERRORSYMBOL)) >= YY_MIN_REDUCE |
| 136536 | ){ |
| @@ -138617,10 +138694,11 @@ | |
| 138694 | } aFlagOp[] = { |
| 138695 | { SQLITE_DBCONFIG_ENABLE_FKEY, SQLITE_ForeignKeys }, |
| 138696 | { SQLITE_DBCONFIG_ENABLE_TRIGGER, SQLITE_EnableTrigger }, |
| 138697 | { SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER, SQLITE_Fts3Tokenizer }, |
| 138698 | { SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, SQLITE_LoadExtension }, |
| 138699 | { SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE, SQLITE_NoCkptOnClose }, |
| 138700 | }; |
| 138701 | unsigned int i; |
| 138702 | rc = SQLITE_ERROR; /* IMP: R-42790-23372 */ |
| 138703 | for(i=0; i<ArraySize(aFlagOp); i++){ |
| 138704 | if( aFlagOp[i].op==op ){ |
| @@ -139913,10 +139991,17 @@ | |
| 139991 | db->busyHandler.nBusy = 0; |
| 139992 | rc = sqlite3Checkpoint(db, iDb, eMode, pnLog, pnCkpt); |
| 139993 | sqlite3Error(db, rc); |
| 139994 | } |
| 139995 | rc = sqlite3ApiExit(db, rc); |
| 139996 | |
| 139997 | /* If there are no active statements, clear the interrupt flag at this |
| 139998 | ** point. */ |
| 139999 | if( db->nVdbeActive==0 ){ |
| 140000 | db->u1.isInterrupted = 0; |
| 140001 | } |
| 140002 | |
| 140003 | sqlite3_mutex_leave(db->mutex); |
| 140004 | return rc; |
| 140005 | #endif |
| 140006 | } |
| 140007 | |
| @@ -140415,10 +140500,11 @@ | |
| 140500 | int octet = (sqlite3HexToInt(zUri[iIn++]) << 4); |
| 140501 | octet += sqlite3HexToInt(zUri[iIn++]); |
| 140502 | |
| 140503 | assert( octet>=0 && octet<256 ); |
| 140504 | if( octet==0 ){ |
| 140505 | #ifndef SQLITE_ENABLE_URI_00_ERROR |
| 140506 | /* This branch is taken when "%00" appears within the URI. In this |
| 140507 | ** case we ignore all text in the remainder of the path, name or |
| 140508 | ** value currently being parsed. So ignore the current character |
| 140509 | ** and skip to the next "?", "=" or "&", as appropriate. */ |
| 140510 | while( (c = zUri[iIn])!=0 && c!='#' |
| @@ -140427,10 +140513,16 @@ | |
| 140513 | && (eState!=2 || c!='&') |
| 140514 | ){ |
| 140515 | iIn++; |
| 140516 | } |
| 140517 | continue; |
| 140518 | #else |
| 140519 | /* If ENABLE_URI_00_ERROR is defined, "%00" in a URI is an error. */ |
| 140520 | *pzErrMsg = sqlite3_mprintf("unexpected %%00 in uri"); |
| 140521 | rc = SQLITE_ERROR; |
| 140522 | goto parse_uri_out; |
| 140523 | #endif |
| 140524 | } |
| 140525 | c = octet; |
| 140526 | }else if( eState==1 && (c=='&' || c=='=') ){ |
| 140527 | if( zFile[iOut-1]==0 ){ |
| 140528 | /* An empty option name. Ignore this option altogether. */ |
| @@ -164306,14 +164398,16 @@ | |
| 164398 | char *zSql; |
| 164399 | sqlite3_stmt *p; |
| 164400 | int rc; |
| 164401 | i64 nRow = 0; |
| 164402 | |
| 164403 | rc = sqlite3_table_column_metadata( |
| 164404 | db, pRtree->zDb, "sqlite_stat1",0,0,0,0,0,0 |
| 164405 | ); |
| 164406 | if( rc!=SQLITE_OK ){ |
| 164407 | pRtree->nRowEst = RTREE_DEFAULT_ROWEST; |
| 164408 | return rc==SQLITE_ERROR ? SQLITE_OK : rc; |
| 164409 | } |
| 164410 | zSql = sqlite3_mprintf(zFmt, pRtree->zDb, pRtree->zName); |
| 164411 | if( zSql==0 ){ |
| 164412 | rc = SQLITE_NOMEM; |
| 164413 | }else{ |
| @@ -165210,11 +165304,11 @@ | |
| 165304 | ** of the locale to use. Passing an empty string ("") or SQL NULL value |
| 165305 | ** as the second argument is the same as invoking the 1 argument version |
| 165306 | ** of upper() or lower(). |
| 165307 | ** |
| 165308 | ** lower('I', 'en_us') -> 'i' |
| 165309 | ** lower('I', 'tr_tr') -> '\u131' (small dotless i) |
| 165310 | ** |
| 165311 | ** http://www.icu-project.org/userguide/posix.html#case_mappings |
| 165312 | */ |
| 165313 | static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){ |
| 165314 | const UChar *zInput; /* Pointer to input string */ |
| @@ -181140,11 +181234,11 @@ | |
| 181234 | } |
| 181235 | #endif |
| 181236 | fts5yy_destructor(fts5yypParser, (fts5YYCODETYPE)fts5yymajor, &fts5yyminorunion); |
| 181237 | fts5yymajor = fts5YYNOCODE; |
| 181238 | }else{ |
| 181239 | while( fts5yypParser->fts5yytos >= fts5yypParser->fts5yystack |
| 181240 | && fts5yymx != fts5YYERRORSYMBOL |
| 181241 | && (fts5yyact = fts5yy_find_reduce_action( |
| 181242 | fts5yypParser->fts5yytos->stateno, |
| 181243 | fts5YYERRORSYMBOL)) >= fts5YY_MIN_REDUCE |
| 181244 | ){ |
| @@ -181506,10 +181600,13 @@ | |
| 181600 | int nToken, /* Size of token in bytes */ |
| 181601 | int iStartOff, /* Start offset of token */ |
| 181602 | int iEndOff /* End offset of token */ |
| 181603 | ){ |
| 181604 | int rc = SQLITE_OK; |
| 181605 | |
| 181606 | UNUSED_PARAM2(pToken, nToken); |
| 181607 | UNUSED_PARAM(iEndOff); |
| 181608 | |
| 181609 | if( (tflags & FTS5_TOKEN_COLOCATED)==0 ){ |
| 181610 | Fts5SFinder *p = (Fts5SFinder*)pContext; |
| 181611 | if( p->iPos>0 ){ |
| 181612 | int i; |
| @@ -181662,11 +181759,10 @@ | |
| 181759 | for(jj=0; jj<(sFinder.nFirst-1); jj++){ |
| 181760 | if( sFinder.aFirst[jj+1]>io ) break; |
| 181761 | } |
| 181762 | |
| 181763 | if( sFinder.aFirst[jj]<io ){ |
| 181764 | memset(aSeen, 0, nPhrase); |
| 181765 | rc = fts5SnippetScore(pApi, pFts, nDocsize, aSeen, i, |
| 181766 | sFinder.aFirst[jj], nToken, &nScore, 0 |
| 181767 | ); |
| 181768 | |
| @@ -195597,11 +195693,11 @@ | |
| 195693 | int nArg, /* Number of args */ |
| 195694 | sqlite3_value **apUnused /* Function arguments */ |
| 195695 | ){ |
| 195696 | assert( nArg==0 ); |
| 195697 | UNUSED_PARAM2(nArg, apUnused); |
| 195698 | sqlite3_result_text(pCtx, "fts5: 2016-10-26 16:05:10 ec9dab8054c71d112c68f58a45821b38c2a45677", -1, SQLITE_TRANSIENT); |
| 195699 | } |
| 195700 | |
| 195701 | static int fts5Init(sqlite3 *db){ |
| 195702 | static const sqlite3_module fts5Mod = { |
| 195703 | /* iVersion */ 2, |
| 195704 |
+28
-7
| --- src/sqlite3.h | ||
| +++ src/sqlite3.h | ||
| @@ -119,13 +119,13 @@ | ||
| 119 | 119 | ** |
| 120 | 120 | ** See also: [sqlite3_libversion()], |
| 121 | 121 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 122 | 122 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 123 | 123 | */ |
| 124 | -#define SQLITE_VERSION "3.15.0" | |
| 125 | -#define SQLITE_VERSION_NUMBER 3015000 | |
| 126 | -#define SQLITE_SOURCE_ID "2016-09-22 18:53:13 c3774c6a5fe48af91fda28e9e18c6ed9053ea992" | |
| 124 | +#define SQLITE_VERSION "3.16.0" | |
| 125 | +#define SQLITE_VERSION_NUMBER 3016000 | |
| 126 | +#define SQLITE_SOURCE_ID "2016-11-02 14:50:19 3028845329c9b7acdec2ec8b01d00d782347454c" | |
| 127 | 127 | |
| 128 | 128 | /* |
| 129 | 129 | ** CAPI3REF: Run-Time Library Version Numbers |
| 130 | 130 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 131 | 131 | ** |
| @@ -975,10 +975,16 @@ | ||
| 975 | 975 | ** <li>[[SQLITE_FCNTL_HAS_MOVED]] |
| 976 | 976 | ** The [SQLITE_FCNTL_HAS_MOVED] file control interprets its argument as a |
| 977 | 977 | ** pointer to an integer and it writes a boolean into that integer depending |
| 978 | 978 | ** on whether or not the file has been renamed, moved, or deleted since it |
| 979 | 979 | ** was first opened. |
| 980 | +** | |
| 981 | +** <li>[[SQLITE_FCNTL_WIN32_GET_HANDLE]] | |
| 982 | +** The [SQLITE_FCNTL_WIN32_GET_HANDLE] opcode can be used to obtain the | |
| 983 | +** underlying native file handle associated with a file handle. This file | |
| 984 | +** control interprets its argument as a pointer to a native file handle and | |
| 985 | +** writes the resulting value there. | |
| 980 | 986 | ** |
| 981 | 987 | ** <li>[[SQLITE_FCNTL_WIN32_SET_HANDLE]] |
| 982 | 988 | ** The [SQLITE_FCNTL_WIN32_SET_HANDLE] opcode is used for debugging. This |
| 983 | 989 | ** opcode causes the xFileControl method to swap the file handle with the one |
| 984 | 990 | ** pointed to by the pArg argument. This capability is used during testing |
| @@ -1026,10 +1032,12 @@ | ||
| 1026 | 1032 | #define SQLITE_FCNTL_WAL_BLOCK 24 |
| 1027 | 1033 | #define SQLITE_FCNTL_ZIPVFS 25 |
| 1028 | 1034 | #define SQLITE_FCNTL_RBU 26 |
| 1029 | 1035 | #define SQLITE_FCNTL_VFS_POINTER 27 |
| 1030 | 1036 | #define SQLITE_FCNTL_JOURNAL_POINTER 28 |
| 1037 | +#define SQLITE_FCNTL_WIN32_GET_HANDLE 29 | |
| 1038 | +#define SQLITE_FCNTL_PDB 30 | |
| 1031 | 1039 | |
| 1032 | 1040 | /* deprecated names */ |
| 1033 | 1041 | #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE |
| 1034 | 1042 | #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE |
| 1035 | 1043 | #define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO |
| @@ -1978,18 +1986,31 @@ | ||
| 1978 | 1986 | ** does not make a copy of the new main schema name string, so the application |
| 1979 | 1987 | ** must ensure that the argument passed into this DBCONFIG option is unchanged |
| 1980 | 1988 | ** until after the database connection closes. |
| 1981 | 1989 | ** </dd> |
| 1982 | 1990 | ** |
| 1991 | +** <dt>SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE</dt> | |
| 1992 | +** <dd> Usually, when a database in wal mode is closed or detached from a | |
| 1993 | +** database handle, SQLite checks if this will mean that there are now no | |
| 1994 | +** connections at all to the database. If so, it performs a checkpoint | |
| 1995 | +** operation before closing the connection. This option may be used to | |
| 1996 | +** override this behaviour. The first parameter passed to this operation | |
| 1997 | +** is an integer - non-zero to disable checkpoints-on-close, or zero (the | |
| 1998 | +** default) to enable them. The second parameter is a pointer to an integer | |
| 1999 | +** into which is written 0 or 1 to indicate whether checkpoints-on-close | |
| 2000 | +** have been disabled - 0 if they are not disabled, 1 if they are. | |
| 2001 | +** </dd> | |
| 2002 | +** | |
| 1983 | 2003 | ** </dl> |
| 1984 | 2004 | */ |
| 1985 | 2005 | #define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */ |
| 1986 | 2006 | #define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */ |
| 1987 | 2007 | #define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */ |
| 1988 | 2008 | #define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */ |
| 1989 | 2009 | #define SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1004 /* int int* */ |
| 1990 | 2010 | #define SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1005 /* int int* */ |
| 2011 | +#define SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE 1006 /* int int* */ | |
| 1991 | 2012 | |
| 1992 | 2013 | |
| 1993 | 2014 | /* |
| 1994 | 2015 | ** CAPI3REF: Enable Or Disable Extended Result Codes |
| 1995 | 2016 | ** METHOD: sqlite3 |
| @@ -8655,11 +8676,11 @@ | ||
| 8655 | 8676 | |
| 8656 | 8677 | /* |
| 8657 | 8678 | ** CAPI3REF: Set a table filter on a Session Object. |
| 8658 | 8679 | ** |
| 8659 | 8680 | ** The second argument (xFilter) is the "filter callback". For changes to rows |
| 8660 | -** in tables that are not attached to the Session oject, the filter is called | |
| 8681 | +** in tables that are not attached to the Session object, the filter is called | |
| 8661 | 8682 | ** to determine whether changes to the table's rows should be tracked or not. |
| 8662 | 8683 | ** If xFilter returns 0, changes is not tracked. Note that once a table is |
| 8663 | 8684 | ** attached, xFilter will not be called again. |
| 8664 | 8685 | */ |
| 8665 | 8686 | void sqlite3session_table_filter( |
| @@ -8921,11 +8942,11 @@ | ||
| 8921 | 8942 | ** Assuming the changeset blob was created by one of the |
| 8922 | 8943 | ** [sqlite3session_changeset()], [sqlite3changeset_concat()] or |
| 8923 | 8944 | ** [sqlite3changeset_invert()] functions, all changes within the changeset |
| 8924 | 8945 | ** that apply to a single table are grouped together. This means that when |
| 8925 | 8946 | ** an application iterates through a changeset using an iterator created by |
| 8926 | -** this function, all changes that relate to a single table are visted | |
| 8947 | +** this function, all changes that relate to a single table are visited | |
| 8927 | 8948 | ** consecutively. There is no chance that the iterator will visit a change |
| 8928 | 8949 | ** the applies to table X, then one for table Y, and then later on visit |
| 8929 | 8950 | ** another change for table X. |
| 8930 | 8951 | */ |
| 8931 | 8952 | int sqlite3changeset_start( |
| @@ -9008,11 +9029,11 @@ | ||
| 9008 | 9029 | ** If successful, *pabPK is set to point to an array of nCol entries, where |
| 9009 | 9030 | ** nCol is the number of columns in the table. Elements of *pabPK are set to |
| 9010 | 9031 | ** 0x01 if the corresponding column is part of the tables primary key, or |
| 9011 | 9032 | ** 0x00 if it is not. |
| 9012 | 9033 | ** |
| 9013 | -** If argumet pnCol is not NULL, then *pnCol is set to the number of columns | |
| 9034 | +** If argument pnCol is not NULL, then *pnCol is set to the number of columns | |
| 9014 | 9035 | ** in the table. |
| 9015 | 9036 | ** |
| 9016 | 9037 | ** If this function is called when the iterator does not point to a valid |
| 9017 | 9038 | ** entry, SQLITE_MISUSE is returned and the output variables zeroed. Otherwise, |
| 9018 | 9039 | ** SQLITE_OK is returned and the output variables populated as described |
| @@ -9283,11 +9304,11 @@ | ||
| 9283 | 9304 | ** Rows within the changeset and changegroup are identified by the values in |
| 9284 | 9305 | ** their PRIMARY KEY columns. A change in the changeset is considered to |
| 9285 | 9306 | ** apply to the same row as a change already present in the changegroup if |
| 9286 | 9307 | ** the two rows have the same primary key. |
| 9287 | 9308 | ** |
| 9288 | -** Changes to rows that that do not already appear in the changegroup are | |
| 9309 | +** Changes to rows that do not already appear in the changegroup are | |
| 9289 | 9310 | ** simply copied into it. Or, if both the new changeset and the changegroup |
| 9290 | 9311 | ** contain changes that apply to a single row, the final contents of the |
| 9291 | 9312 | ** changegroup depends on the type of each change, as follows: |
| 9292 | 9313 | ** |
| 9293 | 9314 | ** <table border=1 style="margin-left:8ex;margin-right:8ex"> |
| 9294 | 9315 |
| --- src/sqlite3.h | |
| +++ src/sqlite3.h | |
| @@ -119,13 +119,13 @@ | |
| 119 | ** |
| 120 | ** See also: [sqlite3_libversion()], |
| 121 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 122 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 123 | */ |
| 124 | #define SQLITE_VERSION "3.15.0" |
| 125 | #define SQLITE_VERSION_NUMBER 3015000 |
| 126 | #define SQLITE_SOURCE_ID "2016-09-22 18:53:13 c3774c6a5fe48af91fda28e9e18c6ed9053ea992" |
| 127 | |
| 128 | /* |
| 129 | ** CAPI3REF: Run-Time Library Version Numbers |
| 130 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 131 | ** |
| @@ -975,10 +975,16 @@ | |
| 975 | ** <li>[[SQLITE_FCNTL_HAS_MOVED]] |
| 976 | ** The [SQLITE_FCNTL_HAS_MOVED] file control interprets its argument as a |
| 977 | ** pointer to an integer and it writes a boolean into that integer depending |
| 978 | ** on whether or not the file has been renamed, moved, or deleted since it |
| 979 | ** was first opened. |
| 980 | ** |
| 981 | ** <li>[[SQLITE_FCNTL_WIN32_SET_HANDLE]] |
| 982 | ** The [SQLITE_FCNTL_WIN32_SET_HANDLE] opcode is used for debugging. This |
| 983 | ** opcode causes the xFileControl method to swap the file handle with the one |
| 984 | ** pointed to by the pArg argument. This capability is used during testing |
| @@ -1026,10 +1032,12 @@ | |
| 1026 | #define SQLITE_FCNTL_WAL_BLOCK 24 |
| 1027 | #define SQLITE_FCNTL_ZIPVFS 25 |
| 1028 | #define SQLITE_FCNTL_RBU 26 |
| 1029 | #define SQLITE_FCNTL_VFS_POINTER 27 |
| 1030 | #define SQLITE_FCNTL_JOURNAL_POINTER 28 |
| 1031 | |
| 1032 | /* deprecated names */ |
| 1033 | #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE |
| 1034 | #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE |
| 1035 | #define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO |
| @@ -1978,18 +1986,31 @@ | |
| 1978 | ** does not make a copy of the new main schema name string, so the application |
| 1979 | ** must ensure that the argument passed into this DBCONFIG option is unchanged |
| 1980 | ** until after the database connection closes. |
| 1981 | ** </dd> |
| 1982 | ** |
| 1983 | ** </dl> |
| 1984 | */ |
| 1985 | #define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */ |
| 1986 | #define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */ |
| 1987 | #define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */ |
| 1988 | #define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */ |
| 1989 | #define SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1004 /* int int* */ |
| 1990 | #define SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1005 /* int int* */ |
| 1991 | |
| 1992 | |
| 1993 | /* |
| 1994 | ** CAPI3REF: Enable Or Disable Extended Result Codes |
| 1995 | ** METHOD: sqlite3 |
| @@ -8655,11 +8676,11 @@ | |
| 8655 | |
| 8656 | /* |
| 8657 | ** CAPI3REF: Set a table filter on a Session Object. |
| 8658 | ** |
| 8659 | ** The second argument (xFilter) is the "filter callback". For changes to rows |
| 8660 | ** in tables that are not attached to the Session oject, the filter is called |
| 8661 | ** to determine whether changes to the table's rows should be tracked or not. |
| 8662 | ** If xFilter returns 0, changes is not tracked. Note that once a table is |
| 8663 | ** attached, xFilter will not be called again. |
| 8664 | */ |
| 8665 | void sqlite3session_table_filter( |
| @@ -8921,11 +8942,11 @@ | |
| 8921 | ** Assuming the changeset blob was created by one of the |
| 8922 | ** [sqlite3session_changeset()], [sqlite3changeset_concat()] or |
| 8923 | ** [sqlite3changeset_invert()] functions, all changes within the changeset |
| 8924 | ** that apply to a single table are grouped together. This means that when |
| 8925 | ** an application iterates through a changeset using an iterator created by |
| 8926 | ** this function, all changes that relate to a single table are visted |
| 8927 | ** consecutively. There is no chance that the iterator will visit a change |
| 8928 | ** the applies to table X, then one for table Y, and then later on visit |
| 8929 | ** another change for table X. |
| 8930 | */ |
| 8931 | int sqlite3changeset_start( |
| @@ -9008,11 +9029,11 @@ | |
| 9008 | ** If successful, *pabPK is set to point to an array of nCol entries, where |
| 9009 | ** nCol is the number of columns in the table. Elements of *pabPK are set to |
| 9010 | ** 0x01 if the corresponding column is part of the tables primary key, or |
| 9011 | ** 0x00 if it is not. |
| 9012 | ** |
| 9013 | ** If argumet pnCol is not NULL, then *pnCol is set to the number of columns |
| 9014 | ** in the table. |
| 9015 | ** |
| 9016 | ** If this function is called when the iterator does not point to a valid |
| 9017 | ** entry, SQLITE_MISUSE is returned and the output variables zeroed. Otherwise, |
| 9018 | ** SQLITE_OK is returned and the output variables populated as described |
| @@ -9283,11 +9304,11 @@ | |
| 9283 | ** Rows within the changeset and changegroup are identified by the values in |
| 9284 | ** their PRIMARY KEY columns. A change in the changeset is considered to |
| 9285 | ** apply to the same row as a change already present in the changegroup if |
| 9286 | ** the two rows have the same primary key. |
| 9287 | ** |
| 9288 | ** Changes to rows that that do not already appear in the changegroup are |
| 9289 | ** simply copied into it. Or, if both the new changeset and the changegroup |
| 9290 | ** contain changes that apply to a single row, the final contents of the |
| 9291 | ** changegroup depends on the type of each change, as follows: |
| 9292 | ** |
| 9293 | ** <table border=1 style="margin-left:8ex;margin-right:8ex"> |
| 9294 |
| --- src/sqlite3.h | |
| +++ src/sqlite3.h | |
| @@ -119,13 +119,13 @@ | |
| 119 | ** |
| 120 | ** See also: [sqlite3_libversion()], |
| 121 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 122 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 123 | */ |
| 124 | #define SQLITE_VERSION "3.16.0" |
| 125 | #define SQLITE_VERSION_NUMBER 3016000 |
| 126 | #define SQLITE_SOURCE_ID "2016-11-02 14:50:19 3028845329c9b7acdec2ec8b01d00d782347454c" |
| 127 | |
| 128 | /* |
| 129 | ** CAPI3REF: Run-Time Library Version Numbers |
| 130 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 131 | ** |
| @@ -975,10 +975,16 @@ | |
| 975 | ** <li>[[SQLITE_FCNTL_HAS_MOVED]] |
| 976 | ** The [SQLITE_FCNTL_HAS_MOVED] file control interprets its argument as a |
| 977 | ** pointer to an integer and it writes a boolean into that integer depending |
| 978 | ** on whether or not the file has been renamed, moved, or deleted since it |
| 979 | ** was first opened. |
| 980 | ** |
| 981 | ** <li>[[SQLITE_FCNTL_WIN32_GET_HANDLE]] |
| 982 | ** The [SQLITE_FCNTL_WIN32_GET_HANDLE] opcode can be used to obtain the |
| 983 | ** underlying native file handle associated with a file handle. This file |
| 984 | ** control interprets its argument as a pointer to a native file handle and |
| 985 | ** writes the resulting value there. |
| 986 | ** |
| 987 | ** <li>[[SQLITE_FCNTL_WIN32_SET_HANDLE]] |
| 988 | ** The [SQLITE_FCNTL_WIN32_SET_HANDLE] opcode is used for debugging. This |
| 989 | ** opcode causes the xFileControl method to swap the file handle with the one |
| 990 | ** pointed to by the pArg argument. This capability is used during testing |
| @@ -1026,10 +1032,12 @@ | |
| 1032 | #define SQLITE_FCNTL_WAL_BLOCK 24 |
| 1033 | #define SQLITE_FCNTL_ZIPVFS 25 |
| 1034 | #define SQLITE_FCNTL_RBU 26 |
| 1035 | #define SQLITE_FCNTL_VFS_POINTER 27 |
| 1036 | #define SQLITE_FCNTL_JOURNAL_POINTER 28 |
| 1037 | #define SQLITE_FCNTL_WIN32_GET_HANDLE 29 |
| 1038 | #define SQLITE_FCNTL_PDB 30 |
| 1039 | |
| 1040 | /* deprecated names */ |
| 1041 | #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE |
| 1042 | #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE |
| 1043 | #define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO |
| @@ -1978,18 +1986,31 @@ | |
| 1986 | ** does not make a copy of the new main schema name string, so the application |
| 1987 | ** must ensure that the argument passed into this DBCONFIG option is unchanged |
| 1988 | ** until after the database connection closes. |
| 1989 | ** </dd> |
| 1990 | ** |
| 1991 | ** <dt>SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE</dt> |
| 1992 | ** <dd> Usually, when a database in wal mode is closed or detached from a |
| 1993 | ** database handle, SQLite checks if this will mean that there are now no |
| 1994 | ** connections at all to the database. If so, it performs a checkpoint |
| 1995 | ** operation before closing the connection. This option may be used to |
| 1996 | ** override this behaviour. The first parameter passed to this operation |
| 1997 | ** is an integer - non-zero to disable checkpoints-on-close, or zero (the |
| 1998 | ** default) to enable them. The second parameter is a pointer to an integer |
| 1999 | ** into which is written 0 or 1 to indicate whether checkpoints-on-close |
| 2000 | ** have been disabled - 0 if they are not disabled, 1 if they are. |
| 2001 | ** </dd> |
| 2002 | ** |
| 2003 | ** </dl> |
| 2004 | */ |
| 2005 | #define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */ |
| 2006 | #define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */ |
| 2007 | #define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */ |
| 2008 | #define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */ |
| 2009 | #define SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1004 /* int int* */ |
| 2010 | #define SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1005 /* int int* */ |
| 2011 | #define SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE 1006 /* int int* */ |
| 2012 | |
| 2013 | |
| 2014 | /* |
| 2015 | ** CAPI3REF: Enable Or Disable Extended Result Codes |
| 2016 | ** METHOD: sqlite3 |
| @@ -8655,11 +8676,11 @@ | |
| 8676 | |
| 8677 | /* |
| 8678 | ** CAPI3REF: Set a table filter on a Session Object. |
| 8679 | ** |
| 8680 | ** The second argument (xFilter) is the "filter callback". For changes to rows |
| 8681 | ** in tables that are not attached to the Session object, the filter is called |
| 8682 | ** to determine whether changes to the table's rows should be tracked or not. |
| 8683 | ** If xFilter returns 0, changes is not tracked. Note that once a table is |
| 8684 | ** attached, xFilter will not be called again. |
| 8685 | */ |
| 8686 | void sqlite3session_table_filter( |
| @@ -8921,11 +8942,11 @@ | |
| 8942 | ** Assuming the changeset blob was created by one of the |
| 8943 | ** [sqlite3session_changeset()], [sqlite3changeset_concat()] or |
| 8944 | ** [sqlite3changeset_invert()] functions, all changes within the changeset |
| 8945 | ** that apply to a single table are grouped together. This means that when |
| 8946 | ** an application iterates through a changeset using an iterator created by |
| 8947 | ** this function, all changes that relate to a single table are visited |
| 8948 | ** consecutively. There is no chance that the iterator will visit a change |
| 8949 | ** the applies to table X, then one for table Y, and then later on visit |
| 8950 | ** another change for table X. |
| 8951 | */ |
| 8952 | int sqlite3changeset_start( |
| @@ -9008,11 +9029,11 @@ | |
| 9029 | ** If successful, *pabPK is set to point to an array of nCol entries, where |
| 9030 | ** nCol is the number of columns in the table. Elements of *pabPK are set to |
| 9031 | ** 0x01 if the corresponding column is part of the tables primary key, or |
| 9032 | ** 0x00 if it is not. |
| 9033 | ** |
| 9034 | ** If argument pnCol is not NULL, then *pnCol is set to the number of columns |
| 9035 | ** in the table. |
| 9036 | ** |
| 9037 | ** If this function is called when the iterator does not point to a valid |
| 9038 | ** entry, SQLITE_MISUSE is returned and the output variables zeroed. Otherwise, |
| 9039 | ** SQLITE_OK is returned and the output variables populated as described |
| @@ -9283,11 +9304,11 @@ | |
| 9304 | ** Rows within the changeset and changegroup are identified by the values in |
| 9305 | ** their PRIMARY KEY columns. A change in the changeset is considered to |
| 9306 | ** apply to the same row as a change already present in the changegroup if |
| 9307 | ** the two rows have the same primary key. |
| 9308 | ** |
| 9309 | ** Changes to rows that do not already appear in the changegroup are |
| 9310 | ** simply copied into it. Or, if both the new changeset and the changegroup |
| 9311 | ** contain changes that apply to a single row, the final contents of the |
| 9312 | ** changegroup depends on the type of each change, as follows: |
| 9313 | ** |
| 9314 | ** <table border=1 style="margin-left:8ex;margin-right:8ex"> |
| 9315 |
+42
-31
| --- src/stash.c | ||
| +++ src/stash.c | ||
| @@ -25,11 +25,11 @@ | ||
| 25 | 25 | ** SQL code to implement the tables needed by the stash. |
| 26 | 26 | */ |
| 27 | 27 | static const char zStashInit[] = |
| 28 | 28 | @ CREATE TABLE IF NOT EXISTS localdb.stash( |
| 29 | 29 | @ stashid INTEGER PRIMARY KEY, -- Unique stash identifier |
| 30 | -@ vid INTEGER, -- The baseline check-out for this stash | |
| 30 | +@ vid INTEGER, -- The baseline checkout for this stash | |
| 31 | 31 | @ comment TEXT, -- Comment for this stash. Or NULL |
| 32 | 32 | @ ctime TIMESTAMP -- When the stash was created |
| 33 | 33 | @ ); |
| 34 | 34 | @ CREATE TABLE IF NOT EXISTS localdb.stashfile( |
| 35 | 35 | @ stashid INTEGER REFERENCES stash, -- Stash that contains this file |
| @@ -39,11 +39,11 @@ | ||
| 39 | 39 | @ isExec BOOLEAN, -- True if file is executable |
| 40 | 40 | @ isLink BOOLEAN, -- True if file is a symlink |
| 41 | 41 | @ origname TEXT, -- Original filename |
| 42 | 42 | @ newname TEXT, -- New name for file at next check-in |
| 43 | 43 | @ delta BLOB, -- Delta from baseline. Content if rid=0 |
| 44 | -@ PRIMARY KEY(origname, stashid) | |
| 44 | +@ PRIMARY KEY(newname, stashid) | |
| 45 | 45 | @ ); |
| 46 | 46 | @ INSERT OR IGNORE INTO vvar(name, value) VALUES('stash-next', 1); |
| 47 | 47 | ; |
| 48 | 48 | |
| 49 | 49 | /* |
| @@ -196,11 +196,11 @@ | ||
| 196 | 196 | } |
| 197 | 197 | return stashid; |
| 198 | 198 | } |
| 199 | 199 | |
| 200 | 200 | /* |
| 201 | -** Apply a stash to the current check-out. | |
| 201 | +** Apply a stash to the current checkout. | |
| 202 | 202 | */ |
| 203 | 203 | static void stash_apply(int stashid, int nConflict){ |
| 204 | 204 | int vid; |
| 205 | 205 | Stmt q; |
| 206 | 206 | db_prepare(&q, |
| @@ -278,10 +278,15 @@ | ||
| 278 | 278 | } |
| 279 | 279 | blob_reset(&delta); |
| 280 | 280 | if( fossil_strcmp(zOrig,zNew)!=0 ){ |
| 281 | 281 | undo_save(zOrig); |
| 282 | 282 | file_delete(zOPath); |
| 283 | + db_multi_exec( | |
| 284 | + "UPDATE vfile SET pathname='%q', origname='%q'" | |
| 285 | + " WHERE pathname='%q' %s AND vid=%d", | |
| 286 | + zNew, zOrig, zOrig, filename_collation(), vid | |
| 287 | + ); | |
| 283 | 288 | } |
| 284 | 289 | } |
| 285 | 290 | stash_add_files_in_sfile(vid); |
| 286 | 291 | db_finalize(&q); |
| 287 | 292 | if( nConflict ){ |
| @@ -393,18 +398,18 @@ | ||
| 393 | 398 | ** return that number. Or throw a fatal error if it is not a valid |
| 394 | 399 | ** stash number. If it is NULL, return the most recent stash or |
| 395 | 400 | ** throw an error if the stash is empty. |
| 396 | 401 | */ |
| 397 | 402 | static int stash_get_id(const char *zStashId){ |
| 398 | - int stashid = 0; | |
| 403 | + int stashid; | |
| 399 | 404 | if( zStashId==0 ){ |
| 400 | 405 | stashid = db_int(0, "SELECT max(stashid) FROM stash"); |
| 401 | 406 | if( stashid==0 ) fossil_fatal("empty stash"); |
| 402 | 407 | }else{ |
| 403 | 408 | stashid = atoi(zStashId); |
| 404 | 409 | if( !db_exists("SELECT 1 FROM stash WHERE stashid=%d", stashid) ){ |
| 405 | - fossil_fatal("no such stash: %d\n", stashid); | |
| 410 | + fossil_fatal("no such stash: %s", zStashId); | |
| 406 | 411 | } |
| 407 | 412 | } |
| 408 | 413 | return stashid; |
| 409 | 414 | } |
| 410 | 415 | |
| @@ -420,70 +425,83 @@ | ||
| 420 | 425 | ** Save the current changes in the working tree as a new stash. |
| 421 | 426 | ** Then revert the changes back to the last check-in. If FILES |
| 422 | 427 | ** are listed, then only stash and revert the named files. The |
| 423 | 428 | ** "save" verb can be omitted if and only if there are no other |
| 424 | 429 | ** arguments. The "snapshot" verb works the same as "save" but |
| 425 | -** omits the revert, keeping the check-out unchanged. | |
| 430 | +** omits the revert, keeping the checkout unchanged. | |
| 426 | 431 | ** |
| 427 | -** fossil stash list ?-v|--verbose? | |
| 428 | -** fossil stash ls ?-v|--verbose? | |
| 432 | +** fossil stash list|ls ?-v|--verbose? ?-W|--width <num>? | |
| 429 | 433 | ** |
| 430 | 434 | ** List all changes sets currently stashed. Show information about |
| 431 | 435 | ** individual files in each changeset if -v or --verbose is used. |
| 432 | 436 | ** |
| 433 | -** fossil stash show|cat ?STASHID? ?DIFF-FLAGS? | |
| 437 | +** fossil stash show|cat ?STASHID? ?DIFF-OPTIONS? | |
| 434 | 438 | ** |
| 435 | -** Show the content of a stash | |
| 439 | +** Show the contents of a stash. | |
| 436 | 440 | ** |
| 437 | 441 | ** fossil stash pop |
| 438 | 442 | ** fossil stash apply ?STASHID? |
| 439 | 443 | ** |
| 440 | 444 | ** Apply STASHID or the most recently create stash to the current |
| 441 | -** working check-out. The "pop" command deletes that changeset from | |
| 445 | +** working checkout. The "pop" command deletes that changeset from | |
| 442 | 446 | ** the stash after applying it but the "apply" command retains the |
| 443 | 447 | ** changeset. |
| 444 | 448 | ** |
| 445 | 449 | ** fossil stash goto ?STASHID? |
| 446 | 450 | ** |
| 447 | 451 | ** Update to the baseline checkout for STASHID then apply the |
| 448 | 452 | ** changes of STASHID. Keep STASHID so that it can be reused |
| 449 | 453 | ** This command is undoable. |
| 450 | 454 | ** |
| 451 | -** fossil stash drop ?STASHID? ?-a|--all? | |
| 452 | -** fossil stash rm ?STASHID? ?-a|--all? | |
| 455 | +** fossil stash drop|rm ?STASHID? ?-a|--all? | |
| 453 | 456 | ** |
| 454 | 457 | ** Forget everything about STASHID. Forget the whole stash if the |
| 455 | 458 | ** -a|--all flag is used. Individual drops are undoable but -a|--all |
| 456 | 459 | ** is not. |
| 457 | 460 | ** |
| 458 | -** fossil stash diff ?STASHID? | |
| 459 | -** fossil stash gdiff ?STASHID? | |
| 461 | +** fossil stash diff ?STASHID? ?DIFF-OPTIONS? | |
| 462 | +** fossil stash gdiff ?STASHID? ?DIFF-OPTIONS? | |
| 460 | 463 | ** |
| 461 | 464 | ** Show diffs of the current working directory and what that |
| 462 | 465 | ** directory would be if STASHID were applied. |
| 463 | 466 | ** |
| 464 | 467 | ** SUMMARY: |
| 465 | 468 | ** fossil stash |
| 466 | 469 | ** fossil stash save ?-m|--comment COMMENT? ?FILES...? |
| 467 | 470 | ** fossil stash snapshot ?-m|--comment COMMENT? ?FILES...? |
| 468 | -** fossil stash list|ls ?-v|--verbose? ?-W|--width <num>? | |
| 471 | +** fossil stash list|ls ?-v|--verbose? ?-W|--width <num>? | |
| 469 | 472 | ** fossil stash show|cat ?STASHID? ?DIFF-OPTIONS? |
| 470 | 473 | ** fossil stash pop |
| 471 | -** fossil stash apply ?STASHID? | |
| 472 | -** fossil stash goto ?STASHID? | |
| 473 | -** fossil stash rm|drop ?STASHID? ?-a|--all? | |
| 474 | -** fossil stash [g]diff ?STASHID? ?DIFF-OPTIONS? | |
| 474 | +** fossil stash apply|goto ?STASHID? | |
| 475 | +** fossil stash drop|rm ?STASHID? ?-a|--all? | |
| 476 | +** fossil stash diff ?STASHID? ?DIFF-OPTIONS? | |
| 477 | +** fossil stash gdiff ?STASHID? ?DIFF-OPTIONS? | |
| 475 | 478 | */ |
| 476 | 479 | void stash_cmd(void){ |
| 477 | 480 | const char *zCmd; |
| 478 | 481 | int nCmd; |
| 479 | 482 | int stashid = 0; |
| 483 | + int rc; | |
| 480 | 484 | undo_capture_command_line(); |
| 481 | 485 | db_must_be_within_tree(); |
| 482 | 486 | db_open_config(0, 0); |
| 483 | 487 | db_begin_transaction(); |
| 484 | 488 | db_multi_exec(zStashInit /*works-like:""*/); |
| 489 | + rc = db_exists("SELECT 1 FROM sqlite_master" | |
| 490 | + " WHERE name='stashfile'" | |
| 491 | + " AND sql GLOB '* PRIMARY KEY(origname, stashid)*'"); | |
| 492 | + if( rc!=0 ){ | |
| 493 | + db_multi_exec( | |
| 494 | + "CREATE TABLE localdb.stashfile_tmp AS SELECT * FROM stashfile;" | |
| 495 | + "DROP TABLE stashfile;" | |
| 496 | + ); | |
| 497 | + db_multi_exec(zStashInit /*works-like:""*/); | |
| 498 | + db_multi_exec( | |
| 499 | + "INSERT INTO stashfile SELECT * FROM stashfile_tmp;" | |
| 500 | + "DROP TABLE stashfile_tmp;" | |
| 501 | + ); | |
| 502 | + } | |
| 485 | 503 | if( g.argc<=2 ){ |
| 486 | 504 | zCmd = "save"; |
| 487 | 505 | }else{ |
| 488 | 506 | zCmd = g.argv[2]; |
| 489 | 507 | } |
| @@ -641,37 +659,30 @@ | ||
| 641 | 659 | || memcmp(zCmd, "cat", nCmd)==0 |
| 642 | 660 | ){ |
| 643 | 661 | const char *zDiffCmd = 0; |
| 644 | 662 | const char *zBinGlob = 0; |
| 645 | 663 | int fIncludeBinary = 0; |
| 664 | + int fBaseline = zCmd[0]=='s' || zCmd[0]=='c'; | |
| 646 | 665 | u64 diffFlags; |
| 647 | 666 | |
| 648 | 667 | if( find_option("tk",0,0)!=0 ){ |
| 649 | 668 | db_close(0); |
| 650 | - switch (zCmd[0]) { | |
| 651 | - case 's': | |
| 652 | - case 'c': | |
| 653 | - diff_tk("stash show", 3); | |
| 654 | - break; | |
| 655 | - | |
| 656 | - default: | |
| 657 | - diff_tk("stash diff", 3); | |
| 658 | - } | |
| 669 | + diff_tk(fBaseline ? "stash show" : "stash diff", 3); | |
| 659 | 670 | return; |
| 660 | 671 | } |
| 661 | 672 | if( find_option("internal","i",0)==0 ){ |
| 662 | 673 | zDiffCmd = diff_command_external(memcmp(zCmd, "gdiff", nCmd)==0); |
| 663 | 674 | } |
| 664 | 675 | diffFlags = diff_options(); |
| 665 | 676 | if( find_option("verbose","v",0)!=0 ) diffFlags |= DIFF_VERBOSE; |
| 666 | - if( g.argc>4 ) usage(mprintf("%s STASHID", zCmd)); | |
| 677 | + if( g.argc>4 ) usage(mprintf("%s ?STASHID? ?DIFF-OPTIONS?", zCmd)); | |
| 667 | 678 | if( zDiffCmd ){ |
| 668 | 679 | zBinGlob = diff_get_binary_glob(); |
| 669 | 680 | fIncludeBinary = diff_include_binary_files(); |
| 670 | 681 | } |
| 671 | 682 | stashid = stash_get_id(g.argc==4 ? g.argv[3] : 0); |
| 672 | - stash_diff(stashid, zDiffCmd, zBinGlob, zCmd[0]=='s', fIncludeBinary, | |
| 683 | + stash_diff(stashid, zDiffCmd, zBinGlob, fBaseline, fIncludeBinary, | |
| 673 | 684 | diffFlags); |
| 674 | 685 | }else |
| 675 | 686 | if( memcmp(zCmd, "help", nCmd)==0 ){ |
| 676 | 687 | g.argv[1] = "help"; |
| 677 | 688 | g.argv[2] = "stash"; |
| 678 | 689 |
| --- src/stash.c | |
| +++ src/stash.c | |
| @@ -25,11 +25,11 @@ | |
| 25 | ** SQL code to implement the tables needed by the stash. |
| 26 | */ |
| 27 | static const char zStashInit[] = |
| 28 | @ CREATE TABLE IF NOT EXISTS localdb.stash( |
| 29 | @ stashid INTEGER PRIMARY KEY, -- Unique stash identifier |
| 30 | @ vid INTEGER, -- The baseline check-out for this stash |
| 31 | @ comment TEXT, -- Comment for this stash. Or NULL |
| 32 | @ ctime TIMESTAMP -- When the stash was created |
| 33 | @ ); |
| 34 | @ CREATE TABLE IF NOT EXISTS localdb.stashfile( |
| 35 | @ stashid INTEGER REFERENCES stash, -- Stash that contains this file |
| @@ -39,11 +39,11 @@ | |
| 39 | @ isExec BOOLEAN, -- True if file is executable |
| 40 | @ isLink BOOLEAN, -- True if file is a symlink |
| 41 | @ origname TEXT, -- Original filename |
| 42 | @ newname TEXT, -- New name for file at next check-in |
| 43 | @ delta BLOB, -- Delta from baseline. Content if rid=0 |
| 44 | @ PRIMARY KEY(origname, stashid) |
| 45 | @ ); |
| 46 | @ INSERT OR IGNORE INTO vvar(name, value) VALUES('stash-next', 1); |
| 47 | ; |
| 48 | |
| 49 | /* |
| @@ -196,11 +196,11 @@ | |
| 196 | } |
| 197 | return stashid; |
| 198 | } |
| 199 | |
| 200 | /* |
| 201 | ** Apply a stash to the current check-out. |
| 202 | */ |
| 203 | static void stash_apply(int stashid, int nConflict){ |
| 204 | int vid; |
| 205 | Stmt q; |
| 206 | db_prepare(&q, |
| @@ -278,10 +278,15 @@ | |
| 278 | } |
| 279 | blob_reset(&delta); |
| 280 | if( fossil_strcmp(zOrig,zNew)!=0 ){ |
| 281 | undo_save(zOrig); |
| 282 | file_delete(zOPath); |
| 283 | } |
| 284 | } |
| 285 | stash_add_files_in_sfile(vid); |
| 286 | db_finalize(&q); |
| 287 | if( nConflict ){ |
| @@ -393,18 +398,18 @@ | |
| 393 | ** return that number. Or throw a fatal error if it is not a valid |
| 394 | ** stash number. If it is NULL, return the most recent stash or |
| 395 | ** throw an error if the stash is empty. |
| 396 | */ |
| 397 | static int stash_get_id(const char *zStashId){ |
| 398 | int stashid = 0; |
| 399 | if( zStashId==0 ){ |
| 400 | stashid = db_int(0, "SELECT max(stashid) FROM stash"); |
| 401 | if( stashid==0 ) fossil_fatal("empty stash"); |
| 402 | }else{ |
| 403 | stashid = atoi(zStashId); |
| 404 | if( !db_exists("SELECT 1 FROM stash WHERE stashid=%d", stashid) ){ |
| 405 | fossil_fatal("no such stash: %d\n", stashid); |
| 406 | } |
| 407 | } |
| 408 | return stashid; |
| 409 | } |
| 410 | |
| @@ -420,70 +425,83 @@ | |
| 420 | ** Save the current changes in the working tree as a new stash. |
| 421 | ** Then revert the changes back to the last check-in. If FILES |
| 422 | ** are listed, then only stash and revert the named files. The |
| 423 | ** "save" verb can be omitted if and only if there are no other |
| 424 | ** arguments. The "snapshot" verb works the same as "save" but |
| 425 | ** omits the revert, keeping the check-out unchanged. |
| 426 | ** |
| 427 | ** fossil stash list ?-v|--verbose? |
| 428 | ** fossil stash ls ?-v|--verbose? |
| 429 | ** |
| 430 | ** List all changes sets currently stashed. Show information about |
| 431 | ** individual files in each changeset if -v or --verbose is used. |
| 432 | ** |
| 433 | ** fossil stash show|cat ?STASHID? ?DIFF-FLAGS? |
| 434 | ** |
| 435 | ** Show the content of a stash |
| 436 | ** |
| 437 | ** fossil stash pop |
| 438 | ** fossil stash apply ?STASHID? |
| 439 | ** |
| 440 | ** Apply STASHID or the most recently create stash to the current |
| 441 | ** working check-out. The "pop" command deletes that changeset from |
| 442 | ** the stash after applying it but the "apply" command retains the |
| 443 | ** changeset. |
| 444 | ** |
| 445 | ** fossil stash goto ?STASHID? |
| 446 | ** |
| 447 | ** Update to the baseline checkout for STASHID then apply the |
| 448 | ** changes of STASHID. Keep STASHID so that it can be reused |
| 449 | ** This command is undoable. |
| 450 | ** |
| 451 | ** fossil stash drop ?STASHID? ?-a|--all? |
| 452 | ** fossil stash rm ?STASHID? ?-a|--all? |
| 453 | ** |
| 454 | ** Forget everything about STASHID. Forget the whole stash if the |
| 455 | ** -a|--all flag is used. Individual drops are undoable but -a|--all |
| 456 | ** is not. |
| 457 | ** |
| 458 | ** fossil stash diff ?STASHID? |
| 459 | ** fossil stash gdiff ?STASHID? |
| 460 | ** |
| 461 | ** Show diffs of the current working directory and what that |
| 462 | ** directory would be if STASHID were applied. |
| 463 | ** |
| 464 | ** SUMMARY: |
| 465 | ** fossil stash |
| 466 | ** fossil stash save ?-m|--comment COMMENT? ?FILES...? |
| 467 | ** fossil stash snapshot ?-m|--comment COMMENT? ?FILES...? |
| 468 | ** fossil stash list|ls ?-v|--verbose? ?-W|--width <num>? |
| 469 | ** fossil stash show|cat ?STASHID? ?DIFF-OPTIONS? |
| 470 | ** fossil stash pop |
| 471 | ** fossil stash apply ?STASHID? |
| 472 | ** fossil stash goto ?STASHID? |
| 473 | ** fossil stash rm|drop ?STASHID? ?-a|--all? |
| 474 | ** fossil stash [g]diff ?STASHID? ?DIFF-OPTIONS? |
| 475 | */ |
| 476 | void stash_cmd(void){ |
| 477 | const char *zCmd; |
| 478 | int nCmd; |
| 479 | int stashid = 0; |
| 480 | undo_capture_command_line(); |
| 481 | db_must_be_within_tree(); |
| 482 | db_open_config(0, 0); |
| 483 | db_begin_transaction(); |
| 484 | db_multi_exec(zStashInit /*works-like:""*/); |
| 485 | if( g.argc<=2 ){ |
| 486 | zCmd = "save"; |
| 487 | }else{ |
| 488 | zCmd = g.argv[2]; |
| 489 | } |
| @@ -641,37 +659,30 @@ | |
| 641 | || memcmp(zCmd, "cat", nCmd)==0 |
| 642 | ){ |
| 643 | const char *zDiffCmd = 0; |
| 644 | const char *zBinGlob = 0; |
| 645 | int fIncludeBinary = 0; |
| 646 | u64 diffFlags; |
| 647 | |
| 648 | if( find_option("tk",0,0)!=0 ){ |
| 649 | db_close(0); |
| 650 | switch (zCmd[0]) { |
| 651 | case 's': |
| 652 | case 'c': |
| 653 | diff_tk("stash show", 3); |
| 654 | break; |
| 655 | |
| 656 | default: |
| 657 | diff_tk("stash diff", 3); |
| 658 | } |
| 659 | return; |
| 660 | } |
| 661 | if( find_option("internal","i",0)==0 ){ |
| 662 | zDiffCmd = diff_command_external(memcmp(zCmd, "gdiff", nCmd)==0); |
| 663 | } |
| 664 | diffFlags = diff_options(); |
| 665 | if( find_option("verbose","v",0)!=0 ) diffFlags |= DIFF_VERBOSE; |
| 666 | if( g.argc>4 ) usage(mprintf("%s STASHID", zCmd)); |
| 667 | if( zDiffCmd ){ |
| 668 | zBinGlob = diff_get_binary_glob(); |
| 669 | fIncludeBinary = diff_include_binary_files(); |
| 670 | } |
| 671 | stashid = stash_get_id(g.argc==4 ? g.argv[3] : 0); |
| 672 | stash_diff(stashid, zDiffCmd, zBinGlob, zCmd[0]=='s', fIncludeBinary, |
| 673 | diffFlags); |
| 674 | }else |
| 675 | if( memcmp(zCmd, "help", nCmd)==0 ){ |
| 676 | g.argv[1] = "help"; |
| 677 | g.argv[2] = "stash"; |
| 678 |
| --- src/stash.c | |
| +++ src/stash.c | |
| @@ -25,11 +25,11 @@ | |
| 25 | ** SQL code to implement the tables needed by the stash. |
| 26 | */ |
| 27 | static const char zStashInit[] = |
| 28 | @ CREATE TABLE IF NOT EXISTS localdb.stash( |
| 29 | @ stashid INTEGER PRIMARY KEY, -- Unique stash identifier |
| 30 | @ vid INTEGER, -- The baseline checkout for this stash |
| 31 | @ comment TEXT, -- Comment for this stash. Or NULL |
| 32 | @ ctime TIMESTAMP -- When the stash was created |
| 33 | @ ); |
| 34 | @ CREATE TABLE IF NOT EXISTS localdb.stashfile( |
| 35 | @ stashid INTEGER REFERENCES stash, -- Stash that contains this file |
| @@ -39,11 +39,11 @@ | |
| 39 | @ isExec BOOLEAN, -- True if file is executable |
| 40 | @ isLink BOOLEAN, -- True if file is a symlink |
| 41 | @ origname TEXT, -- Original filename |
| 42 | @ newname TEXT, -- New name for file at next check-in |
| 43 | @ delta BLOB, -- Delta from baseline. Content if rid=0 |
| 44 | @ PRIMARY KEY(newname, stashid) |
| 45 | @ ); |
| 46 | @ INSERT OR IGNORE INTO vvar(name, value) VALUES('stash-next', 1); |
| 47 | ; |
| 48 | |
| 49 | /* |
| @@ -196,11 +196,11 @@ | |
| 196 | } |
| 197 | return stashid; |
| 198 | } |
| 199 | |
| 200 | /* |
| 201 | ** Apply a stash to the current checkout. |
| 202 | */ |
| 203 | static void stash_apply(int stashid, int nConflict){ |
| 204 | int vid; |
| 205 | Stmt q; |
| 206 | db_prepare(&q, |
| @@ -278,10 +278,15 @@ | |
| 278 | } |
| 279 | blob_reset(&delta); |
| 280 | if( fossil_strcmp(zOrig,zNew)!=0 ){ |
| 281 | undo_save(zOrig); |
| 282 | file_delete(zOPath); |
| 283 | db_multi_exec( |
| 284 | "UPDATE vfile SET pathname='%q', origname='%q'" |
| 285 | " WHERE pathname='%q' %s AND vid=%d", |
| 286 | zNew, zOrig, zOrig, filename_collation(), vid |
| 287 | ); |
| 288 | } |
| 289 | } |
| 290 | stash_add_files_in_sfile(vid); |
| 291 | db_finalize(&q); |
| 292 | if( nConflict ){ |
| @@ -393,18 +398,18 @@ | |
| 398 | ** return that number. Or throw a fatal error if it is not a valid |
| 399 | ** stash number. If it is NULL, return the most recent stash or |
| 400 | ** throw an error if the stash is empty. |
| 401 | */ |
| 402 | static int stash_get_id(const char *zStashId){ |
| 403 | int stashid; |
| 404 | if( zStashId==0 ){ |
| 405 | stashid = db_int(0, "SELECT max(stashid) FROM stash"); |
| 406 | if( stashid==0 ) fossil_fatal("empty stash"); |
| 407 | }else{ |
| 408 | stashid = atoi(zStashId); |
| 409 | if( !db_exists("SELECT 1 FROM stash WHERE stashid=%d", stashid) ){ |
| 410 | fossil_fatal("no such stash: %s", zStashId); |
| 411 | } |
| 412 | } |
| 413 | return stashid; |
| 414 | } |
| 415 | |
| @@ -420,70 +425,83 @@ | |
| 425 | ** Save the current changes in the working tree as a new stash. |
| 426 | ** Then revert the changes back to the last check-in. If FILES |
| 427 | ** are listed, then only stash and revert the named files. The |
| 428 | ** "save" verb can be omitted if and only if there are no other |
| 429 | ** arguments. The "snapshot" verb works the same as "save" but |
| 430 | ** omits the revert, keeping the checkout unchanged. |
| 431 | ** |
| 432 | ** fossil stash list|ls ?-v|--verbose? ?-W|--width <num>? |
| 433 | ** |
| 434 | ** List all changes sets currently stashed. Show information about |
| 435 | ** individual files in each changeset if -v or --verbose is used. |
| 436 | ** |
| 437 | ** fossil stash show|cat ?STASHID? ?DIFF-OPTIONS? |
| 438 | ** |
| 439 | ** Show the contents of a stash. |
| 440 | ** |
| 441 | ** fossil stash pop |
| 442 | ** fossil stash apply ?STASHID? |
| 443 | ** |
| 444 | ** Apply STASHID or the most recently create stash to the current |
| 445 | ** working checkout. The "pop" command deletes that changeset from |
| 446 | ** the stash after applying it but the "apply" command retains the |
| 447 | ** changeset. |
| 448 | ** |
| 449 | ** fossil stash goto ?STASHID? |
| 450 | ** |
| 451 | ** Update to the baseline checkout for STASHID then apply the |
| 452 | ** changes of STASHID. Keep STASHID so that it can be reused |
| 453 | ** This command is undoable. |
| 454 | ** |
| 455 | ** fossil stash drop|rm ?STASHID? ?-a|--all? |
| 456 | ** |
| 457 | ** Forget everything about STASHID. Forget the whole stash if the |
| 458 | ** -a|--all flag is used. Individual drops are undoable but -a|--all |
| 459 | ** is not. |
| 460 | ** |
| 461 | ** fossil stash diff ?STASHID? ?DIFF-OPTIONS? |
| 462 | ** fossil stash gdiff ?STASHID? ?DIFF-OPTIONS? |
| 463 | ** |
| 464 | ** Show diffs of the current working directory and what that |
| 465 | ** directory would be if STASHID were applied. |
| 466 | ** |
| 467 | ** SUMMARY: |
| 468 | ** fossil stash |
| 469 | ** fossil stash save ?-m|--comment COMMENT? ?FILES...? |
| 470 | ** fossil stash snapshot ?-m|--comment COMMENT? ?FILES...? |
| 471 | ** fossil stash list|ls ?-v|--verbose? ?-W|--width <num>? |
| 472 | ** fossil stash show|cat ?STASHID? ?DIFF-OPTIONS? |
| 473 | ** fossil stash pop |
| 474 | ** fossil stash apply|goto ?STASHID? |
| 475 | ** fossil stash drop|rm ?STASHID? ?-a|--all? |
| 476 | ** fossil stash diff ?STASHID? ?DIFF-OPTIONS? |
| 477 | ** fossil stash gdiff ?STASHID? ?DIFF-OPTIONS? |
| 478 | */ |
| 479 | void stash_cmd(void){ |
| 480 | const char *zCmd; |
| 481 | int nCmd; |
| 482 | int stashid = 0; |
| 483 | int rc; |
| 484 | undo_capture_command_line(); |
| 485 | db_must_be_within_tree(); |
| 486 | db_open_config(0, 0); |
| 487 | db_begin_transaction(); |
| 488 | db_multi_exec(zStashInit /*works-like:""*/); |
| 489 | rc = db_exists("SELECT 1 FROM sqlite_master" |
| 490 | " WHERE name='stashfile'" |
| 491 | " AND sql GLOB '* PRIMARY KEY(origname, stashid)*'"); |
| 492 | if( rc!=0 ){ |
| 493 | db_multi_exec( |
| 494 | "CREATE TABLE localdb.stashfile_tmp AS SELECT * FROM stashfile;" |
| 495 | "DROP TABLE stashfile;" |
| 496 | ); |
| 497 | db_multi_exec(zStashInit /*works-like:""*/); |
| 498 | db_multi_exec( |
| 499 | "INSERT INTO stashfile SELECT * FROM stashfile_tmp;" |
| 500 | "DROP TABLE stashfile_tmp;" |
| 501 | ); |
| 502 | } |
| 503 | if( g.argc<=2 ){ |
| 504 | zCmd = "save"; |
| 505 | }else{ |
| 506 | zCmd = g.argv[2]; |
| 507 | } |
| @@ -641,37 +659,30 @@ | |
| 659 | || memcmp(zCmd, "cat", nCmd)==0 |
| 660 | ){ |
| 661 | const char *zDiffCmd = 0; |
| 662 | const char *zBinGlob = 0; |
| 663 | int fIncludeBinary = 0; |
| 664 | int fBaseline = zCmd[0]=='s' || zCmd[0]=='c'; |
| 665 | u64 diffFlags; |
| 666 | |
| 667 | if( find_option("tk",0,0)!=0 ){ |
| 668 | db_close(0); |
| 669 | diff_tk(fBaseline ? "stash show" : "stash diff", 3); |
| 670 | return; |
| 671 | } |
| 672 | if( find_option("internal","i",0)==0 ){ |
| 673 | zDiffCmd = diff_command_external(memcmp(zCmd, "gdiff", nCmd)==0); |
| 674 | } |
| 675 | diffFlags = diff_options(); |
| 676 | if( find_option("verbose","v",0)!=0 ) diffFlags |= DIFF_VERBOSE; |
| 677 | if( g.argc>4 ) usage(mprintf("%s ?STASHID? ?DIFF-OPTIONS?", zCmd)); |
| 678 | if( zDiffCmd ){ |
| 679 | zBinGlob = diff_get_binary_glob(); |
| 680 | fIncludeBinary = diff_include_binary_files(); |
| 681 | } |
| 682 | stashid = stash_get_id(g.argc==4 ? g.argv[3] : 0); |
| 683 | stash_diff(stashid, zDiffCmd, zBinGlob, fBaseline, fIncludeBinary, |
| 684 | diffFlags); |
| 685 | }else |
| 686 | if( memcmp(zCmd, "help", nCmd)==0 ){ |
| 687 | g.argv[1] = "help"; |
| 688 | g.argv[2] = "stash"; |
| 689 |
+4
-7
| --- src/stat.c | ||
| +++ src/stat.c | ||
| @@ -422,19 +422,18 @@ | ||
| 422 | 422 | style_submenu_element("Stat", "Repository Stats", "stat"); |
| 423 | 423 | if( g.perm.Admin ){ |
| 424 | 424 | style_submenu_element("Schema", "Repository Schema", "repo_schema"); |
| 425 | 425 | } |
| 426 | 426 | db_multi_exec( |
| 427 | - "CREATE VIRTUAL TABLE temp.dbx USING dbstat(repository);" | |
| 428 | 427 | "CREATE TEMP TABLE trans(name TEXT PRIMARY KEY,tabname TEXT)WITHOUT ROWID;" |
| 429 | 428 | "INSERT INTO trans(name,tabname)" |
| 430 | 429 | " SELECT name, tbl_name FROM repository.sqlite_master;" |
| 431 | 430 | "CREATE TEMP TABLE piechart(amt REAL, label TEXT);" |
| 432 | 431 | "INSERT INTO piechart(amt,label)" |
| 433 | 432 | " SELECT count(*), " |
| 434 | - " coalesce((SELECT tabname FROM trans WHERE trans.name=dbx.name),name)" | |
| 435 | - " FROM dbx" | |
| 433 | + " coalesce((SELECT tabname FROM trans WHERE trans.name=dbstat.name),name)" | |
| 434 | + " FROM dbstat('repository')" | |
| 436 | 435 | " GROUP BY 2 ORDER BY 2;" |
| 437 | 436 | ); |
| 438 | 437 | nPageFree = db_int(0, "PRAGMA repository.freelist_count"); |
| 439 | 438 | if( nPageFree>0 ){ |
| 440 | 439 | db_multi_exec( |
| @@ -449,20 +448,18 @@ | ||
| 449 | 448 | piechart_render(800,500,PIE_OTHER|PIE_PERCENT); |
| 450 | 449 | @ </svg></center> |
| 451 | 450 | |
| 452 | 451 | if( g.localOpen ){ |
| 453 | 452 | db_multi_exec( |
| 454 | - "DROP TABLE temp.dbx;" | |
| 455 | - "CREATE VIRTUAL TABLE temp.dbx USING dbstat(localdb);" | |
| 456 | 453 | "DELETE FROM trans;" |
| 457 | 454 | "INSERT INTO trans(name,tabname)" |
| 458 | 455 | " SELECT name, tbl_name FROM localdb.sqlite_master;" |
| 459 | 456 | "DELETE FROM piechart;" |
| 460 | 457 | "INSERT INTO piechart(amt,label)" |
| 461 | 458 | " SELECT count(*), " |
| 462 | - " coalesce((SELECT tabname FROM trans WHERE trans.name=dbx.name),name)" | |
| 463 | - " FROM dbx" | |
| 459 | + " coalesce((SELECT tabname FROM trans WHERE trans.name=dbstat.name),name)" | |
| 460 | + " FROM dbstat('localdb')" | |
| 464 | 461 | " GROUP BY 2 ORDER BY 2;" |
| 465 | 462 | ); |
| 466 | 463 | nPageFree = db_int(0, "PRAGMA localdb.freelist_count"); |
| 467 | 464 | if( nPageFree>0 ){ |
| 468 | 465 | db_multi_exec( |
| 469 | 466 |
| --- src/stat.c | |
| +++ src/stat.c | |
| @@ -422,19 +422,18 @@ | |
| 422 | style_submenu_element("Stat", "Repository Stats", "stat"); |
| 423 | if( g.perm.Admin ){ |
| 424 | style_submenu_element("Schema", "Repository Schema", "repo_schema"); |
| 425 | } |
| 426 | db_multi_exec( |
| 427 | "CREATE VIRTUAL TABLE temp.dbx USING dbstat(repository);" |
| 428 | "CREATE TEMP TABLE trans(name TEXT PRIMARY KEY,tabname TEXT)WITHOUT ROWID;" |
| 429 | "INSERT INTO trans(name,tabname)" |
| 430 | " SELECT name, tbl_name FROM repository.sqlite_master;" |
| 431 | "CREATE TEMP TABLE piechart(amt REAL, label TEXT);" |
| 432 | "INSERT INTO piechart(amt,label)" |
| 433 | " SELECT count(*), " |
| 434 | " coalesce((SELECT tabname FROM trans WHERE trans.name=dbx.name),name)" |
| 435 | " FROM dbx" |
| 436 | " GROUP BY 2 ORDER BY 2;" |
| 437 | ); |
| 438 | nPageFree = db_int(0, "PRAGMA repository.freelist_count"); |
| 439 | if( nPageFree>0 ){ |
| 440 | db_multi_exec( |
| @@ -449,20 +448,18 @@ | |
| 449 | piechart_render(800,500,PIE_OTHER|PIE_PERCENT); |
| 450 | @ </svg></center> |
| 451 | |
| 452 | if( g.localOpen ){ |
| 453 | db_multi_exec( |
| 454 | "DROP TABLE temp.dbx;" |
| 455 | "CREATE VIRTUAL TABLE temp.dbx USING dbstat(localdb);" |
| 456 | "DELETE FROM trans;" |
| 457 | "INSERT INTO trans(name,tabname)" |
| 458 | " SELECT name, tbl_name FROM localdb.sqlite_master;" |
| 459 | "DELETE FROM piechart;" |
| 460 | "INSERT INTO piechart(amt,label)" |
| 461 | " SELECT count(*), " |
| 462 | " coalesce((SELECT tabname FROM trans WHERE trans.name=dbx.name),name)" |
| 463 | " FROM dbx" |
| 464 | " GROUP BY 2 ORDER BY 2;" |
| 465 | ); |
| 466 | nPageFree = db_int(0, "PRAGMA localdb.freelist_count"); |
| 467 | if( nPageFree>0 ){ |
| 468 | db_multi_exec( |
| 469 |
| --- src/stat.c | |
| +++ src/stat.c | |
| @@ -422,19 +422,18 @@ | |
| 422 | style_submenu_element("Stat", "Repository Stats", "stat"); |
| 423 | if( g.perm.Admin ){ |
| 424 | style_submenu_element("Schema", "Repository Schema", "repo_schema"); |
| 425 | } |
| 426 | db_multi_exec( |
| 427 | "CREATE TEMP TABLE trans(name TEXT PRIMARY KEY,tabname TEXT)WITHOUT ROWID;" |
| 428 | "INSERT INTO trans(name,tabname)" |
| 429 | " SELECT name, tbl_name FROM repository.sqlite_master;" |
| 430 | "CREATE TEMP TABLE piechart(amt REAL, label TEXT);" |
| 431 | "INSERT INTO piechart(amt,label)" |
| 432 | " SELECT count(*), " |
| 433 | " coalesce((SELECT tabname FROM trans WHERE trans.name=dbstat.name),name)" |
| 434 | " FROM dbstat('repository')" |
| 435 | " GROUP BY 2 ORDER BY 2;" |
| 436 | ); |
| 437 | nPageFree = db_int(0, "PRAGMA repository.freelist_count"); |
| 438 | if( nPageFree>0 ){ |
| 439 | db_multi_exec( |
| @@ -449,20 +448,18 @@ | |
| 448 | piechart_render(800,500,PIE_OTHER|PIE_PERCENT); |
| 449 | @ </svg></center> |
| 450 | |
| 451 | if( g.localOpen ){ |
| 452 | db_multi_exec( |
| 453 | "DELETE FROM trans;" |
| 454 | "INSERT INTO trans(name,tabname)" |
| 455 | " SELECT name, tbl_name FROM localdb.sqlite_master;" |
| 456 | "DELETE FROM piechart;" |
| 457 | "INSERT INTO piechart(amt,label)" |
| 458 | " SELECT count(*), " |
| 459 | " coalesce((SELECT tabname FROM trans WHERE trans.name=dbstat.name),name)" |
| 460 | " FROM dbstat('localdb')" |
| 461 | " GROUP BY 2 ORDER BY 2;" |
| 462 | ); |
| 463 | nPageFree = db_int(0, "PRAGMA localdb.freelist_count"); |
| 464 | if( nPageFree>0 ){ |
| 465 | db_multi_exec( |
| 466 |
+1
| --- src/style.c | ||
| +++ src/style.c | ||
| @@ -400,10 +400,11 @@ | ||
| 400 | 400 | |
| 401 | 401 | if( g.thTrace ) Th_Trace("BEGIN_HEADER<br />\n", -1); |
| 402 | 402 | |
| 403 | 403 | /* Generate the header up through the main menu */ |
| 404 | 404 | Th_Store("project_name", db_get("project-name","Unnamed Fossil Project")); |
| 405 | + Th_Store("project_description", db_get("project-description","")); | |
| 405 | 406 | Th_Store("title", zTitle); |
| 406 | 407 | Th_Store("baseurl", g.zBaseURL); |
| 407 | 408 | Th_Store("secureurl", login_wants_https_redirect()? g.zHttpsURL: g.zBaseURL); |
| 408 | 409 | Th_Store("home", g.zTop); |
| 409 | 410 | Th_Store("index_page", db_get("index-page","/home")); |
| 410 | 411 |
| --- src/style.c | |
| +++ src/style.c | |
| @@ -400,10 +400,11 @@ | |
| 400 | |
| 401 | if( g.thTrace ) Th_Trace("BEGIN_HEADER<br />\n", -1); |
| 402 | |
| 403 | /* Generate the header up through the main menu */ |
| 404 | Th_Store("project_name", db_get("project-name","Unnamed Fossil Project")); |
| 405 | Th_Store("title", zTitle); |
| 406 | Th_Store("baseurl", g.zBaseURL); |
| 407 | Th_Store("secureurl", login_wants_https_redirect()? g.zHttpsURL: g.zBaseURL); |
| 408 | Th_Store("home", g.zTop); |
| 409 | Th_Store("index_page", db_get("index-page","/home")); |
| 410 |
| --- src/style.c | |
| +++ src/style.c | |
| @@ -400,10 +400,11 @@ | |
| 400 | |
| 401 | if( g.thTrace ) Th_Trace("BEGIN_HEADER<br />\n", -1); |
| 402 | |
| 403 | /* Generate the header up through the main menu */ |
| 404 | Th_Store("project_name", db_get("project-name","Unnamed Fossil Project")); |
| 405 | Th_Store("project_description", db_get("project-description","")); |
| 406 | Th_Store("title", zTitle); |
| 407 | Th_Store("baseurl", g.zBaseURL); |
| 408 | Th_Store("secureurl", login_wants_https_redirect()? g.zHttpsURL: g.zBaseURL); |
| 409 | Th_Store("home", g.zTop); |
| 410 | Th_Store("index_page", db_get("index-page","/home")); |
| 411 |
+1
| --- src/tag.c | ||
| +++ src/tag.c | ||
| @@ -359,10 +359,11 @@ | ||
| 359 | 359 | }else{ |
| 360 | 360 | nrid = content_put(&ctrl); |
| 361 | 361 | manifest_crosslink(nrid, &ctrl, MC_PERMIT_HOOKS); |
| 362 | 362 | } |
| 363 | 363 | assert( blob_is_reset(&ctrl) ); |
| 364 | + manifest_to_disk(rid); | |
| 364 | 365 | } |
| 365 | 366 | |
| 366 | 367 | /* |
| 367 | 368 | ** COMMAND: tag |
| 368 | 369 | ** |
| 369 | 370 |
| --- src/tag.c | |
| +++ src/tag.c | |
| @@ -359,10 +359,11 @@ | |
| 359 | }else{ |
| 360 | nrid = content_put(&ctrl); |
| 361 | manifest_crosslink(nrid, &ctrl, MC_PERMIT_HOOKS); |
| 362 | } |
| 363 | assert( blob_is_reset(&ctrl) ); |
| 364 | } |
| 365 | |
| 366 | /* |
| 367 | ** COMMAND: tag |
| 368 | ** |
| 369 |
| --- src/tag.c | |
| +++ src/tag.c | |
| @@ -359,10 +359,11 @@ | |
| 359 | }else{ |
| 360 | nrid = content_put(&ctrl); |
| 361 | manifest_crosslink(nrid, &ctrl, MC_PERMIT_HOOKS); |
| 362 | } |
| 363 | assert( blob_is_reset(&ctrl) ); |
| 364 | manifest_to_disk(rid); |
| 365 | } |
| 366 | |
| 367 | /* |
| 368 | ** COMMAND: tag |
| 369 | ** |
| 370 |
+52
-16
| --- src/tar.c | ||
| +++ src/tar.c | ||
| @@ -475,11 +475,11 @@ | ||
| 475 | 475 | Blob mfile, hash, file; |
| 476 | 476 | Manifest *pManifest; |
| 477 | 477 | ManifestFile *pFile; |
| 478 | 478 | Blob filename; |
| 479 | 479 | int nPrefix; |
| 480 | - char *zName; | |
| 480 | + char *zName = 0; | |
| 481 | 481 | unsigned int mTime; |
| 482 | 482 | |
| 483 | 483 | content_get(rid, &mfile); |
| 484 | 484 | if( blob_size(&mfile)==0 ){ |
| 485 | 485 | blob_zero(pTar); |
| @@ -493,28 +493,64 @@ | ||
| 493 | 493 | } |
| 494 | 494 | nPrefix = blob_size(&filename); |
| 495 | 495 | |
| 496 | 496 | pManifest = manifest_get(rid, CFTYPE_MANIFEST, 0); |
| 497 | 497 | if( pManifest ){ |
| 498 | + int flg, eflg = 0; | |
| 498 | 499 | mTime = (pManifest->rDate - 2440587.5)*86400.0; |
| 499 | 500 | tar_begin(mTime); |
| 500 | - if( (pInclude==0 || glob_match(pInclude, "manifest")) | |
| 501 | - && !glob_match(pExclude, "manifest") | |
| 502 | - && db_get_boolean("manifest", 0) | |
| 503 | - ){ | |
| 504 | - blob_append(&filename, "manifest", -1); | |
| 505 | - zName = blob_str(&filename); | |
| 506 | - sha1sum_blob(&mfile, &hash); | |
| 507 | - sterilize_manifest(&mfile); | |
| 508 | - tar_add_file(zName, &mfile, 0, mTime); | |
| 501 | + flg = db_get_manifest_setting(); | |
| 502 | + if( flg ){ | |
| 503 | + /* eflg is the effective flags, taking include/exclude into account */ | |
| 504 | + if( (pInclude==0 || glob_match(pInclude, "manifest")) | |
| 505 | + && !glob_match(pExclude, "manifest") | |
| 506 | + && (flg & MFESTFLG_RAW) ){ | |
| 507 | + eflg |= MFESTFLG_RAW; | |
| 508 | + } | |
| 509 | + if( (pInclude==0 || glob_match(pInclude, "manifest.uuid")) | |
| 510 | + && !glob_match(pExclude, "manifest.uuid") | |
| 511 | + && (flg & MFESTFLG_UUID) ){ | |
| 512 | + eflg |= MFESTFLG_UUID; | |
| 513 | + } | |
| 514 | + if( (pInclude==0 || glob_match(pInclude, "manifest.tags")) | |
| 515 | + && !glob_match(pExclude, "manifest.tags") | |
| 516 | + && (flg & MFESTFLG_TAGS) ){ | |
| 517 | + eflg |= MFESTFLG_TAGS; | |
| 518 | + } | |
| 519 | + | |
| 520 | + if( eflg & (MFESTFLG_RAW|MFESTFLG_UUID) ){ | |
| 521 | + if( eflg & MFESTFLG_RAW ){ | |
| 522 | + blob_append(&filename, "manifest", -1); | |
| 523 | + zName = blob_str(&filename); | |
| 524 | + } | |
| 525 | + if( eflg & MFESTFLG_UUID ){ | |
| 526 | + sha1sum_blob(&mfile, &hash); | |
| 527 | + } | |
| 528 | + if( eflg & MFESTFLG_RAW ) { | |
| 529 | + sterilize_manifest(&mfile); | |
| 530 | + tar_add_file(zName, &mfile, 0, mTime); | |
| 531 | + } | |
| 532 | + } | |
| 509 | 533 | blob_reset(&mfile); |
| 510 | - blob_append(&hash, "\n", 1); | |
| 511 | - blob_resize(&filename, nPrefix); | |
| 512 | - blob_append(&filename, "manifest.uuid", -1); | |
| 513 | - zName = blob_str(&filename); | |
| 514 | - tar_add_file(zName, &hash, 0, mTime); | |
| 515 | - blob_reset(&hash); | |
| 534 | + if( eflg & MFESTFLG_UUID ){ | |
| 535 | + blob_append(&hash, "\n", 1); | |
| 536 | + blob_resize(&filename, nPrefix); | |
| 537 | + blob_append(&filename, "manifest.uuid", -1); | |
| 538 | + zName = blob_str(&filename); | |
| 539 | + tar_add_file(zName, &hash, 0, mTime); | |
| 540 | + blob_reset(&hash); | |
| 541 | + } | |
| 542 | + if( eflg & MFESTFLG_TAGS ){ | |
| 543 | + Blob tagslist; | |
| 544 | + blob_zero(&tagslist); | |
| 545 | + get_checkin_taglist(rid, &tagslist); | |
| 546 | + blob_resize(&filename, nPrefix); | |
| 547 | + blob_append(&filename, "manifest.tags", -1); | |
| 548 | + zName = blob_str(&filename); | |
| 549 | + tar_add_file(zName, &tagslist, 0, mTime); | |
| 550 | + blob_reset(&tagslist); | |
| 551 | + } | |
| 516 | 552 | } |
| 517 | 553 | manifest_file_rewind(pManifest); |
| 518 | 554 | while( (pFile = manifest_file_next(pManifest,0))!=0 ){ |
| 519 | 555 | int fid; |
| 520 | 556 | if( pInclude!=0 && !glob_match(pInclude, pFile->zName) ) continue; |
| 521 | 557 |
| --- src/tar.c | |
| +++ src/tar.c | |
| @@ -475,11 +475,11 @@ | |
| 475 | Blob mfile, hash, file; |
| 476 | Manifest *pManifest; |
| 477 | ManifestFile *pFile; |
| 478 | Blob filename; |
| 479 | int nPrefix; |
| 480 | char *zName; |
| 481 | unsigned int mTime; |
| 482 | |
| 483 | content_get(rid, &mfile); |
| 484 | if( blob_size(&mfile)==0 ){ |
| 485 | blob_zero(pTar); |
| @@ -493,28 +493,64 @@ | |
| 493 | } |
| 494 | nPrefix = blob_size(&filename); |
| 495 | |
| 496 | pManifest = manifest_get(rid, CFTYPE_MANIFEST, 0); |
| 497 | if( pManifest ){ |
| 498 | mTime = (pManifest->rDate - 2440587.5)*86400.0; |
| 499 | tar_begin(mTime); |
| 500 | if( (pInclude==0 || glob_match(pInclude, "manifest")) |
| 501 | && !glob_match(pExclude, "manifest") |
| 502 | && db_get_boolean("manifest", 0) |
| 503 | ){ |
| 504 | blob_append(&filename, "manifest", -1); |
| 505 | zName = blob_str(&filename); |
| 506 | sha1sum_blob(&mfile, &hash); |
| 507 | sterilize_manifest(&mfile); |
| 508 | tar_add_file(zName, &mfile, 0, mTime); |
| 509 | blob_reset(&mfile); |
| 510 | blob_append(&hash, "\n", 1); |
| 511 | blob_resize(&filename, nPrefix); |
| 512 | blob_append(&filename, "manifest.uuid", -1); |
| 513 | zName = blob_str(&filename); |
| 514 | tar_add_file(zName, &hash, 0, mTime); |
| 515 | blob_reset(&hash); |
| 516 | } |
| 517 | manifest_file_rewind(pManifest); |
| 518 | while( (pFile = manifest_file_next(pManifest,0))!=0 ){ |
| 519 | int fid; |
| 520 | if( pInclude!=0 && !glob_match(pInclude, pFile->zName) ) continue; |
| 521 |
| --- src/tar.c | |
| +++ src/tar.c | |
| @@ -475,11 +475,11 @@ | |
| 475 | Blob mfile, hash, file; |
| 476 | Manifest *pManifest; |
| 477 | ManifestFile *pFile; |
| 478 | Blob filename; |
| 479 | int nPrefix; |
| 480 | char *zName = 0; |
| 481 | unsigned int mTime; |
| 482 | |
| 483 | content_get(rid, &mfile); |
| 484 | if( blob_size(&mfile)==0 ){ |
| 485 | blob_zero(pTar); |
| @@ -493,28 +493,64 @@ | |
| 493 | } |
| 494 | nPrefix = blob_size(&filename); |
| 495 | |
| 496 | pManifest = manifest_get(rid, CFTYPE_MANIFEST, 0); |
| 497 | if( pManifest ){ |
| 498 | int flg, eflg = 0; |
| 499 | mTime = (pManifest->rDate - 2440587.5)*86400.0; |
| 500 | tar_begin(mTime); |
| 501 | flg = db_get_manifest_setting(); |
| 502 | if( flg ){ |
| 503 | /* eflg is the effective flags, taking include/exclude into account */ |
| 504 | if( (pInclude==0 || glob_match(pInclude, "manifest")) |
| 505 | && !glob_match(pExclude, "manifest") |
| 506 | && (flg & MFESTFLG_RAW) ){ |
| 507 | eflg |= MFESTFLG_RAW; |
| 508 | } |
| 509 | if( (pInclude==0 || glob_match(pInclude, "manifest.uuid")) |
| 510 | && !glob_match(pExclude, "manifest.uuid") |
| 511 | && (flg & MFESTFLG_UUID) ){ |
| 512 | eflg |= MFESTFLG_UUID; |
| 513 | } |
| 514 | if( (pInclude==0 || glob_match(pInclude, "manifest.tags")) |
| 515 | && !glob_match(pExclude, "manifest.tags") |
| 516 | && (flg & MFESTFLG_TAGS) ){ |
| 517 | eflg |= MFESTFLG_TAGS; |
| 518 | } |
| 519 | |
| 520 | if( eflg & (MFESTFLG_RAW|MFESTFLG_UUID) ){ |
| 521 | if( eflg & MFESTFLG_RAW ){ |
| 522 | blob_append(&filename, "manifest", -1); |
| 523 | zName = blob_str(&filename); |
| 524 | } |
| 525 | if( eflg & MFESTFLG_UUID ){ |
| 526 | sha1sum_blob(&mfile, &hash); |
| 527 | } |
| 528 | if( eflg & MFESTFLG_RAW ) { |
| 529 | sterilize_manifest(&mfile); |
| 530 | tar_add_file(zName, &mfile, 0, mTime); |
| 531 | } |
| 532 | } |
| 533 | blob_reset(&mfile); |
| 534 | if( eflg & MFESTFLG_UUID ){ |
| 535 | blob_append(&hash, "\n", 1); |
| 536 | blob_resize(&filename, nPrefix); |
| 537 | blob_append(&filename, "manifest.uuid", -1); |
| 538 | zName = blob_str(&filename); |
| 539 | tar_add_file(zName, &hash, 0, mTime); |
| 540 | blob_reset(&hash); |
| 541 | } |
| 542 | if( eflg & MFESTFLG_TAGS ){ |
| 543 | Blob tagslist; |
| 544 | blob_zero(&tagslist); |
| 545 | get_checkin_taglist(rid, &tagslist); |
| 546 | blob_resize(&filename, nPrefix); |
| 547 | blob_append(&filename, "manifest.tags", -1); |
| 548 | zName = blob_str(&filename); |
| 549 | tar_add_file(zName, &tagslist, 0, mTime); |
| 550 | blob_reset(&tagslist); |
| 551 | } |
| 552 | } |
| 553 | manifest_file_rewind(pManifest); |
| 554 | while( (pFile = manifest_file_next(pManifest,0))!=0 ){ |
| 555 | int fid; |
| 556 | if( pInclude!=0 && !glob_match(pInclude, pFile->zName) ) continue; |
| 557 |
+84
-1
| --- src/th_main.c | ||
| +++ src/th_main.c | ||
| @@ -1317,10 +1317,92 @@ | ||
| 1317 | 1317 | }else{ |
| 1318 | 1318 | Th_SetResult(interp, "repository unavailable", -1); |
| 1319 | 1319 | return TH_ERROR; |
| 1320 | 1320 | } |
| 1321 | 1321 | } |
| 1322 | + | |
| 1323 | +/* | |
| 1324 | +** TH1 command: unversioned content FILENAME | |
| 1325 | +** | |
| 1326 | +** Attempts to locate the specified unversioned file and return its contents. | |
| 1327 | +** An error is generated if the repository is not open or the unversioned file | |
| 1328 | +** cannot be found. | |
| 1329 | +*/ | |
| 1330 | +static int unversionedContentCmd( | |
| 1331 | + Th_Interp *interp, | |
| 1332 | + void *p, | |
| 1333 | + int argc, | |
| 1334 | + const char **argv, | |
| 1335 | + int *argl | |
| 1336 | +){ | |
| 1337 | + if( argc!=3 ){ | |
| 1338 | + return Th_WrongNumArgs(interp, "unversioned content FILENAME"); | |
| 1339 | + } | |
| 1340 | + if( Th_IsRepositoryOpen() ){ | |
| 1341 | + Blob content; | |
| 1342 | + if( unversioned_content(argv[2], &content)==0 ){ | |
| 1343 | + Th_SetResult(interp, blob_str(&content), blob_size(&content)); | |
| 1344 | + blob_reset(&content); | |
| 1345 | + return TH_OK; | |
| 1346 | + }else{ | |
| 1347 | + return TH_ERROR; | |
| 1348 | + } | |
| 1349 | + }else{ | |
| 1350 | + Th_SetResult(interp, "repository unavailable", -1); | |
| 1351 | + return TH_ERROR; | |
| 1352 | + } | |
| 1353 | +} | |
| 1354 | + | |
| 1355 | +/* | |
| 1356 | +** TH1 command: unversioned list | |
| 1357 | +** | |
| 1358 | +** Returns a list of the names of all unversioned files held in the local | |
| 1359 | +** repository. An error is generated if the repository is not open. | |
| 1360 | +*/ | |
| 1361 | +static int unversionedListCmd( | |
| 1362 | + Th_Interp *interp, | |
| 1363 | + void *p, | |
| 1364 | + int argc, | |
| 1365 | + const char **argv, | |
| 1366 | + int *argl | |
| 1367 | +){ | |
| 1368 | + if( argc!=2 ){ | |
| 1369 | + return Th_WrongNumArgs(interp, "unversioned list"); | |
| 1370 | + } | |
| 1371 | + if( Th_IsRepositoryOpen() ){ | |
| 1372 | + Stmt q; | |
| 1373 | + char *zList = 0; | |
| 1374 | + int nList = 0; | |
| 1375 | + db_prepare(&q, "SELECT name FROM unversioned WHERE hash IS NOT NULL" | |
| 1376 | + " ORDER BY name"); | |
| 1377 | + while( db_step(&q)==SQLITE_ROW ){ | |
| 1378 | + Th_ListAppend(interp, &zList, &nList, db_column_text(&q,0), -1); | |
| 1379 | + } | |
| 1380 | + db_finalize(&q); | |
| 1381 | + Th_SetResult(interp, zList, nList); | |
| 1382 | + Th_Free(interp, zList); | |
| 1383 | + return TH_OK; | |
| 1384 | + }else{ | |
| 1385 | + Th_SetResult(interp, "repository unavailable", -1); | |
| 1386 | + return TH_ERROR; | |
| 1387 | + } | |
| 1388 | +} | |
| 1389 | + | |
| 1390 | +static int unversionedCmd( | |
| 1391 | + Th_Interp *interp, | |
| 1392 | + void *p, | |
| 1393 | + int argc, | |
| 1394 | + const char **argv, | |
| 1395 | + int *argl | |
| 1396 | +){ | |
| 1397 | + static const Th_SubCommand aSub[] = { | |
| 1398 | + { "content", unversionedContentCmd }, | |
| 1399 | + { "list", unversionedListCmd }, | |
| 1400 | + { 0, 0 } | |
| 1401 | + }; | |
| 1402 | + return Th_CallSubCommand(interp, p, argc, argv, argl, aSub); | |
| 1403 | +} | |
| 1322 | 1404 | |
| 1323 | 1405 | #ifdef _WIN32 |
| 1324 | 1406 | # include <windows.h> |
| 1325 | 1407 | #else |
| 1326 | 1408 | # include <sys/time.h> |
| @@ -1886,10 +1968,11 @@ | ||
| 1886 | 1968 | {"styleHeader", styleHeaderCmd, 0}, |
| 1887 | 1969 | {"styleFooter", styleFooterCmd, 0}, |
| 1888 | 1970 | {"tclReady", tclReadyCmd, 0}, |
| 1889 | 1971 | {"trace", traceCmd, 0}, |
| 1890 | 1972 | {"stime", stimeCmd, 0}, |
| 1973 | + {"unversioned", unversionedCmd, 0}, | |
| 1891 | 1974 | {"utime", utimeCmd, 0}, |
| 1892 | 1975 | {"verifyCsrf", verifyCsrfCmd, 0}, |
| 1893 | 1976 | {"wiki", wikiCmd, (void*)&aFlags[0]}, |
| 1894 | 1977 | {0, 0, 0} |
| 1895 | 1978 | }; |
| @@ -2593,11 +2676,11 @@ | ||
| 2593 | 2676 | }else if( fossil_stricmp(g.argv[2], "webhook")==0 ){ |
| 2594 | 2677 | rc = Th_WebpageHook(g.argv[3], (unsigned int)atoi(g.argv[4])); |
| 2595 | 2678 | }else if( fossil_stricmp(g.argv[2], "webnotify")==0 ){ |
| 2596 | 2679 | rc = Th_WebpageNotify(g.argv[3], (unsigned int)atoi(g.argv[4])); |
| 2597 | 2680 | }else{ |
| 2598 | - fossil_fatal("Unknown TH1 hook %s\n", g.argv[2]); | |
| 2681 | + fossil_fatal("Unknown TH1 hook %s", g.argv[2]); | |
| 2599 | 2682 | } |
| 2600 | 2683 | if( g.interp ){ |
| 2601 | 2684 | zResult = (char*)Th_GetResult(g.interp, &nResult); |
| 2602 | 2685 | } |
| 2603 | 2686 | sendText("RESULT (", -1, 0); |
| 2604 | 2687 |
| --- src/th_main.c | |
| +++ src/th_main.c | |
| @@ -1317,10 +1317,92 @@ | |
| 1317 | }else{ |
| 1318 | Th_SetResult(interp, "repository unavailable", -1); |
| 1319 | return TH_ERROR; |
| 1320 | } |
| 1321 | } |
| 1322 | |
| 1323 | #ifdef _WIN32 |
| 1324 | # include <windows.h> |
| 1325 | #else |
| 1326 | # include <sys/time.h> |
| @@ -1886,10 +1968,11 @@ | |
| 1886 | {"styleHeader", styleHeaderCmd, 0}, |
| 1887 | {"styleFooter", styleFooterCmd, 0}, |
| 1888 | {"tclReady", tclReadyCmd, 0}, |
| 1889 | {"trace", traceCmd, 0}, |
| 1890 | {"stime", stimeCmd, 0}, |
| 1891 | {"utime", utimeCmd, 0}, |
| 1892 | {"verifyCsrf", verifyCsrfCmd, 0}, |
| 1893 | {"wiki", wikiCmd, (void*)&aFlags[0]}, |
| 1894 | {0, 0, 0} |
| 1895 | }; |
| @@ -2593,11 +2676,11 @@ | |
| 2593 | }else if( fossil_stricmp(g.argv[2], "webhook")==0 ){ |
| 2594 | rc = Th_WebpageHook(g.argv[3], (unsigned int)atoi(g.argv[4])); |
| 2595 | }else if( fossil_stricmp(g.argv[2], "webnotify")==0 ){ |
| 2596 | rc = Th_WebpageNotify(g.argv[3], (unsigned int)atoi(g.argv[4])); |
| 2597 | }else{ |
| 2598 | fossil_fatal("Unknown TH1 hook %s\n", g.argv[2]); |
| 2599 | } |
| 2600 | if( g.interp ){ |
| 2601 | zResult = (char*)Th_GetResult(g.interp, &nResult); |
| 2602 | } |
| 2603 | sendText("RESULT (", -1, 0); |
| 2604 |
| --- src/th_main.c | |
| +++ src/th_main.c | |
| @@ -1317,10 +1317,92 @@ | |
| 1317 | }else{ |
| 1318 | Th_SetResult(interp, "repository unavailable", -1); |
| 1319 | return TH_ERROR; |
| 1320 | } |
| 1321 | } |
| 1322 | |
| 1323 | /* |
| 1324 | ** TH1 command: unversioned content FILENAME |
| 1325 | ** |
| 1326 | ** Attempts to locate the specified unversioned file and return its contents. |
| 1327 | ** An error is generated if the repository is not open or the unversioned file |
| 1328 | ** cannot be found. |
| 1329 | */ |
| 1330 | static int unversionedContentCmd( |
| 1331 | Th_Interp *interp, |
| 1332 | void *p, |
| 1333 | int argc, |
| 1334 | const char **argv, |
| 1335 | int *argl |
| 1336 | ){ |
| 1337 | if( argc!=3 ){ |
| 1338 | return Th_WrongNumArgs(interp, "unversioned content FILENAME"); |
| 1339 | } |
| 1340 | if( Th_IsRepositoryOpen() ){ |
| 1341 | Blob content; |
| 1342 | if( unversioned_content(argv[2], &content)==0 ){ |
| 1343 | Th_SetResult(interp, blob_str(&content), blob_size(&content)); |
| 1344 | blob_reset(&content); |
| 1345 | return TH_OK; |
| 1346 | }else{ |
| 1347 | return TH_ERROR; |
| 1348 | } |
| 1349 | }else{ |
| 1350 | Th_SetResult(interp, "repository unavailable", -1); |
| 1351 | return TH_ERROR; |
| 1352 | } |
| 1353 | } |
| 1354 | |
| 1355 | /* |
| 1356 | ** TH1 command: unversioned list |
| 1357 | ** |
| 1358 | ** Returns a list of the names of all unversioned files held in the local |
| 1359 | ** repository. An error is generated if the repository is not open. |
| 1360 | */ |
| 1361 | static int unversionedListCmd( |
| 1362 | Th_Interp *interp, |
| 1363 | void *p, |
| 1364 | int argc, |
| 1365 | const char **argv, |
| 1366 | int *argl |
| 1367 | ){ |
| 1368 | if( argc!=2 ){ |
| 1369 | return Th_WrongNumArgs(interp, "unversioned list"); |
| 1370 | } |
| 1371 | if( Th_IsRepositoryOpen() ){ |
| 1372 | Stmt q; |
| 1373 | char *zList = 0; |
| 1374 | int nList = 0; |
| 1375 | db_prepare(&q, "SELECT name FROM unversioned WHERE hash IS NOT NULL" |
| 1376 | " ORDER BY name"); |
| 1377 | while( db_step(&q)==SQLITE_ROW ){ |
| 1378 | Th_ListAppend(interp, &zList, &nList, db_column_text(&q,0), -1); |
| 1379 | } |
| 1380 | db_finalize(&q); |
| 1381 | Th_SetResult(interp, zList, nList); |
| 1382 | Th_Free(interp, zList); |
| 1383 | return TH_OK; |
| 1384 | }else{ |
| 1385 | Th_SetResult(interp, "repository unavailable", -1); |
| 1386 | return TH_ERROR; |
| 1387 | } |
| 1388 | } |
| 1389 | |
| 1390 | static int unversionedCmd( |
| 1391 | Th_Interp *interp, |
| 1392 | void *p, |
| 1393 | int argc, |
| 1394 | const char **argv, |
| 1395 | int *argl |
| 1396 | ){ |
| 1397 | static const Th_SubCommand aSub[] = { |
| 1398 | { "content", unversionedContentCmd }, |
| 1399 | { "list", unversionedListCmd }, |
| 1400 | { 0, 0 } |
| 1401 | }; |
| 1402 | return Th_CallSubCommand(interp, p, argc, argv, argl, aSub); |
| 1403 | } |
| 1404 | |
| 1405 | #ifdef _WIN32 |
| 1406 | # include <windows.h> |
| 1407 | #else |
| 1408 | # include <sys/time.h> |
| @@ -1886,10 +1968,11 @@ | |
| 1968 | {"styleHeader", styleHeaderCmd, 0}, |
| 1969 | {"styleFooter", styleFooterCmd, 0}, |
| 1970 | {"tclReady", tclReadyCmd, 0}, |
| 1971 | {"trace", traceCmd, 0}, |
| 1972 | {"stime", stimeCmd, 0}, |
| 1973 | {"unversioned", unversionedCmd, 0}, |
| 1974 | {"utime", utimeCmd, 0}, |
| 1975 | {"verifyCsrf", verifyCsrfCmd, 0}, |
| 1976 | {"wiki", wikiCmd, (void*)&aFlags[0]}, |
| 1977 | {0, 0, 0} |
| 1978 | }; |
| @@ -2593,11 +2676,11 @@ | |
| 2676 | }else if( fossil_stricmp(g.argv[2], "webhook")==0 ){ |
| 2677 | rc = Th_WebpageHook(g.argv[3], (unsigned int)atoi(g.argv[4])); |
| 2678 | }else if( fossil_stricmp(g.argv[2], "webnotify")==0 ){ |
| 2679 | rc = Th_WebpageNotify(g.argv[3], (unsigned int)atoi(g.argv[4])); |
| 2680 | }else{ |
| 2681 | fossil_fatal("Unknown TH1 hook %s", g.argv[2]); |
| 2682 | } |
| 2683 | if( g.interp ){ |
| 2684 | zResult = (char*)Th_GetResult(g.interp, &nResult); |
| 2685 | } |
| 2686 | sendText("RESULT (", -1, 0); |
| 2687 |
+36
-18
| --- src/timeline.c | ||
| +++ src/timeline.c | ||
| @@ -26,10 +26,19 @@ | ||
| 26 | 26 | /* |
| 27 | 27 | ** The value of one second in julianday notation |
| 28 | 28 | */ |
| 29 | 29 | #define ONE_SECOND (1.0/86400.0) |
| 30 | 30 | |
| 31 | +/* | |
| 32 | +** timeline mode options | |
| 33 | +*/ | |
| 34 | +#define TIMELINE_MODE_NONE 0 | |
| 35 | +#define TIMELINE_MODE_BEFORE 1 | |
| 36 | +#define TIMELINE_MODE_AFTER 2 | |
| 37 | +#define TIMELINE_MODE_CHILDREN 3 | |
| 38 | +#define TIMELINE_MODE_PARENTS 4 | |
| 39 | + | |
| 31 | 40 | /* |
| 32 | 41 | ** Add an appropriate tag to the output if "rid" is unpublished (private) |
| 33 | 42 | */ |
| 34 | 43 | #define UNPUB_TAG "<em>(unpublished)</em>" |
| 35 | 44 | void tag_private_status(int rid){ |
| @@ -728,11 +737,11 @@ | ||
| 728 | 737 | pRow->mergeOut, /* mo */ |
| 729 | 738 | pRow->mergeUpto, /* mu */ |
| 730 | 739 | pRow->aiRiser[pRow->iRail], /* u */ |
| 731 | 740 | pRow->isLeaf ? 1 : 0 /* f */ |
| 732 | 741 | ); |
| 733 | - /* u */ | |
| 742 | + /* au */ | |
| 734 | 743 | cSep = '['; |
| 735 | 744 | for(i=0; i<GR_MAX_RAIL; i++){ |
| 736 | 745 | if( i==pRow->iRail ) continue; |
| 737 | 746 | if( pRow->aiRiser[i]>0 ){ |
| 738 | 747 | cgi_printf("%c%d,%d", cSep, i, pRow->aiRiser[i]); |
| @@ -748,11 +757,11 @@ | ||
| 748 | 757 | cgi_printf("mi:"); |
| 749 | 758 | cSep = '['; |
| 750 | 759 | for(i=0; i<GR_MAX_RAIL; i++){ |
| 751 | 760 | if( pRow->mergeIn[i] ){ |
| 752 | 761 | int mi = i; |
| 753 | - if( pRow->mergeDown & (1<<i) ) mi = -mi; | |
| 762 | + if( (pRow->mergeDown >> i) & 1 ) mi = -mi; | |
| 754 | 763 | cgi_printf("%c%d", cSep, mi); |
| 755 | 764 | cSep = ','; |
| 756 | 765 | } |
| 757 | 766 | } |
| 758 | 767 | if( cSep=='[' ) cgi_printf("["); |
| @@ -2029,10 +2038,17 @@ | ||
| 2029 | 2038 | && z[4]=='-' |
| 2030 | 2039 | && z[7]=='-' |
| 2031 | 2040 | && fossil_isdigit(z[0]) |
| 2032 | 2041 | && fossil_isdigit(z[5]); |
| 2033 | 2042 | } |
| 2043 | + | |
| 2044 | +/* | |
| 2045 | +** Return true if the input string can be converted to a julianday. | |
| 2046 | +*/ | |
| 2047 | +static int fossil_is_julianday(const char *zDate){ | |
| 2048 | + return db_int(0, "SELECT EXISTS (SELECT julianday(%Q) AS jd WHERE jd IS NOT NULL)", zDate); | |
| 2049 | +} | |
| 2034 | 2050 | |
| 2035 | 2051 | /* |
| 2036 | 2052 | ** COMMAND: timeline |
| 2037 | 2053 | ** |
| 2038 | 2054 | ** Usage: %fossil timeline ?WHEN? ?CHECKIN|DATETIME? ?OPTIONS? |
| @@ -2087,11 +2103,11 @@ | ||
| 2087 | 2103 | char *zOrigin; |
| 2088 | 2104 | char *zDate; |
| 2089 | 2105 | Blob sql; |
| 2090 | 2106 | int objid = 0; |
| 2091 | 2107 | Blob uuid; |
| 2092 | - int mode = 0 ; /* 0:none 1: before 2:after 3:children 4:parents */ | |
| 2108 | + int mode = TIMELINE_MODE_NONE; | |
| 2093 | 2109 | int verboseFlag = 0 ; |
| 2094 | 2110 | int iOffset; |
| 2095 | 2111 | const char *zFilePattern = 0; |
| 2096 | 2112 | Blob treeName; |
| 2097 | 2113 | |
| @@ -2128,21 +2144,21 @@ | ||
| 2128 | 2144 | verify_all_options(); |
| 2129 | 2145 | |
| 2130 | 2146 | if( g.argc>=4 ){ |
| 2131 | 2147 | k = strlen(g.argv[2]); |
| 2132 | 2148 | if( strncmp(g.argv[2],"before",k)==0 ){ |
| 2133 | - mode = 1; | |
| 2149 | + mode = TIMELINE_MODE_BEFORE; | |
| 2134 | 2150 | }else if( strncmp(g.argv[2],"after",k)==0 && k>1 ){ |
| 2135 | - mode = 2; | |
| 2151 | + mode = TIMELINE_MODE_AFTER; | |
| 2136 | 2152 | }else if( strncmp(g.argv[2],"descendants",k)==0 ){ |
| 2137 | - mode = 3; | |
| 2153 | + mode = TIMELINE_MODE_CHILDREN; | |
| 2138 | 2154 | }else if( strncmp(g.argv[2],"children",k)==0 ){ |
| 2139 | - mode = 3; | |
| 2155 | + mode = TIMELINE_MODE_CHILDREN; | |
| 2140 | 2156 | }else if( strncmp(g.argv[2],"ancestors",k)==0 && k>1 ){ |
| 2141 | - mode = 4; | |
| 2157 | + mode = TIMELINE_MODE_PARENTS; | |
| 2142 | 2158 | }else if( strncmp(g.argv[2],"parents",k)==0 ){ |
| 2143 | - mode = 4; | |
| 2159 | + mode = TIMELINE_MODE_PARENTS; | |
| 2144 | 2160 | }else if(!zType && !zLimit){ |
| 2145 | 2161 | usage("?WHEN? ?CHECKIN|DATETIME? ?-n|--limit #? ?-t|--type TYPE? " |
| 2146 | 2162 | "?-W|--width WIDTH? ?-p|--path PATH"); |
| 2147 | 2163 | } |
| 2148 | 2164 | if( '-' != *g.argv[3] ){ |
| @@ -2157,11 +2173,11 @@ | ||
| 2157 | 2173 | } |
| 2158 | 2174 | k = strlen(zOrigin); |
| 2159 | 2175 | blob_zero(&uuid); |
| 2160 | 2176 | blob_append(&uuid, zOrigin, -1); |
| 2161 | 2177 | if( fossil_strcmp(zOrigin, "now")==0 ){ |
| 2162 | - if( mode==3 || mode==4 ){ | |
| 2178 | + if( mode==TIMELINE_MODE_CHILDREN || mode==TIMELINE_MODE_PARENTS ){ | |
| 2163 | 2179 | fossil_fatal("cannot compute descendants or ancestors of a date"); |
| 2164 | 2180 | } |
| 2165 | 2181 | zDate = mprintf("(SELECT datetime('now'))"); |
| 2166 | 2182 | }else if( strncmp(zOrigin, "current", k)==0 ){ |
| 2167 | 2183 | if( !g.localOpen ){ |
| @@ -2170,19 +2186,21 @@ | ||
| 2170 | 2186 | objid = db_lget_int("checkout",0); |
| 2171 | 2187 | zDate = mprintf("(SELECT mtime FROM plink WHERE cid=%d)", objid); |
| 2172 | 2188 | }else if( name_to_uuid(&uuid, 0, "*")==0 ){ |
| 2173 | 2189 | objid = db_int(0, "SELECT rid FROM blob WHERE uuid=%B", &uuid); |
| 2174 | 2190 | zDate = mprintf("(SELECT mtime FROM event WHERE objid=%d)", objid); |
| 2175 | - }else{ | |
| 2191 | + }else if( fossil_is_julianday(zOrigin) ){ | |
| 2176 | 2192 | const char *zShift = ""; |
| 2177 | - if( mode==3 || mode==4 ){ | |
| 2193 | + if( mode==TIMELINE_MODE_CHILDREN || mode==TIMELINE_MODE_PARENTS ){ | |
| 2178 | 2194 | fossil_fatal("cannot compute descendants or ancestors of a date"); |
| 2179 | 2195 | } |
| 2180 | - if( mode==0 ){ | |
| 2196 | + if( mode==TIMELINE_MODE_NONE ){ | |
| 2181 | 2197 | if( isIsoDate(zOrigin) ) zShift = ",'+1 day'"; |
| 2182 | 2198 | } |
| 2183 | 2199 | zDate = mprintf("(SELECT julianday(%Q%s, fromLocal()))", zOrigin, zShift); |
| 2200 | + }else{ | |
| 2201 | + fossil_fatal("unknown check-in or invalid date: %s", zOrigin); | |
| 2184 | 2202 | } |
| 2185 | 2203 | |
| 2186 | 2204 | if( zFilePattern ){ |
| 2187 | 2205 | if( zType==0 ){ |
| 2188 | 2206 | /* When zFilePattern is specified and type is not specified, only show |
| @@ -2195,21 +2213,21 @@ | ||
| 2195 | 2213 | * zFilePattern. */ |
| 2196 | 2214 | zFilePattern = 0; |
| 2197 | 2215 | } |
| 2198 | 2216 | } |
| 2199 | 2217 | |
| 2200 | - if( mode==0 ) mode = 1; | |
| 2218 | + if( mode==TIMELINE_MODE_NONE ) mode = TIMELINE_MODE_BEFORE; | |
| 2201 | 2219 | blob_zero(&sql); |
| 2202 | 2220 | blob_append(&sql, timeline_query_for_tty(), -1); |
| 2203 | 2221 | blob_append_sql(&sql, "\n AND event.mtime %s %s", |
| 2204 | - (mode==1 || mode==4) ? "<=" : ">=", | |
| 2205 | - zDate /*safe-for-%s*/ | |
| 2222 | + ( mode==TIMELINE_MODE_BEFORE || | |
| 2223 | + mode==TIMELINE_MODE_PARENTS ) ? "<=" : ">=", zDate /*safe-for-%s*/ | |
| 2206 | 2224 | ); |
| 2207 | 2225 | |
| 2208 | - if( mode==3 || mode==4 ){ | |
| 2226 | + if( mode==TIMELINE_MODE_CHILDREN || mode==TIMELINE_MODE_PARENTS ){ | |
| 2209 | 2227 | db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)"); |
| 2210 | - if( mode==3 ){ | |
| 2228 | + if( mode==TIMELINE_MODE_CHILDREN ){ | |
| 2211 | 2229 | compute_descendants(objid, n); |
| 2212 | 2230 | }else{ |
| 2213 | 2231 | compute_ancestors(objid, n, 0); |
| 2214 | 2232 | } |
| 2215 | 2233 | blob_append_sql(&sql, "\n AND blob.rid IN ok"); |
| 2216 | 2234 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -26,10 +26,19 @@ | |
| 26 | /* |
| 27 | ** The value of one second in julianday notation |
| 28 | */ |
| 29 | #define ONE_SECOND (1.0/86400.0) |
| 30 | |
| 31 | /* |
| 32 | ** Add an appropriate tag to the output if "rid" is unpublished (private) |
| 33 | */ |
| 34 | #define UNPUB_TAG "<em>(unpublished)</em>" |
| 35 | void tag_private_status(int rid){ |
| @@ -728,11 +737,11 @@ | |
| 728 | pRow->mergeOut, /* mo */ |
| 729 | pRow->mergeUpto, /* mu */ |
| 730 | pRow->aiRiser[pRow->iRail], /* u */ |
| 731 | pRow->isLeaf ? 1 : 0 /* f */ |
| 732 | ); |
| 733 | /* u */ |
| 734 | cSep = '['; |
| 735 | for(i=0; i<GR_MAX_RAIL; i++){ |
| 736 | if( i==pRow->iRail ) continue; |
| 737 | if( pRow->aiRiser[i]>0 ){ |
| 738 | cgi_printf("%c%d,%d", cSep, i, pRow->aiRiser[i]); |
| @@ -748,11 +757,11 @@ | |
| 748 | cgi_printf("mi:"); |
| 749 | cSep = '['; |
| 750 | for(i=0; i<GR_MAX_RAIL; i++){ |
| 751 | if( pRow->mergeIn[i] ){ |
| 752 | int mi = i; |
| 753 | if( pRow->mergeDown & (1<<i) ) mi = -mi; |
| 754 | cgi_printf("%c%d", cSep, mi); |
| 755 | cSep = ','; |
| 756 | } |
| 757 | } |
| 758 | if( cSep=='[' ) cgi_printf("["); |
| @@ -2029,10 +2038,17 @@ | |
| 2029 | && z[4]=='-' |
| 2030 | && z[7]=='-' |
| 2031 | && fossil_isdigit(z[0]) |
| 2032 | && fossil_isdigit(z[5]); |
| 2033 | } |
| 2034 | |
| 2035 | /* |
| 2036 | ** COMMAND: timeline |
| 2037 | ** |
| 2038 | ** Usage: %fossil timeline ?WHEN? ?CHECKIN|DATETIME? ?OPTIONS? |
| @@ -2087,11 +2103,11 @@ | |
| 2087 | char *zOrigin; |
| 2088 | char *zDate; |
| 2089 | Blob sql; |
| 2090 | int objid = 0; |
| 2091 | Blob uuid; |
| 2092 | int mode = 0 ; /* 0:none 1: before 2:after 3:children 4:parents */ |
| 2093 | int verboseFlag = 0 ; |
| 2094 | int iOffset; |
| 2095 | const char *zFilePattern = 0; |
| 2096 | Blob treeName; |
| 2097 | |
| @@ -2128,21 +2144,21 @@ | |
| 2128 | verify_all_options(); |
| 2129 | |
| 2130 | if( g.argc>=4 ){ |
| 2131 | k = strlen(g.argv[2]); |
| 2132 | if( strncmp(g.argv[2],"before",k)==0 ){ |
| 2133 | mode = 1; |
| 2134 | }else if( strncmp(g.argv[2],"after",k)==0 && k>1 ){ |
| 2135 | mode = 2; |
| 2136 | }else if( strncmp(g.argv[2],"descendants",k)==0 ){ |
| 2137 | mode = 3; |
| 2138 | }else if( strncmp(g.argv[2],"children",k)==0 ){ |
| 2139 | mode = 3; |
| 2140 | }else if( strncmp(g.argv[2],"ancestors",k)==0 && k>1 ){ |
| 2141 | mode = 4; |
| 2142 | }else if( strncmp(g.argv[2],"parents",k)==0 ){ |
| 2143 | mode = 4; |
| 2144 | }else if(!zType && !zLimit){ |
| 2145 | usage("?WHEN? ?CHECKIN|DATETIME? ?-n|--limit #? ?-t|--type TYPE? " |
| 2146 | "?-W|--width WIDTH? ?-p|--path PATH"); |
| 2147 | } |
| 2148 | if( '-' != *g.argv[3] ){ |
| @@ -2157,11 +2173,11 @@ | |
| 2157 | } |
| 2158 | k = strlen(zOrigin); |
| 2159 | blob_zero(&uuid); |
| 2160 | blob_append(&uuid, zOrigin, -1); |
| 2161 | if( fossil_strcmp(zOrigin, "now")==0 ){ |
| 2162 | if( mode==3 || mode==4 ){ |
| 2163 | fossil_fatal("cannot compute descendants or ancestors of a date"); |
| 2164 | } |
| 2165 | zDate = mprintf("(SELECT datetime('now'))"); |
| 2166 | }else if( strncmp(zOrigin, "current", k)==0 ){ |
| 2167 | if( !g.localOpen ){ |
| @@ -2170,19 +2186,21 @@ | |
| 2170 | objid = db_lget_int("checkout",0); |
| 2171 | zDate = mprintf("(SELECT mtime FROM plink WHERE cid=%d)", objid); |
| 2172 | }else if( name_to_uuid(&uuid, 0, "*")==0 ){ |
| 2173 | objid = db_int(0, "SELECT rid FROM blob WHERE uuid=%B", &uuid); |
| 2174 | zDate = mprintf("(SELECT mtime FROM event WHERE objid=%d)", objid); |
| 2175 | }else{ |
| 2176 | const char *zShift = ""; |
| 2177 | if( mode==3 || mode==4 ){ |
| 2178 | fossil_fatal("cannot compute descendants or ancestors of a date"); |
| 2179 | } |
| 2180 | if( mode==0 ){ |
| 2181 | if( isIsoDate(zOrigin) ) zShift = ",'+1 day'"; |
| 2182 | } |
| 2183 | zDate = mprintf("(SELECT julianday(%Q%s, fromLocal()))", zOrigin, zShift); |
| 2184 | } |
| 2185 | |
| 2186 | if( zFilePattern ){ |
| 2187 | if( zType==0 ){ |
| 2188 | /* When zFilePattern is specified and type is not specified, only show |
| @@ -2195,21 +2213,21 @@ | |
| 2195 | * zFilePattern. */ |
| 2196 | zFilePattern = 0; |
| 2197 | } |
| 2198 | } |
| 2199 | |
| 2200 | if( mode==0 ) mode = 1; |
| 2201 | blob_zero(&sql); |
| 2202 | blob_append(&sql, timeline_query_for_tty(), -1); |
| 2203 | blob_append_sql(&sql, "\n AND event.mtime %s %s", |
| 2204 | (mode==1 || mode==4) ? "<=" : ">=", |
| 2205 | zDate /*safe-for-%s*/ |
| 2206 | ); |
| 2207 | |
| 2208 | if( mode==3 || mode==4 ){ |
| 2209 | db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)"); |
| 2210 | if( mode==3 ){ |
| 2211 | compute_descendants(objid, n); |
| 2212 | }else{ |
| 2213 | compute_ancestors(objid, n, 0); |
| 2214 | } |
| 2215 | blob_append_sql(&sql, "\n AND blob.rid IN ok"); |
| 2216 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -26,10 +26,19 @@ | |
| 26 | /* |
| 27 | ** The value of one second in julianday notation |
| 28 | */ |
| 29 | #define ONE_SECOND (1.0/86400.0) |
| 30 | |
| 31 | /* |
| 32 | ** timeline mode options |
| 33 | */ |
| 34 | #define TIMELINE_MODE_NONE 0 |
| 35 | #define TIMELINE_MODE_BEFORE 1 |
| 36 | #define TIMELINE_MODE_AFTER 2 |
| 37 | #define TIMELINE_MODE_CHILDREN 3 |
| 38 | #define TIMELINE_MODE_PARENTS 4 |
| 39 | |
| 40 | /* |
| 41 | ** Add an appropriate tag to the output if "rid" is unpublished (private) |
| 42 | */ |
| 43 | #define UNPUB_TAG "<em>(unpublished)</em>" |
| 44 | void tag_private_status(int rid){ |
| @@ -728,11 +737,11 @@ | |
| 737 | pRow->mergeOut, /* mo */ |
| 738 | pRow->mergeUpto, /* mu */ |
| 739 | pRow->aiRiser[pRow->iRail], /* u */ |
| 740 | pRow->isLeaf ? 1 : 0 /* f */ |
| 741 | ); |
| 742 | /* au */ |
| 743 | cSep = '['; |
| 744 | for(i=0; i<GR_MAX_RAIL; i++){ |
| 745 | if( i==pRow->iRail ) continue; |
| 746 | if( pRow->aiRiser[i]>0 ){ |
| 747 | cgi_printf("%c%d,%d", cSep, i, pRow->aiRiser[i]); |
| @@ -748,11 +757,11 @@ | |
| 757 | cgi_printf("mi:"); |
| 758 | cSep = '['; |
| 759 | for(i=0; i<GR_MAX_RAIL; i++){ |
| 760 | if( pRow->mergeIn[i] ){ |
| 761 | int mi = i; |
| 762 | if( (pRow->mergeDown >> i) & 1 ) mi = -mi; |
| 763 | cgi_printf("%c%d", cSep, mi); |
| 764 | cSep = ','; |
| 765 | } |
| 766 | } |
| 767 | if( cSep=='[' ) cgi_printf("["); |
| @@ -2029,10 +2038,17 @@ | |
| 2038 | && z[4]=='-' |
| 2039 | && z[7]=='-' |
| 2040 | && fossil_isdigit(z[0]) |
| 2041 | && fossil_isdigit(z[5]); |
| 2042 | } |
| 2043 | |
| 2044 | /* |
| 2045 | ** Return true if the input string can be converted to a julianday. |
| 2046 | */ |
| 2047 | static int fossil_is_julianday(const char *zDate){ |
| 2048 | return db_int(0, "SELECT EXISTS (SELECT julianday(%Q) AS jd WHERE jd IS NOT NULL)", zDate); |
| 2049 | } |
| 2050 | |
| 2051 | /* |
| 2052 | ** COMMAND: timeline |
| 2053 | ** |
| 2054 | ** Usage: %fossil timeline ?WHEN? ?CHECKIN|DATETIME? ?OPTIONS? |
| @@ -2087,11 +2103,11 @@ | |
| 2103 | char *zOrigin; |
| 2104 | char *zDate; |
| 2105 | Blob sql; |
| 2106 | int objid = 0; |
| 2107 | Blob uuid; |
| 2108 | int mode = TIMELINE_MODE_NONE; |
| 2109 | int verboseFlag = 0 ; |
| 2110 | int iOffset; |
| 2111 | const char *zFilePattern = 0; |
| 2112 | Blob treeName; |
| 2113 | |
| @@ -2128,21 +2144,21 @@ | |
| 2144 | verify_all_options(); |
| 2145 | |
| 2146 | if( g.argc>=4 ){ |
| 2147 | k = strlen(g.argv[2]); |
| 2148 | if( strncmp(g.argv[2],"before",k)==0 ){ |
| 2149 | mode = TIMELINE_MODE_BEFORE; |
| 2150 | }else if( strncmp(g.argv[2],"after",k)==0 && k>1 ){ |
| 2151 | mode = TIMELINE_MODE_AFTER; |
| 2152 | }else if( strncmp(g.argv[2],"descendants",k)==0 ){ |
| 2153 | mode = TIMELINE_MODE_CHILDREN; |
| 2154 | }else if( strncmp(g.argv[2],"children",k)==0 ){ |
| 2155 | mode = TIMELINE_MODE_CHILDREN; |
| 2156 | }else if( strncmp(g.argv[2],"ancestors",k)==0 && k>1 ){ |
| 2157 | mode = TIMELINE_MODE_PARENTS; |
| 2158 | }else if( strncmp(g.argv[2],"parents",k)==0 ){ |
| 2159 | mode = TIMELINE_MODE_PARENTS; |
| 2160 | }else if(!zType && !zLimit){ |
| 2161 | usage("?WHEN? ?CHECKIN|DATETIME? ?-n|--limit #? ?-t|--type TYPE? " |
| 2162 | "?-W|--width WIDTH? ?-p|--path PATH"); |
| 2163 | } |
| 2164 | if( '-' != *g.argv[3] ){ |
| @@ -2157,11 +2173,11 @@ | |
| 2173 | } |
| 2174 | k = strlen(zOrigin); |
| 2175 | blob_zero(&uuid); |
| 2176 | blob_append(&uuid, zOrigin, -1); |
| 2177 | if( fossil_strcmp(zOrigin, "now")==0 ){ |
| 2178 | if( mode==TIMELINE_MODE_CHILDREN || mode==TIMELINE_MODE_PARENTS ){ |
| 2179 | fossil_fatal("cannot compute descendants or ancestors of a date"); |
| 2180 | } |
| 2181 | zDate = mprintf("(SELECT datetime('now'))"); |
| 2182 | }else if( strncmp(zOrigin, "current", k)==0 ){ |
| 2183 | if( !g.localOpen ){ |
| @@ -2170,19 +2186,21 @@ | |
| 2186 | objid = db_lget_int("checkout",0); |
| 2187 | zDate = mprintf("(SELECT mtime FROM plink WHERE cid=%d)", objid); |
| 2188 | }else if( name_to_uuid(&uuid, 0, "*")==0 ){ |
| 2189 | objid = db_int(0, "SELECT rid FROM blob WHERE uuid=%B", &uuid); |
| 2190 | zDate = mprintf("(SELECT mtime FROM event WHERE objid=%d)", objid); |
| 2191 | }else if( fossil_is_julianday(zOrigin) ){ |
| 2192 | const char *zShift = ""; |
| 2193 | if( mode==TIMELINE_MODE_CHILDREN || mode==TIMELINE_MODE_PARENTS ){ |
| 2194 | fossil_fatal("cannot compute descendants or ancestors of a date"); |
| 2195 | } |
| 2196 | if( mode==TIMELINE_MODE_NONE ){ |
| 2197 | if( isIsoDate(zOrigin) ) zShift = ",'+1 day'"; |
| 2198 | } |
| 2199 | zDate = mprintf("(SELECT julianday(%Q%s, fromLocal()))", zOrigin, zShift); |
| 2200 | }else{ |
| 2201 | fossil_fatal("unknown check-in or invalid date: %s", zOrigin); |
| 2202 | } |
| 2203 | |
| 2204 | if( zFilePattern ){ |
| 2205 | if( zType==0 ){ |
| 2206 | /* When zFilePattern is specified and type is not specified, only show |
| @@ -2195,21 +2213,21 @@ | |
| 2213 | * zFilePattern. */ |
| 2214 | zFilePattern = 0; |
| 2215 | } |
| 2216 | } |
| 2217 | |
| 2218 | if( mode==TIMELINE_MODE_NONE ) mode = TIMELINE_MODE_BEFORE; |
| 2219 | blob_zero(&sql); |
| 2220 | blob_append(&sql, timeline_query_for_tty(), -1); |
| 2221 | blob_append_sql(&sql, "\n AND event.mtime %s %s", |
| 2222 | ( mode==TIMELINE_MODE_BEFORE || |
| 2223 | mode==TIMELINE_MODE_PARENTS ) ? "<=" : ">=", zDate /*safe-for-%s*/ |
| 2224 | ); |
| 2225 | |
| 2226 | if( mode==TIMELINE_MODE_CHILDREN || mode==TIMELINE_MODE_PARENTS ){ |
| 2227 | db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)"); |
| 2228 | if( mode==TIMELINE_MODE_CHILDREN ){ |
| 2229 | compute_descendants(objid, n); |
| 2230 | }else{ |
| 2231 | compute_ancestors(objid, n, 0); |
| 2232 | } |
| 2233 | blob_append_sql(&sql, "\n AND blob.rid IN ok"); |
| 2234 |
+14
-8
| --- src/tkt.c | ||
| +++ src/tkt.c | ||
| @@ -216,20 +216,25 @@ | ||
| 216 | 216 | const char *zBaseName = zName[0]=='+' ? zName+1 : zName; |
| 217 | 217 | j = fieldId(zBaseName); |
| 218 | 218 | if( j<0 ) continue; |
| 219 | 219 | aUsed[j] = 1; |
| 220 | 220 | if( aField[j].mUsed & USEDBY_TICKET ){ |
| 221 | - if( zName[0]=='+' ){ | |
| 222 | - zName++; | |
| 221 | + const char *zUsedByName = zName; | |
| 222 | + if( zUsedByName[0]=='+' ){ | |
| 223 | + zUsedByName++; | |
| 223 | 224 | blob_append_sql(&sql1,", \"%w\"=coalesce(\"%w\",'') || %Q", |
| 224 | - zName, zName, p->aField[i].zValue); | |
| 225 | + zUsedByName, zUsedByName, p->aField[i].zValue); | |
| 225 | 226 | }else{ |
| 226 | - blob_append_sql(&sql1,", \"%w\"=%Q", zName, p->aField[i].zValue); | |
| 227 | + blob_append_sql(&sql1,", \"%w\"=%Q", zUsedByName, p->aField[i].zValue); | |
| 227 | 228 | } |
| 228 | 229 | } |
| 229 | 230 | if( aField[j].mUsed & USEDBY_TICKETCHNG ){ |
| 230 | - blob_append_sql(&sql2, ",\"%w\"", zName); | |
| 231 | + const char *zUsedByName = zName; | |
| 232 | + if( zUsedByName[0]=='+' ){ | |
| 233 | + zUsedByName++; | |
| 234 | + } | |
| 235 | + blob_append_sql(&sql2, ",\"%w\"", zUsedByName); | |
| 231 | 236 | blob_append_sql(&sql3, ",%Q", p->aField[i].zValue); |
| 232 | 237 | } |
| 233 | 238 | if( rid>0 ){ |
| 234 | 239 | wiki_extract_links(p->aField[i].zValue, rid, 1, p->rDate, i==0, 0); |
| 235 | 240 | } |
| @@ -546,11 +551,13 @@ | ||
| 546 | 551 | Blob *pTicket, /* The text of the ticket change record */ |
| 547 | 552 | const char *zTktId, /* The ticket to which this change is applied */ |
| 548 | 553 | int needMod /* True if moderation is needed */ |
| 549 | 554 | ){ |
| 550 | 555 | int result; |
| 551 | - int rid = content_put_ex(pTicket, 0, 0, 0, needMod); | |
| 556 | + int rid; | |
| 557 | + manifest_crosslink_begin(); | |
| 558 | + rid = content_put_ex(pTicket, 0, 0, 0, needMod); | |
| 552 | 559 | if( rid==0 ){ |
| 553 | 560 | fossil_fatal("trouble committing ticket: %s", g.zErrMsg); |
| 554 | 561 | } |
| 555 | 562 | if( needMod ){ |
| 556 | 563 | moderation_table_create(); |
| @@ -560,11 +567,10 @@ | ||
| 560 | 567 | ); |
| 561 | 568 | }else{ |
| 562 | 569 | db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d);", rid); |
| 563 | 570 | db_multi_exec("INSERT OR IGNORE INTO unclustered VALUES(%d);", rid); |
| 564 | 571 | } |
| 565 | - manifest_crosslink_begin(); | |
| 566 | 572 | result = (manifest_crosslink(rid, pTicket, MC_NONE)==0); |
| 567 | 573 | assert( blob_is_reset(pTicket) ); |
| 568 | 574 | if( !result ){ |
| 569 | 575 | result = manifest_crosslink_end(MC_PERMIT_HOOKS); |
| 570 | 576 | }else{ |
| @@ -1386,11 +1392,11 @@ | ||
| 1386 | 1392 | blob_appendf(&tktchng, "K %s\n", zTktUuid); |
| 1387 | 1393 | blob_appendf(&tktchng, "U %F\n", zUser); |
| 1388 | 1394 | md5sum_blob(&tktchng, &cksum); |
| 1389 | 1395 | blob_appendf(&tktchng, "Z %b\n", &cksum); |
| 1390 | 1396 | if( ticket_put(&tktchng, zTktUuid, ticket_need_moderation(1)) ){ |
| 1391 | - fossil_fatal("%s\n", g.zErrMsg); | |
| 1397 | + fossil_fatal("%s", g.zErrMsg); | |
| 1392 | 1398 | }else{ |
| 1393 | 1399 | fossil_print("ticket %s succeeded for %s\n", |
| 1394 | 1400 | (eCmd==set?"set":"add"),zTktUuid); |
| 1395 | 1401 | } |
| 1396 | 1402 | } |
| 1397 | 1403 |
| --- src/tkt.c | |
| +++ src/tkt.c | |
| @@ -216,20 +216,25 @@ | |
| 216 | const char *zBaseName = zName[0]=='+' ? zName+1 : zName; |
| 217 | j = fieldId(zBaseName); |
| 218 | if( j<0 ) continue; |
| 219 | aUsed[j] = 1; |
| 220 | if( aField[j].mUsed & USEDBY_TICKET ){ |
| 221 | if( zName[0]=='+' ){ |
| 222 | zName++; |
| 223 | blob_append_sql(&sql1,", \"%w\"=coalesce(\"%w\",'') || %Q", |
| 224 | zName, zName, p->aField[i].zValue); |
| 225 | }else{ |
| 226 | blob_append_sql(&sql1,", \"%w\"=%Q", zName, p->aField[i].zValue); |
| 227 | } |
| 228 | } |
| 229 | if( aField[j].mUsed & USEDBY_TICKETCHNG ){ |
| 230 | blob_append_sql(&sql2, ",\"%w\"", zName); |
| 231 | blob_append_sql(&sql3, ",%Q", p->aField[i].zValue); |
| 232 | } |
| 233 | if( rid>0 ){ |
| 234 | wiki_extract_links(p->aField[i].zValue, rid, 1, p->rDate, i==0, 0); |
| 235 | } |
| @@ -546,11 +551,13 @@ | |
| 546 | Blob *pTicket, /* The text of the ticket change record */ |
| 547 | const char *zTktId, /* The ticket to which this change is applied */ |
| 548 | int needMod /* True if moderation is needed */ |
| 549 | ){ |
| 550 | int result; |
| 551 | int rid = content_put_ex(pTicket, 0, 0, 0, needMod); |
| 552 | if( rid==0 ){ |
| 553 | fossil_fatal("trouble committing ticket: %s", g.zErrMsg); |
| 554 | } |
| 555 | if( needMod ){ |
| 556 | moderation_table_create(); |
| @@ -560,11 +567,10 @@ | |
| 560 | ); |
| 561 | }else{ |
| 562 | db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d);", rid); |
| 563 | db_multi_exec("INSERT OR IGNORE INTO unclustered VALUES(%d);", rid); |
| 564 | } |
| 565 | manifest_crosslink_begin(); |
| 566 | result = (manifest_crosslink(rid, pTicket, MC_NONE)==0); |
| 567 | assert( blob_is_reset(pTicket) ); |
| 568 | if( !result ){ |
| 569 | result = manifest_crosslink_end(MC_PERMIT_HOOKS); |
| 570 | }else{ |
| @@ -1386,11 +1392,11 @@ | |
| 1386 | blob_appendf(&tktchng, "K %s\n", zTktUuid); |
| 1387 | blob_appendf(&tktchng, "U %F\n", zUser); |
| 1388 | md5sum_blob(&tktchng, &cksum); |
| 1389 | blob_appendf(&tktchng, "Z %b\n", &cksum); |
| 1390 | if( ticket_put(&tktchng, zTktUuid, ticket_need_moderation(1)) ){ |
| 1391 | fossil_fatal("%s\n", g.zErrMsg); |
| 1392 | }else{ |
| 1393 | fossil_print("ticket %s succeeded for %s\n", |
| 1394 | (eCmd==set?"set":"add"),zTktUuid); |
| 1395 | } |
| 1396 | } |
| 1397 |
| --- src/tkt.c | |
| +++ src/tkt.c | |
| @@ -216,20 +216,25 @@ | |
| 216 | const char *zBaseName = zName[0]=='+' ? zName+1 : zName; |
| 217 | j = fieldId(zBaseName); |
| 218 | if( j<0 ) continue; |
| 219 | aUsed[j] = 1; |
| 220 | if( aField[j].mUsed & USEDBY_TICKET ){ |
| 221 | const char *zUsedByName = zName; |
| 222 | if( zUsedByName[0]=='+' ){ |
| 223 | zUsedByName++; |
| 224 | blob_append_sql(&sql1,", \"%w\"=coalesce(\"%w\",'') || %Q", |
| 225 | zUsedByName, zUsedByName, p->aField[i].zValue); |
| 226 | }else{ |
| 227 | blob_append_sql(&sql1,", \"%w\"=%Q", zUsedByName, p->aField[i].zValue); |
| 228 | } |
| 229 | } |
| 230 | if( aField[j].mUsed & USEDBY_TICKETCHNG ){ |
| 231 | const char *zUsedByName = zName; |
| 232 | if( zUsedByName[0]=='+' ){ |
| 233 | zUsedByName++; |
| 234 | } |
| 235 | blob_append_sql(&sql2, ",\"%w\"", zUsedByName); |
| 236 | blob_append_sql(&sql3, ",%Q", p->aField[i].zValue); |
| 237 | } |
| 238 | if( rid>0 ){ |
| 239 | wiki_extract_links(p->aField[i].zValue, rid, 1, p->rDate, i==0, 0); |
| 240 | } |
| @@ -546,11 +551,13 @@ | |
| 551 | Blob *pTicket, /* The text of the ticket change record */ |
| 552 | const char *zTktId, /* The ticket to which this change is applied */ |
| 553 | int needMod /* True if moderation is needed */ |
| 554 | ){ |
| 555 | int result; |
| 556 | int rid; |
| 557 | manifest_crosslink_begin(); |
| 558 | rid = content_put_ex(pTicket, 0, 0, 0, needMod); |
| 559 | if( rid==0 ){ |
| 560 | fossil_fatal("trouble committing ticket: %s", g.zErrMsg); |
| 561 | } |
| 562 | if( needMod ){ |
| 563 | moderation_table_create(); |
| @@ -560,11 +567,10 @@ | |
| 567 | ); |
| 568 | }else{ |
| 569 | db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d);", rid); |
| 570 | db_multi_exec("INSERT OR IGNORE INTO unclustered VALUES(%d);", rid); |
| 571 | } |
| 572 | result = (manifest_crosslink(rid, pTicket, MC_NONE)==0); |
| 573 | assert( blob_is_reset(pTicket) ); |
| 574 | if( !result ){ |
| 575 | result = manifest_crosslink_end(MC_PERMIT_HOOKS); |
| 576 | }else{ |
| @@ -1386,11 +1392,11 @@ | |
| 1392 | blob_appendf(&tktchng, "K %s\n", zTktUuid); |
| 1393 | blob_appendf(&tktchng, "U %F\n", zUser); |
| 1394 | md5sum_blob(&tktchng, &cksum); |
| 1395 | blob_appendf(&tktchng, "Z %b\n", &cksum); |
| 1396 | if( ticket_put(&tktchng, zTktUuid, ticket_need_moderation(1)) ){ |
| 1397 | fossil_fatal("%s", g.zErrMsg); |
| 1398 | }else{ |
| 1399 | fossil_print("ticket %s succeeded for %s\n", |
| 1400 | (eCmd==set?"set":"add"),zTktUuid); |
| 1401 | } |
| 1402 | } |
| 1403 |
+3
-2
| --- src/undo.c | ||
| +++ src/undo.c | ||
| @@ -477,14 +477,15 @@ | ||
| 477 | 477 | if( undo_available==0 ){ |
| 478 | 478 | fossil_print("No undo or redo is available\n"); |
| 479 | 479 | }else{ |
| 480 | 480 | Stmt q; |
| 481 | 481 | int nChng = 0; |
| 482 | + const char *zArticle = undo_available==1 ? "An" : "A"; | |
| 482 | 483 | zCmd = undo_available==1 ? "undo" : "redo"; |
| 483 | - fossil_print("A %s is available for the following command:\n\n" | |
| 484 | + fossil_print("%s %s is available for the following command:\n\n" | |
| 484 | 485 | " %s %s\n\n", |
| 485 | - zCmd, g.argv[0], db_lget("undo_cmdline", "???")); | |
| 486 | + zArticle, zCmd, g.argv[0], db_lget("undo_cmdline", "???")); | |
| 486 | 487 | db_prepare(&q, |
| 487 | 488 | "SELECT existsflag, pathname FROM undo ORDER BY pathname" |
| 488 | 489 | ); |
| 489 | 490 | while( db_step(&q)==SQLITE_ROW ){ |
| 490 | 491 | if( nChng==0 ){ |
| 491 | 492 |
| --- src/undo.c | |
| +++ src/undo.c | |
| @@ -477,14 +477,15 @@ | |
| 477 | if( undo_available==0 ){ |
| 478 | fossil_print("No undo or redo is available\n"); |
| 479 | }else{ |
| 480 | Stmt q; |
| 481 | int nChng = 0; |
| 482 | zCmd = undo_available==1 ? "undo" : "redo"; |
| 483 | fossil_print("A %s is available for the following command:\n\n" |
| 484 | " %s %s\n\n", |
| 485 | zCmd, g.argv[0], db_lget("undo_cmdline", "???")); |
| 486 | db_prepare(&q, |
| 487 | "SELECT existsflag, pathname FROM undo ORDER BY pathname" |
| 488 | ); |
| 489 | while( db_step(&q)==SQLITE_ROW ){ |
| 490 | if( nChng==0 ){ |
| 491 |
| --- src/undo.c | |
| +++ src/undo.c | |
| @@ -477,14 +477,15 @@ | |
| 477 | if( undo_available==0 ){ |
| 478 | fossil_print("No undo or redo is available\n"); |
| 479 | }else{ |
| 480 | Stmt q; |
| 481 | int nChng = 0; |
| 482 | const char *zArticle = undo_available==1 ? "An" : "A"; |
| 483 | zCmd = undo_available==1 ? "undo" : "redo"; |
| 484 | fossil_print("%s %s is available for the following command:\n\n" |
| 485 | " %s %s\n\n", |
| 486 | zArticle, zCmd, g.argv[0], db_lget("undo_cmdline", "???")); |
| 487 | db_prepare(&q, |
| 488 | "SELECT existsflag, pathname FROM undo ORDER BY pathname" |
| 489 | ); |
| 490 | while( db_step(&q)==SQLITE_ROW ){ |
| 491 | if( nChng==0 ){ |
| 492 |
+37
-12
| --- src/unversioned.c | ||
| +++ src/unversioned.c | ||
| @@ -190,13 +190,26 @@ | ||
| 190 | 190 | } |
| 191 | 191 | return syncFlags; |
| 192 | 192 | } |
| 193 | 193 | |
| 194 | 194 | /* |
| 195 | +** Return true if the zName contains any whitespace | |
| 196 | +*/ | |
| 197 | +static int contains_whitespace(const char *zName){ | |
| 198 | + while( zName[0] ){ | |
| 199 | + if( fossil_isspace(zName[0]) ) return 1; | |
| 200 | + zName++; | |
| 201 | + } | |
| 202 | + return 0; | |
| 203 | +} | |
| 204 | + | |
| 205 | +/* | |
| 206 | +** COMMAND: uv* | |
| 195 | 207 | ** COMMAND: unversioned |
| 196 | 208 | ** |
| 197 | 209 | ** Usage: %fossil unversioned SUBCOMMAND ARGS... |
| 210 | +** or: %fossil uv SUBCOMMAND ARGS.. | |
| 198 | 211 | ** |
| 199 | 212 | ** Unversioned files (UV-files) are artifacts that are synced and are available |
| 200 | 213 | ** for download but which do not preserve history. Only the most recent version |
| 201 | 214 | ** of each UV-file is retained. Changes to an UV-file are permanent and cannot |
| 202 | 215 | ** be undone, so use appropriate caution with this command. |
| @@ -214,35 +227,40 @@ | ||
| 214 | 227 | ** |
| 215 | 228 | ** edit FILE Bring up FILE in a text editor for modification. |
| 216 | 229 | ** |
| 217 | 230 | ** export FILE OUTPUT Write the content of FILE into OUTPUT on disk |
| 218 | 231 | ** |
| 219 | -** list | ls Show all unversioned files held in the local repository. | |
| 232 | +** list | ls Show all unversioned files held in the local | |
| 233 | +** repository. | |
| 220 | 234 | ** |
| 221 | -** revert ?URL? Restore the state of all unversioned files in the local | |
| 222 | -** repository to match the remote repository URL. | |
| 235 | +** revert ?URL? Restore the state of all unversioned files in the | |
| 236 | +** local repository to match the remote repository | |
| 237 | +** URL. | |
| 238 | +** | |
| 223 | 239 | ** Options: |
| 224 | 240 | ** -v|--verbose Extra diagnostic output |
| 225 | 241 | ** -n|--dryrun Show what would have happened |
| 226 | 242 | ** |
| 227 | -** rm FILE ... Remove an unversioned files from the local repository. | |
| 243 | +** remove | rm FILE ... Remove unversioned files from the local repository. | |
| 228 | 244 | ** Changes are not pushed to other repositories until |
| 229 | -** the next sync. | |
| 245 | +** the next sync. | |
| 230 | 246 | ** |
| 231 | 247 | ** sync ?URL? Synchronize the state of all unversioned files with |
| 232 | -** the remote repository URL. The most recent version of | |
| 233 | -** each file is propagate to all repositories and all | |
| 234 | -** prior versions are permanently forgotten. | |
| 248 | +** the remote repository URL. The most recent version | |
| 249 | +** of each file is propagate to all repositories and | |
| 250 | +** all prior versions are permanently forgotten. | |
| 251 | +** | |
| 235 | 252 | ** Options: |
| 236 | 253 | ** -v|--verbose Extra diagnostic output |
| 237 | 254 | ** -n|--dryrun Show what would have happened |
| 238 | 255 | ** |
| 239 | 256 | ** touch FILE ... Update the TIMESTAMP on all of the listed files |
| 240 | 257 | ** |
| 241 | 258 | ** Options: |
| 242 | 259 | ** |
| 243 | -** --mtime TIMESTAMP Use TIMESTAMP instead of "now" for "add" and "rm". | |
| 260 | +** --mtime TIMESTAMP Use TIMESTAMP instead of "now" for the "add", | |
| 261 | +** "edit", "remove", and "touch" subcommands. | |
| 244 | 262 | */ |
| 245 | 263 | void unversioned_cmd(void){ |
| 246 | 264 | const char *zCmd; |
| 247 | 265 | int nCmd; |
| 248 | 266 | const char *zMtime = find_option("mtime", 0, 1); |
| @@ -271,10 +289,13 @@ | ||
| 271 | 289 | for(i=3; i<g.argc; i++){ |
| 272 | 290 | zIn = zAs ? zAs : g.argv[i]; |
| 273 | 291 | if( zIn[0]==0 || zIn[0]=='/' || !file_is_simple_pathname(zIn,1) ){ |
| 274 | 292 | fossil_fatal("'%Q' is not an acceptable filename", zIn); |
| 275 | 293 | } |
| 294 | + if( contains_whitespace(zIn) ){ | |
| 295 | + fossil_fatal("names of unversioned files may not contain whitespace"); | |
| 296 | + } | |
| 276 | 297 | blob_init(&file,0,0); |
| 277 | 298 | blob_read_from_file(&file, g.argv[i]); |
| 278 | 299 | unversioned_write(zIn, &file, mtime); |
| 279 | 300 | blob_reset(&file); |
| 280 | 301 | } |
| @@ -389,11 +410,11 @@ | ||
| 389 | 410 | }else if( memcmp(zCmd, "revert", nCmd)==0 ){ |
| 390 | 411 | unsigned syncFlags = unversioned_sync_flags(SYNC_UNVERSIONED|SYNC_UV_REVERT); |
| 391 | 412 | g.argv[1] = "sync"; |
| 392 | 413 | g.argv[2] = "--uv-noop"; |
| 393 | 414 | sync_unversioned(syncFlags); |
| 394 | - }else if( memcmp(zCmd, "rm", nCmd)==0 ){ | |
| 415 | + }else if( memcmp(zCmd, "remove", nCmd)==0 || memcmp(zCmd, "rm", nCmd)==0 ){ | |
| 395 | 416 | int i; |
| 396 | 417 | verify_all_options(); |
| 397 | 418 | db_begin_transaction(); |
| 398 | 419 | for(i=3; i<g.argc; i++){ |
| 399 | 420 | db_multi_exec( |
| @@ -420,11 +441,11 @@ | ||
| 420 | 441 | ); |
| 421 | 442 | } |
| 422 | 443 | db_unset("uv-hash", 0); |
| 423 | 444 | db_end_transaction(0); |
| 424 | 445 | }else{ |
| 425 | - usage("add|cat|edit|export|ls|revert|rm|sync|touch"); | |
| 446 | + usage("add|cat|edit|export|list|revert|remove|sync|touch"); | |
| 426 | 447 | } |
| 427 | 448 | } |
| 428 | 449 | |
| 429 | 450 | /* |
| 430 | 451 | ** WEBPAGE: uvlist |
| @@ -431,18 +452,20 @@ | ||
| 431 | 452 | ** |
| 432 | 453 | ** Display a list of all unversioned files in the repository. |
| 433 | 454 | ** Query parameters: |
| 434 | 455 | ** |
| 435 | 456 | ** byage=1 Order the initial display be decreasing age |
| 457 | +** showdel=0 Show deleted files | |
| 436 | 458 | */ |
| 437 | 459 | void uvstat_page(void){ |
| 438 | 460 | Stmt q; |
| 439 | 461 | sqlite3_int64 iNow; |
| 440 | 462 | sqlite3_int64 iTotalSz = 0; |
| 441 | 463 | int cnt = 0; |
| 442 | 464 | int n = 0; |
| 443 | 465 | const char *zOrderBy = "name"; |
| 466 | + int showDel = 0; | |
| 444 | 467 | char zSzName[100]; |
| 445 | 468 | |
| 446 | 469 | login_check_credentials(); |
| 447 | 470 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 448 | 471 | style_header("Unversioned Files"); |
| @@ -450,20 +473,22 @@ | ||
| 450 | 473 | @ No unversioned files on this server |
| 451 | 474 | style_footer(); |
| 452 | 475 | return; |
| 453 | 476 | } |
| 454 | 477 | if( PB("byage") ) zOrderBy = "mtime DESC"; |
| 478 | + if( PB("showdel") ) showDel = 1; | |
| 455 | 479 | db_prepare(&q, |
| 456 | 480 | "SELECT" |
| 457 | 481 | " name," |
| 458 | 482 | " mtime," |
| 459 | 483 | " hash," |
| 460 | 484 | " sz," |
| 461 | 485 | " (SELECT login FROM rcvfrom, user" |
| 462 | 486 | " WHERE user.uid=rcvfrom.uid AND rcvfrom.rcvid=unversioned.rcvid)," |
| 463 | 487 | " rcvid" |
| 464 | - " FROM unversioned ORDER BY %s", | |
| 488 | + " FROM unversioned %s ORDER BY %s", | |
| 489 | + showDel ? "" : "WHERE hash IS NOT NULL" /*safe-for-%s*/, | |
| 465 | 490 | zOrderBy/*safe-for-%s*/ |
| 466 | 491 | ); |
| 467 | 492 | iNow = db_int64(0, "SELECT strftime('%%s','now');"); |
| 468 | 493 | while( db_step(&q)==SQLITE_ROW ){ |
| 469 | 494 | const char *zName = db_column_text(&q, 0); |
| 470 | 495 |
| --- src/unversioned.c | |
| +++ src/unversioned.c | |
| @@ -190,13 +190,26 @@ | |
| 190 | } |
| 191 | return syncFlags; |
| 192 | } |
| 193 | |
| 194 | /* |
| 195 | ** COMMAND: unversioned |
| 196 | ** |
| 197 | ** Usage: %fossil unversioned SUBCOMMAND ARGS... |
| 198 | ** |
| 199 | ** Unversioned files (UV-files) are artifacts that are synced and are available |
| 200 | ** for download but which do not preserve history. Only the most recent version |
| 201 | ** of each UV-file is retained. Changes to an UV-file are permanent and cannot |
| 202 | ** be undone, so use appropriate caution with this command. |
| @@ -214,35 +227,40 @@ | |
| 214 | ** |
| 215 | ** edit FILE Bring up FILE in a text editor for modification. |
| 216 | ** |
| 217 | ** export FILE OUTPUT Write the content of FILE into OUTPUT on disk |
| 218 | ** |
| 219 | ** list | ls Show all unversioned files held in the local repository. |
| 220 | ** |
| 221 | ** revert ?URL? Restore the state of all unversioned files in the local |
| 222 | ** repository to match the remote repository URL. |
| 223 | ** Options: |
| 224 | ** -v|--verbose Extra diagnostic output |
| 225 | ** -n|--dryrun Show what would have happened |
| 226 | ** |
| 227 | ** rm FILE ... Remove an unversioned files from the local repository. |
| 228 | ** Changes are not pushed to other repositories until |
| 229 | ** the next sync. |
| 230 | ** |
| 231 | ** sync ?URL? Synchronize the state of all unversioned files with |
| 232 | ** the remote repository URL. The most recent version of |
| 233 | ** each file is propagate to all repositories and all |
| 234 | ** prior versions are permanently forgotten. |
| 235 | ** Options: |
| 236 | ** -v|--verbose Extra diagnostic output |
| 237 | ** -n|--dryrun Show what would have happened |
| 238 | ** |
| 239 | ** touch FILE ... Update the TIMESTAMP on all of the listed files |
| 240 | ** |
| 241 | ** Options: |
| 242 | ** |
| 243 | ** --mtime TIMESTAMP Use TIMESTAMP instead of "now" for "add" and "rm". |
| 244 | */ |
| 245 | void unversioned_cmd(void){ |
| 246 | const char *zCmd; |
| 247 | int nCmd; |
| 248 | const char *zMtime = find_option("mtime", 0, 1); |
| @@ -271,10 +289,13 @@ | |
| 271 | for(i=3; i<g.argc; i++){ |
| 272 | zIn = zAs ? zAs : g.argv[i]; |
| 273 | if( zIn[0]==0 || zIn[0]=='/' || !file_is_simple_pathname(zIn,1) ){ |
| 274 | fossil_fatal("'%Q' is not an acceptable filename", zIn); |
| 275 | } |
| 276 | blob_init(&file,0,0); |
| 277 | blob_read_from_file(&file, g.argv[i]); |
| 278 | unversioned_write(zIn, &file, mtime); |
| 279 | blob_reset(&file); |
| 280 | } |
| @@ -389,11 +410,11 @@ | |
| 389 | }else if( memcmp(zCmd, "revert", nCmd)==0 ){ |
| 390 | unsigned syncFlags = unversioned_sync_flags(SYNC_UNVERSIONED|SYNC_UV_REVERT); |
| 391 | g.argv[1] = "sync"; |
| 392 | g.argv[2] = "--uv-noop"; |
| 393 | sync_unversioned(syncFlags); |
| 394 | }else if( memcmp(zCmd, "rm", nCmd)==0 ){ |
| 395 | int i; |
| 396 | verify_all_options(); |
| 397 | db_begin_transaction(); |
| 398 | for(i=3; i<g.argc; i++){ |
| 399 | db_multi_exec( |
| @@ -420,11 +441,11 @@ | |
| 420 | ); |
| 421 | } |
| 422 | db_unset("uv-hash", 0); |
| 423 | db_end_transaction(0); |
| 424 | }else{ |
| 425 | usage("add|cat|edit|export|ls|revert|rm|sync|touch"); |
| 426 | } |
| 427 | } |
| 428 | |
| 429 | /* |
| 430 | ** WEBPAGE: uvlist |
| @@ -431,18 +452,20 @@ | |
| 431 | ** |
| 432 | ** Display a list of all unversioned files in the repository. |
| 433 | ** Query parameters: |
| 434 | ** |
| 435 | ** byage=1 Order the initial display be decreasing age |
| 436 | */ |
| 437 | void uvstat_page(void){ |
| 438 | Stmt q; |
| 439 | sqlite3_int64 iNow; |
| 440 | sqlite3_int64 iTotalSz = 0; |
| 441 | int cnt = 0; |
| 442 | int n = 0; |
| 443 | const char *zOrderBy = "name"; |
| 444 | char zSzName[100]; |
| 445 | |
| 446 | login_check_credentials(); |
| 447 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 448 | style_header("Unversioned Files"); |
| @@ -450,20 +473,22 @@ | |
| 450 | @ No unversioned files on this server |
| 451 | style_footer(); |
| 452 | return; |
| 453 | } |
| 454 | if( PB("byage") ) zOrderBy = "mtime DESC"; |
| 455 | db_prepare(&q, |
| 456 | "SELECT" |
| 457 | " name," |
| 458 | " mtime," |
| 459 | " hash," |
| 460 | " sz," |
| 461 | " (SELECT login FROM rcvfrom, user" |
| 462 | " WHERE user.uid=rcvfrom.uid AND rcvfrom.rcvid=unversioned.rcvid)," |
| 463 | " rcvid" |
| 464 | " FROM unversioned ORDER BY %s", |
| 465 | zOrderBy/*safe-for-%s*/ |
| 466 | ); |
| 467 | iNow = db_int64(0, "SELECT strftime('%%s','now');"); |
| 468 | while( db_step(&q)==SQLITE_ROW ){ |
| 469 | const char *zName = db_column_text(&q, 0); |
| 470 |
| --- src/unversioned.c | |
| +++ src/unversioned.c | |
| @@ -190,13 +190,26 @@ | |
| 190 | } |
| 191 | return syncFlags; |
| 192 | } |
| 193 | |
| 194 | /* |
| 195 | ** Return true if the zName contains any whitespace |
| 196 | */ |
| 197 | static int contains_whitespace(const char *zName){ |
| 198 | while( zName[0] ){ |
| 199 | if( fossil_isspace(zName[0]) ) return 1; |
| 200 | zName++; |
| 201 | } |
| 202 | return 0; |
| 203 | } |
| 204 | |
| 205 | /* |
| 206 | ** COMMAND: uv* |
| 207 | ** COMMAND: unversioned |
| 208 | ** |
| 209 | ** Usage: %fossil unversioned SUBCOMMAND ARGS... |
| 210 | ** or: %fossil uv SUBCOMMAND ARGS.. |
| 211 | ** |
| 212 | ** Unversioned files (UV-files) are artifacts that are synced and are available |
| 213 | ** for download but which do not preserve history. Only the most recent version |
| 214 | ** of each UV-file is retained. Changes to an UV-file are permanent and cannot |
| 215 | ** be undone, so use appropriate caution with this command. |
| @@ -214,35 +227,40 @@ | |
| 227 | ** |
| 228 | ** edit FILE Bring up FILE in a text editor for modification. |
| 229 | ** |
| 230 | ** export FILE OUTPUT Write the content of FILE into OUTPUT on disk |
| 231 | ** |
| 232 | ** list | ls Show all unversioned files held in the local |
| 233 | ** repository. |
| 234 | ** |
| 235 | ** revert ?URL? Restore the state of all unversioned files in the |
| 236 | ** local repository to match the remote repository |
| 237 | ** URL. |
| 238 | ** |
| 239 | ** Options: |
| 240 | ** -v|--verbose Extra diagnostic output |
| 241 | ** -n|--dryrun Show what would have happened |
| 242 | ** |
| 243 | ** remove | rm FILE ... Remove unversioned files from the local repository. |
| 244 | ** Changes are not pushed to other repositories until |
| 245 | ** the next sync. |
| 246 | ** |
| 247 | ** sync ?URL? Synchronize the state of all unversioned files with |
| 248 | ** the remote repository URL. The most recent version |
| 249 | ** of each file is propagate to all repositories and |
| 250 | ** all prior versions are permanently forgotten. |
| 251 | ** |
| 252 | ** Options: |
| 253 | ** -v|--verbose Extra diagnostic output |
| 254 | ** -n|--dryrun Show what would have happened |
| 255 | ** |
| 256 | ** touch FILE ... Update the TIMESTAMP on all of the listed files |
| 257 | ** |
| 258 | ** Options: |
| 259 | ** |
| 260 | ** --mtime TIMESTAMP Use TIMESTAMP instead of "now" for the "add", |
| 261 | ** "edit", "remove", and "touch" subcommands. |
| 262 | */ |
| 263 | void unversioned_cmd(void){ |
| 264 | const char *zCmd; |
| 265 | int nCmd; |
| 266 | const char *zMtime = find_option("mtime", 0, 1); |
| @@ -271,10 +289,13 @@ | |
| 289 | for(i=3; i<g.argc; i++){ |
| 290 | zIn = zAs ? zAs : g.argv[i]; |
| 291 | if( zIn[0]==0 || zIn[0]=='/' || !file_is_simple_pathname(zIn,1) ){ |
| 292 | fossil_fatal("'%Q' is not an acceptable filename", zIn); |
| 293 | } |
| 294 | if( contains_whitespace(zIn) ){ |
| 295 | fossil_fatal("names of unversioned files may not contain whitespace"); |
| 296 | } |
| 297 | blob_init(&file,0,0); |
| 298 | blob_read_from_file(&file, g.argv[i]); |
| 299 | unversioned_write(zIn, &file, mtime); |
| 300 | blob_reset(&file); |
| 301 | } |
| @@ -389,11 +410,11 @@ | |
| 410 | }else if( memcmp(zCmd, "revert", nCmd)==0 ){ |
| 411 | unsigned syncFlags = unversioned_sync_flags(SYNC_UNVERSIONED|SYNC_UV_REVERT); |
| 412 | g.argv[1] = "sync"; |
| 413 | g.argv[2] = "--uv-noop"; |
| 414 | sync_unversioned(syncFlags); |
| 415 | }else if( memcmp(zCmd, "remove", nCmd)==0 || memcmp(zCmd, "rm", nCmd)==0 ){ |
| 416 | int i; |
| 417 | verify_all_options(); |
| 418 | db_begin_transaction(); |
| 419 | for(i=3; i<g.argc; i++){ |
| 420 | db_multi_exec( |
| @@ -420,11 +441,11 @@ | |
| 441 | ); |
| 442 | } |
| 443 | db_unset("uv-hash", 0); |
| 444 | db_end_transaction(0); |
| 445 | }else{ |
| 446 | usage("add|cat|edit|export|list|revert|remove|sync|touch"); |
| 447 | } |
| 448 | } |
| 449 | |
| 450 | /* |
| 451 | ** WEBPAGE: uvlist |
| @@ -431,18 +452,20 @@ | |
| 452 | ** |
| 453 | ** Display a list of all unversioned files in the repository. |
| 454 | ** Query parameters: |
| 455 | ** |
| 456 | ** byage=1 Order the initial display be decreasing age |
| 457 | ** showdel=0 Show deleted files |
| 458 | */ |
| 459 | void uvstat_page(void){ |
| 460 | Stmt q; |
| 461 | sqlite3_int64 iNow; |
| 462 | sqlite3_int64 iTotalSz = 0; |
| 463 | int cnt = 0; |
| 464 | int n = 0; |
| 465 | const char *zOrderBy = "name"; |
| 466 | int showDel = 0; |
| 467 | char zSzName[100]; |
| 468 | |
| 469 | login_check_credentials(); |
| 470 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 471 | style_header("Unversioned Files"); |
| @@ -450,20 +473,22 @@ | |
| 473 | @ No unversioned files on this server |
| 474 | style_footer(); |
| 475 | return; |
| 476 | } |
| 477 | if( PB("byage") ) zOrderBy = "mtime DESC"; |
| 478 | if( PB("showdel") ) showDel = 1; |
| 479 | db_prepare(&q, |
| 480 | "SELECT" |
| 481 | " name," |
| 482 | " mtime," |
| 483 | " hash," |
| 484 | " sz," |
| 485 | " (SELECT login FROM rcvfrom, user" |
| 486 | " WHERE user.uid=rcvfrom.uid AND rcvfrom.rcvid=unversioned.rcvid)," |
| 487 | " rcvid" |
| 488 | " FROM unversioned %s ORDER BY %s", |
| 489 | showDel ? "" : "WHERE hash IS NOT NULL" /*safe-for-%s*/, |
| 490 | zOrderBy/*safe-for-%s*/ |
| 491 | ); |
| 492 | iNow = db_int64(0, "SELECT strftime('%%s','now');"); |
| 493 | while( db_step(&q)==SQLITE_ROW ){ |
| 494 | const char *zName = db_column_text(&q, 0); |
| 495 |
+48
-16
| --- src/user.c | ||
| +++ src/user.c | ||
| @@ -19,14 +19,10 @@ | ||
| 19 | 19 | ** querying information about users. |
| 20 | 20 | */ |
| 21 | 21 | #include "config.h" |
| 22 | 22 | #include "user.h" |
| 23 | 23 | |
| 24 | -#if defined(_WIN32) | |
| 25 | -#include <conio.h> | |
| 26 | -#endif | |
| 27 | - | |
| 28 | 24 | /* |
| 29 | 25 | ** Strip leading and trailing space from a string and add the string |
| 30 | 26 | ** onto the end of a blob. |
| 31 | 27 | */ |
| 32 | 28 | static void strip_string(Blob *pBlob, char *z){ |
| @@ -43,53 +39,74 @@ | ||
| 43 | 39 | } |
| 44 | 40 | blob_append(pBlob, z, -1); |
| 45 | 41 | } |
| 46 | 42 | |
| 47 | 43 | #if defined(_WIN32) || defined(__BIONIC__) |
| 48 | -#ifdef __MINGW32__ | |
| 44 | +#ifdef _WIN32 | |
| 49 | 45 | #include <conio.h> |
| 50 | 46 | #endif |
| 47 | + | |
| 51 | 48 | /* |
| 52 | -** getpass for Windows and Android | |
| 49 | +** getpass() for Windows and Android. | |
| 53 | 50 | */ |
| 51 | +static char *zPwdBuffer = 0; | |
| 52 | +static size_t nPwdBuffer = 0; | |
| 53 | + | |
| 54 | 54 | static char *getpass(const char *prompt){ |
| 55 | - static char pwd[64]; | |
| 55 | + char *zPwd; | |
| 56 | + size_t nPwd; | |
| 56 | 57 | size_t i; |
| 57 | 58 | |
| 59 | + if( zPwdBuffer==0 ){ | |
| 60 | + zPwdBuffer = fossil_secure_alloc_page(&nPwdBuffer); | |
| 61 | + assert( zPwdBuffer ); | |
| 62 | + }else{ | |
| 63 | + fossil_secure_zero(zPwdBuffer, nPwdBuffer); | |
| 64 | + } | |
| 65 | + zPwd = zPwdBuffer; | |
| 66 | + nPwd = nPwdBuffer; | |
| 58 | 67 | fputs(prompt,stderr); |
| 59 | 68 | fflush(stderr); |
| 60 | - for(i=0; i<sizeof(pwd)-1; ++i){ | |
| 69 | + assert( zPwd!=0 ); | |
| 70 | + assert( nPwd>0 ); | |
| 71 | + for(i=0; i<nPwd-1; ++i){ | |
| 61 | 72 | #if defined(_WIN32) |
| 62 | - pwd[i] = _getch(); | |
| 73 | + zPwd[i] = _getch(); | |
| 63 | 74 | #else |
| 64 | - pwd[i] = getc(stdin); | |
| 75 | + zPwd[i] = getc(stdin); | |
| 65 | 76 | #endif |
| 66 | - if(pwd[i]=='\r' || pwd[i]=='\n'){ | |
| 77 | + if(zPwd[i]=='\r' || zPwd[i]=='\n'){ | |
| 67 | 78 | break; |
| 68 | 79 | } |
| 69 | 80 | /* BS or DEL */ |
| 70 | - else if(i>0 && (pwd[i]==8 || pwd[i]==127)){ | |
| 81 | + else if(i>0 && (zPwd[i]==8 || zPwd[i]==127)){ | |
| 71 | 82 | i -= 2; |
| 72 | 83 | continue; |
| 73 | 84 | } |
| 74 | 85 | /* CTRL-C */ |
| 75 | - else if(pwd[i]==3) { | |
| 86 | + else if(zPwd[i]==3) { | |
| 76 | 87 | i=0; |
| 77 | 88 | break; |
| 78 | 89 | } |
| 79 | 90 | /* ESC */ |
| 80 | - else if(pwd[i]==27){ | |
| 91 | + else if(zPwd[i]==27){ | |
| 81 | 92 | i=0; |
| 82 | 93 | break; |
| 83 | 94 | } |
| 84 | 95 | else{ |
| 85 | 96 | fputc('*',stderr); |
| 86 | 97 | } |
| 87 | 98 | } |
| 88 | - pwd[i]='\0'; | |
| 99 | + zPwd[i]='\0'; | |
| 89 | 100 | fputs("\n", stderr); |
| 90 | - return pwd; | |
| 101 | + assert( zPwd==zPwdBuffer ); | |
| 102 | + return zPwd; | |
| 103 | +} | |
| 104 | +void freepass(){ | |
| 105 | + if( !zPwdBuffer ) return; | |
| 106 | + assert( nPwdBuffer>0 ); | |
| 107 | + fossil_secure_free_page(zPwdBuffer, nPwdBuffer); | |
| 91 | 108 | } |
| 92 | 109 | #endif |
| 93 | 110 | |
| 94 | 111 | #if defined(_WIN32) || defined(WIN32) |
| 95 | 112 | # include <io.h> |
| @@ -553,10 +570,25 @@ | ||
| 553 | 570 | db_multi_exec( |
| 554 | 571 | "UPDATE user SET pw=shared_secret(pw,login), mtime=now()" |
| 555 | 572 | " WHERE length(pw)>0 AND length(pw)!=40" |
| 556 | 573 | ); |
| 557 | 574 | } |
| 575 | + | |
| 576 | +/* | |
| 577 | +** COMMAND: test-prompt-user | |
| 578 | +** | |
| 579 | +** Usage: %fossil test-prompt-user PROMPT | |
| 580 | +** | |
| 581 | +** Prompts the user for input and then prints it verbatim (i.e. without | |
| 582 | +** a trailing line terminator). | |
| 583 | +*/ | |
| 584 | +void test_prompt_user_cmd(void){ | |
| 585 | + Blob answer; | |
| 586 | + if( g.argc!=3 ) usage("PROMPT"); | |
| 587 | + prompt_user(g.argv[2], &answer); | |
| 588 | + fossil_print("%s", blob_str(&answer)); | |
| 589 | +} | |
| 558 | 590 | |
| 559 | 591 | /* |
| 560 | 592 | ** WEBPAGE: access_log |
| 561 | 593 | ** |
| 562 | 594 | ** Show login attempts, including timestamp and IP address. |
| 563 | 595 |
| --- src/user.c | |
| +++ src/user.c | |
| @@ -19,14 +19,10 @@ | |
| 19 | ** querying information about users. |
| 20 | */ |
| 21 | #include "config.h" |
| 22 | #include "user.h" |
| 23 | |
| 24 | #if defined(_WIN32) |
| 25 | #include <conio.h> |
| 26 | #endif |
| 27 | |
| 28 | /* |
| 29 | ** Strip leading and trailing space from a string and add the string |
| 30 | ** onto the end of a blob. |
| 31 | */ |
| 32 | static void strip_string(Blob *pBlob, char *z){ |
| @@ -43,53 +39,74 @@ | |
| 43 | } |
| 44 | blob_append(pBlob, z, -1); |
| 45 | } |
| 46 | |
| 47 | #if defined(_WIN32) || defined(__BIONIC__) |
| 48 | #ifdef __MINGW32__ |
| 49 | #include <conio.h> |
| 50 | #endif |
| 51 | /* |
| 52 | ** getpass for Windows and Android |
| 53 | */ |
| 54 | static char *getpass(const char *prompt){ |
| 55 | static char pwd[64]; |
| 56 | size_t i; |
| 57 | |
| 58 | fputs(prompt,stderr); |
| 59 | fflush(stderr); |
| 60 | for(i=0; i<sizeof(pwd)-1; ++i){ |
| 61 | #if defined(_WIN32) |
| 62 | pwd[i] = _getch(); |
| 63 | #else |
| 64 | pwd[i] = getc(stdin); |
| 65 | #endif |
| 66 | if(pwd[i]=='\r' || pwd[i]=='\n'){ |
| 67 | break; |
| 68 | } |
| 69 | /* BS or DEL */ |
| 70 | else if(i>0 && (pwd[i]==8 || pwd[i]==127)){ |
| 71 | i -= 2; |
| 72 | continue; |
| 73 | } |
| 74 | /* CTRL-C */ |
| 75 | else if(pwd[i]==3) { |
| 76 | i=0; |
| 77 | break; |
| 78 | } |
| 79 | /* ESC */ |
| 80 | else if(pwd[i]==27){ |
| 81 | i=0; |
| 82 | break; |
| 83 | } |
| 84 | else{ |
| 85 | fputc('*',stderr); |
| 86 | } |
| 87 | } |
| 88 | pwd[i]='\0'; |
| 89 | fputs("\n", stderr); |
| 90 | return pwd; |
| 91 | } |
| 92 | #endif |
| 93 | |
| 94 | #if defined(_WIN32) || defined(WIN32) |
| 95 | # include <io.h> |
| @@ -553,10 +570,25 @@ | |
| 553 | db_multi_exec( |
| 554 | "UPDATE user SET pw=shared_secret(pw,login), mtime=now()" |
| 555 | " WHERE length(pw)>0 AND length(pw)!=40" |
| 556 | ); |
| 557 | } |
| 558 | |
| 559 | /* |
| 560 | ** WEBPAGE: access_log |
| 561 | ** |
| 562 | ** Show login attempts, including timestamp and IP address. |
| 563 |
| --- src/user.c | |
| +++ src/user.c | |
| @@ -19,14 +19,10 @@ | |
| 19 | ** querying information about users. |
| 20 | */ |
| 21 | #include "config.h" |
| 22 | #include "user.h" |
| 23 | |
| 24 | /* |
| 25 | ** Strip leading and trailing space from a string and add the string |
| 26 | ** onto the end of a blob. |
| 27 | */ |
| 28 | static void strip_string(Blob *pBlob, char *z){ |
| @@ -43,53 +39,74 @@ | |
| 39 | } |
| 40 | blob_append(pBlob, z, -1); |
| 41 | } |
| 42 | |
| 43 | #if defined(_WIN32) || defined(__BIONIC__) |
| 44 | #ifdef _WIN32 |
| 45 | #include <conio.h> |
| 46 | #endif |
| 47 | |
| 48 | /* |
| 49 | ** getpass() for Windows and Android. |
| 50 | */ |
| 51 | static char *zPwdBuffer = 0; |
| 52 | static size_t nPwdBuffer = 0; |
| 53 | |
| 54 | static char *getpass(const char *prompt){ |
| 55 | char *zPwd; |
| 56 | size_t nPwd; |
| 57 | size_t i; |
| 58 | |
| 59 | if( zPwdBuffer==0 ){ |
| 60 | zPwdBuffer = fossil_secure_alloc_page(&nPwdBuffer); |
| 61 | assert( zPwdBuffer ); |
| 62 | }else{ |
| 63 | fossil_secure_zero(zPwdBuffer, nPwdBuffer); |
| 64 | } |
| 65 | zPwd = zPwdBuffer; |
| 66 | nPwd = nPwdBuffer; |
| 67 | fputs(prompt,stderr); |
| 68 | fflush(stderr); |
| 69 | assert( zPwd!=0 ); |
| 70 | assert( nPwd>0 ); |
| 71 | for(i=0; i<nPwd-1; ++i){ |
| 72 | #if defined(_WIN32) |
| 73 | zPwd[i] = _getch(); |
| 74 | #else |
| 75 | zPwd[i] = getc(stdin); |
| 76 | #endif |
| 77 | if(zPwd[i]=='\r' || zPwd[i]=='\n'){ |
| 78 | break; |
| 79 | } |
| 80 | /* BS or DEL */ |
| 81 | else if(i>0 && (zPwd[i]==8 || zPwd[i]==127)){ |
| 82 | i -= 2; |
| 83 | continue; |
| 84 | } |
| 85 | /* CTRL-C */ |
| 86 | else if(zPwd[i]==3) { |
| 87 | i=0; |
| 88 | break; |
| 89 | } |
| 90 | /* ESC */ |
| 91 | else if(zPwd[i]==27){ |
| 92 | i=0; |
| 93 | break; |
| 94 | } |
| 95 | else{ |
| 96 | fputc('*',stderr); |
| 97 | } |
| 98 | } |
| 99 | zPwd[i]='\0'; |
| 100 | fputs("\n", stderr); |
| 101 | assert( zPwd==zPwdBuffer ); |
| 102 | return zPwd; |
| 103 | } |
| 104 | void freepass(){ |
| 105 | if( !zPwdBuffer ) return; |
| 106 | assert( nPwdBuffer>0 ); |
| 107 | fossil_secure_free_page(zPwdBuffer, nPwdBuffer); |
| 108 | } |
| 109 | #endif |
| 110 | |
| 111 | #if defined(_WIN32) || defined(WIN32) |
| 112 | # include <io.h> |
| @@ -553,10 +570,25 @@ | |
| 570 | db_multi_exec( |
| 571 | "UPDATE user SET pw=shared_secret(pw,login), mtime=now()" |
| 572 | " WHERE length(pw)>0 AND length(pw)!=40" |
| 573 | ); |
| 574 | } |
| 575 | |
| 576 | /* |
| 577 | ** COMMAND: test-prompt-user |
| 578 | ** |
| 579 | ** Usage: %fossil test-prompt-user PROMPT |
| 580 | ** |
| 581 | ** Prompts the user for input and then prints it verbatim (i.e. without |
| 582 | ** a trailing line terminator). |
| 583 | */ |
| 584 | void test_prompt_user_cmd(void){ |
| 585 | Blob answer; |
| 586 | if( g.argc!=3 ) usage("PROMPT"); |
| 587 | prompt_user(g.argv[2], &answer); |
| 588 | fossil_print("%s", blob_str(&answer)); |
| 589 | } |
| 590 | |
| 591 | /* |
| 592 | ** WEBPAGE: access_log |
| 593 | ** |
| 594 | ** Show login attempts, including timestamp and IP address. |
| 595 |
+1
-1
| --- src/utf8.c | ||
| +++ src/utf8.c | ||
| @@ -317,11 +317,11 @@ | ||
| 317 | 317 | wchar_t *zUnicode; /* Unicode version of zUtf8 */ |
| 318 | 318 | DWORD dummy; |
| 319 | 319 | Blob blob; |
| 320 | 320 | |
| 321 | 321 | static int istty[2] = { -1, -1 }; |
| 322 | - if( istty[toStdErr] == -1 ){ | |
| 322 | + if( istty[toStdErr]==-1 ){ | |
| 323 | 323 | istty[toStdErr] = _isatty(toStdErr + 1) != 0; |
| 324 | 324 | } |
| 325 | 325 | if( !istty[toStdErr] ){ |
| 326 | 326 | /* stdout/stderr is not a console. */ |
| 327 | 327 | return -1; |
| 328 | 328 |
| --- src/utf8.c | |
| +++ src/utf8.c | |
| @@ -317,11 +317,11 @@ | |
| 317 | wchar_t *zUnicode; /* Unicode version of zUtf8 */ |
| 318 | DWORD dummy; |
| 319 | Blob blob; |
| 320 | |
| 321 | static int istty[2] = { -1, -1 }; |
| 322 | if( istty[toStdErr] == -1 ){ |
| 323 | istty[toStdErr] = _isatty(toStdErr + 1) != 0; |
| 324 | } |
| 325 | if( !istty[toStdErr] ){ |
| 326 | /* stdout/stderr is not a console. */ |
| 327 | return -1; |
| 328 |
| --- src/utf8.c | |
| +++ src/utf8.c | |
| @@ -317,11 +317,11 @@ | |
| 317 | wchar_t *zUnicode; /* Unicode version of zUtf8 */ |
| 318 | DWORD dummy; |
| 319 | Blob blob; |
| 320 | |
| 321 | static int istty[2] = { -1, -1 }; |
| 322 | if( istty[toStdErr]==-1 ){ |
| 323 | istty[toStdErr] = _isatty(toStdErr + 1) != 0; |
| 324 | } |
| 325 | if( !istty[toStdErr] ){ |
| 326 | /* stdout/stderr is not a console. */ |
| 327 | return -1; |
| 328 |
+57
| --- src/util.c | ||
| +++ src/util.c | ||
| @@ -55,10 +55,67 @@ | ||
| 55 | 55 | } |
| 56 | 56 | void *fossil_realloc(void *p, size_t n){ |
| 57 | 57 | p = realloc(p, n); |
| 58 | 58 | if( p==0 ) fossil_panic("out of memory"); |
| 59 | 59 | return p; |
| 60 | +} | |
| 61 | +void fossil_secure_zero(void *p, size_t n){ | |
| 62 | + volatile unsigned char *vp = (volatile unsigned char *)p; | |
| 63 | + size_t i; | |
| 64 | + | |
| 65 | + if( p==0 ) return; | |
| 66 | + assert( n>0 ); | |
| 67 | + if( n==0 ) return; | |
| 68 | + for(i=0; i<n; i++){ vp[i] ^= 0xFF; } | |
| 69 | + for(i=0; i<n; i++){ vp[i] ^= vp[i]; } | |
| 70 | +} | |
| 71 | +void fossil_get_page_size(size_t *piPageSize){ | |
| 72 | +#if defined(_WIN32) | |
| 73 | + SYSTEM_INFO sysInfo; | |
| 74 | + memset(&sysInfo, 0, sizeof(SYSTEM_INFO)); | |
| 75 | + GetSystemInfo(&sysInfo); | |
| 76 | + *piPageSize = (size_t)sysInfo.dwPageSize; | |
| 77 | +#else | |
| 78 | + *piPageSize = 4096; /* FIXME: What for POSIX? */ | |
| 79 | +#endif | |
| 80 | +} | |
| 81 | +void *fossil_secure_alloc_page(size_t *pN){ | |
| 82 | + void *p; | |
| 83 | + size_t pageSize; | |
| 84 | + | |
| 85 | + fossil_get_page_size(&pageSize); | |
| 86 | + assert( pageSize>0 ); | |
| 87 | + assert( pageSize%2==0 ); | |
| 88 | +#if defined(_WIN32) | |
| 89 | + p = VirtualAlloc(NULL, pageSize, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE); | |
| 90 | + if( p==NULL ){ | |
| 91 | + fossil_fatal("VirtualAlloc failed: %lu\n", GetLastError()); | |
| 92 | + } | |
| 93 | + if( !VirtualLock(p, pageSize) ){ | |
| 94 | + fossil_fatal("VirtualLock failed: %lu\n", GetLastError()); | |
| 95 | + } | |
| 96 | +#else | |
| 97 | + p = fossil_malloc(pageSize); | |
| 98 | +#endif | |
| 99 | + fossil_secure_zero(p, pageSize); | |
| 100 | + if( pN ) *pN = pageSize; | |
| 101 | + return p; | |
| 102 | +} | |
| 103 | +void fossil_secure_free_page(void *p, size_t n){ | |
| 104 | + if( !p ) return; | |
| 105 | + assert( n>0 ); | |
| 106 | + fossil_secure_zero(p, n); | |
| 107 | +#if defined(_WIN32) | |
| 108 | + if( !VirtualUnlock(p, n) ){ | |
| 109 | + fossil_fatal("VirtualUnlock failed: %lu\n", GetLastError()); | |
| 110 | + } | |
| 111 | + if( !VirtualFree(p, 0, MEM_RELEASE) ){ | |
| 112 | + fossil_fatal("VirtualFree failed: %lu\n", GetLastError()); | |
| 113 | + } | |
| 114 | +#else | |
| 115 | + fossil_free(p); | |
| 116 | +#endif | |
| 60 | 117 | } |
| 61 | 118 | |
| 62 | 119 | /* |
| 63 | 120 | ** This function implements a cross-platform "system()" interface. |
| 64 | 121 | */ |
| 65 | 122 |
| --- src/util.c | |
| +++ src/util.c | |
| @@ -55,10 +55,67 @@ | |
| 55 | } |
| 56 | void *fossil_realloc(void *p, size_t n){ |
| 57 | p = realloc(p, n); |
| 58 | if( p==0 ) fossil_panic("out of memory"); |
| 59 | return p; |
| 60 | } |
| 61 | |
| 62 | /* |
| 63 | ** This function implements a cross-platform "system()" interface. |
| 64 | */ |
| 65 |
| --- src/util.c | |
| +++ src/util.c | |
| @@ -55,10 +55,67 @@ | |
| 55 | } |
| 56 | void *fossil_realloc(void *p, size_t n){ |
| 57 | p = realloc(p, n); |
| 58 | if( p==0 ) fossil_panic("out of memory"); |
| 59 | return p; |
| 60 | } |
| 61 | void fossil_secure_zero(void *p, size_t n){ |
| 62 | volatile unsigned char *vp = (volatile unsigned char *)p; |
| 63 | size_t i; |
| 64 | |
| 65 | if( p==0 ) return; |
| 66 | assert( n>0 ); |
| 67 | if( n==0 ) return; |
| 68 | for(i=0; i<n; i++){ vp[i] ^= 0xFF; } |
| 69 | for(i=0; i<n; i++){ vp[i] ^= vp[i]; } |
| 70 | } |
| 71 | void fossil_get_page_size(size_t *piPageSize){ |
| 72 | #if defined(_WIN32) |
| 73 | SYSTEM_INFO sysInfo; |
| 74 | memset(&sysInfo, 0, sizeof(SYSTEM_INFO)); |
| 75 | GetSystemInfo(&sysInfo); |
| 76 | *piPageSize = (size_t)sysInfo.dwPageSize; |
| 77 | #else |
| 78 | *piPageSize = 4096; /* FIXME: What for POSIX? */ |
| 79 | #endif |
| 80 | } |
| 81 | void *fossil_secure_alloc_page(size_t *pN){ |
| 82 | void *p; |
| 83 | size_t pageSize; |
| 84 | |
| 85 | fossil_get_page_size(&pageSize); |
| 86 | assert( pageSize>0 ); |
| 87 | assert( pageSize%2==0 ); |
| 88 | #if defined(_WIN32) |
| 89 | p = VirtualAlloc(NULL, pageSize, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE); |
| 90 | if( p==NULL ){ |
| 91 | fossil_fatal("VirtualAlloc failed: %lu\n", GetLastError()); |
| 92 | } |
| 93 | if( !VirtualLock(p, pageSize) ){ |
| 94 | fossil_fatal("VirtualLock failed: %lu\n", GetLastError()); |
| 95 | } |
| 96 | #else |
| 97 | p = fossil_malloc(pageSize); |
| 98 | #endif |
| 99 | fossil_secure_zero(p, pageSize); |
| 100 | if( pN ) *pN = pageSize; |
| 101 | return p; |
| 102 | } |
| 103 | void fossil_secure_free_page(void *p, size_t n){ |
| 104 | if( !p ) return; |
| 105 | assert( n>0 ); |
| 106 | fossil_secure_zero(p, n); |
| 107 | #if defined(_WIN32) |
| 108 | if( !VirtualUnlock(p, n) ){ |
| 109 | fossil_fatal("VirtualUnlock failed: %lu\n", GetLastError()); |
| 110 | } |
| 111 | if( !VirtualFree(p, 0, MEM_RELEASE) ){ |
| 112 | fossil_fatal("VirtualFree failed: %lu\n", GetLastError()); |
| 113 | } |
| 114 | #else |
| 115 | fossil_free(p); |
| 116 | #endif |
| 117 | } |
| 118 | |
| 119 | /* |
| 120 | ** This function implements a cross-platform "system()" interface. |
| 121 | */ |
| 122 |
+8
-8
| --- src/vfile.c | ||
| +++ src/vfile.c | ||
| @@ -264,19 +264,19 @@ | ||
| 264 | 264 | } |
| 265 | 265 | } |
| 266 | 266 | } |
| 267 | 267 | #ifndef _WIN32 |
| 268 | 268 | if( chnged==0 || chnged==6 || chnged==7 || chnged==8 || chnged==9 ){ |
| 269 | - if( origPerm == currentPerm ){ | |
| 269 | + if( origPerm==currentPerm ){ | |
| 270 | 270 | chnged = 0; |
| 271 | - }else if( currentPerm == PERM_EXE ){ | |
| 271 | + }else if( currentPerm==PERM_EXE ){ | |
| 272 | 272 | chnged = 6; |
| 273 | - }else if( currentPerm == PERM_LNK ){ | |
| 273 | + }else if( currentPerm==PERM_LNK ){ | |
| 274 | 274 | chnged = 7; |
| 275 | - }else if( origPerm == PERM_EXE ){ | |
| 275 | + }else if( origPerm==PERM_EXE ){ | |
| 276 | 276 | chnged = 8; |
| 277 | - }else if( origPerm == PERM_LNK ){ | |
| 277 | + }else if( origPerm==PERM_LNK ){ | |
| 278 | 278 | chnged = 9; |
| 279 | 279 | } |
| 280 | 280 | } |
| 281 | 281 | #endif |
| 282 | 282 | if( currentMtime!=oldMtime || chnged!=oldChnged ){ |
| @@ -348,13 +348,13 @@ | ||
| 348 | 348 | blob_reset(&content); |
| 349 | 349 | continue; |
| 350 | 350 | } |
| 351 | 351 | } |
| 352 | 352 | if( verbose ) fossil_print("%s\n", &zName[nRepos]); |
| 353 | - if( file_wd_isdir(zName) == 1 ){ | |
| 353 | + if( file_wd_isdir(zName)==1 ){ | |
| 354 | 354 | /*TODO(dchest): remove directories? */ |
| 355 | - fossil_fatal("%s is directory, cannot overwrite\n", zName); | |
| 355 | + fossil_fatal("%s is directory, cannot overwrite", zName); | |
| 356 | 356 | } |
| 357 | 357 | if( file_wd_size(zName)>=0 && (isLink || file_wd_islink(0)) ){ |
| 358 | 358 | file_delete(zName); |
| 359 | 359 | } |
| 360 | 360 | if( isLink ){ |
| @@ -918,11 +918,11 @@ | ||
| 918 | 918 | blob_zero(pManOut); |
| 919 | 919 | } |
| 920 | 920 | db_must_be_within_tree(); |
| 921 | 921 | pManifest = manifest_get(vid, CFTYPE_MANIFEST, &err); |
| 922 | 922 | if( pManifest==0 ){ |
| 923 | - fossil_fatal("manifest file (%d) is malformed:\n%s\n", | |
| 923 | + fossil_fatal("manifest file (%d) is malformed:\n%s", | |
| 924 | 924 | vid, blob_str(&err)); |
| 925 | 925 | } |
| 926 | 926 | manifest_file_rewind(pManifest); |
| 927 | 927 | while( (pFile = manifest_file_next(pManifest,0))!=0 ){ |
| 928 | 928 | if( pFile->zUuid==0 ) continue; |
| 929 | 929 |
| --- src/vfile.c | |
| +++ src/vfile.c | |
| @@ -264,19 +264,19 @@ | |
| 264 | } |
| 265 | } |
| 266 | } |
| 267 | #ifndef _WIN32 |
| 268 | if( chnged==0 || chnged==6 || chnged==7 || chnged==8 || chnged==9 ){ |
| 269 | if( origPerm == currentPerm ){ |
| 270 | chnged = 0; |
| 271 | }else if( currentPerm == PERM_EXE ){ |
| 272 | chnged = 6; |
| 273 | }else if( currentPerm == PERM_LNK ){ |
| 274 | chnged = 7; |
| 275 | }else if( origPerm == PERM_EXE ){ |
| 276 | chnged = 8; |
| 277 | }else if( origPerm == PERM_LNK ){ |
| 278 | chnged = 9; |
| 279 | } |
| 280 | } |
| 281 | #endif |
| 282 | if( currentMtime!=oldMtime || chnged!=oldChnged ){ |
| @@ -348,13 +348,13 @@ | |
| 348 | blob_reset(&content); |
| 349 | continue; |
| 350 | } |
| 351 | } |
| 352 | if( verbose ) fossil_print("%s\n", &zName[nRepos]); |
| 353 | if( file_wd_isdir(zName) == 1 ){ |
| 354 | /*TODO(dchest): remove directories? */ |
| 355 | fossil_fatal("%s is directory, cannot overwrite\n", zName); |
| 356 | } |
| 357 | if( file_wd_size(zName)>=0 && (isLink || file_wd_islink(0)) ){ |
| 358 | file_delete(zName); |
| 359 | } |
| 360 | if( isLink ){ |
| @@ -918,11 +918,11 @@ | |
| 918 | blob_zero(pManOut); |
| 919 | } |
| 920 | db_must_be_within_tree(); |
| 921 | pManifest = manifest_get(vid, CFTYPE_MANIFEST, &err); |
| 922 | if( pManifest==0 ){ |
| 923 | fossil_fatal("manifest file (%d) is malformed:\n%s\n", |
| 924 | vid, blob_str(&err)); |
| 925 | } |
| 926 | manifest_file_rewind(pManifest); |
| 927 | while( (pFile = manifest_file_next(pManifest,0))!=0 ){ |
| 928 | if( pFile->zUuid==0 ) continue; |
| 929 |
| --- src/vfile.c | |
| +++ src/vfile.c | |
| @@ -264,19 +264,19 @@ | |
| 264 | } |
| 265 | } |
| 266 | } |
| 267 | #ifndef _WIN32 |
| 268 | if( chnged==0 || chnged==6 || chnged==7 || chnged==8 || chnged==9 ){ |
| 269 | if( origPerm==currentPerm ){ |
| 270 | chnged = 0; |
| 271 | }else if( currentPerm==PERM_EXE ){ |
| 272 | chnged = 6; |
| 273 | }else if( currentPerm==PERM_LNK ){ |
| 274 | chnged = 7; |
| 275 | }else if( origPerm==PERM_EXE ){ |
| 276 | chnged = 8; |
| 277 | }else if( origPerm==PERM_LNK ){ |
| 278 | chnged = 9; |
| 279 | } |
| 280 | } |
| 281 | #endif |
| 282 | if( currentMtime!=oldMtime || chnged!=oldChnged ){ |
| @@ -348,13 +348,13 @@ | |
| 348 | blob_reset(&content); |
| 349 | continue; |
| 350 | } |
| 351 | } |
| 352 | if( verbose ) fossil_print("%s\n", &zName[nRepos]); |
| 353 | if( file_wd_isdir(zName)==1 ){ |
| 354 | /*TODO(dchest): remove directories? */ |
| 355 | fossil_fatal("%s is directory, cannot overwrite", zName); |
| 356 | } |
| 357 | if( file_wd_size(zName)>=0 && (isLink || file_wd_islink(0)) ){ |
| 358 | file_delete(zName); |
| 359 | } |
| 360 | if( isLink ){ |
| @@ -918,11 +918,11 @@ | |
| 918 | blob_zero(pManOut); |
| 919 | } |
| 920 | db_must_be_within_tree(); |
| 921 | pManifest = manifest_get(vid, CFTYPE_MANIFEST, &err); |
| 922 | if( pManifest==0 ){ |
| 923 | fossil_fatal("manifest file (%d) is malformed:\n%s", |
| 924 | vid, blob_str(&err)); |
| 925 | } |
| 926 | manifest_file_rewind(pManifest); |
| 927 | while( (pFile = manifest_file_next(pManifest,0))!=0 ){ |
| 928 | if( pFile->zUuid==0 ) continue; |
| 929 |
+105
-17
| --- src/winhttp.c | ||
| +++ src/winhttp.c | ||
| @@ -24,10 +24,24 @@ | ||
| 24 | 24 | /* This code is for win32 only */ |
| 25 | 25 | #include <windows.h> |
| 26 | 26 | #include <process.h> |
| 27 | 27 | #include "winhttp.h" |
| 28 | 28 | |
| 29 | +/* | |
| 30 | +** The HttpServer structure holds information about an instance of | |
| 31 | +** the HTTP server itself. | |
| 32 | +*/ | |
| 33 | +typedef struct HttpServer HttpServer; | |
| 34 | +struct HttpServer { | |
| 35 | + HANDLE hStoppedEvent; /* Event to signal when server is stopped, | |
| 36 | + ** must be closed by callee. */ | |
| 37 | + char *zStopper; /* The stopper file name, must be freed by | |
| 38 | + ** callee. */ | |
| 39 | + SOCKET listener; /* Socket on which the server is listening, | |
| 40 | + ** may be closed by callee. */ | |
| 41 | +}; | |
| 42 | + | |
| 29 | 43 | /* |
| 30 | 44 | ** The HttpRequest structure holds information about each incoming |
| 31 | 45 | ** HTTP request. |
| 32 | 46 | */ |
| 33 | 47 | typedef struct HttpRequest HttpRequest; |
| @@ -70,10 +84,51 @@ | ||
| 70 | 84 | const char *zService, |
| 71 | 85 | const char *zErr |
| 72 | 86 | ){ |
| 73 | 87 | fossil_fatal("unable to %s service '%s': %s", zOp, zService, zErr); |
| 74 | 88 | } |
| 89 | + | |
| 90 | +/* | |
| 91 | +** Make sure the server stops as soon as possible after the stopper file | |
| 92 | +** is found. If there is no stopper file name, do nothing. | |
| 93 | +*/ | |
| 94 | +static void win32_server_stopper(void *pAppData){ | |
| 95 | + HttpServer *p = (HttpServer*)pAppData; | |
| 96 | + if( p!=0 ){ | |
| 97 | + HANDLE hStoppedEvent = p->hStoppedEvent; | |
| 98 | + const char *zStopper = p->zStopper; | |
| 99 | + SOCKET listener = p->listener; | |
| 100 | + if( hStoppedEvent!=NULL && zStopper!=0 && listener!=INVALID_SOCKET ){ | |
| 101 | + while( 1 ){ | |
| 102 | + DWORD dwResult = WaitForMultipleObjectsEx(1, &hStoppedEvent, FALSE, | |
| 103 | + 1000, TRUE); | |
| 104 | + if( dwResult!=WAIT_IO_COMPLETION && dwResult!=WAIT_TIMEOUT ){ | |
| 105 | + /* The event is either invalid, signaled, or abandoned. Bail | |
| 106 | + ** out now because those conditions should indicate the parent | |
| 107 | + ** thread is dead or dying. */ | |
| 108 | + break; | |
| 109 | + } | |
| 110 | + if( file_size(zStopper)>=0 ){ | |
| 111 | + /* The stopper file has been found. Attempt to close the server | |
| 112 | + ** listener socket now and then exit. */ | |
| 113 | + closesocket(listener); | |
| 114 | + p->listener = INVALID_SOCKET; | |
| 115 | + break; | |
| 116 | + } | |
| 117 | + } | |
| 118 | + } | |
| 119 | + if( hStoppedEvent!=NULL ){ | |
| 120 | + CloseHandle(hStoppedEvent); | |
| 121 | + p->hStoppedEvent = NULL; | |
| 122 | + } | |
| 123 | + if( zStopper!=0 ){ | |
| 124 | + fossil_free(p->zStopper); | |
| 125 | + p->zStopper = 0; | |
| 126 | + } | |
| 127 | + fossil_free(p); | |
| 128 | + } | |
| 129 | +} | |
| 75 | 130 | |
| 76 | 131 | /* |
| 77 | 132 | ** Process a single incoming HTTP request. |
| 78 | 133 | */ |
| 79 | 134 | static void win32_http_request(void *pAppData){ |
| @@ -163,11 +218,11 @@ | ||
| 163 | 218 | if( in ) fclose(in); |
| 164 | 219 | closesocket(p->s); |
| 165 | 220 | file_delete(zRequestFName); |
| 166 | 221 | file_delete(zReplyFName); |
| 167 | 222 | file_delete(zCmdFName); |
| 168 | - free(p); | |
| 223 | + fossil_free(p); | |
| 169 | 224 | } |
| 170 | 225 | |
| 171 | 226 | /* |
| 172 | 227 | ** Process a single incoming SCGI request. |
| 173 | 228 | */ |
| @@ -225,11 +280,11 @@ | ||
| 225 | 280 | if( out ) fclose(out); |
| 226 | 281 | if( in ) fclose(in); |
| 227 | 282 | closesocket(p->s); |
| 228 | 283 | file_delete(zRequestFName); |
| 229 | 284 | file_delete(zReplyFName); |
| 230 | - free(p); | |
| 285 | + fossil_free(p); | |
| 231 | 286 | } |
| 232 | 287 | |
| 233 | 288 | |
| 234 | 289 | /* |
| 235 | 290 | ** Start a listening socket and process incoming HTTP requests on |
| @@ -243,19 +298,23 @@ | ||
| 243 | 298 | const char *zNotFound, /* The --notfound option, or NULL */ |
| 244 | 299 | const char *zFileGlob, /* The --fileglob option, or NULL */ |
| 245 | 300 | const char *zIpAddr, /* Bind to this IP address, if not NULL */ |
| 246 | 301 | int flags /* One or more HTTP_SERVER_ flags */ |
| 247 | 302 | ){ |
| 303 | + HANDLE hStoppedEvent; | |
| 248 | 304 | WSADATA wd; |
| 249 | 305 | SOCKET s = INVALID_SOCKET; |
| 250 | 306 | SOCKADDR_IN addr; |
| 251 | 307 | int idCnt = 0; |
| 252 | 308 | int iPort = mnPort; |
| 253 | 309 | Blob options; |
| 254 | 310 | wchar_t zTmpPath[MAX_PATH]; |
| 311 | +#if USE_SEE | |
| 312 | + const char *zSavedKey = 0; | |
| 313 | + size_t savedKeySize = 0; | |
| 314 | +#endif | |
| 255 | 315 | |
| 256 | - if( zStopper ) file_delete(zStopper); | |
| 257 | 316 | blob_zero(&options); |
| 258 | 317 | if( zBaseUrl ){ |
| 259 | 318 | blob_appendf(&options, " --baseurl %s", zBaseUrl); |
| 260 | 319 | } |
| 261 | 320 | if( zNotFound ){ |
| @@ -271,10 +330,18 @@ | ||
| 271 | 330 | blob_appendf(&options, " --th-trace"); |
| 272 | 331 | } |
| 273 | 332 | if( flags & HTTP_SERVER_REPOLIST ){ |
| 274 | 333 | blob_appendf(&options, " --repolist"); |
| 275 | 334 | } |
| 335 | +#if USE_SEE | |
| 336 | + zSavedKey = db_get_saved_encryption_key(); | |
| 337 | + savedKeySize = db_get_saved_encryption_key_size(); | |
| 338 | + if( zSavedKey!=0 && savedKeySize>0 ){ | |
| 339 | + blob_appendf(&options, " --usepidkey %lu:%p:%u", GetCurrentProcessId(), | |
| 340 | + zSavedKey, savedKeySize); | |
| 341 | + } | |
| 342 | +#endif | |
| 276 | 343 | if( WSAStartup(MAKEWORD(1,1), &wd) ){ |
| 277 | 344 | fossil_fatal("unable to initialize winsock"); |
| 278 | 345 | } |
| 279 | 346 | while( iPort<=mxPort ){ |
| 280 | 347 | s = socket(AF_INET, SOCK_STREAM, 0); |
| @@ -324,17 +391,35 @@ | ||
| 324 | 391 | zBrowser = mprintf(zBrowser /*works-like:"%d"*/, iPort); |
| 325 | 392 | fossil_print("Launch webbrowser: %s\n", zBrowser); |
| 326 | 393 | fossil_system(zBrowser); |
| 327 | 394 | } |
| 328 | 395 | fossil_print("Type Ctrl-C to stop the HTTP server\n"); |
| 396 | + /* Create an event used to signal when this server is exiting. */ | |
| 397 | + hStoppedEvent = CreateEvent(NULL, TRUE, FALSE, NULL); | |
| 398 | + assert( hStoppedEvent!=NULL ); | |
| 399 | + /* If there is a stopper file name, start the dedicated thread now. | |
| 400 | + ** It will attempt to close the listener socket within 1 second of | |
| 401 | + ** the stopper file being created. */ | |
| 402 | + if( zStopper ){ | |
| 403 | + HttpServer *pServer = fossil_malloc(sizeof(HttpServer)); | |
| 404 | + memset(pServer, 0, sizeof(HttpServer)); | |
| 405 | + DuplicateHandle(GetCurrentProcess(), hStoppedEvent, | |
| 406 | + GetCurrentProcess(), &pServer->hStoppedEvent, | |
| 407 | + 0, FALSE, DUPLICATE_SAME_ACCESS); | |
| 408 | + assert( pServer->hStoppedEvent!=NULL ); | |
| 409 | + pServer->zStopper = fossil_strdup(zStopper); | |
| 410 | + pServer->listener = s; | |
| 411 | + file_delete(zStopper); | |
| 412 | + _beginthread(win32_server_stopper, 0, (void*)pServer); | |
| 413 | + } | |
| 329 | 414 | /* Set the service status to running and pass the listener socket to the |
| 330 | 415 | ** service handling procedures. */ |
| 331 | 416 | win32_http_service_running(s); |
| 332 | 417 | for(;;){ |
| 333 | 418 | SOCKET client; |
| 334 | 419 | SOCKADDR_IN client_addr; |
| 335 | - HttpRequest *p; | |
| 420 | + HttpRequest *pRequest; | |
| 336 | 421 | int len = sizeof(client_addr); |
| 337 | 422 | int wsaError; |
| 338 | 423 | |
| 339 | 424 | client = accept(s, (struct sockaddr*)&client_addr, &len); |
| 340 | 425 | if( client==INVALID_SOCKET ){ |
| @@ -347,27 +432,27 @@ | ||
| 347 | 432 | }else{ |
| 348 | 433 | closesocket(s); |
| 349 | 434 | WSACleanup(); |
| 350 | 435 | fossil_fatal("error from accept()"); |
| 351 | 436 | } |
| 352 | - }else if( zStopper && file_size(zStopper)>=0 ){ | |
| 353 | - break; | |
| 354 | - } | |
| 355 | - p = fossil_malloc( sizeof(*p) ); | |
| 356 | - p->id = ++idCnt; | |
| 357 | - p->s = client; | |
| 358 | - p->addr = client_addr; | |
| 359 | - p->flags = flags; | |
| 360 | - p->zOptions = blob_str(&options); | |
| 437 | + } | |
| 438 | + pRequest = fossil_malloc(sizeof(HttpRequest)); | |
| 439 | + pRequest->id = ++idCnt; | |
| 440 | + pRequest->s = client; | |
| 441 | + pRequest->addr = client_addr; | |
| 442 | + pRequest->flags = flags; | |
| 443 | + pRequest->zOptions = blob_str(&options); | |
| 361 | 444 | if( flags & HTTP_SERVER_SCGI ){ |
| 362 | - _beginthread(win32_scgi_request, 0, (void*)p); | |
| 445 | + _beginthread(win32_scgi_request, 0, (void*)pRequest); | |
| 363 | 446 | }else{ |
| 364 | - _beginthread(win32_http_request, 0, (void*)p); | |
| 447 | + _beginthread(win32_http_request, 0, (void*)pRequest); | |
| 365 | 448 | } |
| 366 | 449 | } |
| 367 | 450 | closesocket(s); |
| 368 | 451 | WSACleanup(); |
| 452 | + SetEvent(hStoppedEvent); | |
| 453 | + CloseHandle(hStoppedEvent); | |
| 369 | 454 | } |
| 370 | 455 | |
| 371 | 456 | /* |
| 372 | 457 | ** The HttpService structure is used to pass information to the service main |
| 373 | 458 | ** function and to the service control handler function. |
| @@ -581,11 +666,13 @@ | ||
| 581 | 666 | } |
| 582 | 667 | } |
| 583 | 668 | return 0; |
| 584 | 669 | } |
| 585 | 670 | |
| 586 | -/* dupe ifdef needed for mkindex | |
| 671 | +/* Dupliate #ifdef needed for mkindex */ | |
| 672 | +#ifdef _WIN32 | |
| 673 | +/* | |
| 587 | 674 | ** COMMAND: winsrv* |
| 588 | 675 | ** |
| 589 | 676 | ** Usage: %fossil winsrv METHOD ?SERVICE-NAME? ?OPTIONS? |
| 590 | 677 | ** |
| 591 | 678 | ** Where METHOD is one of: create delete show start stop. |
| @@ -1030,6 +1117,7 @@ | ||
| 1030 | 1117 | fossil_fatal("METHOD should be one of:" |
| 1031 | 1118 | " create delete show start stop"); |
| 1032 | 1119 | } |
| 1033 | 1120 | return; |
| 1034 | 1121 | } |
| 1035 | -#endif /* _WIN32 -- This code is for win32 only */ | |
| 1122 | +#endif /* _WIN32 -- dupe needed for mkindex */ | |
| 1123 | +#endif /* _WIN32 -- This code is for win32 only */ | |
| 1036 | 1124 |
| --- src/winhttp.c | |
| +++ src/winhttp.c | |
| @@ -24,10 +24,24 @@ | |
| 24 | /* This code is for win32 only */ |
| 25 | #include <windows.h> |
| 26 | #include <process.h> |
| 27 | #include "winhttp.h" |
| 28 | |
| 29 | /* |
| 30 | ** The HttpRequest structure holds information about each incoming |
| 31 | ** HTTP request. |
| 32 | */ |
| 33 | typedef struct HttpRequest HttpRequest; |
| @@ -70,10 +84,51 @@ | |
| 70 | const char *zService, |
| 71 | const char *zErr |
| 72 | ){ |
| 73 | fossil_fatal("unable to %s service '%s': %s", zOp, zService, zErr); |
| 74 | } |
| 75 | |
| 76 | /* |
| 77 | ** Process a single incoming HTTP request. |
| 78 | */ |
| 79 | static void win32_http_request(void *pAppData){ |
| @@ -163,11 +218,11 @@ | |
| 163 | if( in ) fclose(in); |
| 164 | closesocket(p->s); |
| 165 | file_delete(zRequestFName); |
| 166 | file_delete(zReplyFName); |
| 167 | file_delete(zCmdFName); |
| 168 | free(p); |
| 169 | } |
| 170 | |
| 171 | /* |
| 172 | ** Process a single incoming SCGI request. |
| 173 | */ |
| @@ -225,11 +280,11 @@ | |
| 225 | if( out ) fclose(out); |
| 226 | if( in ) fclose(in); |
| 227 | closesocket(p->s); |
| 228 | file_delete(zRequestFName); |
| 229 | file_delete(zReplyFName); |
| 230 | free(p); |
| 231 | } |
| 232 | |
| 233 | |
| 234 | /* |
| 235 | ** Start a listening socket and process incoming HTTP requests on |
| @@ -243,19 +298,23 @@ | |
| 243 | const char *zNotFound, /* The --notfound option, or NULL */ |
| 244 | const char *zFileGlob, /* The --fileglob option, or NULL */ |
| 245 | const char *zIpAddr, /* Bind to this IP address, if not NULL */ |
| 246 | int flags /* One or more HTTP_SERVER_ flags */ |
| 247 | ){ |
| 248 | WSADATA wd; |
| 249 | SOCKET s = INVALID_SOCKET; |
| 250 | SOCKADDR_IN addr; |
| 251 | int idCnt = 0; |
| 252 | int iPort = mnPort; |
| 253 | Blob options; |
| 254 | wchar_t zTmpPath[MAX_PATH]; |
| 255 | |
| 256 | if( zStopper ) file_delete(zStopper); |
| 257 | blob_zero(&options); |
| 258 | if( zBaseUrl ){ |
| 259 | blob_appendf(&options, " --baseurl %s", zBaseUrl); |
| 260 | } |
| 261 | if( zNotFound ){ |
| @@ -271,10 +330,18 @@ | |
| 271 | blob_appendf(&options, " --th-trace"); |
| 272 | } |
| 273 | if( flags & HTTP_SERVER_REPOLIST ){ |
| 274 | blob_appendf(&options, " --repolist"); |
| 275 | } |
| 276 | if( WSAStartup(MAKEWORD(1,1), &wd) ){ |
| 277 | fossil_fatal("unable to initialize winsock"); |
| 278 | } |
| 279 | while( iPort<=mxPort ){ |
| 280 | s = socket(AF_INET, SOCK_STREAM, 0); |
| @@ -324,17 +391,35 @@ | |
| 324 | zBrowser = mprintf(zBrowser /*works-like:"%d"*/, iPort); |
| 325 | fossil_print("Launch webbrowser: %s\n", zBrowser); |
| 326 | fossil_system(zBrowser); |
| 327 | } |
| 328 | fossil_print("Type Ctrl-C to stop the HTTP server\n"); |
| 329 | /* Set the service status to running and pass the listener socket to the |
| 330 | ** service handling procedures. */ |
| 331 | win32_http_service_running(s); |
| 332 | for(;;){ |
| 333 | SOCKET client; |
| 334 | SOCKADDR_IN client_addr; |
| 335 | HttpRequest *p; |
| 336 | int len = sizeof(client_addr); |
| 337 | int wsaError; |
| 338 | |
| 339 | client = accept(s, (struct sockaddr*)&client_addr, &len); |
| 340 | if( client==INVALID_SOCKET ){ |
| @@ -347,27 +432,27 @@ | |
| 347 | }else{ |
| 348 | closesocket(s); |
| 349 | WSACleanup(); |
| 350 | fossil_fatal("error from accept()"); |
| 351 | } |
| 352 | }else if( zStopper && file_size(zStopper)>=0 ){ |
| 353 | break; |
| 354 | } |
| 355 | p = fossil_malloc( sizeof(*p) ); |
| 356 | p->id = ++idCnt; |
| 357 | p->s = client; |
| 358 | p->addr = client_addr; |
| 359 | p->flags = flags; |
| 360 | p->zOptions = blob_str(&options); |
| 361 | if( flags & HTTP_SERVER_SCGI ){ |
| 362 | _beginthread(win32_scgi_request, 0, (void*)p); |
| 363 | }else{ |
| 364 | _beginthread(win32_http_request, 0, (void*)p); |
| 365 | } |
| 366 | } |
| 367 | closesocket(s); |
| 368 | WSACleanup(); |
| 369 | } |
| 370 | |
| 371 | /* |
| 372 | ** The HttpService structure is used to pass information to the service main |
| 373 | ** function and to the service control handler function. |
| @@ -581,11 +666,13 @@ | |
| 581 | } |
| 582 | } |
| 583 | return 0; |
| 584 | } |
| 585 | |
| 586 | /* dupe ifdef needed for mkindex |
| 587 | ** COMMAND: winsrv* |
| 588 | ** |
| 589 | ** Usage: %fossil winsrv METHOD ?SERVICE-NAME? ?OPTIONS? |
| 590 | ** |
| 591 | ** Where METHOD is one of: create delete show start stop. |
| @@ -1030,6 +1117,7 @@ | |
| 1030 | fossil_fatal("METHOD should be one of:" |
| 1031 | " create delete show start stop"); |
| 1032 | } |
| 1033 | return; |
| 1034 | } |
| 1035 | #endif /* _WIN32 -- This code is for win32 only */ |
| 1036 |
| --- src/winhttp.c | |
| +++ src/winhttp.c | |
| @@ -24,10 +24,24 @@ | |
| 24 | /* This code is for win32 only */ |
| 25 | #include <windows.h> |
| 26 | #include <process.h> |
| 27 | #include "winhttp.h" |
| 28 | |
| 29 | /* |
| 30 | ** The HttpServer structure holds information about an instance of |
| 31 | ** the HTTP server itself. |
| 32 | */ |
| 33 | typedef struct HttpServer HttpServer; |
| 34 | struct HttpServer { |
| 35 | HANDLE hStoppedEvent; /* Event to signal when server is stopped, |
| 36 | ** must be closed by callee. */ |
| 37 | char *zStopper; /* The stopper file name, must be freed by |
| 38 | ** callee. */ |
| 39 | SOCKET listener; /* Socket on which the server is listening, |
| 40 | ** may be closed by callee. */ |
| 41 | }; |
| 42 | |
| 43 | /* |
| 44 | ** The HttpRequest structure holds information about each incoming |
| 45 | ** HTTP request. |
| 46 | */ |
| 47 | typedef struct HttpRequest HttpRequest; |
| @@ -70,10 +84,51 @@ | |
| 84 | const char *zService, |
| 85 | const char *zErr |
| 86 | ){ |
| 87 | fossil_fatal("unable to %s service '%s': %s", zOp, zService, zErr); |
| 88 | } |
| 89 | |
| 90 | /* |
| 91 | ** Make sure the server stops as soon as possible after the stopper file |
| 92 | ** is found. If there is no stopper file name, do nothing. |
| 93 | */ |
| 94 | static void win32_server_stopper(void *pAppData){ |
| 95 | HttpServer *p = (HttpServer*)pAppData; |
| 96 | if( p!=0 ){ |
| 97 | HANDLE hStoppedEvent = p->hStoppedEvent; |
| 98 | const char *zStopper = p->zStopper; |
| 99 | SOCKET listener = p->listener; |
| 100 | if( hStoppedEvent!=NULL && zStopper!=0 && listener!=INVALID_SOCKET ){ |
| 101 | while( 1 ){ |
| 102 | DWORD dwResult = WaitForMultipleObjectsEx(1, &hStoppedEvent, FALSE, |
| 103 | 1000, TRUE); |
| 104 | if( dwResult!=WAIT_IO_COMPLETION && dwResult!=WAIT_TIMEOUT ){ |
| 105 | /* The event is either invalid, signaled, or abandoned. Bail |
| 106 | ** out now because those conditions should indicate the parent |
| 107 | ** thread is dead or dying. */ |
| 108 | break; |
| 109 | } |
| 110 | if( file_size(zStopper)>=0 ){ |
| 111 | /* The stopper file has been found. Attempt to close the server |
| 112 | ** listener socket now and then exit. */ |
| 113 | closesocket(listener); |
| 114 | p->listener = INVALID_SOCKET; |
| 115 | break; |
| 116 | } |
| 117 | } |
| 118 | } |
| 119 | if( hStoppedEvent!=NULL ){ |
| 120 | CloseHandle(hStoppedEvent); |
| 121 | p->hStoppedEvent = NULL; |
| 122 | } |
| 123 | if( zStopper!=0 ){ |
| 124 | fossil_free(p->zStopper); |
| 125 | p->zStopper = 0; |
| 126 | } |
| 127 | fossil_free(p); |
| 128 | } |
| 129 | } |
| 130 | |
| 131 | /* |
| 132 | ** Process a single incoming HTTP request. |
| 133 | */ |
| 134 | static void win32_http_request(void *pAppData){ |
| @@ -163,11 +218,11 @@ | |
| 218 | if( in ) fclose(in); |
| 219 | closesocket(p->s); |
| 220 | file_delete(zRequestFName); |
| 221 | file_delete(zReplyFName); |
| 222 | file_delete(zCmdFName); |
| 223 | fossil_free(p); |
| 224 | } |
| 225 | |
| 226 | /* |
| 227 | ** Process a single incoming SCGI request. |
| 228 | */ |
| @@ -225,11 +280,11 @@ | |
| 280 | if( out ) fclose(out); |
| 281 | if( in ) fclose(in); |
| 282 | closesocket(p->s); |
| 283 | file_delete(zRequestFName); |
| 284 | file_delete(zReplyFName); |
| 285 | fossil_free(p); |
| 286 | } |
| 287 | |
| 288 | |
| 289 | /* |
| 290 | ** Start a listening socket and process incoming HTTP requests on |
| @@ -243,19 +298,23 @@ | |
| 298 | const char *zNotFound, /* The --notfound option, or NULL */ |
| 299 | const char *zFileGlob, /* The --fileglob option, or NULL */ |
| 300 | const char *zIpAddr, /* Bind to this IP address, if not NULL */ |
| 301 | int flags /* One or more HTTP_SERVER_ flags */ |
| 302 | ){ |
| 303 | HANDLE hStoppedEvent; |
| 304 | WSADATA wd; |
| 305 | SOCKET s = INVALID_SOCKET; |
| 306 | SOCKADDR_IN addr; |
| 307 | int idCnt = 0; |
| 308 | int iPort = mnPort; |
| 309 | Blob options; |
| 310 | wchar_t zTmpPath[MAX_PATH]; |
| 311 | #if USE_SEE |
| 312 | const char *zSavedKey = 0; |
| 313 | size_t savedKeySize = 0; |
| 314 | #endif |
| 315 | |
| 316 | blob_zero(&options); |
| 317 | if( zBaseUrl ){ |
| 318 | blob_appendf(&options, " --baseurl %s", zBaseUrl); |
| 319 | } |
| 320 | if( zNotFound ){ |
| @@ -271,10 +330,18 @@ | |
| 330 | blob_appendf(&options, " --th-trace"); |
| 331 | } |
| 332 | if( flags & HTTP_SERVER_REPOLIST ){ |
| 333 | blob_appendf(&options, " --repolist"); |
| 334 | } |
| 335 | #if USE_SEE |
| 336 | zSavedKey = db_get_saved_encryption_key(); |
| 337 | savedKeySize = db_get_saved_encryption_key_size(); |
| 338 | if( zSavedKey!=0 && savedKeySize>0 ){ |
| 339 | blob_appendf(&options, " --usepidkey %lu:%p:%u", GetCurrentProcessId(), |
| 340 | zSavedKey, savedKeySize); |
| 341 | } |
| 342 | #endif |
| 343 | if( WSAStartup(MAKEWORD(1,1), &wd) ){ |
| 344 | fossil_fatal("unable to initialize winsock"); |
| 345 | } |
| 346 | while( iPort<=mxPort ){ |
| 347 | s = socket(AF_INET, SOCK_STREAM, 0); |
| @@ -324,17 +391,35 @@ | |
| 391 | zBrowser = mprintf(zBrowser /*works-like:"%d"*/, iPort); |
| 392 | fossil_print("Launch webbrowser: %s\n", zBrowser); |
| 393 | fossil_system(zBrowser); |
| 394 | } |
| 395 | fossil_print("Type Ctrl-C to stop the HTTP server\n"); |
| 396 | /* Create an event used to signal when this server is exiting. */ |
| 397 | hStoppedEvent = CreateEvent(NULL, TRUE, FALSE, NULL); |
| 398 | assert( hStoppedEvent!=NULL ); |
| 399 | /* If there is a stopper file name, start the dedicated thread now. |
| 400 | ** It will attempt to close the listener socket within 1 second of |
| 401 | ** the stopper file being created. */ |
| 402 | if( zStopper ){ |
| 403 | HttpServer *pServer = fossil_malloc(sizeof(HttpServer)); |
| 404 | memset(pServer, 0, sizeof(HttpServer)); |
| 405 | DuplicateHandle(GetCurrentProcess(), hStoppedEvent, |
| 406 | GetCurrentProcess(), &pServer->hStoppedEvent, |
| 407 | 0, FALSE, DUPLICATE_SAME_ACCESS); |
| 408 | assert( pServer->hStoppedEvent!=NULL ); |
| 409 | pServer->zStopper = fossil_strdup(zStopper); |
| 410 | pServer->listener = s; |
| 411 | file_delete(zStopper); |
| 412 | _beginthread(win32_server_stopper, 0, (void*)pServer); |
| 413 | } |
| 414 | /* Set the service status to running and pass the listener socket to the |
| 415 | ** service handling procedures. */ |
| 416 | win32_http_service_running(s); |
| 417 | for(;;){ |
| 418 | SOCKET client; |
| 419 | SOCKADDR_IN client_addr; |
| 420 | HttpRequest *pRequest; |
| 421 | int len = sizeof(client_addr); |
| 422 | int wsaError; |
| 423 | |
| 424 | client = accept(s, (struct sockaddr*)&client_addr, &len); |
| 425 | if( client==INVALID_SOCKET ){ |
| @@ -347,27 +432,27 @@ | |
| 432 | }else{ |
| 433 | closesocket(s); |
| 434 | WSACleanup(); |
| 435 | fossil_fatal("error from accept()"); |
| 436 | } |
| 437 | } |
| 438 | pRequest = fossil_malloc(sizeof(HttpRequest)); |
| 439 | pRequest->id = ++idCnt; |
| 440 | pRequest->s = client; |
| 441 | pRequest->addr = client_addr; |
| 442 | pRequest->flags = flags; |
| 443 | pRequest->zOptions = blob_str(&options); |
| 444 | if( flags & HTTP_SERVER_SCGI ){ |
| 445 | _beginthread(win32_scgi_request, 0, (void*)pRequest); |
| 446 | }else{ |
| 447 | _beginthread(win32_http_request, 0, (void*)pRequest); |
| 448 | } |
| 449 | } |
| 450 | closesocket(s); |
| 451 | WSACleanup(); |
| 452 | SetEvent(hStoppedEvent); |
| 453 | CloseHandle(hStoppedEvent); |
| 454 | } |
| 455 | |
| 456 | /* |
| 457 | ** The HttpService structure is used to pass information to the service main |
| 458 | ** function and to the service control handler function. |
| @@ -581,11 +666,13 @@ | |
| 666 | } |
| 667 | } |
| 668 | return 0; |
| 669 | } |
| 670 | |
| 671 | /* Dupliate #ifdef needed for mkindex */ |
| 672 | #ifdef _WIN32 |
| 673 | /* |
| 674 | ** COMMAND: winsrv* |
| 675 | ** |
| 676 | ** Usage: %fossil winsrv METHOD ?SERVICE-NAME? ?OPTIONS? |
| 677 | ** |
| 678 | ** Where METHOD is one of: create delete show start stop. |
| @@ -1030,6 +1117,7 @@ | |
| 1117 | fossil_fatal("METHOD should be one of:" |
| 1118 | " create delete show start stop"); |
| 1119 | } |
| 1120 | return; |
| 1121 | } |
| 1122 | #endif /* _WIN32 -- dupe needed for mkindex */ |
| 1123 | #endif /* _WIN32 -- This code is for win32 only */ |
| 1124 |
+1
-1
| --- src/xfer.c | ||
| +++ src/xfer.c | ||
| @@ -2140,11 +2140,11 @@ | ||
| 2140 | 2140 | } |
| 2141 | 2141 | if( syncFlags & (SYNC_UV_TRACE|SYNC_UV_DRYRUN) ){ |
| 2142 | 2142 | const char *zMsg = 0; |
| 2143 | 2143 | switch( iStatus ){ |
| 2144 | 2144 | case 0: |
| 2145 | - case 1: zMsg = "UV-PULL"; break; | |
| 2145 | + case 1: zMsg = "UV-PULL"; break; | |
| 2146 | 2146 | case 2: zMsg = "UV-PULL-MTIME-ONLY"; break; |
| 2147 | 2147 | case 4: zMsg = "UV-PUSH-MTIME-ONLY"; break; |
| 2148 | 2148 | case 5: zMsg = "UV-PUSH"; break; |
| 2149 | 2149 | } |
| 2150 | 2150 | if( zMsg ) fossil_print("\r%s: %s\n", zMsg, zName); |
| 2151 | 2151 |
| --- src/xfer.c | |
| +++ src/xfer.c | |
| @@ -2140,11 +2140,11 @@ | |
| 2140 | } |
| 2141 | if( syncFlags & (SYNC_UV_TRACE|SYNC_UV_DRYRUN) ){ |
| 2142 | const char *zMsg = 0; |
| 2143 | switch( iStatus ){ |
| 2144 | case 0: |
| 2145 | case 1: zMsg = "UV-PULL"; break; |
| 2146 | case 2: zMsg = "UV-PULL-MTIME-ONLY"; break; |
| 2147 | case 4: zMsg = "UV-PUSH-MTIME-ONLY"; break; |
| 2148 | case 5: zMsg = "UV-PUSH"; break; |
| 2149 | } |
| 2150 | if( zMsg ) fossil_print("\r%s: %s\n", zMsg, zName); |
| 2151 |
| --- src/xfer.c | |
| +++ src/xfer.c | |
| @@ -2140,11 +2140,11 @@ | |
| 2140 | } |
| 2141 | if( syncFlags & (SYNC_UV_TRACE|SYNC_UV_DRYRUN) ){ |
| 2142 | const char *zMsg = 0; |
| 2143 | switch( iStatus ){ |
| 2144 | case 0: |
| 2145 | case 1: zMsg = "UV-PULL"; break; |
| 2146 | case 2: zMsg = "UV-PULL-MTIME-ONLY"; break; |
| 2147 | case 4: zMsg = "UV-PUSH-MTIME-ONLY"; break; |
| 2148 | case 5: zMsg = "UV-PUSH"; break; |
| 2149 | } |
| 2150 | if( zMsg ) fossil_print("\r%s: %s\n", zMsg, zName); |
| 2151 |
+55
-17
| --- src/zip.c | ||
| +++ src/zip.c | ||
| @@ -350,29 +350,67 @@ | ||
| 350 | 350 | } |
| 351 | 351 | nPrefix = blob_size(&filename); |
| 352 | 352 | |
| 353 | 353 | pManifest = manifest_get(rid, CFTYPE_MANIFEST, 0); |
| 354 | 354 | if( pManifest ){ |
| 355 | - char *zName; | |
| 355 | + int flg, eflg = 0; | |
| 356 | + char *zName = 0; | |
| 356 | 357 | zip_set_timedate(pManifest->rDate); |
| 357 | - if( (pInclude==0 || glob_match(pInclude, "manifest")) | |
| 358 | - && !glob_match(pExclude, "manifest") | |
| 359 | - && db_get_boolean("manifest", 0) | |
| 360 | - ){ | |
| 361 | - blob_append(&filename, "manifest", -1); | |
| 362 | - zName = blob_str(&filename); | |
| 363 | - zip_add_folders(zName); | |
| 364 | - sha1sum_blob(&mfile, &hash); | |
| 365 | - sterilize_manifest(&mfile); | |
| 366 | - zip_add_file(zName, &mfile, 0); | |
| 358 | + flg = db_get_manifest_setting(); | |
| 359 | + if( flg ){ | |
| 360 | + /* eflg is the effective flags, taking include/exclude into account */ | |
| 361 | + if( (pInclude==0 || glob_match(pInclude, "manifest")) | |
| 362 | + && !glob_match(pExclude, "manifest") | |
| 363 | + && (flg & MFESTFLG_RAW) ){ | |
| 364 | + eflg |= MFESTFLG_RAW; | |
| 365 | + } | |
| 366 | + if( (pInclude==0 || glob_match(pInclude, "manifest.uuid")) | |
| 367 | + && !glob_match(pExclude, "manifest.uuid") | |
| 368 | + && (flg & MFESTFLG_UUID) ){ | |
| 369 | + eflg |= MFESTFLG_UUID; | |
| 370 | + } | |
| 371 | + if( (pInclude==0 || glob_match(pInclude, "manifest.tags")) | |
| 372 | + && !glob_match(pExclude, "manifest.tags") | |
| 373 | + && (flg & MFESTFLG_TAGS) ){ | |
| 374 | + eflg |= MFESTFLG_TAGS; | |
| 375 | + } | |
| 376 | + | |
| 377 | + if( eflg & (MFESTFLG_RAW|MFESTFLG_UUID) ){ | |
| 378 | + if( eflg & MFESTFLG_RAW ){ | |
| 379 | + blob_append(&filename, "manifest", -1); | |
| 380 | + zName = blob_str(&filename); | |
| 381 | + zip_add_folders(zName); | |
| 382 | + } | |
| 383 | + if( eflg & MFESTFLG_UUID ){ | |
| 384 | + sha1sum_blob(&mfile, &hash); | |
| 385 | + } | |
| 386 | + if( eflg & MFESTFLG_RAW ){ | |
| 387 | + sterilize_manifest(&mfile); | |
| 388 | + zip_add_file(zName, &mfile, 0); | |
| 389 | + } | |
| 390 | + } | |
| 367 | 391 | blob_reset(&mfile); |
| 368 | - blob_append(&hash, "\n", 1); | |
| 369 | - blob_resize(&filename, nPrefix); | |
| 370 | - blob_append(&filename, "manifest.uuid", -1); | |
| 371 | - zName = blob_str(&filename); | |
| 372 | - zip_add_file(zName, &hash, 0); | |
| 373 | - blob_reset(&hash); | |
| 392 | + if( eflg & MFESTFLG_UUID ){ | |
| 393 | + blob_append(&hash, "\n", 1); | |
| 394 | + blob_resize(&filename, nPrefix); | |
| 395 | + blob_append(&filename, "manifest.uuid", -1); | |
| 396 | + zName = blob_str(&filename); | |
| 397 | + zip_add_folders(zName); | |
| 398 | + zip_add_file(zName, &hash, 0); | |
| 399 | + blob_reset(&hash); | |
| 400 | + } | |
| 401 | + if( eflg & MFESTFLG_TAGS ){ | |
| 402 | + Blob tagslist; | |
| 403 | + blob_zero(&tagslist); | |
| 404 | + get_checkin_taglist(rid, &tagslist); | |
| 405 | + blob_resize(&filename, nPrefix); | |
| 406 | + blob_append(&filename, "manifest.tags", -1); | |
| 407 | + zName = blob_str(&filename); | |
| 408 | + zip_add_folders(zName); | |
| 409 | + zip_add_file(zName, &tagslist, 0); | |
| 410 | + blob_reset(&tagslist); | |
| 411 | + } | |
| 374 | 412 | } |
| 375 | 413 | manifest_file_rewind(pManifest); |
| 376 | 414 | while( (pFile = manifest_file_next(pManifest,0))!=0 ){ |
| 377 | 415 | int fid; |
| 378 | 416 | if( pInclude!=0 && !glob_match(pInclude, pFile->zName) ) continue; |
| 379 | 417 |
| --- src/zip.c | |
| +++ src/zip.c | |
| @@ -350,29 +350,67 @@ | |
| 350 | } |
| 351 | nPrefix = blob_size(&filename); |
| 352 | |
| 353 | pManifest = manifest_get(rid, CFTYPE_MANIFEST, 0); |
| 354 | if( pManifest ){ |
| 355 | char *zName; |
| 356 | zip_set_timedate(pManifest->rDate); |
| 357 | if( (pInclude==0 || glob_match(pInclude, "manifest")) |
| 358 | && !glob_match(pExclude, "manifest") |
| 359 | && db_get_boolean("manifest", 0) |
| 360 | ){ |
| 361 | blob_append(&filename, "manifest", -1); |
| 362 | zName = blob_str(&filename); |
| 363 | zip_add_folders(zName); |
| 364 | sha1sum_blob(&mfile, &hash); |
| 365 | sterilize_manifest(&mfile); |
| 366 | zip_add_file(zName, &mfile, 0); |
| 367 | blob_reset(&mfile); |
| 368 | blob_append(&hash, "\n", 1); |
| 369 | blob_resize(&filename, nPrefix); |
| 370 | blob_append(&filename, "manifest.uuid", -1); |
| 371 | zName = blob_str(&filename); |
| 372 | zip_add_file(zName, &hash, 0); |
| 373 | blob_reset(&hash); |
| 374 | } |
| 375 | manifest_file_rewind(pManifest); |
| 376 | while( (pFile = manifest_file_next(pManifest,0))!=0 ){ |
| 377 | int fid; |
| 378 | if( pInclude!=0 && !glob_match(pInclude, pFile->zName) ) continue; |
| 379 |
| --- src/zip.c | |
| +++ src/zip.c | |
| @@ -350,29 +350,67 @@ | |
| 350 | } |
| 351 | nPrefix = blob_size(&filename); |
| 352 | |
| 353 | pManifest = manifest_get(rid, CFTYPE_MANIFEST, 0); |
| 354 | if( pManifest ){ |
| 355 | int flg, eflg = 0; |
| 356 | char *zName = 0; |
| 357 | zip_set_timedate(pManifest->rDate); |
| 358 | flg = db_get_manifest_setting(); |
| 359 | if( flg ){ |
| 360 | /* eflg is the effective flags, taking include/exclude into account */ |
| 361 | if( (pInclude==0 || glob_match(pInclude, "manifest")) |
| 362 | && !glob_match(pExclude, "manifest") |
| 363 | && (flg & MFESTFLG_RAW) ){ |
| 364 | eflg |= MFESTFLG_RAW; |
| 365 | } |
| 366 | if( (pInclude==0 || glob_match(pInclude, "manifest.uuid")) |
| 367 | && !glob_match(pExclude, "manifest.uuid") |
| 368 | && (flg & MFESTFLG_UUID) ){ |
| 369 | eflg |= MFESTFLG_UUID; |
| 370 | } |
| 371 | if( (pInclude==0 || glob_match(pInclude, "manifest.tags")) |
| 372 | && !glob_match(pExclude, "manifest.tags") |
| 373 | && (flg & MFESTFLG_TAGS) ){ |
| 374 | eflg |= MFESTFLG_TAGS; |
| 375 | } |
| 376 | |
| 377 | if( eflg & (MFESTFLG_RAW|MFESTFLG_UUID) ){ |
| 378 | if( eflg & MFESTFLG_RAW ){ |
| 379 | blob_append(&filename, "manifest", -1); |
| 380 | zName = blob_str(&filename); |
| 381 | zip_add_folders(zName); |
| 382 | } |
| 383 | if( eflg & MFESTFLG_UUID ){ |
| 384 | sha1sum_blob(&mfile, &hash); |
| 385 | } |
| 386 | if( eflg & MFESTFLG_RAW ){ |
| 387 | sterilize_manifest(&mfile); |
| 388 | zip_add_file(zName, &mfile, 0); |
| 389 | } |
| 390 | } |
| 391 | blob_reset(&mfile); |
| 392 | if( eflg & MFESTFLG_UUID ){ |
| 393 | blob_append(&hash, "\n", 1); |
| 394 | blob_resize(&filename, nPrefix); |
| 395 | blob_append(&filename, "manifest.uuid", -1); |
| 396 | zName = blob_str(&filename); |
| 397 | zip_add_folders(zName); |
| 398 | zip_add_file(zName, &hash, 0); |
| 399 | blob_reset(&hash); |
| 400 | } |
| 401 | if( eflg & MFESTFLG_TAGS ){ |
| 402 | Blob tagslist; |
| 403 | blob_zero(&tagslist); |
| 404 | get_checkin_taglist(rid, &tagslist); |
| 405 | blob_resize(&filename, nPrefix); |
| 406 | blob_append(&filename, "manifest.tags", -1); |
| 407 | zName = blob_str(&filename); |
| 408 | zip_add_folders(zName); |
| 409 | zip_add_file(zName, &tagslist, 0); |
| 410 | blob_reset(&tagslist); |
| 411 | } |
| 412 | } |
| 413 | manifest_file_rewind(pManifest); |
| 414 | while( (pFile = manifest_file_next(pManifest,0))!=0 ){ |
| 415 | int fid; |
| 416 | if( pInclude!=0 && !glob_match(pInclude, pFile->zName) ) continue; |
| 417 |
+12
-3
| --- test/delta1.test | ||
| +++ test/delta1.test | ||
| @@ -34,18 +34,27 @@ | ||
| 34 | 34 | set f1 [read_file $f] |
| 35 | 35 | write_file t1 $f1 |
| 36 | 36 | for {set i 0} {$i<100} {incr i} { |
| 37 | 37 | write_file t2 [random_changes $f1 1 1 0 0.1] |
| 38 | 38 | fossil test-delta t1 t2 |
| 39 | - test delta-$base-$i-1 {$RESULT=="ok"} | |
| 39 | + test delta-$base-$i-1 {[normalize_result]=="ok"} | |
| 40 | 40 | write_file t2 [random_changes $f1 1 1 0 0.2] |
| 41 | 41 | fossil test-delta t1 t2 |
| 42 | - test delta-$base-$i-2 {$RESULT=="ok"} | |
| 42 | + test delta-$base-$i-2 {[normalize_result]=="ok"} | |
| 43 | 43 | write_file t2 [random_changes $f1 1 1 0 0.4] |
| 44 | 44 | fossil test-delta t1 t2 |
| 45 | - test delta-$base-$i-3 {$RESULT=="ok"} | |
| 45 | + test delta-$base-$i-3 {[normalize_result]=="ok"} | |
| 46 | 46 | } |
| 47 | 47 | } |
| 48 | 48 | |
| 49 | +set empties { "" "" "" a a "" } | |
| 50 | +set i 0 | |
| 51 | +foreach {f1 f2} $empties { | |
| 52 | + incr i | |
| 53 | + write_file t1 $f1 | |
| 54 | + write_file t2 $f2 | |
| 55 | + fossil test-delta t1 t2 | |
| 56 | + test delta-empty-$i {[normalize_result]=="ok"} | |
| 57 | +} | |
| 49 | 58 | ############################################################################### |
| 50 | 59 | |
| 51 | 60 | test_cleanup |
| 52 | 61 | |
| 53 | 62 | ADDED test/diff.test |
| 54 | 63 | ADDED test/fake-editor.tcl |
| --- test/delta1.test | |
| +++ test/delta1.test | |
| @@ -34,18 +34,27 @@ | |
| 34 | set f1 [read_file $f] |
| 35 | write_file t1 $f1 |
| 36 | for {set i 0} {$i<100} {incr i} { |
| 37 | write_file t2 [random_changes $f1 1 1 0 0.1] |
| 38 | fossil test-delta t1 t2 |
| 39 | test delta-$base-$i-1 {$RESULT=="ok"} |
| 40 | write_file t2 [random_changes $f1 1 1 0 0.2] |
| 41 | fossil test-delta t1 t2 |
| 42 | test delta-$base-$i-2 {$RESULT=="ok"} |
| 43 | write_file t2 [random_changes $f1 1 1 0 0.4] |
| 44 | fossil test-delta t1 t2 |
| 45 | test delta-$base-$i-3 {$RESULT=="ok"} |
| 46 | } |
| 47 | } |
| 48 | |
| 49 | ############################################################################### |
| 50 | |
| 51 | test_cleanup |
| 52 | |
| 53 | DDED test/diff.test |
| 54 | DDED test/fake-editor.tcl |
| --- test/delta1.test | |
| +++ test/delta1.test | |
| @@ -34,18 +34,27 @@ | |
| 34 | set f1 [read_file $f] |
| 35 | write_file t1 $f1 |
| 36 | for {set i 0} {$i<100} {incr i} { |
| 37 | write_file t2 [random_changes $f1 1 1 0 0.1] |
| 38 | fossil test-delta t1 t2 |
| 39 | test delta-$base-$i-1 {[normalize_result]=="ok"} |
| 40 | write_file t2 [random_changes $f1 1 1 0 0.2] |
| 41 | fossil test-delta t1 t2 |
| 42 | test delta-$base-$i-2 {[normalize_result]=="ok"} |
| 43 | write_file t2 [random_changes $f1 1 1 0 0.4] |
| 44 | fossil test-delta t1 t2 |
| 45 | test delta-$base-$i-3 {[normalize_result]=="ok"} |
| 46 | } |
| 47 | } |
| 48 | |
| 49 | set empties { "" "" "" a a "" } |
| 50 | set i 0 |
| 51 | foreach {f1 f2} $empties { |
| 52 | incr i |
| 53 | write_file t1 $f1 |
| 54 | write_file t2 $f2 |
| 55 | fossil test-delta t1 t2 |
| 56 | test delta-empty-$i {[normalize_result]=="ok"} |
| 57 | } |
| 58 | ############################################################################### |
| 59 | |
| 60 | test_cleanup |
| 61 | |
| 62 | DDED test/diff.test |
| 63 | DDED test/fake-editor.tcl |
+31
| --- a/test/diff.test | ||
| +++ b/test/diff.test | ||
| @@ -0,0 +1,31 @@ | ||
| 1 | +16384]" | |
| 2 | +write_file file4_file file4.dat "test file 4 (l16384]\ntwo" | |
| 3 | +write_file f163842016 D. Richard Hipp | |
| 4 | +# | |
| 5 | +# This program is free software; you can redistribute it and/or | |
| 6 | +# modify it under the terms of the Simplified BSD License (also | |
| 7 | +# known as the "2-Clause License" or "FreeBSD License".) | |
| 8 | +# | |
| 9 | +# This program is distributed in the hope that it will be useful, | |
| 10 | +# but without any warranty; without even the implied warranty of | |
| 11 | +# merchantability or fitness for a particular purpose. | |
| 12 | +# | |
| 13 | +# Author contact information: | |
| 14 | +# [email protected] | |
| 15 | +# http://www.hwaci.com/drh/ | |
| 16 | +# | |
| 17 | +############################################################################ | |
| 18 | +# | |
| 19 | +# Tests for the diff command. | |
| 20 | +# | |
| 21 | + | |
| 22 | +require_no_open_checkout | |
| 23 | + | |
| 24 | +test_setup; set rootDir [file normalize [pwd]] | |
| 25 | + | |
| 26 | +################################### | |
| 27 | +# Tests of binary file det# | |
| 28 | +# Coite_file file1.dat z 32768] | |
| 29 | +fossil diff file1.dat | |
| 30 | + | |
| 31 | +test diff-file1-1 {[normalize_restest_cleanup |
| --- a/test/diff.test | |
| +++ b/test/diff.test | |
| @@ -0,0 +1,31 @@ | |
| --- a/test/diff.test | |
| +++ b/test/diff.test | |
| @@ -0,0 +1,31 @@ | |
| 1 | 16384]" |
| 2 | write_file file4_file file4.dat "test file 4 (l16384]\ntwo" |
| 3 | write_file f163842016 D. Richard Hipp |
| 4 | # |
| 5 | # This program is free software; you can redistribute it and/or |
| 6 | # modify it under the terms of the Simplified BSD License (also |
| 7 | # known as the "2-Clause License" or "FreeBSD License".) |
| 8 | # |
| 9 | # This program is distributed in the hope that it will be useful, |
| 10 | # but without any warranty; without even the implied warranty of |
| 11 | # merchantability or fitness for a particular purpose. |
| 12 | # |
| 13 | # Author contact information: |
| 14 | # [email protected] |
| 15 | # http://www.hwaci.com/drh/ |
| 16 | # |
| 17 | ############################################################################ |
| 18 | # |
| 19 | # Tests for the diff command. |
| 20 | # |
| 21 | |
| 22 | require_no_open_checkout |
| 23 | |
| 24 | test_setup; set rootDir [file normalize [pwd]] |
| 25 | |
| 26 | ################################### |
| 27 | # Tests of binary file det# |
| 28 | # Coite_file file1.dat z 32768] |
| 29 | fossil diff file1.dat |
| 30 | |
| 31 | test diff-file1-1 {[normalize_restest_cleanup |
+2
| --- a/test/fake-editor.tcl | ||
| +++ b/test/fake-editor.tcl | ||
| @@ -0,0 +1,2 @@ | ||
| 1 | +# | |
| 2 | +# Copyright ( |
| --- a/test/fake-editor.tcl | |
| +++ b/test/fake-editor.tcl | |
| @@ -0,0 +1,2 @@ | |
| --- a/test/fake-editor.tcl | |
| +++ b/test/fake-editor.tcl | |
| @@ -0,0 +1,2 @@ | |
| 1 | # |
| 2 | # Copyright ( |
| --- test/graph-test-1.wiki | ||
| +++ test/graph-test-1.wiki | ||
| @@ -66,10 +66,13 @@ | ||
| 66 | 66 | * <a href="../../../timeline?c=20015206bc" |
| 67 | 67 | target="testwindow"> |
| 68 | 68 | This timeline has a hidden commit.</a> Click Unhide to reveal. |
| 69 | 69 | * <a href="../../../timeline?y=ci&n=15&b=2a4e4cf03e" |
| 70 | 70 | target="testwindow">Isolated check-ins.</a> |
| 71 | + * <a href="../../../timeline?b=0fa60142&n=50" | |
| 72 | + target="testwindow">Single branch raiser from bottom of page | |
| 73 | + up to checkins 057e4b and d3cc6d</a> | |
| 71 | 74 | |
| 72 | 75 | External: |
| 73 | 76 | |
| 74 | 77 | * <a href="http://www.sqlite.org/src/timeline?c=2010-09-29&nd" |
| 75 | 78 | target="testwindow">Timewarp due to a mis-configured system clock.</a> |
| 76 | 79 |
| --- test/graph-test-1.wiki | |
| +++ test/graph-test-1.wiki | |
| @@ -66,10 +66,13 @@ | |
| 66 | * <a href="../../../timeline?c=20015206bc" |
| 67 | target="testwindow"> |
| 68 | This timeline has a hidden commit.</a> Click Unhide to reveal. |
| 69 | * <a href="../../../timeline?y=ci&n=15&b=2a4e4cf03e" |
| 70 | target="testwindow">Isolated check-ins.</a> |
| 71 | |
| 72 | External: |
| 73 | |
| 74 | * <a href="http://www.sqlite.org/src/timeline?c=2010-09-29&nd" |
| 75 | target="testwindow">Timewarp due to a mis-configured system clock.</a> |
| 76 |
| --- test/graph-test-1.wiki | |
| +++ test/graph-test-1.wiki | |
| @@ -66,10 +66,13 @@ | |
| 66 | * <a href="../../../timeline?c=20015206bc" |
| 67 | target="testwindow"> |
| 68 | This timeline has a hidden commit.</a> Click Unhide to reveal. |
| 69 | * <a href="../../../timeline?y=ci&n=15&b=2a4e4cf03e" |
| 70 | target="testwindow">Isolated check-ins.</a> |
| 71 | * <a href="../../../timeline?b=0fa60142&n=50" |
| 72 | target="testwindow">Single branch raiser from bottom of page |
| 73 | up to checkins 057e4b and d3cc6d</a> |
| 74 | |
| 75 | External: |
| 76 | |
| 77 | * <a href="http://www.sqlite.org/src/timeline?c=2010-09-29&nd" |
| 78 | target="testwindow">Timewarp due to a mis-configured system clock.</a> |
| 79 |
+1
-1
| --- test/json.test | ||
| +++ test/json.test | ||
| @@ -23,11 +23,11 @@ | ||
| 23 | 23 | # practice of eliminating all trace of the fossil json command when |
| 24 | 24 | # not configured. If that changes, these conditions might not prevent |
| 25 | 25 | # the rest of this file from running. |
| 26 | 26 | fossil test-th-eval "hasfeature json" |
| 27 | 27 | |
| 28 | -if {$::RESULT ne "1"} then { | |
| 28 | +if {[normalize_result] ne "1"} then { | |
| 29 | 29 | puts "Fossil was not compiled with JSON support." |
| 30 | 30 | test_cleanup_then_return |
| 31 | 31 | } |
| 32 | 32 | |
| 33 | 33 | # We need a JSON parser to effectively test the JSON produced by |
| 34 | 34 |
| --- test/json.test | |
| +++ test/json.test | |
| @@ -23,11 +23,11 @@ | |
| 23 | # practice of eliminating all trace of the fossil json command when |
| 24 | # not configured. If that changes, these conditions might not prevent |
| 25 | # the rest of this file from running. |
| 26 | fossil test-th-eval "hasfeature json" |
| 27 | |
| 28 | if {$::RESULT ne "1"} then { |
| 29 | puts "Fossil was not compiled with JSON support." |
| 30 | test_cleanup_then_return |
| 31 | } |
| 32 | |
| 33 | # We need a JSON parser to effectively test the JSON produced by |
| 34 |
| --- test/json.test | |
| +++ test/json.test | |
| @@ -23,11 +23,11 @@ | |
| 23 | # practice of eliminating all trace of the fossil json command when |
| 24 | # not configured. If that changes, these conditions might not prevent |
| 25 | # the rest of this file from running. |
| 26 | fossil test-th-eval "hasfeature json" |
| 27 | |
| 28 | if {[normalize_result] ne "1"} then { |
| 29 | puts "Fossil was not compiled with JSON support." |
| 30 | test_cleanup_then_return |
| 31 | } |
| 32 | |
| 33 | # We need a JSON parser to effectively test the JSON produced by |
| 34 |
+1
| --- test/merge2.test | ||
| +++ test/merge2.test | ||
| @@ -35,10 +35,11 @@ | ||
| 35 | 35 | expr {srand($i*2+1)} |
| 36 | 36 | write_file t23 [random_changes $f2 2 4 2 0.1] |
| 37 | 37 | expr {srand($i*2)} |
| 38 | 38 | write_file t32 [random_changes $f3 2 4 0 0.1] |
| 39 | 39 | fossil 3-way-merge t1 t2 t3 a23 |
| 40 | + if {[regexp {<<<<< BEGIN MERGE CONFLICT:} [read_file a23]]} continue | |
| 40 | 41 | test merge-$base-$i-23 {[same_file a23 t23]} |
| 41 | 42 | fossil 3-way-merge t1 t3 t2 a32 |
| 42 | 43 | test merge-$base-$i-32 {[same_file a32 t32]} |
| 43 | 44 | } |
| 44 | 45 | } |
| 45 | 46 |
| --- test/merge2.test | |
| +++ test/merge2.test | |
| @@ -35,10 +35,11 @@ | |
| 35 | expr {srand($i*2+1)} |
| 36 | write_file t23 [random_changes $f2 2 4 2 0.1] |
| 37 | expr {srand($i*2)} |
| 38 | write_file t32 [random_changes $f3 2 4 0 0.1] |
| 39 | fossil 3-way-merge t1 t2 t3 a23 |
| 40 | test merge-$base-$i-23 {[same_file a23 t23]} |
| 41 | fossil 3-way-merge t1 t3 t2 a32 |
| 42 | test merge-$base-$i-32 {[same_file a32 t32]} |
| 43 | } |
| 44 | } |
| 45 |
| --- test/merge2.test | |
| +++ test/merge2.test | |
| @@ -35,10 +35,11 @@ | |
| 35 | expr {srand($i*2+1)} |
| 36 | write_file t23 [random_changes $f2 2 4 2 0.1] |
| 37 | expr {srand($i*2)} |
| 38 | write_file t32 [random_changes $f3 2 4 0 0.1] |
| 39 | fossil 3-way-merge t1 t2 t3 a23 |
| 40 | if {[regexp {<<<<< BEGIN MERGE CONFLICT:} [read_file a23]]} continue |
| 41 | test merge-$base-$i-23 {[same_file a23 t23]} |
| 42 | fossil 3-way-merge t1 t3 t2 a32 |
| 43 | test merge-$base-$i-32 {[same_file a32 t32]} |
| 44 | } |
| 45 | } |
| 46 |
+2
| --- test/mv-rm.test | ||
| +++ test/mv-rm.test | ||
| @@ -15,10 +15,12 @@ | ||
| 15 | 15 | # |
| 16 | 16 | ############################################################################ |
| 17 | 17 | # |
| 18 | 18 | # MV / RM Commands |
| 19 | 19 | # |
| 20 | + | |
| 21 | +set path [file dirname [info script]] | |
| 20 | 22 | |
| 21 | 23 | require_no_open_checkout |
| 22 | 24 | |
| 23 | 25 | ######################################## |
| 24 | 26 | # Setup: Add Files and Commit # |
| 25 | 27 | |
| 26 | 28 | ADDED test/set-manifest.test |
| --- test/mv-rm.test | |
| +++ test/mv-rm.test | |
| @@ -15,10 +15,12 @@ | |
| 15 | # |
| 16 | ############################################################################ |
| 17 | # |
| 18 | # MV / RM Commands |
| 19 | # |
| 20 | |
| 21 | require_no_open_checkout |
| 22 | |
| 23 | ######################################## |
| 24 | # Setup: Add Files and Commit # |
| 25 | |
| 26 | DDED test/set-manifest.test |
| --- test/mv-rm.test | |
| +++ test/mv-rm.test | |
| @@ -15,10 +15,12 @@ | |
| 15 | # |
| 16 | ############################################################################ |
| 17 | # |
| 18 | # MV / RM Commands |
| 19 | # |
| 20 | |
| 21 | set path [file dirname [info script]] |
| 22 | |
| 23 | require_no_open_checkout |
| 24 | |
| 25 | ######################################## |
| 26 | # Setup: Add Files and Commit # |
| 27 | |
| 28 | DDED test/set-manifest.test |
+113
| --- a/test/set-manifest.test | ||
| +++ b/test/set-manifest.test | ||
| @@ -0,0 +1,113 @@ | ||
| 1 | +# | |
| 2 | +# Copyright (c) 2016 D. Richard Hipp | |
| 3 | +# | |
| 4 | +# This program is free software; you can redistribute it and/or | |
| 5 | +# modify it under the terms of the Simplified BSD License (also | |
| 6 | +# known as the "2-Clause License" or "FreeBSD License".) | |
| 7 | +# | |
| 8 | +# This program is distributed in the hope that it will be useful, | |
| 9 | +# but without any warranty; without even the implied warranty of | |
| 10 | +# merchantability or fitness for a particular purpose. | |
| 11 | +# | |
| 12 | +# Author contact information: | |
| 13 | +# [email protected] | |
| 14 | +# http://www.hwaci.com/drh/ | |
| 15 | +# | |
| 16 | +############################################################################ | |
| 17 | +# | |
| 18 | +# Test manifest setting | |
| 19 | +# | |
| 20 | + | |
| 21 | +t (c) 2016 D. Richard Hipp | |
| 22 | +# | |
| 23 | +# This program is free software; you can redistribute it and/or | |
| 24 | +# modify it under the terms of the Simplified BSD License (also | |
| 25 | +# known as the "2-Clause License" or "FreeBSD License".) | |
| 26 | +# | |
| 27 | +# T# | |
| 28 | +# Copyright (c) 20 | |
| 29 | + | |
| 30 | +proc file_contains {fname match} { | |
| 31 | + set fp [open $fname r] | |
| 32 | + set contents [read $fp] | |
| 33 | + close $fp | |
| 34 | + set lines [split $contents "\n"] | |
| 35 | + foreach line $lines { | |
| 36 | + if {[regexp $match $line]} { | |
| 37 | + return 1 | |
| 38 | + } | |
| 39 | + } | |
| 40 | + return 0 | |
| 41 | +} | |
| 42 | + | |
| 43 | +# We need SHA1 to effectively test the manifest files produced by | |
| 44 | +# fossil. It looks like the one from tcllib is exactly what we need. | |
| 45 | +# On ActiveTcl, add it with teacup. On other platforms, YMMV. | |
| 46 | +# teacup install sha1 | |
| 47 | +if {[catch {package require sha1}] != 0} then { | |
| 48 | + puts "The \"sha1\" package is not available." | |
| 49 | + test_cleanup_then_return | |
| 50 | +} | |
| 51 | + | |
| 52 | +# We need a respository, so let it have one. | |
| 53 | +test_setup | |
| 54 | + | |
| 55 | +#### Verify classic behavior of the manifest setting | |
| 56 | + | |
| 57 | +# Setting is off by default, and there are no extra files. | |
| 58 | +fossil settings manifest | |
| 59 | +test "set-manifest-1" {[regexp {^manifest *$} $RESULT]} | |
| 60 | +set filelist [$v" {$RESULT eq ""} | |
| 61 | + fossi D. Richard Hipp | |
| 62 | +# | |
| 63 | +# This program is free software; you can redistribute it and/or | |
| 64 | +# modify it under the terms of the Simplified BSD License (also | |
| 65 | +# known as the "2-Clause License" or "FreeBSD License".) | |
| 66 | +# | |
| 67 | +# This program is distributed in the hope that it will be useful, | |
| 68 | +# buithout any warranty; without even the implied warranty of | |
| 69 | +# mer# | |
| 70 | +# Copyright manifes$ckid eq $uuid} foreach f $filelist { | |
| 71 | + test "set-manifest-2-$v-f-$f" {[file isfile $f]} | |
| 72 | + } | |
| 73 | +} | |
| 74 | + | |
| 75 | +# ... and manifest.uuid is the checkout's hash | |
| 76 | +fossil info | |
| 77 | +regexp {(?m)^checkout:\s+([0-9a-f]{40,64})\s.*$} $RESULT ckoutline ckid | |
| 78 | +set uuid [string trim [read_file "manifest.uuid"]] | |
| 79 | +test "set-manifest-2-uuid" {[same_uuid $ckid $uuid]} | |
| 80 | + | |
| 81 | + | |
| 82 | +# ... which is also the SHA1 of the file "manifest" before it was | |
| 83 | +#License" or "FreeBSD License0 | |
| 84 | + | |
| 85 | +proc file_contains {fname match}e "manifest"] "" ma2-manifest" {$muuid eq $uuidequire sha1}] != 0} then close $fp | |
| 86 | + set lines [split $contents "\n"] | |
| 87 | + foreach line $lines { | |
| 88 | + if {[regexp $match $line]} { | |
| 89 | + return 1 | |
| 90 | + } | |
| 91 | + } | |
| 92 | + return 0 | |
| 93 | +} | |
| 94 | + | |
| 95 | +# We need SHA1 to effectively test the manifest files produced by | |
| 96 | +# fossil. It looks like the one from tcllib is exactly what we need. | |
| 97 | +# On ActiveTcl, add it with teacup. On other platforms, YMMV. | |
| 98 | +# teacup install sha1 | |
| 99 | +if {[catch {package require sha1}] != 0} then { | |
| 100 | + puts "The \"sha1\" package is not available." | |
| 101 | + test_cleanup_then_return | |
| 102 | +} | |
| 103 | + | |
| 104 | +# We need a respository, so let it have one. | |
| 105 | +test_setup | |
| 106 | + | |
| 107 | +#### Verify classic behavior of the manifest setting | |
| 108 | + | |
| 109 | +# Setting is off by default, and there are no extra files. | |
| 110 | +fossil settings manifest | |
| 111 | +test "set-manifest-1" {[regexp {^manifest *$} $RESULT]} | |
| 112 | +set filelist [$v" {$RESULT eq ""} | |
| 113 | + fossi D. R |
| --- a/test/set-manifest.test | |
| +++ b/test/set-manifest.test | |
| @@ -0,0 +1,113 @@ | |
| --- a/test/set-manifest.test | |
| +++ b/test/set-manifest.test | |
| @@ -0,0 +1,113 @@ | |
| 1 | # |
| 2 | # Copyright (c) 2016 D. Richard Hipp |
| 3 | # |
| 4 | # This program is free software; you can redistribute it and/or |
| 5 | # modify it under the terms of the Simplified BSD License (also |
| 6 | # known as the "2-Clause License" or "FreeBSD License".) |
| 7 | # |
| 8 | # This program is distributed in the hope that it will be useful, |
| 9 | # but without any warranty; without even the implied warranty of |
| 10 | # merchantability or fitness for a particular purpose. |
| 11 | # |
| 12 | # Author contact information: |
| 13 | # [email protected] |
| 14 | # http://www.hwaci.com/drh/ |
| 15 | # |
| 16 | ############################################################################ |
| 17 | # |
| 18 | # Test manifest setting |
| 19 | # |
| 20 | |
| 21 | t (c) 2016 D. Richard Hipp |
| 22 | # |
| 23 | # This program is free software; you can redistribute it and/or |
| 24 | # modify it under the terms of the Simplified BSD License (also |
| 25 | # known as the "2-Clause License" or "FreeBSD License".) |
| 26 | # |
| 27 | # T# |
| 28 | # Copyright (c) 20 |
| 29 | |
| 30 | proc file_contains {fname match} { |
| 31 | set fp [open $fname r] |
| 32 | set contents [read $fp] |
| 33 | close $fp |
| 34 | set lines [split $contents "\n"] |
| 35 | foreach line $lines { |
| 36 | if {[regexp $match $line]} { |
| 37 | return 1 |
| 38 | } |
| 39 | } |
| 40 | return 0 |
| 41 | } |
| 42 | |
| 43 | # We need SHA1 to effectively test the manifest files produced by |
| 44 | # fossil. It looks like the one from tcllib is exactly what we need. |
| 45 | # On ActiveTcl, add it with teacup. On other platforms, YMMV. |
| 46 | # teacup install sha1 |
| 47 | if {[catch {package require sha1}] != 0} then { |
| 48 | puts "The \"sha1\" package is not available." |
| 49 | test_cleanup_then_return |
| 50 | } |
| 51 | |
| 52 | # We need a respository, so let it have one. |
| 53 | test_setup |
| 54 | |
| 55 | #### Verify classic behavior of the manifest setting |
| 56 | |
| 57 | # Setting is off by default, and there are no extra files. |
| 58 | fossil settings manifest |
| 59 | test "set-manifest-1" {[regexp {^manifest *$} $RESULT]} |
| 60 | set filelist [$v" {$RESULT eq ""} |
| 61 | fossi D. Richard Hipp |
| 62 | # |
| 63 | # This program is free software; you can redistribute it and/or |
| 64 | # modify it under the terms of the Simplified BSD License (also |
| 65 | # known as the "2-Clause License" or "FreeBSD License".) |
| 66 | # |
| 67 | # This program is distributed in the hope that it will be useful, |
| 68 | # buithout any warranty; without even the implied warranty of |
| 69 | # mer# |
| 70 | # Copyright manifes$ckid eq $uuid} foreach f $filelist { |
| 71 | test "set-manifest-2-$v-f-$f" {[file isfile $f]} |
| 72 | } |
| 73 | } |
| 74 | |
| 75 | # ... and manifest.uuid is the checkout's hash |
| 76 | fossil info |
| 77 | regexp {(?m)^checkout:\s+([0-9a-f]{40,64})\s.*$} $RESULT ckoutline ckid |
| 78 | set uuid [string trim [read_file "manifest.uuid"]] |
| 79 | test "set-manifest-2-uuid" {[same_uuid $ckid $uuid]} |
| 80 | |
| 81 | |
| 82 | # ... which is also the SHA1 of the file "manifest" before it was |
| 83 | #License" or "FreeBSD License0 |
| 84 | |
| 85 | proc file_contains {fname match}e "manifest"] "" ma2-manifest" {$muuid eq $uuidequire sha1}] != 0} then close $fp |
| 86 | set lines [split $contents "\n"] |
| 87 | foreach line $lines { |
| 88 | if {[regexp $match $line]} { |
| 89 | return 1 |
| 90 | } |
| 91 | } |
| 92 | return 0 |
| 93 | } |
| 94 | |
| 95 | # We need SHA1 to effectively test the manifest files produced by |
| 96 | # fossil. It looks like the one from tcllib is exactly what we need. |
| 97 | # On ActiveTcl, add it with teacup. On other platforms, YMMV. |
| 98 | # teacup install sha1 |
| 99 | if {[catch {package require sha1}] != 0} then { |
| 100 | puts "The \"sha1\" package is not available." |
| 101 | test_cleanup_then_return |
| 102 | } |
| 103 | |
| 104 | # We need a respository, so let it have one. |
| 105 | test_setup |
| 106 | |
| 107 | #### Verify classic behavior of the manifest setting |
| 108 | |
| 109 | # Setting is off by default, and there are no extra files. |
| 110 | fossil settings manifest |
| 111 | test "set-manifest-1" {[regexp {^manifest *$} $RESULT]} |
| 112 | set filelist [$v" {$RESULT eq ""} |
| 113 | fossi D. R |
+4
-1
| --- test/settings-repo.test | ||
| +++ test/settings-repo.test | ||
| @@ -16,12 +16,15 @@ | ||
| 16 | 16 | ############################################################################ |
| 17 | 17 | # |
| 18 | 18 | # The "settings" and "unset" commands that may modify the repository. |
| 19 | 19 | # |
| 20 | 20 | |
| 21 | +set path [file dirname [info script]] | |
| 22 | + | |
| 21 | 23 | require_no_open_checkout |
| 22 | -set dir [file dirname [info script]]; test_setup | |
| 24 | + | |
| 25 | +test_setup | |
| 23 | 26 | |
| 24 | 27 | ############################################################################### |
| 25 | 28 | # |
| 26 | 29 | # Complete syntax as tested: |
| 27 | 30 | # |
| 28 | 31 |
| --- test/settings-repo.test | |
| +++ test/settings-repo.test | |
| @@ -16,12 +16,15 @@ | |
| 16 | ############################################################################ |
| 17 | # |
| 18 | # The "settings" and "unset" commands that may modify the repository. |
| 19 | # |
| 20 | |
| 21 | require_no_open_checkout |
| 22 | set dir [file dirname [info script]]; test_setup |
| 23 | |
| 24 | ############################################################################### |
| 25 | # |
| 26 | # Complete syntax as tested: |
| 27 | # |
| 28 |
| --- test/settings-repo.test | |
| +++ test/settings-repo.test | |
| @@ -16,12 +16,15 @@ | |
| 16 | ############################################################################ |
| 17 | # |
| 18 | # The "settings" and "unset" commands that may modify the repository. |
| 19 | # |
| 20 | |
| 21 | set path [file dirname [info script]] |
| 22 | |
| 23 | require_no_open_checkout |
| 24 | |
| 25 | test_setup |
| 26 | |
| 27 | ############################################################################### |
| 28 | # |
| 29 | # Complete syntax as tested: |
| 30 | # |
| 31 |
+1
-1
| --- test/settings.test | ||
| +++ test/settings.test | ||
| @@ -16,11 +16,11 @@ | ||
| 16 | 16 | ############################################################################ |
| 17 | 17 | # |
| 18 | 18 | # The "settings" and "unset" commands. |
| 19 | 19 | # |
| 20 | 20 | |
| 21 | -set dir [file dirname [info script]]; test_setup | |
| 21 | +set path [file dirname [info script]]; test_setup | |
| 22 | 22 | |
| 23 | 23 | ############################################################################### |
| 24 | 24 | # |
| 25 | 25 | # Complete syntax as tested: |
| 26 | 26 | # |
| 27 | 27 |
| --- test/settings.test | |
| +++ test/settings.test | |
| @@ -16,11 +16,11 @@ | |
| 16 | ############################################################################ |
| 17 | # |
| 18 | # The "settings" and "unset" commands. |
| 19 | # |
| 20 | |
| 21 | set dir [file dirname [info script]]; test_setup |
| 22 | |
| 23 | ############################################################################### |
| 24 | # |
| 25 | # Complete syntax as tested: |
| 26 | # |
| 27 |
| --- test/settings.test | |
| +++ test/settings.test | |
| @@ -16,11 +16,11 @@ | |
| 16 | ############################################################################ |
| 17 | # |
| 18 | # The "settings" and "unset" commands. |
| 19 | # |
| 20 | |
| 21 | set path [file dirname [info script]]; test_setup |
| 22 | |
| 23 | ############################################################################### |
| 24 | # |
| 25 | # Complete syntax as tested: |
| 26 | # |
| 27 |
+2
-6
| --- test/stash.test | ||
| +++ test/stash.test | ||
| @@ -185,15 +185,13 @@ | ||
| 185 | 185 | ADDED f0 |
| 186 | 186 | } -changes { |
| 187 | 187 | ADDED f0 |
| 188 | 188 | MISSING f1 |
| 189 | 189 | EDITED f2 |
| 190 | - MISSING f3 | |
| 190 | + RENAMED f3n | |
| 191 | 191 | } -addremove { |
| 192 | - ADDED f3n | |
| 193 | 192 | DELETED f1 |
| 194 | - DELETED f3 | |
| 195 | 193 | } -exists {f0 f2 f3n} -notexists {f1 f3} |
| 196 | 194 | |
| 197 | 195 | # Confirm there is no longer a stash saved |
| 198 | 196 | fossil stash list |
| 199 | 197 | test stash-2-list {[first_data_line] eq "empty stash"} |
| @@ -311,13 +309,11 @@ | ||
| 311 | 309 | UPDATE f1 |
| 312 | 310 | UPDATE f2n |
| 313 | 311 | } -changes { |
| 314 | 312 | RENAMED f2n |
| 315 | 313 | } -addremove { |
| 316 | - ADDED f2n | |
| 317 | - DELETED f2 | |
| 318 | -} -exists {f1 f2n} -notexists {f2} -knownbugs {-changes} | |
| 314 | +} -exists {f1 f2n} -notexists {f2} | |
| 319 | 315 | |
| 320 | 316 | |
| 321 | 317 | |
| 322 | 318 | ######## |
| 323 | 319 | # fossil stash snapshot ?-m|--comment COMMENT? ?FILES...? |
| 324 | 320 | |
| 325 | 321 | ADDED test/symlinks.test |
| --- test/stash.test | |
| +++ test/stash.test | |
| @@ -185,15 +185,13 @@ | |
| 185 | ADDED f0 |
| 186 | } -changes { |
| 187 | ADDED f0 |
| 188 | MISSING f1 |
| 189 | EDITED f2 |
| 190 | MISSING f3 |
| 191 | } -addremove { |
| 192 | ADDED f3n |
| 193 | DELETED f1 |
| 194 | DELETED f3 |
| 195 | } -exists {f0 f2 f3n} -notexists {f1 f3} |
| 196 | |
| 197 | # Confirm there is no longer a stash saved |
| 198 | fossil stash list |
| 199 | test stash-2-list {[first_data_line] eq "empty stash"} |
| @@ -311,13 +309,11 @@ | |
| 311 | UPDATE f1 |
| 312 | UPDATE f2n |
| 313 | } -changes { |
| 314 | RENAMED f2n |
| 315 | } -addremove { |
| 316 | ADDED f2n |
| 317 | DELETED f2 |
| 318 | } -exists {f1 f2n} -notexists {f2} -knownbugs {-changes} |
| 319 | |
| 320 | |
| 321 | |
| 322 | ######## |
| 323 | # fossil stash snapshot ?-m|--comment COMMENT? ?FILES...? |
| 324 | |
| 325 | DDED test/symlinks.test |
| --- test/stash.test | |
| +++ test/stash.test | |
| @@ -185,15 +185,13 @@ | |
| 185 | ADDED f0 |
| 186 | } -changes { |
| 187 | ADDED f0 |
| 188 | MISSING f1 |
| 189 | EDITED f2 |
| 190 | RENAMED f3n |
| 191 | } -addremove { |
| 192 | DELETED f1 |
| 193 | } -exists {f0 f2 f3n} -notexists {f1 f3} |
| 194 | |
| 195 | # Confirm there is no longer a stash saved |
| 196 | fossil stash list |
| 197 | test stash-2-list {[first_data_line] eq "empty stash"} |
| @@ -311,13 +309,11 @@ | |
| 309 | UPDATE f1 |
| 310 | UPDATE f2n |
| 311 | } -changes { |
| 312 | RENAMED f2n |
| 313 | } -addremove { |
| 314 | } -exists {f1 f2n} -notexists {f2} |
| 315 | |
| 316 | |
| 317 | |
| 318 | ######## |
| 319 | # fossil stash snapshot ?-m|--comment COMMENT? ?FILES...? |
| 320 | |
| 321 | DDED test/symlinks.test |
+68
| --- a/test/symlinks.test | ||
| +++ b/test/symlinks.test | ||
| @@ -0,0 +1,68 @@ | ||
| 1 | +# | |
| 2 | +# Copyright (c) 2016 D. Richard Hipp | |
| 3 | +# | |
| 4 | +# This program is free software; you can redistribute it and/or | |
| 5 | +# modify it under the terms of the Simplified BSD License (also | |
| 6 | +# known as the "2-Clause License" or "FreeBSD License".) | |
| 7 | +# | |
| 8 | +# This program is distributed in the hope that it will be useful, | |
| 9 | +# but without any warranty; without even the implied warranty of | |
| 10 | +# merchantability or fitness for a particular purpose. | |
| 11 | +# | |
| 12 | +# Author contact information: | |
| 13 | +# [email protected] | |
| 14 | +# http://www.hwaci.com/drh/ | |
| 15 | +# | |
| 16 | +############################################################################ | |
| 17 | +# | |
| 18 | +# Symbolic link tests. | |
| 19 | +# | |
| 20 | + | |
| 21 | +set path [file dirname [info script]] | |
| 22 | + | |
| 23 | +if {$tcl_platform(platform) eq "windows"allow | |
| 24 | +puts $RESULTmlinks are not supported on Windows." | |
| 25 | + test_cleanup_then_returnon | |
| 26 | + | |
| 27 | +fossil test-th-eval --open-con"setting allow-symlinks" | |
| 28 | + | |
| 29 | +itory [normalize_result] | |
| 30 | + | |
| 31 | +if {[string length $repository] == 0} { | |
| 32 | + puts "Detection of the open repository file failed." | |
| 33 | + test_cleanup_then_return | |
| 34 | +} | |
| 35 | + | |
| 36 | +####################################### | |
| 37 | +# Use symbolic link to a directory... # | |
| 38 | +##############fossil commit -m "c1"_then_returnon | |
| 39 | + | |
| 40 | +fossil test-th-eval --open-con"setting allow-symlinks" | |
| 41 | + | |
| 42 | +itory [normalize_rght (c) 2016 D. Rich# | |
| 43 | +# Copyright up_then_returnon | |
| 44 | + | |
| 45 | +fossil test-th-eval --open-con"setting allow-symlinks" | |
| 46 | + | |
| 47 | +itory [normalize_result] | |
| 48 | + | |
| 49 | +if {[string length $repository] == 0} { | |
| 50 | + puts "Detection of the open repository file failed." | |
| 51 | + test_cleanup_then_return | |
| 52 | +} | |
| 53 | + | |
| 54 | +####################################### | |
| 55 | +# Use symbolic link to a directory... # | |
| 56 | +####################################### | |
| 57 | + | |
| 58 | +file mkdir [file join $rootDir subdirA] | |
| 59 | +exec ln -s [file join $rootDir subdirA] symdirA | |
| 60 | + | |
| 61 | +############################################################################### | |
| 62 | + | |
| 63 | +write_file [file join $rootDir subdirA f1.txt] "f1" | |
| 64 | +write_file [file join $rootDir subdirA f2.txt] "f2" | |
| 65 | + | |
| 66 | +test symlinks-dir-1 {[file exists [file join $rootDir subdirA f1.txt]] eq 1} | |
| 67 | +test symlinks-dir-2 {[file exists [file join $rootDir symdirA f1.txt]] eq 1} | |
| 68 | +test symlinks-di |
| --- a/test/symlinks.test | |
| +++ b/test/symlinks.test | |
| @@ -0,0 +1,68 @@ | |
| --- a/test/symlinks.test | |
| +++ b/test/symlinks.test | |
| @@ -0,0 +1,68 @@ | |
| 1 | # |
| 2 | # Copyright (c) 2016 D. Richard Hipp |
| 3 | # |
| 4 | # This program is free software; you can redistribute it and/or |
| 5 | # modify it under the terms of the Simplified BSD License (also |
| 6 | # known as the "2-Clause License" or "FreeBSD License".) |
| 7 | # |
| 8 | # This program is distributed in the hope that it will be useful, |
| 9 | # but without any warranty; without even the implied warranty of |
| 10 | # merchantability or fitness for a particular purpose. |
| 11 | # |
| 12 | # Author contact information: |
| 13 | # [email protected] |
| 14 | # http://www.hwaci.com/drh/ |
| 15 | # |
| 16 | ############################################################################ |
| 17 | # |
| 18 | # Symbolic link tests. |
| 19 | # |
| 20 | |
| 21 | set path [file dirname [info script]] |
| 22 | |
| 23 | if {$tcl_platform(platform) eq "windows"allow |
| 24 | puts $RESULTmlinks are not supported on Windows." |
| 25 | test_cleanup_then_returnon |
| 26 | |
| 27 | fossil test-th-eval --open-con"setting allow-symlinks" |
| 28 | |
| 29 | itory [normalize_result] |
| 30 | |
| 31 | if {[string length $repository] == 0} { |
| 32 | puts "Detection of the open repository file failed." |
| 33 | test_cleanup_then_return |
| 34 | } |
| 35 | |
| 36 | ####################################### |
| 37 | # Use symbolic link to a directory... # |
| 38 | ##############fossil commit -m "c1"_then_returnon |
| 39 | |
| 40 | fossil test-th-eval --open-con"setting allow-symlinks" |
| 41 | |
| 42 | itory [normalize_rght (c) 2016 D. Rich# |
| 43 | # Copyright up_then_returnon |
| 44 | |
| 45 | fossil test-th-eval --open-con"setting allow-symlinks" |
| 46 | |
| 47 | itory [normalize_result] |
| 48 | |
| 49 | if {[string length $repository] == 0} { |
| 50 | puts "Detection of the open repository file failed." |
| 51 | test_cleanup_then_return |
| 52 | } |
| 53 | |
| 54 | ####################################### |
| 55 | # Use symbolic link to a directory... # |
| 56 | ####################################### |
| 57 | |
| 58 | file mkdir [file join $rootDir subdirA] |
| 59 | exec ln -s [file join $rootDir subdirA] symdirA |
| 60 | |
| 61 | ############################################################################### |
| 62 | |
| 63 | write_file [file join $rootDir subdirA f1.txt] "f1" |
| 64 | write_file [file join $rootDir subdirA f2.txt] "f2" |
| 65 | |
| 66 | test symlinks-dir-1 {[file exists [file join $rootDir subdirA f1.txt]] eq 1} |
| 67 | test symlinks-dir-2 {[file exists [file join $rootDir symdirA f1.txt]] eq 1} |
| 68 | test symlinks-di |
+126
-18
| --- test/tester.tcl | ||
| +++ test/tester.tcl | ||
| @@ -136,13 +136,20 @@ | ||
| 136 | 136 | # |
| 137 | 137 | proc fossil_maybe_answer {answer args} { |
| 138 | 138 | global fossilexe |
| 139 | 139 | set cmd $fossilexe |
| 140 | 140 | set expectError 0 |
| 141 | - if {[lindex $args end] eq "-expectError"} { | |
| 141 | + set index [lsearch -exact $args -expectError] | |
| 142 | + if {$index != -1} { | |
| 142 | 143 | set expectError 1 |
| 143 | - set args [lrange $args 0 end-1] | |
| 144 | + set args [lreplace $args $index $index] | |
| 145 | + } | |
| 146 | + set keepNewline 0 | |
| 147 | + set index [lsearch -exact $args -keepNewline] | |
| 148 | + if {$index != -1} { | |
| 149 | + set keepNewline 1 | |
| 150 | + set args [lreplace $args $index $index] | |
| 144 | 151 | } |
| 145 | 152 | foreach a $args { |
| 146 | 153 | lappend cmd $a |
| 147 | 154 | } |
| 148 | 155 | protOut $cmd |
| @@ -150,14 +157,22 @@ | ||
| 150 | 157 | flush stdout |
| 151 | 158 | if {[string length $answer] > 0} { |
| 152 | 159 | protOut $answer |
| 153 | 160 | set prompt_file [file join $::tempPath fossil_prompt_answer] |
| 154 | 161 | write_file $prompt_file $answer\n |
| 155 | - set rc [catch {eval exec $cmd <$prompt_file} result] | |
| 162 | + if {$keepNewline} { | |
| 163 | + set rc [catch {eval exec -keepnewline $cmd <$prompt_file} result] | |
| 164 | + } else { | |
| 165 | + set rc [catch {eval exec $cmd <$prompt_file} result] | |
| 166 | + } | |
| 156 | 167 | file delete $prompt_file |
| 157 | 168 | } else { |
| 158 | - set rc [catch {eval exec $cmd} result] | |
| 169 | + if {$keepNewline} { | |
| 170 | + set rc [catch {eval exec -keepnewline $cmd} result] | |
| 171 | + } else { | |
| 172 | + set rc [catch {eval exec $cmd} result] | |
| 173 | + } | |
| 159 | 174 | } |
| 160 | 175 | global RESULT CODE |
| 161 | 176 | set CODE $rc |
| 162 | 177 | if {($rc && !$expectError) || (!$rc && $expectError)} { |
| 163 | 178 | protOut "ERROR: $result" 1 |
| @@ -210,11 +225,11 @@ | ||
| 210 | 225 | th1-setup \ |
| 211 | 226 | th1-uri-regexp] |
| 212 | 227 | |
| 213 | 228 | fossil test-th-eval "hasfeature tcl" |
| 214 | 229 | |
| 215 | - if {$::RESULT eq "1"} { | |
| 230 | + if {[normalize_result] eq "1"} { | |
| 216 | 231 | lappend result tcl-setup |
| 217 | 232 | } |
| 218 | 233 | |
| 219 | 234 | return [lsort -dictionary $result] |
| 220 | 235 | } |
| @@ -270,33 +285,34 @@ | ||
| 270 | 285 | ssh-command \ |
| 271 | 286 | ssl-ca-location \ |
| 272 | 287 | ssl-identity \ |
| 273 | 288 | th1-setup \ |
| 274 | 289 | th1-uri-regexp \ |
| 290 | + uv-sync \ | |
| 275 | 291 | web-browser] |
| 276 | 292 | |
| 277 | 293 | fossil test-th-eval "hasfeature legacyMvRm" |
| 278 | 294 | |
| 279 | - if {$::RESULT eq "1"} { | |
| 295 | + if {[normalize_result] eq "1"} { | |
| 280 | 296 | lappend result mv-rm-files |
| 281 | 297 | } |
| 282 | 298 | |
| 283 | 299 | fossil test-th-eval "hasfeature tcl" |
| 284 | 300 | |
| 285 | - if {$::RESULT eq "1"} { | |
| 301 | + if {[normalize_result] eq "1"} { | |
| 286 | 302 | lappend result tcl tcl-setup |
| 287 | 303 | } |
| 288 | 304 | |
| 289 | 305 | fossil test-th-eval "hasfeature th1Docs" |
| 290 | 306 | |
| 291 | - if {$::RESULT eq "1"} { | |
| 307 | + if {[normalize_result] eq "1"} { | |
| 292 | 308 | lappend result th1-docs |
| 293 | 309 | } |
| 294 | 310 | |
| 295 | 311 | fossil test-th-eval "hasfeature th1Hooks" |
| 296 | 312 | |
| 297 | - if {$::RESULT eq "1"} { | |
| 313 | + if {[normalize_result] eq "1"} { | |
| 298 | 314 | lappend result th1-hooks |
| 299 | 315 | } |
| 300 | 316 | |
| 301 | 317 | return [lsort -dictionary $result] |
| 302 | 318 | } |
| @@ -439,27 +455,27 @@ | ||
| 439 | 455 | |
| 440 | 456 | # This procedure only returns non-zero if the Tcl integration feature was |
| 441 | 457 | # enabled at compile-time and is now enabled at runtime. |
| 442 | 458 | proc is_tcl_usable_by_fossil {} { |
| 443 | 459 | fossil test-th-eval "hasfeature tcl" |
| 444 | - if {$::RESULT ne "1"} {return 0} | |
| 460 | + if {[normalize_result] ne "1"} {return 0} | |
| 445 | 461 | fossil test-th-eval "setting tcl" |
| 446 | - if {$::RESULT eq "1"} {return 1} | |
| 462 | + if {[normalize_result] eq "1"} {return 1} | |
| 447 | 463 | fossil test-th-eval --open-config "setting tcl" |
| 448 | - if {$::RESULT eq "1"} {return 1} | |
| 464 | + if {[normalize_result] eq "1"} {return 1} | |
| 449 | 465 | return [info exists ::env(TH1_ENABLE_TCL)] |
| 450 | 466 | } |
| 451 | 467 | |
| 452 | 468 | # This procedure only returns non-zero if the TH1 hooks feature was enabled |
| 453 | 469 | # at compile-time and is now enabled at runtime. |
| 454 | 470 | proc are_th1_hooks_usable_by_fossil {} { |
| 455 | 471 | fossil test-th-eval "hasfeature th1Hooks" |
| 456 | - if {$::RESULT ne "1"} {return 0} | |
| 472 | + if {[normalize_result] ne "1"} {return 0} | |
| 457 | 473 | fossil test-th-eval "setting th1-hooks" |
| 458 | - if {$::RESULT eq "1"} {return 1} | |
| 474 | + if {[normalize_result] eq "1"} {return 1} | |
| 459 | 475 | fossil test-th-eval --open-config "setting th1-hooks" |
| 460 | - if {$::RESULT eq "1"} {return 1} | |
| 476 | + if {[normalize_result] eq "1"} {return 1} | |
| 461 | 477 | return [info exists ::env(TH1_ENABLE_HOOKS)] |
| 462 | 478 | } |
| 463 | 479 | |
| 464 | 480 | # This (rarely used) procedure is designed to run a test within the Fossil |
| 465 | 481 | # source checkout (e.g. one that does NOT modify any state), while saving |
| @@ -559,14 +575,14 @@ | ||
| 559 | 575 | # NOTE: Check if we can use any of the environment variables. |
| 560 | 576 | # |
| 561 | 577 | foreach name $names { |
| 562 | 578 | set value [getEnvironmentVariable $name] |
| 563 | 579 | |
| 564 | - if {[string length $value] > 0} then { | |
| 580 | + if {[string length $value] > 0} { | |
| 565 | 581 | set value [file normalize $value] |
| 566 | 582 | |
| 567 | - if {[file exists $value] && [file isdirectory $value]} then { | |
| 583 | + if {[file exists $value] && [file isdirectory $value]} { | |
| 568 | 584 | return $value |
| 569 | 585 | } |
| 570 | 586 | } |
| 571 | 587 | } |
| 572 | 588 | |
| @@ -574,11 +590,11 @@ | ||
| 574 | 590 | # NOTE: On non-Windows systems, fallback to /tmp if it is usable. |
| 575 | 591 | # |
| 576 | 592 | if {$::tcl_platform(platform) ne "windows"} { |
| 577 | 593 | set value /tmp |
| 578 | 594 | |
| 579 | - if {[file exists $value] && [file isdirectory $value]} then { | |
| 595 | + if {[file exists $value] && [file isdirectory $value]} { | |
| 580 | 596 | return $value |
| 581 | 597 | } |
| 582 | 598 | } |
| 583 | 599 | |
| 584 | 600 | # |
| @@ -731,10 +747,102 @@ | ||
| 731 | 747 | } |
| 732 | 748 | append out \n$line |
| 733 | 749 | } |
| 734 | 750 | return [string range $out 1 end] |
| 735 | 751 | } |
| 752 | + | |
| 753 | +# This procedure executes the "fossil server" command. The return value | |
| 754 | +# is a list comprised of the new process identifier and the port on which | |
| 755 | +# the server started. The varName argument refers to a variable | |
| 756 | +# where the "stop argument" is to be stored. This value must eventually be | |
| 757 | +# passed to the [test_stop_server] procedure. | |
| 758 | +proc test_start_server { repository {varName ""} } { | |
| 759 | + global fossilexe tempPath | |
| 760 | + set command [list exec $fossilexe server --localhost] | |
| 761 | + if {[string length $varName] > 0} { | |
| 762 | + upvar 1 $varName stopArg | |
| 763 | + } | |
| 764 | + if {$::tcl_platform(platform) eq "windows"} { | |
| 765 | + set stopArg [file join [getTemporaryPath] [appendArgs \ | |
| 766 | + [string trim [clock seconds] -] _ [getSeqNo] .stopper]] | |
| 767 | + lappend command --stopper $stopArg | |
| 768 | + } | |
| 769 | + set outFileName [file join $tempPath [appendArgs \ | |
| 770 | + fossil_server_ [string trim [clock seconds] -] _ \ | |
| 771 | + [getSeqNo]]].out | |
| 772 | + lappend command $repository >&$outFileName & | |
| 773 | + set pid [eval $command] | |
| 774 | + if {$::tcl_platform(platform) ne "windows"} { | |
| 775 | + set stopArg $pid | |
| 776 | + } | |
| 777 | + after 1000; # output might not be there yet | |
| 778 | + set output [read_file $outFileName] | |
| 779 | + if {![regexp {Listening.*TCP port (\d+)} $output dummy port]} { | |
| 780 | + puts stdout "Could not detect Fossil server port, using default..." | |
| 781 | + set port 8080; # return the default port just in case | |
| 782 | + } | |
| 783 | + return [list $pid $port $outFileName] | |
| 784 | +} | |
| 785 | + | |
| 786 | +# This procedure stops a Fossil server instance that was previously started | |
| 787 | +# by the [test_start_server] procedure. The value of the "stop argument" | |
| 788 | +# will vary by platform as will the exact method used to stop the server. | |
| 789 | +# The fileName argument is the name of a temporary output file to delete. | |
| 790 | +proc test_stop_server { stopArg pid fileName } { | |
| 791 | + if {$::tcl_platform(platform) eq "windows"} { | |
| 792 | + # | |
| 793 | + # NOTE: On Windows, the "stop argument" must be the name of a file | |
| 794 | + # that does NOT already exist. | |
| 795 | + # | |
| 796 | + if {[string length $stopArg] > 0 && \ | |
| 797 | + ![file exists $stopArg] && \ | |
| 798 | + [catch {write_file $stopArg [clock seconds]}] == 0} { | |
| 799 | + while {1} { | |
| 800 | + if {[catch { | |
| 801 | + # | |
| 802 | + # NOTE: Using the TaskList utility requires Windows XP or | |
| 803 | + # later. | |
| 804 | + # | |
| 805 | + exec tasklist.exe /FI "PID eq $pid" | |
| 806 | + } result] != 0 || ![regexp -- " $pid " $result]} { | |
| 807 | + break | |
| 808 | + } | |
| 809 | + after 1000; # wait a bit... | |
| 810 | + } | |
| 811 | + file delete $stopArg | |
| 812 | + if {[string length $fileName] > 0} { | |
| 813 | + file delete $fileName | |
| 814 | + } | |
| 815 | + return true | |
| 816 | + } | |
| 817 | + } else { | |
| 818 | + # | |
| 819 | + # NOTE: On Unix, the "stop argument" must be an integer identifier | |
| 820 | + # that refers to an existing process. | |
| 821 | + # | |
| 822 | + if {[regexp {^(?:-)?\d+$} $stopArg] && \ | |
| 823 | + [catch {exec kill -TERM $stopArg}] == 0} { | |
| 824 | + while {1} { | |
| 825 | + if {[catch { | |
| 826 | + # | |
| 827 | + # TODO: Is this portable to all the supported variants of | |
| 828 | + # Unix? It should be, it's POSIX. | |
| 829 | + # | |
| 830 | + exec ps -p $pid | |
| 831 | + } result] != 0 || ![regexp -- "(?:^$pid| $pid) " $result]} { | |
| 832 | + break | |
| 833 | + } | |
| 834 | + after 1000; # wait a bit... | |
| 835 | + } | |
| 836 | + if {[string length $fileName] > 0} { | |
| 837 | + file delete $fileName | |
| 838 | + } | |
| 839 | + return true | |
| 840 | + } | |
| 841 | + } | |
| 842 | + return false | |
| 843 | +} | |
| 736 | 844 | |
| 737 | 845 | # Executes the "fossil http" command. The entire content of the HTTP request |
| 738 | 846 | # is read from the data file name, with [subst] being performed on it prior to |
| 739 | 847 | # submission. Temporary input and output files are created and deleted. The |
| 740 | 848 | # result will be the contents of the temoprary output file. |
| 741 | 849 |
| --- test/tester.tcl | |
| +++ test/tester.tcl | |
| @@ -136,13 +136,20 @@ | |
| 136 | # |
| 137 | proc fossil_maybe_answer {answer args} { |
| 138 | global fossilexe |
| 139 | set cmd $fossilexe |
| 140 | set expectError 0 |
| 141 | if {[lindex $args end] eq "-expectError"} { |
| 142 | set expectError 1 |
| 143 | set args [lrange $args 0 end-1] |
| 144 | } |
| 145 | foreach a $args { |
| 146 | lappend cmd $a |
| 147 | } |
| 148 | protOut $cmd |
| @@ -150,14 +157,22 @@ | |
| 150 | flush stdout |
| 151 | if {[string length $answer] > 0} { |
| 152 | protOut $answer |
| 153 | set prompt_file [file join $::tempPath fossil_prompt_answer] |
| 154 | write_file $prompt_file $answer\n |
| 155 | set rc [catch {eval exec $cmd <$prompt_file} result] |
| 156 | file delete $prompt_file |
| 157 | } else { |
| 158 | set rc [catch {eval exec $cmd} result] |
| 159 | } |
| 160 | global RESULT CODE |
| 161 | set CODE $rc |
| 162 | if {($rc && !$expectError) || (!$rc && $expectError)} { |
| 163 | protOut "ERROR: $result" 1 |
| @@ -210,11 +225,11 @@ | |
| 210 | th1-setup \ |
| 211 | th1-uri-regexp] |
| 212 | |
| 213 | fossil test-th-eval "hasfeature tcl" |
| 214 | |
| 215 | if {$::RESULT eq "1"} { |
| 216 | lappend result tcl-setup |
| 217 | } |
| 218 | |
| 219 | return [lsort -dictionary $result] |
| 220 | } |
| @@ -270,33 +285,34 @@ | |
| 270 | ssh-command \ |
| 271 | ssl-ca-location \ |
| 272 | ssl-identity \ |
| 273 | th1-setup \ |
| 274 | th1-uri-regexp \ |
| 275 | web-browser] |
| 276 | |
| 277 | fossil test-th-eval "hasfeature legacyMvRm" |
| 278 | |
| 279 | if {$::RESULT eq "1"} { |
| 280 | lappend result mv-rm-files |
| 281 | } |
| 282 | |
| 283 | fossil test-th-eval "hasfeature tcl" |
| 284 | |
| 285 | if {$::RESULT eq "1"} { |
| 286 | lappend result tcl tcl-setup |
| 287 | } |
| 288 | |
| 289 | fossil test-th-eval "hasfeature th1Docs" |
| 290 | |
| 291 | if {$::RESULT eq "1"} { |
| 292 | lappend result th1-docs |
| 293 | } |
| 294 | |
| 295 | fossil test-th-eval "hasfeature th1Hooks" |
| 296 | |
| 297 | if {$::RESULT eq "1"} { |
| 298 | lappend result th1-hooks |
| 299 | } |
| 300 | |
| 301 | return [lsort -dictionary $result] |
| 302 | } |
| @@ -439,27 +455,27 @@ | |
| 439 | |
| 440 | # This procedure only returns non-zero if the Tcl integration feature was |
| 441 | # enabled at compile-time and is now enabled at runtime. |
| 442 | proc is_tcl_usable_by_fossil {} { |
| 443 | fossil test-th-eval "hasfeature tcl" |
| 444 | if {$::RESULT ne "1"} {return 0} |
| 445 | fossil test-th-eval "setting tcl" |
| 446 | if {$::RESULT eq "1"} {return 1} |
| 447 | fossil test-th-eval --open-config "setting tcl" |
| 448 | if {$::RESULT eq "1"} {return 1} |
| 449 | return [info exists ::env(TH1_ENABLE_TCL)] |
| 450 | } |
| 451 | |
| 452 | # This procedure only returns non-zero if the TH1 hooks feature was enabled |
| 453 | # at compile-time and is now enabled at runtime. |
| 454 | proc are_th1_hooks_usable_by_fossil {} { |
| 455 | fossil test-th-eval "hasfeature th1Hooks" |
| 456 | if {$::RESULT ne "1"} {return 0} |
| 457 | fossil test-th-eval "setting th1-hooks" |
| 458 | if {$::RESULT eq "1"} {return 1} |
| 459 | fossil test-th-eval --open-config "setting th1-hooks" |
| 460 | if {$::RESULT eq "1"} {return 1} |
| 461 | return [info exists ::env(TH1_ENABLE_HOOKS)] |
| 462 | } |
| 463 | |
| 464 | # This (rarely used) procedure is designed to run a test within the Fossil |
| 465 | # source checkout (e.g. one that does NOT modify any state), while saving |
| @@ -559,14 +575,14 @@ | |
| 559 | # NOTE: Check if we can use any of the environment variables. |
| 560 | # |
| 561 | foreach name $names { |
| 562 | set value [getEnvironmentVariable $name] |
| 563 | |
| 564 | if {[string length $value] > 0} then { |
| 565 | set value [file normalize $value] |
| 566 | |
| 567 | if {[file exists $value] && [file isdirectory $value]} then { |
| 568 | return $value |
| 569 | } |
| 570 | } |
| 571 | } |
| 572 | |
| @@ -574,11 +590,11 @@ | |
| 574 | # NOTE: On non-Windows systems, fallback to /tmp if it is usable. |
| 575 | # |
| 576 | if {$::tcl_platform(platform) ne "windows"} { |
| 577 | set value /tmp |
| 578 | |
| 579 | if {[file exists $value] && [file isdirectory $value]} then { |
| 580 | return $value |
| 581 | } |
| 582 | } |
| 583 | |
| 584 | # |
| @@ -731,10 +747,102 @@ | |
| 731 | } |
| 732 | append out \n$line |
| 733 | } |
| 734 | return [string range $out 1 end] |
| 735 | } |
| 736 | |
| 737 | # Executes the "fossil http" command. The entire content of the HTTP request |
| 738 | # is read from the data file name, with [subst] being performed on it prior to |
| 739 | # submission. Temporary input and output files are created and deleted. The |
| 740 | # result will be the contents of the temoprary output file. |
| 741 |
| --- test/tester.tcl | |
| +++ test/tester.tcl | |
| @@ -136,13 +136,20 @@ | |
| 136 | # |
| 137 | proc fossil_maybe_answer {answer args} { |
| 138 | global fossilexe |
| 139 | set cmd $fossilexe |
| 140 | set expectError 0 |
| 141 | set index [lsearch -exact $args -expectError] |
| 142 | if {$index != -1} { |
| 143 | set expectError 1 |
| 144 | set args [lreplace $args $index $index] |
| 145 | } |
| 146 | set keepNewline 0 |
| 147 | set index [lsearch -exact $args -keepNewline] |
| 148 | if {$index != -1} { |
| 149 | set keepNewline 1 |
| 150 | set args [lreplace $args $index $index] |
| 151 | } |
| 152 | foreach a $args { |
| 153 | lappend cmd $a |
| 154 | } |
| 155 | protOut $cmd |
| @@ -150,14 +157,22 @@ | |
| 157 | flush stdout |
| 158 | if {[string length $answer] > 0} { |
| 159 | protOut $answer |
| 160 | set prompt_file [file join $::tempPath fossil_prompt_answer] |
| 161 | write_file $prompt_file $answer\n |
| 162 | if {$keepNewline} { |
| 163 | set rc [catch {eval exec -keepnewline $cmd <$prompt_file} result] |
| 164 | } else { |
| 165 | set rc [catch {eval exec $cmd <$prompt_file} result] |
| 166 | } |
| 167 | file delete $prompt_file |
| 168 | } else { |
| 169 | if {$keepNewline} { |
| 170 | set rc [catch {eval exec -keepnewline $cmd} result] |
| 171 | } else { |
| 172 | set rc [catch {eval exec $cmd} result] |
| 173 | } |
| 174 | } |
| 175 | global RESULT CODE |
| 176 | set CODE $rc |
| 177 | if {($rc && !$expectError) || (!$rc && $expectError)} { |
| 178 | protOut "ERROR: $result" 1 |
| @@ -210,11 +225,11 @@ | |
| 225 | th1-setup \ |
| 226 | th1-uri-regexp] |
| 227 | |
| 228 | fossil test-th-eval "hasfeature tcl" |
| 229 | |
| 230 | if {[normalize_result] eq "1"} { |
| 231 | lappend result tcl-setup |
| 232 | } |
| 233 | |
| 234 | return [lsort -dictionary $result] |
| 235 | } |
| @@ -270,33 +285,34 @@ | |
| 285 | ssh-command \ |
| 286 | ssl-ca-location \ |
| 287 | ssl-identity \ |
| 288 | th1-setup \ |
| 289 | th1-uri-regexp \ |
| 290 | uv-sync \ |
| 291 | web-browser] |
| 292 | |
| 293 | fossil test-th-eval "hasfeature legacyMvRm" |
| 294 | |
| 295 | if {[normalize_result] eq "1"} { |
| 296 | lappend result mv-rm-files |
| 297 | } |
| 298 | |
| 299 | fossil test-th-eval "hasfeature tcl" |
| 300 | |
| 301 | if {[normalize_result] eq "1"} { |
| 302 | lappend result tcl tcl-setup |
| 303 | } |
| 304 | |
| 305 | fossil test-th-eval "hasfeature th1Docs" |
| 306 | |
| 307 | if {[normalize_result] eq "1"} { |
| 308 | lappend result th1-docs |
| 309 | } |
| 310 | |
| 311 | fossil test-th-eval "hasfeature th1Hooks" |
| 312 | |
| 313 | if {[normalize_result] eq "1"} { |
| 314 | lappend result th1-hooks |
| 315 | } |
| 316 | |
| 317 | return [lsort -dictionary $result] |
| 318 | } |
| @@ -439,27 +455,27 @@ | |
| 455 | |
| 456 | # This procedure only returns non-zero if the Tcl integration feature was |
| 457 | # enabled at compile-time and is now enabled at runtime. |
| 458 | proc is_tcl_usable_by_fossil {} { |
| 459 | fossil test-th-eval "hasfeature tcl" |
| 460 | if {[normalize_result] ne "1"} {return 0} |
| 461 | fossil test-th-eval "setting tcl" |
| 462 | if {[normalize_result] eq "1"} {return 1} |
| 463 | fossil test-th-eval --open-config "setting tcl" |
| 464 | if {[normalize_result] eq "1"} {return 1} |
| 465 | return [info exists ::env(TH1_ENABLE_TCL)] |
| 466 | } |
| 467 | |
| 468 | # This procedure only returns non-zero if the TH1 hooks feature was enabled |
| 469 | # at compile-time and is now enabled at runtime. |
| 470 | proc are_th1_hooks_usable_by_fossil {} { |
| 471 | fossil test-th-eval "hasfeature th1Hooks" |
| 472 | if {[normalize_result] ne "1"} {return 0} |
| 473 | fossil test-th-eval "setting th1-hooks" |
| 474 | if {[normalize_result] eq "1"} {return 1} |
| 475 | fossil test-th-eval --open-config "setting th1-hooks" |
| 476 | if {[normalize_result] eq "1"} {return 1} |
| 477 | return [info exists ::env(TH1_ENABLE_HOOKS)] |
| 478 | } |
| 479 | |
| 480 | # This (rarely used) procedure is designed to run a test within the Fossil |
| 481 | # source checkout (e.g. one that does NOT modify any state), while saving |
| @@ -559,14 +575,14 @@ | |
| 575 | # NOTE: Check if we can use any of the environment variables. |
| 576 | # |
| 577 | foreach name $names { |
| 578 | set value [getEnvironmentVariable $name] |
| 579 | |
| 580 | if {[string length $value] > 0} { |
| 581 | set value [file normalize $value] |
| 582 | |
| 583 | if {[file exists $value] && [file isdirectory $value]} { |
| 584 | return $value |
| 585 | } |
| 586 | } |
| 587 | } |
| 588 | |
| @@ -574,11 +590,11 @@ | |
| 590 | # NOTE: On non-Windows systems, fallback to /tmp if it is usable. |
| 591 | # |
| 592 | if {$::tcl_platform(platform) ne "windows"} { |
| 593 | set value /tmp |
| 594 | |
| 595 | if {[file exists $value] && [file isdirectory $value]} { |
| 596 | return $value |
| 597 | } |
| 598 | } |
| 599 | |
| 600 | # |
| @@ -731,10 +747,102 @@ | |
| 747 | } |
| 748 | append out \n$line |
| 749 | } |
| 750 | return [string range $out 1 end] |
| 751 | } |
| 752 | |
| 753 | # This procedure executes the "fossil server" command. The return value |
| 754 | # is a list comprised of the new process identifier and the port on which |
| 755 | # the server started. The varName argument refers to a variable |
| 756 | # where the "stop argument" is to be stored. This value must eventually be |
| 757 | # passed to the [test_stop_server] procedure. |
| 758 | proc test_start_server { repository {varName ""} } { |
| 759 | global fossilexe tempPath |
| 760 | set command [list exec $fossilexe server --localhost] |
| 761 | if {[string length $varName] > 0} { |
| 762 | upvar 1 $varName stopArg |
| 763 | } |
| 764 | if {$::tcl_platform(platform) eq "windows"} { |
| 765 | set stopArg [file join [getTemporaryPath] [appendArgs \ |
| 766 | [string trim [clock seconds] -] _ [getSeqNo] .stopper]] |
| 767 | lappend command --stopper $stopArg |
| 768 | } |
| 769 | set outFileName [file join $tempPath [appendArgs \ |
| 770 | fossil_server_ [string trim [clock seconds] -] _ \ |
| 771 | [getSeqNo]]].out |
| 772 | lappend command $repository >&$outFileName & |
| 773 | set pid [eval $command] |
| 774 | if {$::tcl_platform(platform) ne "windows"} { |
| 775 | set stopArg $pid |
| 776 | } |
| 777 | after 1000; # output might not be there yet |
| 778 | set output [read_file $outFileName] |
| 779 | if {![regexp {Listening.*TCP port (\d+)} $output dummy port]} { |
| 780 | puts stdout "Could not detect Fossil server port, using default..." |
| 781 | set port 8080; # return the default port just in case |
| 782 | } |
| 783 | return [list $pid $port $outFileName] |
| 784 | } |
| 785 | |
| 786 | # This procedure stops a Fossil server instance that was previously started |
| 787 | # by the [test_start_server] procedure. The value of the "stop argument" |
| 788 | # will vary by platform as will the exact method used to stop the server. |
| 789 | # The fileName argument is the name of a temporary output file to delete. |
| 790 | proc test_stop_server { stopArg pid fileName } { |
| 791 | if {$::tcl_platform(platform) eq "windows"} { |
| 792 | # |
| 793 | # NOTE: On Windows, the "stop argument" must be the name of a file |
| 794 | # that does NOT already exist. |
| 795 | # |
| 796 | if {[string length $stopArg] > 0 && \ |
| 797 | ![file exists $stopArg] && \ |
| 798 | [catch {write_file $stopArg [clock seconds]}] == 0} { |
| 799 | while {1} { |
| 800 | if {[catch { |
| 801 | # |
| 802 | # NOTE: Using the TaskList utility requires Windows XP or |
| 803 | # later. |
| 804 | # |
| 805 | exec tasklist.exe /FI "PID eq $pid" |
| 806 | } result] != 0 || ![regexp -- " $pid " $result]} { |
| 807 | break |
| 808 | } |
| 809 | after 1000; # wait a bit... |
| 810 | } |
| 811 | file delete $stopArg |
| 812 | if {[string length $fileName] > 0} { |
| 813 | file delete $fileName |
| 814 | } |
| 815 | return true |
| 816 | } |
| 817 | } else { |
| 818 | # |
| 819 | # NOTE: On Unix, the "stop argument" must be an integer identifier |
| 820 | # that refers to an existing process. |
| 821 | # |
| 822 | if {[regexp {^(?:-)?\d+$} $stopArg] && \ |
| 823 | [catch {exec kill -TERM $stopArg}] == 0} { |
| 824 | while {1} { |
| 825 | if {[catch { |
| 826 | # |
| 827 | # TODO: Is this portable to all the supported variants of |
| 828 | # Unix? It should be, it's POSIX. |
| 829 | # |
| 830 | exec ps -p $pid |
| 831 | } result] != 0 || ![regexp -- "(?:^$pid| $pid) " $result]} { |
| 832 | break |
| 833 | } |
| 834 | after 1000; # wait a bit... |
| 835 | } |
| 836 | if {[string length $fileName] > 0} { |
| 837 | file delete $fileName |
| 838 | } |
| 839 | return true |
| 840 | } |
| 841 | } |
| 842 | return false |
| 843 | } |
| 844 | |
| 845 | # Executes the "fossil http" command. The entire content of the HTTP request |
| 846 | # is read from the data file name, with [subst] being performed on it prior to |
| 847 | # submission. Temporary input and output files are created and deleted. The |
| 848 | # result will be the contents of the temoprary output file. |
| 849 |
+2
-2
| --- test/th1-docs.test | ||
| +++ test/th1-docs.test | ||
| @@ -18,18 +18,18 @@ | ||
| 18 | 18 | # TH1 Docs |
| 19 | 19 | # |
| 20 | 20 | |
| 21 | 21 | fossil test-th-eval "hasfeature th1Docs" |
| 22 | 22 | |
| 23 | -if {$::RESULT ne "1"} { | |
| 23 | +if {[normalize_result] ne "1"} { | |
| 24 | 24 | puts "Fossil was not compiled with TH1 docs support." |
| 25 | 25 | test_cleanup_then_return |
| 26 | 26 | } |
| 27 | 27 | |
| 28 | 28 | fossil test-th-eval "hasfeature tcl" |
| 29 | 29 | |
| 30 | -if {$::RESULT ne "1"} { | |
| 30 | +if {[normalize_result] ne "1"} { | |
| 31 | 31 | puts "Fossil was not compiled with Tcl support." |
| 32 | 32 | test_cleanup_then_return |
| 33 | 33 | } |
| 34 | 34 | |
| 35 | 35 | ############################################################################### |
| 36 | 36 |
| --- test/th1-docs.test | |
| +++ test/th1-docs.test | |
| @@ -18,18 +18,18 @@ | |
| 18 | # TH1 Docs |
| 19 | # |
| 20 | |
| 21 | fossil test-th-eval "hasfeature th1Docs" |
| 22 | |
| 23 | if {$::RESULT ne "1"} { |
| 24 | puts "Fossil was not compiled with TH1 docs support." |
| 25 | test_cleanup_then_return |
| 26 | } |
| 27 | |
| 28 | fossil test-th-eval "hasfeature tcl" |
| 29 | |
| 30 | if {$::RESULT ne "1"} { |
| 31 | puts "Fossil was not compiled with Tcl support." |
| 32 | test_cleanup_then_return |
| 33 | } |
| 34 | |
| 35 | ############################################################################### |
| 36 |
| --- test/th1-docs.test | |
| +++ test/th1-docs.test | |
| @@ -18,18 +18,18 @@ | |
| 18 | # TH1 Docs |
| 19 | # |
| 20 | |
| 21 | fossil test-th-eval "hasfeature th1Docs" |
| 22 | |
| 23 | if {[normalize_result] ne "1"} { |
| 24 | puts "Fossil was not compiled with TH1 docs support." |
| 25 | test_cleanup_then_return |
| 26 | } |
| 27 | |
| 28 | fossil test-th-eval "hasfeature tcl" |
| 29 | |
| 30 | if {[normalize_result] ne "1"} { |
| 31 | puts "Fossil was not compiled with Tcl support." |
| 32 | test_cleanup_then_return |
| 33 | } |
| 34 | |
| 35 | ############################################################################### |
| 36 |
+14
-4
| --- test/th1-hooks.test | ||
| +++ test/th1-hooks.test | ||
| @@ -18,11 +18,11 @@ | ||
| 18 | 18 | # TH1 Hooks |
| 19 | 19 | # |
| 20 | 20 | |
| 21 | 21 | fossil test-th-eval "hasfeature th1Hooks" |
| 22 | 22 | |
| 23 | -if {$::RESULT ne "1"} { | |
| 23 | +if {[normalize_result] ne "1"} { | |
| 24 | 24 | puts "Fossil was not compiled with TH1 hooks support." |
| 25 | 25 | test_cleanup_then_return |
| 26 | 26 | } |
| 27 | 27 | |
| 28 | 28 | ############################################################################### |
| @@ -75,12 +75,17 @@ | ||
| 75 | 75 | return -code 2 "TH_RETURN return code" |
| 76 | 76 | } elseif {$::cmd_name eq "timeline"} { |
| 77 | 77 | set length [llength $::cmd_args] |
| 78 | 78 | set length [expr {$length - 1}] |
| 79 | 79 | if {[lindex $::cmd_args $length] eq "custom"} { |
| 80 | + append_hook_log "CUSTOM TIMELINE" | |
| 80 | 81 | emit_hook_log |
| 81 | 82 | return "custom timeline" |
| 83 | + } elseif {[lindex $::cmd_args $length] eq "custom2"} { | |
| 84 | + emit_hook_log | |
| 85 | + puts "+++ some stuff here +++" | |
| 86 | + continue "custom2 timeline" | |
| 82 | 87 | } elseif {[lindex $::cmd_args $length] eq "now"} { |
| 83 | 88 | emit_hook_log |
| 84 | 89 | return "now timeline" |
| 85 | 90 | } else { |
| 86 | 91 | emit_hook_log |
| @@ -122,15 +127,21 @@ | ||
| 122 | 127 | |
| 123 | 128 | saveTh1SetupFile; writeTh1SetupFile $testTh1Setup |
| 124 | 129 | |
| 125 | 130 | ############################################################################### |
| 126 | 131 | |
| 127 | -fossil timeline custom; # NOTE: Bad "WHEN" argument. | |
| 132 | +fossil timeline custom -expectError; # NOTE: Bad "WHEN" argument. | |
| 128 | 133 | test th1-cmd-hooks-1a {[normalize_result] eq \ |
| 134 | +{<h1><b>command_hook timeline CUSTOM TIMELINE</b></h1> | |
| 135 | +unknown check-in or invalid date: custom}} | |
| 136 | + | |
| 137 | +############################################################################### | |
| 138 | + | |
| 139 | +fossil timeline custom2; # NOTE: Bad "WHEN" argument. | |
| 140 | +test th1-cmd-hooks-1b {[normalize_result] eq \ | |
| 129 | 141 | {<h1><b>command_hook timeline</b></h1> |
| 130 | -+++ no more data (0) +++ | |
| 131 | - | |
| ++++ some stuff here +++ | ||
| 132 | 142 | <h1><b>command_hook timeline command_notify timeline</b></h1>}} |
| 133 | 143 | |
| 134 | 144 | ############################################################################### |
| 135 | 145 | |
| 136 | 146 | fossil timeline |
| 137 | 147 |
| --- test/th1-hooks.test | |
| +++ test/th1-hooks.test | |
| @@ -18,11 +18,11 @@ | |
| 18 | # TH1 Hooks |
| 19 | # |
| 20 | |
| 21 | fossil test-th-eval "hasfeature th1Hooks" |
| 22 | |
| 23 | if {$::RESULT ne "1"} { |
| 24 | puts "Fossil was not compiled with TH1 hooks support." |
| 25 | test_cleanup_then_return |
| 26 | } |
| 27 | |
| 28 | ############################################################################### |
| @@ -75,12 +75,17 @@ | |
| 75 | return -code 2 "TH_RETURN return code" |
| 76 | } elseif {$::cmd_name eq "timeline"} { |
| 77 | set length [llength $::cmd_args] |
| 78 | set length [expr {$length - 1}] |
| 79 | if {[lindex $::cmd_args $length] eq "custom"} { |
| 80 | emit_hook_log |
| 81 | return "custom timeline" |
| 82 | } elseif {[lindex $::cmd_args $length] eq "now"} { |
| 83 | emit_hook_log |
| 84 | return "now timeline" |
| 85 | } else { |
| 86 | emit_hook_log |
| @@ -122,15 +127,21 @@ | |
| 122 | |
| 123 | saveTh1SetupFile; writeTh1SetupFile $testTh1Setup |
| 124 | |
| 125 | ############################################################################### |
| 126 | |
| 127 | fossil timeline custom; # NOTE: Bad "WHEN" argument. |
| 128 | test th1-cmd-hooks-1a {[normalize_result] eq \ |
| 129 | {<h1><b>command_hook timeline</b></h1> |
| 130 | +++ no more data (0) +++ |
| 131 | |
| ++++ some stuff here +++ | |
| 132 | <h1><b>command_hook timeline command_notify timeline</b></h1>}} |
| 133 | |
| 134 | ############################################################################### |
| 135 | |
| 136 | fossil timeline |
| 137 |
| --- test/th1-hooks.test | |
| +++ test/th1-hooks.test | |
| @@ -18,11 +18,11 @@ | |
| 18 | # TH1 Hooks |
| 19 | # |
| 20 | |
| 21 | fossil test-th-eval "hasfeature th1Hooks" |
| 22 | |
| 23 | if {[normalize_result] ne "1"} { |
| 24 | puts "Fossil was not compiled with TH1 hooks support." |
| 25 | test_cleanup_then_return |
| 26 | } |
| 27 | |
| 28 | ############################################################################### |
| @@ -75,12 +75,17 @@ | |
| 75 | return -code 2 "TH_RETURN return code" |
| 76 | } elseif {$::cmd_name eq "timeline"} { |
| 77 | set length [llength $::cmd_args] |
| 78 | set length [expr {$length - 1}] |
| 79 | if {[lindex $::cmd_args $length] eq "custom"} { |
| 80 | append_hook_log "CUSTOM TIMELINE" |
| 81 | emit_hook_log |
| 82 | return "custom timeline" |
| 83 | } elseif {[lindex $::cmd_args $length] eq "custom2"} { |
| 84 | emit_hook_log |
| 85 | puts "+++ some stuff here +++" |
| 86 | continue "custom2 timeline" |
| 87 | } elseif {[lindex $::cmd_args $length] eq "now"} { |
| 88 | emit_hook_log |
| 89 | return "now timeline" |
| 90 | } else { |
| 91 | emit_hook_log |
| @@ -122,15 +127,21 @@ | |
| 127 | |
| 128 | saveTh1SetupFile; writeTh1SetupFile $testTh1Setup |
| 129 | |
| 130 | ############################################################################### |
| 131 | |
| 132 | fossil timeline custom -expectError; # NOTE: Bad "WHEN" argument. |
| 133 | test th1-cmd-hooks-1a {[normalize_result] eq \ |
| 134 | {<h1><b>command_hook timeline CUSTOM TIMELINE</b></h1> |
| 135 | unknown check-in or invalid date: custom}} |
| 136 | |
| 137 | ############################################################################### |
| 138 | |
| 139 | fossil timeline custom2; # NOTE: Bad "WHEN" argument. |
| 140 | test th1-cmd-hooks-1b {[normalize_result] eq \ |
| 141 | {<h1><b>command_hook timeline</b></h1> |
| ++++ some stuff here +++ | |
| 142 | <h1><b>command_hook timeline command_notify timeline</b></h1>}} |
| 143 | |
| 144 | ############################################################################### |
| 145 | |
| 146 | fossil timeline |
| 147 |
+2
-2
| --- test/th1-repo.test | ||
| +++ test/th1-repo.test | ||
| @@ -19,10 +19,12 @@ | ||
| 19 | 19 | ############################################################################ |
| 20 | 20 | # |
| 21 | 21 | # TH1 tests that may modify the repository |
| 22 | 22 | # |
| 23 | 23 | |
| 24 | +set path [file dirname [info script]] | |
| 25 | + | |
| 24 | 26 | require_no_open_checkout |
| 25 | 27 | |
| 26 | 28 | ######################################## |
| 27 | 29 | # Setup: Add Files and Commit # |
| 28 | 30 | ######################################## |
| @@ -51,12 +53,10 @@ | ||
| 51 | 53 | set files_md [list subdirB/f5.md subdirB/f6.md subdirB/f8.md subdirC/f10.md] |
| 52 | 54 | |
| 53 | 55 | fossil add $rootDir |
| 54 | 56 | fossil commit -m "c1" |
| 55 | 57 | |
| 56 | -set dir [file dirname [info script]] | |
| 57 | - | |
| 58 | 58 | ############################################################################### |
| 59 | 59 | |
| 60 | 60 | fossil test-th-eval --open-config "dir trunk subdir*/*.md" |
| 61 | 61 | test th1-dir-1 {[llength $RESULT] eq [llength $files_md]} |
| 62 | 62 | |
| 63 | 63 |
| --- test/th1-repo.test | |
| +++ test/th1-repo.test | |
| @@ -19,10 +19,12 @@ | |
| 19 | ############################################################################ |
| 20 | # |
| 21 | # TH1 tests that may modify the repository |
| 22 | # |
| 23 | |
| 24 | require_no_open_checkout |
| 25 | |
| 26 | ######################################## |
| 27 | # Setup: Add Files and Commit # |
| 28 | ######################################## |
| @@ -51,12 +53,10 @@ | |
| 51 | set files_md [list subdirB/f5.md subdirB/f6.md subdirB/f8.md subdirC/f10.md] |
| 52 | |
| 53 | fossil add $rootDir |
| 54 | fossil commit -m "c1" |
| 55 | |
| 56 | set dir [file dirname [info script]] |
| 57 | |
| 58 | ############################################################################### |
| 59 | |
| 60 | fossil test-th-eval --open-config "dir trunk subdir*/*.md" |
| 61 | test th1-dir-1 {[llength $RESULT] eq [llength $files_md]} |
| 62 | |
| 63 |
| --- test/th1-repo.test | |
| +++ test/th1-repo.test | |
| @@ -19,10 +19,12 @@ | |
| 19 | ############################################################################ |
| 20 | # |
| 21 | # TH1 tests that may modify the repository |
| 22 | # |
| 23 | |
| 24 | set path [file dirname [info script]] |
| 25 | |
| 26 | require_no_open_checkout |
| 27 | |
| 28 | ######################################## |
| 29 | # Setup: Add Files and Commit # |
| 30 | ######################################## |
| @@ -51,12 +53,10 @@ | |
| 53 | set files_md [list subdirB/f5.md subdirB/f6.md subdirB/f8.md subdirC/f10.md] |
| 54 | |
| 55 | fossil add $rootDir |
| 56 | fossil commit -m "c1" |
| 57 | |
| 58 | ############################################################################### |
| 59 | |
| 60 | fossil test-th-eval --open-config "dir trunk subdir*/*.md" |
| 61 | test th1-dir-1 {[llength $RESULT] eq [llength $files_md]} |
| 62 | |
| 63 |
+12
-12
| --- test/th1-tcl.test | ||
| +++ test/th1-tcl.test | ||
| @@ -16,17 +16,17 @@ | ||
| 16 | 16 | ############################################################################ |
| 17 | 17 | # |
| 18 | 18 | # TH1/Tcl integration |
| 19 | 19 | # |
| 20 | 20 | |
| 21 | -set dir [file dirname [info script]] | |
| 21 | +set path [file dirname [info script]] | |
| 22 | 22 | |
| 23 | 23 | ############################################################################### |
| 24 | 24 | |
| 25 | 25 | fossil test-th-eval "hasfeature tcl" |
| 26 | 26 | |
| 27 | -if {$::RESULT ne "1"} { | |
| 27 | +if {[normalize_result] ne "1"} { | |
| 28 | 28 | puts "Fossil was not compiled with Tcl support." |
| 29 | 29 | test_cleanup_then_return |
| 30 | 30 | } |
| 31 | 31 | |
| 32 | 32 | ############################################################################### |
| @@ -38,11 +38,11 @@ | ||
| 38 | 38 | set env(TH1_ENABLE_TCL) 1; # Tcl integration must be enabled for this test. |
| 39 | 39 | |
| 40 | 40 | ############################################################################### |
| 41 | 41 | |
| 42 | 42 | fossil test-th-render --open-config \ |
| 43 | - [file nativename [file join $dir th1-tcl1.txt]] | |
| 43 | + [file nativename [file join $path th1-tcl1.txt]] | |
| 44 | 44 | |
| 45 | 45 | test th1-tcl-1 {[regexp -- {^tclReady\(before\) = 0 |
| 46 | 46 | tclReady\(after\) = 1 |
| 47 | 47 | \d+ |
| 48 | 48 | \d+ |
| @@ -65,62 +65,62 @@ | ||
| 65 | 65 | |
| 66 | 66 | ############################################################################### |
| 67 | 67 | |
| 68 | 68 | if {[catch {package require sqlite3}] == 0} { |
| 69 | 69 | fossil test-th-render --open-config \ |
| 70 | - [file nativename [file join $dir th1-tcl2.txt]] | |
| 70 | + [file nativename [file join $path th1-tcl2.txt]] | |
| 71 | 71 | |
| 72 | 72 | test th1-tcl-2 {[regexp -- {^\d+$} [normalize_result]]} |
| 73 | 73 | } else { |
| 74 | 74 | puts stderr "Skipping 'th1-tcl-2', SQLite package for Tcl not available" |
| 75 | 75 | } |
| 76 | 76 | |
| 77 | 77 | ############################################################################### |
| 78 | 78 | |
| 79 | 79 | fossil test-th-render --open-config \ |
| 80 | - [file nativename [file join $dir th1-tcl3.txt]] | |
| 80 | + [file nativename [file join $path th1-tcl3.txt]] | |
| 81 | 81 | |
| 82 | 82 | test th1-tcl-3 {$RESULT eq {<hr /><p class="thmainError">ERROR:\ |
| 83 | 83 | invalid command name "bad_command"</p>}} |
| 84 | 84 | |
| 85 | 85 | ############################################################################### |
| 86 | 86 | |
| 87 | 87 | fossil test-th-render --open-config \ |
| 88 | - [file nativename [file join $dir th1-tcl4.txt]] | |
| 88 | + [file nativename [file join $path th1-tcl4.txt]] | |
| 89 | 89 | |
| 90 | 90 | test th1-tcl-4 {$RESULT eq {<hr /><p class="thmainError">ERROR:\ |
| 91 | 91 | divide by zero</p>}} |
| 92 | 92 | |
| 93 | 93 | ############################################################################### |
| 94 | 94 | |
| 95 | 95 | fossil test-th-render --open-config \ |
| 96 | - [file nativename [file join $dir th1-tcl5.txt]] | |
| 96 | + [file nativename [file join $path th1-tcl5.txt]] | |
| 97 | 97 | |
| 98 | 98 | test th1-tcl-5 {$RESULT eq {<hr /><p class="thmainError">ERROR:\ |
| 99 | 99 | Tcl command not found: bad_command</p>} || $RESULT eq {<hr /><p\ |
| 100 | 100 | class="thmainError">ERROR: invalid command name "bad_command"</p>}} |
| 101 | 101 | |
| 102 | 102 | ############################################################################### |
| 103 | 103 | |
| 104 | 104 | fossil test-th-render --open-config \ |
| 105 | - [file nativename [file join $dir th1-tcl6.txt]] | |
| 105 | + [file nativename [file join $path th1-tcl6.txt]] | |
| 106 | 106 | |
| 107 | 107 | test th1-tcl-6 {$RESULT eq {<hr /><p class="thmainError">ERROR:\ |
| 108 | 108 | no such command: bad_command</p>}} |
| 109 | 109 | |
| 110 | 110 | ############################################################################### |
| 111 | 111 | |
| 112 | 112 | fossil test-th-render --open-config \ |
| 113 | - [file nativename [file join $dir th1-tcl7.txt]] | |
| 113 | + [file nativename [file join $path th1-tcl7.txt]] | |
| 114 | 114 | |
| 115 | 115 | test th1-tcl-7 {$RESULT eq {<hr /><p class="thmainError">ERROR:\ |
| 116 | 116 | syntax error in expression: "2**0"</p>}} |
| 117 | 117 | |
| 118 | 118 | ############################################################################### |
| 119 | 119 | |
| 120 | 120 | fossil test-th-render --open-config \ |
| 121 | - [file nativename [file join $dir th1-tcl8.txt]] | |
| 121 | + [file nativename [file join $path th1-tcl8.txt]] | |
| 122 | 122 | |
| 123 | 123 | test th1-tcl-8 {$RESULT eq {<hr /><p class="thmainError">ERROR:\ |
| 124 | 124 | cannot invoke Tcl command: tailcall</p>} || $RESULT eq {<hr /><p\ |
| 125 | 125 | class="thmainError">ERROR: tailcall can only be called from a proc or\ |
| 126 | 126 | lambda</p>} || $RESULT eq {<hr /><p class="thmainError">ERROR: This test\ |
| @@ -127,14 +127,14 @@ | ||
| 127 | 127 | requires Tcl 8.6 or higher.</p>}} |
| 128 | 128 | |
| 129 | 129 | ############################################################################### |
| 130 | 130 | |
| 131 | 131 | fossil test-th-render --open-config \ |
| 132 | - [file nativename [file join $dir th1-tcl9.txt]] | |
| 132 | + [file nativename [file join $path th1-tcl9.txt]] | |
| 133 | 133 | |
| 134 | 134 | test th1-tcl-9 {[string trim $RESULT] eq [list [file tail $fossilexe] 3 \ |
| 135 | -[list test-th-render --open-config [file nativename [file join $dir \ | |
| 135 | +[list test-th-render --open-config [file nativename [file join $path \ | |
| 136 | 136 | th1-tcl9.txt]]]]} |
| 137 | 137 | |
| 138 | 138 | ############################################################################### |
| 139 | 139 | |
| 140 | 140 | fossil test-th-eval "tclMakeSafe a" |
| 141 | 141 |
| --- test/th1-tcl.test | |
| +++ test/th1-tcl.test | |
| @@ -16,17 +16,17 @@ | |
| 16 | ############################################################################ |
| 17 | # |
| 18 | # TH1/Tcl integration |
| 19 | # |
| 20 | |
| 21 | set dir [file dirname [info script]] |
| 22 | |
| 23 | ############################################################################### |
| 24 | |
| 25 | fossil test-th-eval "hasfeature tcl" |
| 26 | |
| 27 | if {$::RESULT ne "1"} { |
| 28 | puts "Fossil was not compiled with Tcl support." |
| 29 | test_cleanup_then_return |
| 30 | } |
| 31 | |
| 32 | ############################################################################### |
| @@ -38,11 +38,11 @@ | |
| 38 | set env(TH1_ENABLE_TCL) 1; # Tcl integration must be enabled for this test. |
| 39 | |
| 40 | ############################################################################### |
| 41 | |
| 42 | fossil test-th-render --open-config \ |
| 43 | [file nativename [file join $dir th1-tcl1.txt]] |
| 44 | |
| 45 | test th1-tcl-1 {[regexp -- {^tclReady\(before\) = 0 |
| 46 | tclReady\(after\) = 1 |
| 47 | \d+ |
| 48 | \d+ |
| @@ -65,62 +65,62 @@ | |
| 65 | |
| 66 | ############################################################################### |
| 67 | |
| 68 | if {[catch {package require sqlite3}] == 0} { |
| 69 | fossil test-th-render --open-config \ |
| 70 | [file nativename [file join $dir th1-tcl2.txt]] |
| 71 | |
| 72 | test th1-tcl-2 {[regexp -- {^\d+$} [normalize_result]]} |
| 73 | } else { |
| 74 | puts stderr "Skipping 'th1-tcl-2', SQLite package for Tcl not available" |
| 75 | } |
| 76 | |
| 77 | ############################################################################### |
| 78 | |
| 79 | fossil test-th-render --open-config \ |
| 80 | [file nativename [file join $dir th1-tcl3.txt]] |
| 81 | |
| 82 | test th1-tcl-3 {$RESULT eq {<hr /><p class="thmainError">ERROR:\ |
| 83 | invalid command name "bad_command"</p>}} |
| 84 | |
| 85 | ############################################################################### |
| 86 | |
| 87 | fossil test-th-render --open-config \ |
| 88 | [file nativename [file join $dir th1-tcl4.txt]] |
| 89 | |
| 90 | test th1-tcl-4 {$RESULT eq {<hr /><p class="thmainError">ERROR:\ |
| 91 | divide by zero</p>}} |
| 92 | |
| 93 | ############################################################################### |
| 94 | |
| 95 | fossil test-th-render --open-config \ |
| 96 | [file nativename [file join $dir th1-tcl5.txt]] |
| 97 | |
| 98 | test th1-tcl-5 {$RESULT eq {<hr /><p class="thmainError">ERROR:\ |
| 99 | Tcl command not found: bad_command</p>} || $RESULT eq {<hr /><p\ |
| 100 | class="thmainError">ERROR: invalid command name "bad_command"</p>}} |
| 101 | |
| 102 | ############################################################################### |
| 103 | |
| 104 | fossil test-th-render --open-config \ |
| 105 | [file nativename [file join $dir th1-tcl6.txt]] |
| 106 | |
| 107 | test th1-tcl-6 {$RESULT eq {<hr /><p class="thmainError">ERROR:\ |
| 108 | no such command: bad_command</p>}} |
| 109 | |
| 110 | ############################################################################### |
| 111 | |
| 112 | fossil test-th-render --open-config \ |
| 113 | [file nativename [file join $dir th1-tcl7.txt]] |
| 114 | |
| 115 | test th1-tcl-7 {$RESULT eq {<hr /><p class="thmainError">ERROR:\ |
| 116 | syntax error in expression: "2**0"</p>}} |
| 117 | |
| 118 | ############################################################################### |
| 119 | |
| 120 | fossil test-th-render --open-config \ |
| 121 | [file nativename [file join $dir th1-tcl8.txt]] |
| 122 | |
| 123 | test th1-tcl-8 {$RESULT eq {<hr /><p class="thmainError">ERROR:\ |
| 124 | cannot invoke Tcl command: tailcall</p>} || $RESULT eq {<hr /><p\ |
| 125 | class="thmainError">ERROR: tailcall can only be called from a proc or\ |
| 126 | lambda</p>} || $RESULT eq {<hr /><p class="thmainError">ERROR: This test\ |
| @@ -127,14 +127,14 @@ | |
| 127 | requires Tcl 8.6 or higher.</p>}} |
| 128 | |
| 129 | ############################################################################### |
| 130 | |
| 131 | fossil test-th-render --open-config \ |
| 132 | [file nativename [file join $dir th1-tcl9.txt]] |
| 133 | |
| 134 | test th1-tcl-9 {[string trim $RESULT] eq [list [file tail $fossilexe] 3 \ |
| 135 | [list test-th-render --open-config [file nativename [file join $dir \ |
| 136 | th1-tcl9.txt]]]]} |
| 137 | |
| 138 | ############################################################################### |
| 139 | |
| 140 | fossil test-th-eval "tclMakeSafe a" |
| 141 |
| --- test/th1-tcl.test | |
| +++ test/th1-tcl.test | |
| @@ -16,17 +16,17 @@ | |
| 16 | ############################################################################ |
| 17 | # |
| 18 | # TH1/Tcl integration |
| 19 | # |
| 20 | |
| 21 | set path [file dirname [info script]] |
| 22 | |
| 23 | ############################################################################### |
| 24 | |
| 25 | fossil test-th-eval "hasfeature tcl" |
| 26 | |
| 27 | if {[normalize_result] ne "1"} { |
| 28 | puts "Fossil was not compiled with Tcl support." |
| 29 | test_cleanup_then_return |
| 30 | } |
| 31 | |
| 32 | ############################################################################### |
| @@ -38,11 +38,11 @@ | |
| 38 | set env(TH1_ENABLE_TCL) 1; # Tcl integration must be enabled for this test. |
| 39 | |
| 40 | ############################################################################### |
| 41 | |
| 42 | fossil test-th-render --open-config \ |
| 43 | [file nativename [file join $path th1-tcl1.txt]] |
| 44 | |
| 45 | test th1-tcl-1 {[regexp -- {^tclReady\(before\) = 0 |
| 46 | tclReady\(after\) = 1 |
| 47 | \d+ |
| 48 | \d+ |
| @@ -65,62 +65,62 @@ | |
| 65 | |
| 66 | ############################################################################### |
| 67 | |
| 68 | if {[catch {package require sqlite3}] == 0} { |
| 69 | fossil test-th-render --open-config \ |
| 70 | [file nativename [file join $path th1-tcl2.txt]] |
| 71 | |
| 72 | test th1-tcl-2 {[regexp -- {^\d+$} [normalize_result]]} |
| 73 | } else { |
| 74 | puts stderr "Skipping 'th1-tcl-2', SQLite package for Tcl not available" |
| 75 | } |
| 76 | |
| 77 | ############################################################################### |
| 78 | |
| 79 | fossil test-th-render --open-config \ |
| 80 | [file nativename [file join $path th1-tcl3.txt]] |
| 81 | |
| 82 | test th1-tcl-3 {$RESULT eq {<hr /><p class="thmainError">ERROR:\ |
| 83 | invalid command name "bad_command"</p>}} |
| 84 | |
| 85 | ############################################################################### |
| 86 | |
| 87 | fossil test-th-render --open-config \ |
| 88 | [file nativename [file join $path th1-tcl4.txt]] |
| 89 | |
| 90 | test th1-tcl-4 {$RESULT eq {<hr /><p class="thmainError">ERROR:\ |
| 91 | divide by zero</p>}} |
| 92 | |
| 93 | ############################################################################### |
| 94 | |
| 95 | fossil test-th-render --open-config \ |
| 96 | [file nativename [file join $path th1-tcl5.txt]] |
| 97 | |
| 98 | test th1-tcl-5 {$RESULT eq {<hr /><p class="thmainError">ERROR:\ |
| 99 | Tcl command not found: bad_command</p>} || $RESULT eq {<hr /><p\ |
| 100 | class="thmainError">ERROR: invalid command name "bad_command"</p>}} |
| 101 | |
| 102 | ############################################################################### |
| 103 | |
| 104 | fossil test-th-render --open-config \ |
| 105 | [file nativename [file join $path th1-tcl6.txt]] |
| 106 | |
| 107 | test th1-tcl-6 {$RESULT eq {<hr /><p class="thmainError">ERROR:\ |
| 108 | no such command: bad_command</p>}} |
| 109 | |
| 110 | ############################################################################### |
| 111 | |
| 112 | fossil test-th-render --open-config \ |
| 113 | [file nativename [file join $path th1-tcl7.txt]] |
| 114 | |
| 115 | test th1-tcl-7 {$RESULT eq {<hr /><p class="thmainError">ERROR:\ |
| 116 | syntax error in expression: "2**0"</p>}} |
| 117 | |
| 118 | ############################################################################### |
| 119 | |
| 120 | fossil test-th-render --open-config \ |
| 121 | [file nativename [file join $path th1-tcl8.txt]] |
| 122 | |
| 123 | test th1-tcl-8 {$RESULT eq {<hr /><p class="thmainError">ERROR:\ |
| 124 | cannot invoke Tcl command: tailcall</p>} || $RESULT eq {<hr /><p\ |
| 125 | class="thmainError">ERROR: tailcall can only be called from a proc or\ |
| 126 | lambda</p>} || $RESULT eq {<hr /><p class="thmainError">ERROR: This test\ |
| @@ -127,14 +127,14 @@ | |
| 127 | requires Tcl 8.6 or higher.</p>}} |
| 128 | |
| 129 | ############################################################################### |
| 130 | |
| 131 | fossil test-th-render --open-config \ |
| 132 | [file nativename [file join $path th1-tcl9.txt]] |
| 133 | |
| 134 | test th1-tcl-9 {[string trim $RESULT] eq [list [file tail $fossilexe] 3 \ |
| 135 | [list test-th-render --open-config [file nativename [file join $path \ |
| 136 | th1-tcl9.txt]]]]} |
| 137 | |
| 138 | ############################################################################### |
| 139 | |
| 140 | fossil test-th-eval "tclMakeSafe a" |
| 141 |
+39
-3
| --- test/th1.test | ||
| +++ test/th1.test | ||
| @@ -16,11 +16,11 @@ | ||
| 16 | 16 | ############################################################################ |
| 17 | 17 | # |
| 18 | 18 | # TH1 Commands |
| 19 | 19 | # |
| 20 | 20 | |
| 21 | -set dir [file dirname [info script]]; test_setup | |
| 21 | +set path [file dirname [info script]]; test_setup | |
| 22 | 22 | |
| 23 | 23 | ############################################################################### |
| 24 | 24 | |
| 25 | 25 | set th1Tcl [is_tcl_usable_by_fossil] |
| 26 | 26 | set th1Hooks [are_th1_hooks_usable_by_fossil] |
| @@ -1038,11 +1038,11 @@ | ||
| 1038 | 1038 | error expr for getParameter glob_match globalState hascap hasfeature\ |
| 1039 | 1039 | html htmlize http httpize if info insertCsrf lindex linecount list\ |
| 1040 | 1040 | llength lsearch markdown proc puts query randhex redirect regexp\ |
| 1041 | 1041 | reinitialize rename render repository return searchable set\ |
| 1042 | 1042 | setParameter setting stime string styleFooter styleHeader tclReady\ |
| 1043 | - trace unset uplevel upvar utime verifyCsrf wiki} | |
| 1043 | + trace unset unversioned uplevel upvar utime verifyCsrf wiki} | |
| 1044 | 1044 | set tcl_commands {tclEval tclExpr tclInvoke tclIsSafe tclMakeSafe} |
| 1045 | 1045 | if {$th1Tcl} { |
| 1046 | 1046 | test th1-info-commands-1 {$sorted_result eq [lsort "$base_commands $tcl_commands"]} |
| 1047 | 1047 | } else { |
| 1048 | 1048 | test th1-info-commands-1 {$sorted_result eq [lsort "$base_commands"]} |
| @@ -1468,11 +1468,11 @@ | ||
| 1468 | 1468 | </div> |
| 1469 | 1469 | }}} |
| 1470 | 1470 | |
| 1471 | 1471 | ############################################################################### |
| 1472 | 1472 | |
| 1473 | -set markdown [read_file [file join $dir markdown-test1.md]] | |
| 1473 | +set markdown [read_file [file join $path markdown-test1.md]] | |
| 1474 | 1474 | fossil test-th-eval [string map \ |
| 1475 | 1475 | [list %markdown% $markdown] {markdown {%markdown%}}] |
| 1476 | 1476 | test th1-markdown-5 {[normalize_result] eq \ |
| 1477 | 1477 | {{Markdown Formatter Test Document} {<div class="markdown"> |
| 1478 | 1478 | |
| @@ -1562,9 +1562,45 @@ | ||
| 1562 | 1562 | } |
| 1563 | 1563 | |
| 1564 | 1564 | fossil test-th-source $th1FileName |
| 1565 | 1565 | test th1-source-1 {$RESULT eq {TH_RETURN: 0 1 2 3 4 5 6 7 8 9}} |
| 1566 | 1566 | file delete $th1FileName |
| 1567 | + | |
| 1568 | +############################################################################### | |
| 1569 | + | |
| 1570 | +# | |
| 1571 | +# TODO: Modify the result of this test if the list of unversioned files | |
| 1572 | +# changes. | |
| 1573 | +# | |
| 1574 | +run_in_checkout { | |
| 1575 | + fossil test-th-eval --open-config "unversioned list" | |
| 1576 | +} | |
| 1577 | + | |
| 1578 | +test th1-unversioned-1 {[normalize_result] eq \ | |
| 1579 | +{build-icons/linux.gif build-icons/linux64.gif build-icons/mac.gif\ | |
| 1580 | +build-icons/openbsd.gif build-icons/src.gif build-icons/win32.gif\ | |
| 1581 | +download.html download/fossil-linux-x86-1.32.zip\ | |
| 1582 | +download/fossil-linux-x86-1.33.zip download/fossil-linux-x86-1.34.zip\ | |
| 1583 | +download/fossil-linux-x86-1.35.zip download/fossil-macosx-x86-1.32.zip\ | |
| 1584 | +download/fossil-macosx-x86-1.33.zip download/fossil-macosx-x86-1.34.zip\ | |
| 1585 | +download/fossil-macosx-x86-1.35.zip download/fossil-openbsd-x86-1.32.zip\ | |
| 1586 | +download/fossil-openbsd-x86-1.33.zip download/fossil-openbsd-x86-1.34.tar.gz\ | |
| 1587 | +download/fossil-openbsd-x86-1.35.tar.gz download/fossil-src-1.32.tar.gz\ | |
| 1588 | +download/fossil-src-1.33.tar.gz download/fossil-src-1.34.tar.gz\ | |
| 1589 | +download/fossil-src-1.35.tar.gz download/fossil-w32-1.32.zip\ | |
| 1590 | +download/fossil-w32-1.33.zip download/fossil-w32-1.34.zip\ | |
| 1591 | +download/fossil-w32-1.35.zip download/releasenotes-1.32.html\ | |
| 1592 | +download/releasenotes-1.33.html download/releasenotes-1.34.html\ | |
| 1593 | +download/releasenotes-1.35.html index.wiki}} | |
| 1594 | + | |
| 1595 | +############################################################################### | |
| 1596 | + | |
| 1597 | +run_in_checkout { | |
| 1598 | + fossil test-th-eval --open-config \ | |
| 1599 | + {string length [unversioned content build-icons/src.gif]} | |
| 1600 | +} | |
| 1601 | + | |
| 1602 | +test th1-unversioned-2 {$RESULT eq {4592}} | |
| 1567 | 1603 | |
| 1568 | 1604 | ############################################################################### |
| 1569 | 1605 | |
| 1570 | 1606 | test_cleanup |
| 1571 | 1607 | |
| 1572 | 1608 | ADDED test/unversioned.test |
| --- test/th1.test | |
| +++ test/th1.test | |
| @@ -16,11 +16,11 @@ | |
| 16 | ############################################################################ |
| 17 | # |
| 18 | # TH1 Commands |
| 19 | # |
| 20 | |
| 21 | set dir [file dirname [info script]]; test_setup |
| 22 | |
| 23 | ############################################################################### |
| 24 | |
| 25 | set th1Tcl [is_tcl_usable_by_fossil] |
| 26 | set th1Hooks [are_th1_hooks_usable_by_fossil] |
| @@ -1038,11 +1038,11 @@ | |
| 1038 | error expr for getParameter glob_match globalState hascap hasfeature\ |
| 1039 | html htmlize http httpize if info insertCsrf lindex linecount list\ |
| 1040 | llength lsearch markdown proc puts query randhex redirect regexp\ |
| 1041 | reinitialize rename render repository return searchable set\ |
| 1042 | setParameter setting stime string styleFooter styleHeader tclReady\ |
| 1043 | trace unset uplevel upvar utime verifyCsrf wiki} |
| 1044 | set tcl_commands {tclEval tclExpr tclInvoke tclIsSafe tclMakeSafe} |
| 1045 | if {$th1Tcl} { |
| 1046 | test th1-info-commands-1 {$sorted_result eq [lsort "$base_commands $tcl_commands"]} |
| 1047 | } else { |
| 1048 | test th1-info-commands-1 {$sorted_result eq [lsort "$base_commands"]} |
| @@ -1468,11 +1468,11 @@ | |
| 1468 | </div> |
| 1469 | }}} |
| 1470 | |
| 1471 | ############################################################################### |
| 1472 | |
| 1473 | set markdown [read_file [file join $dir markdown-test1.md]] |
| 1474 | fossil test-th-eval [string map \ |
| 1475 | [list %markdown% $markdown] {markdown {%markdown%}}] |
| 1476 | test th1-markdown-5 {[normalize_result] eq \ |
| 1477 | {{Markdown Formatter Test Document} {<div class="markdown"> |
| 1478 | |
| @@ -1562,9 +1562,45 @@ | |
| 1562 | } |
| 1563 | |
| 1564 | fossil test-th-source $th1FileName |
| 1565 | test th1-source-1 {$RESULT eq {TH_RETURN: 0 1 2 3 4 5 6 7 8 9}} |
| 1566 | file delete $th1FileName |
| 1567 | |
| 1568 | ############################################################################### |
| 1569 | |
| 1570 | test_cleanup |
| 1571 | |
| 1572 | DDED test/unversioned.test |
| --- test/th1.test | |
| +++ test/th1.test | |
| @@ -16,11 +16,11 @@ | |
| 16 | ############################################################################ |
| 17 | # |
| 18 | # TH1 Commands |
| 19 | # |
| 20 | |
| 21 | set path [file dirname [info script]]; test_setup |
| 22 | |
| 23 | ############################################################################### |
| 24 | |
| 25 | set th1Tcl [is_tcl_usable_by_fossil] |
| 26 | set th1Hooks [are_th1_hooks_usable_by_fossil] |
| @@ -1038,11 +1038,11 @@ | |
| 1038 | error expr for getParameter glob_match globalState hascap hasfeature\ |
| 1039 | html htmlize http httpize if info insertCsrf lindex linecount list\ |
| 1040 | llength lsearch markdown proc puts query randhex redirect regexp\ |
| 1041 | reinitialize rename render repository return searchable set\ |
| 1042 | setParameter setting stime string styleFooter styleHeader tclReady\ |
| 1043 | trace unset unversioned uplevel upvar utime verifyCsrf wiki} |
| 1044 | set tcl_commands {tclEval tclExpr tclInvoke tclIsSafe tclMakeSafe} |
| 1045 | if {$th1Tcl} { |
| 1046 | test th1-info-commands-1 {$sorted_result eq [lsort "$base_commands $tcl_commands"]} |
| 1047 | } else { |
| 1048 | test th1-info-commands-1 {$sorted_result eq [lsort "$base_commands"]} |
| @@ -1468,11 +1468,11 @@ | |
| 1468 | </div> |
| 1469 | }}} |
| 1470 | |
| 1471 | ############################################################################### |
| 1472 | |
| 1473 | set markdown [read_file [file join $path markdown-test1.md]] |
| 1474 | fossil test-th-eval [string map \ |
| 1475 | [list %markdown% $markdown] {markdown {%markdown%}}] |
| 1476 | test th1-markdown-5 {[normalize_result] eq \ |
| 1477 | {{Markdown Formatter Test Document} {<div class="markdown"> |
| 1478 | |
| @@ -1562,9 +1562,45 @@ | |
| 1562 | } |
| 1563 | |
| 1564 | fossil test-th-source $th1FileName |
| 1565 | test th1-source-1 {$RESULT eq {TH_RETURN: 0 1 2 3 4 5 6 7 8 9}} |
| 1566 | file delete $th1FileName |
| 1567 | |
| 1568 | ############################################################################### |
| 1569 | |
| 1570 | # |
| 1571 | # TODO: Modify the result of this test if the list of unversioned files |
| 1572 | # changes. |
| 1573 | # |
| 1574 | run_in_checkout { |
| 1575 | fossil test-th-eval --open-config "unversioned list" |
| 1576 | } |
| 1577 | |
| 1578 | test th1-unversioned-1 {[normalize_result] eq \ |
| 1579 | {build-icons/linux.gif build-icons/linux64.gif build-icons/mac.gif\ |
| 1580 | build-icons/openbsd.gif build-icons/src.gif build-icons/win32.gif\ |
| 1581 | download.html download/fossil-linux-x86-1.32.zip\ |
| 1582 | download/fossil-linux-x86-1.33.zip download/fossil-linux-x86-1.34.zip\ |
| 1583 | download/fossil-linux-x86-1.35.zip download/fossil-macosx-x86-1.32.zip\ |
| 1584 | download/fossil-macosx-x86-1.33.zip download/fossil-macosx-x86-1.34.zip\ |
| 1585 | download/fossil-macosx-x86-1.35.zip download/fossil-openbsd-x86-1.32.zip\ |
| 1586 | download/fossil-openbsd-x86-1.33.zip download/fossil-openbsd-x86-1.34.tar.gz\ |
| 1587 | download/fossil-openbsd-x86-1.35.tar.gz download/fossil-src-1.32.tar.gz\ |
| 1588 | download/fossil-src-1.33.tar.gz download/fossil-src-1.34.tar.gz\ |
| 1589 | download/fossil-src-1.35.tar.gz download/fossil-w32-1.32.zip\ |
| 1590 | download/fossil-w32-1.33.zip download/fossil-w32-1.34.zip\ |
| 1591 | download/fossil-w32-1.35.zip download/releasenotes-1.32.html\ |
| 1592 | download/releasenotes-1.33.html download/releasenotes-1.34.html\ |
| 1593 | download/releasenotes-1.35.html index.wiki}} |
| 1594 | |
| 1595 | ############################################################################### |
| 1596 | |
| 1597 | run_in_checkout { |
| 1598 | fossil test-th-eval --open-config \ |
| 1599 | {string length [unversioned content build-icons/src.gif]} |
| 1600 | } |
| 1601 | |
| 1602 | test th1-unversioned-2 {$RESULT eq {4592}} |
| 1603 | |
| 1604 | ############################################################################### |
| 1605 | |
| 1606 | test_cleanup |
| 1607 | |
| 1608 | DDED test/unversioned.test |
| --- a/test/unversioned.test | ||
| +++ b/test/unversioned.test | ||
| @@ -0,0 +1 @@ | ||
| 1 | +nam |
| --- a/test/unversioned.test | |
| +++ b/test/unversioned.test | |
| @@ -0,0 +1 @@ | |
| --- a/test/unversioned.test | |
| +++ b/test/unversioned.test | |
| @@ -0,0 +1 @@ | |
| 1 | nam |
+1
-1
| --- win/Makefile.PellesCGMake | ||
| +++ win/Makefile.PellesCGMake | ||
| @@ -83,11 +83,11 @@ | ||
| 83 | 83 | |
| 84 | 84 | # define the SQLite files, which need special flags on compile |
| 85 | 85 | SQLITESRC=sqlite3.c |
| 86 | 86 | ORIGSQLITESRC=$(foreach sf,$(SQLITESRC),$(SRCDIR)$(sf)) |
| 87 | 87 | SQLITEOBJ=$(foreach sf,$(SQLITESRC),$(sf:.c=.obj)) |
| 88 | -SQLITEDEFINES=-DNDEBUG=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_WIN32_NO_ANSI | |
| 88 | +SQLITEDEFINES=-DNDEBUG=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_WIN32_NO_ANSI | |
| 89 | 89 | |
| 90 | 90 | # define the SQLite shell files, which need special flags on compile |
| 91 | 91 | SQLITESHELLSRC=shell.c |
| 92 | 92 | ORIGSQLITESHELLSRC=$(foreach sf,$(SQLITESHELLSRC),$(SRCDIR)$(sf)) |
| 93 | 93 | SQLITESHELLOBJ=$(foreach sf,$(SQLITESHELLSRC),$(sf:.c=.obj)) |
| 94 | 94 |
| --- win/Makefile.PellesCGMake | |
| +++ win/Makefile.PellesCGMake | |
| @@ -83,11 +83,11 @@ | |
| 83 | |
| 84 | # define the SQLite files, which need special flags on compile |
| 85 | SQLITESRC=sqlite3.c |
| 86 | ORIGSQLITESRC=$(foreach sf,$(SQLITESRC),$(SRCDIR)$(sf)) |
| 87 | SQLITEOBJ=$(foreach sf,$(SQLITESRC),$(sf:.c=.obj)) |
| 88 | SQLITEDEFINES=-DNDEBUG=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_WIN32_NO_ANSI |
| 89 | |
| 90 | # define the SQLite shell files, which need special flags on compile |
| 91 | SQLITESHELLSRC=shell.c |
| 92 | ORIGSQLITESHELLSRC=$(foreach sf,$(SQLITESHELLSRC),$(SRCDIR)$(sf)) |
| 93 | SQLITESHELLOBJ=$(foreach sf,$(SQLITESHELLSRC),$(sf:.c=.obj)) |
| 94 |
| --- win/Makefile.PellesCGMake | |
| +++ win/Makefile.PellesCGMake | |
| @@ -83,11 +83,11 @@ | |
| 83 | |
| 84 | # define the SQLite files, which need special flags on compile |
| 85 | SQLITESRC=sqlite3.c |
| 86 | ORIGSQLITESRC=$(foreach sf,$(SQLITESRC),$(SRCDIR)$(sf)) |
| 87 | SQLITEOBJ=$(foreach sf,$(SQLITESRC),$(sf:.c=.obj)) |
| 88 | SQLITEDEFINES=-DNDEBUG=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_WIN32_NO_ANSI |
| 89 | |
| 90 | # define the SQLite shell files, which need special flags on compile |
| 91 | SQLITESHELLSRC=shell.c |
| 92 | ORIGSQLITESHELLSRC=$(foreach sf,$(SQLITESHELLSRC),$(SRCDIR)$(sf)) |
| 93 | SQLITESHELLOBJ=$(foreach sf,$(SQLITESHELLSRC),$(sf:.c=.obj)) |
| 94 |
+1
-1
| --- win/Makefile.dmc | ||
| +++ win/Makefile.dmc | ||
| @@ -24,11 +24,11 @@ | ||
| 24 | 24 | CFLAGS = -o |
| 25 | 25 | BCC = $(DMDIR)\bin\dmc $(CFLAGS) |
| 26 | 26 | TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL) |
| 27 | 27 | LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32 |
| 28 | 28 | |
| 29 | -SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 | |
| 29 | +SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 | |
| 30 | 30 | |
| 31 | 31 | SHELL_OPTIONS = -Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=fossil_open -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen |
| 32 | 32 | |
| 33 | 33 | SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c dispatch_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c foci_.c fshell_.c fusefs_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c loadctrl_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c piechart_.c pivot_.c popen_.c pqueue_.c printf_.c publish_.c purge_.c rebuild_.c regexp_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c sitemap_.c skins_.c sqlcmd_.c stash_.c stat_.c statrep_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c unversioned_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c |
| 34 | 34 | |
| 35 | 35 |
| --- win/Makefile.dmc | |
| +++ win/Makefile.dmc | |
| @@ -24,11 +24,11 @@ | |
| 24 | CFLAGS = -o |
| 25 | BCC = $(DMDIR)\bin\dmc $(CFLAGS) |
| 26 | TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL) |
| 27 | LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32 |
| 28 | |
| 29 | SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 |
| 30 | |
| 31 | SHELL_OPTIONS = -Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=fossil_open -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen |
| 32 | |
| 33 | SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c dispatch_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c foci_.c fshell_.c fusefs_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c loadctrl_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c piechart_.c pivot_.c popen_.c pqueue_.c printf_.c publish_.c purge_.c rebuild_.c regexp_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c sitemap_.c skins_.c sqlcmd_.c stash_.c stat_.c statrep_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c unversioned_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c |
| 34 | |
| 35 |
| --- win/Makefile.dmc | |
| +++ win/Makefile.dmc | |
| @@ -24,11 +24,11 @@ | |
| 24 | CFLAGS = -o |
| 25 | BCC = $(DMDIR)\bin\dmc $(CFLAGS) |
| 26 | TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL) |
| 27 | LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32 |
| 28 | |
| 29 | SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 |
| 30 | |
| 31 | SHELL_OPTIONS = -Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=fossil_open -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen |
| 32 | |
| 33 | SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c dispatch_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c foci_.c fshell_.c fusefs_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c loadctrl_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c piechart_.c pivot_.c popen_.c pqueue_.c printf_.c publish_.c purge_.c rebuild_.c regexp_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c sitemap_.c skins_.c sqlcmd_.c stash_.c stat_.c statrep_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c unversioned_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c |
| 34 | |
| 35 |
+2
| --- win/Makefile.mingw | ||
| +++ win/Makefile.mingw | ||
| @@ -2174,10 +2174,12 @@ | ||
| 2174 | 2174 | -DSQLITE_OMIT_DECLTYPE \ |
| 2175 | 2175 | -DSQLITE_OMIT_DEPRECATED \ |
| 2176 | 2176 | -DSQLITE_OMIT_PROGRESS_CALLBACK \ |
| 2177 | 2177 | -DSQLITE_OMIT_SHARED_CACHE \ |
| 2178 | 2178 | -DSQLITE_OMIT_LOAD_EXTENSION \ |
| 2179 | + -DSQLITE_MAX_EXPR_DEPTH=0 \ | |
| 2180 | + -DSQLITE_USE_ALLOCA \ | |
| 2179 | 2181 | -DSQLITE_ENABLE_LOCKING_STYLE=0 \ |
| 2180 | 2182 | -DSQLITE_DEFAULT_FILE_FORMAT=4 \ |
| 2181 | 2183 | -DSQLITE_ENABLE_EXPLAIN_COMMENTS \ |
| 2182 | 2184 | -DSQLITE_ENABLE_FTS4 \ |
| 2183 | 2185 | -DSQLITE_ENABLE_FTS3_PARENTHESIS \ |
| 2184 | 2186 |
| --- win/Makefile.mingw | |
| +++ win/Makefile.mingw | |
| @@ -2174,10 +2174,12 @@ | |
| 2174 | -DSQLITE_OMIT_DECLTYPE \ |
| 2175 | -DSQLITE_OMIT_DEPRECATED \ |
| 2176 | -DSQLITE_OMIT_PROGRESS_CALLBACK \ |
| 2177 | -DSQLITE_OMIT_SHARED_CACHE \ |
| 2178 | -DSQLITE_OMIT_LOAD_EXTENSION \ |
| 2179 | -DSQLITE_ENABLE_LOCKING_STYLE=0 \ |
| 2180 | -DSQLITE_DEFAULT_FILE_FORMAT=4 \ |
| 2181 | -DSQLITE_ENABLE_EXPLAIN_COMMENTS \ |
| 2182 | -DSQLITE_ENABLE_FTS4 \ |
| 2183 | -DSQLITE_ENABLE_FTS3_PARENTHESIS \ |
| 2184 |
| --- win/Makefile.mingw | |
| +++ win/Makefile.mingw | |
| @@ -2174,10 +2174,12 @@ | |
| 2174 | -DSQLITE_OMIT_DECLTYPE \ |
| 2175 | -DSQLITE_OMIT_DEPRECATED \ |
| 2176 | -DSQLITE_OMIT_PROGRESS_CALLBACK \ |
| 2177 | -DSQLITE_OMIT_SHARED_CACHE \ |
| 2178 | -DSQLITE_OMIT_LOAD_EXTENSION \ |
| 2179 | -DSQLITE_MAX_EXPR_DEPTH=0 \ |
| 2180 | -DSQLITE_USE_ALLOCA \ |
| 2181 | -DSQLITE_ENABLE_LOCKING_STYLE=0 \ |
| 2182 | -DSQLITE_DEFAULT_FILE_FORMAT=4 \ |
| 2183 | -DSQLITE_ENABLE_EXPLAIN_COMMENTS \ |
| 2184 | -DSQLITE_ENABLE_FTS4 \ |
| 2185 | -DSQLITE_ENABLE_FTS3_PARENTHESIS \ |
| 2186 |
+2
| --- win/Makefile.mingw | ||
| +++ win/Makefile.mingw | ||
| @@ -2174,10 +2174,12 @@ | ||
| 2174 | 2174 | -DSQLITE_OMIT_DECLTYPE \ |
| 2175 | 2175 | -DSQLITE_OMIT_DEPRECATED \ |
| 2176 | 2176 | -DSQLITE_OMIT_PROGRESS_CALLBACK \ |
| 2177 | 2177 | -DSQLITE_OMIT_SHARED_CACHE \ |
| 2178 | 2178 | -DSQLITE_OMIT_LOAD_EXTENSION \ |
| 2179 | + -DSQLITE_MAX_EXPR_DEPTH=0 \ | |
| 2180 | + -DSQLITE_USE_ALLOCA \ | |
| 2179 | 2181 | -DSQLITE_ENABLE_LOCKING_STYLE=0 \ |
| 2180 | 2182 | -DSQLITE_DEFAULT_FILE_FORMAT=4 \ |
| 2181 | 2183 | -DSQLITE_ENABLE_EXPLAIN_COMMENTS \ |
| 2182 | 2184 | -DSQLITE_ENABLE_FTS4 \ |
| 2183 | 2185 | -DSQLITE_ENABLE_FTS3_PARENTHESIS \ |
| 2184 | 2186 |
| --- win/Makefile.mingw | |
| +++ win/Makefile.mingw | |
| @@ -2174,10 +2174,12 @@ | |
| 2174 | -DSQLITE_OMIT_DECLTYPE \ |
| 2175 | -DSQLITE_OMIT_DEPRECATED \ |
| 2176 | -DSQLITE_OMIT_PROGRESS_CALLBACK \ |
| 2177 | -DSQLITE_OMIT_SHARED_CACHE \ |
| 2178 | -DSQLITE_OMIT_LOAD_EXTENSION \ |
| 2179 | -DSQLITE_ENABLE_LOCKING_STYLE=0 \ |
| 2180 | -DSQLITE_DEFAULT_FILE_FORMAT=4 \ |
| 2181 | -DSQLITE_ENABLE_EXPLAIN_COMMENTS \ |
| 2182 | -DSQLITE_ENABLE_FTS4 \ |
| 2183 | -DSQLITE_ENABLE_FTS3_PARENTHESIS \ |
| 2184 |
| --- win/Makefile.mingw | |
| +++ win/Makefile.mingw | |
| @@ -2174,10 +2174,12 @@ | |
| 2174 | -DSQLITE_OMIT_DECLTYPE \ |
| 2175 | -DSQLITE_OMIT_DEPRECATED \ |
| 2176 | -DSQLITE_OMIT_PROGRESS_CALLBACK \ |
| 2177 | -DSQLITE_OMIT_SHARED_CACHE \ |
| 2178 | -DSQLITE_OMIT_LOAD_EXTENSION \ |
| 2179 | -DSQLITE_MAX_EXPR_DEPTH=0 \ |
| 2180 | -DSQLITE_USE_ALLOCA \ |
| 2181 | -DSQLITE_ENABLE_LOCKING_STYLE=0 \ |
| 2182 | -DSQLITE_DEFAULT_FILE_FORMAT=4 \ |
| 2183 | -DSQLITE_ENABLE_EXPLAIN_COMMENTS \ |
| 2184 | -DSQLITE_ENABLE_FTS4 \ |
| 2185 | -DSQLITE_ENABLE_FTS3_PARENTHESIS \ |
| 2186 |
| --- win/Makefile.mingw.mistachkin | ||
| +++ win/Makefile.mingw.mistachkin | ||
| @@ -2174,10 +2174,12 @@ | ||
| 2174 | 2174 | -DSQLITE_OMIT_DECLTYPE \ |
| 2175 | 2175 | -DSQLITE_OMIT_DEPRECATED \ |
| 2176 | 2176 | -DSQLITE_OMIT_PROGRESS_CALLBACK \ |
| 2177 | 2177 | -DSQLITE_OMIT_SHARED_CACHE \ |
| 2178 | 2178 | -DSQLITE_OMIT_LOAD_EXTENSION \ |
| 2179 | + -DSQLITE_MAX_EXPR_DEPTH=0 \ | |
| 2180 | + -DSQLITE_USE_ALLOCA \ | |
| 2179 | 2181 | -DSQLITE_ENABLE_LOCKING_STYLE=0 \ |
| 2180 | 2182 | -DSQLITE_DEFAULT_FILE_FORMAT=4 \ |
| 2181 | 2183 | -DSQLITE_ENABLE_EXPLAIN_COMMENTS \ |
| 2182 | 2184 | -DSQLITE_ENABLE_FTS4 \ |
| 2183 | 2185 | -DSQLITE_ENABLE_FTS3_PARENTHESIS \ |
| 2184 | 2186 |
| --- win/Makefile.mingw.mistachkin | |
| +++ win/Makefile.mingw.mistachkin | |
| @@ -2174,10 +2174,12 @@ | |
| 2174 | -DSQLITE_OMIT_DECLTYPE \ |
| 2175 | -DSQLITE_OMIT_DEPRECATED \ |
| 2176 | -DSQLITE_OMIT_PROGRESS_CALLBACK \ |
| 2177 | -DSQLITE_OMIT_SHARED_CACHE \ |
| 2178 | -DSQLITE_OMIT_LOAD_EXTENSION \ |
| 2179 | -DSQLITE_ENABLE_LOCKING_STYLE=0 \ |
| 2180 | -DSQLITE_DEFAULT_FILE_FORMAT=4 \ |
| 2181 | -DSQLITE_ENABLE_EXPLAIN_COMMENTS \ |
| 2182 | -DSQLITE_ENABLE_FTS4 \ |
| 2183 | -DSQLITE_ENABLE_FTS3_PARENTHESIS \ |
| 2184 |
| --- win/Makefile.mingw.mistachkin | |
| +++ win/Makefile.mingw.mistachkin | |
| @@ -2174,10 +2174,12 @@ | |
| 2174 | -DSQLITE_OMIT_DECLTYPE \ |
| 2175 | -DSQLITE_OMIT_DEPRECATED \ |
| 2176 | -DSQLITE_OMIT_PROGRESS_CALLBACK \ |
| 2177 | -DSQLITE_OMIT_SHARED_CACHE \ |
| 2178 | -DSQLITE_OMIT_LOAD_EXTENSION \ |
| 2179 | -DSQLITE_MAX_EXPR_DEPTH=0 \ |
| 2180 | -DSQLITE_USE_ALLOCA \ |
| 2181 | -DSQLITE_ENABLE_LOCKING_STYLE=0 \ |
| 2182 | -DSQLITE_DEFAULT_FILE_FORMAT=4 \ |
| 2183 | -DSQLITE_ENABLE_EXPLAIN_COMMENTS \ |
| 2184 | -DSQLITE_ENABLE_FTS4 \ |
| 2185 | -DSQLITE_ENABLE_FTS3_PARENTHESIS \ |
| 2186 |
| --- win/Makefile.mingw.mistachkin | ||
| +++ win/Makefile.mingw.mistachkin | ||
| @@ -2174,10 +2174,12 @@ | ||
| 2174 | 2174 | -DSQLITE_OMIT_DECLTYPE \ |
| 2175 | 2175 | -DSQLITE_OMIT_DEPRECATED \ |
| 2176 | 2176 | -DSQLITE_OMIT_PROGRESS_CALLBACK \ |
| 2177 | 2177 | -DSQLITE_OMIT_SHARED_CACHE \ |
| 2178 | 2178 | -DSQLITE_OMIT_LOAD_EXTENSION \ |
| 2179 | + -DSQLITE_MAX_EXPR_DEPTH=0 \ | |
| 2180 | + -DSQLITE_USE_ALLOCA \ | |
| 2179 | 2181 | -DSQLITE_ENABLE_LOCKING_STYLE=0 \ |
| 2180 | 2182 | -DSQLITE_DEFAULT_FILE_FORMAT=4 \ |
| 2181 | 2183 | -DSQLITE_ENABLE_EXPLAIN_COMMENTS \ |
| 2182 | 2184 | -DSQLITE_ENABLE_FTS4 \ |
| 2183 | 2185 | -DSQLITE_ENABLE_FTS3_PARENTHESIS \ |
| 2184 | 2186 |
| --- win/Makefile.mingw.mistachkin | |
| +++ win/Makefile.mingw.mistachkin | |
| @@ -2174,10 +2174,12 @@ | |
| 2174 | -DSQLITE_OMIT_DECLTYPE \ |
| 2175 | -DSQLITE_OMIT_DEPRECATED \ |
| 2176 | -DSQLITE_OMIT_PROGRESS_CALLBACK \ |
| 2177 | -DSQLITE_OMIT_SHARED_CACHE \ |
| 2178 | -DSQLITE_OMIT_LOAD_EXTENSION \ |
| 2179 | -DSQLITE_ENABLE_LOCKING_STYLE=0 \ |
| 2180 | -DSQLITE_DEFAULT_FILE_FORMAT=4 \ |
| 2181 | -DSQLITE_ENABLE_EXPLAIN_COMMENTS \ |
| 2182 | -DSQLITE_ENABLE_FTS4 \ |
| 2183 | -DSQLITE_ENABLE_FTS3_PARENTHESIS \ |
| 2184 |
| --- win/Makefile.mingw.mistachkin | |
| +++ win/Makefile.mingw.mistachkin | |
| @@ -2174,10 +2174,12 @@ | |
| 2174 | -DSQLITE_OMIT_DECLTYPE \ |
| 2175 | -DSQLITE_OMIT_DEPRECATED \ |
| 2176 | -DSQLITE_OMIT_PROGRESS_CALLBACK \ |
| 2177 | -DSQLITE_OMIT_SHARED_CACHE \ |
| 2178 | -DSQLITE_OMIT_LOAD_EXTENSION \ |
| 2179 | -DSQLITE_MAX_EXPR_DEPTH=0 \ |
| 2180 | -DSQLITE_USE_ALLOCA \ |
| 2181 | -DSQLITE_ENABLE_LOCKING_STYLE=0 \ |
| 2182 | -DSQLITE_DEFAULT_FILE_FORMAT=4 \ |
| 2183 | -DSQLITE_ENABLE_EXPLAIN_COMMENTS \ |
| 2184 | -DSQLITE_ENABLE_FTS4 \ |
| 2185 | -DSQLITE_ENABLE_FTS3_PARENTHESIS \ |
| 2186 |
+2
| --- win/Makefile.msc | ||
| +++ win/Makefile.msc | ||
| @@ -321,10 +321,12 @@ | ||
| 321 | 321 | /DSQLITE_OMIT_DECLTYPE \ |
| 322 | 322 | /DSQLITE_OMIT_DEPRECATED \ |
| 323 | 323 | /DSQLITE_OMIT_PROGRESS_CALLBACK \ |
| 324 | 324 | /DSQLITE_OMIT_SHARED_CACHE \ |
| 325 | 325 | /DSQLITE_OMIT_LOAD_EXTENSION \ |
| 326 | + /DSQLITE_MAX_EXPR_DEPTH=0 \ | |
| 327 | + /DSQLITE_USE_ALLOCA \ | |
| 326 | 328 | /DSQLITE_ENABLE_LOCKING_STYLE=0 \ |
| 327 | 329 | /DSQLITE_DEFAULT_FILE_FORMAT=4 \ |
| 328 | 330 | /DSQLITE_ENABLE_EXPLAIN_COMMENTS \ |
| 329 | 331 | /DSQLITE_ENABLE_FTS4 \ |
| 330 | 332 | /DSQLITE_ENABLE_FTS3_PARENTHESIS \ |
| 331 | 333 |
| --- win/Makefile.msc | |
| +++ win/Makefile.msc | |
| @@ -321,10 +321,12 @@ | |
| 321 | /DSQLITE_OMIT_DECLTYPE \ |
| 322 | /DSQLITE_OMIT_DEPRECATED \ |
| 323 | /DSQLITE_OMIT_PROGRESS_CALLBACK \ |
| 324 | /DSQLITE_OMIT_SHARED_CACHE \ |
| 325 | /DSQLITE_OMIT_LOAD_EXTENSION \ |
| 326 | /DSQLITE_ENABLE_LOCKING_STYLE=0 \ |
| 327 | /DSQLITE_DEFAULT_FILE_FORMAT=4 \ |
| 328 | /DSQLITE_ENABLE_EXPLAIN_COMMENTS \ |
| 329 | /DSQLITE_ENABLE_FTS4 \ |
| 330 | /DSQLITE_ENABLE_FTS3_PARENTHESIS \ |
| 331 |
| --- win/Makefile.msc | |
| +++ win/Makefile.msc | |
| @@ -321,10 +321,12 @@ | |
| 321 | /DSQLITE_OMIT_DECLTYPE \ |
| 322 | /DSQLITE_OMIT_DEPRECATED \ |
| 323 | /DSQLITE_OMIT_PROGRESS_CALLBACK \ |
| 324 | /DSQLITE_OMIT_SHARED_CACHE \ |
| 325 | /DSQLITE_OMIT_LOAD_EXTENSION \ |
| 326 | /DSQLITE_MAX_EXPR_DEPTH=0 \ |
| 327 | /DSQLITE_USE_ALLOCA \ |
| 328 | /DSQLITE_ENABLE_LOCKING_STYLE=0 \ |
| 329 | /DSQLITE_DEFAULT_FILE_FORMAT=4 \ |
| 330 | /DSQLITE_ENABLE_EXPLAIN_COMMENTS \ |
| 331 | /DSQLITE_ENABLE_FTS4 \ |
| 332 | /DSQLITE_ENABLE_FTS3_PARENTHESIS \ |
| 333 |
+2
| --- win/Makefile.msc | ||
| +++ win/Makefile.msc | ||
| @@ -321,10 +321,12 @@ | ||
| 321 | 321 | /DSQLITE_OMIT_DECLTYPE \ |
| 322 | 322 | /DSQLITE_OMIT_DEPRECATED \ |
| 323 | 323 | /DSQLITE_OMIT_PROGRESS_CALLBACK \ |
| 324 | 324 | /DSQLITE_OMIT_SHARED_CACHE \ |
| 325 | 325 | /DSQLITE_OMIT_LOAD_EXTENSION \ |
| 326 | + /DSQLITE_MAX_EXPR_DEPTH=0 \ | |
| 327 | + /DSQLITE_USE_ALLOCA \ | |
| 326 | 328 | /DSQLITE_ENABLE_LOCKING_STYLE=0 \ |
| 327 | 329 | /DSQLITE_DEFAULT_FILE_FORMAT=4 \ |
| 328 | 330 | /DSQLITE_ENABLE_EXPLAIN_COMMENTS \ |
| 329 | 331 | /DSQLITE_ENABLE_FTS4 \ |
| 330 | 332 | /DSQLITE_ENABLE_FTS3_PARENTHESIS \ |
| 331 | 333 |
| --- win/Makefile.msc | |
| +++ win/Makefile.msc | |
| @@ -321,10 +321,12 @@ | |
| 321 | /DSQLITE_OMIT_DECLTYPE \ |
| 322 | /DSQLITE_OMIT_DEPRECATED \ |
| 323 | /DSQLITE_OMIT_PROGRESS_CALLBACK \ |
| 324 | /DSQLITE_OMIT_SHARED_CACHE \ |
| 325 | /DSQLITE_OMIT_LOAD_EXTENSION \ |
| 326 | /DSQLITE_ENABLE_LOCKING_STYLE=0 \ |
| 327 | /DSQLITE_DEFAULT_FILE_FORMAT=4 \ |
| 328 | /DSQLITE_ENABLE_EXPLAIN_COMMENTS \ |
| 329 | /DSQLITE_ENABLE_FTS4 \ |
| 330 | /DSQLITE_ENABLE_FTS3_PARENTHESIS \ |
| 331 |
| --- win/Makefile.msc | |
| +++ win/Makefile.msc | |
| @@ -321,10 +321,12 @@ | |
| 321 | /DSQLITE_OMIT_DECLTYPE \ |
| 322 | /DSQLITE_OMIT_DEPRECATED \ |
| 323 | /DSQLITE_OMIT_PROGRESS_CALLBACK \ |
| 324 | /DSQLITE_OMIT_SHARED_CACHE \ |
| 325 | /DSQLITE_OMIT_LOAD_EXTENSION \ |
| 326 | /DSQLITE_MAX_EXPR_DEPTH=0 \ |
| 327 | /DSQLITE_USE_ALLOCA \ |
| 328 | /DSQLITE_ENABLE_LOCKING_STYLE=0 \ |
| 329 | /DSQLITE_DEFAULT_FILE_FORMAT=4 \ |
| 330 | /DSQLITE_ENABLE_EXPLAIN_COMMENTS \ |
| 331 | /DSQLITE_ENABLE_FTS4 \ |
| 332 | /DSQLITE_ENABLE_FTS3_PARENTHESIS \ |
| 333 |
+11
-11
| --- www/aboutcgi.wiki | ||
| +++ www/aboutcgi.wiki | ||
| @@ -66,11 +66,11 @@ | ||
| 66 | 66 | <p> |
| 67 | 67 | In addition to setting various CGI environment variables, if the HTTP |
| 68 | 68 | request contains POST content, then the web server relays the POST content |
| 69 | 69 | to standard input of the CGI script. |
| 70 | 70 | <p> |
| 71 | -In summary, the task of the | |
| 71 | +In summary, the task of the | |
| 72 | 72 | CGI script is to read the various CGI environment variables and |
| 73 | 73 | the POST content on standard input (if any), figure out an appropriate |
| 74 | 74 | reply, then write that reply on standard output. |
| 75 | 75 | The web server will read the output from the CGI script, reformat it |
| 76 | 76 | into an appropriate HTTP reply, and relay the result back to the |
| @@ -89,31 +89,31 @@ | ||
| 89 | 89 | like the following: |
| 90 | 90 | <blockquote><pre> |
| 91 | 91 | #!/usr/bin/fossil |
| 92 | 92 | repository: /home/www/repos/project.fossil |
| 93 | 93 | </pre></blockquote> |
| 94 | -The first line of the script is a | |
| 94 | +The first line of the script is a | |
| 95 | 95 | "[https://en.wikipedia.org/wiki/Shebang_%28Unix%29|shebang]" |
| 96 | 96 | that tells the operating system what program to use as the interpreter |
| 97 | 97 | for this script. On unix, when you execute a script that starts with |
| 98 | 98 | a shebang, the operating system runs the program identified by the |
| 99 | -shebang with a single argument that is the full pathname of the script | |
| 99 | +shebang with a single argument that is the full pathname of the script | |
| 100 | 100 | itself. |
| 101 | 101 | In our example, the interpreter is Fossil, and the argument might |
| 102 | 102 | be something like "/var/www/cgi-bin/one/two" (depending on how your |
| 103 | 103 | particular web server is configured). |
| 104 | 104 | <p> |
| 105 | 105 | The Fossil program that is run as the script interpreter |
| 106 | 106 | is the same Fossil that runs when |
| 107 | 107 | you type ordinary Fossil commands like "fossil sync" or "fossil commit". |
| 108 | 108 | But in this case, as soon as it launches, the Fossil program |
| 109 | -recognizes that the GATEWAY_INTERFACE environment variable is | |
| 109 | +recognizes that the GATEWAY_INTERFACE environment variable is | |
| 110 | 110 | set to "CGI/1.0" and it therefore knows that it is being used as |
| 111 | 111 | CGI rather than as an ordinary command-line tool, and behaves accordingly. |
| 112 | 112 | <p> |
| 113 | 113 | When Fossil recognizes that it is being run as CGI, it opens and reads |
| 114 | -the file identified by its sole argument (the file named by | |
| 114 | +the file identified by its sole argument (the file named by | |
| 115 | 115 | <code>argv[1]</code>). In our example, the second line of that file |
| 116 | 116 | tells Fossil the location of the repository it will be serving. |
| 117 | 117 | Fossil then starts looking at the CGI environment variables to figure |
| 118 | 118 | out what web page is being requested, generates that one web page, |
| 119 | 119 | then exits. |
| @@ -130,12 +130,12 @@ | ||
| 130 | 130 | <ol type='A'> |
| 131 | 131 | <li> [https://www.fossil-scm.org/fossil/info/c14ecc43] |
| 132 | 132 | <li> [https://www.fossil-scm.org/fossil/info?name=c14ecc43] |
| 133 | 133 | </ol> |
| 134 | 134 | In both cases, the CGI script is called "/fossil". For case (A), |
| 135 | -the PATH_INFO variable will be "info/c14ecc43" and so the | |
| 136 | -"[/help?cmd=/info]" webpage will be generated and the suffix of | |
| 135 | +the PATH_INFO variable will be "info/c14ecc43" and so the | |
| 136 | +"[/help?cmd=/info|/info]" webpage will be generated and the suffix of | |
| 137 | 137 | PATH_INFO will be converted into the "name" query parameter, which |
| 138 | 138 | identifies the artifact about which information is requested. |
| 139 | 139 | In case (B), the PATH_INFO is just "info", but the same "name" |
| 140 | 140 | query parameter is set explicitly by the URL itself. |
| 141 | 141 | </blockquote> |
| @@ -164,11 +164,11 @@ | ||
| 164 | 164 | <blockquote> |
| 165 | 165 | <b>http://example.com/cgis/example2/subdir/three/timeline</b> |
| 166 | 166 | </blockquote> |
| 167 | 167 | Here is what happens: |
| 168 | 168 | <ol> |
| 169 | -<li> The input URI on the HTTP request is | |
| 169 | +<li> The input URI on the HTTP request is | |
| 170 | 170 | <b>/cgis/example2/subdir/three/timeline</b> |
| 171 | 171 | <li> The web server searches prefixes of the input URI until it finds |
| 172 | 172 | the "cgis/example2" script. The web server then sets |
| 173 | 173 | PATH_INFO to the "subdir/three/timeline" suffix and invokes the |
| 174 | 174 | "cgis/example2" script. |
| @@ -175,11 +175,11 @@ | ||
| 175 | 175 | <li> Fossil runs and sees the "directory:" line pointing to |
| 176 | 176 | "/home/www/repos". Fossil then starts pulling terms off the |
| 177 | 177 | front of the PATH_INFO looking for a repository. It first looks |
| 178 | 178 | at "/home/www/resps/subdir.fossil" but there is no such repository. |
| 179 | 179 | So then it looks at "/home/www/repos/subdir/three.fossil" and finds |
| 180 | - a repository. The PATH_INFO is shortened by removing | |
| 180 | + a repository. The PATH_INFO is shortened by removing | |
| 181 | 181 | "subdir/three/" leaving it at just "timeline". |
| 182 | 182 | <li> Fossil looks at the rest of PATH_INFO to see that the webpage |
| 183 | 183 | requested is "timeline". |
| 184 | 184 | </ol> |
| 185 | 185 | </blockquote> |
| @@ -201,14 +201,14 @@ | ||
| 201 | 201 | and has a value. |
| 202 | 202 | <li><p> |
| 203 | 203 | The "[/help?cmd=ui|fossil ui]" and "[/help?cmd=server|fossil server]" commands |
| 204 | 204 | are implemented using a simple built-in web server that accepts incoming HTTP |
| 205 | 205 | requests, translates each request into a CGI invocation, then creates a |
| 206 | -separate child Fossil process to handle each request. In other words, CGI | |
| 206 | +separate child Fossil process to handle each request. In other words, CGI | |
| 207 | 207 | is used internally to implement "fossil ui/server". |
| 208 | 208 | <p> |
| 209 | 209 | SCGI is processed using the same built-in web server, just modified |
| 210 | 210 | to parse SCGI requests instead of HTTP requests. Each SCGI request is |
| 211 | -converted into CGI, then Fossil creates a separate child Fossil | |
| 211 | +converted into CGI, then Fossil creates a separate child Fossil | |
| 212 | 212 | process to handle each CGI request. |
| 213 | 213 | </ol> |
| 214 | 214 | </blockquote> |
| 215 | 215 |
| --- www/aboutcgi.wiki | |
| +++ www/aboutcgi.wiki | |
| @@ -66,11 +66,11 @@ | |
| 66 | <p> |
| 67 | In addition to setting various CGI environment variables, if the HTTP |
| 68 | request contains POST content, then the web server relays the POST content |
| 69 | to standard input of the CGI script. |
| 70 | <p> |
| 71 | In summary, the task of the |
| 72 | CGI script is to read the various CGI environment variables and |
| 73 | the POST content on standard input (if any), figure out an appropriate |
| 74 | reply, then write that reply on standard output. |
| 75 | The web server will read the output from the CGI script, reformat it |
| 76 | into an appropriate HTTP reply, and relay the result back to the |
| @@ -89,31 +89,31 @@ | |
| 89 | like the following: |
| 90 | <blockquote><pre> |
| 91 | #!/usr/bin/fossil |
| 92 | repository: /home/www/repos/project.fossil |
| 93 | </pre></blockquote> |
| 94 | The first line of the script is a |
| 95 | "[https://en.wikipedia.org/wiki/Shebang_%28Unix%29|shebang]" |
| 96 | that tells the operating system what program to use as the interpreter |
| 97 | for this script. On unix, when you execute a script that starts with |
| 98 | a shebang, the operating system runs the program identified by the |
| 99 | shebang with a single argument that is the full pathname of the script |
| 100 | itself. |
| 101 | In our example, the interpreter is Fossil, and the argument might |
| 102 | be something like "/var/www/cgi-bin/one/two" (depending on how your |
| 103 | particular web server is configured). |
| 104 | <p> |
| 105 | The Fossil program that is run as the script interpreter |
| 106 | is the same Fossil that runs when |
| 107 | you type ordinary Fossil commands like "fossil sync" or "fossil commit". |
| 108 | But in this case, as soon as it launches, the Fossil program |
| 109 | recognizes that the GATEWAY_INTERFACE environment variable is |
| 110 | set to "CGI/1.0" and it therefore knows that it is being used as |
| 111 | CGI rather than as an ordinary command-line tool, and behaves accordingly. |
| 112 | <p> |
| 113 | When Fossil recognizes that it is being run as CGI, it opens and reads |
| 114 | the file identified by its sole argument (the file named by |
| 115 | <code>argv[1]</code>). In our example, the second line of that file |
| 116 | tells Fossil the location of the repository it will be serving. |
| 117 | Fossil then starts looking at the CGI environment variables to figure |
| 118 | out what web page is being requested, generates that one web page, |
| 119 | then exits. |
| @@ -130,12 +130,12 @@ | |
| 130 | <ol type='A'> |
| 131 | <li> [https://www.fossil-scm.org/fossil/info/c14ecc43] |
| 132 | <li> [https://www.fossil-scm.org/fossil/info?name=c14ecc43] |
| 133 | </ol> |
| 134 | In both cases, the CGI script is called "/fossil". For case (A), |
| 135 | the PATH_INFO variable will be "info/c14ecc43" and so the |
| 136 | "[/help?cmd=/info]" webpage will be generated and the suffix of |
| 137 | PATH_INFO will be converted into the "name" query parameter, which |
| 138 | identifies the artifact about which information is requested. |
| 139 | In case (B), the PATH_INFO is just "info", but the same "name" |
| 140 | query parameter is set explicitly by the URL itself. |
| 141 | </blockquote> |
| @@ -164,11 +164,11 @@ | |
| 164 | <blockquote> |
| 165 | <b>http://example.com/cgis/example2/subdir/three/timeline</b> |
| 166 | </blockquote> |
| 167 | Here is what happens: |
| 168 | <ol> |
| 169 | <li> The input URI on the HTTP request is |
| 170 | <b>/cgis/example2/subdir/three/timeline</b> |
| 171 | <li> The web server searches prefixes of the input URI until it finds |
| 172 | the "cgis/example2" script. The web server then sets |
| 173 | PATH_INFO to the "subdir/three/timeline" suffix and invokes the |
| 174 | "cgis/example2" script. |
| @@ -175,11 +175,11 @@ | |
| 175 | <li> Fossil runs and sees the "directory:" line pointing to |
| 176 | "/home/www/repos". Fossil then starts pulling terms off the |
| 177 | front of the PATH_INFO looking for a repository. It first looks |
| 178 | at "/home/www/resps/subdir.fossil" but there is no such repository. |
| 179 | So then it looks at "/home/www/repos/subdir/three.fossil" and finds |
| 180 | a repository. The PATH_INFO is shortened by removing |
| 181 | "subdir/three/" leaving it at just "timeline". |
| 182 | <li> Fossil looks at the rest of PATH_INFO to see that the webpage |
| 183 | requested is "timeline". |
| 184 | </ol> |
| 185 | </blockquote> |
| @@ -201,14 +201,14 @@ | |
| 201 | and has a value. |
| 202 | <li><p> |
| 203 | The "[/help?cmd=ui|fossil ui]" and "[/help?cmd=server|fossil server]" commands |
| 204 | are implemented using a simple built-in web server that accepts incoming HTTP |
| 205 | requests, translates each request into a CGI invocation, then creates a |
| 206 | separate child Fossil process to handle each request. In other words, CGI |
| 207 | is used internally to implement "fossil ui/server". |
| 208 | <p> |
| 209 | SCGI is processed using the same built-in web server, just modified |
| 210 | to parse SCGI requests instead of HTTP requests. Each SCGI request is |
| 211 | converted into CGI, then Fossil creates a separate child Fossil |
| 212 | process to handle each CGI request. |
| 213 | </ol> |
| 214 | </blockquote> |
| 215 |
| --- www/aboutcgi.wiki | |
| +++ www/aboutcgi.wiki | |
| @@ -66,11 +66,11 @@ | |
| 66 | <p> |
| 67 | In addition to setting various CGI environment variables, if the HTTP |
| 68 | request contains POST content, then the web server relays the POST content |
| 69 | to standard input of the CGI script. |
| 70 | <p> |
| 71 | In summary, the task of the |
| 72 | CGI script is to read the various CGI environment variables and |
| 73 | the POST content on standard input (if any), figure out an appropriate |
| 74 | reply, then write that reply on standard output. |
| 75 | The web server will read the output from the CGI script, reformat it |
| 76 | into an appropriate HTTP reply, and relay the result back to the |
| @@ -89,31 +89,31 @@ | |
| 89 | like the following: |
| 90 | <blockquote><pre> |
| 91 | #!/usr/bin/fossil |
| 92 | repository: /home/www/repos/project.fossil |
| 93 | </pre></blockquote> |
| 94 | The first line of the script is a |
| 95 | "[https://en.wikipedia.org/wiki/Shebang_%28Unix%29|shebang]" |
| 96 | that tells the operating system what program to use as the interpreter |
| 97 | for this script. On unix, when you execute a script that starts with |
| 98 | a shebang, the operating system runs the program identified by the |
| 99 | shebang with a single argument that is the full pathname of the script |
| 100 | itself. |
| 101 | In our example, the interpreter is Fossil, and the argument might |
| 102 | be something like "/var/www/cgi-bin/one/two" (depending on how your |
| 103 | particular web server is configured). |
| 104 | <p> |
| 105 | The Fossil program that is run as the script interpreter |
| 106 | is the same Fossil that runs when |
| 107 | you type ordinary Fossil commands like "fossil sync" or "fossil commit". |
| 108 | But in this case, as soon as it launches, the Fossil program |
| 109 | recognizes that the GATEWAY_INTERFACE environment variable is |
| 110 | set to "CGI/1.0" and it therefore knows that it is being used as |
| 111 | CGI rather than as an ordinary command-line tool, and behaves accordingly. |
| 112 | <p> |
| 113 | When Fossil recognizes that it is being run as CGI, it opens and reads |
| 114 | the file identified by its sole argument (the file named by |
| 115 | <code>argv[1]</code>). In our example, the second line of that file |
| 116 | tells Fossil the location of the repository it will be serving. |
| 117 | Fossil then starts looking at the CGI environment variables to figure |
| 118 | out what web page is being requested, generates that one web page, |
| 119 | then exits. |
| @@ -130,12 +130,12 @@ | |
| 130 | <ol type='A'> |
| 131 | <li> [https://www.fossil-scm.org/fossil/info/c14ecc43] |
| 132 | <li> [https://www.fossil-scm.org/fossil/info?name=c14ecc43] |
| 133 | </ol> |
| 134 | In both cases, the CGI script is called "/fossil". For case (A), |
| 135 | the PATH_INFO variable will be "info/c14ecc43" and so the |
| 136 | "[/help?cmd=/info|/info]" webpage will be generated and the suffix of |
| 137 | PATH_INFO will be converted into the "name" query parameter, which |
| 138 | identifies the artifact about which information is requested. |
| 139 | In case (B), the PATH_INFO is just "info", but the same "name" |
| 140 | query parameter is set explicitly by the URL itself. |
| 141 | </blockquote> |
| @@ -164,11 +164,11 @@ | |
| 164 | <blockquote> |
| 165 | <b>http://example.com/cgis/example2/subdir/three/timeline</b> |
| 166 | </blockquote> |
| 167 | Here is what happens: |
| 168 | <ol> |
| 169 | <li> The input URI on the HTTP request is |
| 170 | <b>/cgis/example2/subdir/three/timeline</b> |
| 171 | <li> The web server searches prefixes of the input URI until it finds |
| 172 | the "cgis/example2" script. The web server then sets |
| 173 | PATH_INFO to the "subdir/three/timeline" suffix and invokes the |
| 174 | "cgis/example2" script. |
| @@ -175,11 +175,11 @@ | |
| 175 | <li> Fossil runs and sees the "directory:" line pointing to |
| 176 | "/home/www/repos". Fossil then starts pulling terms off the |
| 177 | front of the PATH_INFO looking for a repository. It first looks |
| 178 | at "/home/www/resps/subdir.fossil" but there is no such repository. |
| 179 | So then it looks at "/home/www/repos/subdir/three.fossil" and finds |
| 180 | a repository. The PATH_INFO is shortened by removing |
| 181 | "subdir/three/" leaving it at just "timeline". |
| 182 | <li> Fossil looks at the rest of PATH_INFO to see that the webpage |
| 183 | requested is "timeline". |
| 184 | </ol> |
| 185 | </blockquote> |
| @@ -201,14 +201,14 @@ | |
| 201 | and has a value. |
| 202 | <li><p> |
| 203 | The "[/help?cmd=ui|fossil ui]" and "[/help?cmd=server|fossil server]" commands |
| 204 | are implemented using a simple built-in web server that accepts incoming HTTP |
| 205 | requests, translates each request into a CGI invocation, then creates a |
| 206 | separate child Fossil process to handle each request. In other words, CGI |
| 207 | is used internally to implement "fossil ui/server". |
| 208 | <p> |
| 209 | SCGI is processed using the same built-in web server, just modified |
| 210 | to parse SCGI requests instead of HTTP requests. Each SCGI request is |
| 211 | converted into CGI, then Fossil creates a separate child Fossil |
| 212 | process to handle each CGI request. |
| 213 | </ol> |
| 214 | </blockquote> |
| 215 |
+5
-5
| --- www/adding_code.wiki | ||
| +++ www/adding_code.wiki | ||
| @@ -22,11 +22,11 @@ | ||
| 22 | 22 | |
| 23 | 23 | 2. The <b>makeheaders</b> preprocessor generates all the ".h" files |
| 24 | 24 | automatically. Fossil programmers write ".c" files only and let the |
| 25 | 25 | makeheaders preprocessor create the ".h" files. |
| 26 | 26 | |
| 27 | - 3. The <b>translate</b> preprocessor converts source code lines that | |
| 27 | + 3. The <b>translate</b> preprocessor converts source code lines that | |
| 28 | 28 | begin with "@" into string literals, or into print statements that |
| 29 | 29 | generate web page output, depending on context. |
| 30 | 30 | |
| 31 | 31 | The [./makefile.wiki|Makefile] for Fossil takes care of running these |
| 32 | 32 | preprocessors with all the right arguments and in the right order. So it is |
| @@ -39,13 +39,13 @@ | ||
| 39 | 39 | <h2>3.0 Adding New Source Code Files</h2> |
| 40 | 40 | |
| 41 | 41 | New source code files are added in the "src/" subdirectory of the Fossil |
| 42 | 42 | source tree. Suppose one wants to add a new source code file named |
| 43 | 43 | "xyzzy.c". The first step is to add this file to the various makefiles. |
| 44 | -Do so by editing the file src/makemake.tcl and adding "xyzzy" (without | |
| 44 | +Do so by editing the file src/makemake.tcl and adding "xyzzy" (without | |
| 45 | 45 | the final ".c") to the list of source modules at the top of that script. |
| 46 | -Save the result and then run the makemake.tcl script using a TCL | |
| 46 | +Save the result and then run the makemake.tcl script using a TCL | |
| 47 | 47 | interpreter. The command to run the makemake.tcl script is: |
| 48 | 48 | |
| 49 | 49 | <b>tclsh makemake.tcl</b> |
| 50 | 50 | |
| 51 | 51 | The working directory must be src/ when the command above is run. |
| @@ -60,11 +60,11 @@ | ||
| 60 | 60 | |
| 61 | 61 | <blockquote><verbatim> |
| 62 | 62 | /* |
| 63 | 63 | ** Copyright boilerplate goes here. |
| 64 | 64 | ***************************************************** |
| 65 | -** High-level description of what this module goes | |
| 65 | +** High-level description of what this module goes | |
| 66 | 66 | ** here. |
| 67 | 67 | */ |
| 68 | 68 | #include "config.h" |
| 69 | 69 | #include "xyzzy.h" |
| 70 | 70 | |
| @@ -83,11 +83,11 @@ | ||
| 83 | 83 | exceptions to this rule. Don't worry about those exceptions. The |
| 84 | 84 | files you write will require this #include line.) |
| 85 | 85 | |
| 86 | 86 | The "#if INTERFACE ... #endif" section is optional and is only needed |
| 87 | 87 | if there are structure definitions or typedefs or macros that need to |
| 88 | -be used by other source code files. The makeheaders preprocessor | |
| 88 | +be used by other source code files. The makeheaders preprocessor | |
| 89 | 89 | uses definitions in the INTERFACE section to help it generate header |
| 90 | 90 | files. See [../src/makeheaders.html | makeheaders.html] for additional |
| 91 | 91 | information. |
| 92 | 92 | |
| 93 | 93 | After creating a template file such as shown above, and after updating |
| 94 | 94 |
| --- www/adding_code.wiki | |
| +++ www/adding_code.wiki | |
| @@ -22,11 +22,11 @@ | |
| 22 | |
| 23 | 2. The <b>makeheaders</b> preprocessor generates all the ".h" files |
| 24 | automatically. Fossil programmers write ".c" files only and let the |
| 25 | makeheaders preprocessor create the ".h" files. |
| 26 | |
| 27 | 3. The <b>translate</b> preprocessor converts source code lines that |
| 28 | begin with "@" into string literals, or into print statements that |
| 29 | generate web page output, depending on context. |
| 30 | |
| 31 | The [./makefile.wiki|Makefile] for Fossil takes care of running these |
| 32 | preprocessors with all the right arguments and in the right order. So it is |
| @@ -39,13 +39,13 @@ | |
| 39 | <h2>3.0 Adding New Source Code Files</h2> |
| 40 | |
| 41 | New source code files are added in the "src/" subdirectory of the Fossil |
| 42 | source tree. Suppose one wants to add a new source code file named |
| 43 | "xyzzy.c". The first step is to add this file to the various makefiles. |
| 44 | Do so by editing the file src/makemake.tcl and adding "xyzzy" (without |
| 45 | the final ".c") to the list of source modules at the top of that script. |
| 46 | Save the result and then run the makemake.tcl script using a TCL |
| 47 | interpreter. The command to run the makemake.tcl script is: |
| 48 | |
| 49 | <b>tclsh makemake.tcl</b> |
| 50 | |
| 51 | The working directory must be src/ when the command above is run. |
| @@ -60,11 +60,11 @@ | |
| 60 | |
| 61 | <blockquote><verbatim> |
| 62 | /* |
| 63 | ** Copyright boilerplate goes here. |
| 64 | ***************************************************** |
| 65 | ** High-level description of what this module goes |
| 66 | ** here. |
| 67 | */ |
| 68 | #include "config.h" |
| 69 | #include "xyzzy.h" |
| 70 | |
| @@ -83,11 +83,11 @@ | |
| 83 | exceptions to this rule. Don't worry about those exceptions. The |
| 84 | files you write will require this #include line.) |
| 85 | |
| 86 | The "#if INTERFACE ... #endif" section is optional and is only needed |
| 87 | if there are structure definitions or typedefs or macros that need to |
| 88 | be used by other source code files. The makeheaders preprocessor |
| 89 | uses definitions in the INTERFACE section to help it generate header |
| 90 | files. See [../src/makeheaders.html | makeheaders.html] for additional |
| 91 | information. |
| 92 | |
| 93 | After creating a template file such as shown above, and after updating |
| 94 |
| --- www/adding_code.wiki | |
| +++ www/adding_code.wiki | |
| @@ -22,11 +22,11 @@ | |
| 22 | |
| 23 | 2. The <b>makeheaders</b> preprocessor generates all the ".h" files |
| 24 | automatically. Fossil programmers write ".c" files only and let the |
| 25 | makeheaders preprocessor create the ".h" files. |
| 26 | |
| 27 | 3. The <b>translate</b> preprocessor converts source code lines that |
| 28 | begin with "@" into string literals, or into print statements that |
| 29 | generate web page output, depending on context. |
| 30 | |
| 31 | The [./makefile.wiki|Makefile] for Fossil takes care of running these |
| 32 | preprocessors with all the right arguments and in the right order. So it is |
| @@ -39,13 +39,13 @@ | |
| 39 | <h2>3.0 Adding New Source Code Files</h2> |
| 40 | |
| 41 | New source code files are added in the "src/" subdirectory of the Fossil |
| 42 | source tree. Suppose one wants to add a new source code file named |
| 43 | "xyzzy.c". The first step is to add this file to the various makefiles. |
| 44 | Do so by editing the file src/makemake.tcl and adding "xyzzy" (without |
| 45 | the final ".c") to the list of source modules at the top of that script. |
| 46 | Save the result and then run the makemake.tcl script using a TCL |
| 47 | interpreter. The command to run the makemake.tcl script is: |
| 48 | |
| 49 | <b>tclsh makemake.tcl</b> |
| 50 | |
| 51 | The working directory must be src/ when the command above is run. |
| @@ -60,11 +60,11 @@ | |
| 60 | |
| 61 | <blockquote><verbatim> |
| 62 | /* |
| 63 | ** Copyright boilerplate goes here. |
| 64 | ***************************************************** |
| 65 | ** High-level description of what this module goes |
| 66 | ** here. |
| 67 | */ |
| 68 | #include "config.h" |
| 69 | #include "xyzzy.h" |
| 70 | |
| @@ -83,11 +83,11 @@ | |
| 83 | exceptions to this rule. Don't worry about those exceptions. The |
| 84 | files you write will require this #include line.) |
| 85 | |
| 86 | The "#if INTERFACE ... #endif" section is optional and is only needed |
| 87 | if there are structure definitions or typedefs or macros that need to |
| 88 | be used by other source code files. The makeheaders preprocessor |
| 89 | uses definitions in the INTERFACE section to help it generate header |
| 90 | files. See [../src/makeheaders.html | makeheaders.html] for additional |
| 91 | information. |
| 92 | |
| 93 | After creating a template file such as shown above, and after updating |
| 94 |
+11
-11
| --- www/antibot.wiki | ||
| +++ www/antibot.wiki | ||
| @@ -1,27 +1,27 @@ | ||
| 1 | 1 | <title>Defense Against Spiders</title> |
| 2 | 2 | |
| 3 | 3 | The website presented by a Fossil server has many hyperlinks. |
| 4 | 4 | Even a modest project can have millions of pages in its |
| 5 | -tree, and many of those pages (for example diffs and annotations | |
| 5 | +tree, and many of those pages (for example diffs and annotations | |
| 6 | 6 | and ZIP archive of older check-ins) can be expensive to compute. |
| 7 | 7 | If a spider or bot tries to walk a website implemented by |
| 8 | 8 | Fossil, it can present a crippling bandwidth and CPU load. |
| 9 | 9 | |
| 10 | 10 | The website presented by a Fossil server is intended to be used |
| 11 | -interactively by humans, not walked by spiders. This article | |
| 11 | +interactively by humans, not walked by spiders. This article | |
| 12 | 12 | describes the techniques used by Fossil to try to welcome human |
| 13 | 13 | users while keeping out spiders. |
| 14 | 14 | |
| 15 | 15 | <h2>The "hyperlink" user capability</h2> |
| 16 | 16 | |
| 17 | 17 | Every Fossil web session has a "user". For random passers-by on the internet |
| 18 | 18 | (and for spiders) that user is "nobody". The "anonymous" user is also |
| 19 | 19 | available for humans who do not wish to identify themselves. The difference |
| 20 | 20 | is that "anonymous" requires a login (using a password supplied via |
| 21 | -a CAPTCHA) whereas "nobody" does not require a login. | |
| 22 | -The site administrator can also create logins with | |
| 21 | +a CAPTCHA) whereas "nobody" does not require a login. | |
| 22 | +The site administrator can also create logins with | |
| 23 | 23 | passwords for specific individuals. |
| 24 | 24 | |
| 25 | 25 | The "h" or "hyperlink" capability is a permission that can be granted |
| 26 | 26 | to users that enables the display of hyperlinks. Most of the hyperlinks |
| 27 | 27 | generated by Fossil are suppressed if this capability is missing. So |
| @@ -37,11 +37,11 @@ | ||
| 37 | 37 | page inviting the user to log in as anonymous in order to activate hyperlinks. |
| 38 | 38 | |
| 39 | 39 | Removing the "h" capability from user "nobody" is an effective means |
| 40 | 40 | of preventing spiders from walking a Fossil-generated website. But |
| 41 | 41 | it can also be annoying to humans, since it requires them to log in. |
| 42 | -Hence, Fossil provides other techniques for blocking spiders which | |
| 42 | +Hence, Fossil provides other techniques for blocking spiders which | |
| 43 | 43 | are less cumbersome to humans. |
| 44 | 44 | |
| 45 | 45 | <h2>Automatic hyperlinks based on UserAgent</h2> |
| 46 | 46 | |
| 47 | 47 | Fossil has the ability to selectively enable hyperlinks for users |
| @@ -94,25 +94,25 @@ | ||
| 94 | 94 | web browsers implement javascript, so hyperlinks will appears |
| 95 | 95 | normally for human users. |
| 96 | 96 | |
| 97 | 97 | <h2>Further defenses</h2> |
| 98 | 98 | |
| 99 | -Recently (as of this writing, in the spring of 2013) the Fossil server | |
| 99 | +Recently (as of this writing, in the spring of 2013) the Fossil server | |
| 100 | 100 | on the SQLite website ([http://www.sqlite.org/src/]) has been hit repeatedly |
| 101 | -by Chinese spiders that use forged UserAgent strings to make them look | |
| 101 | +by Chinese spiders that use forged UserAgent strings to make them look | |
| 102 | 102 | like normal web browsers and which interpret javascript. We do not |
| 103 | 103 | believe these attacks to be nefarious since SQLite is public domain |
| 104 | 104 | and the attackers could obtain all information they ever wanted to |
| 105 | -know about SQLite simply by cloning the repository. Instead, we | |
| 105 | +know about SQLite simply by cloning the repository. Instead, we | |
| 106 | 106 | believe these "attacks" are coming from "script kiddies". But regardless |
| 107 | 107 | of whether or not malice is involved, these attacks do present |
| 108 | 108 | an unnecessary load on the server which reduces the responsiveness of |
| 109 | 109 | the SQLite website for well-behaved and socially responsible users. |
| 110 | 110 | For this reason, additional defenses against |
| 111 | 111 | spiders have been put in place. |
| 112 | 112 | |
| 113 | -On the Admin/Access page of Fossil, just below the | |
| 113 | +On the Admin/Access page of Fossil, just below the | |
| 114 | 114 | "<b>Enable hyperlinks for "nobody" based on User-Agent and Javascript</b>" |
| 115 | 115 | setting, there are now two additional subsettings that can be optionally |
| 116 | 116 | enabled to control hyperlinks. |
| 117 | 117 | |
| 118 | 118 | The first subsetting waits to run the |
| @@ -137,11 +137,11 @@ | ||
| 137 | 137 | Fossil currently does a very good job of providing easy access to humans |
| 138 | 138 | while keeping out troublesome robots and spiders. However, spiders and |
| 139 | 139 | bots continue to grow more sophisticated, requiring ever more advanced |
| 140 | 140 | defenses. This "arms race" is unlikely to ever end. The developers of |
| 141 | 141 | Fossil will continue to try improve the spider defenses of Fossil so |
| 142 | -check back from time to time for the latest releases and updates. | |
| 142 | +check back from time to time for the latest releases and updates. | |
| 143 | 143 | |
| 144 | 144 | Readers of this page who have suggestions on how to improve the spider |
| 145 | 145 | defenses in Fossil are invited to submit your ideas to the Fossil Users |
| 146 | -mailing list: | |
| 146 | +mailing list: | |
| 147 | 147 | [mailto:[email protected] | [email protected]]. |
| 148 | 148 |
| --- www/antibot.wiki | |
| +++ www/antibot.wiki | |
| @@ -1,27 +1,27 @@ | |
| 1 | <title>Defense Against Spiders</title> |
| 2 | |
| 3 | The website presented by a Fossil server has many hyperlinks. |
| 4 | Even a modest project can have millions of pages in its |
| 5 | tree, and many of those pages (for example diffs and annotations |
| 6 | and ZIP archive of older check-ins) can be expensive to compute. |
| 7 | If a spider or bot tries to walk a website implemented by |
| 8 | Fossil, it can present a crippling bandwidth and CPU load. |
| 9 | |
| 10 | The website presented by a Fossil server is intended to be used |
| 11 | interactively by humans, not walked by spiders. This article |
| 12 | describes the techniques used by Fossil to try to welcome human |
| 13 | users while keeping out spiders. |
| 14 | |
| 15 | <h2>The "hyperlink" user capability</h2> |
| 16 | |
| 17 | Every Fossil web session has a "user". For random passers-by on the internet |
| 18 | (and for spiders) that user is "nobody". The "anonymous" user is also |
| 19 | available for humans who do not wish to identify themselves. The difference |
| 20 | is that "anonymous" requires a login (using a password supplied via |
| 21 | a CAPTCHA) whereas "nobody" does not require a login. |
| 22 | The site administrator can also create logins with |
| 23 | passwords for specific individuals. |
| 24 | |
| 25 | The "h" or "hyperlink" capability is a permission that can be granted |
| 26 | to users that enables the display of hyperlinks. Most of the hyperlinks |
| 27 | generated by Fossil are suppressed if this capability is missing. So |
| @@ -37,11 +37,11 @@ | |
| 37 | page inviting the user to log in as anonymous in order to activate hyperlinks. |
| 38 | |
| 39 | Removing the "h" capability from user "nobody" is an effective means |
| 40 | of preventing spiders from walking a Fossil-generated website. But |
| 41 | it can also be annoying to humans, since it requires them to log in. |
| 42 | Hence, Fossil provides other techniques for blocking spiders which |
| 43 | are less cumbersome to humans. |
| 44 | |
| 45 | <h2>Automatic hyperlinks based on UserAgent</h2> |
| 46 | |
| 47 | Fossil has the ability to selectively enable hyperlinks for users |
| @@ -94,25 +94,25 @@ | |
| 94 | web browsers implement javascript, so hyperlinks will appears |
| 95 | normally for human users. |
| 96 | |
| 97 | <h2>Further defenses</h2> |
| 98 | |
| 99 | Recently (as of this writing, in the spring of 2013) the Fossil server |
| 100 | on the SQLite website ([http://www.sqlite.org/src/]) has been hit repeatedly |
| 101 | by Chinese spiders that use forged UserAgent strings to make them look |
| 102 | like normal web browsers and which interpret javascript. We do not |
| 103 | believe these attacks to be nefarious since SQLite is public domain |
| 104 | and the attackers could obtain all information they ever wanted to |
| 105 | know about SQLite simply by cloning the repository. Instead, we |
| 106 | believe these "attacks" are coming from "script kiddies". But regardless |
| 107 | of whether or not malice is involved, these attacks do present |
| 108 | an unnecessary load on the server which reduces the responsiveness of |
| 109 | the SQLite website for well-behaved and socially responsible users. |
| 110 | For this reason, additional defenses against |
| 111 | spiders have been put in place. |
| 112 | |
| 113 | On the Admin/Access page of Fossil, just below the |
| 114 | "<b>Enable hyperlinks for "nobody" based on User-Agent and Javascript</b>" |
| 115 | setting, there are now two additional subsettings that can be optionally |
| 116 | enabled to control hyperlinks. |
| 117 | |
| 118 | The first subsetting waits to run the |
| @@ -137,11 +137,11 @@ | |
| 137 | Fossil currently does a very good job of providing easy access to humans |
| 138 | while keeping out troublesome robots and spiders. However, spiders and |
| 139 | bots continue to grow more sophisticated, requiring ever more advanced |
| 140 | defenses. This "arms race" is unlikely to ever end. The developers of |
| 141 | Fossil will continue to try improve the spider defenses of Fossil so |
| 142 | check back from time to time for the latest releases and updates. |
| 143 | |
| 144 | Readers of this page who have suggestions on how to improve the spider |
| 145 | defenses in Fossil are invited to submit your ideas to the Fossil Users |
| 146 | mailing list: |
| 147 | [mailto:[email protected] | [email protected]]. |
| 148 |
| --- www/antibot.wiki | |
| +++ www/antibot.wiki | |
| @@ -1,27 +1,27 @@ | |
| 1 | <title>Defense Against Spiders</title> |
| 2 | |
| 3 | The website presented by a Fossil server has many hyperlinks. |
| 4 | Even a modest project can have millions of pages in its |
| 5 | tree, and many of those pages (for example diffs and annotations |
| 6 | and ZIP archive of older check-ins) can be expensive to compute. |
| 7 | If a spider or bot tries to walk a website implemented by |
| 8 | Fossil, it can present a crippling bandwidth and CPU load. |
| 9 | |
| 10 | The website presented by a Fossil server is intended to be used |
| 11 | interactively by humans, not walked by spiders. This article |
| 12 | describes the techniques used by Fossil to try to welcome human |
| 13 | users while keeping out spiders. |
| 14 | |
| 15 | <h2>The "hyperlink" user capability</h2> |
| 16 | |
| 17 | Every Fossil web session has a "user". For random passers-by on the internet |
| 18 | (and for spiders) that user is "nobody". The "anonymous" user is also |
| 19 | available for humans who do not wish to identify themselves. The difference |
| 20 | is that "anonymous" requires a login (using a password supplied via |
| 21 | a CAPTCHA) whereas "nobody" does not require a login. |
| 22 | The site administrator can also create logins with |
| 23 | passwords for specific individuals. |
| 24 | |
| 25 | The "h" or "hyperlink" capability is a permission that can be granted |
| 26 | to users that enables the display of hyperlinks. Most of the hyperlinks |
| 27 | generated by Fossil are suppressed if this capability is missing. So |
| @@ -37,11 +37,11 @@ | |
| 37 | page inviting the user to log in as anonymous in order to activate hyperlinks. |
| 38 | |
| 39 | Removing the "h" capability from user "nobody" is an effective means |
| 40 | of preventing spiders from walking a Fossil-generated website. But |
| 41 | it can also be annoying to humans, since it requires them to log in. |
| 42 | Hence, Fossil provides other techniques for blocking spiders which |
| 43 | are less cumbersome to humans. |
| 44 | |
| 45 | <h2>Automatic hyperlinks based on UserAgent</h2> |
| 46 | |
| 47 | Fossil has the ability to selectively enable hyperlinks for users |
| @@ -94,25 +94,25 @@ | |
| 94 | web browsers implement javascript, so hyperlinks will appears |
| 95 | normally for human users. |
| 96 | |
| 97 | <h2>Further defenses</h2> |
| 98 | |
| 99 | Recently (as of this writing, in the spring of 2013) the Fossil server |
| 100 | on the SQLite website ([http://www.sqlite.org/src/]) has been hit repeatedly |
| 101 | by Chinese spiders that use forged UserAgent strings to make them look |
| 102 | like normal web browsers and which interpret javascript. We do not |
| 103 | believe these attacks to be nefarious since SQLite is public domain |
| 104 | and the attackers could obtain all information they ever wanted to |
| 105 | know about SQLite simply by cloning the repository. Instead, we |
| 106 | believe these "attacks" are coming from "script kiddies". But regardless |
| 107 | of whether or not malice is involved, these attacks do present |
| 108 | an unnecessary load on the server which reduces the responsiveness of |
| 109 | the SQLite website for well-behaved and socially responsible users. |
| 110 | For this reason, additional defenses against |
| 111 | spiders have been put in place. |
| 112 | |
| 113 | On the Admin/Access page of Fossil, just below the |
| 114 | "<b>Enable hyperlinks for "nobody" based on User-Agent and Javascript</b>" |
| 115 | setting, there are now two additional subsettings that can be optionally |
| 116 | enabled to control hyperlinks. |
| 117 | |
| 118 | The first subsetting waits to run the |
| @@ -137,11 +137,11 @@ | |
| 137 | Fossil currently does a very good job of providing easy access to humans |
| 138 | while keeping out troublesome robots and spiders. However, spiders and |
| 139 | bots continue to grow more sophisticated, requiring ever more advanced |
| 140 | defenses. This "arms race" is unlikely to ever end. The developers of |
| 141 | Fossil will continue to try improve the spider defenses of Fossil so |
| 142 | check back from time to time for the latest releases and updates. |
| 143 | |
| 144 | Readers of this page who have suggestions on how to improve the spider |
| 145 | defenses in Fossil are invited to submit your ideas to the Fossil Users |
| 146 | mailing list: |
| 147 | [mailto:[email protected] | [email protected]]. |
| 148 |
+4
-4
| --- www/blame.wiki | ||
| +++ www/blame.wiki | ||
| @@ -18,16 +18,16 @@ | ||
| 18 | 18 | <li>Locate the check-in that contains the file that is to be |
| 19 | 19 | annotated. Call this check-in C0. |
| 20 | 20 | <li>Find all direct ancestors of C0. A direct ancestor is the closure |
| 21 | 21 | of the primary parent of C0. Merged in branches are not part of |
| 22 | 22 | the direct ancestors of C0. |
| 23 | -<li>Prune the list of ancestors of C0 so that it contains only | |
| 23 | +<li>Prune the list of ancestors of C0 so that it contains only | |
| 24 | 24 | check-in in which the file to be annotated was modified. |
| 25 | 25 | <li>Load the complete text of the file to be annotated from check-in C0. |
| 26 | 26 | Call this version of the file F0. |
| 27 | 27 | <li>Parse F0 into lines. Mark each line as "unchanged". |
| 28 | -<li>For each ancestor of C0 on the pruned list (call the ancestor CX), | |
| 28 | +<li>For each ancestor of C0 on the pruned list (call the ancestor CX), | |
| 29 | 29 | beginning with the most |
| 30 | 30 | recent ancestor and moving toward the oldest ancestor, do the |
| 31 | 31 | following steps: |
| 32 | 32 | <ol type='a'> |
| 33 | 33 | <li>Load the text for the file to be annotated as it existed in check-in CX. |
| @@ -44,19 +44,19 @@ | ||
| 44 | 44 | <h2>3.0 Discussion and Notes</h2> |
| 45 | 45 | |
| 46 | 46 | The time-consuming part of this algorithm is step 6b - computing the |
| 47 | 47 | diff from all historical versions of the file to the version of the file |
| 48 | 48 | under analysis. For a large file that has many historical changes, this |
| 49 | -can take several seconds. For this reason, the default | |
| 49 | +can take several seconds. For this reason, the default | |
| 50 | 50 | [/help?cmd=/annotate|/annotate] webpage only shows those lines that where |
| 51 | 51 | changed by the 20 most recent modifications to the file. This allows |
| 52 | 52 | the loop on step 6 to terminate after only 19 diffs instead of the hundreds |
| 53 | 53 | or thousands of diffs that might be required for a frequently modified file. |
| 54 | 54 | |
| 55 | 55 | As currently implemented (as of 2015-12-12) the annotate algorithm does not |
| 56 | -follow files across name changes. File name change information is | |
| 56 | +follow files across name changes. File name change information is | |
| 57 | 57 | available in the database, and so the algorithm could be enhanced to follow |
| 58 | 58 | files across name changes by modifications to step 3. |
| 59 | 59 | |
| 60 | 60 | Step 2 is interesting in that it is |
| 61 | 61 | [/artifact/6cb824a0417?ln=196-201 | implemented] using a |
| 62 | 62 | [https://www.sqlite.org/lang_with.html#recursivecte|recursive common table expression]. |
| 63 | 63 |
| --- www/blame.wiki | |
| +++ www/blame.wiki | |
| @@ -18,16 +18,16 @@ | |
| 18 | <li>Locate the check-in that contains the file that is to be |
| 19 | annotated. Call this check-in C0. |
| 20 | <li>Find all direct ancestors of C0. A direct ancestor is the closure |
| 21 | of the primary parent of C0. Merged in branches are not part of |
| 22 | the direct ancestors of C0. |
| 23 | <li>Prune the list of ancestors of C0 so that it contains only |
| 24 | check-in in which the file to be annotated was modified. |
| 25 | <li>Load the complete text of the file to be annotated from check-in C0. |
| 26 | Call this version of the file F0. |
| 27 | <li>Parse F0 into lines. Mark each line as "unchanged". |
| 28 | <li>For each ancestor of C0 on the pruned list (call the ancestor CX), |
| 29 | beginning with the most |
| 30 | recent ancestor and moving toward the oldest ancestor, do the |
| 31 | following steps: |
| 32 | <ol type='a'> |
| 33 | <li>Load the text for the file to be annotated as it existed in check-in CX. |
| @@ -44,19 +44,19 @@ | |
| 44 | <h2>3.0 Discussion and Notes</h2> |
| 45 | |
| 46 | The time-consuming part of this algorithm is step 6b - computing the |
| 47 | diff from all historical versions of the file to the version of the file |
| 48 | under analysis. For a large file that has many historical changes, this |
| 49 | can take several seconds. For this reason, the default |
| 50 | [/help?cmd=/annotate|/annotate] webpage only shows those lines that where |
| 51 | changed by the 20 most recent modifications to the file. This allows |
| 52 | the loop on step 6 to terminate after only 19 diffs instead of the hundreds |
| 53 | or thousands of diffs that might be required for a frequently modified file. |
| 54 | |
| 55 | As currently implemented (as of 2015-12-12) the annotate algorithm does not |
| 56 | follow files across name changes. File name change information is |
| 57 | available in the database, and so the algorithm could be enhanced to follow |
| 58 | files across name changes by modifications to step 3. |
| 59 | |
| 60 | Step 2 is interesting in that it is |
| 61 | [/artifact/6cb824a0417?ln=196-201 | implemented] using a |
| 62 | [https://www.sqlite.org/lang_with.html#recursivecte|recursive common table expression]. |
| 63 |
| --- www/blame.wiki | |
| +++ www/blame.wiki | |
| @@ -18,16 +18,16 @@ | |
| 18 | <li>Locate the check-in that contains the file that is to be |
| 19 | annotated. Call this check-in C0. |
| 20 | <li>Find all direct ancestors of C0. A direct ancestor is the closure |
| 21 | of the primary parent of C0. Merged in branches are not part of |
| 22 | the direct ancestors of C0. |
| 23 | <li>Prune the list of ancestors of C0 so that it contains only |
| 24 | check-in in which the file to be annotated was modified. |
| 25 | <li>Load the complete text of the file to be annotated from check-in C0. |
| 26 | Call this version of the file F0. |
| 27 | <li>Parse F0 into lines. Mark each line as "unchanged". |
| 28 | <li>For each ancestor of C0 on the pruned list (call the ancestor CX), |
| 29 | beginning with the most |
| 30 | recent ancestor and moving toward the oldest ancestor, do the |
| 31 | following steps: |
| 32 | <ol type='a'> |
| 33 | <li>Load the text for the file to be annotated as it existed in check-in CX. |
| @@ -44,19 +44,19 @@ | |
| 44 | <h2>3.0 Discussion and Notes</h2> |
| 45 | |
| 46 | The time-consuming part of this algorithm is step 6b - computing the |
| 47 | diff from all historical versions of the file to the version of the file |
| 48 | under analysis. For a large file that has many historical changes, this |
| 49 | can take several seconds. For this reason, the default |
| 50 | [/help?cmd=/annotate|/annotate] webpage only shows those lines that where |
| 51 | changed by the 20 most recent modifications to the file. This allows |
| 52 | the loop on step 6 to terminate after only 19 diffs instead of the hundreds |
| 53 | or thousands of diffs that might be required for a frequently modified file. |
| 54 | |
| 55 | As currently implemented (as of 2015-12-12) the annotate algorithm does not |
| 56 | follow files across name changes. File name change information is |
| 57 | available in the database, and so the algorithm could be enhanced to follow |
| 58 | files across name changes by modifications to step 3. |
| 59 | |
| 60 | Step 2 is interesting in that it is |
| 61 | [/artifact/6cb824a0417?ln=196-201 | implemented] using a |
| 62 | [https://www.sqlite.org/lang_with.html#recursivecte|recursive common table expression]. |
| 63 |
+1
-1
| --- www/bugtheory.wiki | ||
| +++ www/bugtheory.wiki | ||
| @@ -27,11 +27,11 @@ | ||
| 27 | 27 | Recall that a fossil repository consists of an |
| 28 | 28 | unordered collection of <i>artifacts</i>. (See the |
| 29 | 29 | <a href="fileformat.wiki">file format document</a> for details.) |
| 30 | 30 | Some artifacts have a special format, and among those are |
| 31 | 31 | <a href="fileformat.wiki#tktchng">Ticket Change Artifacts</a>. |
| 32 | -One or more ticket change artifacts are associated with each | |
| 32 | +One or more ticket change artifacts are associated with each | |
| 33 | 33 | ticket. A ticket is created by a ticket change artifact. |
| 34 | 34 | Each subsequent modification of the ticket is a separate artifact. |
| 35 | 35 | |
| 36 | 36 | The "push", "pull", and "sync" algorithms share ticket change artifacts |
| 37 | 37 | between repositories in the same way as every other artifact. In fact, |
| 38 | 38 |
| --- www/bugtheory.wiki | |
| +++ www/bugtheory.wiki | |
| @@ -27,11 +27,11 @@ | |
| 27 | Recall that a fossil repository consists of an |
| 28 | unordered collection of <i>artifacts</i>. (See the |
| 29 | <a href="fileformat.wiki">file format document</a> for details.) |
| 30 | Some artifacts have a special format, and among those are |
| 31 | <a href="fileformat.wiki#tktchng">Ticket Change Artifacts</a>. |
| 32 | One or more ticket change artifacts are associated with each |
| 33 | ticket. A ticket is created by a ticket change artifact. |
| 34 | Each subsequent modification of the ticket is a separate artifact. |
| 35 | |
| 36 | The "push", "pull", and "sync" algorithms share ticket change artifacts |
| 37 | between repositories in the same way as every other artifact. In fact, |
| 38 |
| --- www/bugtheory.wiki | |
| +++ www/bugtheory.wiki | |
| @@ -27,11 +27,11 @@ | |
| 27 | Recall that a fossil repository consists of an |
| 28 | unordered collection of <i>artifacts</i>. (See the |
| 29 | <a href="fileformat.wiki">file format document</a> for details.) |
| 30 | Some artifacts have a special format, and among those are |
| 31 | <a href="fileformat.wiki#tktchng">Ticket Change Artifacts</a>. |
| 32 | One or more ticket change artifacts are associated with each |
| 33 | ticket. A ticket is created by a ticket change artifact. |
| 34 | Each subsequent modification of the ticket is a separate artifact. |
| 35 | |
| 36 | The "push", "pull", and "sync" algorithms share ticket change artifacts |
| 37 | between repositories in the same way as every other artifact. In fact, |
| 38 |
+31
-2
| --- www/changes.wiki | ||
| +++ www/changes.wiki | ||
| @@ -1,20 +1,42 @@ | ||
| 1 | 1 | <title>Change Log</title> |
| 2 | 2 | |
| 3 | -<h2>Changes for Version 1.36 (2016-00-00)</h2> | |
| 3 | +<a name='v1_37'></a> | |
| 4 | +<h2>Changes for Version 1.37 (2017-XX-YY)</h2> | |
| 5 | + | |
| 6 | + * Fix a C99-ism that prevents the 1.36 release from building with MSVC. | |
| 7 | + * Fix [/help?cmd=ticket|ticket set] when using the "+" prefix with fields | |
| 8 | + from the "ticketchng" table. | |
| 9 | + * Enhance the "brlist" page to make use of branch colors. | |
| 10 | + * Remove the "fusefs" command from builds that do not have the underlying | |
| 11 | + support enabled. | |
| 12 | + * Fixes for incremental git import/export. | |
| 13 | + * Minor security enhancements to | |
| 14 | + [./encryptedrepos.wiki|encrypted repositories]. | |
| 15 | + * TH1 enhancements: | |
| 16 | + <ul><li>Add <nowiki>[unversioned content]</nowiki> command.</li> | |
| 17 | + <li>Add <nowiki>[unversioned list]</nowiki> command.</li> | |
| 18 | + <li>Add project_description variable.</li> | |
| 19 | + </ul> | |
| 20 | + | |
| 21 | +<a name='v1_36'></a> | |
| 22 | +<h2>Changes for Version 1.36 (2016-10-24)</h2> | |
| 4 | 23 | |
| 5 | 24 | * Add support for [./unvers.wiki|unversioned content], |
| 6 | 25 | the [/help?cmd=unversioned|fossil unversioned] command and the |
| 7 | 26 | [/help?cmd=/uv|/uv] and [/uvlist] web pages. |
| 8 | 27 | * The [/uv/download.html|download page] is moved into |
| 9 | 28 | [./unvers.wiki|unversioned content] so that the self-hosting Fossil |
| 10 | 29 | websites no longer uses any external content. |
| 11 | 30 | * Added the "Search" button to the graphical diff generated by |
| 12 | 31 | the --tk option on the [/help?cmd=diff|diff] command. |
| 32 | + * Added the "--checkin VERSION" option to the | |
| 33 | + [/help?cmd=diff|diff] command. | |
| 34 | + * Various performance enhancements to the [/help?cmd=diff|diff] command. | |
| 13 | 35 | * Update internal Unicode character tables, used in regular expression |
| 14 | 36 | handling, from version 8.0 to 9.0. |
| 15 | - * Update the built-in SQLite to version 3.15 (beta). Fossil now requires | |
| 37 | + * Update the built-in SQLite to version 3.15. Fossil now requires | |
| 16 | 38 | the SQLITE_DBCONFIG_MAINDBNAME interface of SQLite which is only available |
| 17 | 39 | in SQLite version 3.15 and later and so Fossil will not work with |
| 18 | 40 | earlier SQLite versions. |
| 19 | 41 | * Fix [https://www.mail-archive.com/[email protected]/msg23618.html|multi-line timeline bug] |
| 20 | 42 | * Enhance the [/help?cmd=purge|fossil purge] command. |
| @@ -25,10 +47,11 @@ | ||
| 25 | 47 | able to pull from their parent but not push. |
| 26 | 48 | * Added the -nocomplain option to the TH1 "query" command. |
| 27 | 49 | * Added support for the chng=GLOBLIST query parameter on the |
| 28 | 50 | [/help?cmd=/timeline|/timeline] webpage. |
| 29 | 51 | |
| 52 | +<a name='v1_35'></a> | |
| 30 | 53 | <h2>Changes for Version 1.35 (2016-06-14)</h2> |
| 31 | 54 | |
| 32 | 55 | * Enable symlinks by default on all non-Windows platforms. |
| 33 | 56 | * Enhance the [/md_rules|Markdown formatting] so that hyperlinks that begin |
| 34 | 57 | with "/" are relative to the root of the Fossil repository. |
| @@ -68,10 +91,11 @@ | ||
| 68 | 91 | names in place of getpass() to read passwords and passphrases |
| 69 | 92 | * Option --baseurl now works on Windows. |
| 70 | 93 | * Numerious documentation improvements. |
| 71 | 94 | * Update the built-in SQLite to version 3.13.0. |
| 72 | 95 | |
| 96 | +<a name='v1_34'></a> | |
| 73 | 97 | <h2>Changes for Version 1.34 (2015-11-02)</h2> |
| 74 | 98 | |
| 75 | 99 | * Make the [/help?cmd=clean|fossil clean] command undoable for files less |
| 76 | 100 | than 10MiB. |
| 77 | 101 | * Update internal Unicode character tables, used in regular expression |
| @@ -103,10 +127,11 @@ | ||
| 103 | 127 | * Change the mimetype for ".n" and ".man" files to text/plain. |
| 104 | 128 | * Display improvements in the [/help?cmd=bisect|fossil bisect chart] command. |
| 105 | 129 | * Updated the built-in SQLite to version 3.9.1 and activated JSON1 and FTS5 |
| 106 | 130 | support (both currently unused within Fossil). |
| 107 | 131 | |
| 132 | +<a name='v1_33'></a> | |
| 108 | 133 | <h2>Changes for Version 1.33 (2015-05-23)</h2> |
| 109 | 134 | * Improved fork detection on [/help?cmd=update|fossil update], |
| 110 | 135 | [/help?cmd=status|fossil status] and related commands. |
| 111 | 136 | * Change the default skin to what used to be called "San Francisco Modern". |
| 112 | 137 | * Add the [/repo-tabsize] web page |
| @@ -152,10 +177,11 @@ | ||
| 152 | 177 | field for direct entry of the user name to each applicable report. |
| 153 | 178 | * Create parent directories of [/help?cmd=settings|empty-dirs] if they don't |
| 154 | 179 | already exist. |
| 155 | 180 | * Inhibit timeline links to wiki pages that have been deleted. |
| 156 | 181 | |
| 182 | +<a name='v1_33'></a> | |
| 157 | 183 | <h2>Changes for Version 1.32 (2015-03-14)</h2> |
| 158 | 184 | * When creating a new repository using [/help?cmd=init|fossil init], ensure |
| 159 | 185 | that the new repository is fully compatible with historical versions of |
| 160 | 186 | Fossil by having a valid manifest as RID 1. |
| 161 | 187 | * Anti-aliased rendering of arrowheads on timeline graphs. |
| @@ -168,10 +194,11 @@ | ||
| 168 | 194 | * Enhance the "ln=" query parameter on artifact displays to accept multiple |
| 169 | 195 | ranges, separate by spaces (or "+" when URL-encoded). |
| 170 | 196 | * Added [/help?cmd=forget|fossil forget] as an alias for |
| 171 | 197 | [/help?cmd=rm|fossil rm]. |
| 172 | 198 | |
| 199 | +<a name='v1_31'></a> | |
| 173 | 200 | <h2>Changes For Version 1.31 (2015-02-23)</h2> |
| 174 | 201 | * Change the auxiliary schema by adding columns MLINK.ISAUX and MLINK.PMID |
| 175 | 202 | columns to the schema, to support better drawing of file change graphs. |
| 176 | 203 | A [/help?cmd=rebuild|fossil rebuild] is recommended but is not required. |
| 177 | 204 | so that the new graph drawing logic can work effectively. |
| @@ -219,10 +246,11 @@ | ||
| 219 | 246 | * Allow the user of Common Table Expressions in the SQL that defaults |
| 220 | 247 | ticket reports. |
| 221 | 248 | * Break out the components (css, footer, and header) for the |
| 222 | 249 | various built-in skins into separate files in the source tree. |
| 223 | 250 | |
| 251 | +<a name='v1_30'></a> | |
| 224 | 252 | <h2>Changes For Version 1.30 (2015-01-19)</h2> |
| 225 | 253 | * Added the [/help?cmd=bundle|fossil bundle] command. |
| 226 | 254 | * Added the [/help?cmd=purge|fossil purge] command. |
| 227 | 255 | * Added the [/help?cmd=publish|fossil publish] command. |
| 228 | 256 | * Added the [/help?cmd=unpublished|fossil unpublished] command. |
| @@ -289,10 +317,11 @@ | ||
| 289 | 317 | the correctness of printf-style formatting strings. |
| 290 | 318 | * Fix CVE-2014-3566, also known as the POODLE SSL 3.0 vulnerability. |
| 291 | 319 | * Numerous documentation fixes and improvements. |
| 292 | 320 | * Other obscure and minor bug fixes - see the timeline for details. |
| 293 | 321 | |
| 322 | +<a name='v1_29'></a> | |
| 294 | 323 | <h2>Changes For Version 1.29 (2014-06-12)</h2> |
| 295 | 324 | * Add the ability to display content, diffs and annotations for UTF16 |
| 296 | 325 | text files in the web interface. |
| 297 | 326 | * Add the "SaveAs..." and "Invert" buttons |
| 298 | 327 | to the graphical diff display that results |
| 299 | 328 |
| --- www/changes.wiki | |
| +++ www/changes.wiki | |
| @@ -1,20 +1,42 @@ | |
| 1 | <title>Change Log</title> |
| 2 | |
| 3 | <h2>Changes for Version 1.36 (2016-00-00)</h2> |
| 4 | |
| 5 | * Add support for [./unvers.wiki|unversioned content], |
| 6 | the [/help?cmd=unversioned|fossil unversioned] command and the |
| 7 | [/help?cmd=/uv|/uv] and [/uvlist] web pages. |
| 8 | * The [/uv/download.html|download page] is moved into |
| 9 | [./unvers.wiki|unversioned content] so that the self-hosting Fossil |
| 10 | websites no longer uses any external content. |
| 11 | * Added the "Search" button to the graphical diff generated by |
| 12 | the --tk option on the [/help?cmd=diff|diff] command. |
| 13 | * Update internal Unicode character tables, used in regular expression |
| 14 | handling, from version 8.0 to 9.0. |
| 15 | * Update the built-in SQLite to version 3.15 (beta). Fossil now requires |
| 16 | the SQLITE_DBCONFIG_MAINDBNAME interface of SQLite which is only available |
| 17 | in SQLite version 3.15 and later and so Fossil will not work with |
| 18 | earlier SQLite versions. |
| 19 | * Fix [https://www.mail-archive.com/[email protected]/msg23618.html|multi-line timeline bug] |
| 20 | * Enhance the [/help?cmd=purge|fossil purge] command. |
| @@ -25,10 +47,11 @@ | |
| 25 | able to pull from their parent but not push. |
| 26 | * Added the -nocomplain option to the TH1 "query" command. |
| 27 | * Added support for the chng=GLOBLIST query parameter on the |
| 28 | [/help?cmd=/timeline|/timeline] webpage. |
| 29 | |
| 30 | <h2>Changes for Version 1.35 (2016-06-14)</h2> |
| 31 | |
| 32 | * Enable symlinks by default on all non-Windows platforms. |
| 33 | * Enhance the [/md_rules|Markdown formatting] so that hyperlinks that begin |
| 34 | with "/" are relative to the root of the Fossil repository. |
| @@ -68,10 +91,11 @@ | |
| 68 | names in place of getpass() to read passwords and passphrases |
| 69 | * Option --baseurl now works on Windows. |
| 70 | * Numerious documentation improvements. |
| 71 | * Update the built-in SQLite to version 3.13.0. |
| 72 | |
| 73 | <h2>Changes for Version 1.34 (2015-11-02)</h2> |
| 74 | |
| 75 | * Make the [/help?cmd=clean|fossil clean] command undoable for files less |
| 76 | than 10MiB. |
| 77 | * Update internal Unicode character tables, used in regular expression |
| @@ -103,10 +127,11 @@ | |
| 103 | * Change the mimetype for ".n" and ".man" files to text/plain. |
| 104 | * Display improvements in the [/help?cmd=bisect|fossil bisect chart] command. |
| 105 | * Updated the built-in SQLite to version 3.9.1 and activated JSON1 and FTS5 |
| 106 | support (both currently unused within Fossil). |
| 107 | |
| 108 | <h2>Changes for Version 1.33 (2015-05-23)</h2> |
| 109 | * Improved fork detection on [/help?cmd=update|fossil update], |
| 110 | [/help?cmd=status|fossil status] and related commands. |
| 111 | * Change the default skin to what used to be called "San Francisco Modern". |
| 112 | * Add the [/repo-tabsize] web page |
| @@ -152,10 +177,11 @@ | |
| 152 | field for direct entry of the user name to each applicable report. |
| 153 | * Create parent directories of [/help?cmd=settings|empty-dirs] if they don't |
| 154 | already exist. |
| 155 | * Inhibit timeline links to wiki pages that have been deleted. |
| 156 | |
| 157 | <h2>Changes for Version 1.32 (2015-03-14)</h2> |
| 158 | * When creating a new repository using [/help?cmd=init|fossil init], ensure |
| 159 | that the new repository is fully compatible with historical versions of |
| 160 | Fossil by having a valid manifest as RID 1. |
| 161 | * Anti-aliased rendering of arrowheads on timeline graphs. |
| @@ -168,10 +194,11 @@ | |
| 168 | * Enhance the "ln=" query parameter on artifact displays to accept multiple |
| 169 | ranges, separate by spaces (or "+" when URL-encoded). |
| 170 | * Added [/help?cmd=forget|fossil forget] as an alias for |
| 171 | [/help?cmd=rm|fossil rm]. |
| 172 | |
| 173 | <h2>Changes For Version 1.31 (2015-02-23)</h2> |
| 174 | * Change the auxiliary schema by adding columns MLINK.ISAUX and MLINK.PMID |
| 175 | columns to the schema, to support better drawing of file change graphs. |
| 176 | A [/help?cmd=rebuild|fossil rebuild] is recommended but is not required. |
| 177 | so that the new graph drawing logic can work effectively. |
| @@ -219,10 +246,11 @@ | |
| 219 | * Allow the user of Common Table Expressions in the SQL that defaults |
| 220 | ticket reports. |
| 221 | * Break out the components (css, footer, and header) for the |
| 222 | various built-in skins into separate files in the source tree. |
| 223 | |
| 224 | <h2>Changes For Version 1.30 (2015-01-19)</h2> |
| 225 | * Added the [/help?cmd=bundle|fossil bundle] command. |
| 226 | * Added the [/help?cmd=purge|fossil purge] command. |
| 227 | * Added the [/help?cmd=publish|fossil publish] command. |
| 228 | * Added the [/help?cmd=unpublished|fossil unpublished] command. |
| @@ -289,10 +317,11 @@ | |
| 289 | the correctness of printf-style formatting strings. |
| 290 | * Fix CVE-2014-3566, also known as the POODLE SSL 3.0 vulnerability. |
| 291 | * Numerous documentation fixes and improvements. |
| 292 | * Other obscure and minor bug fixes - see the timeline for details. |
| 293 | |
| 294 | <h2>Changes For Version 1.29 (2014-06-12)</h2> |
| 295 | * Add the ability to display content, diffs and annotations for UTF16 |
| 296 | text files in the web interface. |
| 297 | * Add the "SaveAs..." and "Invert" buttons |
| 298 | to the graphical diff display that results |
| 299 |
| --- www/changes.wiki | |
| +++ www/changes.wiki | |
| @@ -1,20 +1,42 @@ | |
| 1 | <title>Change Log</title> |
| 2 | |
| 3 | <a name='v1_37'></a> |
| 4 | <h2>Changes for Version 1.37 (2017-XX-YY)</h2> |
| 5 | |
| 6 | * Fix a C99-ism that prevents the 1.36 release from building with MSVC. |
| 7 | * Fix [/help?cmd=ticket|ticket set] when using the "+" prefix with fields |
| 8 | from the "ticketchng" table. |
| 9 | * Enhance the "brlist" page to make use of branch colors. |
| 10 | * Remove the "fusefs" command from builds that do not have the underlying |
| 11 | support enabled. |
| 12 | * Fixes for incremental git import/export. |
| 13 | * Minor security enhancements to |
| 14 | [./encryptedrepos.wiki|encrypted repositories]. |
| 15 | * TH1 enhancements: |
| 16 | <ul><li>Add <nowiki>[unversioned content]</nowiki> command.</li> |
| 17 | <li>Add <nowiki>[unversioned list]</nowiki> command.</li> |
| 18 | <li>Add project_description variable.</li> |
| 19 | </ul> |
| 20 | |
| 21 | <a name='v1_36'></a> |
| 22 | <h2>Changes for Version 1.36 (2016-10-24)</h2> |
| 23 | |
| 24 | * Add support for [./unvers.wiki|unversioned content], |
| 25 | the [/help?cmd=unversioned|fossil unversioned] command and the |
| 26 | [/help?cmd=/uv|/uv] and [/uvlist] web pages. |
| 27 | * The [/uv/download.html|download page] is moved into |
| 28 | [./unvers.wiki|unversioned content] so that the self-hosting Fossil |
| 29 | websites no longer uses any external content. |
| 30 | * Added the "Search" button to the graphical diff generated by |
| 31 | the --tk option on the [/help?cmd=diff|diff] command. |
| 32 | * Added the "--checkin VERSION" option to the |
| 33 | [/help?cmd=diff|diff] command. |
| 34 | * Various performance enhancements to the [/help?cmd=diff|diff] command. |
| 35 | * Update internal Unicode character tables, used in regular expression |
| 36 | handling, from version 8.0 to 9.0. |
| 37 | * Update the built-in SQLite to version 3.15. Fossil now requires |
| 38 | the SQLITE_DBCONFIG_MAINDBNAME interface of SQLite which is only available |
| 39 | in SQLite version 3.15 and later and so Fossil will not work with |
| 40 | earlier SQLite versions. |
| 41 | * Fix [https://www.mail-archive.com/[email protected]/msg23618.html|multi-line timeline bug] |
| 42 | * Enhance the [/help?cmd=purge|fossil purge] command. |
| @@ -25,10 +47,11 @@ | |
| 47 | able to pull from their parent but not push. |
| 48 | * Added the -nocomplain option to the TH1 "query" command. |
| 49 | * Added support for the chng=GLOBLIST query parameter on the |
| 50 | [/help?cmd=/timeline|/timeline] webpage. |
| 51 | |
| 52 | <a name='v1_35'></a> |
| 53 | <h2>Changes for Version 1.35 (2016-06-14)</h2> |
| 54 | |
| 55 | * Enable symlinks by default on all non-Windows platforms. |
| 56 | * Enhance the [/md_rules|Markdown formatting] so that hyperlinks that begin |
| 57 | with "/" are relative to the root of the Fossil repository. |
| @@ -68,10 +91,11 @@ | |
| 91 | names in place of getpass() to read passwords and passphrases |
| 92 | * Option --baseurl now works on Windows. |
| 93 | * Numerious documentation improvements. |
| 94 | * Update the built-in SQLite to version 3.13.0. |
| 95 | |
| 96 | <a name='v1_34'></a> |
| 97 | <h2>Changes for Version 1.34 (2015-11-02)</h2> |
| 98 | |
| 99 | * Make the [/help?cmd=clean|fossil clean] command undoable for files less |
| 100 | than 10MiB. |
| 101 | * Update internal Unicode character tables, used in regular expression |
| @@ -103,10 +127,11 @@ | |
| 127 | * Change the mimetype for ".n" and ".man" files to text/plain. |
| 128 | * Display improvements in the [/help?cmd=bisect|fossil bisect chart] command. |
| 129 | * Updated the built-in SQLite to version 3.9.1 and activated JSON1 and FTS5 |
| 130 | support (both currently unused within Fossil). |
| 131 | |
| 132 | <a name='v1_33'></a> |
| 133 | <h2>Changes for Version 1.33 (2015-05-23)</h2> |
| 134 | * Improved fork detection on [/help?cmd=update|fossil update], |
| 135 | [/help?cmd=status|fossil status] and related commands. |
| 136 | * Change the default skin to what used to be called "San Francisco Modern". |
| 137 | * Add the [/repo-tabsize] web page |
| @@ -152,10 +177,11 @@ | |
| 177 | field for direct entry of the user name to each applicable report. |
| 178 | * Create parent directories of [/help?cmd=settings|empty-dirs] if they don't |
| 179 | already exist. |
| 180 | * Inhibit timeline links to wiki pages that have been deleted. |
| 181 | |
| 182 | <a name='v1_33'></a> |
| 183 | <h2>Changes for Version 1.32 (2015-03-14)</h2> |
| 184 | * When creating a new repository using [/help?cmd=init|fossil init], ensure |
| 185 | that the new repository is fully compatible with historical versions of |
| 186 | Fossil by having a valid manifest as RID 1. |
| 187 | * Anti-aliased rendering of arrowheads on timeline graphs. |
| @@ -168,10 +194,11 @@ | |
| 194 | * Enhance the "ln=" query parameter on artifact displays to accept multiple |
| 195 | ranges, separate by spaces (or "+" when URL-encoded). |
| 196 | * Added [/help?cmd=forget|fossil forget] as an alias for |
| 197 | [/help?cmd=rm|fossil rm]. |
| 198 | |
| 199 | <a name='v1_31'></a> |
| 200 | <h2>Changes For Version 1.31 (2015-02-23)</h2> |
| 201 | * Change the auxiliary schema by adding columns MLINK.ISAUX and MLINK.PMID |
| 202 | columns to the schema, to support better drawing of file change graphs. |
| 203 | A [/help?cmd=rebuild|fossil rebuild] is recommended but is not required. |
| 204 | so that the new graph drawing logic can work effectively. |
| @@ -219,10 +246,11 @@ | |
| 246 | * Allow the user of Common Table Expressions in the SQL that defaults |
| 247 | ticket reports. |
| 248 | * Break out the components (css, footer, and header) for the |
| 249 | various built-in skins into separate files in the source tree. |
| 250 | |
| 251 | <a name='v1_30'></a> |
| 252 | <h2>Changes For Version 1.30 (2015-01-19)</h2> |
| 253 | * Added the [/help?cmd=bundle|fossil bundle] command. |
| 254 | * Added the [/help?cmd=purge|fossil purge] command. |
| 255 | * Added the [/help?cmd=publish|fossil publish] command. |
| 256 | * Added the [/help?cmd=unpublished|fossil unpublished] command. |
| @@ -289,10 +317,11 @@ | |
| 317 | the correctness of printf-style formatting strings. |
| 318 | * Fix CVE-2014-3566, also known as the POODLE SSL 3.0 vulnerability. |
| 319 | * Numerous documentation fixes and improvements. |
| 320 | * Other obscure and minor bug fixes - see the timeline for details. |
| 321 | |
| 322 | <a name='v1_29'></a> |
| 323 | <h2>Changes For Version 1.29 (2014-06-12)</h2> |
| 324 | * Add the ability to display content, diffs and annotations for UTF16 |
| 325 | text files in the web interface. |
| 326 | * Add the "SaveAs..." and "Invert" buttons |
| 327 | to the graphical diff display that results |
| 328 |
+9
-9
| --- www/checkin_names.wiki | ||
| +++ www/checkin_names.wiki | ||
| @@ -55,20 +55,20 @@ | ||
| 55 | 55 | </pre></blockquote> |
| 56 | 56 | |
| 57 | 57 | The full 40-character SHA1 hash is unwieldy to remember and type, though, |
| 58 | 58 | so Fossil also accepts a unique prefix of the hash, using any combination |
| 59 | 59 | of upper and lower case letters, as long as the prefix is at least 4 |
| 60 | -characters long. Hence the following commands all | |
| 60 | +characters long. Hence the following commands all | |
| 61 | 61 | accomplish the same thing as the above: |
| 62 | 62 | |
| 63 | 63 | <blockquote><pre> |
| 64 | 64 | fossil info e5a734a19a9 |
| 65 | 65 | fossil info E5a734A |
| 66 | 66 | fossil info e5a7 |
| 67 | 67 | </blockquote> |
| 68 | 68 | |
| 69 | -Many web-interface screens identify check-ins by 10- or 16-character | |
| 69 | +Many web-interface screens identify check-ins by 10- or 16-character | |
| 70 | 70 | prefix of canonical name. |
| 71 | 71 | |
| 72 | 72 | <h2>Tags And Branch Names</h2> |
| 73 | 73 | |
| 74 | 74 | Using a tag or branch name where a check-in name is expected causes |
| @@ -112,11 +112,11 @@ | ||
| 112 | 112 | |
| 113 | 113 | <blockquote><tt> |
| 114 | 114 | fossil info tag:deed2 |
| 115 | 115 | </tt></blockquote> |
| 116 | 116 | |
| 117 | -The "tag:deed2" name will refer to the most recent check-in | |
| 117 | +The "tag:deed2" name will refer to the most recent check-in | |
| 118 | 118 | tagged with "deed2" not to the |
| 119 | 119 | check-in whose canonical name begins with "deed2". |
| 120 | 120 | |
| 121 | 121 | <h2>Whole Branches</h2> |
| 122 | 122 | |
| @@ -147,11 +147,11 @@ | ||
| 147 | 147 | * <i>YYYY-MM-DD</i> |
| 148 | 148 | * <i>YYYY-MM-DD HH:MM</i> |
| 149 | 149 | * <i>YYYY-MM-DD HH:MM:SS</i> |
| 150 | 150 | * <i>YYYY-MM-DD HH:MM:SS.SSS</i> |
| 151 | 151 | |
| 152 | -The space between the day and the year can optionally be | |
| 152 | +The space between the day and the year can optionally be | |
| 153 | 153 | replaced by an uppercase <b>T</b> and the entire timestamp can |
| 154 | 154 | optionally be followed by "<b>z</b>" or "<b>Z</b>". In the fourth |
| 155 | 155 | form with fractional seconds, any number of digits may follow the |
| 156 | 156 | decimal point, though due to precision limits only the first three |
| 157 | 157 | digits will be significant. |
| @@ -158,17 +158,17 @@ | ||
| 158 | 158 | |
| 159 | 159 | In its default configuration, Fossil interprets and displays all dates |
| 160 | 160 | in Universal Coordinated Time (UTC). This tends to work the best for |
| 161 | 161 | distributed projects where participants are scattered around the globe. |
| 162 | 162 | But there is an option on the Admin/Timeline page of the web-interface to |
| 163 | -switch to local time. The "<b>Z</b>" suffix on an timestamp check-in | |
| 163 | +switch to local time. The "<b>Z</b>" suffix on a timestamp check-in | |
| 164 | 164 | name is meaningless if Fossil is in the default mode of using UTC for |
| 165 | 165 | everything, but if Fossil has been switched to local time mode, then the |
| 166 | -"<b>Z</b>" suffix means to interpret that particular timestamp using | |
| 166 | +"<b>Z</b>" suffix means to interpret that particular timestamp using | |
| 167 | 167 | UTC instead of local time. |
| 168 | 168 | |
| 169 | -For an example of how timestamps are useful, | |
| 169 | +For an example of how timestamps are useful, | |
| 170 | 170 | consider the homepage for the Fossil website itself: |
| 171 | 171 | |
| 172 | 172 | <blockquote> |
| 173 | 173 | http://www.fossil-scm.org/fossil/doc/<b>trunk</b>/www/index.wiki |
| 174 | 174 | </blockquote> |
| @@ -191,11 +191,11 @@ | ||
| 191 | 191 | <blockquote> |
| 192 | 192 | fossil update trunk:2010-07-01T14:30 |
| 193 | 193 | </blockquote> |
| 194 | 194 | |
| 195 | 195 | Would cause Fossil to update the working check-out to be the most recent |
| 196 | -check-in on the trunk that is not more recent that 14:30 (UTC) on | |
| 196 | +check-in on the trunk that is not more recent that 14:30 (UTC) on | |
| 197 | 197 | July 1, 2010. |
| 198 | 198 | |
| 199 | 199 | <h2>Root Of A Branch</h2> |
| 200 | 200 | |
| 201 | 201 | A branch name that begins with the "<tt>root:</tt>" prefix refers to the |
| @@ -220,11 +220,11 @@ | ||
| 220 | 220 | current check-out. And the "previous" or "prev" tag means the primary |
| 221 | 221 | (non-merge) parent of the current check-out. |
| 222 | 222 | |
| 223 | 223 | For embedded documentation, the tag "ckout" means the version as present in |
| 224 | 224 | the local source tree on disk, provided that the web server is started using |
| 225 | -"fossil ui" or "fossil server" from within the source tree. This tag can be | |
| 225 | +"fossil ui" or "fossil server" from within the source tree. This tag can be | |
| 226 | 226 | used to preview local changes to documentation before committing them. It does |
| 227 | 227 | not apply to CLI commands. |
| 228 | 228 | |
| 229 | 229 | <h2>Additional Examples</h2> |
| 230 | 230 | |
| 231 | 231 |
| --- www/checkin_names.wiki | |
| +++ www/checkin_names.wiki | |
| @@ -55,20 +55,20 @@ | |
| 55 | </pre></blockquote> |
| 56 | |
| 57 | The full 40-character SHA1 hash is unwieldy to remember and type, though, |
| 58 | so Fossil also accepts a unique prefix of the hash, using any combination |
| 59 | of upper and lower case letters, as long as the prefix is at least 4 |
| 60 | characters long. Hence the following commands all |
| 61 | accomplish the same thing as the above: |
| 62 | |
| 63 | <blockquote><pre> |
| 64 | fossil info e5a734a19a9 |
| 65 | fossil info E5a734A |
| 66 | fossil info e5a7 |
| 67 | </blockquote> |
| 68 | |
| 69 | Many web-interface screens identify check-ins by 10- or 16-character |
| 70 | prefix of canonical name. |
| 71 | |
| 72 | <h2>Tags And Branch Names</h2> |
| 73 | |
| 74 | Using a tag or branch name where a check-in name is expected causes |
| @@ -112,11 +112,11 @@ | |
| 112 | |
| 113 | <blockquote><tt> |
| 114 | fossil info tag:deed2 |
| 115 | </tt></blockquote> |
| 116 | |
| 117 | The "tag:deed2" name will refer to the most recent check-in |
| 118 | tagged with "deed2" not to the |
| 119 | check-in whose canonical name begins with "deed2". |
| 120 | |
| 121 | <h2>Whole Branches</h2> |
| 122 | |
| @@ -147,11 +147,11 @@ | |
| 147 | * <i>YYYY-MM-DD</i> |
| 148 | * <i>YYYY-MM-DD HH:MM</i> |
| 149 | * <i>YYYY-MM-DD HH:MM:SS</i> |
| 150 | * <i>YYYY-MM-DD HH:MM:SS.SSS</i> |
| 151 | |
| 152 | The space between the day and the year can optionally be |
| 153 | replaced by an uppercase <b>T</b> and the entire timestamp can |
| 154 | optionally be followed by "<b>z</b>" or "<b>Z</b>". In the fourth |
| 155 | form with fractional seconds, any number of digits may follow the |
| 156 | decimal point, though due to precision limits only the first three |
| 157 | digits will be significant. |
| @@ -158,17 +158,17 @@ | |
| 158 | |
| 159 | In its default configuration, Fossil interprets and displays all dates |
| 160 | in Universal Coordinated Time (UTC). This tends to work the best for |
| 161 | distributed projects where participants are scattered around the globe. |
| 162 | But there is an option on the Admin/Timeline page of the web-interface to |
| 163 | switch to local time. The "<b>Z</b>" suffix on an timestamp check-in |
| 164 | name is meaningless if Fossil is in the default mode of using UTC for |
| 165 | everything, but if Fossil has been switched to local time mode, then the |
| 166 | "<b>Z</b>" suffix means to interpret that particular timestamp using |
| 167 | UTC instead of local time. |
| 168 | |
| 169 | For an example of how timestamps are useful, |
| 170 | consider the homepage for the Fossil website itself: |
| 171 | |
| 172 | <blockquote> |
| 173 | http://www.fossil-scm.org/fossil/doc/<b>trunk</b>/www/index.wiki |
| 174 | </blockquote> |
| @@ -191,11 +191,11 @@ | |
| 191 | <blockquote> |
| 192 | fossil update trunk:2010-07-01T14:30 |
| 193 | </blockquote> |
| 194 | |
| 195 | Would cause Fossil to update the working check-out to be the most recent |
| 196 | check-in on the trunk that is not more recent that 14:30 (UTC) on |
| 197 | July 1, 2010. |
| 198 | |
| 199 | <h2>Root Of A Branch</h2> |
| 200 | |
| 201 | A branch name that begins with the "<tt>root:</tt>" prefix refers to the |
| @@ -220,11 +220,11 @@ | |
| 220 | current check-out. And the "previous" or "prev" tag means the primary |
| 221 | (non-merge) parent of the current check-out. |
| 222 | |
| 223 | For embedded documentation, the tag "ckout" means the version as present in |
| 224 | the local source tree on disk, provided that the web server is started using |
| 225 | "fossil ui" or "fossil server" from within the source tree. This tag can be |
| 226 | used to preview local changes to documentation before committing them. It does |
| 227 | not apply to CLI commands. |
| 228 | |
| 229 | <h2>Additional Examples</h2> |
| 230 | |
| 231 |
| --- www/checkin_names.wiki | |
| +++ www/checkin_names.wiki | |
| @@ -55,20 +55,20 @@ | |
| 55 | </pre></blockquote> |
| 56 | |
| 57 | The full 40-character SHA1 hash is unwieldy to remember and type, though, |
| 58 | so Fossil also accepts a unique prefix of the hash, using any combination |
| 59 | of upper and lower case letters, as long as the prefix is at least 4 |
| 60 | characters long. Hence the following commands all |
| 61 | accomplish the same thing as the above: |
| 62 | |
| 63 | <blockquote><pre> |
| 64 | fossil info e5a734a19a9 |
| 65 | fossil info E5a734A |
| 66 | fossil info e5a7 |
| 67 | </blockquote> |
| 68 | |
| 69 | Many web-interface screens identify check-ins by 10- or 16-character |
| 70 | prefix of canonical name. |
| 71 | |
| 72 | <h2>Tags And Branch Names</h2> |
| 73 | |
| 74 | Using a tag or branch name where a check-in name is expected causes |
| @@ -112,11 +112,11 @@ | |
| 112 | |
| 113 | <blockquote><tt> |
| 114 | fossil info tag:deed2 |
| 115 | </tt></blockquote> |
| 116 | |
| 117 | The "tag:deed2" name will refer to the most recent check-in |
| 118 | tagged with "deed2" not to the |
| 119 | check-in whose canonical name begins with "deed2". |
| 120 | |
| 121 | <h2>Whole Branches</h2> |
| 122 | |
| @@ -147,11 +147,11 @@ | |
| 147 | * <i>YYYY-MM-DD</i> |
| 148 | * <i>YYYY-MM-DD HH:MM</i> |
| 149 | * <i>YYYY-MM-DD HH:MM:SS</i> |
| 150 | * <i>YYYY-MM-DD HH:MM:SS.SSS</i> |
| 151 | |
| 152 | The space between the day and the year can optionally be |
| 153 | replaced by an uppercase <b>T</b> and the entire timestamp can |
| 154 | optionally be followed by "<b>z</b>" or "<b>Z</b>". In the fourth |
| 155 | form with fractional seconds, any number of digits may follow the |
| 156 | decimal point, though due to precision limits only the first three |
| 157 | digits will be significant. |
| @@ -158,17 +158,17 @@ | |
| 158 | |
| 159 | In its default configuration, Fossil interprets and displays all dates |
| 160 | in Universal Coordinated Time (UTC). This tends to work the best for |
| 161 | distributed projects where participants are scattered around the globe. |
| 162 | But there is an option on the Admin/Timeline page of the web-interface to |
| 163 | switch to local time. The "<b>Z</b>" suffix on a timestamp check-in |
| 164 | name is meaningless if Fossil is in the default mode of using UTC for |
| 165 | everything, but if Fossil has been switched to local time mode, then the |
| 166 | "<b>Z</b>" suffix means to interpret that particular timestamp using |
| 167 | UTC instead of local time. |
| 168 | |
| 169 | For an example of how timestamps are useful, |
| 170 | consider the homepage for the Fossil website itself: |
| 171 | |
| 172 | <blockquote> |
| 173 | http://www.fossil-scm.org/fossil/doc/<b>trunk</b>/www/index.wiki |
| 174 | </blockquote> |
| @@ -191,11 +191,11 @@ | |
| 191 | <blockquote> |
| 192 | fossil update trunk:2010-07-01T14:30 |
| 193 | </blockquote> |
| 194 | |
| 195 | Would cause Fossil to update the working check-out to be the most recent |
| 196 | check-in on the trunk that is not more recent that 14:30 (UTC) on |
| 197 | July 1, 2010. |
| 198 | |
| 199 | <h2>Root Of A Branch</h2> |
| 200 | |
| 201 | A branch name that begins with the "<tt>root:</tt>" prefix refers to the |
| @@ -220,11 +220,11 @@ | |
| 220 | current check-out. And the "previous" or "prev" tag means the primary |
| 221 | (non-merge) parent of the current check-out. |
| 222 | |
| 223 | For embedded documentation, the tag "ckout" means the version as present in |
| 224 | the local source tree on disk, provided that the web server is started using |
| 225 | "fossil ui" or "fossil server" from within the source tree. This tag can be |
| 226 | used to preview local changes to documentation before committing them. It does |
| 227 | not apply to CLI commands. |
| 228 | |
| 229 | <h2>Additional Examples</h2> |
| 230 | |
| 231 |
+3
-3
| --- www/childprojects.wiki | ||
| +++ www/childprojects.wiki | ||
| @@ -37,21 +37,21 @@ | ||
| 37 | 37 | VALUES('project-code',lower(hex(randomblob(20)))); |
| 38 | 38 | INSERT INTO config(name,value) |
| 39 | 39 | VALUES('project-name','CHILD-PROJECT-NAME'); |
| 40 | 40 | </verbatim></blockquote> |
| 41 | 41 | |
| 42 | -Modify the CHILD-PROJECT-NAME in the last statement to be the name of | |
| 42 | +Modify the CHILD-PROJECT-NAME in the last statement to be the name of | |
| 43 | 43 | the child project, of course. |
| 44 | 44 | |
| 45 | 45 | The repository is now a separate project, independent from its parent. |
| 46 | 46 | Clone the new project to the developers as needed. |
| 47 | 47 | |
| 48 | 48 | The child project and the parent project will not normally be able to sync |
| 49 | 49 | with one another, since they are now separate projects with distinct |
| 50 | 50 | project codes. However, if the |
| 51 | -"--from-parent-project" command-line option is provided to the | |
| 52 | -"[/help?cmd=pull|fossil pull]" command in the child, and the URL of | |
| 51 | +"--from-parent-project" command-line option is provided to the | |
| 52 | +"[/help?cmd=pull|fossil pull]" command in the child, and the URL of | |
| 53 | 53 | parent repository is also provided on the command-line, then updates to |
| 54 | 54 | the parent project that occurred after the child was created will be added |
| 55 | 55 | to the child repository. Thus, by periodically doing a |
| 56 | 56 | pull --from-parent-project, the child project is able to stay up to date |
| 57 | 57 | with all the latest changes in the parent. |
| 58 | 58 |
| --- www/childprojects.wiki | |
| +++ www/childprojects.wiki | |
| @@ -37,21 +37,21 @@ | |
| 37 | VALUES('project-code',lower(hex(randomblob(20)))); |
| 38 | INSERT INTO config(name,value) |
| 39 | VALUES('project-name','CHILD-PROJECT-NAME'); |
| 40 | </verbatim></blockquote> |
| 41 | |
| 42 | Modify the CHILD-PROJECT-NAME in the last statement to be the name of |
| 43 | the child project, of course. |
| 44 | |
| 45 | The repository is now a separate project, independent from its parent. |
| 46 | Clone the new project to the developers as needed. |
| 47 | |
| 48 | The child project and the parent project will not normally be able to sync |
| 49 | with one another, since they are now separate projects with distinct |
| 50 | project codes. However, if the |
| 51 | "--from-parent-project" command-line option is provided to the |
| 52 | "[/help?cmd=pull|fossil pull]" command in the child, and the URL of |
| 53 | parent repository is also provided on the command-line, then updates to |
| 54 | the parent project that occurred after the child was created will be added |
| 55 | to the child repository. Thus, by periodically doing a |
| 56 | pull --from-parent-project, the child project is able to stay up to date |
| 57 | with all the latest changes in the parent. |
| 58 |
| --- www/childprojects.wiki | |
| +++ www/childprojects.wiki | |
| @@ -37,21 +37,21 @@ | |
| 37 | VALUES('project-code',lower(hex(randomblob(20)))); |
| 38 | INSERT INTO config(name,value) |
| 39 | VALUES('project-name','CHILD-PROJECT-NAME'); |
| 40 | </verbatim></blockquote> |
| 41 | |
| 42 | Modify the CHILD-PROJECT-NAME in the last statement to be the name of |
| 43 | the child project, of course. |
| 44 | |
| 45 | The repository is now a separate project, independent from its parent. |
| 46 | Clone the new project to the developers as needed. |
| 47 | |
| 48 | The child project and the parent project will not normally be able to sync |
| 49 | with one another, since they are now separate projects with distinct |
| 50 | project codes. However, if the |
| 51 | "--from-parent-project" command-line option is provided to the |
| 52 | "[/help?cmd=pull|fossil pull]" command in the child, and the URL of |
| 53 | parent repository is also provided on the command-line, then updates to |
| 54 | the parent project that occurred after the child was created will be added |
| 55 | to the child repository. Thus, by periodically doing a |
| 56 | pull --from-parent-project, the child project is able to stay up to date |
| 57 | with all the latest changes in the parent. |
| 58 |
+13
-8
| --- www/concepts.wiki | ||
| +++ www/concepts.wiki | ||
| @@ -13,10 +13,15 @@ | ||
| 13 | 13 | to setup and operate. |
| 14 | 14 | |
| 15 | 15 | This document is intended as a quick introduction to the concepts |
| 16 | 16 | behind Fossil. |
| 17 | 17 | |
| 18 | +See also: | |
| 19 | + | |
| 20 | + * [./whyusefossil.wiki#definitions|Definitions] | |
| 21 | + * [./quickstart.wiki|Quick start guide] | |
| 22 | + | |
| 18 | 23 | <h2>2.0 Composition Of A Project</h2> |
| 19 | 24 | <img src="concept1.gif" align="right" hspace="10"> |
| 20 | 25 | |
| 21 | 26 | A software project normally consists of a "source tree". |
| 22 | 27 | A source tree is a hierarchy of files that are used to generate |
| @@ -126,11 +131,11 @@ | ||
| 126 | 131 | <h3>2.2 Manifests</h3> |
| 127 | 132 | |
| 128 | 133 | Associated with every check-in is a special file called the |
| 129 | 134 | [./fileformat.wiki#manifest| "manifest"]. The manifest is a |
| 130 | 135 | listing of all other files in |
| 131 | -that source tree. The manifest contains the (complete) artifact ID | |
| 136 | +that source tree. The manifest contains the (complete) artifact ID | |
| 132 | 137 | of the file and the name of the file as it appears on disk, |
| 133 | 138 | and thus serves as a mapping from artifact ID to disk name. The artifact ID |
| 134 | 139 | of the manifest is the identifier for the entire check-in. When |
| 135 | 140 | you look at a "timeline" of changes in Fossil, the ID associated |
| 136 | 141 | with each check-in or commit is really just the artifact ID of the |
| @@ -142,11 +147,11 @@ | ||
| 142 | 147 | manifest file to be materialized to disk, if desired. Both Fossil |
| 143 | 148 | itself, and SQLite cause the manifest file to be materialized to disk |
| 144 | 149 | so that the makefiles for these project can read the manifest and |
| 145 | 150 | embed version information in generated binaries. |
| 146 | 151 | |
| 147 | -<p>Fossil automatically generates a manifest whenever you "commit" | |
| 152 | +<p>Fossil automatically generates a manifest whenever you "commit" | |
| 148 | 153 | a new check-in. So this is not something that you, the developer, |
| 149 | 154 | need to worry with. The format of a manifest is intentionally |
| 150 | 155 | designed to be simple to parse, so that if |
| 151 | 156 | you want to read and interpret a manifest, either by hand or |
| 152 | 157 | with a script, that is easy to do. But you will probably never |
| @@ -195,11 +200,11 @@ | ||
| 195 | 200 | Fossil effectively. You will want to have some kind of text editor |
| 196 | 201 | for entering check-in comments. Fossil will use whatever text editor |
| 197 | 202 | is identified by your VISUAL environment variable. Fossil will also |
| 198 | 203 | use GPG to clearsign your manifests if you happen to have it installed, |
| 199 | 204 | but Fossil will skip that step if GPG missing from your system. |
| 200 | -You can optionally set up Fossil to use external "diff" programs, | |
| 205 | +You can optionally set up Fossil to use external "diff" programs, | |
| 201 | 206 | though Fossil has an excellent built-in "diff" algorithm that works |
| 202 | 207 | fine for most people. If you happen to have Tcl/Tk installed on your |
| 203 | 208 | system, Fossil will use it to generate a graphical "diff" display when |
| 204 | 209 | you use the --tk option to the "diff" command, but this too is entirely |
| 205 | 210 | optional. |
| @@ -206,11 +211,11 @@ | ||
| 206 | 211 | |
| 207 | 212 | |
| 208 | 213 | To uninstall Fossil, simply delete the executable. |
| 209 | 214 | |
| 210 | 215 | To upgrade an older version of Fossil to a newer version, just |
| 211 | -replace the old executable with the new one. You might need to | |
| 216 | +replace the old executable with the new one. You might need to | |
| 212 | 217 | run "<b>fossil all rebuild</b>" to restructure your repositories after |
| 213 | 218 | an upgrade. Running "all rebuild" never hurts, so when upgrading it |
| 214 | 219 | is a good policy to run it even if it is not strictly necessary. |
| 215 | 220 | |
| 216 | 221 | To use Fossil, simply type the name of the executable in your |
| @@ -261,11 +266,11 @@ | ||
| 261 | 266 | |
| 262 | 267 | <ol> |
| 263 | 268 | <li> |
| 264 | 269 | Establish a local repository using either the <b>new</b> command |
| 265 | 270 | to start a new project, or the <b>clone</b> command to make a clone |
| 266 | -of a repository for an existing project. | |
| 271 | +of a repository for an existing project. | |
| 267 | 272 | </li> |
| 268 | 273 | |
| 269 | 274 | <li> |
| 270 | 275 | Establish one or more source trees using |
| 271 | 276 | the <b>open</b> command with the name of the repository file as its |
| @@ -274,11 +279,11 @@ | ||
| 274 | 279 | |
| 275 | 280 | <li> |
| 276 | 281 | The <b>open</b> command in the previous step populates your local source |
| 277 | 282 | tree with a copy of the latest check-in. Usually this is what you want. |
| 278 | 283 | In the rare cases where it is not, use the <b>update</b> command to |
| 279 | -switch to a different check-in. | |
| 284 | +switch to a different check-in. | |
| 280 | 285 | Use the <b>timeline</b> or <b>leaves</b> commands |
| 281 | 286 | to identify alternative check-ins to switch to. |
| 282 | 287 | </li> |
| 283 | 288 | |
| 284 | 289 | <li> |
| @@ -297,17 +302,17 @@ | ||
| 297 | 302 | you cloned from or whatever server you most recently synced with. |
| 298 | 303 | </li> |
| 299 | 304 | |
| 300 | 305 | <li> |
| 301 | 306 | When your coworkers make their own changes, you can merge those changes |
| 302 | -into your local local source tree using the <b>update</b> command. | |
| 307 | +into your local local source tree using the <b>update</b> command. | |
| 303 | 308 | In autosync mode, <b>update</b> will first go back to the server you |
| 304 | 309 | cloned from or with which you most recently synced, and pull down all |
| 305 | 310 | recent changes into your local repository. Then it will merge recent |
| 306 | 311 | changes into your local source tree. If you do an <b>update</b> and |
| 307 | 312 | find that it messes something up in your source tree (perhaps a co-worker |
| 308 | -checked in incompatible changes) you can use the <b>undo</b> command | |
| 313 | +checked in incompatible changes) you can use the <b>undo</b> command | |
| 309 | 314 | to back out the changes. |
| 310 | 315 | </li> |
| 311 | 316 | |
| 312 | 317 | <li> |
| 313 | 318 | Repeat all of the above until you have generated great software. |
| 314 | 319 |
| --- www/concepts.wiki | |
| +++ www/concepts.wiki | |
| @@ -13,10 +13,15 @@ | |
| 13 | to setup and operate. |
| 14 | |
| 15 | This document is intended as a quick introduction to the concepts |
| 16 | behind Fossil. |
| 17 | |
| 18 | <h2>2.0 Composition Of A Project</h2> |
| 19 | <img src="concept1.gif" align="right" hspace="10"> |
| 20 | |
| 21 | A software project normally consists of a "source tree". |
| 22 | A source tree is a hierarchy of files that are used to generate |
| @@ -126,11 +131,11 @@ | |
| 126 | <h3>2.2 Manifests</h3> |
| 127 | |
| 128 | Associated with every check-in is a special file called the |
| 129 | [./fileformat.wiki#manifest| "manifest"]. The manifest is a |
| 130 | listing of all other files in |
| 131 | that source tree. The manifest contains the (complete) artifact ID |
| 132 | of the file and the name of the file as it appears on disk, |
| 133 | and thus serves as a mapping from artifact ID to disk name. The artifact ID |
| 134 | of the manifest is the identifier for the entire check-in. When |
| 135 | you look at a "timeline" of changes in Fossil, the ID associated |
| 136 | with each check-in or commit is really just the artifact ID of the |
| @@ -142,11 +147,11 @@ | |
| 142 | manifest file to be materialized to disk, if desired. Both Fossil |
| 143 | itself, and SQLite cause the manifest file to be materialized to disk |
| 144 | so that the makefiles for these project can read the manifest and |
| 145 | embed version information in generated binaries. |
| 146 | |
| 147 | <p>Fossil automatically generates a manifest whenever you "commit" |
| 148 | a new check-in. So this is not something that you, the developer, |
| 149 | need to worry with. The format of a manifest is intentionally |
| 150 | designed to be simple to parse, so that if |
| 151 | you want to read and interpret a manifest, either by hand or |
| 152 | with a script, that is easy to do. But you will probably never |
| @@ -195,11 +200,11 @@ | |
| 195 | Fossil effectively. You will want to have some kind of text editor |
| 196 | for entering check-in comments. Fossil will use whatever text editor |
| 197 | is identified by your VISUAL environment variable. Fossil will also |
| 198 | use GPG to clearsign your manifests if you happen to have it installed, |
| 199 | but Fossil will skip that step if GPG missing from your system. |
| 200 | You can optionally set up Fossil to use external "diff" programs, |
| 201 | though Fossil has an excellent built-in "diff" algorithm that works |
| 202 | fine for most people. If you happen to have Tcl/Tk installed on your |
| 203 | system, Fossil will use it to generate a graphical "diff" display when |
| 204 | you use the --tk option to the "diff" command, but this too is entirely |
| 205 | optional. |
| @@ -206,11 +211,11 @@ | |
| 206 | |
| 207 | |
| 208 | To uninstall Fossil, simply delete the executable. |
| 209 | |
| 210 | To upgrade an older version of Fossil to a newer version, just |
| 211 | replace the old executable with the new one. You might need to |
| 212 | run "<b>fossil all rebuild</b>" to restructure your repositories after |
| 213 | an upgrade. Running "all rebuild" never hurts, so when upgrading it |
| 214 | is a good policy to run it even if it is not strictly necessary. |
| 215 | |
| 216 | To use Fossil, simply type the name of the executable in your |
| @@ -261,11 +266,11 @@ | |
| 261 | |
| 262 | <ol> |
| 263 | <li> |
| 264 | Establish a local repository using either the <b>new</b> command |
| 265 | to start a new project, or the <b>clone</b> command to make a clone |
| 266 | of a repository for an existing project. |
| 267 | </li> |
| 268 | |
| 269 | <li> |
| 270 | Establish one or more source trees using |
| 271 | the <b>open</b> command with the name of the repository file as its |
| @@ -274,11 +279,11 @@ | |
| 274 | |
| 275 | <li> |
| 276 | The <b>open</b> command in the previous step populates your local source |
| 277 | tree with a copy of the latest check-in. Usually this is what you want. |
| 278 | In the rare cases where it is not, use the <b>update</b> command to |
| 279 | switch to a different check-in. |
| 280 | Use the <b>timeline</b> or <b>leaves</b> commands |
| 281 | to identify alternative check-ins to switch to. |
| 282 | </li> |
| 283 | |
| 284 | <li> |
| @@ -297,17 +302,17 @@ | |
| 297 | you cloned from or whatever server you most recently synced with. |
| 298 | </li> |
| 299 | |
| 300 | <li> |
| 301 | When your coworkers make their own changes, you can merge those changes |
| 302 | into your local local source tree using the <b>update</b> command. |
| 303 | In autosync mode, <b>update</b> will first go back to the server you |
| 304 | cloned from or with which you most recently synced, and pull down all |
| 305 | recent changes into your local repository. Then it will merge recent |
| 306 | changes into your local source tree. If you do an <b>update</b> and |
| 307 | find that it messes something up in your source tree (perhaps a co-worker |
| 308 | checked in incompatible changes) you can use the <b>undo</b> command |
| 309 | to back out the changes. |
| 310 | </li> |
| 311 | |
| 312 | <li> |
| 313 | Repeat all of the above until you have generated great software. |
| 314 |
| --- www/concepts.wiki | |
| +++ www/concepts.wiki | |
| @@ -13,10 +13,15 @@ | |
| 13 | to setup and operate. |
| 14 | |
| 15 | This document is intended as a quick introduction to the concepts |
| 16 | behind Fossil. |
| 17 | |
| 18 | See also: |
| 19 | |
| 20 | * [./whyusefossil.wiki#definitions|Definitions] |
| 21 | * [./quickstart.wiki|Quick start guide] |
| 22 | |
| 23 | <h2>2.0 Composition Of A Project</h2> |
| 24 | <img src="concept1.gif" align="right" hspace="10"> |
| 25 | |
| 26 | A software project normally consists of a "source tree". |
| 27 | A source tree is a hierarchy of files that are used to generate |
| @@ -126,11 +131,11 @@ | |
| 131 | <h3>2.2 Manifests</h3> |
| 132 | |
| 133 | Associated with every check-in is a special file called the |
| 134 | [./fileformat.wiki#manifest| "manifest"]. The manifest is a |
| 135 | listing of all other files in |
| 136 | that source tree. The manifest contains the (complete) artifact ID |
| 137 | of the file and the name of the file as it appears on disk, |
| 138 | and thus serves as a mapping from artifact ID to disk name. The artifact ID |
| 139 | of the manifest is the identifier for the entire check-in. When |
| 140 | you look at a "timeline" of changes in Fossil, the ID associated |
| 141 | with each check-in or commit is really just the artifact ID of the |
| @@ -142,11 +147,11 @@ | |
| 147 | manifest file to be materialized to disk, if desired. Both Fossil |
| 148 | itself, and SQLite cause the manifest file to be materialized to disk |
| 149 | so that the makefiles for these project can read the manifest and |
| 150 | embed version information in generated binaries. |
| 151 | |
| 152 | <p>Fossil automatically generates a manifest whenever you "commit" |
| 153 | a new check-in. So this is not something that you, the developer, |
| 154 | need to worry with. The format of a manifest is intentionally |
| 155 | designed to be simple to parse, so that if |
| 156 | you want to read and interpret a manifest, either by hand or |
| 157 | with a script, that is easy to do. But you will probably never |
| @@ -195,11 +200,11 @@ | |
| 200 | Fossil effectively. You will want to have some kind of text editor |
| 201 | for entering check-in comments. Fossil will use whatever text editor |
| 202 | is identified by your VISUAL environment variable. Fossil will also |
| 203 | use GPG to clearsign your manifests if you happen to have it installed, |
| 204 | but Fossil will skip that step if GPG missing from your system. |
| 205 | You can optionally set up Fossil to use external "diff" programs, |
| 206 | though Fossil has an excellent built-in "diff" algorithm that works |
| 207 | fine for most people. If you happen to have Tcl/Tk installed on your |
| 208 | system, Fossil will use it to generate a graphical "diff" display when |
| 209 | you use the --tk option to the "diff" command, but this too is entirely |
| 210 | optional. |
| @@ -206,11 +211,11 @@ | |
| 211 | |
| 212 | |
| 213 | To uninstall Fossil, simply delete the executable. |
| 214 | |
| 215 | To upgrade an older version of Fossil to a newer version, just |
| 216 | replace the old executable with the new one. You might need to |
| 217 | run "<b>fossil all rebuild</b>" to restructure your repositories after |
| 218 | an upgrade. Running "all rebuild" never hurts, so when upgrading it |
| 219 | is a good policy to run it even if it is not strictly necessary. |
| 220 | |
| 221 | To use Fossil, simply type the name of the executable in your |
| @@ -261,11 +266,11 @@ | |
| 266 | |
| 267 | <ol> |
| 268 | <li> |
| 269 | Establish a local repository using either the <b>new</b> command |
| 270 | to start a new project, or the <b>clone</b> command to make a clone |
| 271 | of a repository for an existing project. |
| 272 | </li> |
| 273 | |
| 274 | <li> |
| 275 | Establish one or more source trees using |
| 276 | the <b>open</b> command with the name of the repository file as its |
| @@ -274,11 +279,11 @@ | |
| 279 | |
| 280 | <li> |
| 281 | The <b>open</b> command in the previous step populates your local source |
| 282 | tree with a copy of the latest check-in. Usually this is what you want. |
| 283 | In the rare cases where it is not, use the <b>update</b> command to |
| 284 | switch to a different check-in. |
| 285 | Use the <b>timeline</b> or <b>leaves</b> commands |
| 286 | to identify alternative check-ins to switch to. |
| 287 | </li> |
| 288 | |
| 289 | <li> |
| @@ -297,17 +302,17 @@ | |
| 302 | you cloned from or whatever server you most recently synced with. |
| 303 | </li> |
| 304 | |
| 305 | <li> |
| 306 | When your coworkers make their own changes, you can merge those changes |
| 307 | into your local local source tree using the <b>update</b> command. |
| 308 | In autosync mode, <b>update</b> will first go back to the server you |
| 309 | cloned from or with which you most recently synced, and pull down all |
| 310 | recent changes into your local repository. Then it will merge recent |
| 311 | changes into your local source tree. If you do an <b>update</b> and |
| 312 | find that it messes something up in your source tree (perhaps a co-worker |
| 313 | checked in incompatible changes) you can use the <b>undo</b> command |
| 314 | to back out the changes. |
| 315 | </li> |
| 316 | |
| 317 | <li> |
| 318 | Repeat all of the above until you have generated great software. |
| 319 |
+7
-7
| --- www/contribute.wiki | ||
| +++ www/contribute.wiki | ||
| @@ -10,11 +10,11 @@ | ||
| 10 | 10 | [./copyright-release.pdf | Contributor Agreement (PDF)] |
| 11 | 11 | (or [./copyright-release.html | as HTML]) on file for you. We require |
| 12 | 12 | this in order to maintain clear title to the Fossil code and prevent |
| 13 | 13 | the introduction of code with incompatible licenses or other entanglements |
| 14 | 14 | that might cause legal problems for Fossil users. Many larger companies |
| 15 | -and other lawyer-rich organizations require this as a precondition to using | |
| 15 | +and other lawyer-rich organizations require this as a precondition to using | |
| 16 | 16 | Fossil. |
| 17 | 17 | |
| 18 | 18 | If you do not wish to submit a Contributor Agreement, we would still |
| 19 | 19 | welcome your suggestions and example code, but we will not use your code |
| 20 | 20 | directly - we will be forced to re-implement your changes from scratch which |
| @@ -21,14 +21,14 @@ | ||
| 21 | 21 | might take longer. |
| 22 | 22 | |
| 23 | 23 | <h2>2.0 Submitting Patches</h2> |
| 24 | 24 | |
| 25 | 25 | Suggested changes or bug fixes can be submitted by creating a patch |
| 26 | -against the current source tree. Email patches to | |
| 27 | -<a href="mailto:[email protected]">[email protected]</a>. Be sure to | |
| 26 | +against the current source tree. Email patches to | |
| 27 | +<a href="mailto:[email protected]">[email protected]</a>. Be sure to | |
| 28 | 28 | describe in detail what the patch does and which version of Fossil |
| 29 | -it is written against. | |
| 29 | +it is written against. | |
| 30 | 30 | |
| 31 | 31 | A contributor agreement is not strictly necessary to submit a patch. |
| 32 | 32 | However, without a contributor agreement on file, your patch will be |
| 33 | 33 | used for reference only - it will not be applied to the code. This |
| 34 | 34 | may delay acceptance of your patch. |
| @@ -53,23 +53,23 @@ | ||
| 53 | 53 | Fossil Architect (Richard Hipp) will merge changes onto the trunk.</p> |
| 54 | 54 | |
| 55 | 55 | Contributors are required to following the |
| 56 | 56 | [./checkin.wiki | pre-checkin checklist] prior to every check-in to |
| 57 | 57 | the Fossil self-hosting repository. This checklist is short and succinct |
| 58 | -and should only require a few seconds to follow. Contributors | |
| 58 | +and should only require a few seconds to follow. Contributors | |
| 59 | 59 | should print out a copy of the pre-checkin checklist and keep |
| 60 | 60 | it on a notecard beside their workstations, for quick reference. |
| 61 | 61 | |
| 62 | 62 | Contributors should review the |
| 63 | 63 | [./style.wiki | Coding Style Guidelines] and mimic the coding style |
| 64 | 64 | used through the rest of the Fossil source code. Your code should |
| 65 | 65 | blend in. A third-party reader should be unable to distinguish your |
| 66 | -code from any other code in the source corpus. | |
| 66 | +code from any other code in the source corpus. | |
| 67 | 67 | |
| 68 | 68 | <h2>4.0 Testing</h2> |
| 69 | 69 | |
| 70 | -Fossil has the beginnings of a | |
| 70 | +Fossil has the beginnings of a | |
| 71 | 71 | [../test/release-checklist.wiki | release checklist] but this is an |
| 72 | 72 | area that needs further work. (Your contributions here are welcomed!) |
| 73 | 73 | Contributors with check-in privileges are expected to run the release |
| 74 | 74 | checklist on any major changes they contribute, and if appropriate expand |
| 75 | 75 | the checklist and/or the automated test scripts to cover their additions. |
| 76 | 76 |
| --- www/contribute.wiki | |
| +++ www/contribute.wiki | |
| @@ -10,11 +10,11 @@ | |
| 10 | [./copyright-release.pdf | Contributor Agreement (PDF)] |
| 11 | (or [./copyright-release.html | as HTML]) on file for you. We require |
| 12 | this in order to maintain clear title to the Fossil code and prevent |
| 13 | the introduction of code with incompatible licenses or other entanglements |
| 14 | that might cause legal problems for Fossil users. Many larger companies |
| 15 | and other lawyer-rich organizations require this as a precondition to using |
| 16 | Fossil. |
| 17 | |
| 18 | If you do not wish to submit a Contributor Agreement, we would still |
| 19 | welcome your suggestions and example code, but we will not use your code |
| 20 | directly - we will be forced to re-implement your changes from scratch which |
| @@ -21,14 +21,14 @@ | |
| 21 | might take longer. |
| 22 | |
| 23 | <h2>2.0 Submitting Patches</h2> |
| 24 | |
| 25 | Suggested changes or bug fixes can be submitted by creating a patch |
| 26 | against the current source tree. Email patches to |
| 27 | <a href="mailto:[email protected]">[email protected]</a>. Be sure to |
| 28 | describe in detail what the patch does and which version of Fossil |
| 29 | it is written against. |
| 30 | |
| 31 | A contributor agreement is not strictly necessary to submit a patch. |
| 32 | However, without a contributor agreement on file, your patch will be |
| 33 | used for reference only - it will not be applied to the code. This |
| 34 | may delay acceptance of your patch. |
| @@ -53,23 +53,23 @@ | |
| 53 | Fossil Architect (Richard Hipp) will merge changes onto the trunk.</p> |
| 54 | |
| 55 | Contributors are required to following the |
| 56 | [./checkin.wiki | pre-checkin checklist] prior to every check-in to |
| 57 | the Fossil self-hosting repository. This checklist is short and succinct |
| 58 | and should only require a few seconds to follow. Contributors |
| 59 | should print out a copy of the pre-checkin checklist and keep |
| 60 | it on a notecard beside their workstations, for quick reference. |
| 61 | |
| 62 | Contributors should review the |
| 63 | [./style.wiki | Coding Style Guidelines] and mimic the coding style |
| 64 | used through the rest of the Fossil source code. Your code should |
| 65 | blend in. A third-party reader should be unable to distinguish your |
| 66 | code from any other code in the source corpus. |
| 67 | |
| 68 | <h2>4.0 Testing</h2> |
| 69 | |
| 70 | Fossil has the beginnings of a |
| 71 | [../test/release-checklist.wiki | release checklist] but this is an |
| 72 | area that needs further work. (Your contributions here are welcomed!) |
| 73 | Contributors with check-in privileges are expected to run the release |
| 74 | checklist on any major changes they contribute, and if appropriate expand |
| 75 | the checklist and/or the automated test scripts to cover their additions. |
| 76 |
| --- www/contribute.wiki | |
| +++ www/contribute.wiki | |
| @@ -10,11 +10,11 @@ | |
| 10 | [./copyright-release.pdf | Contributor Agreement (PDF)] |
| 11 | (or [./copyright-release.html | as HTML]) on file for you. We require |
| 12 | this in order to maintain clear title to the Fossil code and prevent |
| 13 | the introduction of code with incompatible licenses or other entanglements |
| 14 | that might cause legal problems for Fossil users. Many larger companies |
| 15 | and other lawyer-rich organizations require this as a precondition to using |
| 16 | Fossil. |
| 17 | |
| 18 | If you do not wish to submit a Contributor Agreement, we would still |
| 19 | welcome your suggestions and example code, but we will not use your code |
| 20 | directly - we will be forced to re-implement your changes from scratch which |
| @@ -21,14 +21,14 @@ | |
| 21 | might take longer. |
| 22 | |
| 23 | <h2>2.0 Submitting Patches</h2> |
| 24 | |
| 25 | Suggested changes or bug fixes can be submitted by creating a patch |
| 26 | against the current source tree. Email patches to |
| 27 | <a href="mailto:[email protected]">[email protected]</a>. Be sure to |
| 28 | describe in detail what the patch does and which version of Fossil |
| 29 | it is written against. |
| 30 | |
| 31 | A contributor agreement is not strictly necessary to submit a patch. |
| 32 | However, without a contributor agreement on file, your patch will be |
| 33 | used for reference only - it will not be applied to the code. This |
| 34 | may delay acceptance of your patch. |
| @@ -53,23 +53,23 @@ | |
| 53 | Fossil Architect (Richard Hipp) will merge changes onto the trunk.</p> |
| 54 | |
| 55 | Contributors are required to following the |
| 56 | [./checkin.wiki | pre-checkin checklist] prior to every check-in to |
| 57 | the Fossil self-hosting repository. This checklist is short and succinct |
| 58 | and should only require a few seconds to follow. Contributors |
| 59 | should print out a copy of the pre-checkin checklist and keep |
| 60 | it on a notecard beside their workstations, for quick reference. |
| 61 | |
| 62 | Contributors should review the |
| 63 | [./style.wiki | Coding Style Guidelines] and mimic the coding style |
| 64 | used through the rest of the Fossil source code. Your code should |
| 65 | blend in. A third-party reader should be unable to distinguish your |
| 66 | code from any other code in the source corpus. |
| 67 | |
| 68 | <h2>4.0 Testing</h2> |
| 69 | |
| 70 | Fossil has the beginnings of a |
| 71 | [../test/release-checklist.wiki | release checklist] but this is an |
| 72 | area that needs further work. (Your contributions here are welcomed!) |
| 73 | Contributors with check-in privileges are expected to run the release |
| 74 | checklist on any major changes they contribute, and if appropriate expand |
| 75 | the checklist and/or the automated test scripts to cover their additions. |
| 76 |
+2
-2
| --- www/custom_ticket.wiki | ||
| +++ www/custom_ticket.wiki | ||
| @@ -65,11 +65,11 @@ | ||
| 65 | 65 | </tr> |
| 66 | 66 | <th1>enable_output 1</th1> |
| 67 | 67 | </pre> |
| 68 | 68 | This bit of code will get rid of the "email" field entry for logged-in users. |
| 69 | 69 | Since we know the user's information, we don't have to ask for it. NOTE: it |
| 70 | -might be good to automatically scoop up the user's email and put it here. | |
| 70 | +might be good to automatically scoop up the user's email and put it here. | |
| 71 | 71 | </p> |
| 72 | 72 | </blockquote> |
| 73 | 73 | |
| 74 | 74 | <h2>Modify the 'view ticket' page</h2><blockquote> |
| 75 | 75 | <p> |
| @@ -83,11 +83,11 @@ | ||
| 83 | 83 | <td align="right">Opened by:</td><td bgcolor="#d0d0d0"> |
| 84 | 84 | $<opened_by> |
| 85 | 85 | </td> |
| 86 | 86 | </pre> |
| 87 | 87 | This will add a row which displays these two fields, in the event the user has |
| 88 | -"edit" capability. | |
| 88 | +"edit" capability. | |
| 89 | 89 | </p> |
| 90 | 90 | </blockquote> |
| 91 | 91 | |
| 92 | 92 | <h2>Modify the 'edit ticket' page</h2><blockquote> |
| 93 | 93 | <p> |
| 94 | 94 |
| --- www/custom_ticket.wiki | |
| +++ www/custom_ticket.wiki | |
| @@ -65,11 +65,11 @@ | |
| 65 | </tr> |
| 66 | <th1>enable_output 1</th1> |
| 67 | </pre> |
| 68 | This bit of code will get rid of the "email" field entry for logged-in users. |
| 69 | Since we know the user's information, we don't have to ask for it. NOTE: it |
| 70 | might be good to automatically scoop up the user's email and put it here. |
| 71 | </p> |
| 72 | </blockquote> |
| 73 | |
| 74 | <h2>Modify the 'view ticket' page</h2><blockquote> |
| 75 | <p> |
| @@ -83,11 +83,11 @@ | |
| 83 | <td align="right">Opened by:</td><td bgcolor="#d0d0d0"> |
| 84 | $<opened_by> |
| 85 | </td> |
| 86 | </pre> |
| 87 | This will add a row which displays these two fields, in the event the user has |
| 88 | "edit" capability. |
| 89 | </p> |
| 90 | </blockquote> |
| 91 | |
| 92 | <h2>Modify the 'edit ticket' page</h2><blockquote> |
| 93 | <p> |
| 94 |
| --- www/custom_ticket.wiki | |
| +++ www/custom_ticket.wiki | |
| @@ -65,11 +65,11 @@ | |
| 65 | </tr> |
| 66 | <th1>enable_output 1</th1> |
| 67 | </pre> |
| 68 | This bit of code will get rid of the "email" field entry for logged-in users. |
| 69 | Since we know the user's information, we don't have to ask for it. NOTE: it |
| 70 | might be good to automatically scoop up the user's email and put it here. |
| 71 | </p> |
| 72 | </blockquote> |
| 73 | |
| 74 | <h2>Modify the 'view ticket' page</h2><blockquote> |
| 75 | <p> |
| @@ -83,11 +83,11 @@ | |
| 83 | <td align="right">Opened by:</td><td bgcolor="#d0d0d0"> |
| 84 | $<opened_by> |
| 85 | </td> |
| 86 | </pre> |
| 87 | This will add a row which displays these two fields, in the event the user has |
| 88 | "edit" capability. |
| 89 | </p> |
| 90 | </blockquote> |
| 91 | |
| 92 | <h2>Modify the 'edit ticket' page</h2><blockquote> |
| 93 | <p> |
| 94 |
+4
| --- www/customskin.md | ||
| +++ www/customskin.md | ||
| @@ -144,10 +144,14 @@ | ||
| 144 | 144 | respository settings and the specific page being generated. |
| 145 | 145 | |
| 146 | 146 | * **project_name** - The project_name variable is filled with the |
| 147 | 147 | name of the project as configured under the Admin/Configuration |
| 148 | 148 | menu. |
| 149 | + | |
| 150 | + * **project_description** - The project_description variable is | |
| 151 | + filled with the description of the project as configured under | |
| 152 | + the Admin/Configuration menu. | |
| 149 | 153 | |
| 150 | 154 | * **title** - The title variable holds the title of the page being |
| 151 | 155 | generated. |
| 152 | 156 | |
| 153 | 157 | The title variable is special in that it is deleted after |
| 154 | 158 |
| --- www/customskin.md | |
| +++ www/customskin.md | |
| @@ -144,10 +144,14 @@ | |
| 144 | respository settings and the specific page being generated. |
| 145 | |
| 146 | * **project_name** - The project_name variable is filled with the |
| 147 | name of the project as configured under the Admin/Configuration |
| 148 | menu. |
| 149 | |
| 150 | * **title** - The title variable holds the title of the page being |
| 151 | generated. |
| 152 | |
| 153 | The title variable is special in that it is deleted after |
| 154 |
| --- www/customskin.md | |
| +++ www/customskin.md | |
| @@ -144,10 +144,14 @@ | |
| 144 | respository settings and the specific page being generated. |
| 145 | |
| 146 | * **project_name** - The project_name variable is filled with the |
| 147 | name of the project as configured under the Admin/Configuration |
| 148 | menu. |
| 149 | |
| 150 | * **project_description** - The project_description variable is |
| 151 | filled with the description of the project as configured under |
| 152 | the Admin/Configuration menu. |
| 153 | |
| 154 | * **title** - The title variable holds the title of the page being |
| 155 | generated. |
| 156 | |
| 157 | The title variable is special in that it is deleted after |
| 158 |
+1
-1
| --- www/delta_encoder_algorithm.wiki | ||
| +++ www/delta_encoder_algorithm.wiki | ||
| @@ -153,11 +153,11 @@ | ||
| 153 | 153 | byte forward. The "base" is left unchanged in that case.</p> |
| 154 | 154 | |
| 155 | 155 | <p>The processing loop stops at one of two conditions: |
| 156 | 156 | <ol> |
| 157 | 157 | <li>The encoder decided to move the window forward, but the end of the |
| 158 | -window reached the end of the "target". | |
| 158 | +window reached the end of the "target". | |
| 159 | 159 | </li> |
| 160 | 160 | <li>After the emission of instructions the new "base" location is |
| 161 | 161 | within NHASH bytes of end of the "target", i.e. there are no more than |
| 162 | 162 | at most NHASH bytes left. |
| 163 | 163 | </li> |
| 164 | 164 |
| --- www/delta_encoder_algorithm.wiki | |
| +++ www/delta_encoder_algorithm.wiki | |
| @@ -153,11 +153,11 @@ | |
| 153 | byte forward. The "base" is left unchanged in that case.</p> |
| 154 | |
| 155 | <p>The processing loop stops at one of two conditions: |
| 156 | <ol> |
| 157 | <li>The encoder decided to move the window forward, but the end of the |
| 158 | window reached the end of the "target". |
| 159 | </li> |
| 160 | <li>After the emission of instructions the new "base" location is |
| 161 | within NHASH bytes of end of the "target", i.e. there are no more than |
| 162 | at most NHASH bytes left. |
| 163 | </li> |
| 164 |
| --- www/delta_encoder_algorithm.wiki | |
| +++ www/delta_encoder_algorithm.wiki | |
| @@ -153,11 +153,11 @@ | |
| 153 | byte forward. The "base" is left unchanged in that case.</p> |
| 154 | |
| 155 | <p>The processing loop stops at one of two conditions: |
| 156 | <ol> |
| 157 | <li>The encoder decided to move the window forward, but the end of the |
| 158 | window reached the end of the "target". |
| 159 | </li> |
| 160 | <li>After the emission of instructions the new "base" location is |
| 161 | within NHASH bytes of end of the "target", i.e. there are no more than |
| 162 | at most NHASH bytes left. |
| 163 | </li> |
| 164 |
+9
-9
| --- www/delta_format.wiki | ||
| +++ www/delta_format.wiki | ||
| @@ -161,49 +161,49 @@ | ||
| 161 | 161 | </table> |
| 162 | 162 | |
| 163 | 163 | <p>The unified diff behind the above delta is</p> |
| 164 | 164 | |
| 165 | 165 | <table border=1><tr><td><pre> |
| 166 | -bluepeak:(761) ~/Projects/Tcl/Fossil/Devel/devel > diff -u ../DELTA/old ../DELTA/new | |
| 166 | +bluepeak:(761) ~/Projects/Tcl/Fossil/Devel/devel > diff -u ../DELTA/old ../DELTA/new | |
| 167 | 167 | --- ../DELTA/old 2007-08-23 21:14:40.000000000 -0700 |
| 168 | 168 | +++ ../DELTA/new 2007-08-23 21:14:33.000000000 -0700 |
| 169 | 169 | @@ -5,7 +5,7 @@ |
| 170 | - | |
| 170 | + | |
| 171 | 171 | * If the server does not have write permission on the database |
| 172 | - file, or on the directory containing the database file (and | |
| 172 | + file, or on the directory containing the database file (and | |
| 173 | 173 | - it is thus unable to update database because it cannot create |
| 174 | 174 | + it is thus unable to update the database because it cannot create |
| 175 | 175 | a rollback journal) then it currently fails silently on a push. |
| 176 | 176 | It needs to return a helpful error. |
| 177 | - | |
| 177 | + | |
| 178 | 178 | @@ -27,8 +27,8 @@ |
| 179 | 179 | * Additional information displayed for the "vinfo" page: |
| 180 | - | |
| 180 | + | |
| 181 | 181 | + All leaves of this version that are not included in the |
| 182 | 182 | - descendant list. With date, user, comment, and hyperlink. |
| 183 | 183 | - Leaves in the descendant table should be marked as such. |
| 184 | 184 | + descendant list. With date, user, comment, and hyperlink. |
| 185 | 185 | + Leaves in the descendant table should be marked as such. |
| 186 | 186 | See the compute_leaves() function to see how to find all |
| 187 | 187 | leaves. |
| 188 | 188 | + Add file diff links to the file change list. |
| 189 | 189 | @@ -37,7 +37,7 @@ |
| 190 | - | |
| 190 | + | |
| 191 | 191 | * The /xfer handler (for push, pull, and clone) does not do |
| 192 | 192 | delta compression. This results in excess bandwidth usage. |
| 193 | 193 | - There are some code in xfer.c that are sketches of ideas on |
| 194 | 194 | + There are some pieces in xfer.c that are sketches of ideas on |
| 195 | 195 | how to do delta compression, but nothing has been implemented. |
| 196 | - | |
| 196 | + | |
| 197 | 197 | * Enhancements to the diff and tkdiff commands in the cli. |
| 198 | 198 | @@ -45,7 +45,7 @@ |
| 199 | 199 | single file. Allow diffs against any two arbitrary versions, |
| 200 | - not just diffs against the current check-out. Allow | |
| 200 | + not just diffs against the current check-out. Allow | |
| 201 | 201 | configuration options to replace tkdiff with some other |
| 202 | 202 | - visual differ of the users choice. |
| 203 | 203 | + visual differ of the users choice. Example: eskil. |
| 204 | - | |
| 204 | + | |
| 205 | 205 | * Ticketing interface (expand this bullet) |
| 206 | 206 | |
| 207 | 207 | </pre></td></tr></table> |
| 208 | 208 | |
| 209 | 209 | |
| 210 | 210 |
| --- www/delta_format.wiki | |
| +++ www/delta_format.wiki | |
| @@ -161,49 +161,49 @@ | |
| 161 | </table> |
| 162 | |
| 163 | <p>The unified diff behind the above delta is</p> |
| 164 | |
| 165 | <table border=1><tr><td><pre> |
| 166 | bluepeak:(761) ~/Projects/Tcl/Fossil/Devel/devel > diff -u ../DELTA/old ../DELTA/new |
| 167 | --- ../DELTA/old 2007-08-23 21:14:40.000000000 -0700 |
| 168 | +++ ../DELTA/new 2007-08-23 21:14:33.000000000 -0700 |
| 169 | @@ -5,7 +5,7 @@ |
| 170 | |
| 171 | * If the server does not have write permission on the database |
| 172 | file, or on the directory containing the database file (and |
| 173 | - it is thus unable to update database because it cannot create |
| 174 | + it is thus unable to update the database because it cannot create |
| 175 | a rollback journal) then it currently fails silently on a push. |
| 176 | It needs to return a helpful error. |
| 177 | |
| 178 | @@ -27,8 +27,8 @@ |
| 179 | * Additional information displayed for the "vinfo" page: |
| 180 | |
| 181 | + All leaves of this version that are not included in the |
| 182 | - descendant list. With date, user, comment, and hyperlink. |
| 183 | - Leaves in the descendant table should be marked as such. |
| 184 | + descendant list. With date, user, comment, and hyperlink. |
| 185 | + Leaves in the descendant table should be marked as such. |
| 186 | See the compute_leaves() function to see how to find all |
| 187 | leaves. |
| 188 | + Add file diff links to the file change list. |
| 189 | @@ -37,7 +37,7 @@ |
| 190 | |
| 191 | * The /xfer handler (for push, pull, and clone) does not do |
| 192 | delta compression. This results in excess bandwidth usage. |
| 193 | - There are some code in xfer.c that are sketches of ideas on |
| 194 | + There are some pieces in xfer.c that are sketches of ideas on |
| 195 | how to do delta compression, but nothing has been implemented. |
| 196 | |
| 197 | * Enhancements to the diff and tkdiff commands in the cli. |
| 198 | @@ -45,7 +45,7 @@ |
| 199 | single file. Allow diffs against any two arbitrary versions, |
| 200 | not just diffs against the current check-out. Allow |
| 201 | configuration options to replace tkdiff with some other |
| 202 | - visual differ of the users choice. |
| 203 | + visual differ of the users choice. Example: eskil. |
| 204 | |
| 205 | * Ticketing interface (expand this bullet) |
| 206 | |
| 207 | </pre></td></tr></table> |
| 208 | |
| 209 | |
| 210 |
| --- www/delta_format.wiki | |
| +++ www/delta_format.wiki | |
| @@ -161,49 +161,49 @@ | |
| 161 | </table> |
| 162 | |
| 163 | <p>The unified diff behind the above delta is</p> |
| 164 | |
| 165 | <table border=1><tr><td><pre> |
| 166 | bluepeak:(761) ~/Projects/Tcl/Fossil/Devel/devel > diff -u ../DELTA/old ../DELTA/new |
| 167 | --- ../DELTA/old 2007-08-23 21:14:40.000000000 -0700 |
| 168 | +++ ../DELTA/new 2007-08-23 21:14:33.000000000 -0700 |
| 169 | @@ -5,7 +5,7 @@ |
| 170 | |
| 171 | * If the server does not have write permission on the database |
| 172 | file, or on the directory containing the database file (and |
| 173 | - it is thus unable to update database because it cannot create |
| 174 | + it is thus unable to update the database because it cannot create |
| 175 | a rollback journal) then it currently fails silently on a push. |
| 176 | It needs to return a helpful error. |
| 177 | |
| 178 | @@ -27,8 +27,8 @@ |
| 179 | * Additional information displayed for the "vinfo" page: |
| 180 | |
| 181 | + All leaves of this version that are not included in the |
| 182 | - descendant list. With date, user, comment, and hyperlink. |
| 183 | - Leaves in the descendant table should be marked as such. |
| 184 | + descendant list. With date, user, comment, and hyperlink. |
| 185 | + Leaves in the descendant table should be marked as such. |
| 186 | See the compute_leaves() function to see how to find all |
| 187 | leaves. |
| 188 | + Add file diff links to the file change list. |
| 189 | @@ -37,7 +37,7 @@ |
| 190 | |
| 191 | * The /xfer handler (for push, pull, and clone) does not do |
| 192 | delta compression. This results in excess bandwidth usage. |
| 193 | - There are some code in xfer.c that are sketches of ideas on |
| 194 | + There are some pieces in xfer.c that are sketches of ideas on |
| 195 | how to do delta compression, but nothing has been implemented. |
| 196 | |
| 197 | * Enhancements to the diff and tkdiff commands in the cli. |
| 198 | @@ -45,7 +45,7 @@ |
| 199 | single file. Allow diffs against any two arbitrary versions, |
| 200 | not just diffs against the current check-out. Allow |
| 201 | configuration options to replace tkdiff with some other |
| 202 | - visual differ of the users choice. |
| 203 | + visual differ of the users choice. Example: eskil. |
| 204 | |
| 205 | * Ticketing interface (expand this bullet) |
| 206 | |
| 207 | </pre></td></tr></table> |
| 208 | |
| 209 | |
| 210 |
+9
-9
| --- www/embeddeddoc.wiki | ||
| +++ www/embeddeddoc.wiki | ||
| @@ -42,13 +42,13 @@ | ||
| 42 | 42 | <b>http://www.hwaci.com/cgi-bin/fossil</b>. |
| 43 | 43 | If you launch the web server using the "<b>fossil server</b>" command line, |
| 44 | 44 | then the <i><baseurl></i> is usually |
| 45 | 45 | <b>http://localhost:8080/</b>. |
| 46 | 46 | |
| 47 | -The <i><version></i> is any unique prefix of the check-in ID for | |
| 47 | +The <i><version></i> is any unique prefix of the check-in ID for | |
| 48 | 48 | the check-in containing the documentation you want to access. |
| 49 | -Or <i><version></i> can be the name of a | |
| 49 | +Or <i><version></i> can be the name of a | |
| 50 | 50 | [./branching.wiki | branch] in order to show |
| 51 | 51 | the documentation for the latest version of that branch. |
| 52 | 52 | Or <i><version></i> can be one of the keywords "<b>tip</b>" or |
| 53 | 53 | "<b>ckout</b>". The "<b>tip</b>" keyword means to use the most recent |
| 54 | 54 | check-in. This is useful if you want to see the very latest |
| @@ -62,30 +62,30 @@ | ||
| 62 | 62 | |
| 63 | 63 | Finally, the <i><filename></i> element of the URL is the |
| 64 | 64 | pathname of the documentation file relative to the root of the source |
| 65 | 65 | tree. |
| 66 | 66 | |
| 67 | -The mimetype (and thus the rendering) of documentation files is | |
| 68 | -determined by the file suffix. Fossil currently understands | |
| 67 | +The mimetype (and thus the rendering) of documentation files is | |
| 68 | +determined by the file suffix. Fossil currently understands | |
| 69 | 69 | [/mimetype_list|many different file suffixes], |
| 70 | 70 | including all the popular ones such as ".css", ".gif", ".htm", |
| 71 | 71 | ".html", ".jpg", ".jpeg", ".png", and ".txt". |
| 72 | 72 | |
| 73 | -Documentation files whose names end in ".wiki" use the | |
| 73 | +Documentation files whose names end in ".wiki" use the | |
| 74 | 74 | [/wiki_rules | fossil wiki markup] - |
| 75 | 75 | a safe subset of HTML together with some wiki rules for paragraph |
| 76 | -breaks, lists, and hyperlinks. | |
| 76 | +breaks, lists, and hyperlinks. | |
| 77 | 77 | Documentation files ending in ".md" or ".markdown" use the |
| 78 | 78 | [/md_rules | Markdown markup langauge]. |
| 79 | 79 | Documentation files ending in ".txt" are plain text. |
| 80 | 80 | Wiki, markdown, and plain text documentation files |
| 81 | 81 | are rendered with the standard fossil header and footer added. |
| 82 | 82 | Most other mimetypes are delivered directly to the requesting |
| 83 | 83 | web browser without interpretation, additions, or changes. |
| 84 | 84 | |
| 85 | 85 | Files with the mimetype "text/html" (the .html or .htm suffix) are |
| 86 | -usually rendered directly to the browser without interpretation. | |
| 86 | +usually rendered directly to the browser without interpretation. | |
| 87 | 87 | However, if the file begins with a <div> element like this: |
| 88 | 88 | |
| 89 | 89 | <b><div class='fossil-doc' data-title='<i>Title Text</i>'></b> |
| 90 | 90 | |
| 91 | 91 | Then the standard Fossil header and footer are added to the document |
| @@ -117,11 +117,11 @@ | ||
| 117 | 117 | <blockquote><pre> |
| 118 | 118 | #!/usr/bin/fossil |
| 119 | 119 | repository: /fossil/fossil.fossil |
| 120 | 120 | </pre></blockquote> |
| 121 | 121 | |
| 122 | -This is one of four ways to set up a | |
| 122 | +This is one of four ways to set up a | |
| 123 | 123 | <a href="./server.wiki">fossil web server</a>. |
| 124 | 124 | |
| 125 | 125 | The "<b>/trunk/</b>" part of the URL tells fossil to use |
| 126 | 126 | the documentation files from the most recent trunk check-in. |
| 127 | 127 | If you wanted to see an historical version of this document, |
| @@ -138,11 +138,11 @@ | ||
| 138 | 138 | <li> <i>YYYY-MM-DD</i> |
| 139 | 139 | <li> <i>YYYY-MM-DD</i><b>T</b><i>HH:MM</i> |
| 140 | 140 | <li> <i>YYYY-MM-DD</i><b>T</b><i>HH:MM:SS</i> |
| 141 | 141 | </ul> |
| 142 | 142 | |
| 143 | -When the symbolic name is a date and time, fossil shows the version | |
| 143 | +When the symbolic name is a date and time, fossil shows the version | |
| 144 | 144 | of the document that was most recently checked in as of the date |
| 145 | 145 | and time specified. So, for example, to see what the fossil website |
| 146 | 146 | looked like at the beginning of 2010, enter: |
| 147 | 147 | |
| 148 | 148 | <blockquote> |
| 149 | 149 |
| --- www/embeddeddoc.wiki | |
| +++ www/embeddeddoc.wiki | |
| @@ -42,13 +42,13 @@ | |
| 42 | <b>http://www.hwaci.com/cgi-bin/fossil</b>. |
| 43 | If you launch the web server using the "<b>fossil server</b>" command line, |
| 44 | then the <i><baseurl></i> is usually |
| 45 | <b>http://localhost:8080/</b>. |
| 46 | |
| 47 | The <i><version></i> is any unique prefix of the check-in ID for |
| 48 | the check-in containing the documentation you want to access. |
| 49 | Or <i><version></i> can be the name of a |
| 50 | [./branching.wiki | branch] in order to show |
| 51 | the documentation for the latest version of that branch. |
| 52 | Or <i><version></i> can be one of the keywords "<b>tip</b>" or |
| 53 | "<b>ckout</b>". The "<b>tip</b>" keyword means to use the most recent |
| 54 | check-in. This is useful if you want to see the very latest |
| @@ -62,30 +62,30 @@ | |
| 62 | |
| 63 | Finally, the <i><filename></i> element of the URL is the |
| 64 | pathname of the documentation file relative to the root of the source |
| 65 | tree. |
| 66 | |
| 67 | The mimetype (and thus the rendering) of documentation files is |
| 68 | determined by the file suffix. Fossil currently understands |
| 69 | [/mimetype_list|many different file suffixes], |
| 70 | including all the popular ones such as ".css", ".gif", ".htm", |
| 71 | ".html", ".jpg", ".jpeg", ".png", and ".txt". |
| 72 | |
| 73 | Documentation files whose names end in ".wiki" use the |
| 74 | [/wiki_rules | fossil wiki markup] - |
| 75 | a safe subset of HTML together with some wiki rules for paragraph |
| 76 | breaks, lists, and hyperlinks. |
| 77 | Documentation files ending in ".md" or ".markdown" use the |
| 78 | [/md_rules | Markdown markup langauge]. |
| 79 | Documentation files ending in ".txt" are plain text. |
| 80 | Wiki, markdown, and plain text documentation files |
| 81 | are rendered with the standard fossil header and footer added. |
| 82 | Most other mimetypes are delivered directly to the requesting |
| 83 | web browser without interpretation, additions, or changes. |
| 84 | |
| 85 | Files with the mimetype "text/html" (the .html or .htm suffix) are |
| 86 | usually rendered directly to the browser without interpretation. |
| 87 | However, if the file begins with a <div> element like this: |
| 88 | |
| 89 | <b><div class='fossil-doc' data-title='<i>Title Text</i>'></b> |
| 90 | |
| 91 | Then the standard Fossil header and footer are added to the document |
| @@ -117,11 +117,11 @@ | |
| 117 | <blockquote><pre> |
| 118 | #!/usr/bin/fossil |
| 119 | repository: /fossil/fossil.fossil |
| 120 | </pre></blockquote> |
| 121 | |
| 122 | This is one of four ways to set up a |
| 123 | <a href="./server.wiki">fossil web server</a>. |
| 124 | |
| 125 | The "<b>/trunk/</b>" part of the URL tells fossil to use |
| 126 | the documentation files from the most recent trunk check-in. |
| 127 | If you wanted to see an historical version of this document, |
| @@ -138,11 +138,11 @@ | |
| 138 | <li> <i>YYYY-MM-DD</i> |
| 139 | <li> <i>YYYY-MM-DD</i><b>T</b><i>HH:MM</i> |
| 140 | <li> <i>YYYY-MM-DD</i><b>T</b><i>HH:MM:SS</i> |
| 141 | </ul> |
| 142 | |
| 143 | When the symbolic name is a date and time, fossil shows the version |
| 144 | of the document that was most recently checked in as of the date |
| 145 | and time specified. So, for example, to see what the fossil website |
| 146 | looked like at the beginning of 2010, enter: |
| 147 | |
| 148 | <blockquote> |
| 149 |
| --- www/embeddeddoc.wiki | |
| +++ www/embeddeddoc.wiki | |
| @@ -42,13 +42,13 @@ | |
| 42 | <b>http://www.hwaci.com/cgi-bin/fossil</b>. |
| 43 | If you launch the web server using the "<b>fossil server</b>" command line, |
| 44 | then the <i><baseurl></i> is usually |
| 45 | <b>http://localhost:8080/</b>. |
| 46 | |
| 47 | The <i><version></i> is any unique prefix of the check-in ID for |
| 48 | the check-in containing the documentation you want to access. |
| 49 | Or <i><version></i> can be the name of a |
| 50 | [./branching.wiki | branch] in order to show |
| 51 | the documentation for the latest version of that branch. |
| 52 | Or <i><version></i> can be one of the keywords "<b>tip</b>" or |
| 53 | "<b>ckout</b>". The "<b>tip</b>" keyword means to use the most recent |
| 54 | check-in. This is useful if you want to see the very latest |
| @@ -62,30 +62,30 @@ | |
| 62 | |
| 63 | Finally, the <i><filename></i> element of the URL is the |
| 64 | pathname of the documentation file relative to the root of the source |
| 65 | tree. |
| 66 | |
| 67 | The mimetype (and thus the rendering) of documentation files is |
| 68 | determined by the file suffix. Fossil currently understands |
| 69 | [/mimetype_list|many different file suffixes], |
| 70 | including all the popular ones such as ".css", ".gif", ".htm", |
| 71 | ".html", ".jpg", ".jpeg", ".png", and ".txt". |
| 72 | |
| 73 | Documentation files whose names end in ".wiki" use the |
| 74 | [/wiki_rules | fossil wiki markup] - |
| 75 | a safe subset of HTML together with some wiki rules for paragraph |
| 76 | breaks, lists, and hyperlinks. |
| 77 | Documentation files ending in ".md" or ".markdown" use the |
| 78 | [/md_rules | Markdown markup langauge]. |
| 79 | Documentation files ending in ".txt" are plain text. |
| 80 | Wiki, markdown, and plain text documentation files |
| 81 | are rendered with the standard fossil header and footer added. |
| 82 | Most other mimetypes are delivered directly to the requesting |
| 83 | web browser without interpretation, additions, or changes. |
| 84 | |
| 85 | Files with the mimetype "text/html" (the .html or .htm suffix) are |
| 86 | usually rendered directly to the browser without interpretation. |
| 87 | However, if the file begins with a <div> element like this: |
| 88 | |
| 89 | <b><div class='fossil-doc' data-title='<i>Title Text</i>'></b> |
| 90 | |
| 91 | Then the standard Fossil header and footer are added to the document |
| @@ -117,11 +117,11 @@ | |
| 117 | <blockquote><pre> |
| 118 | #!/usr/bin/fossil |
| 119 | repository: /fossil/fossil.fossil |
| 120 | </pre></blockquote> |
| 121 | |
| 122 | This is one of four ways to set up a |
| 123 | <a href="./server.wiki">fossil web server</a>. |
| 124 | |
| 125 | The "<b>/trunk/</b>" part of the URL tells fossil to use |
| 126 | the documentation files from the most recent trunk check-in. |
| 127 | If you wanted to see an historical version of this document, |
| @@ -138,11 +138,11 @@ | |
| 138 | <li> <i>YYYY-MM-DD</i> |
| 139 | <li> <i>YYYY-MM-DD</i><b>T</b><i>HH:MM</i> |
| 140 | <li> <i>YYYY-MM-DD</i><b>T</b><i>HH:MM:SS</i> |
| 141 | </ul> |
| 142 | |
| 143 | When the symbolic name is a date and time, fossil shows the version |
| 144 | of the document that was most recently checked in as of the date |
| 145 | and time specified. So, for example, to see what the fossil website |
| 146 | looked like at the beginning of 2010, enter: |
| 147 | |
| 148 | <blockquote> |
| 149 |
+1
-1
| --- www/encryptedrepos.wiki | ||
| +++ www/encryptedrepos.wiki | ||
| @@ -3,11 +3,11 @@ | ||
| 3 | 3 | Fossil can be compiled so that it works with encrypted repositories using |
| 4 | 4 | the [https://www.sqlite.org/see/doc/trunk/www/readme.wiki|SQLite Encryption Extension]. |
| 5 | 5 | This technical note explains the process. |
| 6 | 6 | </blockquote> |
| 7 | 7 | <h2>Building An Encryption-Enabled Fossil</h2><blockquote> |
| 8 | -The SQLite Encryption Extension (SEE) is proprietary software and requires | |
| 8 | +The SQLite Encryption Extension (SEE) is proprietary software and requires | |
| 9 | 9 | [http://www.hwaci.com/cgi-bin/see-step1|purchasing a license]. |
| 10 | 10 | <p> |
| 11 | 11 | Assuming you have an SEE license, the first step of compiling Fossil to |
| 12 | 12 | use SEE is to create an SEE-enabled version of the SQLite database source code. |
| 13 | 13 | This alternative SQLite database source file should be called "sqlite3-see.c" |
| 14 | 14 |
| --- www/encryptedrepos.wiki | |
| +++ www/encryptedrepos.wiki | |
| @@ -3,11 +3,11 @@ | |
| 3 | Fossil can be compiled so that it works with encrypted repositories using |
| 4 | the [https://www.sqlite.org/see/doc/trunk/www/readme.wiki|SQLite Encryption Extension]. |
| 5 | This technical note explains the process. |
| 6 | </blockquote> |
| 7 | <h2>Building An Encryption-Enabled Fossil</h2><blockquote> |
| 8 | The SQLite Encryption Extension (SEE) is proprietary software and requires |
| 9 | [http://www.hwaci.com/cgi-bin/see-step1|purchasing a license]. |
| 10 | <p> |
| 11 | Assuming you have an SEE license, the first step of compiling Fossil to |
| 12 | use SEE is to create an SEE-enabled version of the SQLite database source code. |
| 13 | This alternative SQLite database source file should be called "sqlite3-see.c" |
| 14 |
| --- www/encryptedrepos.wiki | |
| +++ www/encryptedrepos.wiki | |
| @@ -3,11 +3,11 @@ | |
| 3 | Fossil can be compiled so that it works with encrypted repositories using |
| 4 | the [https://www.sqlite.org/see/doc/trunk/www/readme.wiki|SQLite Encryption Extension]. |
| 5 | This technical note explains the process. |
| 6 | </blockquote> |
| 7 | <h2>Building An Encryption-Enabled Fossil</h2><blockquote> |
| 8 | The SQLite Encryption Extension (SEE) is proprietary software and requires |
| 9 | [http://www.hwaci.com/cgi-bin/see-step1|purchasing a license]. |
| 10 | <p> |
| 11 | Assuming you have an SEE license, the first step of compiling Fossil to |
| 12 | use SEE is to create an SEE-enabled version of the SQLite database source code. |
| 13 | This alternative SQLite database source file should be called "sqlite3-see.c" |
| 14 |
+5
-1
| --- www/env-opts.md | ||
| +++ www/env-opts.md | ||
| @@ -88,11 +88,15 @@ | ||
| 88 | 88 | `--sqlstats`: (Sets `g.fSqlStats`.) Print a number of performance |
| 89 | 89 | statistics about each SQLite database used when it is closed. |
| 90 | 90 | |
| 91 | 91 | `--sshtrace`: (Sets `g.fSshTrace`.) |
| 92 | 92 | |
| 93 | -`--ssl-identity SSLIDENTITY`: | |
| 93 | +`--ssl-identity`: The fully qualified name of the file containing the client | |
| 94 | +certificate and private key to use, in PEM format. It can be created by | |
| 95 | +concatenating the client certificate and private key files. This identity will | |
| 96 | +be presented to SSL servers to authenticate the client, in addition to the | |
| 97 | +normal password authentication. | |
| 94 | 98 | |
| 95 | 99 | `--systemtrace`: (Sets `g.fSystemTrace`.) Trace all commands launched |
| 96 | 100 | as sub processes. |
| 97 | 101 | |
| 98 | 102 | `--user LOGIN`: (Sets `g.zLogin`) Also `-U LOGIN`. Set the user name |
| 99 | 103 |
| --- www/env-opts.md | |
| +++ www/env-opts.md | |
| @@ -88,11 +88,15 @@ | |
| 88 | `--sqlstats`: (Sets `g.fSqlStats`.) Print a number of performance |
| 89 | statistics about each SQLite database used when it is closed. |
| 90 | |
| 91 | `--sshtrace`: (Sets `g.fSshTrace`.) |
| 92 | |
| 93 | `--ssl-identity SSLIDENTITY`: |
| 94 | |
| 95 | `--systemtrace`: (Sets `g.fSystemTrace`.) Trace all commands launched |
| 96 | as sub processes. |
| 97 | |
| 98 | `--user LOGIN`: (Sets `g.zLogin`) Also `-U LOGIN`. Set the user name |
| 99 |
| --- www/env-opts.md | |
| +++ www/env-opts.md | |
| @@ -88,11 +88,15 @@ | |
| 88 | `--sqlstats`: (Sets `g.fSqlStats`.) Print a number of performance |
| 89 | statistics about each SQLite database used when it is closed. |
| 90 | |
| 91 | `--sshtrace`: (Sets `g.fSshTrace`.) |
| 92 | |
| 93 | `--ssl-identity`: The fully qualified name of the file containing the client |
| 94 | certificate and private key to use, in PEM format. It can be created by |
| 95 | concatenating the client certificate and private key files. This identity will |
| 96 | be presented to SSL servers to authenticate the client, in addition to the |
| 97 | normal password authentication. |
| 98 | |
| 99 | `--systemtrace`: (Sets `g.fSystemTrace`.) Trace all commands launched |
| 100 | as sub processes. |
| 101 | |
| 102 | `--user LOGIN`: (Sets `g.zLogin`) Also `-U LOGIN`. Set the user name |
| 103 |
+3
-3
| --- www/event.wiki | ||
| +++ www/event.wiki | ||
| @@ -23,11 +23,11 @@ | ||
| 23 | 23 | can be something simple like "Version 1.2.3" perhaps with a bright |
| 24 | 24 | color background to draw attention to the entry and the wiki content |
| 25 | 25 | can contain release notes, for example. |
| 26 | 26 | |
| 27 | 27 | * <b>Blog Entries</b>. Blog entries from developers describing the current |
| 28 | - state of a project, or rational for various design decisions, or | |
| 28 | + state of a project, or rational for various design decisions, or | |
| 29 | 29 | roadmaps for future development, can be entered as technotes. |
| 30 | 30 | |
| 31 | 31 | * <b>Process Checkpoints</b>. For projects that have a formal process, |
| 32 | 32 | technotes can be used to record the completion or the initiation of |
| 33 | 33 | various process steps. For example, a technote can be used to record |
| @@ -49,11 +49,11 @@ | ||
| 49 | 49 | stay better organized and provide a better historical record of the |
| 50 | 50 | development progress. |
| 51 | 51 | |
| 52 | 52 | <h2>Viewing Technotes</h2> |
| 53 | 53 | |
| 54 | -Because technotes are considered a special kind of wiki, | |
| 54 | +Because technotes are considered a special kind of wiki, | |
| 55 | 55 | users must have permission to read wiki in order read technotes. |
| 56 | 56 | Enable the "j" permission under the /Setup/Users menu in order |
| 57 | 57 | to give specific users or user classes the ability to view wiki |
| 58 | 58 | and technotes. |
| 59 | 59 | |
| @@ -64,12 +64,12 @@ | ||
| 64 | 64 | |
| 65 | 65 | There is a hyperlink under the /wikihelp menu that can be used to create |
| 66 | 66 | new technotes. And there is a submenu hyperlink on technote displays for |
| 67 | 67 | editing existing technotes. |
| 68 | 68 | |
| 69 | -Users must have check-in privileges (permission "i") in order to | |
| 69 | +Users must have check-in privileges (permission "i") in order to | |
| 70 | 70 | create or edit technotes. In addition, users must have create-wiki |
| 71 | 71 | privilege (permission "f") to create new technotes and edit-wiki |
| 72 | 72 | privilege (permission "k") in order to edit existing technotes. |
| 73 | 73 | |
| 74 | 74 | Technote content may be formatted as [/wiki_rules | Fossil wiki], |
| 75 | 75 | [/md_rules | Markdown], or a plain text. |
| 76 | 76 |
| --- www/event.wiki | |
| +++ www/event.wiki | |
| @@ -23,11 +23,11 @@ | |
| 23 | can be something simple like "Version 1.2.3" perhaps with a bright |
| 24 | color background to draw attention to the entry and the wiki content |
| 25 | can contain release notes, for example. |
| 26 | |
| 27 | * <b>Blog Entries</b>. Blog entries from developers describing the current |
| 28 | state of a project, or rational for various design decisions, or |
| 29 | roadmaps for future development, can be entered as technotes. |
| 30 | |
| 31 | * <b>Process Checkpoints</b>. For projects that have a formal process, |
| 32 | technotes can be used to record the completion or the initiation of |
| 33 | various process steps. For example, a technote can be used to record |
| @@ -49,11 +49,11 @@ | |
| 49 | stay better organized and provide a better historical record of the |
| 50 | development progress. |
| 51 | |
| 52 | <h2>Viewing Technotes</h2> |
| 53 | |
| 54 | Because technotes are considered a special kind of wiki, |
| 55 | users must have permission to read wiki in order read technotes. |
| 56 | Enable the "j" permission under the /Setup/Users menu in order |
| 57 | to give specific users or user classes the ability to view wiki |
| 58 | and technotes. |
| 59 | |
| @@ -64,12 +64,12 @@ | |
| 64 | |
| 65 | There is a hyperlink under the /wikihelp menu that can be used to create |
| 66 | new technotes. And there is a submenu hyperlink on technote displays for |
| 67 | editing existing technotes. |
| 68 | |
| 69 | Users must have check-in privileges (permission "i") in order to |
| 70 | create or edit technotes. In addition, users must have create-wiki |
| 71 | privilege (permission "f") to create new technotes and edit-wiki |
| 72 | privilege (permission "k") in order to edit existing technotes. |
| 73 | |
| 74 | Technote content may be formatted as [/wiki_rules | Fossil wiki], |
| 75 | [/md_rules | Markdown], or a plain text. |
| 76 |
| --- www/event.wiki | |
| +++ www/event.wiki | |
| @@ -23,11 +23,11 @@ | |
| 23 | can be something simple like "Version 1.2.3" perhaps with a bright |
| 24 | color background to draw attention to the entry and the wiki content |
| 25 | can contain release notes, for example. |
| 26 | |
| 27 | * <b>Blog Entries</b>. Blog entries from developers describing the current |
| 28 | state of a project, or rational for various design decisions, or |
| 29 | roadmaps for future development, can be entered as technotes. |
| 30 | |
| 31 | * <b>Process Checkpoints</b>. For projects that have a formal process, |
| 32 | technotes can be used to record the completion or the initiation of |
| 33 | various process steps. For example, a technote can be used to record |
| @@ -49,11 +49,11 @@ | |
| 49 | stay better organized and provide a better historical record of the |
| 50 | development progress. |
| 51 | |
| 52 | <h2>Viewing Technotes</h2> |
| 53 | |
| 54 | Because technotes are considered a special kind of wiki, |
| 55 | users must have permission to read wiki in order read technotes. |
| 56 | Enable the "j" permission under the /Setup/Users menu in order |
| 57 | to give specific users or user classes the ability to view wiki |
| 58 | and technotes. |
| 59 | |
| @@ -64,12 +64,12 @@ | |
| 64 | |
| 65 | There is a hyperlink under the /wikihelp menu that can be used to create |
| 66 | new technotes. And there is a submenu hyperlink on technote displays for |
| 67 | editing existing technotes. |
| 68 | |
| 69 | Users must have check-in privileges (permission "i") in order to |
| 70 | create or edit technotes. In addition, users must have create-wiki |
| 71 | privilege (permission "f") to create new technotes and edit-wiki |
| 72 | privilege (permission "k") in order to edit existing technotes. |
| 73 | |
| 74 | Technote content may be formatted as [/wiki_rules | Fossil wiki], |
| 75 | [/md_rules | Markdown], or a plain text. |
| 76 |
+5
-5
| --- www/faq.wiki | ||
| +++ www/faq.wiki | ||
| @@ -62,12 +62,12 @@ | ||
| 62 | 62 | If you already have a fork in your check-in tree and you want to convert |
| 63 | 63 | that fork to a branch, you can do this from the web interface. |
| 64 | 64 | First locate the check-in that you want to be |
| 65 | 65 | the initial check-in of your branch on the timeline and click on its |
| 66 | 66 | link so that you are on the <b>ci</b> page. Then find the "<b>edit</b>" |
| 67 | -link (near the "Commands:" label) and click on that. On the | |
| 68 | -"Edit Check-in" page, check the box beside "Branching:" and fill in | |
| 67 | +link (near the "Commands:" label) and click on that. On the | |
| 68 | +"Edit Check-in" page, check the box beside "Branching:" and fill in | |
| 69 | 69 | the name of your new branch to the right and press the "Apply Changes" |
| 70 | 70 | button.</blockquote></li> |
| 71 | 71 | |
| 72 | 72 | <a name="q4"></a> |
| 73 | 73 | <p><b>(4) How do I tag a check-in?</b></p> |
| @@ -89,11 +89,11 @@ | ||
| 89 | 89 | |
| 90 | 90 | The CHECK-IN in the previous line can be any |
| 91 | 91 | [./checkin_names.wiki | valid check-in name format]. |
| 92 | 92 | |
| 93 | 93 | You can also add (and remove) tags from a check-in using the |
| 94 | -[./webui.wiki | web interface]. First locate the check-in that you | |
| 94 | +[./webui.wiki | web interface]. First locate the check-in that you | |
| 95 | 95 | what to tag on the timeline, then click on the link to go the detailed |
| 96 | 96 | information page for that check-in. Then find the "<b>edit</b>" |
| 97 | 97 | link (near the "Commands:" label) and click on that. There are |
| 98 | 98 | controls on the edit page that allow new tags to be added and existing |
| 99 | 99 | tags to be removed.</blockquote></li> |
| @@ -100,13 +100,13 @@ | ||
| 100 | 100 | |
| 101 | 101 | <a name="q5"></a> |
| 102 | 102 | <p><b>(5) How do I create a private branch that won't get pushed back to the |
| 103 | 103 | main repository.</b></p> |
| 104 | 104 | |
| 105 | -<blockquote>Use the <b>--private</b> command-line option on the | |
| 105 | +<blockquote>Use the <b>--private</b> command-line option on the | |
| 106 | 106 | <b>commit</b> command. The result will be a check-in which exists on |
| 107 | -your local repository only and is never pushed to other repositories. | |
| 107 | +your local repository only and is never pushed to other repositories. | |
| 108 | 108 | All descendants of a private check-in are also private. |
| 109 | 109 | |
| 110 | 110 | Unless you specify something different using the <b>--branch</b> and/or |
| 111 | 111 | <b>--bgcolor</b> options, the new private check-in will be put on a branch |
| 112 | 112 | named "private" with an orange background color. |
| 113 | 113 |
| --- www/faq.wiki | |
| +++ www/faq.wiki | |
| @@ -62,12 +62,12 @@ | |
| 62 | If you already have a fork in your check-in tree and you want to convert |
| 63 | that fork to a branch, you can do this from the web interface. |
| 64 | First locate the check-in that you want to be |
| 65 | the initial check-in of your branch on the timeline and click on its |
| 66 | link so that you are on the <b>ci</b> page. Then find the "<b>edit</b>" |
| 67 | link (near the "Commands:" label) and click on that. On the |
| 68 | "Edit Check-in" page, check the box beside "Branching:" and fill in |
| 69 | the name of your new branch to the right and press the "Apply Changes" |
| 70 | button.</blockquote></li> |
| 71 | |
| 72 | <a name="q4"></a> |
| 73 | <p><b>(4) How do I tag a check-in?</b></p> |
| @@ -89,11 +89,11 @@ | |
| 89 | |
| 90 | The CHECK-IN in the previous line can be any |
| 91 | [./checkin_names.wiki | valid check-in name format]. |
| 92 | |
| 93 | You can also add (and remove) tags from a check-in using the |
| 94 | [./webui.wiki | web interface]. First locate the check-in that you |
| 95 | what to tag on the timeline, then click on the link to go the detailed |
| 96 | information page for that check-in. Then find the "<b>edit</b>" |
| 97 | link (near the "Commands:" label) and click on that. There are |
| 98 | controls on the edit page that allow new tags to be added and existing |
| 99 | tags to be removed.</blockquote></li> |
| @@ -100,13 +100,13 @@ | |
| 100 | |
| 101 | <a name="q5"></a> |
| 102 | <p><b>(5) How do I create a private branch that won't get pushed back to the |
| 103 | main repository.</b></p> |
| 104 | |
| 105 | <blockquote>Use the <b>--private</b> command-line option on the |
| 106 | <b>commit</b> command. The result will be a check-in which exists on |
| 107 | your local repository only and is never pushed to other repositories. |
| 108 | All descendants of a private check-in are also private. |
| 109 | |
| 110 | Unless you specify something different using the <b>--branch</b> and/or |
| 111 | <b>--bgcolor</b> options, the new private check-in will be put on a branch |
| 112 | named "private" with an orange background color. |
| 113 |
| --- www/faq.wiki | |
| +++ www/faq.wiki | |
| @@ -62,12 +62,12 @@ | |
| 62 | If you already have a fork in your check-in tree and you want to convert |
| 63 | that fork to a branch, you can do this from the web interface. |
| 64 | First locate the check-in that you want to be |
| 65 | the initial check-in of your branch on the timeline and click on its |
| 66 | link so that you are on the <b>ci</b> page. Then find the "<b>edit</b>" |
| 67 | link (near the "Commands:" label) and click on that. On the |
| 68 | "Edit Check-in" page, check the box beside "Branching:" and fill in |
| 69 | the name of your new branch to the right and press the "Apply Changes" |
| 70 | button.</blockquote></li> |
| 71 | |
| 72 | <a name="q4"></a> |
| 73 | <p><b>(4) How do I tag a check-in?</b></p> |
| @@ -89,11 +89,11 @@ | |
| 89 | |
| 90 | The CHECK-IN in the previous line can be any |
| 91 | [./checkin_names.wiki | valid check-in name format]. |
| 92 | |
| 93 | You can also add (and remove) tags from a check-in using the |
| 94 | [./webui.wiki | web interface]. First locate the check-in that you |
| 95 | what to tag on the timeline, then click on the link to go the detailed |
| 96 | information page for that check-in. Then find the "<b>edit</b>" |
| 97 | link (near the "Commands:" label) and click on that. There are |
| 98 | controls on the edit page that allow new tags to be added and existing |
| 99 | tags to be removed.</blockquote></li> |
| @@ -100,13 +100,13 @@ | |
| 100 | |
| 101 | <a name="q5"></a> |
| 102 | <p><b>(5) How do I create a private branch that won't get pushed back to the |
| 103 | main repository.</b></p> |
| 104 | |
| 105 | <blockquote>Use the <b>--private</b> command-line option on the |
| 106 | <b>commit</b> command. The result will be a check-in which exists on |
| 107 | your local repository only and is never pushed to other repositories. |
| 108 | All descendants of a private check-in are also private. |
| 109 | |
| 110 | Unless you specify something different using the <b>--branch</b> and/or |
| 111 | <b>--bgcolor</b> options, the new private check-in will be put on a branch |
| 112 | named "private" with an orange background color. |
| 113 |
+33
-33
| --- www/fileformat.wiki | ||
| +++ www/fileformat.wiki | ||
| @@ -2,11 +2,11 @@ | ||
| 2 | 2 | <h1 align="center"> |
| 3 | 3 | Fossil File Formats |
| 4 | 4 | </h1> |
| 5 | 5 | |
| 6 | 6 | The global state of a fossil repository is kept simple so that it can |
| 7 | -endure in useful form for decades or centuries. | |
| 7 | +endure in useful form for decades or centuries. | |
| 8 | 8 | A fossil repository is intended to be readable, |
| 9 | 9 | searchable, and extensible by people not yet born. |
| 10 | 10 | |
| 11 | 11 | The global state of a fossil repository is an unordered |
| 12 | 12 | set of <i>artifacts</i>. |
| @@ -14,11 +14,11 @@ | ||
| 14 | 14 | part of a trouble ticket, or one of several special control artifacts |
| 15 | 15 | used to show the relationships between other artifacts within the |
| 16 | 16 | project. Each artifact is normally represented on disk as a separate |
| 17 | 17 | file. Artifacts can be text or binary. |
| 18 | 18 | |
| 19 | -In addition to the global state, | |
| 19 | +In addition to the global state, | |
| 20 | 20 | each fossil repository also contains local state. |
| 21 | 21 | The local state consists of web-page formatting |
| 22 | 22 | preferences, authorized users, ticket display and reporting formats, |
| 23 | 23 | and so forth. The global state is shared in common among all |
| 24 | 24 | repositories for the same project, whereas the local state is often |
| @@ -30,11 +30,11 @@ | ||
| 30 | 30 | mentioned here in order to distinguish it from global state. |
| 31 | 31 | |
| 32 | 32 | Each artifact in the repository is named by its SHA1 hash. |
| 33 | 33 | No prefixes or meta information is added to an artifact before |
| 34 | 34 | its hash is computed. The name of an artifact in the repository |
| 35 | -is exactly the same SHA1 hash that is computed by sha1sum | |
| 35 | +is exactly the same SHA1 hash that is computed by sha1sum | |
| 36 | 36 | on the file as it exists in your source tree.</p> |
| 37 | 37 | |
| 38 | 38 | Some artifacts have a particular format which gives them special |
| 39 | 39 | meaning to fossil. Fossil recognizes: |
| 40 | 40 | |
| @@ -84,11 +84,11 @@ | ||
| 84 | 84 | Each card begins with a single |
| 85 | 85 | character "card type". Zero or more arguments may follow |
| 86 | 86 | the card type. All arguments are separated from each other |
| 87 | 87 | and from the card-type character by a single space |
| 88 | 88 | character. There is no surplus white space between arguments |
| 89 | -and no leading or trailing whitespace except for the newline | |
| 89 | +and no leading or trailing whitespace except for the newline | |
| 90 | 90 | character that acts as the card separator. |
| 91 | 91 | |
| 92 | 92 | All cards of the manifest occur in strict sorted lexicographical order. |
| 93 | 93 | No card may be duplicated. |
| 94 | 94 | The entire manifest may be PGP clear-signed, but otherwise it |
| @@ -114,18 +114,18 @@ | ||
| 114 | 114 | another manifest that serves as the "baseline" for this manifest. A |
| 115 | 115 | manifest that has a B-card is called a delta-manifest and a manifest |
| 116 | 116 | that omits the B-card is a baseline-manifest. The other manifest |
| 117 | 117 | identified by the argument of the B-card must be a baseline-manifest. |
| 118 | 118 | A baseline-manifest records the complete contents of a check-in. |
| 119 | -A delta-manifest records only changes from its baseline. | |
| 119 | +A delta-manifest records only changes from its baseline. | |
| 120 | 120 | |
| 121 | 121 | A manifest must have exactly one C-card. The sole argument to |
| 122 | 122 | the C-card is a check-in comment that describes the check-in that |
| 123 | 123 | the manifest defines. The check-in comment is text. The following |
| 124 | 124 | escape sequences are applied to the text: |
| 125 | 125 | A space (ASCII 0x20) is represented as "\s" (ASCII 0x5C, 0x73). A |
| 126 | -newline (ASCII 0x0a) is "\n" (ASCII 0x5C, x6E). A backslash | |
| 126 | +newline (ASCII 0x0a) is "\n" (ASCII 0x5C, x6E). A backslash | |
| 127 | 127 | (ASCII 0x5C) is represented as two backslashes "\\". Apart from |
| 128 | 128 | space and newline, no other whitespace characters are allowed in |
| 129 | 129 | the check-in comment. Nor are any unprintable characters allowed |
| 130 | 130 | in the comment. |
| 131 | 131 | |
| @@ -166,15 +166,15 @@ | ||
| 166 | 166 | text in the comment of the C-card. If the N-card is omitted, a default mimetype |
| 167 | 167 | is used. |
| 168 | 168 | |
| 169 | 169 | A manifest has zero or one P-cards. Most manifests have one P-card. |
| 170 | 170 | The P-card has a varying number of arguments that |
| 171 | -defines other manifests from which the current manifest | |
| 172 | -is derived. Each argument is an 40-character lowercase | |
| 173 | -hexadecimal SHA1 of the predecessor manifest. All arguments | |
| 174 | -to the P-card must be unique to that line. | |
| 175 | -The first predecessor is the direct ancestor of the manifest. | |
| 171 | +define other manifests from which the current manifest | |
| 172 | +is derived. Each argument is a 40-character lowercase | |
| 173 | +hexadecimal SHA1 of a predecessor manifest. All arguments | |
| 174 | +to the P-card must be unique within that card. | |
| 175 | +The first argument is the SHA1 of the direct ancestor of the manifest. | |
| 176 | 176 | Other arguments define manifests with which the first was |
| 177 | 177 | merged to yield the current manifest. Most manifests have |
| 178 | 178 | a P-card with a single argument. The first manifest in the |
| 179 | 179 | project has no ancestors and thus has no P-card or (depending |
| 180 | 180 | on the Fossil version) an empty P-card (no arguments). |
| @@ -184,28 +184,28 @@ | ||
| 184 | 184 | whereas a P-card defines the immediate ancestor or a merge |
| 185 | 185 | ancestor, the Q-card is used to identify a single check-in or a small |
| 186 | 186 | range of check-ins which were cherry-picked for inclusion in or |
| 187 | 187 | exclusion from the current manifest. The first argument of |
| 188 | 188 | the Q-card is the artifact ID of another manifest (the "target") |
| 189 | -which has had its changes included or excluded in the current manifest. | |
| 189 | +which has had its changes included or excluded in the current manifest. | |
| 190 | 190 | The target is preceded by "+" or "-" to show inclusion or |
| 191 | 191 | exclusion, respectively. The optional second argument to the |
| 192 | 192 | Q-card is another manifest artifact ID which is the "baseline" |
| 193 | 193 | for the cherry-pick. If omitted, the baseline is the primary |
| 194 | 194 | parent of the target. The |
| 195 | 195 | changes included or excluded consist of all changes moving from |
| 196 | -the baseline to the target. | |
| 196 | +the baseline to the target. | |
| 197 | 197 | |
| 198 | -The Q-card was added to the interface specification on 2011-02-26. | |
| 198 | +The Q-card was added to the interface specification on 2011-02-26. | |
| 199 | 199 | Older versions of Fossil will reject manifests that contain Q-cards. |
| 200 | 200 | |
| 201 | 201 | A manifest may optionally have a single R-card. The R-card has |
| 202 | -a single argument which is the MD5 checksum of all files in | |
| 202 | +a single argument which is the MD5 checksum of all files in | |
| 203 | 203 | the check-in except the manifest itself. The checksum is expressed |
| 204 | -as 32-characters of lowercase hexadecimal. The checksum is | |
| 204 | +as 32 characters of lowercase hexadecimal. The checksum is | |
| 205 | 205 | computed as follows: For each file in the check-in (except for |
| 206 | -the manifest itself) in strict sorted lexicographical order, | |
| 206 | +the manifest itself) in strict sorted lexicographical order, | |
| 207 | 207 | take the pathname of the file relative to the root of the |
| 208 | 208 | repository, append a single space (ASCII 0x20), the |
| 209 | 209 | size of the file in ASCII decimal, a single newline |
| 210 | 210 | character (ASCII 0x0A), and the complete text of the file. |
| 211 | 211 | Compute the MD5 checksum of the result. |
| @@ -228,12 +228,12 @@ | ||
| 228 | 228 | is encoded using the same character escapes as is used for the |
| 229 | 229 | check-in comment argument to the C-card. |
| 230 | 230 | |
| 231 | 231 | A manifest must have a single Z-card as its last line. The argument |
| 232 | 232 | to the Z-card is a 32-character lowercase hexadecimal MD5 hash |
| 233 | -of all prior lines of the manifest up to and including the newline | |
| 234 | -character that immediately precedes the "Z". The Z-card is | |
| 233 | +of all prior lines of the manifest up to and including the newline | |
| 234 | +character that immediately precedes the "Z". The Z-card is | |
| 235 | 235 | a sanity check to prove that the manifest is well-formed and |
| 236 | 236 | consistent. |
| 237 | 237 | |
| 238 | 238 | A sample manifest from Fossil itself can be seen |
| 239 | 239 | [/artifact/28987096ac | here]. |
| @@ -240,27 +240,27 @@ | ||
| 240 | 240 | |
| 241 | 241 | <a name="cluster"></a> |
| 242 | 242 | <h2>2.0 Clusters</h2> |
| 243 | 243 | |
| 244 | 244 | A cluster is an artifact that declares the existence of other artifacts. |
| 245 | -Clusters are used during repository synchronization to help | |
| 245 | +Clusters are used during repository synchronization to help | |
| 246 | 246 | reduce network traffic. As such, clusters are an optimization and |
| 247 | 247 | may be removed from a repository without loss or damage to the |
| 248 | 248 | underlying project code. |
| 249 | 249 | |
| 250 | 250 | Clusters follow a syntax that is very similar to manifests. |
| 251 | -A Cluster is a line-oriented text file. Newline characters | |
| 251 | +A cluster is a line-oriented text file. Newline characters | |
| 252 | 252 | (ASCII 0x0a) separate the artifact into cards. Each card begins with a single |
| 253 | 253 | character "card type". Zero or more arguments may follow |
| 254 | 254 | the card type. All arguments are separated from each other |
| 255 | 255 | and from the card-type character by a single space |
| 256 | 256 | character. There is no surplus white space between arguments |
| 257 | -and no leading or trailing whitespace except for the newline | |
| 257 | +and no leading or trailing whitespace except for the newline | |
| 258 | 258 | character that acts as the card separator. |
| 259 | 259 | All cards of a cluster occur in strict sorted lexicographical order. |
| 260 | 260 | No card may be duplicated. |
| 261 | -The cluster may not contain additional text or data beyond | |
| 261 | +The cluster may not contain additional text or data beyond | |
| 262 | 262 | what is described here. |
| 263 | 263 | Unlike manifests, clusters are never PGP signed. |
| 264 | 264 | |
| 265 | 265 | Allowed cards in the cluster are as follows: |
| 266 | 266 | |
| @@ -268,12 +268,12 @@ | ||
| 268 | 268 | <b>M</b> <i>artifact-id</i><br /> |
| 269 | 269 | <b>Z</b> <i>checksum</i> |
| 270 | 270 | </blockquote> |
| 271 | 271 | |
| 272 | 272 | A cluster contains one or more "M" cards followed by a single "Z" |
| 273 | -line. Each M card has a single argument which is the artifact ID of | |
| 274 | -another artifact in the repository. The Z card work exactly like | |
| 273 | +card. Each M card has a single argument which is the artifact ID of | |
| 274 | +another artifact in the repository. The Z card works exactly like | |
| 275 | 275 | the Z card of a manifest. The argument to the Z card is the |
| 276 | 276 | lower-case hexadecimal representation of the MD5 checksum of all |
| 277 | 277 | prior cards in the cluster. The Z-card is required. |
| 278 | 278 | |
| 279 | 279 | An example cluster from Fossil can be seen |
| @@ -315,11 +315,11 @@ | ||
| 315 | 315 | first value is the tag name. The first character of the tag |
| 316 | 316 | is either "+", "-", or "*". The "+" means the tag should be added |
| 317 | 317 | to the artifact. The "-" means the tag should be removed. |
| 318 | 318 | The "*" character means the tag should be added to the artifact |
| 319 | 319 | and all direct descendants (but not descendants through a merge) down |
| 320 | -to but not including the first descendant that contains a | |
| 320 | +to but not including the first descendant that contains a | |
| 321 | 321 | more recent "-", "*", or "+" tag with the same name. |
| 322 | 322 | The optional third argument is the value of the tag. A tag |
| 323 | 323 | without a value is a Boolean. |
| 324 | 324 | |
| 325 | 325 | When two or more tags with the same name are applied to the |
| @@ -331,11 +331,11 @@ | ||
| 331 | 331 | for display purposes. The "user" tag overrides the name of the |
| 332 | 332 | check-in user. The "date" tag overrides the check-in date. |
| 333 | 333 | The "branch" tag sets the name of the branch that at check-in |
| 334 | 334 | belongs to. Symbolic tags begin with the "sym-" prefix. |
| 335 | 335 | |
| 336 | -The U card is the name of the user that created the control | |
| 336 | +The U card is the name of the user that created the control | |
| 337 | 337 | artifact. The Z card is the usual required artifact checksum. |
| 338 | 338 | |
| 339 | 339 | An example control artifacts can be seen [/info/9d302ccda8 | here]. |
| 340 | 340 | |
| 341 | 341 | |
| @@ -360,11 +360,11 @@ | ||
| 360 | 360 | |
| 361 | 361 | The D card is the date and time when the wiki page was edited. |
| 362 | 362 | The P card specifies the parent wiki pages, if any. The L card |
| 363 | 363 | gives the name of the wiki page. The optional N card specifies |
| 364 | 364 | the mimetype of the wiki text. If the N card is omitted, the |
| 365 | -mimetype is assumed to be text/x-fossil-wiki. | |
| 365 | +mimetype is assumed to be text/x-fossil-wiki. | |
| 366 | 366 | The U card specifies the login |
| 367 | 367 | of the user who made this edit to the wiki page. The Z card is |
| 368 | 368 | the usual checksum over the entire artifact and is required. |
| 369 | 369 | |
| 370 | 370 | The W card is used to specify the text of the wiki page. The |
| @@ -405,11 +405,11 @@ | ||
| 405 | 405 | If the <i>value</i> parameter of the J card is omitted, then the |
| 406 | 406 | field is set to an empty string. |
| 407 | 407 | Each fossil server has a ticket configuration which specifies the fields its |
| 408 | 408 | understands. The ticket configuration is part of the local state for |
| 409 | 409 | the repository and thus can vary from one repository to another. |
| 410 | -Hence a J card might specify a <i>field</i> that do not exist in the | |
| 410 | +Hence a J card might specify a <i>field</i> that do not exist in the | |
| 411 | 411 | local ticket configuration. If a J card specifies a <i>field</i> that |
| 412 | 412 | is not in the local configuration, then that J card |
| 413 | 413 | is simply ignored. |
| 414 | 414 | |
| 415 | 415 | The first argument of the J card is the field name. The second |
| @@ -424,11 +424,11 @@ | ||
| 424 | 424 | |
| 425 | 425 | <a name="attachment"></a> |
| 426 | 426 | <h2>6.0 Attachments</h2> |
| 427 | 427 | |
| 428 | 428 | An attachment artifact associates some other artifact that is the |
| 429 | -attachment (the source artifact) with a ticket or wiki page or | |
| 429 | +attachment (the source artifact) with a ticket or wiki page or | |
| 430 | 430 | technical note to which |
| 431 | 431 | the attachment is connected (the target artifact). |
| 432 | 432 | The following cards are allowed on an attachment artifact: |
| 433 | 433 | |
| 434 | 434 | <blockquote> |
| @@ -441,11 +441,11 @@ | ||
| 441 | 441 | </blockquote> |
| 442 | 442 | |
| 443 | 443 | The A card specifies a filename for the attachment in its first argument. |
| 444 | 444 | The second argument to the A card is the name of the wiki page or |
| 445 | 445 | ticket or technical note to which the attachment is connected. The |
| 446 | -third argument is either missing or else it is the 40-character artifact | |
| 446 | +third argument is either missing or else it is the 40-character artifact | |
| 447 | 447 | ID of the attachment itself. A missing third argument means that the |
| 448 | 448 | attachment should be deleted. |
| 449 | 449 | |
| 450 | 450 | The C card is an optional comment describing what the attachment is about. |
| 451 | 451 | The C card is optional, but there can only be one. |
| @@ -487,11 +487,11 @@ | ||
| 487 | 487 | </blockquote> |
| 488 | 488 | |
| 489 | 489 | The C card contains text that is displayed on the timeline for the |
| 490 | 490 | technote. The C card is optional, but there can only be one. |
| 491 | 491 | |
| 492 | -A single D card is required to give the date and time when the | |
| 492 | +A single D card is required to give the date and time when the | |
| 493 | 493 | technote artifact was created. This is different from the time at which |
| 494 | 494 | the technote appears on the timeline. |
| 495 | 495 | |
| 496 | 496 | A single E card gives the time of the technote (the point on the timeline |
| 497 | 497 | where the technote is displayed) and a unique identifier for the technote. |
| @@ -525,11 +525,11 @@ | ||
| 525 | 525 | display color for timelines. |
| 526 | 526 | |
| 527 | 527 | The optional U card gives name of the user who entered the technote. |
| 528 | 528 | |
| 529 | 529 | A single W card provides wiki text for the document associated with the |
| 530 | -technote. The format of the W card is exactly the same as for a | |
| 530 | +technote. The format of the W card is exactly the same as for a | |
| 531 | 531 | [#wikichng | wiki artifact]. |
| 532 | 532 | |
| 533 | 533 | The Z card is the required checksum over the rest of the artifact. |
| 534 | 534 | |
| 535 | 535 | |
| 536 | 536 |
| --- www/fileformat.wiki | |
| +++ www/fileformat.wiki | |
| @@ -2,11 +2,11 @@ | |
| 2 | <h1 align="center"> |
| 3 | Fossil File Formats |
| 4 | </h1> |
| 5 | |
| 6 | The global state of a fossil repository is kept simple so that it can |
| 7 | endure in useful form for decades or centuries. |
| 8 | A fossil repository is intended to be readable, |
| 9 | searchable, and extensible by people not yet born. |
| 10 | |
| 11 | The global state of a fossil repository is an unordered |
| 12 | set of <i>artifacts</i>. |
| @@ -14,11 +14,11 @@ | |
| 14 | part of a trouble ticket, or one of several special control artifacts |
| 15 | used to show the relationships between other artifacts within the |
| 16 | project. Each artifact is normally represented on disk as a separate |
| 17 | file. Artifacts can be text or binary. |
| 18 | |
| 19 | In addition to the global state, |
| 20 | each fossil repository also contains local state. |
| 21 | The local state consists of web-page formatting |
| 22 | preferences, authorized users, ticket display and reporting formats, |
| 23 | and so forth. The global state is shared in common among all |
| 24 | repositories for the same project, whereas the local state is often |
| @@ -30,11 +30,11 @@ | |
| 30 | mentioned here in order to distinguish it from global state. |
| 31 | |
| 32 | Each artifact in the repository is named by its SHA1 hash. |
| 33 | No prefixes or meta information is added to an artifact before |
| 34 | its hash is computed. The name of an artifact in the repository |
| 35 | is exactly the same SHA1 hash that is computed by sha1sum |
| 36 | on the file as it exists in your source tree.</p> |
| 37 | |
| 38 | Some artifacts have a particular format which gives them special |
| 39 | meaning to fossil. Fossil recognizes: |
| 40 | |
| @@ -84,11 +84,11 @@ | |
| 84 | Each card begins with a single |
| 85 | character "card type". Zero or more arguments may follow |
| 86 | the card type. All arguments are separated from each other |
| 87 | and from the card-type character by a single space |
| 88 | character. There is no surplus white space between arguments |
| 89 | and no leading or trailing whitespace except for the newline |
| 90 | character that acts as the card separator. |
| 91 | |
| 92 | All cards of the manifest occur in strict sorted lexicographical order. |
| 93 | No card may be duplicated. |
| 94 | The entire manifest may be PGP clear-signed, but otherwise it |
| @@ -114,18 +114,18 @@ | |
| 114 | another manifest that serves as the "baseline" for this manifest. A |
| 115 | manifest that has a B-card is called a delta-manifest and a manifest |
| 116 | that omits the B-card is a baseline-manifest. The other manifest |
| 117 | identified by the argument of the B-card must be a baseline-manifest. |
| 118 | A baseline-manifest records the complete contents of a check-in. |
| 119 | A delta-manifest records only changes from its baseline. |
| 120 | |
| 121 | A manifest must have exactly one C-card. The sole argument to |
| 122 | the C-card is a check-in comment that describes the check-in that |
| 123 | the manifest defines. The check-in comment is text. The following |
| 124 | escape sequences are applied to the text: |
| 125 | A space (ASCII 0x20) is represented as "\s" (ASCII 0x5C, 0x73). A |
| 126 | newline (ASCII 0x0a) is "\n" (ASCII 0x5C, x6E). A backslash |
| 127 | (ASCII 0x5C) is represented as two backslashes "\\". Apart from |
| 128 | space and newline, no other whitespace characters are allowed in |
| 129 | the check-in comment. Nor are any unprintable characters allowed |
| 130 | in the comment. |
| 131 | |
| @@ -166,15 +166,15 @@ | |
| 166 | text in the comment of the C-card. If the N-card is omitted, a default mimetype |
| 167 | is used. |
| 168 | |
| 169 | A manifest has zero or one P-cards. Most manifests have one P-card. |
| 170 | The P-card has a varying number of arguments that |
| 171 | defines other manifests from which the current manifest |
| 172 | is derived. Each argument is an 40-character lowercase |
| 173 | hexadecimal SHA1 of the predecessor manifest. All arguments |
| 174 | to the P-card must be unique to that line. |
| 175 | The first predecessor is the direct ancestor of the manifest. |
| 176 | Other arguments define manifests with which the first was |
| 177 | merged to yield the current manifest. Most manifests have |
| 178 | a P-card with a single argument. The first manifest in the |
| 179 | project has no ancestors and thus has no P-card or (depending |
| 180 | on the Fossil version) an empty P-card (no arguments). |
| @@ -184,28 +184,28 @@ | |
| 184 | whereas a P-card defines the immediate ancestor or a merge |
| 185 | ancestor, the Q-card is used to identify a single check-in or a small |
| 186 | range of check-ins which were cherry-picked for inclusion in or |
| 187 | exclusion from the current manifest. The first argument of |
| 188 | the Q-card is the artifact ID of another manifest (the "target") |
| 189 | which has had its changes included or excluded in the current manifest. |
| 190 | The target is preceded by "+" or "-" to show inclusion or |
| 191 | exclusion, respectively. The optional second argument to the |
| 192 | Q-card is another manifest artifact ID which is the "baseline" |
| 193 | for the cherry-pick. If omitted, the baseline is the primary |
| 194 | parent of the target. The |
| 195 | changes included or excluded consist of all changes moving from |
| 196 | the baseline to the target. |
| 197 | |
| 198 | The Q-card was added to the interface specification on 2011-02-26. |
| 199 | Older versions of Fossil will reject manifests that contain Q-cards. |
| 200 | |
| 201 | A manifest may optionally have a single R-card. The R-card has |
| 202 | a single argument which is the MD5 checksum of all files in |
| 203 | the check-in except the manifest itself. The checksum is expressed |
| 204 | as 32-characters of lowercase hexadecimal. The checksum is |
| 205 | computed as follows: For each file in the check-in (except for |
| 206 | the manifest itself) in strict sorted lexicographical order, |
| 207 | take the pathname of the file relative to the root of the |
| 208 | repository, append a single space (ASCII 0x20), the |
| 209 | size of the file in ASCII decimal, a single newline |
| 210 | character (ASCII 0x0A), and the complete text of the file. |
| 211 | Compute the MD5 checksum of the result. |
| @@ -228,12 +228,12 @@ | |
| 228 | is encoded using the same character escapes as is used for the |
| 229 | check-in comment argument to the C-card. |
| 230 | |
| 231 | A manifest must have a single Z-card as its last line. The argument |
| 232 | to the Z-card is a 32-character lowercase hexadecimal MD5 hash |
| 233 | of all prior lines of the manifest up to and including the newline |
| 234 | character that immediately precedes the "Z". The Z-card is |
| 235 | a sanity check to prove that the manifest is well-formed and |
| 236 | consistent. |
| 237 | |
| 238 | A sample manifest from Fossil itself can be seen |
| 239 | [/artifact/28987096ac | here]. |
| @@ -240,27 +240,27 @@ | |
| 240 | |
| 241 | <a name="cluster"></a> |
| 242 | <h2>2.0 Clusters</h2> |
| 243 | |
| 244 | A cluster is an artifact that declares the existence of other artifacts. |
| 245 | Clusters are used during repository synchronization to help |
| 246 | reduce network traffic. As such, clusters are an optimization and |
| 247 | may be removed from a repository without loss or damage to the |
| 248 | underlying project code. |
| 249 | |
| 250 | Clusters follow a syntax that is very similar to manifests. |
| 251 | A Cluster is a line-oriented text file. Newline characters |
| 252 | (ASCII 0x0a) separate the artifact into cards. Each card begins with a single |
| 253 | character "card type". Zero or more arguments may follow |
| 254 | the card type. All arguments are separated from each other |
| 255 | and from the card-type character by a single space |
| 256 | character. There is no surplus white space between arguments |
| 257 | and no leading or trailing whitespace except for the newline |
| 258 | character that acts as the card separator. |
| 259 | All cards of a cluster occur in strict sorted lexicographical order. |
| 260 | No card may be duplicated. |
| 261 | The cluster may not contain additional text or data beyond |
| 262 | what is described here. |
| 263 | Unlike manifests, clusters are never PGP signed. |
| 264 | |
| 265 | Allowed cards in the cluster are as follows: |
| 266 | |
| @@ -268,12 +268,12 @@ | |
| 268 | <b>M</b> <i>artifact-id</i><br /> |
| 269 | <b>Z</b> <i>checksum</i> |
| 270 | </blockquote> |
| 271 | |
| 272 | A cluster contains one or more "M" cards followed by a single "Z" |
| 273 | line. Each M card has a single argument which is the artifact ID of |
| 274 | another artifact in the repository. The Z card work exactly like |
| 275 | the Z card of a manifest. The argument to the Z card is the |
| 276 | lower-case hexadecimal representation of the MD5 checksum of all |
| 277 | prior cards in the cluster. The Z-card is required. |
| 278 | |
| 279 | An example cluster from Fossil can be seen |
| @@ -315,11 +315,11 @@ | |
| 315 | first value is the tag name. The first character of the tag |
| 316 | is either "+", "-", or "*". The "+" means the tag should be added |
| 317 | to the artifact. The "-" means the tag should be removed. |
| 318 | The "*" character means the tag should be added to the artifact |
| 319 | and all direct descendants (but not descendants through a merge) down |
| 320 | to but not including the first descendant that contains a |
| 321 | more recent "-", "*", or "+" tag with the same name. |
| 322 | The optional third argument is the value of the tag. A tag |
| 323 | without a value is a Boolean. |
| 324 | |
| 325 | When two or more tags with the same name are applied to the |
| @@ -331,11 +331,11 @@ | |
| 331 | for display purposes. The "user" tag overrides the name of the |
| 332 | check-in user. The "date" tag overrides the check-in date. |
| 333 | The "branch" tag sets the name of the branch that at check-in |
| 334 | belongs to. Symbolic tags begin with the "sym-" prefix. |
| 335 | |
| 336 | The U card is the name of the user that created the control |
| 337 | artifact. The Z card is the usual required artifact checksum. |
| 338 | |
| 339 | An example control artifacts can be seen [/info/9d302ccda8 | here]. |
| 340 | |
| 341 | |
| @@ -360,11 +360,11 @@ | |
| 360 | |
| 361 | The D card is the date and time when the wiki page was edited. |
| 362 | The P card specifies the parent wiki pages, if any. The L card |
| 363 | gives the name of the wiki page. The optional N card specifies |
| 364 | the mimetype of the wiki text. If the N card is omitted, the |
| 365 | mimetype is assumed to be text/x-fossil-wiki. |
| 366 | The U card specifies the login |
| 367 | of the user who made this edit to the wiki page. The Z card is |
| 368 | the usual checksum over the entire artifact and is required. |
| 369 | |
| 370 | The W card is used to specify the text of the wiki page. The |
| @@ -405,11 +405,11 @@ | |
| 405 | If the <i>value</i> parameter of the J card is omitted, then the |
| 406 | field is set to an empty string. |
| 407 | Each fossil server has a ticket configuration which specifies the fields its |
| 408 | understands. The ticket configuration is part of the local state for |
| 409 | the repository and thus can vary from one repository to another. |
| 410 | Hence a J card might specify a <i>field</i> that do not exist in the |
| 411 | local ticket configuration. If a J card specifies a <i>field</i> that |
| 412 | is not in the local configuration, then that J card |
| 413 | is simply ignored. |
| 414 | |
| 415 | The first argument of the J card is the field name. The second |
| @@ -424,11 +424,11 @@ | |
| 424 | |
| 425 | <a name="attachment"></a> |
| 426 | <h2>6.0 Attachments</h2> |
| 427 | |
| 428 | An attachment artifact associates some other artifact that is the |
| 429 | attachment (the source artifact) with a ticket or wiki page or |
| 430 | technical note to which |
| 431 | the attachment is connected (the target artifact). |
| 432 | The following cards are allowed on an attachment artifact: |
| 433 | |
| 434 | <blockquote> |
| @@ -441,11 +441,11 @@ | |
| 441 | </blockquote> |
| 442 | |
| 443 | The A card specifies a filename for the attachment in its first argument. |
| 444 | The second argument to the A card is the name of the wiki page or |
| 445 | ticket or technical note to which the attachment is connected. The |
| 446 | third argument is either missing or else it is the 40-character artifact |
| 447 | ID of the attachment itself. A missing third argument means that the |
| 448 | attachment should be deleted. |
| 449 | |
| 450 | The C card is an optional comment describing what the attachment is about. |
| 451 | The C card is optional, but there can only be one. |
| @@ -487,11 +487,11 @@ | |
| 487 | </blockquote> |
| 488 | |
| 489 | The C card contains text that is displayed on the timeline for the |
| 490 | technote. The C card is optional, but there can only be one. |
| 491 | |
| 492 | A single D card is required to give the date and time when the |
| 493 | technote artifact was created. This is different from the time at which |
| 494 | the technote appears on the timeline. |
| 495 | |
| 496 | A single E card gives the time of the technote (the point on the timeline |
| 497 | where the technote is displayed) and a unique identifier for the technote. |
| @@ -525,11 +525,11 @@ | |
| 525 | display color for timelines. |
| 526 | |
| 527 | The optional U card gives name of the user who entered the technote. |
| 528 | |
| 529 | A single W card provides wiki text for the document associated with the |
| 530 | technote. The format of the W card is exactly the same as for a |
| 531 | [#wikichng | wiki artifact]. |
| 532 | |
| 533 | The Z card is the required checksum over the rest of the artifact. |
| 534 | |
| 535 | |
| 536 |
| --- www/fileformat.wiki | |
| +++ www/fileformat.wiki | |
| @@ -2,11 +2,11 @@ | |
| 2 | <h1 align="center"> |
| 3 | Fossil File Formats |
| 4 | </h1> |
| 5 | |
| 6 | The global state of a fossil repository is kept simple so that it can |
| 7 | endure in useful form for decades or centuries. |
| 8 | A fossil repository is intended to be readable, |
| 9 | searchable, and extensible by people not yet born. |
| 10 | |
| 11 | The global state of a fossil repository is an unordered |
| 12 | set of <i>artifacts</i>. |
| @@ -14,11 +14,11 @@ | |
| 14 | part of a trouble ticket, or one of several special control artifacts |
| 15 | used to show the relationships between other artifacts within the |
| 16 | project. Each artifact is normally represented on disk as a separate |
| 17 | file. Artifacts can be text or binary. |
| 18 | |
| 19 | In addition to the global state, |
| 20 | each fossil repository also contains local state. |
| 21 | The local state consists of web-page formatting |
| 22 | preferences, authorized users, ticket display and reporting formats, |
| 23 | and so forth. The global state is shared in common among all |
| 24 | repositories for the same project, whereas the local state is often |
| @@ -30,11 +30,11 @@ | |
| 30 | mentioned here in order to distinguish it from global state. |
| 31 | |
| 32 | Each artifact in the repository is named by its SHA1 hash. |
| 33 | No prefixes or meta information is added to an artifact before |
| 34 | its hash is computed. The name of an artifact in the repository |
| 35 | is exactly the same SHA1 hash that is computed by sha1sum |
| 36 | on the file as it exists in your source tree.</p> |
| 37 | |
| 38 | Some artifacts have a particular format which gives them special |
| 39 | meaning to fossil. Fossil recognizes: |
| 40 | |
| @@ -84,11 +84,11 @@ | |
| 84 | Each card begins with a single |
| 85 | character "card type". Zero or more arguments may follow |
| 86 | the card type. All arguments are separated from each other |
| 87 | and from the card-type character by a single space |
| 88 | character. There is no surplus white space between arguments |
| 89 | and no leading or trailing whitespace except for the newline |
| 90 | character that acts as the card separator. |
| 91 | |
| 92 | All cards of the manifest occur in strict sorted lexicographical order. |
| 93 | No card may be duplicated. |
| 94 | The entire manifest may be PGP clear-signed, but otherwise it |
| @@ -114,18 +114,18 @@ | |
| 114 | another manifest that serves as the "baseline" for this manifest. A |
| 115 | manifest that has a B-card is called a delta-manifest and a manifest |
| 116 | that omits the B-card is a baseline-manifest. The other manifest |
| 117 | identified by the argument of the B-card must be a baseline-manifest. |
| 118 | A baseline-manifest records the complete contents of a check-in. |
| 119 | A delta-manifest records only changes from its baseline. |
| 120 | |
| 121 | A manifest must have exactly one C-card. The sole argument to |
| 122 | the C-card is a check-in comment that describes the check-in that |
| 123 | the manifest defines. The check-in comment is text. The following |
| 124 | escape sequences are applied to the text: |
| 125 | A space (ASCII 0x20) is represented as "\s" (ASCII 0x5C, 0x73). A |
| 126 | newline (ASCII 0x0a) is "\n" (ASCII 0x5C, x6E). A backslash |
| 127 | (ASCII 0x5C) is represented as two backslashes "\\". Apart from |
| 128 | space and newline, no other whitespace characters are allowed in |
| 129 | the check-in comment. Nor are any unprintable characters allowed |
| 130 | in the comment. |
| 131 | |
| @@ -166,15 +166,15 @@ | |
| 166 | text in the comment of the C-card. If the N-card is omitted, a default mimetype |
| 167 | is used. |
| 168 | |
| 169 | A manifest has zero or one P-cards. Most manifests have one P-card. |
| 170 | The P-card has a varying number of arguments that |
| 171 | define other manifests from which the current manifest |
| 172 | is derived. Each argument is a 40-character lowercase |
| 173 | hexadecimal SHA1 of a predecessor manifest. All arguments |
| 174 | to the P-card must be unique within that card. |
| 175 | The first argument is the SHA1 of the direct ancestor of the manifest. |
| 176 | Other arguments define manifests with which the first was |
| 177 | merged to yield the current manifest. Most manifests have |
| 178 | a P-card with a single argument. The first manifest in the |
| 179 | project has no ancestors and thus has no P-card or (depending |
| 180 | on the Fossil version) an empty P-card (no arguments). |
| @@ -184,28 +184,28 @@ | |
| 184 | whereas a P-card defines the immediate ancestor or a merge |
| 185 | ancestor, the Q-card is used to identify a single check-in or a small |
| 186 | range of check-ins which were cherry-picked for inclusion in or |
| 187 | exclusion from the current manifest. The first argument of |
| 188 | the Q-card is the artifact ID of another manifest (the "target") |
| 189 | which has had its changes included or excluded in the current manifest. |
| 190 | The target is preceded by "+" or "-" to show inclusion or |
| 191 | exclusion, respectively. The optional second argument to the |
| 192 | Q-card is another manifest artifact ID which is the "baseline" |
| 193 | for the cherry-pick. If omitted, the baseline is the primary |
| 194 | parent of the target. The |
| 195 | changes included or excluded consist of all changes moving from |
| 196 | the baseline to the target. |
| 197 | |
| 198 | The Q-card was added to the interface specification on 2011-02-26. |
| 199 | Older versions of Fossil will reject manifests that contain Q-cards. |
| 200 | |
| 201 | A manifest may optionally have a single R-card. The R-card has |
| 202 | a single argument which is the MD5 checksum of all files in |
| 203 | the check-in except the manifest itself. The checksum is expressed |
| 204 | as 32 characters of lowercase hexadecimal. The checksum is |
| 205 | computed as follows: For each file in the check-in (except for |
| 206 | the manifest itself) in strict sorted lexicographical order, |
| 207 | take the pathname of the file relative to the root of the |
| 208 | repository, append a single space (ASCII 0x20), the |
| 209 | size of the file in ASCII decimal, a single newline |
| 210 | character (ASCII 0x0A), and the complete text of the file. |
| 211 | Compute the MD5 checksum of the result. |
| @@ -228,12 +228,12 @@ | |
| 228 | is encoded using the same character escapes as is used for the |
| 229 | check-in comment argument to the C-card. |
| 230 | |
| 231 | A manifest must have a single Z-card as its last line. The argument |
| 232 | to the Z-card is a 32-character lowercase hexadecimal MD5 hash |
| 233 | of all prior lines of the manifest up to and including the newline |
| 234 | character that immediately precedes the "Z". The Z-card is |
| 235 | a sanity check to prove that the manifest is well-formed and |
| 236 | consistent. |
| 237 | |
| 238 | A sample manifest from Fossil itself can be seen |
| 239 | [/artifact/28987096ac | here]. |
| @@ -240,27 +240,27 @@ | |
| 240 | |
| 241 | <a name="cluster"></a> |
| 242 | <h2>2.0 Clusters</h2> |
| 243 | |
| 244 | A cluster is an artifact that declares the existence of other artifacts. |
| 245 | Clusters are used during repository synchronization to help |
| 246 | reduce network traffic. As such, clusters are an optimization and |
| 247 | may be removed from a repository without loss or damage to the |
| 248 | underlying project code. |
| 249 | |
| 250 | Clusters follow a syntax that is very similar to manifests. |
| 251 | A cluster is a line-oriented text file. Newline characters |
| 252 | (ASCII 0x0a) separate the artifact into cards. Each card begins with a single |
| 253 | character "card type". Zero or more arguments may follow |
| 254 | the card type. All arguments are separated from each other |
| 255 | and from the card-type character by a single space |
| 256 | character. There is no surplus white space between arguments |
| 257 | and no leading or trailing whitespace except for the newline |
| 258 | character that acts as the card separator. |
| 259 | All cards of a cluster occur in strict sorted lexicographical order. |
| 260 | No card may be duplicated. |
| 261 | The cluster may not contain additional text or data beyond |
| 262 | what is described here. |
| 263 | Unlike manifests, clusters are never PGP signed. |
| 264 | |
| 265 | Allowed cards in the cluster are as follows: |
| 266 | |
| @@ -268,12 +268,12 @@ | |
| 268 | <b>M</b> <i>artifact-id</i><br /> |
| 269 | <b>Z</b> <i>checksum</i> |
| 270 | </blockquote> |
| 271 | |
| 272 | A cluster contains one or more "M" cards followed by a single "Z" |
| 273 | card. Each M card has a single argument which is the artifact ID of |
| 274 | another artifact in the repository. The Z card works exactly like |
| 275 | the Z card of a manifest. The argument to the Z card is the |
| 276 | lower-case hexadecimal representation of the MD5 checksum of all |
| 277 | prior cards in the cluster. The Z-card is required. |
| 278 | |
| 279 | An example cluster from Fossil can be seen |
| @@ -315,11 +315,11 @@ | |
| 315 | first value is the tag name. The first character of the tag |
| 316 | is either "+", "-", or "*". The "+" means the tag should be added |
| 317 | to the artifact. The "-" means the tag should be removed. |
| 318 | The "*" character means the tag should be added to the artifact |
| 319 | and all direct descendants (but not descendants through a merge) down |
| 320 | to but not including the first descendant that contains a |
| 321 | more recent "-", "*", or "+" tag with the same name. |
| 322 | The optional third argument is the value of the tag. A tag |
| 323 | without a value is a Boolean. |
| 324 | |
| 325 | When two or more tags with the same name are applied to the |
| @@ -331,11 +331,11 @@ | |
| 331 | for display purposes. The "user" tag overrides the name of the |
| 332 | check-in user. The "date" tag overrides the check-in date. |
| 333 | The "branch" tag sets the name of the branch that at check-in |
| 334 | belongs to. Symbolic tags begin with the "sym-" prefix. |
| 335 | |
| 336 | The U card is the name of the user that created the control |
| 337 | artifact. The Z card is the usual required artifact checksum. |
| 338 | |
| 339 | An example control artifacts can be seen [/info/9d302ccda8 | here]. |
| 340 | |
| 341 | |
| @@ -360,11 +360,11 @@ | |
| 360 | |
| 361 | The D card is the date and time when the wiki page was edited. |
| 362 | The P card specifies the parent wiki pages, if any. The L card |
| 363 | gives the name of the wiki page. The optional N card specifies |
| 364 | the mimetype of the wiki text. If the N card is omitted, the |
| 365 | mimetype is assumed to be text/x-fossil-wiki. |
| 366 | The U card specifies the login |
| 367 | of the user who made this edit to the wiki page. The Z card is |
| 368 | the usual checksum over the entire artifact and is required. |
| 369 | |
| 370 | The W card is used to specify the text of the wiki page. The |
| @@ -405,11 +405,11 @@ | |
| 405 | If the <i>value</i> parameter of the J card is omitted, then the |
| 406 | field is set to an empty string. |
| 407 | Each fossil server has a ticket configuration which specifies the fields its |
| 408 | understands. The ticket configuration is part of the local state for |
| 409 | the repository and thus can vary from one repository to another. |
| 410 | Hence a J card might specify a <i>field</i> that do not exist in the |
| 411 | local ticket configuration. If a J card specifies a <i>field</i> that |
| 412 | is not in the local configuration, then that J card |
| 413 | is simply ignored. |
| 414 | |
| 415 | The first argument of the J card is the field name. The second |
| @@ -424,11 +424,11 @@ | |
| 424 | |
| 425 | <a name="attachment"></a> |
| 426 | <h2>6.0 Attachments</h2> |
| 427 | |
| 428 | An attachment artifact associates some other artifact that is the |
| 429 | attachment (the source artifact) with a ticket or wiki page or |
| 430 | technical note to which |
| 431 | the attachment is connected (the target artifact). |
| 432 | The following cards are allowed on an attachment artifact: |
| 433 | |
| 434 | <blockquote> |
| @@ -441,11 +441,11 @@ | |
| 441 | </blockquote> |
| 442 | |
| 443 | The A card specifies a filename for the attachment in its first argument. |
| 444 | The second argument to the A card is the name of the wiki page or |
| 445 | ticket or technical note to which the attachment is connected. The |
| 446 | third argument is either missing or else it is the 40-character artifact |
| 447 | ID of the attachment itself. A missing third argument means that the |
| 448 | attachment should be deleted. |
| 449 | |
| 450 | The C card is an optional comment describing what the attachment is about. |
| 451 | The C card is optional, but there can only be one. |
| @@ -487,11 +487,11 @@ | |
| 487 | </blockquote> |
| 488 | |
| 489 | The C card contains text that is displayed on the timeline for the |
| 490 | technote. The C card is optional, but there can only be one. |
| 491 | |
| 492 | A single D card is required to give the date and time when the |
| 493 | technote artifact was created. This is different from the time at which |
| 494 | the technote appears on the timeline. |
| 495 | |
| 496 | A single E card gives the time of the technote (the point on the timeline |
| 497 | where the technote is displayed) and a unique identifier for the technote. |
| @@ -525,11 +525,11 @@ | |
| 525 | display color for timelines. |
| 526 | |
| 527 | The optional U card gives name of the user who entered the technote. |
| 528 | |
| 529 | A single W card provides wiki text for the document associated with the |
| 530 | technote. The format of the W card is exactly the same as for a |
| 531 | [#wikichng | wiki artifact]. |
| 532 | |
| 533 | The Z card is the required checksum over the rest of the artifact. |
| 534 | |
| 535 | |
| 536 |
+19
-19
| --- www/fiveminutes.wiki | ||
| +++ www/fiveminutes.wiki | ||
| @@ -4,65 +4,65 @@ | ||
| 4 | 4 | The following document was contributed by Gilles Ganault on 2013-01-08. |
| 5 | 5 | </i></b> |
| 6 | 6 | </p><hr> |
| 7 | 7 | |
| 8 | 8 | <h1>Up and running in 5 minutes as a single user</h1> |
| 9 | -<p>This short document explains the main basic Fossil commands for a single | |
| 10 | -user, i.e. with no additional users, with no need to synchronize with some remote | |
| 9 | +<p>This short document explains the main basic Fossil commands for a single | |
| 10 | +user, i.e. with no additional users, with no need to synchronize with some remote | |
| 11 | 11 | repository, and no need for branching/forking.</p> |
| 12 | 12 | |
| 13 | 13 | <h2>Create a new repository</h2> |
| 14 | 14 | <p>fossil new c:\test.repo</p> |
| 15 | -<p>This will create the new SQLite binary file that holds the repository, i.e. | |
| 16 | -files, tickets, wiki, etc. It can be located anywhere, although it's considered | |
| 17 | -best practice to keep it outside the work directory where you will work on files | |
| 15 | +<p>This will create the new SQLite binary file that holds the repository, i.e. | |
| 16 | +files, tickets, wiki, etc. It can be located anywhere, although it's considered | |
| 17 | +best practice to keep it outside the work directory where you will work on files | |
| 18 | 18 | after they've been checked out of the repository.</p> |
| 19 | 19 | |
| 20 | 20 | <h2>Open the repository</h2> |
| 21 | 21 | <p>cd c:\temp\test.fossil</p> |
| 22 | 22 | <p>fossil open c:\test.repo</p> |
| 23 | -<p>This will check out the last revision of all the files in the repository, | |
| 24 | -if any, into the current work directory. In addition, it will create a binary | |
| 23 | +<p>This will check out the last revision of all the files in the repository, | |
| 24 | +if any, into the current work directory. In addition, it will create a binary | |
| 25 | 25 | file _FOSSIL_ to keep track of changes (on non-Windows systems it is called |
| 26 | 26 | <tt>.fslckout</tt>).</p> |
| 27 | 27 | |
| 28 | 28 | <h2>Add new files</h2> |
| 29 | 29 | <p>fossil add .</p> |
| 30 | -<p>To tell Fossil to add new files to the repository. The files aren't actually | |
| 31 | -added until you run "commit". When using ".", it tells Fossil | |
| 32 | -to add all the files in the current directory recursively, i.e. including all | |
| 30 | +<p>To tell Fossil to add new files to the repository. The files aren't actually | |
| 31 | +added until you run "commit". When using ".", it tells Fossil | |
| 32 | +to add all the files in the current directory recursively, i.e. including all | |
| 33 | 33 | the files in all the subdirectories.</p> |
| 34 | 34 | <p>Note: To tell Fossil to ignore some extensions:</p> |
| 35 | 35 | <p>fossil settings ignore-glob "*.o,*.obj,*.exe" --global</p> |
| 36 | 36 | |
| 37 | 37 | <h2>Remove files that haven't been committed yet</h2> |
| 38 | 38 | <p>fossil delete myfile.c</p> |
| 39 | -<p>This will simply remove the item from the list of files that were previously | |
| 39 | +<p>This will simply remove the item from the list of files that were previously | |
| 40 | 40 | added through "fossil add".</p> |
| 41 | 41 | |
| 42 | 42 | <h2>Check current status</h2> |
| 43 | 43 | <p>fossil changes</p> |
| 44 | -<p>This shows the list of changes that have been done and will be committed the | |
| 45 | -next time you run "fossil commit". It's a useful command to run before | |
| 44 | +<p>This shows the list of changes that have been done and will be committed the | |
| 45 | +next time you run "fossil commit". It's a useful command to run before | |
| 46 | 46 | running "fossil commit" just to check that things are OK before proceeding.</p> |
| 47 | 47 | |
| 48 | 48 | <h2>Commit changes</h2> |
| 49 | -<p>To actually apply the pending changes to the repository, e.g. new files marked | |
| 50 | -for addition, checked-out files that have been edited and must be checked-in, | |
| 49 | +<p>To actually apply the pending changes to the repository, e.g. new files marked | |
| 50 | +for addition, checked-out files that have been edited and must be checked-in, | |
| 51 | 51 | etc.</p> |
| 52 | 52 | |
| 53 | 53 | <p>fossil commit -m "Added stuff"</p> |
| 54 | 54 | |
| 55 | 55 | If no file names are provided on the command-line then all changes will be checked in, |
| 56 | 56 | otherwise just the listed file(s) will be checked in. |
| 57 | 57 | |
| 58 | 58 | <h2>Compare two revisions of a file</h2> |
| 59 | -<p>If you wish to compare the last revision of a file and its checked out version | |
| 59 | +<p>If you wish to compare the last revision of a file and its checked out version | |
| 60 | 60 | in your work directory:</p> |
| 61 | 61 | <p>fossil gdiff myfile.c</p> |
| 62 | 62 | <p>If you wish to compare two different revisions of a file in the repository:</p> |
| 63 | -<p>fossil finfo myfile: Note the first hash, which is the UUID of the commit | |
| 63 | +<p>fossil finfo myfile: Note the first hash, which is the UUID of the commit | |
| 64 | 64 | when the file was committed</p> |
| 65 | 65 | <p>fossil gdiff --from UUID#1 --to UUID#2 myfile.c</p> |
| 66 | 66 | <h2>Cancel changes and go back to previous revision</h2> |
| 67 | 67 | <p>fossil revert myfile.c</p> |
| 68 | 68 | <p>Fossil does not prompt when reverting a file. It simply reminds the user about the |
| @@ -69,8 +69,8 @@ | ||
| 69 | 69 | "undo" command, just in case the revert was a mistake.</p> |
| 70 | 70 | |
| 71 | 71 | |
| 72 | 72 | <h2>Close the repository</h2> |
| 73 | 73 | <p>fossil close</p> |
| 74 | -<p>This will simply remove the _FOSSIL_ at the root of the work directory but | |
| 75 | -will not delete the files in the work directory. From then on, any use of "fossil" | |
| 74 | +<p>This will simply remove the _FOSSIL_ at the root of the work directory but | |
| 75 | +will not delete the files in the work directory. From then on, any use of "fossil" | |
| 76 | 76 | will trigger an error since there is no longer any connection.</p> |
| 77 | 77 |
| --- www/fiveminutes.wiki | |
| +++ www/fiveminutes.wiki | |
| @@ -4,65 +4,65 @@ | |
| 4 | The following document was contributed by Gilles Ganault on 2013-01-08. |
| 5 | </i></b> |
| 6 | </p><hr> |
| 7 | |
| 8 | <h1>Up and running in 5 minutes as a single user</h1> |
| 9 | <p>This short document explains the main basic Fossil commands for a single |
| 10 | user, i.e. with no additional users, with no need to synchronize with some remote |
| 11 | repository, and no need for branching/forking.</p> |
| 12 | |
| 13 | <h2>Create a new repository</h2> |
| 14 | <p>fossil new c:\test.repo</p> |
| 15 | <p>This will create the new SQLite binary file that holds the repository, i.e. |
| 16 | files, tickets, wiki, etc. It can be located anywhere, although it's considered |
| 17 | best practice to keep it outside the work directory where you will work on files |
| 18 | after they've been checked out of the repository.</p> |
| 19 | |
| 20 | <h2>Open the repository</h2> |
| 21 | <p>cd c:\temp\test.fossil</p> |
| 22 | <p>fossil open c:\test.repo</p> |
| 23 | <p>This will check out the last revision of all the files in the repository, |
| 24 | if any, into the current work directory. In addition, it will create a binary |
| 25 | file _FOSSIL_ to keep track of changes (on non-Windows systems it is called |
| 26 | <tt>.fslckout</tt>).</p> |
| 27 | |
| 28 | <h2>Add new files</h2> |
| 29 | <p>fossil add .</p> |
| 30 | <p>To tell Fossil to add new files to the repository. The files aren't actually |
| 31 | added until you run "commit". When using ".", it tells Fossil |
| 32 | to add all the files in the current directory recursively, i.e. including all |
| 33 | the files in all the subdirectories.</p> |
| 34 | <p>Note: To tell Fossil to ignore some extensions:</p> |
| 35 | <p>fossil settings ignore-glob "*.o,*.obj,*.exe" --global</p> |
| 36 | |
| 37 | <h2>Remove files that haven't been committed yet</h2> |
| 38 | <p>fossil delete myfile.c</p> |
| 39 | <p>This will simply remove the item from the list of files that were previously |
| 40 | added through "fossil add".</p> |
| 41 | |
| 42 | <h2>Check current status</h2> |
| 43 | <p>fossil changes</p> |
| 44 | <p>This shows the list of changes that have been done and will be committed the |
| 45 | next time you run "fossil commit". It's a useful command to run before |
| 46 | running "fossil commit" just to check that things are OK before proceeding.</p> |
| 47 | |
| 48 | <h2>Commit changes</h2> |
| 49 | <p>To actually apply the pending changes to the repository, e.g. new files marked |
| 50 | for addition, checked-out files that have been edited and must be checked-in, |
| 51 | etc.</p> |
| 52 | |
| 53 | <p>fossil commit -m "Added stuff"</p> |
| 54 | |
| 55 | If no file names are provided on the command-line then all changes will be checked in, |
| 56 | otherwise just the listed file(s) will be checked in. |
| 57 | |
| 58 | <h2>Compare two revisions of a file</h2> |
| 59 | <p>If you wish to compare the last revision of a file and its checked out version |
| 60 | in your work directory:</p> |
| 61 | <p>fossil gdiff myfile.c</p> |
| 62 | <p>If you wish to compare two different revisions of a file in the repository:</p> |
| 63 | <p>fossil finfo myfile: Note the first hash, which is the UUID of the commit |
| 64 | when the file was committed</p> |
| 65 | <p>fossil gdiff --from UUID#1 --to UUID#2 myfile.c</p> |
| 66 | <h2>Cancel changes and go back to previous revision</h2> |
| 67 | <p>fossil revert myfile.c</p> |
| 68 | <p>Fossil does not prompt when reverting a file. It simply reminds the user about the |
| @@ -69,8 +69,8 @@ | |
| 69 | "undo" command, just in case the revert was a mistake.</p> |
| 70 | |
| 71 | |
| 72 | <h2>Close the repository</h2> |
| 73 | <p>fossil close</p> |
| 74 | <p>This will simply remove the _FOSSIL_ at the root of the work directory but |
| 75 | will not delete the files in the work directory. From then on, any use of "fossil" |
| 76 | will trigger an error since there is no longer any connection.</p> |
| 77 |
| --- www/fiveminutes.wiki | |
| +++ www/fiveminutes.wiki | |
| @@ -4,65 +4,65 @@ | |
| 4 | The following document was contributed by Gilles Ganault on 2013-01-08. |
| 5 | </i></b> |
| 6 | </p><hr> |
| 7 | |
| 8 | <h1>Up and running in 5 minutes as a single user</h1> |
| 9 | <p>This short document explains the main basic Fossil commands for a single |
| 10 | user, i.e. with no additional users, with no need to synchronize with some remote |
| 11 | repository, and no need for branching/forking.</p> |
| 12 | |
| 13 | <h2>Create a new repository</h2> |
| 14 | <p>fossil new c:\test.repo</p> |
| 15 | <p>This will create the new SQLite binary file that holds the repository, i.e. |
| 16 | files, tickets, wiki, etc. It can be located anywhere, although it's considered |
| 17 | best practice to keep it outside the work directory where you will work on files |
| 18 | after they've been checked out of the repository.</p> |
| 19 | |
| 20 | <h2>Open the repository</h2> |
| 21 | <p>cd c:\temp\test.fossil</p> |
| 22 | <p>fossil open c:\test.repo</p> |
| 23 | <p>This will check out the last revision of all the files in the repository, |
| 24 | if any, into the current work directory. In addition, it will create a binary |
| 25 | file _FOSSIL_ to keep track of changes (on non-Windows systems it is called |
| 26 | <tt>.fslckout</tt>).</p> |
| 27 | |
| 28 | <h2>Add new files</h2> |
| 29 | <p>fossil add .</p> |
| 30 | <p>To tell Fossil to add new files to the repository. The files aren't actually |
| 31 | added until you run "commit". When using ".", it tells Fossil |
| 32 | to add all the files in the current directory recursively, i.e. including all |
| 33 | the files in all the subdirectories.</p> |
| 34 | <p>Note: To tell Fossil to ignore some extensions:</p> |
| 35 | <p>fossil settings ignore-glob "*.o,*.obj,*.exe" --global</p> |
| 36 | |
| 37 | <h2>Remove files that haven't been committed yet</h2> |
| 38 | <p>fossil delete myfile.c</p> |
| 39 | <p>This will simply remove the item from the list of files that were previously |
| 40 | added through "fossil add".</p> |
| 41 | |
| 42 | <h2>Check current status</h2> |
| 43 | <p>fossil changes</p> |
| 44 | <p>This shows the list of changes that have been done and will be committed the |
| 45 | next time you run "fossil commit". It's a useful command to run before |
| 46 | running "fossil commit" just to check that things are OK before proceeding.</p> |
| 47 | |
| 48 | <h2>Commit changes</h2> |
| 49 | <p>To actually apply the pending changes to the repository, e.g. new files marked |
| 50 | for addition, checked-out files that have been edited and must be checked-in, |
| 51 | etc.</p> |
| 52 | |
| 53 | <p>fossil commit -m "Added stuff"</p> |
| 54 | |
| 55 | If no file names are provided on the command-line then all changes will be checked in, |
| 56 | otherwise just the listed file(s) will be checked in. |
| 57 | |
| 58 | <h2>Compare two revisions of a file</h2> |
| 59 | <p>If you wish to compare the last revision of a file and its checked out version |
| 60 | in your work directory:</p> |
| 61 | <p>fossil gdiff myfile.c</p> |
| 62 | <p>If you wish to compare two different revisions of a file in the repository:</p> |
| 63 | <p>fossil finfo myfile: Note the first hash, which is the UUID of the commit |
| 64 | when the file was committed</p> |
| 65 | <p>fossil gdiff --from UUID#1 --to UUID#2 myfile.c</p> |
| 66 | <h2>Cancel changes and go back to previous revision</h2> |
| 67 | <p>fossil revert myfile.c</p> |
| 68 | <p>Fossil does not prompt when reverting a file. It simply reminds the user about the |
| @@ -69,8 +69,8 @@ | |
| 69 | "undo" command, just in case the revert was a mistake.</p> |
| 70 | |
| 71 | |
| 72 | <h2>Close the repository</h2> |
| 73 | <p>fossil close</p> |
| 74 | <p>This will simply remove the _FOSSIL_ at the root of the work directory but |
| 75 | will not delete the files in the work directory. From then on, any use of "fossil" |
| 76 | will trigger an error since there is no longer any connection.</p> |
| 77 |
+2
-2
| --- www/foss-cklist.wiki | ||
| +++ www/foss-cklist.wiki | ||
| @@ -89,11 +89,11 @@ | ||
| 89 | 89 | |
| 90 | 90 | <li><p>The project has a website. |
| 91 | 91 | |
| 92 | 92 | <li><p>Release version numbers are in the traditional X.Y or X.Y.Z format. |
| 93 | 93 | |
| 94 | -<li><p>Releases can be downloaded as tarball using | |
| 94 | +<li><p>Releases can be downloaded as tarball using | |
| 95 | 95 | gzip or bzip2 compression. |
| 96 | 96 | |
| 97 | 97 | <li><p>Releases unpack into a versioned top-level directory. |
| 98 | 98 | (ex: "projectname-1.2.3/"). |
| 99 | 99 | |
| @@ -102,12 +102,12 @@ | ||
| 102 | 102 | tarball. |
| 103 | 103 | |
| 104 | 104 | <li><p>There are no incompatible licenses in the code. |
| 105 | 105 | |
| 106 | 106 | <li><p>The project has not been blithely proclaimed "public domain" without |
| 107 | -having gone through the tedious and exacting legal steps to actually put it | |
| 107 | +having gone through the tedious and exacting legal steps to actually put it | |
| 108 | 108 | in the public domain. |
| 109 | 109 | |
| 110 | 110 | <li><p>There is an accurate change log in the code and on the website. |
| 111 | 111 | |
| 112 | 112 | <li><p>There is documentation in the code and on the website. |
| 113 | 113 | </ol> |
| 114 | 114 |
| --- www/foss-cklist.wiki | |
| +++ www/foss-cklist.wiki | |
| @@ -89,11 +89,11 @@ | |
| 89 | |
| 90 | <li><p>The project has a website. |
| 91 | |
| 92 | <li><p>Release version numbers are in the traditional X.Y or X.Y.Z format. |
| 93 | |
| 94 | <li><p>Releases can be downloaded as tarball using |
| 95 | gzip or bzip2 compression. |
| 96 | |
| 97 | <li><p>Releases unpack into a versioned top-level directory. |
| 98 | (ex: "projectname-1.2.3/"). |
| 99 | |
| @@ -102,12 +102,12 @@ | |
| 102 | tarball. |
| 103 | |
| 104 | <li><p>There are no incompatible licenses in the code. |
| 105 | |
| 106 | <li><p>The project has not been blithely proclaimed "public domain" without |
| 107 | having gone through the tedious and exacting legal steps to actually put it |
| 108 | in the public domain. |
| 109 | |
| 110 | <li><p>There is an accurate change log in the code and on the website. |
| 111 | |
| 112 | <li><p>There is documentation in the code and on the website. |
| 113 | </ol> |
| 114 |
| --- www/foss-cklist.wiki | |
| +++ www/foss-cklist.wiki | |
| @@ -89,11 +89,11 @@ | |
| 89 | |
| 90 | <li><p>The project has a website. |
| 91 | |
| 92 | <li><p>Release version numbers are in the traditional X.Y or X.Y.Z format. |
| 93 | |
| 94 | <li><p>Releases can be downloaded as tarball using |
| 95 | gzip or bzip2 compression. |
| 96 | |
| 97 | <li><p>Releases unpack into a versioned top-level directory. |
| 98 | (ex: "projectname-1.2.3/"). |
| 99 | |
| @@ -102,12 +102,12 @@ | |
| 102 | tarball. |
| 103 | |
| 104 | <li><p>There are no incompatible licenses in the code. |
| 105 | |
| 106 | <li><p>The project has not been blithely proclaimed "public domain" without |
| 107 | having gone through the tedious and exacting legal steps to actually put it |
| 108 | in the public domain. |
| 109 | |
| 110 | <li><p>There is an accurate change log in the code and on the website. |
| 111 | |
| 112 | <li><p>There is documentation in the code and on the website. |
| 113 | </ol> |
| 114 |
+11
-11
| --- www/fossil-from-msvc.wiki | ||
| +++ www/fossil-from-msvc.wiki | ||
| @@ -11,41 +11,41 @@ | ||
| 11 | 11 | <li>Tools > External Tools, where the items in this list map |
| 12 | 12 | to "External Tool X" that we'll add to our own Fossil |
| 13 | 13 | menu later: </li> |
| 14 | 14 | <ol type="1"> |
| 15 | 15 | <li>Rename the default "[New Tool 1]" to eg. |
| 16 | - "Commit" 2. | |
| 16 | + "Commit" 2. | |
| 17 | 17 | </li> |
| 18 | 18 | <li>Change Command to where Fossil is located eg. |
| 19 | 19 | "c:\fossil.exe"</li> |
| 20 | 20 | <li>Change Arguments to the required command, eg. |
| 21 | - "commit -m". | |
| 21 | + "commit -m". | |
| 22 | 22 | The user will be prompted to type the comment that Commit expects</li> |
| 23 | - <li>Set "Initial Directory" to point it to the work directory | |
| 23 | + <li>Set "Initial Directory" to point it to the work directory | |
| 24 | 24 | where the source files are currently checked out |
| 25 | 25 | by Fossil (eg. c:\Workspace). It's also possible to use system |
| 26 | 26 | variables such as "$(ProjectDir)" instead of hard-coding the path</li> |
| 27 | 27 | <li>Check "Prompt for arguments", since Commit |
| 28 | 28 | requires typing a comment. Useless for commands like Changes |
| 29 | 29 | that don't require arguments</li> |
| 30 | - <li>Uncheck "Close on Exit", so we can see what Fossil says | |
| 31 | - before closing the DOS box. Note that "Use Output Window" | |
| 32 | - will display the output in a child window within the IDE instead of | |
| 30 | + <li>Uncheck "Close on Exit", so we can see what Fossil says | |
| 31 | + before closing the DOS box. Note that "Use Output Window" | |
| 32 | + will display the output in a child window within the IDE instead of | |
| 33 | 33 | opening a DOS box</li> |
| 34 | 34 | <li>Click on OK</li> |
| 35 | 35 | </ol> |
| 36 | 36 | <li>Tools > Customize > Commands</li> |
| 37 | 37 | <ol type="1"> |
| 38 | - <li>With "Menu bar = Menu Bar" selected, click on "Add | |
| 38 | + <li>With "Menu bar = Menu Bar" selected, click on "Add | |
| 39 | 39 | New Menu". A new "Fossil" menu is displayed in the |
| 40 | 40 | IDE's menu bar</li> |
| 41 | 41 | <li>Click on "Modify Selection" to rename it |
| 42 | 42 | "Fossil", and...</li> |
| 43 | 43 | <li>Use the "Move Down" button to move it lower in |
| 44 | 44 | the list</li> |
| 45 | 45 | </ol> |
| 46 | - <li>Still in Customize dialog: In the "Menu bar" combo, select | |
| 47 | - the new Fossil menu you just created, and Click on "Add Command...": | |
| 48 | - From Categories, select Tools, and select "External Command 1". | |
| 49 | - Click on Close. It's unfortunate that the IDE doesn't say which command | |
| 46 | + <li>Still in Customize dialog: In the "Menu bar" combo, select | |
| 47 | + the new Fossil menu you just created, and Click on "Add Command...": | |
| 48 | + From Categories, select Tools, and select "External Command 1". | |
| 49 | + Click on Close. It's unfortunate that the IDE doesn't say which command | |
| 50 | 50 | maps to "External Command X".</li> |
| 51 | 51 | </ol> |
| 52 | 52 |
| --- www/fossil-from-msvc.wiki | |
| +++ www/fossil-from-msvc.wiki | |
| @@ -11,41 +11,41 @@ | |
| 11 | <li>Tools > External Tools, where the items in this list map |
| 12 | to "External Tool X" that we'll add to our own Fossil |
| 13 | menu later: </li> |
| 14 | <ol type="1"> |
| 15 | <li>Rename the default "[New Tool 1]" to eg. |
| 16 | "Commit" 2. |
| 17 | </li> |
| 18 | <li>Change Command to where Fossil is located eg. |
| 19 | "c:\fossil.exe"</li> |
| 20 | <li>Change Arguments to the required command, eg. |
| 21 | "commit -m". |
| 22 | The user will be prompted to type the comment that Commit expects</li> |
| 23 | <li>Set "Initial Directory" to point it to the work directory |
| 24 | where the source files are currently checked out |
| 25 | by Fossil (eg. c:\Workspace). It's also possible to use system |
| 26 | variables such as "$(ProjectDir)" instead of hard-coding the path</li> |
| 27 | <li>Check "Prompt for arguments", since Commit |
| 28 | requires typing a comment. Useless for commands like Changes |
| 29 | that don't require arguments</li> |
| 30 | <li>Uncheck "Close on Exit", so we can see what Fossil says |
| 31 | before closing the DOS box. Note that "Use Output Window" |
| 32 | will display the output in a child window within the IDE instead of |
| 33 | opening a DOS box</li> |
| 34 | <li>Click on OK</li> |
| 35 | </ol> |
| 36 | <li>Tools > Customize > Commands</li> |
| 37 | <ol type="1"> |
| 38 | <li>With "Menu bar = Menu Bar" selected, click on "Add |
| 39 | New Menu". A new "Fossil" menu is displayed in the |
| 40 | IDE's menu bar</li> |
| 41 | <li>Click on "Modify Selection" to rename it |
| 42 | "Fossil", and...</li> |
| 43 | <li>Use the "Move Down" button to move it lower in |
| 44 | the list</li> |
| 45 | </ol> |
| 46 | <li>Still in Customize dialog: In the "Menu bar" combo, select |
| 47 | the new Fossil menu you just created, and Click on "Add Command...": |
| 48 | From Categories, select Tools, and select "External Command 1". |
| 49 | Click on Close. It's unfortunate that the IDE doesn't say which command |
| 50 | maps to "External Command X".</li> |
| 51 | </ol> |
| 52 |
| --- www/fossil-from-msvc.wiki | |
| +++ www/fossil-from-msvc.wiki | |
| @@ -11,41 +11,41 @@ | |
| 11 | <li>Tools > External Tools, where the items in this list map |
| 12 | to "External Tool X" that we'll add to our own Fossil |
| 13 | menu later: </li> |
| 14 | <ol type="1"> |
| 15 | <li>Rename the default "[New Tool 1]" to eg. |
| 16 | "Commit" 2. |
| 17 | </li> |
| 18 | <li>Change Command to where Fossil is located eg. |
| 19 | "c:\fossil.exe"</li> |
| 20 | <li>Change Arguments to the required command, eg. |
| 21 | "commit -m". |
| 22 | The user will be prompted to type the comment that Commit expects</li> |
| 23 | <li>Set "Initial Directory" to point it to the work directory |
| 24 | where the source files are currently checked out |
| 25 | by Fossil (eg. c:\Workspace). It's also possible to use system |
| 26 | variables such as "$(ProjectDir)" instead of hard-coding the path</li> |
| 27 | <li>Check "Prompt for arguments", since Commit |
| 28 | requires typing a comment. Useless for commands like Changes |
| 29 | that don't require arguments</li> |
| 30 | <li>Uncheck "Close on Exit", so we can see what Fossil says |
| 31 | before closing the DOS box. Note that "Use Output Window" |
| 32 | will display the output in a child window within the IDE instead of |
| 33 | opening a DOS box</li> |
| 34 | <li>Click on OK</li> |
| 35 | </ol> |
| 36 | <li>Tools > Customize > Commands</li> |
| 37 | <ol type="1"> |
| 38 | <li>With "Menu bar = Menu Bar" selected, click on "Add |
| 39 | New Menu". A new "Fossil" menu is displayed in the |
| 40 | IDE's menu bar</li> |
| 41 | <li>Click on "Modify Selection" to rename it |
| 42 | "Fossil", and...</li> |
| 43 | <li>Use the "Move Down" button to move it lower in |
| 44 | the list</li> |
| 45 | </ol> |
| 46 | <li>Still in Customize dialog: In the "Menu bar" combo, select |
| 47 | the new Fossil menu you just created, and Click on "Add Command...": |
| 48 | From Categories, select Tools, and select "External Command 1". |
| 49 | Click on Close. It's unfortunate that the IDE doesn't say which command |
| 50 | maps to "External Command X".</li> |
| 51 | </ol> |
| 52 |
+2
-2
| --- www/index.wiki | ||
| +++ www/index.wiki | ||
| @@ -2,11 +2,11 @@ | ||
| 2 | 2 | |
| 3 | 3 | <h3>What Is Fossil?</h3> |
| 4 | 4 | |
| 5 | 5 | <div style='width:200px;float:right;border:2px solid #446979;padding:10px;margin:0px 10px;'> |
| 6 | 6 | <ul> |
| 7 | -<li> [http://www.fossil-scm.org/download.html | Download] | |
| 7 | +<li> [/uv/download.html | Download] | |
| 8 | 8 | <li> [./quickstart.wiki | Quick Start] |
| 9 | 9 | <li> [./build.wiki | Install] |
| 10 | 10 | <li> [../COPYRIGHT-BSD2.txt | License] |
| 11 | 11 | <li> [./faq.wiki | FAQ] |
| 12 | 12 | <li> [./changes.wiki | Change Log] |
| @@ -38,11 +38,11 @@ | ||
| 38 | 38 | ([./webpage-ex.md|examples]) designed to promote situational awareness. |
| 39 | 39 | |
| 40 | 40 | This entire website is just a running instance of Fossil. |
| 41 | 41 | The pages you see here are all [./wikitheory.wiki | wiki] or |
| 42 | 42 | [./embeddeddoc.wiki | embedded documentation] or (in the case of |
| 43 | - the [/uv/download.html|download] page) | |
| 43 | + the [/uv/download.html|download] page) | |
| 44 | 44 | [./unvers.wiki | unversioned files]. |
| 45 | 45 | When you clone Fossil from one of its |
| 46 | 46 | [./selfhost.wiki | self-hosting repositories], |
| 47 | 47 | you get more than just source code - you get this entire website. |
| 48 | 48 | |
| 49 | 49 |
| --- www/index.wiki | |
| +++ www/index.wiki | |
| @@ -2,11 +2,11 @@ | |
| 2 | |
| 3 | <h3>What Is Fossil?</h3> |
| 4 | |
| 5 | <div style='width:200px;float:right;border:2px solid #446979;padding:10px;margin:0px 10px;'> |
| 6 | <ul> |
| 7 | <li> [http://www.fossil-scm.org/download.html | Download] |
| 8 | <li> [./quickstart.wiki | Quick Start] |
| 9 | <li> [./build.wiki | Install] |
| 10 | <li> [../COPYRIGHT-BSD2.txt | License] |
| 11 | <li> [./faq.wiki | FAQ] |
| 12 | <li> [./changes.wiki | Change Log] |
| @@ -38,11 +38,11 @@ | |
| 38 | ([./webpage-ex.md|examples]) designed to promote situational awareness. |
| 39 | |
| 40 | This entire website is just a running instance of Fossil. |
| 41 | The pages you see here are all [./wikitheory.wiki | wiki] or |
| 42 | [./embeddeddoc.wiki | embedded documentation] or (in the case of |
| 43 | the [/uv/download.html|download] page) |
| 44 | [./unvers.wiki | unversioned files]. |
| 45 | When you clone Fossil from one of its |
| 46 | [./selfhost.wiki | self-hosting repositories], |
| 47 | you get more than just source code - you get this entire website. |
| 48 | |
| 49 |
| --- www/index.wiki | |
| +++ www/index.wiki | |
| @@ -2,11 +2,11 @@ | |
| 2 | |
| 3 | <h3>What Is Fossil?</h3> |
| 4 | |
| 5 | <div style='width:200px;float:right;border:2px solid #446979;padding:10px;margin:0px 10px;'> |
| 6 | <ul> |
| 7 | <li> [/uv/download.html | Download] |
| 8 | <li> [./quickstart.wiki | Quick Start] |
| 9 | <li> [./build.wiki | Install] |
| 10 | <li> [../COPYRIGHT-BSD2.txt | License] |
| 11 | <li> [./faq.wiki | FAQ] |
| 12 | <li> [./changes.wiki | Change Log] |
| @@ -38,11 +38,11 @@ | |
| 38 | ([./webpage-ex.md|examples]) designed to promote situational awareness. |
| 39 | |
| 40 | This entire website is just a running instance of Fossil. |
| 41 | The pages you see here are all [./wikitheory.wiki | wiki] or |
| 42 | [./embeddeddoc.wiki | embedded documentation] or (in the case of |
| 43 | the [/uv/download.html|download] page) |
| 44 | [./unvers.wiki | unversioned files]. |
| 45 | When you clone Fossil from one of its |
| 46 | [./selfhost.wiki | self-hosting repositories], |
| 47 | you get more than just source code - you get this entire website. |
| 48 | |
| 49 |
+54
-15
| --- www/inout.wiki | ||
| +++ www/inout.wiki | ||
| @@ -1,10 +1,10 @@ | ||
| 1 | 1 | <title>Import And Export</title> |
| 2 | 2 | |
| 3 | -Fossil has the ability to import and export repositories from and to | |
| 3 | +Fossil has the ability to import and export repositories from and to | |
| 4 | 4 | [http://git-scm.com/ | Git]. And since most other version control |
| 5 | -systems will also import/export from Git, that means that you can | |
| 5 | +systems will also import/export from Git, that means that you can | |
| 6 | 6 | import/export a Fossil repository to most version control systems using |
| 7 | 7 | Git as an intermediary. |
| 8 | 8 | |
| 9 | 9 | <h2>Git → Fossil</h2> |
| 10 | 10 | |
| @@ -20,11 +20,11 @@ | ||
| 20 | 20 | command is the name of a new Fossil repository that is created to hold the Git |
| 21 | 21 | content. |
| 22 | 22 | |
| 23 | 23 | The --git option is not actually required. The git-fast-export file format |
| 24 | 24 | is currently the only VCS interchange format that Fossil understands. But |
| 25 | -future versions of Fossil might be enhanced to understand other VCS | |
| 25 | +future versions of Fossil might be enhanced to understand other VCS | |
| 26 | 26 | interchange formats, and so for compatibility, use of the |
| 27 | 27 | --git option is recommended. |
| 28 | 28 | |
| 29 | 29 | <h2>Fossil → Git</h2> |
| 30 | 30 | |
| @@ -43,21 +43,60 @@ | ||
| 43 | 43 | Note that the "fossil export --git" command only exports the versioned files. |
| 44 | 44 | Tickets and wiki and events are not exported, since Git does not understand |
| 45 | 45 | those concepts. |
| 46 | 46 | |
| 47 | 47 | As with the "import" command, the --git option is not required |
| 48 | -since the git-fast-export file format is currently the only VCS interchange | |
| 48 | +since the git-fast-export file format is currently the only VCS interchange | |
| 49 | 49 | format that Fossil will generate. However, |
| 50 | 50 | future versions of Fossil might add the ability to generate other |
| 51 | -VCS interchange formats, and so for compatibility, the use of the --git | |
| 51 | +VCS interchange formats, and so for compatibility, the use of the --git | |
| 52 | 52 | option recommended. |
| 53 | 53 | |
| 54 | -An anonymous user sends this comment: | |
| 55 | - | |
| 56 | -<blockquote> | |
| 57 | -The main Fossil branch is called "trunk", while the main git branch is | |
| 58 | -called "master". After you've exported your FOSSIL repo to git, you won't | |
| 59 | -see any files and gitk will complain about a missing "HEAD". You can | |
| 60 | -resolve this problem by merging "trunk" with "master" | |
| 61 | -(first verify using git status that you are on the "master" branch): | |
| 62 | -<tt>git merge trunk</tt> | |
| 63 | -</blockquote> | |
| 54 | +<h2>Bidirectional Synchronization</h2> | |
| 55 | +Fossil also has the ability to synchronize with a Git repository via repeated | |
| 56 | +imports and/or exports. To do this, it uses marks files to store a record of | |
| 57 | +artifacts which are known by both Git and Fossil to exist at a given point in | |
| 58 | +time. | |
| 59 | + | |
| 60 | +To illustrate, consider the example of a remote Fossil repository that a | |
| 61 | +user wants to import into a local Git repository. First, the user would clone | |
| 62 | +the remote repository and import it into a new Git repository: | |
| 63 | + | |
| 64 | +<blockquote><pre> | |
| 65 | +fossil clone /path/to/remote/repo.fossil repo.fossil | |
| 66 | +mkdir repo | |
| 67 | +cd repo | |
| 68 | +fossil open ../repo.fossil | |
| 69 | +mkdir ../repo.git | |
| 70 | +cd ../repo.git | |
| 71 | +git init . | |
| 72 | +fossil export --git --export-marks ../repo/fossil.marks \ | |
| 73 | + ../repo.fossil | git fast-import \ | |
| 74 | + --export-marks=../repo/git.marks | |
| 75 | +</pre></blockquote> | |
| 76 | + | |
| 77 | +Once the import has completed, the user would need to <tt>git checkout | |
| 78 | +trunk</tt>. At any point after this, new changes can be imported from the | |
| 79 | +remote Fossil repository: | |
| 80 | + | |
| 81 | +<blockquote><pre> | |
| 82 | +cd ../repo | |
| 83 | +fossil pull | |
| 84 | +cd ../repo.git | |
| 85 | +fossil export --git --import-marks ../repo/fossil.marks \ | |
| 86 | + --export-marks ../repo/fossil.marks \ | |
| 87 | + ../repo.fossil | git fast-import \ | |
| 88 | + --import-marks=../repo/git.marks \ | |
| 89 | + --export-marks=../repo/git.marks | |
| 90 | +</pre></blockquote> | |
| 91 | + | |
| 92 | +Changes in the Git repository can be exported to the Fossil repository and then | |
| 93 | +pushed to the remote: | |
| 94 | + | |
| 95 | +<blockquote><pre> | |
| 96 | +git fast-export --import-marks=../repo/git.marks \ | |
| 97 | + --export-marks=../repo/git.marks --all | fossil import --git \ | |
| 98 | + --incremental --import-marks ../repo/fossil.marks \ | |
| 99 | + --export-marks ../repo/fossil.marks ../repo.fossil | |
| 100 | +cd ../repo | |
| 101 | +fossil push | |
| 102 | +</pre></blockquote> | |
| 64 | 103 |
| --- www/inout.wiki | |
| +++ www/inout.wiki | |
| @@ -1,10 +1,10 @@ | |
| 1 | <title>Import And Export</title> |
| 2 | |
| 3 | Fossil has the ability to import and export repositories from and to |
| 4 | [http://git-scm.com/ | Git]. And since most other version control |
| 5 | systems will also import/export from Git, that means that you can |
| 6 | import/export a Fossil repository to most version control systems using |
| 7 | Git as an intermediary. |
| 8 | |
| 9 | <h2>Git → Fossil</h2> |
| 10 | |
| @@ -20,11 +20,11 @@ | |
| 20 | command is the name of a new Fossil repository that is created to hold the Git |
| 21 | content. |
| 22 | |
| 23 | The --git option is not actually required. The git-fast-export file format |
| 24 | is currently the only VCS interchange format that Fossil understands. But |
| 25 | future versions of Fossil might be enhanced to understand other VCS |
| 26 | interchange formats, and so for compatibility, use of the |
| 27 | --git option is recommended. |
| 28 | |
| 29 | <h2>Fossil → Git</h2> |
| 30 | |
| @@ -43,21 +43,60 @@ | |
| 43 | Note that the "fossil export --git" command only exports the versioned files. |
| 44 | Tickets and wiki and events are not exported, since Git does not understand |
| 45 | those concepts. |
| 46 | |
| 47 | As with the "import" command, the --git option is not required |
| 48 | since the git-fast-export file format is currently the only VCS interchange |
| 49 | format that Fossil will generate. However, |
| 50 | future versions of Fossil might add the ability to generate other |
| 51 | VCS interchange formats, and so for compatibility, the use of the --git |
| 52 | option recommended. |
| 53 | |
| 54 | An anonymous user sends this comment: |
| 55 | |
| 56 | <blockquote> |
| 57 | The main Fossil branch is called "trunk", while the main git branch is |
| 58 | called "master". After you've exported your FOSSIL repo to git, you won't |
| 59 | see any files and gitk will complain about a missing "HEAD". You can |
| 60 | resolve this problem by merging "trunk" with "master" |
| 61 | (first verify using git status that you are on the "master" branch): |
| 62 | <tt>git merge trunk</tt> |
| 63 | </blockquote> |
| 64 |
| --- www/inout.wiki | |
| +++ www/inout.wiki | |
| @@ -1,10 +1,10 @@ | |
| 1 | <title>Import And Export</title> |
| 2 | |
| 3 | Fossil has the ability to import and export repositories from and to |
| 4 | [http://git-scm.com/ | Git]. And since most other version control |
| 5 | systems will also import/export from Git, that means that you can |
| 6 | import/export a Fossil repository to most version control systems using |
| 7 | Git as an intermediary. |
| 8 | |
| 9 | <h2>Git → Fossil</h2> |
| 10 | |
| @@ -20,11 +20,11 @@ | |
| 20 | command is the name of a new Fossil repository that is created to hold the Git |
| 21 | content. |
| 22 | |
| 23 | The --git option is not actually required. The git-fast-export file format |
| 24 | is currently the only VCS interchange format that Fossil understands. But |
| 25 | future versions of Fossil might be enhanced to understand other VCS |
| 26 | interchange formats, and so for compatibility, use of the |
| 27 | --git option is recommended. |
| 28 | |
| 29 | <h2>Fossil → Git</h2> |
| 30 | |
| @@ -43,21 +43,60 @@ | |
| 43 | Note that the "fossil export --git" command only exports the versioned files. |
| 44 | Tickets and wiki and events are not exported, since Git does not understand |
| 45 | those concepts. |
| 46 | |
| 47 | As with the "import" command, the --git option is not required |
| 48 | since the git-fast-export file format is currently the only VCS interchange |
| 49 | format that Fossil will generate. However, |
| 50 | future versions of Fossil might add the ability to generate other |
| 51 | VCS interchange formats, and so for compatibility, the use of the --git |
| 52 | option recommended. |
| 53 | |
| 54 | <h2>Bidirectional Synchronization</h2> |
| 55 | Fossil also has the ability to synchronize with a Git repository via repeated |
| 56 | imports and/or exports. To do this, it uses marks files to store a record of |
| 57 | artifacts which are known by both Git and Fossil to exist at a given point in |
| 58 | time. |
| 59 | |
| 60 | To illustrate, consider the example of a remote Fossil repository that a |
| 61 | user wants to import into a local Git repository. First, the user would clone |
| 62 | the remote repository and import it into a new Git repository: |
| 63 | |
| 64 | <blockquote><pre> |
| 65 | fossil clone /path/to/remote/repo.fossil repo.fossil |
| 66 | mkdir repo |
| 67 | cd repo |
| 68 | fossil open ../repo.fossil |
| 69 | mkdir ../repo.git |
| 70 | cd ../repo.git |
| 71 | git init . |
| 72 | fossil export --git --export-marks ../repo/fossil.marks \ |
| 73 | ../repo.fossil | git fast-import \ |
| 74 | --export-marks=../repo/git.marks |
| 75 | </pre></blockquote> |
| 76 | |
| 77 | Once the import has completed, the user would need to <tt>git checkout |
| 78 | trunk</tt>. At any point after this, new changes can be imported from the |
| 79 | remote Fossil repository: |
| 80 | |
| 81 | <blockquote><pre> |
| 82 | cd ../repo |
| 83 | fossil pull |
| 84 | cd ../repo.git |
| 85 | fossil export --git --import-marks ../repo/fossil.marks \ |
| 86 | --export-marks ../repo/fossil.marks \ |
| 87 | ../repo.fossil | git fast-import \ |
| 88 | --import-marks=../repo/git.marks \ |
| 89 | --export-marks=../repo/git.marks |
| 90 | </pre></blockquote> |
| 91 | |
| 92 | Changes in the Git repository can be exported to the Fossil repository and then |
| 93 | pushed to the remote: |
| 94 | |
| 95 | <blockquote><pre> |
| 96 | git fast-export --import-marks=../repo/git.marks \ |
| 97 | --export-marks=../repo/git.marks --all | fossil import --git \ |
| 98 | --incremental --import-marks ../repo/fossil.marks \ |
| 99 | --export-marks ../repo/fossil.marks ../repo.fossil |
| 100 | cd ../repo |
| 101 | fossil push |
| 102 | </pre></blockquote> |
| 103 |
+13
-13
| --- www/makefile.wiki | ||
| +++ www/makefile.wiki | ||
| @@ -2,24 +2,24 @@ | ||
| 2 | 2 | |
| 3 | 3 | <h1>1.0 Introduction</h1> |
| 4 | 4 | |
| 5 | 5 | The build process for Fossil is tricky in that the source code |
| 6 | 6 | needs to be processed by three different preprocessor programs |
| 7 | -before it is compiled. Most users will download a | |
| 7 | +before it is compiled. Most users will download a | |
| 8 | 8 | [http://www.fossil-scm.org/download.html | precompiled binary] |
| 9 | 9 | so this is of no consequence to them, and even those who |
| 10 | -want to compile the code themselves can use one of the | |
| 11 | -[./build.wiki | existing makefiles]. | |
| 10 | +want to compile the code themselves can use one of the | |
| 11 | +[./build.wiki | existing makefiles]. | |
| 12 | 12 | So must people do not need to be concerned with the |
| 13 | 13 | build complexities of Fossil. But hard-core developers who desire |
| 14 | 14 | a deep understanding of how Fossil is put together can benefit |
| 15 | 15 | from reviewing this article. |
| 16 | 16 | |
| 17 | 17 | <a name="srctour"></a> |
| 18 | 18 | <h1>2.0 Source Code Tour</h1> |
| 19 | 19 | |
| 20 | -The source code for Fossil is found in the | |
| 20 | +The source code for Fossil is found in the | |
| 21 | 21 | [/dir?ci=trunk&name=src | src/] subdirectory of the |
| 22 | 22 | source tree. The src/ subdirectory contains all code, including |
| 23 | 23 | the code for the separate preprocessor programs. |
| 24 | 24 | |
| 25 | 25 | Each preprocessor program is a separate C program implemented in |
| @@ -50,11 +50,11 @@ | ||
| 50 | 50 | The TH1 script engine is implemented using files: |
| 51 | 51 | |
| 52 | 52 | 7. th.c |
| 53 | 53 | 8. th.h |
| 54 | 54 | |
| 55 | -These two files are imports like the SQLite source files, | |
| 55 | +These two files are imports like the SQLite source files, | |
| 56 | 56 | and so are not preprocessed. |
| 57 | 57 | |
| 58 | 58 | The VERSION.h header file is generated from other information sources |
| 59 | 59 | using a small program called: |
| 60 | 60 | |
| @@ -86,11 +86,11 @@ | ||
| 86 | 86 | |
| 87 | 87 | 13. main.mk |
| 88 | 88 | |
| 89 | 89 | The main.mk makefile is invoked from the Makefile in the top-level |
| 90 | 90 | directory. The main.mk is generated by makemake.tcl and should not |
| 91 | -be hand edited. Other makefiles generated by makemake.tcl are in | |
| 91 | +be hand edited. Other makefiles generated by makemake.tcl are in | |
| 92 | 92 | other subdirectories (currently all in the win/ subdirectory). |
| 93 | 93 | |
| 94 | 94 | All the other files in the src/ subdirectory (79 files at the time of |
| 95 | 95 | this writing) are C source code files that are subject to the |
| 96 | 96 | preprocessing steps described below. In the sequel, we will call these |
| @@ -109,11 +109,11 @@ | ||
| 109 | 109 | (The "manifest" and "manifest.uuid" files are automatically generated and |
| 110 | 110 | updated by Fossil itself. See the [/help/setting | fossil set manifest] |
| 111 | 111 | command for additional information.) |
| 112 | 112 | |
| 113 | 113 | The VERSION.h header file is generated by |
| 114 | -a C program: src/mkversion.c. | |
| 114 | +a C program: src/mkversion.c. | |
| 115 | 115 | To run the VERSION.h generator, first compile the src/mkversion.c |
| 116 | 116 | source file into a command-line program (named "mkversion.exe") |
| 117 | 117 | then run: |
| 118 | 118 | |
| 119 | 119 | <blockquote><pre> |
| @@ -126,11 +126,11 @@ | ||
| 126 | 126 | in the root of the source tree are the three arguments and |
| 127 | 127 | the generated VERSION.h file appears on standard output. |
| 128 | 128 | |
| 129 | 129 | The builtin_data.h header file is generated by a C program: src/mkbuiltin.c. |
| 130 | 130 | The builtin_data.h file contains C-langauge byte-array definitions for |
| 131 | -the content of resource files used by Fossil. To generate the | |
| 131 | +the content of resource files used by Fossil. To generate the | |
| 132 | 132 | builtin_data.h file, first compile the mkbuiltin.c program, then run: |
| 133 | 133 | |
| 134 | 134 | <blockquote><pre> |
| 135 | 135 | mkbuiltin.exe diff.tcl <i>OtherFiles...</i> >builtin_data.h |
| 136 | 136 | </pre></blockquote> |
| @@ -163,11 +163,11 @@ | ||
| 163 | 163 | Note that "src.c" in the above is a stand-in for the (79) regular source |
| 164 | 164 | files of Fossil - all source files except for the exceptions described in |
| 165 | 165 | section 2.0 above. |
| 166 | 166 | |
| 167 | 167 | The output of the mkindex program is a header file that is #include-ed by |
| 168 | -the main.c source file during the final compilation step. | |
| 168 | +the main.c source file during the final compilation step. | |
| 169 | 169 | |
| 170 | 170 | <h2>4.2 The translate preprocessor</h2> |
| 171 | 171 | |
| 172 | 172 | The translate preprocessor looks for lines of source code that begin |
| 173 | 173 | with "@" and converts those lines into string constants or (depending on |
| @@ -181,11 +181,11 @@ | ||
| 181 | 181 | </pre></blockquote> |
| 182 | 182 | |
| 183 | 183 | In this case, the "src.c" file represents any single source file from the |
| 184 | 184 | set of ordinary source files as described in section 2.0 above. Note that |
| 185 | 185 | each source file is translated separately. By convention, the names of |
| 186 | -the translated source files are the names of the input sources with a | |
| 186 | +the translated source files are the names of the input sources with a | |
| 187 | 187 | single "_" character at the end. But a new makefile can use any naming |
| 188 | 188 | convention it wants - the "_" is not critical to the build process. |
| 189 | 189 | |
| 190 | 190 | After being translated, the output files (the "src_.c" files) should be |
| 191 | 191 | used for all subsequent preprocessing and compilation steps. |
| @@ -209,16 +209,16 @@ | ||
| 209 | 209 | <blockquote><pre> |
| 210 | 210 | makeheaders src_.c:src.h sqlite3.h th.h VERSION.h |
| 211 | 211 | </pre></blockquote> |
| 212 | 212 | |
| 213 | 213 | In the example above the "src_.c" and "src.h" names represent all of the |
| 214 | -(79) ordinary C source files, each as a separate argument. | |
| 214 | +(79) ordinary C source files, each as a separate argument. | |
| 215 | 215 | |
| 216 | 216 | <h1>5.0 Compilation</h1> |
| 217 | 217 | |
| 218 | 218 | After all generated files have been created and all ordinary source files |
| 219 | -have been preprocessed, the generated and preprocessed files can be | |
| 219 | +have been preprocessed, the generated and preprocessed files can be | |
| 220 | 220 | combined into a single executable using a C compiler. This can be done |
| 221 | 221 | all at once, or each preprocessed source file can be compiled into a |
| 222 | 222 | separate object code file and the resulting object code files linked |
| 223 | 223 | together in a final step. |
| 224 | 224 | |
| @@ -247,11 +247,11 @@ | ||
| 247 | 247 | * -Dmain=sqlite3_main |
| 248 | 248 | * -DSQLITE_OMIT_LOAD_EXTENSION=1 |
| 249 | 249 | |
| 250 | 250 | The "main()" routine in the shell must be changed into sqlite3_main() |
| 251 | 251 | to prevent it from colliding with the real main() in Fossil, and to give |
| 252 | -Fossil an entry point to jump to when the | |
| 252 | +Fossil an entry point to jump to when the | |
| 253 | 253 | [/help/sqlite3 | fossil sql] command is invoked. |
| 254 | 254 | |
| 255 | 255 | All the other source code files can be compiled without any special |
| 256 | 256 | options. |
| 257 | 257 | |
| 258 | 258 |
| --- www/makefile.wiki | |
| +++ www/makefile.wiki | |
| @@ -2,24 +2,24 @@ | |
| 2 | |
| 3 | <h1>1.0 Introduction</h1> |
| 4 | |
| 5 | The build process for Fossil is tricky in that the source code |
| 6 | needs to be processed by three different preprocessor programs |
| 7 | before it is compiled. Most users will download a |
| 8 | [http://www.fossil-scm.org/download.html | precompiled binary] |
| 9 | so this is of no consequence to them, and even those who |
| 10 | want to compile the code themselves can use one of the |
| 11 | [./build.wiki | existing makefiles]. |
| 12 | So must people do not need to be concerned with the |
| 13 | build complexities of Fossil. But hard-core developers who desire |
| 14 | a deep understanding of how Fossil is put together can benefit |
| 15 | from reviewing this article. |
| 16 | |
| 17 | <a name="srctour"></a> |
| 18 | <h1>2.0 Source Code Tour</h1> |
| 19 | |
| 20 | The source code for Fossil is found in the |
| 21 | [/dir?ci=trunk&name=src | src/] subdirectory of the |
| 22 | source tree. The src/ subdirectory contains all code, including |
| 23 | the code for the separate preprocessor programs. |
| 24 | |
| 25 | Each preprocessor program is a separate C program implemented in |
| @@ -50,11 +50,11 @@ | |
| 50 | The TH1 script engine is implemented using files: |
| 51 | |
| 52 | 7. th.c |
| 53 | 8. th.h |
| 54 | |
| 55 | These two files are imports like the SQLite source files, |
| 56 | and so are not preprocessed. |
| 57 | |
| 58 | The VERSION.h header file is generated from other information sources |
| 59 | using a small program called: |
| 60 | |
| @@ -86,11 +86,11 @@ | |
| 86 | |
| 87 | 13. main.mk |
| 88 | |
| 89 | The main.mk makefile is invoked from the Makefile in the top-level |
| 90 | directory. The main.mk is generated by makemake.tcl and should not |
| 91 | be hand edited. Other makefiles generated by makemake.tcl are in |
| 92 | other subdirectories (currently all in the win/ subdirectory). |
| 93 | |
| 94 | All the other files in the src/ subdirectory (79 files at the time of |
| 95 | this writing) are C source code files that are subject to the |
| 96 | preprocessing steps described below. In the sequel, we will call these |
| @@ -109,11 +109,11 @@ | |
| 109 | (The "manifest" and "manifest.uuid" files are automatically generated and |
| 110 | updated by Fossil itself. See the [/help/setting | fossil set manifest] |
| 111 | command for additional information.) |
| 112 | |
| 113 | The VERSION.h header file is generated by |
| 114 | a C program: src/mkversion.c. |
| 115 | To run the VERSION.h generator, first compile the src/mkversion.c |
| 116 | source file into a command-line program (named "mkversion.exe") |
| 117 | then run: |
| 118 | |
| 119 | <blockquote><pre> |
| @@ -126,11 +126,11 @@ | |
| 126 | in the root of the source tree are the three arguments and |
| 127 | the generated VERSION.h file appears on standard output. |
| 128 | |
| 129 | The builtin_data.h header file is generated by a C program: src/mkbuiltin.c. |
| 130 | The builtin_data.h file contains C-langauge byte-array definitions for |
| 131 | the content of resource files used by Fossil. To generate the |
| 132 | builtin_data.h file, first compile the mkbuiltin.c program, then run: |
| 133 | |
| 134 | <blockquote><pre> |
| 135 | mkbuiltin.exe diff.tcl <i>OtherFiles...</i> >builtin_data.h |
| 136 | </pre></blockquote> |
| @@ -163,11 +163,11 @@ | |
| 163 | Note that "src.c" in the above is a stand-in for the (79) regular source |
| 164 | files of Fossil - all source files except for the exceptions described in |
| 165 | section 2.0 above. |
| 166 | |
| 167 | The output of the mkindex program is a header file that is #include-ed by |
| 168 | the main.c source file during the final compilation step. |
| 169 | |
| 170 | <h2>4.2 The translate preprocessor</h2> |
| 171 | |
| 172 | The translate preprocessor looks for lines of source code that begin |
| 173 | with "@" and converts those lines into string constants or (depending on |
| @@ -181,11 +181,11 @@ | |
| 181 | </pre></blockquote> |
| 182 | |
| 183 | In this case, the "src.c" file represents any single source file from the |
| 184 | set of ordinary source files as described in section 2.0 above. Note that |
| 185 | each source file is translated separately. By convention, the names of |
| 186 | the translated source files are the names of the input sources with a |
| 187 | single "_" character at the end. But a new makefile can use any naming |
| 188 | convention it wants - the "_" is not critical to the build process. |
| 189 | |
| 190 | After being translated, the output files (the "src_.c" files) should be |
| 191 | used for all subsequent preprocessing and compilation steps. |
| @@ -209,16 +209,16 @@ | |
| 209 | <blockquote><pre> |
| 210 | makeheaders src_.c:src.h sqlite3.h th.h VERSION.h |
| 211 | </pre></blockquote> |
| 212 | |
| 213 | In the example above the "src_.c" and "src.h" names represent all of the |
| 214 | (79) ordinary C source files, each as a separate argument. |
| 215 | |
| 216 | <h1>5.0 Compilation</h1> |
| 217 | |
| 218 | After all generated files have been created and all ordinary source files |
| 219 | have been preprocessed, the generated and preprocessed files can be |
| 220 | combined into a single executable using a C compiler. This can be done |
| 221 | all at once, or each preprocessed source file can be compiled into a |
| 222 | separate object code file and the resulting object code files linked |
| 223 | together in a final step. |
| 224 | |
| @@ -247,11 +247,11 @@ | |
| 247 | * -Dmain=sqlite3_main |
| 248 | * -DSQLITE_OMIT_LOAD_EXTENSION=1 |
| 249 | |
| 250 | The "main()" routine in the shell must be changed into sqlite3_main() |
| 251 | to prevent it from colliding with the real main() in Fossil, and to give |
| 252 | Fossil an entry point to jump to when the |
| 253 | [/help/sqlite3 | fossil sql] command is invoked. |
| 254 | |
| 255 | All the other source code files can be compiled without any special |
| 256 | options. |
| 257 | |
| 258 |
| --- www/makefile.wiki | |
| +++ www/makefile.wiki | |
| @@ -2,24 +2,24 @@ | |
| 2 | |
| 3 | <h1>1.0 Introduction</h1> |
| 4 | |
| 5 | The build process for Fossil is tricky in that the source code |
| 6 | needs to be processed by three different preprocessor programs |
| 7 | before it is compiled. Most users will download a |
| 8 | [http://www.fossil-scm.org/download.html | precompiled binary] |
| 9 | so this is of no consequence to them, and even those who |
| 10 | want to compile the code themselves can use one of the |
| 11 | [./build.wiki | existing makefiles]. |
| 12 | So must people do not need to be concerned with the |
| 13 | build complexities of Fossil. But hard-core developers who desire |
| 14 | a deep understanding of how Fossil is put together can benefit |
| 15 | from reviewing this article. |
| 16 | |
| 17 | <a name="srctour"></a> |
| 18 | <h1>2.0 Source Code Tour</h1> |
| 19 | |
| 20 | The source code for Fossil is found in the |
| 21 | [/dir?ci=trunk&name=src | src/] subdirectory of the |
| 22 | source tree. The src/ subdirectory contains all code, including |
| 23 | the code for the separate preprocessor programs. |
| 24 | |
| 25 | Each preprocessor program is a separate C program implemented in |
| @@ -50,11 +50,11 @@ | |
| 50 | The TH1 script engine is implemented using files: |
| 51 | |
| 52 | 7. th.c |
| 53 | 8. th.h |
| 54 | |
| 55 | These two files are imports like the SQLite source files, |
| 56 | and so are not preprocessed. |
| 57 | |
| 58 | The VERSION.h header file is generated from other information sources |
| 59 | using a small program called: |
| 60 | |
| @@ -86,11 +86,11 @@ | |
| 86 | |
| 87 | 13. main.mk |
| 88 | |
| 89 | The main.mk makefile is invoked from the Makefile in the top-level |
| 90 | directory. The main.mk is generated by makemake.tcl and should not |
| 91 | be hand edited. Other makefiles generated by makemake.tcl are in |
| 92 | other subdirectories (currently all in the win/ subdirectory). |
| 93 | |
| 94 | All the other files in the src/ subdirectory (79 files at the time of |
| 95 | this writing) are C source code files that are subject to the |
| 96 | preprocessing steps described below. In the sequel, we will call these |
| @@ -109,11 +109,11 @@ | |
| 109 | (The "manifest" and "manifest.uuid" files are automatically generated and |
| 110 | updated by Fossil itself. See the [/help/setting | fossil set manifest] |
| 111 | command for additional information.) |
| 112 | |
| 113 | The VERSION.h header file is generated by |
| 114 | a C program: src/mkversion.c. |
| 115 | To run the VERSION.h generator, first compile the src/mkversion.c |
| 116 | source file into a command-line program (named "mkversion.exe") |
| 117 | then run: |
| 118 | |
| 119 | <blockquote><pre> |
| @@ -126,11 +126,11 @@ | |
| 126 | in the root of the source tree are the three arguments and |
| 127 | the generated VERSION.h file appears on standard output. |
| 128 | |
| 129 | The builtin_data.h header file is generated by a C program: src/mkbuiltin.c. |
| 130 | The builtin_data.h file contains C-langauge byte-array definitions for |
| 131 | the content of resource files used by Fossil. To generate the |
| 132 | builtin_data.h file, first compile the mkbuiltin.c program, then run: |
| 133 | |
| 134 | <blockquote><pre> |
| 135 | mkbuiltin.exe diff.tcl <i>OtherFiles...</i> >builtin_data.h |
| 136 | </pre></blockquote> |
| @@ -163,11 +163,11 @@ | |
| 163 | Note that "src.c" in the above is a stand-in for the (79) regular source |
| 164 | files of Fossil - all source files except for the exceptions described in |
| 165 | section 2.0 above. |
| 166 | |
| 167 | The output of the mkindex program is a header file that is #include-ed by |
| 168 | the main.c source file during the final compilation step. |
| 169 | |
| 170 | <h2>4.2 The translate preprocessor</h2> |
| 171 | |
| 172 | The translate preprocessor looks for lines of source code that begin |
| 173 | with "@" and converts those lines into string constants or (depending on |
| @@ -181,11 +181,11 @@ | |
| 181 | </pre></blockquote> |
| 182 | |
| 183 | In this case, the "src.c" file represents any single source file from the |
| 184 | set of ordinary source files as described in section 2.0 above. Note that |
| 185 | each source file is translated separately. By convention, the names of |
| 186 | the translated source files are the names of the input sources with a |
| 187 | single "_" character at the end. But a new makefile can use any naming |
| 188 | convention it wants - the "_" is not critical to the build process. |
| 189 | |
| 190 | After being translated, the output files (the "src_.c" files) should be |
| 191 | used for all subsequent preprocessing and compilation steps. |
| @@ -209,16 +209,16 @@ | |
| 209 | <blockquote><pre> |
| 210 | makeheaders src_.c:src.h sqlite3.h th.h VERSION.h |
| 211 | </pre></blockquote> |
| 212 | |
| 213 | In the example above the "src_.c" and "src.h" names represent all of the |
| 214 | (79) ordinary C source files, each as a separate argument. |
| 215 | |
| 216 | <h1>5.0 Compilation</h1> |
| 217 | |
| 218 | After all generated files have been created and all ordinary source files |
| 219 | have been preprocessed, the generated and preprocessed files can be |
| 220 | combined into a single executable using a C compiler. This can be done |
| 221 | all at once, or each preprocessed source file can be compiled into a |
| 222 | separate object code file and the resulting object code files linked |
| 223 | together in a final step. |
| 224 | |
| @@ -247,11 +247,11 @@ | |
| 247 | * -Dmain=sqlite3_main |
| 248 | * -DSQLITE_OMIT_LOAD_EXTENSION=1 |
| 249 | |
| 250 | The "main()" routine in the shell must be changed into sqlite3_main() |
| 251 | to prevent it from colliding with the real main() in Fossil, and to give |
| 252 | Fossil an entry point to jump to when the |
| 253 | [/help/sqlite3 | fossil sql] command is invoked. |
| 254 | |
| 255 | All the other source code files can be compiled without any special |
| 256 | options. |
| 257 | |
| 258 |
+48
-60
| --- www/mkdownload.tcl | ||
| +++ www/mkdownload.tcl | ||
| @@ -1,41 +1,17 @@ | ||
| 1 | 1 | #!/usr/bin/tclsh |
| 2 | 2 | # |
| 3 | -# Run this script to build the "download.html" page. Also generate | |
| 4 | -# the fossil_download_checksums.html page. | |
| 3 | +# Run this script to build and install the "download.html" page of | |
| 4 | +# unversioned comment. | |
| 5 | +# | |
| 6 | +# Also generate the fossil_download_checksums.html page. | |
| 5 | 7 | # |
| 6 | 8 | # |
| 7 | 9 | set out [open download.html w] |
| 8 | 10 | fconfigure $out -encoding utf-8 -translation lf |
| 9 | 11 | puts $out \ |
| 10 | -{<!DOCTYPE html> | |
| 11 | -<html> | |
| 12 | - <head> | |
| 13 | - <base href="https://www.fossil-scm.org/download.html" /> | |
| 14 | - <title>Fossil: Download</title> | |
| 15 | - <link rel="alternate" type="application/rss+xml" title="RSS Feed" | |
| 16 | - href="/fossil/timeline.rss" /> | |
| 17 | - <link rel="stylesheet" href="/fossil/style.css?default" type="text/css" | |
| 18 | - media="screen" /> | |
| 19 | - </head> | |
| 20 | - | |
| 21 | - <body> | |
| 22 | - <div class="header"> | |
| 23 | - <div class="title"><h1>Fossil</h1>Download</div> | |
| 24 | - </div> | |
| 25 | - <div class="mainmenu"> | |
| 26 | -<a href='/fossil/doc/trunk/www/index.wiki'>Home</a> | |
| 27 | -<a href='/fossil/timeline?y=ci'>Timeline</a> | |
| 28 | -<a href='/fossil/dir?ci=tip'>Code</a> | |
| 29 | -<a href='/fossil/doc/trunk/www/permutedindex.html'>Docs</a> | |
| 30 | -<a href='/fossil/brlist'>Branches</a> | |
| 31 | -<a href='/fossil/ticket'>Tickets</a> | |
| 32 | -<a href='/fossil/wiki'>Wiki</a> | |
| 33 | -<a href='/download.html' class='active'>Download</a> | |
| 34 | -</div> | |
| 35 | -<div class="content"> | |
| 36 | -<p> | |
| 12 | +{<div class='fossil-doc' data-title='Download Page'> | |
| 37 | 13 | |
| 38 | 14 | <center><font size=4>} |
| 39 | 15 | puts $out \ |
| 40 | 16 | "<b>To install Fossil →</b> download the stand-alone executable" |
| 41 | 17 | puts $out \ |
| @@ -45,46 +21,57 @@ | ||
| 45 | 21 | <a href="http://download.opensuse.org/repositories/home:/rmax:/fossil/"> |
| 46 | 22 | here.</a> |
| 47 | 23 | Cryptographic checksums for download files are |
| 48 | 24 | <a href="http://www.hwaci.com/fossil_download_checksums.html">here</a>. |
| 49 | 25 | </small></p> |
| 50 | -</center> | |
| 51 | - | |
| 52 | 26 | <table cellpadding="10"> |
| 53 | 27 | } |
| 54 | 28 | |
| 55 | -# Find all all unique timestamps. | |
| 29 | +# Find all unique timestamps. | |
| 56 | 30 | # |
| 57 | -foreach file [glob -nocomplain download/fossil-*.zip] { | |
| 58 | - if {[regexp -- {-(\d\.\d+).zip$} $file all version]} { | |
| 31 | +set in [open {|fossil uv list} rb] | |
| 32 | +while {[gets $in line]>0} { | |
| 33 | + set fn [lindex $line 5] | |
| 34 | + set filesize($fn) [lindex $line 3] | |
| 35 | + if {[regexp -- {-(\d\.\d+)\.(tar\.gz|zip)$} $fn all version]} { | |
| 36 | + set filehash($fn) [lindex $line 1] | |
| 59 | 37 | set avers($version) 1 |
| 60 | 38 | } |
| 61 | 39 | } |
| 40 | +close $in | |
| 41 | + | |
| 42 | +set vdate(1.36) 2016-10-24 | |
| 43 | +set vdate(1.35) 2016-06-14 | |
| 44 | +set vdate(1.34) 2016-11-02 | |
| 62 | 45 | |
| 63 | 46 | # Do all versions from newest to oldest |
| 64 | 47 | # |
| 65 | 48 | foreach vers [lsort -decr -real [array names avers]] { |
| 66 | - set hr "/fossil/timeline?c=version-$vers;y=ci" | |
| 49 | + # set hr "../timeline?c=version-$vers;y=ci" | |
| 50 | + set v2 v[string map {. _} $vers] | |
| 51 | + set hr "../doc/trunk/www/changes.wiki#$v2" | |
| 67 | 52 | puts $out "<tr><td colspan=6 align=left><hr>" |
| 68 | - puts $out "<center><b><a href=\"$hr\">Version $vers</a></b></center>" | |
| 53 | + puts $out "<center><b><a href=\"$hr\">Version $vers</a>" | |
| 54 | + if {[info exists vdate($vers)]} { | |
| 55 | + set hr2 "../timeline?c=version-$vers&y=ci" | |
| 56 | + puts $out " (<a href='$hr2'>$vdate($vers)</a>)" | |
| 57 | + } | |
| 58 | + puts $out "</b></center>" | |
| 69 | 59 | puts $out "</td></tr>" |
| 70 | 60 | puts $out "<tr>" |
| 71 | 61 | |
| 72 | 62 | foreach {prefix img desc} { |
| 73 | 63 | fossil-linux-x86 linux.gif {Linux 3.x x86} |
| 74 | - fossil-macosx-x86 mac.gif {Mac 10.x x86} | |
| 64 | + fossil-macosx mac.gif {Mac 10.x x86} | |
| 75 | 65 | fossil-openbsd-x86 openbsd.gif {OpenBSD 5.x x86} |
| 76 | 66 | fossil-w32 win32.gif {Windows} |
| 77 | 67 | fossil-src src.gif {Source Tarball} |
| 78 | 68 | } { |
| 79 | - set basename download/$prefix-$vers | |
| 80 | - set filename $basename.tar.gz | |
| 81 | - if {![file exists $basename.tar.gz]} { | |
| 82 | - set filename $basename.zip | |
| 83 | - } | |
| 84 | - if {[file exists $filename]} { | |
| 85 | - set size [file size $filename] | |
| 69 | + set glob download/$prefix*-$vers* | |
| 70 | + set filename [array names filesize $glob] | |
| 71 | + if {[info exists filesize($filename)]} { | |
| 72 | + set size [set filesize($filename)] | |
| 86 | 73 | set units bytes |
| 87 | 74 | if {$size>1024*1024} { |
| 88 | 75 | set size [format %.2f [expr {$size/(1024.0*1024.0)}]] |
| 89 | 76 | set units MiB |
| 90 | 77 | } elseif {$size>1024} { |
| @@ -97,26 +84,23 @@ | ||
| 97 | 84 | } else { |
| 98 | 85 | puts $out "<td> </td>" |
| 99 | 86 | } |
| 100 | 87 | } |
| 101 | 88 | puts $out "</tr>" |
| 102 | - if {[file exists download/releasenotes-$vers.html]} { | |
| 103 | - puts $out "<tr><td colspan=6 align=left>" | |
| 104 | - set rn [open download/releasenotes-$vers.html] | |
| 105 | - fconfigure $rn -encoding utf-8 | |
| 106 | - puts $out "[read $rn]" | |
| 107 | - close $rn | |
| 108 | - puts $out "</td></tr>" | |
| 109 | - } | |
| 89 | +# | |
| 90 | +# if {[info exists filesize(download/releasenotes-$vers.html)]} { | |
| 91 | +# puts $out "<tr><td colspan=6 align=left>" | |
| 92 | +# set rn [|open uv cat download/releasenotes-$vers.html] | |
| 93 | +# fconfigure $rn -encoding utf-8 | |
| 94 | +# puts $out "[read $rn]" | |
| 95 | +# close $rn | |
| 96 | +# puts $out "</td></tr>" | |
| 97 | +# } | |
| 110 | 98 | } |
| 111 | 99 | puts $out "<tr><td colspan=5><hr></td></tr>" |
| 112 | 100 | |
| 113 | -puts $out {</table></div> | |
| 114 | -</body> | |
| 115 | -</html> | |
| 116 | -} | |
| 117 | - | |
| 101 | +puts $out {</table></center></div>} | |
| 118 | 102 | close $out |
| 119 | 103 | |
| 120 | 104 | # Generate the checksum page |
| 121 | 105 | # |
| 122 | 106 | set out [open fossil_download_checksums.html w] |
| @@ -128,11 +112,15 @@ | ||
| 128 | 112 | <p>The following table shows the SHA1 checksums for the precompiled |
| 129 | 113 | binaries available on the |
| 130 | 114 | <a href="/download.html">Fossil website</a>.</p> |
| 131 | 115 | <pre>} |
| 132 | 116 | |
| 133 | -foreach file [lsort [glob -nocomplain download/fossil-*.zip]] { | |
| 134 | - set sha1sum [lindex [exec sha1sum $file] 0] | |
| 135 | - puts $out "$sha1sum [file tail $file]" | |
| 117 | +foreach {line} [split [exec fossil sql "SELECT hash, name FROM unversioned\ | |
| 118 | + WHERE name GLOB '*.tar.gz' OR\ | |
| 119 | + name GLOB '*.zip'"] \n] { | |
| 120 | + set x [split $line |] | |
| 121 | + set hash [lindex $x 0] | |
| 122 | + set nm [file tail [lindex $x 1]] | |
| 123 | + puts $out "$hash $nm" | |
| 136 | 124 | } |
| 137 | 125 | puts $out {</pre></body></html>} |
| 138 | 126 | close $out |
| 139 | 127 |
| --- www/mkdownload.tcl | |
| +++ www/mkdownload.tcl | |
| @@ -1,41 +1,17 @@ | |
| 1 | #!/usr/bin/tclsh |
| 2 | # |
| 3 | # Run this script to build the "download.html" page. Also generate |
| 4 | # the fossil_download_checksums.html page. |
| 5 | # |
| 6 | # |
| 7 | set out [open download.html w] |
| 8 | fconfigure $out -encoding utf-8 -translation lf |
| 9 | puts $out \ |
| 10 | {<!DOCTYPE html> |
| 11 | <html> |
| 12 | <head> |
| 13 | <base href="https://www.fossil-scm.org/download.html" /> |
| 14 | <title>Fossil: Download</title> |
| 15 | <link rel="alternate" type="application/rss+xml" title="RSS Feed" |
| 16 | href="/fossil/timeline.rss" /> |
| 17 | <link rel="stylesheet" href="/fossil/style.css?default" type="text/css" |
| 18 | media="screen" /> |
| 19 | </head> |
| 20 | |
| 21 | <body> |
| 22 | <div class="header"> |
| 23 | <div class="title"><h1>Fossil</h1>Download</div> |
| 24 | </div> |
| 25 | <div class="mainmenu"> |
| 26 | <a href='/fossil/doc/trunk/www/index.wiki'>Home</a> |
| 27 | <a href='/fossil/timeline?y=ci'>Timeline</a> |
| 28 | <a href='/fossil/dir?ci=tip'>Code</a> |
| 29 | <a href='/fossil/doc/trunk/www/permutedindex.html'>Docs</a> |
| 30 | <a href='/fossil/brlist'>Branches</a> |
| 31 | <a href='/fossil/ticket'>Tickets</a> |
| 32 | <a href='/fossil/wiki'>Wiki</a> |
| 33 | <a href='/download.html' class='active'>Download</a> |
| 34 | </div> |
| 35 | <div class="content"> |
| 36 | <p> |
| 37 | |
| 38 | <center><font size=4>} |
| 39 | puts $out \ |
| 40 | "<b>To install Fossil →</b> download the stand-alone executable" |
| 41 | puts $out \ |
| @@ -45,46 +21,57 @@ | |
| 45 | <a href="http://download.opensuse.org/repositories/home:/rmax:/fossil/"> |
| 46 | here.</a> |
| 47 | Cryptographic checksums for download files are |
| 48 | <a href="http://www.hwaci.com/fossil_download_checksums.html">here</a>. |
| 49 | </small></p> |
| 50 | </center> |
| 51 | |
| 52 | <table cellpadding="10"> |
| 53 | } |
| 54 | |
| 55 | # Find all all unique timestamps. |
| 56 | # |
| 57 | foreach file [glob -nocomplain download/fossil-*.zip] { |
| 58 | if {[regexp -- {-(\d\.\d+).zip$} $file all version]} { |
| 59 | set avers($version) 1 |
| 60 | } |
| 61 | } |
| 62 | |
| 63 | # Do all versions from newest to oldest |
| 64 | # |
| 65 | foreach vers [lsort -decr -real [array names avers]] { |
| 66 | set hr "/fossil/timeline?c=version-$vers;y=ci" |
| 67 | puts $out "<tr><td colspan=6 align=left><hr>" |
| 68 | puts $out "<center><b><a href=\"$hr\">Version $vers</a></b></center>" |
| 69 | puts $out "</td></tr>" |
| 70 | puts $out "<tr>" |
| 71 | |
| 72 | foreach {prefix img desc} { |
| 73 | fossil-linux-x86 linux.gif {Linux 3.x x86} |
| 74 | fossil-macosx-x86 mac.gif {Mac 10.x x86} |
| 75 | fossil-openbsd-x86 openbsd.gif {OpenBSD 5.x x86} |
| 76 | fossil-w32 win32.gif {Windows} |
| 77 | fossil-src src.gif {Source Tarball} |
| 78 | } { |
| 79 | set basename download/$prefix-$vers |
| 80 | set filename $basename.tar.gz |
| 81 | if {![file exists $basename.tar.gz]} { |
| 82 | set filename $basename.zip |
| 83 | } |
| 84 | if {[file exists $filename]} { |
| 85 | set size [file size $filename] |
| 86 | set units bytes |
| 87 | if {$size>1024*1024} { |
| 88 | set size [format %.2f [expr {$size/(1024.0*1024.0)}]] |
| 89 | set units MiB |
| 90 | } elseif {$size>1024} { |
| @@ -97,26 +84,23 @@ | |
| 97 | } else { |
| 98 | puts $out "<td> </td>" |
| 99 | } |
| 100 | } |
| 101 | puts $out "</tr>" |
| 102 | if {[file exists download/releasenotes-$vers.html]} { |
| 103 | puts $out "<tr><td colspan=6 align=left>" |
| 104 | set rn [open download/releasenotes-$vers.html] |
| 105 | fconfigure $rn -encoding utf-8 |
| 106 | puts $out "[read $rn]" |
| 107 | close $rn |
| 108 | puts $out "</td></tr>" |
| 109 | } |
| 110 | } |
| 111 | puts $out "<tr><td colspan=5><hr></td></tr>" |
| 112 | |
| 113 | puts $out {</table></div> |
| 114 | </body> |
| 115 | </html> |
| 116 | } |
| 117 | |
| 118 | close $out |
| 119 | |
| 120 | # Generate the checksum page |
| 121 | # |
| 122 | set out [open fossil_download_checksums.html w] |
| @@ -128,11 +112,15 @@ | |
| 128 | <p>The following table shows the SHA1 checksums for the precompiled |
| 129 | binaries available on the |
| 130 | <a href="/download.html">Fossil website</a>.</p> |
| 131 | <pre>} |
| 132 | |
| 133 | foreach file [lsort [glob -nocomplain download/fossil-*.zip]] { |
| 134 | set sha1sum [lindex [exec sha1sum $file] 0] |
| 135 | puts $out "$sha1sum [file tail $file]" |
| 136 | } |
| 137 | puts $out {</pre></body></html>} |
| 138 | close $out |
| 139 |
| --- www/mkdownload.tcl | |
| +++ www/mkdownload.tcl | |
| @@ -1,41 +1,17 @@ | |
| 1 | #!/usr/bin/tclsh |
| 2 | # |
| 3 | # Run this script to build and install the "download.html" page of |
| 4 | # unversioned comment. |
| 5 | # |
| 6 | # Also generate the fossil_download_checksums.html page. |
| 7 | # |
| 8 | # |
| 9 | set out [open download.html w] |
| 10 | fconfigure $out -encoding utf-8 -translation lf |
| 11 | puts $out \ |
| 12 | {<div class='fossil-doc' data-title='Download Page'> |
| 13 | |
| 14 | <center><font size=4>} |
| 15 | puts $out \ |
| 16 | "<b>To install Fossil →</b> download the stand-alone executable" |
| 17 | puts $out \ |
| @@ -45,46 +21,57 @@ | |
| 21 | <a href="http://download.opensuse.org/repositories/home:/rmax:/fossil/"> |
| 22 | here.</a> |
| 23 | Cryptographic checksums for download files are |
| 24 | <a href="http://www.hwaci.com/fossil_download_checksums.html">here</a>. |
| 25 | </small></p> |
| 26 | <table cellpadding="10"> |
| 27 | } |
| 28 | |
| 29 | # Find all unique timestamps. |
| 30 | # |
| 31 | set in [open {|fossil uv list} rb] |
| 32 | while {[gets $in line]>0} { |
| 33 | set fn [lindex $line 5] |
| 34 | set filesize($fn) [lindex $line 3] |
| 35 | if {[regexp -- {-(\d\.\d+)\.(tar\.gz|zip)$} $fn all version]} { |
| 36 | set filehash($fn) [lindex $line 1] |
| 37 | set avers($version) 1 |
| 38 | } |
| 39 | } |
| 40 | close $in |
| 41 | |
| 42 | set vdate(1.36) 2016-10-24 |
| 43 | set vdate(1.35) 2016-06-14 |
| 44 | set vdate(1.34) 2016-11-02 |
| 45 | |
| 46 | # Do all versions from newest to oldest |
| 47 | # |
| 48 | foreach vers [lsort -decr -real [array names avers]] { |
| 49 | # set hr "../timeline?c=version-$vers;y=ci" |
| 50 | set v2 v[string map {. _} $vers] |
| 51 | set hr "../doc/trunk/www/changes.wiki#$v2" |
| 52 | puts $out "<tr><td colspan=6 align=left><hr>" |
| 53 | puts $out "<center><b><a href=\"$hr\">Version $vers</a>" |
| 54 | if {[info exists vdate($vers)]} { |
| 55 | set hr2 "../timeline?c=version-$vers&y=ci" |
| 56 | puts $out " (<a href='$hr2'>$vdate($vers)</a>)" |
| 57 | } |
| 58 | puts $out "</b></center>" |
| 59 | puts $out "</td></tr>" |
| 60 | puts $out "<tr>" |
| 61 | |
| 62 | foreach {prefix img desc} { |
| 63 | fossil-linux-x86 linux.gif {Linux 3.x x86} |
| 64 | fossil-macosx mac.gif {Mac 10.x x86} |
| 65 | fossil-openbsd-x86 openbsd.gif {OpenBSD 5.x x86} |
| 66 | fossil-w32 win32.gif {Windows} |
| 67 | fossil-src src.gif {Source Tarball} |
| 68 | } { |
| 69 | set glob download/$prefix*-$vers* |
| 70 | set filename [array names filesize $glob] |
| 71 | if {[info exists filesize($filename)]} { |
| 72 | set size [set filesize($filename)] |
| 73 | set units bytes |
| 74 | if {$size>1024*1024} { |
| 75 | set size [format %.2f [expr {$size/(1024.0*1024.0)}]] |
| 76 | set units MiB |
| 77 | } elseif {$size>1024} { |
| @@ -97,26 +84,23 @@ | |
| 84 | } else { |
| 85 | puts $out "<td> </td>" |
| 86 | } |
| 87 | } |
| 88 | puts $out "</tr>" |
| 89 | # |
| 90 | # if {[info exists filesize(download/releasenotes-$vers.html)]} { |
| 91 | # puts $out "<tr><td colspan=6 align=left>" |
| 92 | # set rn [|open uv cat download/releasenotes-$vers.html] |
| 93 | # fconfigure $rn -encoding utf-8 |
| 94 | # puts $out "[read $rn]" |
| 95 | # close $rn |
| 96 | # puts $out "</td></tr>" |
| 97 | # } |
| 98 | } |
| 99 | puts $out "<tr><td colspan=5><hr></td></tr>" |
| 100 | |
| 101 | puts $out {</table></center></div>} |
| 102 | close $out |
| 103 | |
| 104 | # Generate the checksum page |
| 105 | # |
| 106 | set out [open fossil_download_checksums.html w] |
| @@ -128,11 +112,15 @@ | |
| 112 | <p>The following table shows the SHA1 checksums for the precompiled |
| 113 | binaries available on the |
| 114 | <a href="/download.html">Fossil website</a>.</p> |
| 115 | <pre>} |
| 116 | |
| 117 | foreach {line} [split [exec fossil sql "SELECT hash, name FROM unversioned\ |
| 118 | WHERE name GLOB '*.tar.gz' OR\ |
| 119 | name GLOB '*.zip'"] \n] { |
| 120 | set x [split $line |] |
| 121 | set hash [lindex $x 0] |
| 122 | set nm [file tail [lindex $x 1]] |
| 123 | puts $out "$hash $nm" |
| 124 | } |
| 125 | puts $out {</pre></body></html>} |
| 126 | close $out |
| 127 |
+1
-1
| --- www/newrepo.wiki | ||
| +++ www/newrepo.wiki | ||
| @@ -53,11 +53,11 @@ | ||
| 53 | 53 | |
| 54 | 54 | <verbatim> |
| 55 | 55 | stephan@ludo:~/fossil$ mkdir demo |
| 56 | 56 | stephan@ludo:~/fossil$ cd demo |
| 57 | 57 | stephan@ludo:~/fossil/demo$ fossil open ../demo.fossil |
| 58 | -stephan@ludo:~/fossil/demo$ | |
| 58 | +stephan@ludo:~/fossil/demo$ | |
| 59 | 59 | </verbatim> |
| 60 | 60 | |
| 61 | 61 | That creates a file called <tt>_FOSSIL_</tt> in the current |
| 62 | 62 | directory, and this file contains all kinds of fossil-related |
| 63 | 63 | information about your local repository. You can ignore it |
| 64 | 64 |
| --- www/newrepo.wiki | |
| +++ www/newrepo.wiki | |
| @@ -53,11 +53,11 @@ | |
| 53 | |
| 54 | <verbatim> |
| 55 | stephan@ludo:~/fossil$ mkdir demo |
| 56 | stephan@ludo:~/fossil$ cd demo |
| 57 | stephan@ludo:~/fossil/demo$ fossil open ../demo.fossil |
| 58 | stephan@ludo:~/fossil/demo$ |
| 59 | </verbatim> |
| 60 | |
| 61 | That creates a file called <tt>_FOSSIL_</tt> in the current |
| 62 | directory, and this file contains all kinds of fossil-related |
| 63 | information about your local repository. You can ignore it |
| 64 |
| --- www/newrepo.wiki | |
| +++ www/newrepo.wiki | |
| @@ -53,11 +53,11 @@ | |
| 53 | |
| 54 | <verbatim> |
| 55 | stephan@ludo:~/fossil$ mkdir demo |
| 56 | stephan@ludo:~/fossil$ cd demo |
| 57 | stephan@ludo:~/fossil/demo$ fossil open ../demo.fossil |
| 58 | stephan@ludo:~/fossil/demo$ |
| 59 | </verbatim> |
| 60 | |
| 61 | That creates a file called <tt>_FOSSIL_</tt> in the current |
| 62 | directory, and this file contains all kinds of fossil-related |
| 63 | information about your local repository. You can ignore it |
| 64 |
+5
-5
| --- www/pop.wiki | ||
| +++ www/pop.wiki | ||
| @@ -4,18 +4,18 @@ | ||
| 4 | 4 | This page attempts to define the foundational principals upon |
| 5 | 5 | which Fossil is built. |
| 6 | 6 | </p> |
| 7 | 7 | |
| 8 | 8 | <ul> |
| 9 | -<li><p>A project consists of source files, wiki pages, and | |
| 9 | +<li><p>A project consists of source files, wiki pages, and | |
| 10 | 10 | trouble tickets, and control files (collectively "artifacts"). |
| 11 | 11 | All historical copies of all artifacts |
| 12 | 12 | are saved. The project maintains an audit |
| 13 | 13 | trail.</p></li> |
| 14 | 14 | |
| 15 | 15 | <li><p>A project resides in one or more repositories. Each |
| 16 | -repository is administered and operates independently | |
| 16 | +repository is administered and operates independently | |
| 17 | 17 | of the others.</p></li> |
| 18 | 18 | |
| 19 | 19 | <li><p>Each repository has both global and local state. The |
| 20 | 20 | global state is common to all repositories (or at least |
| 21 | 21 | has the potential to be shared in common when the |
| @@ -24,28 +24,28 @@ | ||
| 24 | 24 | The global state represents the content of the project. |
| 25 | 25 | The local state identifies the authorized users and |
| 26 | 26 | access policies for a particular repository.</p></li> |
| 27 | 27 | |
| 28 | 28 | <li><p>The global state of a repository is an unordered |
| 29 | -collection of artifacts. Each artifact is named by | |
| 29 | +collection of artifacts. Each artifact is named by | |
| 30 | 30 | its SHA1 hash encoded in lowercase hexadecimal. |
| 31 | 31 | In many contexts, the name can be |
| 32 | 32 | abbreviated to a unique prefix. A five- or six-character |
| 33 | 33 | prefix usually suffices to uniquely identify a file.</p></li> |
| 34 | 34 | |
| 35 | 35 | <li><p>Because artifacts are named by their SHA1 hash, all artifacts |
| 36 | -are immutable. Any change to the content of an artifact also | |
| 36 | +are immutable. Any change to the content of an artifact also | |
| 37 | 37 | changes the hash that forms the artifacts name, thus |
| 38 | 38 | creating a new artifact. Both the old original version of the |
| 39 | 39 | artifact and the new change are preserved under different names.</p></li> |
| 40 | 40 | |
| 41 | 41 | <li><p>It is theoretically possible for two artifacts with different |
| 42 | 42 | content to share the same hash. But finding two such |
| 43 | 43 | artifacts is so incredibly difficult and unlikely that we |
| 44 | 44 | consider it to be an impossibility.</p></li> |
| 45 | 45 | |
| 46 | -<li><p>The signature of an artifact is the SHA1 hash of the | |
| 46 | +<li><p>The signature of an artifact is the SHA1 hash of the | |
| 47 | 47 | artifact itself, exactly as it would appear in a disk file. No prefix |
| 48 | 48 | or meta-information about the artifact is added before computing |
| 49 | 49 | the hash. So you can |
| 50 | 50 | always find the SHA1 signature of a file by using the |
| 51 | 51 | "sha1sum" command-line utility.</p></li> |
| 52 | 52 |
| --- www/pop.wiki | |
| +++ www/pop.wiki | |
| @@ -4,18 +4,18 @@ | |
| 4 | This page attempts to define the foundational principals upon |
| 5 | which Fossil is built. |
| 6 | </p> |
| 7 | |
| 8 | <ul> |
| 9 | <li><p>A project consists of source files, wiki pages, and |
| 10 | trouble tickets, and control files (collectively "artifacts"). |
| 11 | All historical copies of all artifacts |
| 12 | are saved. The project maintains an audit |
| 13 | trail.</p></li> |
| 14 | |
| 15 | <li><p>A project resides in one or more repositories. Each |
| 16 | repository is administered and operates independently |
| 17 | of the others.</p></li> |
| 18 | |
| 19 | <li><p>Each repository has both global and local state. The |
| 20 | global state is common to all repositories (or at least |
| 21 | has the potential to be shared in common when the |
| @@ -24,28 +24,28 @@ | |
| 24 | The global state represents the content of the project. |
| 25 | The local state identifies the authorized users and |
| 26 | access policies for a particular repository.</p></li> |
| 27 | |
| 28 | <li><p>The global state of a repository is an unordered |
| 29 | collection of artifacts. Each artifact is named by |
| 30 | its SHA1 hash encoded in lowercase hexadecimal. |
| 31 | In many contexts, the name can be |
| 32 | abbreviated to a unique prefix. A five- or six-character |
| 33 | prefix usually suffices to uniquely identify a file.</p></li> |
| 34 | |
| 35 | <li><p>Because artifacts are named by their SHA1 hash, all artifacts |
| 36 | are immutable. Any change to the content of an artifact also |
| 37 | changes the hash that forms the artifacts name, thus |
| 38 | creating a new artifact. Both the old original version of the |
| 39 | artifact and the new change are preserved under different names.</p></li> |
| 40 | |
| 41 | <li><p>It is theoretically possible for two artifacts with different |
| 42 | content to share the same hash. But finding two such |
| 43 | artifacts is so incredibly difficult and unlikely that we |
| 44 | consider it to be an impossibility.</p></li> |
| 45 | |
| 46 | <li><p>The signature of an artifact is the SHA1 hash of the |
| 47 | artifact itself, exactly as it would appear in a disk file. No prefix |
| 48 | or meta-information about the artifact is added before computing |
| 49 | the hash. So you can |
| 50 | always find the SHA1 signature of a file by using the |
| 51 | "sha1sum" command-line utility.</p></li> |
| 52 |
| --- www/pop.wiki | |
| +++ www/pop.wiki | |
| @@ -4,18 +4,18 @@ | |
| 4 | This page attempts to define the foundational principals upon |
| 5 | which Fossil is built. |
| 6 | </p> |
| 7 | |
| 8 | <ul> |
| 9 | <li><p>A project consists of source files, wiki pages, and |
| 10 | trouble tickets, and control files (collectively "artifacts"). |
| 11 | All historical copies of all artifacts |
| 12 | are saved. The project maintains an audit |
| 13 | trail.</p></li> |
| 14 | |
| 15 | <li><p>A project resides in one or more repositories. Each |
| 16 | repository is administered and operates independently |
| 17 | of the others.</p></li> |
| 18 | |
| 19 | <li><p>Each repository has both global and local state. The |
| 20 | global state is common to all repositories (or at least |
| 21 | has the potential to be shared in common when the |
| @@ -24,28 +24,28 @@ | |
| 24 | The global state represents the content of the project. |
| 25 | The local state identifies the authorized users and |
| 26 | access policies for a particular repository.</p></li> |
| 27 | |
| 28 | <li><p>The global state of a repository is an unordered |
| 29 | collection of artifacts. Each artifact is named by |
| 30 | its SHA1 hash encoded in lowercase hexadecimal. |
| 31 | In many contexts, the name can be |
| 32 | abbreviated to a unique prefix. A five- or six-character |
| 33 | prefix usually suffices to uniquely identify a file.</p></li> |
| 34 | |
| 35 | <li><p>Because artifacts are named by their SHA1 hash, all artifacts |
| 36 | are immutable. Any change to the content of an artifact also |
| 37 | changes the hash that forms the artifacts name, thus |
| 38 | creating a new artifact. Both the old original version of the |
| 39 | artifact and the new change are preserved under different names.</p></li> |
| 40 | |
| 41 | <li><p>It is theoretically possible for two artifacts with different |
| 42 | content to share the same hash. But finding two such |
| 43 | artifacts is so incredibly difficult and unlikely that we |
| 44 | consider it to be an impossibility.</p></li> |
| 45 | |
| 46 | <li><p>The signature of an artifact is the SHA1 hash of the |
| 47 | artifact itself, exactly as it would appear in a disk file. No prefix |
| 48 | or meta-information about the artifact is added before computing |
| 49 | the hash. So you can |
| 50 | always find the SHA1 signature of a file by using the |
| 51 | "sha1sum" command-line utility.</p></li> |
| 52 |
+3
-3
| --- www/private.wiki | ||
| +++ www/private.wiki | ||
| @@ -41,11 +41,11 @@ | ||
| 41 | 41 | <h2>Syncing Private Branches</h2> |
| 42 | 42 | |
| 43 | 43 | A private branch normally stays on the one repository where it was |
| 44 | 44 | originally created. But sometimes you want to share private branches |
| 45 | 45 | with another repository. For example, you might be building a cross-platform |
| 46 | -application and have separate repositories on your Windows laptop, | |
| 46 | +application and have separate repositories on your Windows laptop, | |
| 47 | 47 | your Linux desktop, and your iMac. You can transfer private branches |
| 48 | 48 | between these machines by using the --private option on the "sync", |
| 49 | 49 | "push", "pull", and "clone" commands. For example, if you are running |
| 50 | 50 | "fossil server" on your Linux box and you want to clone that repository |
| 51 | 51 | to your Mac, including all private branches, use: |
| @@ -67,11 +67,11 @@ | ||
| 67 | 67 | only enable "x" for local repositories when you need to share private |
| 68 | 68 | branches. |
| 69 | 69 | |
| 70 | 70 | Private branch sync only works if you use the --private command-line option. |
| 71 | 71 | Private branches are never synced via the auto-sync mechanism. Once |
| 72 | -again, this restriction is designed to make it hard to accidently | |
| 72 | +again, this restriction is designed to make it hard to accidently | |
| 73 | 73 | push private branches beyond their intended audience. |
| 74 | 74 | |
| 75 | 75 | <h2>Purging Private Branches</h2> |
| 76 | 76 | |
| 77 | 77 | You can remove all private branches from a repository using this command: |
| @@ -85,10 +85,10 @@ | ||
| 85 | 85 | removed, they cannot be retrieved (unless you have synced them to another |
| 86 | 86 | repository.) So be careful with the command. |
| 87 | 87 | |
| 88 | 88 | <h2>Additional Notes</h2> |
| 89 | 89 | |
| 90 | -All of the features above apply to <u>all</u> private branches in a | |
| 90 | +All of the features above apply to <u>all</u> private branches in a | |
| 91 | 91 | single repository at once. There is no mechanism in Fossil (currently) |
| 92 | 92 | that allows you to push, pull, clone, sync, or scrub and individual |
| 93 | 93 | private branch within a repository that contains multiple private |
| 94 | 94 | branches. |
| 95 | 95 |
| --- www/private.wiki | |
| +++ www/private.wiki | |
| @@ -41,11 +41,11 @@ | |
| 41 | <h2>Syncing Private Branches</h2> |
| 42 | |
| 43 | A private branch normally stays on the one repository where it was |
| 44 | originally created. But sometimes you want to share private branches |
| 45 | with another repository. For example, you might be building a cross-platform |
| 46 | application and have separate repositories on your Windows laptop, |
| 47 | your Linux desktop, and your iMac. You can transfer private branches |
| 48 | between these machines by using the --private option on the "sync", |
| 49 | "push", "pull", and "clone" commands. For example, if you are running |
| 50 | "fossil server" on your Linux box and you want to clone that repository |
| 51 | to your Mac, including all private branches, use: |
| @@ -67,11 +67,11 @@ | |
| 67 | only enable "x" for local repositories when you need to share private |
| 68 | branches. |
| 69 | |
| 70 | Private branch sync only works if you use the --private command-line option. |
| 71 | Private branches are never synced via the auto-sync mechanism. Once |
| 72 | again, this restriction is designed to make it hard to accidently |
| 73 | push private branches beyond their intended audience. |
| 74 | |
| 75 | <h2>Purging Private Branches</h2> |
| 76 | |
| 77 | You can remove all private branches from a repository using this command: |
| @@ -85,10 +85,10 @@ | |
| 85 | removed, they cannot be retrieved (unless you have synced them to another |
| 86 | repository.) So be careful with the command. |
| 87 | |
| 88 | <h2>Additional Notes</h2> |
| 89 | |
| 90 | All of the features above apply to <u>all</u> private branches in a |
| 91 | single repository at once. There is no mechanism in Fossil (currently) |
| 92 | that allows you to push, pull, clone, sync, or scrub and individual |
| 93 | private branch within a repository that contains multiple private |
| 94 | branches. |
| 95 |
| --- www/private.wiki | |
| +++ www/private.wiki | |
| @@ -41,11 +41,11 @@ | |
| 41 | <h2>Syncing Private Branches</h2> |
| 42 | |
| 43 | A private branch normally stays on the one repository where it was |
| 44 | originally created. But sometimes you want to share private branches |
| 45 | with another repository. For example, you might be building a cross-platform |
| 46 | application and have separate repositories on your Windows laptop, |
| 47 | your Linux desktop, and your iMac. You can transfer private branches |
| 48 | between these machines by using the --private option on the "sync", |
| 49 | "push", "pull", and "clone" commands. For example, if you are running |
| 50 | "fossil server" on your Linux box and you want to clone that repository |
| 51 | to your Mac, including all private branches, use: |
| @@ -67,11 +67,11 @@ | |
| 67 | only enable "x" for local repositories when you need to share private |
| 68 | branches. |
| 69 | |
| 70 | Private branch sync only works if you use the --private command-line option. |
| 71 | Private branches are never synced via the auto-sync mechanism. Once |
| 72 | again, this restriction is designed to make it hard to accidently |
| 73 | push private branches beyond their intended audience. |
| 74 | |
| 75 | <h2>Purging Private Branches</h2> |
| 76 | |
| 77 | You can remove all private branches from a repository using this command: |
| @@ -85,10 +85,10 @@ | |
| 85 | removed, they cannot be retrieved (unless you have synced them to another |
| 86 | repository.) So be careful with the command. |
| 87 | |
| 88 | <h2>Additional Notes</h2> |
| 89 | |
| 90 | All of the features above apply to <u>all</u> private branches in a |
| 91 | single repository at once. There is no mechanism in Fossil (currently) |
| 92 | that allows you to push, pull, clone, sync, or scrub and individual |
| 93 | private branch within a repository that contains multiple private |
| 94 | branches. |
| 95 |
+10
-10
| --- www/qandc.wiki | ||
| +++ www/qandc.wiki | ||
| @@ -22,11 +22,11 @@ | ||
| 22 | 22 | <li> Integrated <a href="wikitheory.wiki">wiki</a>. </li> |
| 23 | 23 | <li> Integrated <a href="bugtheory.wiki">bug tracking</a> </li> |
| 24 | 24 | <li> Immutable artifacts </li> |
| 25 | 25 | <li> Self-contained, stand-alone executable that can be run in |
| 26 | 26 | a <a href="http://en.wikipedia.org/wiki/Chroot">chroot jail</a> </li> |
| 27 | - <li> Simple, well-defined, | |
| 27 | + <li> Simple, well-defined, | |
| 28 | 28 | <a href="fileformat.wiki">enduring file format</a> </li> |
| 29 | 29 | <li> Integrated <a href="webui.wiki">web interface</a> </li> |
| 30 | 30 | </ol> |
| 31 | 31 | </blockquote> |
| 32 | 32 | |
| @@ -36,11 +36,11 @@ | ||
| 36 | 36 | <ol> |
| 37 | 37 | <li> Fossil is distributed. You can view and/or edit tickets, wiki, and |
| 38 | 38 | code while off network, then sync your changes later. With Trac, you |
| 39 | 39 | can only view and edit tickets and wiki while you are connected to |
| 40 | 40 | the server. </li> |
| 41 | - <li> Fossil is lightweight and fully self-contained. It is very easy | |
| 41 | + <li> Fossil is lightweight and fully self-contained. It is very easy | |
| 42 | 42 | to setup on a low-resource machine. Fossil does not require an |
| 43 | 43 | administrator.</li> |
| 44 | 44 | <li> Fossil integrates code versioning into the same repository with |
| 45 | 45 | wiki and tickets. There is nothing extra to add or install. |
| 46 | 46 | Fossil is an all-in-one turnkey solution. </li> |
| @@ -48,25 +48,25 @@ | ||
| 48 | 48 | </blockquote> |
| 49 | 49 | |
| 50 | 50 | <b>Love the concept here. Anyone using this for real work yet?</b> |
| 51 | 51 | |
| 52 | 52 | <blockquote> |
| 53 | -Fossil is <a href="http://www.fossil-scm.org/">self-hosting</a>. | |
| 53 | +Fossil is <a href="http://www.fossil-scm.org/">self-hosting</a>. | |
| 54 | 54 | In fact, this page was probably delivered |
| 55 | 55 | to your web-browser via a working fossil instance. The same virtual |
| 56 | 56 | machine that hosts http://www.fossil-scm.org/ |
| 57 | 57 | (a <a href="http://www.linode.com/">Linode 720</a>) |
| 58 | 58 | also hosts 24 other fossil repositories for various small projects. |
| 59 | -The documentation files for | |
| 59 | +The documentation files for | |
| 60 | 60 | <a href="http://www.sqlite.org/">SQLite</a> are hosted in a |
| 61 | 61 | fossil repository <a href="http://www.sqlite.org/docsrc/">here</a>, |
| 62 | 62 | for example. |
| 63 | 63 | Other projects are also adopting fossil. But fossil does not yet have |
| 64 | 64 | the massive user base of git or mercurial. |
| 65 | 65 | </blockquote> |
| 66 | 66 | |
| 67 | -<b>Fossil looks like the bug tracker that would be in your | |
| 67 | +<b>Fossil looks like the bug tracker that would be in your | |
| 68 | 68 | Linksys Router's administration screen.</b> |
| 69 | 69 | |
| 70 | 70 | <blockquote> |
| 71 | 71 | <p>I take a pragmatic approach to software: form follows function. |
| 72 | 72 | To me, it is more important to have a reliable, fast, efficient, |
| @@ -83,11 +83,11 @@ | ||
| 83 | 83 | keeps the bug-tracking database in a versioned file. That file can |
| 84 | 84 | then be pushed and pulled along with the rest repository.</b> |
| 85 | 85 | |
| 86 | 86 | <blockquote> |
| 87 | 87 | <p>Fossil already <u>does</u> push and pull bugs along with the files |
| 88 | -in your repository. | |
| 88 | +in your repository. | |
| 89 | 89 | But fossil does <u>not</u> track bugs as files in the source tree. |
| 90 | 90 | That approach to bug tracking was rejected for three reasons:</p> |
| 91 | 91 | |
| 92 | 92 | <ol> |
| 93 | 93 | <li> Check-ins in fossil are immutable. So if |
| @@ -108,11 +108,11 @@ | ||
| 108 | 108 | |
| 109 | 109 | <p>These points are reiterated in the opening paragraphs of |
| 110 | 110 | the <a href="bugtheory.wiki">Bug-Tracking In Fossil</a> document.</p> |
| 111 | 111 | </blockquote> |
| 112 | 112 | |
| 113 | -<b>Fossil is already the name of a plan9 versioned | |
| 113 | +<b>Fossil is already the name of a plan9 versioned | |
| 114 | 114 | append-only filesystem.</b> |
| 115 | 115 | |
| 116 | 116 | <blockquote> |
| 117 | 117 | I did not know that. Perhaps they selected the name for the same reason that |
| 118 | 118 | I did: because a repository with immutable artifacts preserves |
| @@ -137,22 +137,22 @@ | ||
| 137 | 137 | Subversion or Bazaar.</b> |
| 138 | 138 | |
| 139 | 139 | <blockquote> |
| 140 | 140 | <p>I have no doubt that Trac has many features that fossil lacks. But that |
| 141 | 141 | is not the point. Fossil has several key features that Trac lacks and that |
| 142 | -I need: most notably the fact that | |
| 142 | +I need: most notably the fact that | |
| 143 | 143 | fossil supports disconnected operation.</p> |
| 144 | 144 | |
| 145 | 145 | <p>As for bloat: Fossil is a single self-contained executable. |
| 146 | -You do not need any other packages | |
| 146 | +You do not need any other packages | |
| 147 | 147 | (diff, patch, merge, cvs, svn, rcs, git, python, perl, tcl, apache, |
| 148 | 148 | sqlite, and so forth) |
| 149 | 149 | in order to run fossil. Fossil runs just fine in a chroot jail all |
| 150 | 150 | by itself. And the self-contained fossil |
| 151 | 151 | executable is much less than 1MB in size. (Update 2015-01-12: Fossil has |
| 152 | -grown in the years since the previous sentence was written but is still | |
| 152 | +grown in the years since the previous sentence was written but is still | |
| 153 | 153 | much less than 2MB according to "size" when compiled using -Os on x64 Linux.) |
| 154 | 154 | Fossil is the very opposite of bloat.</p> |
| 155 | 155 | </blockquote> |
| 156 | 156 | |
| 157 | 157 | |
| 158 | 158 | </nowiki> |
| 159 | 159 |
| --- www/qandc.wiki | |
| +++ www/qandc.wiki | |
| @@ -22,11 +22,11 @@ | |
| 22 | <li> Integrated <a href="wikitheory.wiki">wiki</a>. </li> |
| 23 | <li> Integrated <a href="bugtheory.wiki">bug tracking</a> </li> |
| 24 | <li> Immutable artifacts </li> |
| 25 | <li> Self-contained, stand-alone executable that can be run in |
| 26 | a <a href="http://en.wikipedia.org/wiki/Chroot">chroot jail</a> </li> |
| 27 | <li> Simple, well-defined, |
| 28 | <a href="fileformat.wiki">enduring file format</a> </li> |
| 29 | <li> Integrated <a href="webui.wiki">web interface</a> </li> |
| 30 | </ol> |
| 31 | </blockquote> |
| 32 | |
| @@ -36,11 +36,11 @@ | |
| 36 | <ol> |
| 37 | <li> Fossil is distributed. You can view and/or edit tickets, wiki, and |
| 38 | code while off network, then sync your changes later. With Trac, you |
| 39 | can only view and edit tickets and wiki while you are connected to |
| 40 | the server. </li> |
| 41 | <li> Fossil is lightweight and fully self-contained. It is very easy |
| 42 | to setup on a low-resource machine. Fossil does not require an |
| 43 | administrator.</li> |
| 44 | <li> Fossil integrates code versioning into the same repository with |
| 45 | wiki and tickets. There is nothing extra to add or install. |
| 46 | Fossil is an all-in-one turnkey solution. </li> |
| @@ -48,25 +48,25 @@ | |
| 48 | </blockquote> |
| 49 | |
| 50 | <b>Love the concept here. Anyone using this for real work yet?</b> |
| 51 | |
| 52 | <blockquote> |
| 53 | Fossil is <a href="http://www.fossil-scm.org/">self-hosting</a>. |
| 54 | In fact, this page was probably delivered |
| 55 | to your web-browser via a working fossil instance. The same virtual |
| 56 | machine that hosts http://www.fossil-scm.org/ |
| 57 | (a <a href="http://www.linode.com/">Linode 720</a>) |
| 58 | also hosts 24 other fossil repositories for various small projects. |
| 59 | The documentation files for |
| 60 | <a href="http://www.sqlite.org/">SQLite</a> are hosted in a |
| 61 | fossil repository <a href="http://www.sqlite.org/docsrc/">here</a>, |
| 62 | for example. |
| 63 | Other projects are also adopting fossil. But fossil does not yet have |
| 64 | the massive user base of git or mercurial. |
| 65 | </blockquote> |
| 66 | |
| 67 | <b>Fossil looks like the bug tracker that would be in your |
| 68 | Linksys Router's administration screen.</b> |
| 69 | |
| 70 | <blockquote> |
| 71 | <p>I take a pragmatic approach to software: form follows function. |
| 72 | To me, it is more important to have a reliable, fast, efficient, |
| @@ -83,11 +83,11 @@ | |
| 83 | keeps the bug-tracking database in a versioned file. That file can |
| 84 | then be pushed and pulled along with the rest repository.</b> |
| 85 | |
| 86 | <blockquote> |
| 87 | <p>Fossil already <u>does</u> push and pull bugs along with the files |
| 88 | in your repository. |
| 89 | But fossil does <u>not</u> track bugs as files in the source tree. |
| 90 | That approach to bug tracking was rejected for three reasons:</p> |
| 91 | |
| 92 | <ol> |
| 93 | <li> Check-ins in fossil are immutable. So if |
| @@ -108,11 +108,11 @@ | |
| 108 | |
| 109 | <p>These points are reiterated in the opening paragraphs of |
| 110 | the <a href="bugtheory.wiki">Bug-Tracking In Fossil</a> document.</p> |
| 111 | </blockquote> |
| 112 | |
| 113 | <b>Fossil is already the name of a plan9 versioned |
| 114 | append-only filesystem.</b> |
| 115 | |
| 116 | <blockquote> |
| 117 | I did not know that. Perhaps they selected the name for the same reason that |
| 118 | I did: because a repository with immutable artifacts preserves |
| @@ -137,22 +137,22 @@ | |
| 137 | Subversion or Bazaar.</b> |
| 138 | |
| 139 | <blockquote> |
| 140 | <p>I have no doubt that Trac has many features that fossil lacks. But that |
| 141 | is not the point. Fossil has several key features that Trac lacks and that |
| 142 | I need: most notably the fact that |
| 143 | fossil supports disconnected operation.</p> |
| 144 | |
| 145 | <p>As for bloat: Fossil is a single self-contained executable. |
| 146 | You do not need any other packages |
| 147 | (diff, patch, merge, cvs, svn, rcs, git, python, perl, tcl, apache, |
| 148 | sqlite, and so forth) |
| 149 | in order to run fossil. Fossil runs just fine in a chroot jail all |
| 150 | by itself. And the self-contained fossil |
| 151 | executable is much less than 1MB in size. (Update 2015-01-12: Fossil has |
| 152 | grown in the years since the previous sentence was written but is still |
| 153 | much less than 2MB according to "size" when compiled using -Os on x64 Linux.) |
| 154 | Fossil is the very opposite of bloat.</p> |
| 155 | </blockquote> |
| 156 | |
| 157 | |
| 158 | </nowiki> |
| 159 |
| --- www/qandc.wiki | |
| +++ www/qandc.wiki | |
| @@ -22,11 +22,11 @@ | |
| 22 | <li> Integrated <a href="wikitheory.wiki">wiki</a>. </li> |
| 23 | <li> Integrated <a href="bugtheory.wiki">bug tracking</a> </li> |
| 24 | <li> Immutable artifacts </li> |
| 25 | <li> Self-contained, stand-alone executable that can be run in |
| 26 | a <a href="http://en.wikipedia.org/wiki/Chroot">chroot jail</a> </li> |
| 27 | <li> Simple, well-defined, |
| 28 | <a href="fileformat.wiki">enduring file format</a> </li> |
| 29 | <li> Integrated <a href="webui.wiki">web interface</a> </li> |
| 30 | </ol> |
| 31 | </blockquote> |
| 32 | |
| @@ -36,11 +36,11 @@ | |
| 36 | <ol> |
| 37 | <li> Fossil is distributed. You can view and/or edit tickets, wiki, and |
| 38 | code while off network, then sync your changes later. With Trac, you |
| 39 | can only view and edit tickets and wiki while you are connected to |
| 40 | the server. </li> |
| 41 | <li> Fossil is lightweight and fully self-contained. It is very easy |
| 42 | to setup on a low-resource machine. Fossil does not require an |
| 43 | administrator.</li> |
| 44 | <li> Fossil integrates code versioning into the same repository with |
| 45 | wiki and tickets. There is nothing extra to add or install. |
| 46 | Fossil is an all-in-one turnkey solution. </li> |
| @@ -48,25 +48,25 @@ | |
| 48 | </blockquote> |
| 49 | |
| 50 | <b>Love the concept here. Anyone using this for real work yet?</b> |
| 51 | |
| 52 | <blockquote> |
| 53 | Fossil is <a href="http://www.fossil-scm.org/">self-hosting</a>. |
| 54 | In fact, this page was probably delivered |
| 55 | to your web-browser via a working fossil instance. The same virtual |
| 56 | machine that hosts http://www.fossil-scm.org/ |
| 57 | (a <a href="http://www.linode.com/">Linode 720</a>) |
| 58 | also hosts 24 other fossil repositories for various small projects. |
| 59 | The documentation files for |
| 60 | <a href="http://www.sqlite.org/">SQLite</a> are hosted in a |
| 61 | fossil repository <a href="http://www.sqlite.org/docsrc/">here</a>, |
| 62 | for example. |
| 63 | Other projects are also adopting fossil. But fossil does not yet have |
| 64 | the massive user base of git or mercurial. |
| 65 | </blockquote> |
| 66 | |
| 67 | <b>Fossil looks like the bug tracker that would be in your |
| 68 | Linksys Router's administration screen.</b> |
| 69 | |
| 70 | <blockquote> |
| 71 | <p>I take a pragmatic approach to software: form follows function. |
| 72 | To me, it is more important to have a reliable, fast, efficient, |
| @@ -83,11 +83,11 @@ | |
| 83 | keeps the bug-tracking database in a versioned file. That file can |
| 84 | then be pushed and pulled along with the rest repository.</b> |
| 85 | |
| 86 | <blockquote> |
| 87 | <p>Fossil already <u>does</u> push and pull bugs along with the files |
| 88 | in your repository. |
| 89 | But fossil does <u>not</u> track bugs as files in the source tree. |
| 90 | That approach to bug tracking was rejected for three reasons:</p> |
| 91 | |
| 92 | <ol> |
| 93 | <li> Check-ins in fossil are immutable. So if |
| @@ -108,11 +108,11 @@ | |
| 108 | |
| 109 | <p>These points are reiterated in the opening paragraphs of |
| 110 | the <a href="bugtheory.wiki">Bug-Tracking In Fossil</a> document.</p> |
| 111 | </blockquote> |
| 112 | |
| 113 | <b>Fossil is already the name of a plan9 versioned |
| 114 | append-only filesystem.</b> |
| 115 | |
| 116 | <blockquote> |
| 117 | I did not know that. Perhaps they selected the name for the same reason that |
| 118 | I did: because a repository with immutable artifacts preserves |
| @@ -137,22 +137,22 @@ | |
| 137 | Subversion or Bazaar.</b> |
| 138 | |
| 139 | <blockquote> |
| 140 | <p>I have no doubt that Trac has many features that fossil lacks. But that |
| 141 | is not the point. Fossil has several key features that Trac lacks and that |
| 142 | I need: most notably the fact that |
| 143 | fossil supports disconnected operation.</p> |
| 144 | |
| 145 | <p>As for bloat: Fossil is a single self-contained executable. |
| 146 | You do not need any other packages |
| 147 | (diff, patch, merge, cvs, svn, rcs, git, python, perl, tcl, apache, |
| 148 | sqlite, and so forth) |
| 149 | in order to run fossil. Fossil runs just fine in a chroot jail all |
| 150 | by itself. And the self-contained fossil |
| 151 | executable is much less than 1MB in size. (Update 2015-01-12: Fossil has |
| 152 | grown in the years since the previous sentence was written but is still |
| 153 | much less than 2MB according to "size" when compiled using -Os on x64 Linux.) |
| 154 | Fossil is the very opposite of bloat.</p> |
| 155 | </blockquote> |
| 156 | |
| 157 | |
| 158 | </nowiki> |
| 159 |
+26
-26
| --- www/quickstart.wiki | ||
| +++ www/quickstart.wiki | ||
| @@ -5,16 +5,16 @@ | ||
| 5 | 5 | and painlessly.</p> |
| 6 | 6 | |
| 7 | 7 | <h2>Installing</h2> |
| 8 | 8 | |
| 9 | 9 | <p>Fossil is a single self-contained C program. You need to |
| 10 | - either download a | |
| 10 | + either download a | |
| 11 | 11 | <a href="http://www.fossil-scm.org/download.html">precompiled binary</a> |
| 12 | 12 | or <a href="build.wiki">compile it yourself</a> from sources. |
| 13 | 13 | Install fossil by putting the fossil binary |
| 14 | 14 | someplace on your $PATH.</p> |
| 15 | - | |
| 15 | + | |
| 16 | 16 | <a name="fslclone"></a> |
| 17 | 17 | <h2>General Work Flow</h2> |
| 18 | 18 | |
| 19 | 19 | <p>Fossil works with repository files (a database with the project's |
| 20 | 20 | complete history) and with checked-out local trees (the working directory |
| @@ -34,11 +34,11 @@ | ||
| 34 | 34 | |
| 35 | 35 | <h2>Starting A New Project</h2> |
| 36 | 36 | |
| 37 | 37 | <p>To start a new project with fossil, create a new empty repository |
| 38 | 38 | this way: ([/help/init | more info]) </p> |
| 39 | - | |
| 39 | + | |
| 40 | 40 | <blockquote> |
| 41 | 41 | <b>fossil init </b><i> repository-filename</i> |
| 42 | 42 | </blockquote> |
| 43 | 43 | |
| 44 | 44 | <h2>Cloning An Existing Repository</h2> |
| @@ -46,36 +46,36 @@ | ||
| 46 | 46 | <p>Most fossil operations interact with a repository that is on the |
| 47 | 47 | local disk drive, not on a remote system. Hence, before accessing |
| 48 | 48 | a remote repository it is necessary to make a local copy of that |
| 49 | 49 | repository. Making a local copy of a remote repository is called |
| 50 | 50 | "cloning".</p> |
| 51 | - | |
| 51 | + | |
| 52 | 52 | <p>Clone a remote repository as follows: ([/help/clone | more info])</p> |
| 53 | - | |
| 53 | + | |
| 54 | 54 | <blockquote> |
| 55 | 55 | <b>fossil clone</b> <i>URL repository-filename</i> |
| 56 | 56 | </blockquote> |
| 57 | - | |
| 57 | + | |
| 58 | 58 | <p>The <i>URL</i> specifies the fossil repository |
| 59 | 59 | you want to clone. The <i>repository-filename</i> is the new local |
| 60 | 60 | filename into which the cloned repository will be written. For |
| 61 | 61 | example: |
| 62 | - | |
| 62 | + | |
| 63 | 63 | <blockquote> |
| 64 | 64 | <b>fossil clone http://www.fossil-scm.org/ myclone.fossil</b> |
| 65 | 65 | </blockquote> |
| 66 | 66 | |
| 67 | - <p>If the remote repository requires a login, include a | |
| 67 | + <p>If the remote repository requires a login, include a | |
| 68 | 68 | userid in the URL like this: |
| 69 | 69 | |
| 70 | 70 | <blockquote> |
| 71 | 71 | <b>fossil clone http://</b><i>userid</i><b>@www.fossil-scm.org/ myclone.fossil</b> |
| 72 | 72 | </blockquote> |
| 73 | - | |
| 73 | + | |
| 74 | 74 | |
| 75 | 75 | <p>You will be prompted separately for the password. |
| 76 | - Use "%HH" escapes for special characters in the userid. | |
| 76 | + Use "%HH" escapes for special characters in the userid. | |
| 77 | 77 | Examples: "%40" in place of "@" and "%2F" in place of "/". |
| 78 | 78 | |
| 79 | 79 | <p>If you are behind a restrictive firewall, you might need |
| 80 | 80 | to <a href="#proxy">specify an HTTP proxy</a>.</p> |
| 81 | 81 | |
| @@ -85,31 +85,31 @@ | ||
| 85 | 85 | information above and beyond the versioned files, including some |
| 86 | 86 | sensitive information such as password hashes and email addresses. If you |
| 87 | 87 | want to share Fossil repositories directly, consider running the |
| 88 | 88 | [/help/scrub|fossil scrub] command to remove sensitive information |
| 89 | 89 | before transmitting the file. |
| 90 | - | |
| 90 | + | |
| 91 | 91 | <h2>Importing From Another Version Control System</h2> |
| 92 | 92 | |
| 93 | 93 | <p>Rather than start a new project, or clone an existing Fossil project, |
| 94 | - you might prefer to | |
| 94 | + you might prefer to | |
| 95 | 95 | <a href="./inout.wiki">import an existing Git project</a> |
| 96 | 96 | into Fossil using the [/help/import | fossil import] command. |
| 97 | 97 | |
| 98 | 98 | <h2>Checking Out A Local Tree</h2> |
| 99 | 99 | |
| 100 | 100 | <p>To work on a project in fossil, you need to check out a local |
| 101 | 101 | copy of the source tree. Create the directory you want to be |
| 102 | 102 | the root of your tree and cd into that directory. Then |
| 103 | 103 | do this: ([/help/open | more info])</p> |
| 104 | - | |
| 104 | + | |
| 105 | 105 | <blockquote> |
| 106 | 106 | <b>fossil open </b><i> repository-filename</i> |
| 107 | 107 | </blockquote> |
| 108 | - | |
| 108 | + | |
| 109 | 109 | <p>This leaves you with the newest version of the tree |
| 110 | - checked out. | |
| 110 | + checked out. | |
| 111 | 111 | From anywhere underneath the root of your local tree, you |
| 112 | 112 | can type commands like the following to find out the status of |
| 113 | 113 | your local tree:</p> |
| 114 | 114 | |
| 115 | 115 | <blockquote> |
| @@ -122,11 +122,11 @@ | ||
| 122 | 122 | <b>[/help/branch | fossil branch]</b><br> |
| 123 | 123 | </blockquote> |
| 124 | 124 | |
| 125 | 125 | <p>Note that Fossil allows you to make multiple check-outs in |
| 126 | 126 | separate directories from the same repository. This enables you, |
| 127 | - for example, to do builds from multiple branches or versions at | |
| 127 | + for example, to do builds from multiple branches or versions at | |
| 128 | 128 | the same time without having to generate extra clones.</p> |
| 129 | 129 | |
| 130 | 130 | <p>To switch a checkout between different versions and branches, |
| 131 | 131 | use:</p> |
| 132 | 132 | |
| @@ -140,17 +140,17 @@ | ||
| 140 | 140 | version, whereas [/help/checkout | checkout] does not |
| 141 | 141 | automatically sync and does a "hard" switch, overwriting local |
| 142 | 142 | changes if told to do so.</p> |
| 143 | 143 | |
| 144 | 144 | <h2>Configuring Your Local Repository</h2> |
| 145 | - | |
| 145 | + | |
| 146 | 146 | <p>When you create a new repository, either by cloning an existing |
| 147 | 147 | project or create a new project of your own, you usually want to do some |
| 148 | 148 | local configuration. This is easily accomplished using the web-server |
| 149 | 149 | that is built into fossil. Start the fossil webserver like this: |
| 150 | 150 | ([/help/ui | more info])</p> |
| 151 | - | |
| 151 | + | |
| 152 | 152 | <blockquote> |
| 153 | 153 | <b>fossil ui </b><i> repository-filename</i> |
| 154 | 154 | </blockquote> |
| 155 | 155 | |
| 156 | 156 | <p>You can omit the <i>repository-filename</i> from the command above |
| @@ -163,15 +163,15 @@ | ||
| 163 | 163 | where to find your web browser using a command like this:</p> |
| 164 | 164 | |
| 165 | 165 | <blockquote> |
| 166 | 166 | <b>fossil setting web-browser </b><i> path-to-web-browser</i> |
| 167 | 167 | </blockquote> |
| 168 | - | |
| 168 | + | |
| 169 | 169 | <p>By default, fossil does not require a login for HTTP connections |
| 170 | 170 | coming in from the IP loopback address 127.0.0.1. You can, and perhaps |
| 171 | 171 | should, change this after you create a few users.</p> |
| 172 | - | |
| 172 | + | |
| 173 | 173 | <p>When you are finished configuring, just press Control-C or use |
| 174 | 174 | the <b>kill</b> command to shut down the mini-server.</p> |
| 175 | 175 | |
| 176 | 176 | <h2>Making Changes</h2> |
| 177 | 177 | |
| @@ -194,18 +194,18 @@ | ||
| 194 | 194 | <p>You will be prompted for check-in comments using whatever editor |
| 195 | 195 | is specified by your VISUAL or EDITOR environment variable.</p> |
| 196 | 196 | |
| 197 | 197 | In the default configuration, the [/help/commit|commit] |
| 198 | 198 | command will also automatically [/help/push|push] your changes, but that |
| 199 | - feature can be disabled. (More information about | |
| 199 | + feature can be disabled. (More information about | |
| 200 | 200 | [./concepts.wiki#workflow|autosync] and how to disable it.) |
| 201 | - Remember that your coworkers can not see your changes until you | |
| 201 | + Remember that your coworkers can not see your changes until you | |
| 202 | 202 | commit and push them.</p> |
| 203 | 203 | |
| 204 | 204 | <h2>Sharing Changes</h2> |
| 205 | 205 | |
| 206 | - <p>When [./concepts.wiki#workflow|autosync] is turned off, | |
| 206 | + <p>When [./concepts.wiki#workflow|autosync] is turned off, | |
| 207 | 207 | the changes you [/help/commit | commit] are only |
| 208 | 208 | on your local repository. |
| 209 | 209 | To share those changes with other repositories, do:</p> |
| 210 | 210 | |
| 211 | 211 | <blockquote> |
| @@ -241,11 +241,11 @@ | ||
| 241 | 241 | the <i>VERSION</i>, then fossil moves you to the |
| 242 | 242 | latest version of the branch your are currently on.</p> |
| 243 | 243 | |
| 244 | 244 | <p>The default behavior is for [./concepts.wiki#workflow|autosync] to |
| 245 | 245 | be turned on. That means that a [/help/pull|pull] automatically occurs |
| 246 | - when you run [/help/update|update] and a [/help/push|push] happens | |
| 246 | + when you run [/help/update|update] and a [/help/push|push] happens | |
| 247 | 247 | automatically after you [/help/commit|commit]. So in normal practice, |
| 248 | 248 | the push, pull, and sync commands are rarely used. But it is important |
| 249 | 249 | to know about them, all the same.</p> |
| 250 | 250 | |
| 251 | 251 | <blockquote> |
| @@ -342,11 +342,11 @@ | ||
| 342 | 342 | <li>[./server.wiki#cgi|CGI] |
| 343 | 343 | <li>[./server.wiki#scgi|SCGI] |
| 344 | 344 | </ul> |
| 345 | 345 | |
| 346 | 346 | <p>The [./selfhost.wiki | self-hosting fossil repositories] use |
| 347 | - CGI. | |
| 347 | + CGI. | |
| 348 | 348 | |
| 349 | 349 | <a name="proxy"></a> |
| 350 | 350 | <h2>HTTP Proxies</h2> |
| 351 | 351 | |
| 352 | 352 | <p>If you are behind a restrictive firewall that requires you to use |
| @@ -382,11 +382,11 @@ | ||
| 382 | 382 | <p>Or unset the environment variable. The fossil setting for the |
| 383 | 383 | HTTP proxy takes precedence over the environment variable and the |
| 384 | 384 | command-line option overrides both. If you have an persistent |
| 385 | 385 | proxy setting that you want to override for a one-time sync, that |
| 386 | 386 | is easily done on the command-line. For example, to sync with |
| 387 | - a co-workers repository on your LAN, you might type:</p> | |
| 387 | + a co-workers repository on your LAN, you might type:</p> | |
| 388 | 388 | |
| 389 | 389 | <blockquote> |
| 390 | 390 | <b>fossil sync http://192.168.1.36:8080/ --proxy off</b> |
| 391 | 391 | </blockquote> |
| 392 | 392 | |
| 393 | 393 |
| --- www/quickstart.wiki | |
| +++ www/quickstart.wiki | |
| @@ -5,16 +5,16 @@ | |
| 5 | and painlessly.</p> |
| 6 | |
| 7 | <h2>Installing</h2> |
| 8 | |
| 9 | <p>Fossil is a single self-contained C program. You need to |
| 10 | either download a |
| 11 | <a href="http://www.fossil-scm.org/download.html">precompiled binary</a> |
| 12 | or <a href="build.wiki">compile it yourself</a> from sources. |
| 13 | Install fossil by putting the fossil binary |
| 14 | someplace on your $PATH.</p> |
| 15 | |
| 16 | <a name="fslclone"></a> |
| 17 | <h2>General Work Flow</h2> |
| 18 | |
| 19 | <p>Fossil works with repository files (a database with the project's |
| 20 | complete history) and with checked-out local trees (the working directory |
| @@ -34,11 +34,11 @@ | |
| 34 | |
| 35 | <h2>Starting A New Project</h2> |
| 36 | |
| 37 | <p>To start a new project with fossil, create a new empty repository |
| 38 | this way: ([/help/init | more info]) </p> |
| 39 | |
| 40 | <blockquote> |
| 41 | <b>fossil init </b><i> repository-filename</i> |
| 42 | </blockquote> |
| 43 | |
| 44 | <h2>Cloning An Existing Repository</h2> |
| @@ -46,36 +46,36 @@ | |
| 46 | <p>Most fossil operations interact with a repository that is on the |
| 47 | local disk drive, not on a remote system. Hence, before accessing |
| 48 | a remote repository it is necessary to make a local copy of that |
| 49 | repository. Making a local copy of a remote repository is called |
| 50 | "cloning".</p> |
| 51 | |
| 52 | <p>Clone a remote repository as follows: ([/help/clone | more info])</p> |
| 53 | |
| 54 | <blockquote> |
| 55 | <b>fossil clone</b> <i>URL repository-filename</i> |
| 56 | </blockquote> |
| 57 | |
| 58 | <p>The <i>URL</i> specifies the fossil repository |
| 59 | you want to clone. The <i>repository-filename</i> is the new local |
| 60 | filename into which the cloned repository will be written. For |
| 61 | example: |
| 62 | |
| 63 | <blockquote> |
| 64 | <b>fossil clone http://www.fossil-scm.org/ myclone.fossil</b> |
| 65 | </blockquote> |
| 66 | |
| 67 | <p>If the remote repository requires a login, include a |
| 68 | userid in the URL like this: |
| 69 | |
| 70 | <blockquote> |
| 71 | <b>fossil clone http://</b><i>userid</i><b>@www.fossil-scm.org/ myclone.fossil</b> |
| 72 | </blockquote> |
| 73 | |
| 74 | |
| 75 | <p>You will be prompted separately for the password. |
| 76 | Use "%HH" escapes for special characters in the userid. |
| 77 | Examples: "%40" in place of "@" and "%2F" in place of "/". |
| 78 | |
| 79 | <p>If you are behind a restrictive firewall, you might need |
| 80 | to <a href="#proxy">specify an HTTP proxy</a>.</p> |
| 81 | |
| @@ -85,31 +85,31 @@ | |
| 85 | information above and beyond the versioned files, including some |
| 86 | sensitive information such as password hashes and email addresses. If you |
| 87 | want to share Fossil repositories directly, consider running the |
| 88 | [/help/scrub|fossil scrub] command to remove sensitive information |
| 89 | before transmitting the file. |
| 90 | |
| 91 | <h2>Importing From Another Version Control System</h2> |
| 92 | |
| 93 | <p>Rather than start a new project, or clone an existing Fossil project, |
| 94 | you might prefer to |
| 95 | <a href="./inout.wiki">import an existing Git project</a> |
| 96 | into Fossil using the [/help/import | fossil import] command. |
| 97 | |
| 98 | <h2>Checking Out A Local Tree</h2> |
| 99 | |
| 100 | <p>To work on a project in fossil, you need to check out a local |
| 101 | copy of the source tree. Create the directory you want to be |
| 102 | the root of your tree and cd into that directory. Then |
| 103 | do this: ([/help/open | more info])</p> |
| 104 | |
| 105 | <blockquote> |
| 106 | <b>fossil open </b><i> repository-filename</i> |
| 107 | </blockquote> |
| 108 | |
| 109 | <p>This leaves you with the newest version of the tree |
| 110 | checked out. |
| 111 | From anywhere underneath the root of your local tree, you |
| 112 | can type commands like the following to find out the status of |
| 113 | your local tree:</p> |
| 114 | |
| 115 | <blockquote> |
| @@ -122,11 +122,11 @@ | |
| 122 | <b>[/help/branch | fossil branch]</b><br> |
| 123 | </blockquote> |
| 124 | |
| 125 | <p>Note that Fossil allows you to make multiple check-outs in |
| 126 | separate directories from the same repository. This enables you, |
| 127 | for example, to do builds from multiple branches or versions at |
| 128 | the same time without having to generate extra clones.</p> |
| 129 | |
| 130 | <p>To switch a checkout between different versions and branches, |
| 131 | use:</p> |
| 132 | |
| @@ -140,17 +140,17 @@ | |
| 140 | version, whereas [/help/checkout | checkout] does not |
| 141 | automatically sync and does a "hard" switch, overwriting local |
| 142 | changes if told to do so.</p> |
| 143 | |
| 144 | <h2>Configuring Your Local Repository</h2> |
| 145 | |
| 146 | <p>When you create a new repository, either by cloning an existing |
| 147 | project or create a new project of your own, you usually want to do some |
| 148 | local configuration. This is easily accomplished using the web-server |
| 149 | that is built into fossil. Start the fossil webserver like this: |
| 150 | ([/help/ui | more info])</p> |
| 151 | |
| 152 | <blockquote> |
| 153 | <b>fossil ui </b><i> repository-filename</i> |
| 154 | </blockquote> |
| 155 | |
| 156 | <p>You can omit the <i>repository-filename</i> from the command above |
| @@ -163,15 +163,15 @@ | |
| 163 | where to find your web browser using a command like this:</p> |
| 164 | |
| 165 | <blockquote> |
| 166 | <b>fossil setting web-browser </b><i> path-to-web-browser</i> |
| 167 | </blockquote> |
| 168 | |
| 169 | <p>By default, fossil does not require a login for HTTP connections |
| 170 | coming in from the IP loopback address 127.0.0.1. You can, and perhaps |
| 171 | should, change this after you create a few users.</p> |
| 172 | |
| 173 | <p>When you are finished configuring, just press Control-C or use |
| 174 | the <b>kill</b> command to shut down the mini-server.</p> |
| 175 | |
| 176 | <h2>Making Changes</h2> |
| 177 | |
| @@ -194,18 +194,18 @@ | |
| 194 | <p>You will be prompted for check-in comments using whatever editor |
| 195 | is specified by your VISUAL or EDITOR environment variable.</p> |
| 196 | |
| 197 | In the default configuration, the [/help/commit|commit] |
| 198 | command will also automatically [/help/push|push] your changes, but that |
| 199 | feature can be disabled. (More information about |
| 200 | [./concepts.wiki#workflow|autosync] and how to disable it.) |
| 201 | Remember that your coworkers can not see your changes until you |
| 202 | commit and push them.</p> |
| 203 | |
| 204 | <h2>Sharing Changes</h2> |
| 205 | |
| 206 | <p>When [./concepts.wiki#workflow|autosync] is turned off, |
| 207 | the changes you [/help/commit | commit] are only |
| 208 | on your local repository. |
| 209 | To share those changes with other repositories, do:</p> |
| 210 | |
| 211 | <blockquote> |
| @@ -241,11 +241,11 @@ | |
| 241 | the <i>VERSION</i>, then fossil moves you to the |
| 242 | latest version of the branch your are currently on.</p> |
| 243 | |
| 244 | <p>The default behavior is for [./concepts.wiki#workflow|autosync] to |
| 245 | be turned on. That means that a [/help/pull|pull] automatically occurs |
| 246 | when you run [/help/update|update] and a [/help/push|push] happens |
| 247 | automatically after you [/help/commit|commit]. So in normal practice, |
| 248 | the push, pull, and sync commands are rarely used. But it is important |
| 249 | to know about them, all the same.</p> |
| 250 | |
| 251 | <blockquote> |
| @@ -342,11 +342,11 @@ | |
| 342 | <li>[./server.wiki#cgi|CGI] |
| 343 | <li>[./server.wiki#scgi|SCGI] |
| 344 | </ul> |
| 345 | |
| 346 | <p>The [./selfhost.wiki | self-hosting fossil repositories] use |
| 347 | CGI. |
| 348 | |
| 349 | <a name="proxy"></a> |
| 350 | <h2>HTTP Proxies</h2> |
| 351 | |
| 352 | <p>If you are behind a restrictive firewall that requires you to use |
| @@ -382,11 +382,11 @@ | |
| 382 | <p>Or unset the environment variable. The fossil setting for the |
| 383 | HTTP proxy takes precedence over the environment variable and the |
| 384 | command-line option overrides both. If you have an persistent |
| 385 | proxy setting that you want to override for a one-time sync, that |
| 386 | is easily done on the command-line. For example, to sync with |
| 387 | a co-workers repository on your LAN, you might type:</p> |
| 388 | |
| 389 | <blockquote> |
| 390 | <b>fossil sync http://192.168.1.36:8080/ --proxy off</b> |
| 391 | </blockquote> |
| 392 | |
| 393 |
| --- www/quickstart.wiki | |
| +++ www/quickstart.wiki | |
| @@ -5,16 +5,16 @@ | |
| 5 | and painlessly.</p> |
| 6 | |
| 7 | <h2>Installing</h2> |
| 8 | |
| 9 | <p>Fossil is a single self-contained C program. You need to |
| 10 | either download a |
| 11 | <a href="http://www.fossil-scm.org/download.html">precompiled binary</a> |
| 12 | or <a href="build.wiki">compile it yourself</a> from sources. |
| 13 | Install fossil by putting the fossil binary |
| 14 | someplace on your $PATH.</p> |
| 15 | |
| 16 | <a name="fslclone"></a> |
| 17 | <h2>General Work Flow</h2> |
| 18 | |
| 19 | <p>Fossil works with repository files (a database with the project's |
| 20 | complete history) and with checked-out local trees (the working directory |
| @@ -34,11 +34,11 @@ | |
| 34 | |
| 35 | <h2>Starting A New Project</h2> |
| 36 | |
| 37 | <p>To start a new project with fossil, create a new empty repository |
| 38 | this way: ([/help/init | more info]) </p> |
| 39 | |
| 40 | <blockquote> |
| 41 | <b>fossil init </b><i> repository-filename</i> |
| 42 | </blockquote> |
| 43 | |
| 44 | <h2>Cloning An Existing Repository</h2> |
| @@ -46,36 +46,36 @@ | |
| 46 | <p>Most fossil operations interact with a repository that is on the |
| 47 | local disk drive, not on a remote system. Hence, before accessing |
| 48 | a remote repository it is necessary to make a local copy of that |
| 49 | repository. Making a local copy of a remote repository is called |
| 50 | "cloning".</p> |
| 51 | |
| 52 | <p>Clone a remote repository as follows: ([/help/clone | more info])</p> |
| 53 | |
| 54 | <blockquote> |
| 55 | <b>fossil clone</b> <i>URL repository-filename</i> |
| 56 | </blockquote> |
| 57 | |
| 58 | <p>The <i>URL</i> specifies the fossil repository |
| 59 | you want to clone. The <i>repository-filename</i> is the new local |
| 60 | filename into which the cloned repository will be written. For |
| 61 | example: |
| 62 | |
| 63 | <blockquote> |
| 64 | <b>fossil clone http://www.fossil-scm.org/ myclone.fossil</b> |
| 65 | </blockquote> |
| 66 | |
| 67 | <p>If the remote repository requires a login, include a |
| 68 | userid in the URL like this: |
| 69 | |
| 70 | <blockquote> |
| 71 | <b>fossil clone http://</b><i>userid</i><b>@www.fossil-scm.org/ myclone.fossil</b> |
| 72 | </blockquote> |
| 73 | |
| 74 | |
| 75 | <p>You will be prompted separately for the password. |
| 76 | Use "%HH" escapes for special characters in the userid. |
| 77 | Examples: "%40" in place of "@" and "%2F" in place of "/". |
| 78 | |
| 79 | <p>If you are behind a restrictive firewall, you might need |
| 80 | to <a href="#proxy">specify an HTTP proxy</a>.</p> |
| 81 | |
| @@ -85,31 +85,31 @@ | |
| 85 | information above and beyond the versioned files, including some |
| 86 | sensitive information such as password hashes and email addresses. If you |
| 87 | want to share Fossil repositories directly, consider running the |
| 88 | [/help/scrub|fossil scrub] command to remove sensitive information |
| 89 | before transmitting the file. |
| 90 | |
| 91 | <h2>Importing From Another Version Control System</h2> |
| 92 | |
| 93 | <p>Rather than start a new project, or clone an existing Fossil project, |
| 94 | you might prefer to |
| 95 | <a href="./inout.wiki">import an existing Git project</a> |
| 96 | into Fossil using the [/help/import | fossil import] command. |
| 97 | |
| 98 | <h2>Checking Out A Local Tree</h2> |
| 99 | |
| 100 | <p>To work on a project in fossil, you need to check out a local |
| 101 | copy of the source tree. Create the directory you want to be |
| 102 | the root of your tree and cd into that directory. Then |
| 103 | do this: ([/help/open | more info])</p> |
| 104 | |
| 105 | <blockquote> |
| 106 | <b>fossil open </b><i> repository-filename</i> |
| 107 | </blockquote> |
| 108 | |
| 109 | <p>This leaves you with the newest version of the tree |
| 110 | checked out. |
| 111 | From anywhere underneath the root of your local tree, you |
| 112 | can type commands like the following to find out the status of |
| 113 | your local tree:</p> |
| 114 | |
| 115 | <blockquote> |
| @@ -122,11 +122,11 @@ | |
| 122 | <b>[/help/branch | fossil branch]</b><br> |
| 123 | </blockquote> |
| 124 | |
| 125 | <p>Note that Fossil allows you to make multiple check-outs in |
| 126 | separate directories from the same repository. This enables you, |
| 127 | for example, to do builds from multiple branches or versions at |
| 128 | the same time without having to generate extra clones.</p> |
| 129 | |
| 130 | <p>To switch a checkout between different versions and branches, |
| 131 | use:</p> |
| 132 | |
| @@ -140,17 +140,17 @@ | |
| 140 | version, whereas [/help/checkout | checkout] does not |
| 141 | automatically sync and does a "hard" switch, overwriting local |
| 142 | changes if told to do so.</p> |
| 143 | |
| 144 | <h2>Configuring Your Local Repository</h2> |
| 145 | |
| 146 | <p>When you create a new repository, either by cloning an existing |
| 147 | project or create a new project of your own, you usually want to do some |
| 148 | local configuration. This is easily accomplished using the web-server |
| 149 | that is built into fossil. Start the fossil webserver like this: |
| 150 | ([/help/ui | more info])</p> |
| 151 | |
| 152 | <blockquote> |
| 153 | <b>fossil ui </b><i> repository-filename</i> |
| 154 | </blockquote> |
| 155 | |
| 156 | <p>You can omit the <i>repository-filename</i> from the command above |
| @@ -163,15 +163,15 @@ | |
| 163 | where to find your web browser using a command like this:</p> |
| 164 | |
| 165 | <blockquote> |
| 166 | <b>fossil setting web-browser </b><i> path-to-web-browser</i> |
| 167 | </blockquote> |
| 168 | |
| 169 | <p>By default, fossil does not require a login for HTTP connections |
| 170 | coming in from the IP loopback address 127.0.0.1. You can, and perhaps |
| 171 | should, change this after you create a few users.</p> |
| 172 | |
| 173 | <p>When you are finished configuring, just press Control-C or use |
| 174 | the <b>kill</b> command to shut down the mini-server.</p> |
| 175 | |
| 176 | <h2>Making Changes</h2> |
| 177 | |
| @@ -194,18 +194,18 @@ | |
| 194 | <p>You will be prompted for check-in comments using whatever editor |
| 195 | is specified by your VISUAL or EDITOR environment variable.</p> |
| 196 | |
| 197 | In the default configuration, the [/help/commit|commit] |
| 198 | command will also automatically [/help/push|push] your changes, but that |
| 199 | feature can be disabled. (More information about |
| 200 | [./concepts.wiki#workflow|autosync] and how to disable it.) |
| 201 | Remember that your coworkers can not see your changes until you |
| 202 | commit and push them.</p> |
| 203 | |
| 204 | <h2>Sharing Changes</h2> |
| 205 | |
| 206 | <p>When [./concepts.wiki#workflow|autosync] is turned off, |
| 207 | the changes you [/help/commit | commit] are only |
| 208 | on your local repository. |
| 209 | To share those changes with other repositories, do:</p> |
| 210 | |
| 211 | <blockquote> |
| @@ -241,11 +241,11 @@ | |
| 241 | the <i>VERSION</i>, then fossil moves you to the |
| 242 | latest version of the branch your are currently on.</p> |
| 243 | |
| 244 | <p>The default behavior is for [./concepts.wiki#workflow|autosync] to |
| 245 | be turned on. That means that a [/help/pull|pull] automatically occurs |
| 246 | when you run [/help/update|update] and a [/help/push|push] happens |
| 247 | automatically after you [/help/commit|commit]. So in normal practice, |
| 248 | the push, pull, and sync commands are rarely used. But it is important |
| 249 | to know about them, all the same.</p> |
| 250 | |
| 251 | <blockquote> |
| @@ -342,11 +342,11 @@ | |
| 342 | <li>[./server.wiki#cgi|CGI] |
| 343 | <li>[./server.wiki#scgi|SCGI] |
| 344 | </ul> |
| 345 | |
| 346 | <p>The [./selfhost.wiki | self-hosting fossil repositories] use |
| 347 | CGI. |
| 348 | |
| 349 | <a name="proxy"></a> |
| 350 | <h2>HTTP Proxies</h2> |
| 351 | |
| 352 | <p>If you are behind a restrictive firewall that requires you to use |
| @@ -382,11 +382,11 @@ | |
| 382 | <p>Or unset the environment variable. The fossil setting for the |
| 383 | HTTP proxy takes precedence over the environment variable and the |
| 384 | command-line option overrides both. If you have an persistent |
| 385 | proxy setting that you want to override for a one-time sync, that |
| 386 | is easily done on the command-line. For example, to sync with |
| 387 | a co-workers repository on your LAN, you might type:</p> |
| 388 | |
| 389 | <blockquote> |
| 390 | <b>fossil sync http://192.168.1.36:8080/ --proxy off</b> |
| 391 | </blockquote> |
| 392 | |
| 393 |
+13
-13
| --- www/quotes.wiki | ||
| +++ www/quotes.wiki | ||
| @@ -5,19 +5,19 @@ | ||
| 5 | 5 | by the creator of Fossil, so of course there is selection bias... |
| 6 | 6 | |
| 7 | 7 | <h2>On The Usability Of Git:</h2> |
| 8 | 8 | |
| 9 | 9 | <ol> |
| 10 | -<li>Git approaches the usability of iptables, which is to say, utterly | |
| 10 | +<li>Git approaches the usability of iptables, which is to say, utterly | |
| 11 | 11 | unusable unless you have the manpage tattooed on you arm. |
| 12 | 12 | |
| 13 | 13 | <blockquote> |
| 14 | 14 | <i>by mml at [http://news.ycombinator.com/item?id=1433387]</i> |
| 15 | 15 | </blockquote> |
| 16 | 16 | |
| 17 | 17 | <li><nowiki>It's simplest to think of the state of your [git] repository |
| 18 | -as a point in a high-dimensional "code-space", in which branches are | |
| 18 | +as a point in a high-dimensional "code-space", in which branches are | |
| 19 | 19 | represented as n-dimensional membranes, mapping the spatial loci of |
| 20 | 20 | successive commits onto the projected manifold of each cloned |
| 21 | 21 | repository.</nowiki> |
| 22 | 22 | |
| 23 | 23 | <blockquote> |
| @@ -25,11 +25,11 @@ | ||
| 25 | 25 | </blockquote> |
| 26 | 26 | |
| 27 | 27 | <li>Git is not a Prius. Git is a Model T. |
| 28 | 28 | Its plumbing and wiring sticks out all over the place. |
| 29 | 29 | You have to be a mechanic to operate it successfully or you'll be |
| 30 | -stuck on the side of the road when it breaks down. | |
| 30 | +stuck on the side of the road when it breaks down. | |
| 31 | 31 | And it <b>will</b> break down. |
| 32 | 32 | |
| 33 | 33 | <blockquote> |
| 34 | 34 | <i>Nick Farina at [http://nfarina.com/post/9868516270/git-is-simpler]</i> |
| 35 | 35 | </blockquote> |
| @@ -39,11 +39,11 @@ | ||
| 39 | 39 | <blockquote> |
| 40 | 40 | <i>Linus Torvalds - 2005-04-07 22:13:13<br> |
| 41 | 41 | Commit comment on the very first source-code check-in for git |
| 42 | 42 | </blockquote> |
| 43 | 43 | |
| 44 | -<li>I've been experimenting a lot with git at work. | |
| 44 | +<li>I've been experimenting a lot with git at work. | |
| 45 | 45 | Damn, it's complicated. |
| 46 | 46 | It has things to trip you up with that sane people just wouldn't ever both with |
| 47 | 47 | including the ability to allow you to commit stuff in such a way that you can't find |
| 48 | 48 | it again afterwards (!!!) |
| 49 | 49 | Demented workflow complexity on acid? |
| @@ -104,19 +104,19 @@ | ||
| 104 | 104 | |
| 105 | 105 | <blockquote> |
| 106 | 106 | <i>Joe Prostko at [http://www.mail-archive.com/[email protected]/msg16716.html] |
| 107 | 107 | </blockquote> |
| 108 | 108 | |
| 109 | -<li>Fossil is awesome!!! I have never seen an app like that before, | |
| 109 | +<li>Fossil is awesome!!! I have never seen an app like that before, | |
| 110 | 110 | such simplicity and flexibility!!! |
| 111 | 111 | |
| 112 | 112 | <blockquote> |
| 113 | 113 | <i>zengr at [http://stackoverflow.com/questions/138621/best-version-control-for-lone-developer]</i> |
| 114 | 114 | </blockquote> |
| 115 | 115 | |
| 116 | 116 | <li>This is my favourite VCS. I can carry it on a USB. And it's a complete system, with it's own |
| 117 | -server, ticketing system, Wiki pages, and a very, very helpful timeline visualization. And | |
| 117 | +server, ticketing system, Wiki pages, and a very, very helpful timeline visualization. And | |
| 118 | 118 | the entire program in a single file! |
| 119 | 119 | |
| 120 | 120 | <blockquote> |
| 121 | 121 | <i>thunderbong commenting on hacker news: [https://news.ycombinator.com/item?id=9131619]</i> |
| 122 | 122 | </blockquote> |
| @@ -127,30 +127,30 @@ | ||
| 127 | 127 | |
| 128 | 128 | <h2>On Git Versus Fossil</h2> |
| 129 | 129 | |
| 130 | 130 | <ol> |
| 131 | 131 | <li value=15> |
| 132 | -Just want to say thanks for fossil making my life easier.... | |
| 132 | +Just want to say thanks for fossil making my life easier.... | |
| 133 | 133 | Also <nowiki>[for]</nowiki> not having a misanthropic command line interface. |
| 134 | 134 | |
| 135 | 135 | <blockquote> |
| 136 | 136 | <i>Joshua Paine at [http://www.mail-archive.com/[email protected]/msg02736.html]</i> |
| 137 | 137 | </blockquote> |
| 138 | 138 | |
| 139 | 139 | <li>We use it at a large university to manage code that small teams write. |
| 140 | -The runs everywhere, ease of installation and portability is something that | |
| 141 | -seems to be a good fit with the environment we have (highly ditrobuted, | |
| 142 | -sometimes very restrictive firewalls, OSX/Win/Linux). We are happy with it | |
| 143 | -and teaching a Msc/Phd student (read complete novice) fossil has just | |
| 140 | +The runs everywhere, ease of installation and portability is something that | |
| 141 | +seems to be a good fit with the environment we have (highly ditrobuted, | |
| 142 | +sometimes very restrictive firewalls, OSX/Win/Linux). We are happy with it | |
| 143 | +and teaching a Msc/Phd student (read complete novice) fossil has just | |
| 144 | 144 | been a smoother ride than Git was. |
| 145 | 145 | |
| 146 | 146 | <blockquote> |
| 147 | 147 | <i>viablepanic at [http://www.reddit.com/r/programming/comments/bxcto/why_not_fossil_scm/]</i> |
| 148 | 148 | </blockquote> |
| 149 | 149 | |
| 150 | -<li>In the fossil community - and hence in fossil itself - development history | |
| 151 | -is pretty much sacrosanct. The very name "fossil" was to chosen to | |
| 150 | +<li>In the fossil community - and hence in fossil itself - development history | |
| 151 | +is pretty much sacrosanct. The very name "fossil" was to chosen to | |
| 152 | 152 | reflect the unchanging nature of things in that history. |
| 153 | 153 | |
| 154 | 154 | <p>In git (or rather, the git community), the development history is part of |
| 155 | 155 | the published aspect of the project, so it provides tools for rearranging |
| 156 | 156 | that history so you can present what you "should" have done rather |
| 157 | 157 |
| --- www/quotes.wiki | |
| +++ www/quotes.wiki | |
| @@ -5,19 +5,19 @@ | |
| 5 | by the creator of Fossil, so of course there is selection bias... |
| 6 | |
| 7 | <h2>On The Usability Of Git:</h2> |
| 8 | |
| 9 | <ol> |
| 10 | <li>Git approaches the usability of iptables, which is to say, utterly |
| 11 | unusable unless you have the manpage tattooed on you arm. |
| 12 | |
| 13 | <blockquote> |
| 14 | <i>by mml at [http://news.ycombinator.com/item?id=1433387]</i> |
| 15 | </blockquote> |
| 16 | |
| 17 | <li><nowiki>It's simplest to think of the state of your [git] repository |
| 18 | as a point in a high-dimensional "code-space", in which branches are |
| 19 | represented as n-dimensional membranes, mapping the spatial loci of |
| 20 | successive commits onto the projected manifold of each cloned |
| 21 | repository.</nowiki> |
| 22 | |
| 23 | <blockquote> |
| @@ -25,11 +25,11 @@ | |
| 25 | </blockquote> |
| 26 | |
| 27 | <li>Git is not a Prius. Git is a Model T. |
| 28 | Its plumbing and wiring sticks out all over the place. |
| 29 | You have to be a mechanic to operate it successfully or you'll be |
| 30 | stuck on the side of the road when it breaks down. |
| 31 | And it <b>will</b> break down. |
| 32 | |
| 33 | <blockquote> |
| 34 | <i>Nick Farina at [http://nfarina.com/post/9868516270/git-is-simpler]</i> |
| 35 | </blockquote> |
| @@ -39,11 +39,11 @@ | |
| 39 | <blockquote> |
| 40 | <i>Linus Torvalds - 2005-04-07 22:13:13<br> |
| 41 | Commit comment on the very first source-code check-in for git |
| 42 | </blockquote> |
| 43 | |
| 44 | <li>I've been experimenting a lot with git at work. |
| 45 | Damn, it's complicated. |
| 46 | It has things to trip you up with that sane people just wouldn't ever both with |
| 47 | including the ability to allow you to commit stuff in such a way that you can't find |
| 48 | it again afterwards (!!!) |
| 49 | Demented workflow complexity on acid? |
| @@ -104,19 +104,19 @@ | |
| 104 | |
| 105 | <blockquote> |
| 106 | <i>Joe Prostko at [http://www.mail-archive.com/[email protected]/msg16716.html] |
| 107 | </blockquote> |
| 108 | |
| 109 | <li>Fossil is awesome!!! I have never seen an app like that before, |
| 110 | such simplicity and flexibility!!! |
| 111 | |
| 112 | <blockquote> |
| 113 | <i>zengr at [http://stackoverflow.com/questions/138621/best-version-control-for-lone-developer]</i> |
| 114 | </blockquote> |
| 115 | |
| 116 | <li>This is my favourite VCS. I can carry it on a USB. And it's a complete system, with it's own |
| 117 | server, ticketing system, Wiki pages, and a very, very helpful timeline visualization. And |
| 118 | the entire program in a single file! |
| 119 | |
| 120 | <blockquote> |
| 121 | <i>thunderbong commenting on hacker news: [https://news.ycombinator.com/item?id=9131619]</i> |
| 122 | </blockquote> |
| @@ -127,30 +127,30 @@ | |
| 127 | |
| 128 | <h2>On Git Versus Fossil</h2> |
| 129 | |
| 130 | <ol> |
| 131 | <li value=15> |
| 132 | Just want to say thanks for fossil making my life easier.... |
| 133 | Also <nowiki>[for]</nowiki> not having a misanthropic command line interface. |
| 134 | |
| 135 | <blockquote> |
| 136 | <i>Joshua Paine at [http://www.mail-archive.com/[email protected]/msg02736.html]</i> |
| 137 | </blockquote> |
| 138 | |
| 139 | <li>We use it at a large university to manage code that small teams write. |
| 140 | The runs everywhere, ease of installation and portability is something that |
| 141 | seems to be a good fit with the environment we have (highly ditrobuted, |
| 142 | sometimes very restrictive firewalls, OSX/Win/Linux). We are happy with it |
| 143 | and teaching a Msc/Phd student (read complete novice) fossil has just |
| 144 | been a smoother ride than Git was. |
| 145 | |
| 146 | <blockquote> |
| 147 | <i>viablepanic at [http://www.reddit.com/r/programming/comments/bxcto/why_not_fossil_scm/]</i> |
| 148 | </blockquote> |
| 149 | |
| 150 | <li>In the fossil community - and hence in fossil itself - development history |
| 151 | is pretty much sacrosanct. The very name "fossil" was to chosen to |
| 152 | reflect the unchanging nature of things in that history. |
| 153 | |
| 154 | <p>In git (or rather, the git community), the development history is part of |
| 155 | the published aspect of the project, so it provides tools for rearranging |
| 156 | that history so you can present what you "should" have done rather |
| 157 |
| --- www/quotes.wiki | |
| +++ www/quotes.wiki | |
| @@ -5,19 +5,19 @@ | |
| 5 | by the creator of Fossil, so of course there is selection bias... |
| 6 | |
| 7 | <h2>On The Usability Of Git:</h2> |
| 8 | |
| 9 | <ol> |
| 10 | <li>Git approaches the usability of iptables, which is to say, utterly |
| 11 | unusable unless you have the manpage tattooed on you arm. |
| 12 | |
| 13 | <blockquote> |
| 14 | <i>by mml at [http://news.ycombinator.com/item?id=1433387]</i> |
| 15 | </blockquote> |
| 16 | |
| 17 | <li><nowiki>It's simplest to think of the state of your [git] repository |
| 18 | as a point in a high-dimensional "code-space", in which branches are |
| 19 | represented as n-dimensional membranes, mapping the spatial loci of |
| 20 | successive commits onto the projected manifold of each cloned |
| 21 | repository.</nowiki> |
| 22 | |
| 23 | <blockquote> |
| @@ -25,11 +25,11 @@ | |
| 25 | </blockquote> |
| 26 | |
| 27 | <li>Git is not a Prius. Git is a Model T. |
| 28 | Its plumbing and wiring sticks out all over the place. |
| 29 | You have to be a mechanic to operate it successfully or you'll be |
| 30 | stuck on the side of the road when it breaks down. |
| 31 | And it <b>will</b> break down. |
| 32 | |
| 33 | <blockquote> |
| 34 | <i>Nick Farina at [http://nfarina.com/post/9868516270/git-is-simpler]</i> |
| 35 | </blockquote> |
| @@ -39,11 +39,11 @@ | |
| 39 | <blockquote> |
| 40 | <i>Linus Torvalds - 2005-04-07 22:13:13<br> |
| 41 | Commit comment on the very first source-code check-in for git |
| 42 | </blockquote> |
| 43 | |
| 44 | <li>I've been experimenting a lot with git at work. |
| 45 | Damn, it's complicated. |
| 46 | It has things to trip you up with that sane people just wouldn't ever both with |
| 47 | including the ability to allow you to commit stuff in such a way that you can't find |
| 48 | it again afterwards (!!!) |
| 49 | Demented workflow complexity on acid? |
| @@ -104,19 +104,19 @@ | |
| 104 | |
| 105 | <blockquote> |
| 106 | <i>Joe Prostko at [http://www.mail-archive.com/[email protected]/msg16716.html] |
| 107 | </blockquote> |
| 108 | |
| 109 | <li>Fossil is awesome!!! I have never seen an app like that before, |
| 110 | such simplicity and flexibility!!! |
| 111 | |
| 112 | <blockquote> |
| 113 | <i>zengr at [http://stackoverflow.com/questions/138621/best-version-control-for-lone-developer]</i> |
| 114 | </blockquote> |
| 115 | |
| 116 | <li>This is my favourite VCS. I can carry it on a USB. And it's a complete system, with it's own |
| 117 | server, ticketing system, Wiki pages, and a very, very helpful timeline visualization. And |
| 118 | the entire program in a single file! |
| 119 | |
| 120 | <blockquote> |
| 121 | <i>thunderbong commenting on hacker news: [https://news.ycombinator.com/item?id=9131619]</i> |
| 122 | </blockquote> |
| @@ -127,30 +127,30 @@ | |
| 127 | |
| 128 | <h2>On Git Versus Fossil</h2> |
| 129 | |
| 130 | <ol> |
| 131 | <li value=15> |
| 132 | Just want to say thanks for fossil making my life easier.... |
| 133 | Also <nowiki>[for]</nowiki> not having a misanthropic command line interface. |
| 134 | |
| 135 | <blockquote> |
| 136 | <i>Joshua Paine at [http://www.mail-archive.com/[email protected]/msg02736.html]</i> |
| 137 | </blockquote> |
| 138 | |
| 139 | <li>We use it at a large university to manage code that small teams write. |
| 140 | The runs everywhere, ease of installation and portability is something that |
| 141 | seems to be a good fit with the environment we have (highly ditrobuted, |
| 142 | sometimes very restrictive firewalls, OSX/Win/Linux). We are happy with it |
| 143 | and teaching a Msc/Phd student (read complete novice) fossil has just |
| 144 | been a smoother ride than Git was. |
| 145 | |
| 146 | <blockquote> |
| 147 | <i>viablepanic at [http://www.reddit.com/r/programming/comments/bxcto/why_not_fossil_scm/]</i> |
| 148 | </blockquote> |
| 149 | |
| 150 | <li>In the fossil community - and hence in fossil itself - development history |
| 151 | is pretty much sacrosanct. The very name "fossil" was to chosen to |
| 152 | reflect the unchanging nature of things in that history. |
| 153 | |
| 154 | <p>In git (or rather, the git community), the development history is part of |
| 155 | the published aspect of the project, so it provides tools for rearranging |
| 156 | that history so you can present what you "should" have done rather |
| 157 |
+12
-12
| --- www/reviews.wiki | ||
| +++ www/reviews.wiki | ||
| @@ -1,8 +1,8 @@ | ||
| 1 | 1 | <title>Reviews</title> |
| 2 | 2 | <b>External links:</b> |
| 3 | - | |
| 3 | + | |
| 4 | 4 | * [http://nixtu.blogspot.com/2010/03/fossil-dvcs-on-go-first-impressions.html | |
| 5 | 5 | Fossil DVCS on the Go - First Impressions] |
| 6 | 6 | * [http://blog.mired.org/2011/02/fossil-sweet-spot-in-vcs-space.html | |
| 7 | 7 | Fossil - a sweet spot in the VCS space] by Mike Meyer. |
| 8 | 8 | * [http://blog.s11n.net/?p=72|Four reasons to take a closer look at the Fossil SCM] by Stephan Beal |
| @@ -22,27 +22,27 @@ | ||
| 22 | 22 | |
| 23 | 23 | |
| 24 | 24 | <b>Joshua Paine on 2010-10-22:</b> |
| 25 | 25 | |
| 26 | 26 | <blockquote> |
| 27 | -With one of my several hats on, I'm in a small team using git. Another | |
| 28 | -team member just checked some stuff into trunk that should have been on | |
| 29 | -a branch. Nothing else had happened since, so in fossil I would have | |
| 30 | -just edited that commit and put it on a new branch. In git that can't | |
| 31 | -actually be done without danger once other people have pulled, so I had | |
| 32 | -to create a new commit rolling back the changes, then branch and cherry | |
| 33 | -pick the earlier changes, then figure out how to make my new branch | |
| 34 | -shared instead of private. Just want to say thanks for fossil making my | |
| 35 | -life easier on most of my projects, and being able to move commits to | |
| 36 | -another branch after the fact and shared-by-default branches are good | |
| 27 | +With one of my several hats on, I'm in a small team using git. Another | |
| 28 | +team member just checked some stuff into trunk that should have been on | |
| 29 | +a branch. Nothing else had happened since, so in fossil I would have | |
| 30 | +just edited that commit and put it on a new branch. In git that can't | |
| 31 | +actually be done without danger once other people have pulled, so I had | |
| 32 | +to create a new commit rolling back the changes, then branch and cherry | |
| 33 | +pick the earlier changes, then figure out how to make my new branch | |
| 34 | +shared instead of private. Just want to say thanks for fossil making my | |
| 35 | +life easier on most of my projects, and being able to move commits to | |
| 36 | +another branch after the fact and shared-by-default branches are good | |
| 37 | 37 | features. Also not having a misanthropic command line interface. |
| 38 | 38 | </blockquote> |
| 39 | 39 | |
| 40 | 40 | <b>Stephan Beal writes on 2009-01-11:</b> |
| 41 | 41 | |
| 42 | 42 | <blockquote> |
| 43 | -Sometime in late 2007 I came across a link to fossil on | |
| 43 | +Sometime in late 2007 I came across a link to fossil on | |
| 44 | 44 | <a href="http://www.sqlite.org/">sqlite.org</a>. It |
| 45 | 45 | was a good thing I bookmarked it, because I was never able to find the |
| 46 | 46 | link again (it might have been in a bug report or something). The |
| 47 | 47 | reasons I first took a close look at it were (A) it stemmed from the |
| 48 | 48 | sqlite project, which I've held in high regards for years (e.g. I |
| 49 | 49 |
| --- www/reviews.wiki | |
| +++ www/reviews.wiki | |
| @@ -1,8 +1,8 @@ | |
| 1 | <title>Reviews</title> |
| 2 | <b>External links:</b> |
| 3 | |
| 4 | * [http://nixtu.blogspot.com/2010/03/fossil-dvcs-on-go-first-impressions.html | |
| 5 | Fossil DVCS on the Go - First Impressions] |
| 6 | * [http://blog.mired.org/2011/02/fossil-sweet-spot-in-vcs-space.html | |
| 7 | Fossil - a sweet spot in the VCS space] by Mike Meyer. |
| 8 | * [http://blog.s11n.net/?p=72|Four reasons to take a closer look at the Fossil SCM] by Stephan Beal |
| @@ -22,27 +22,27 @@ | |
| 22 | |
| 23 | |
| 24 | <b>Joshua Paine on 2010-10-22:</b> |
| 25 | |
| 26 | <blockquote> |
| 27 | With one of my several hats on, I'm in a small team using git. Another |
| 28 | team member just checked some stuff into trunk that should have been on |
| 29 | a branch. Nothing else had happened since, so in fossil I would have |
| 30 | just edited that commit and put it on a new branch. In git that can't |
| 31 | actually be done without danger once other people have pulled, so I had |
| 32 | to create a new commit rolling back the changes, then branch and cherry |
| 33 | pick the earlier changes, then figure out how to make my new branch |
| 34 | shared instead of private. Just want to say thanks for fossil making my |
| 35 | life easier on most of my projects, and being able to move commits to |
| 36 | another branch after the fact and shared-by-default branches are good |
| 37 | features. Also not having a misanthropic command line interface. |
| 38 | </blockquote> |
| 39 | |
| 40 | <b>Stephan Beal writes on 2009-01-11:</b> |
| 41 | |
| 42 | <blockquote> |
| 43 | Sometime in late 2007 I came across a link to fossil on |
| 44 | <a href="http://www.sqlite.org/">sqlite.org</a>. It |
| 45 | was a good thing I bookmarked it, because I was never able to find the |
| 46 | link again (it might have been in a bug report or something). The |
| 47 | reasons I first took a close look at it were (A) it stemmed from the |
| 48 | sqlite project, which I've held in high regards for years (e.g. I |
| 49 |
| --- www/reviews.wiki | |
| +++ www/reviews.wiki | |
| @@ -1,8 +1,8 @@ | |
| 1 | <title>Reviews</title> |
| 2 | <b>External links:</b> |
| 3 | |
| 4 | * [http://nixtu.blogspot.com/2010/03/fossil-dvcs-on-go-first-impressions.html | |
| 5 | Fossil DVCS on the Go - First Impressions] |
| 6 | * [http://blog.mired.org/2011/02/fossil-sweet-spot-in-vcs-space.html | |
| 7 | Fossil - a sweet spot in the VCS space] by Mike Meyer. |
| 8 | * [http://blog.s11n.net/?p=72|Four reasons to take a closer look at the Fossil SCM] by Stephan Beal |
| @@ -22,27 +22,27 @@ | |
| 22 | |
| 23 | |
| 24 | <b>Joshua Paine on 2010-10-22:</b> |
| 25 | |
| 26 | <blockquote> |
| 27 | With one of my several hats on, I'm in a small team using git. Another |
| 28 | team member just checked some stuff into trunk that should have been on |
| 29 | a branch. Nothing else had happened since, so in fossil I would have |
| 30 | just edited that commit and put it on a new branch. In git that can't |
| 31 | actually be done without danger once other people have pulled, so I had |
| 32 | to create a new commit rolling back the changes, then branch and cherry |
| 33 | pick the earlier changes, then figure out how to make my new branch |
| 34 | shared instead of private. Just want to say thanks for fossil making my |
| 35 | life easier on most of my projects, and being able to move commits to |
| 36 | another branch after the fact and shared-by-default branches are good |
| 37 | features. Also not having a misanthropic command line interface. |
| 38 | </blockquote> |
| 39 | |
| 40 | <b>Stephan Beal writes on 2009-01-11:</b> |
| 41 | |
| 42 | <blockquote> |
| 43 | Sometime in late 2007 I came across a link to fossil on |
| 44 | <a href="http://www.sqlite.org/">sqlite.org</a>. It |
| 45 | was a good thing I bookmarked it, because I was never able to find the |
| 46 | link again (it might have been in a bug report or something). The |
| 47 | reasons I first took a close look at it were (A) it stemmed from the |
| 48 | sqlite project, which I've held in high regards for years (e.g. I |
| 49 |
+3
-3
| --- www/selfcheck.wiki | ||
| +++ www/selfcheck.wiki | ||
| @@ -14,11 +14,11 @@ | ||
| 14 | 14 | lost. The integrity checks are doing their job well.</p> |
| 15 | 15 | |
| 16 | 16 | <h2>Atomic Check-ins With Rollback</h2> |
| 17 | 17 | |
| 18 | 18 | The fossil repository is stored in an |
| 19 | -<a href="http://www.sqlite.org/">SQLite</a> database file. | |
| 19 | +<a href="http://www.sqlite.org/">SQLite</a> database file. | |
| 20 | 20 | ([./tech_overview.wiki | Addition information] about the repository |
| 21 | 21 | file format.) |
| 22 | 22 | SQLite is very mature and stable and has been in wide-spread use for many |
| 23 | 23 | years, so we are confident it will not cause repository |
| 24 | 24 | corruption. SQLite |
| @@ -61,11 +61,11 @@ | ||
| 61 | 61 | message is printed and the transaction rolls back. |
| 62 | 62 | |
| 63 | 63 | So, in other words, fossil always checks to make sure it can |
| 64 | 64 | re-extract a file before it commits a change to that file. |
| 65 | 65 | Hence bugs in fossil are unlikely to corrupt the repository in |
| 66 | -a way that prevents us from extracting historical versions of | |
| 66 | +a way that prevents us from extracting historical versions of | |
| 67 | 67 | files. |
| 68 | 68 | |
| 69 | 69 | <h2>Checksum Over All Files In A Check-in</h2> |
| 70 | 70 | |
| 71 | 71 | Manifest artifacts that define a check-in have two fields (the |
| @@ -102,7 +102,7 @@ | ||
| 102 | 102 | <a href="http://en.wikipedia.org/wiki/The_Tortoise_and_the_Hare">tortoise</a>: |
| 103 | 103 | reliability is more important than raw speed. The developers of |
| 104 | 104 | fossil see no merit in getting the wrong answer quickly. |
| 105 | 105 | |
| 106 | 106 | Fossil may not be the fastest versioning system, but it is "fast enough". |
| 107 | -Fossil runs quickly enough to stay out of the developers way. | |
| 107 | +Fossil runs quickly enough to stay out of the developers way. | |
| 108 | 108 | Most operations complete in under a second. |
| 109 | 109 |
| --- www/selfcheck.wiki | |
| +++ www/selfcheck.wiki | |
| @@ -14,11 +14,11 @@ | |
| 14 | lost. The integrity checks are doing their job well.</p> |
| 15 | |
| 16 | <h2>Atomic Check-ins With Rollback</h2> |
| 17 | |
| 18 | The fossil repository is stored in an |
| 19 | <a href="http://www.sqlite.org/">SQLite</a> database file. |
| 20 | ([./tech_overview.wiki | Addition information] about the repository |
| 21 | file format.) |
| 22 | SQLite is very mature and stable and has been in wide-spread use for many |
| 23 | years, so we are confident it will not cause repository |
| 24 | corruption. SQLite |
| @@ -61,11 +61,11 @@ | |
| 61 | message is printed and the transaction rolls back. |
| 62 | |
| 63 | So, in other words, fossil always checks to make sure it can |
| 64 | re-extract a file before it commits a change to that file. |
| 65 | Hence bugs in fossil are unlikely to corrupt the repository in |
| 66 | a way that prevents us from extracting historical versions of |
| 67 | files. |
| 68 | |
| 69 | <h2>Checksum Over All Files In A Check-in</h2> |
| 70 | |
| 71 | Manifest artifacts that define a check-in have two fields (the |
| @@ -102,7 +102,7 @@ | |
| 102 | <a href="http://en.wikipedia.org/wiki/The_Tortoise_and_the_Hare">tortoise</a>: |
| 103 | reliability is more important than raw speed. The developers of |
| 104 | fossil see no merit in getting the wrong answer quickly. |
| 105 | |
| 106 | Fossil may not be the fastest versioning system, but it is "fast enough". |
| 107 | Fossil runs quickly enough to stay out of the developers way. |
| 108 | Most operations complete in under a second. |
| 109 |
| --- www/selfcheck.wiki | |
| +++ www/selfcheck.wiki | |
| @@ -14,11 +14,11 @@ | |
| 14 | lost. The integrity checks are doing their job well.</p> |
| 15 | |
| 16 | <h2>Atomic Check-ins With Rollback</h2> |
| 17 | |
| 18 | The fossil repository is stored in an |
| 19 | <a href="http://www.sqlite.org/">SQLite</a> database file. |
| 20 | ([./tech_overview.wiki | Addition information] about the repository |
| 21 | file format.) |
| 22 | SQLite is very mature and stable and has been in wide-spread use for many |
| 23 | years, so we are confident it will not cause repository |
| 24 | corruption. SQLite |
| @@ -61,11 +61,11 @@ | |
| 61 | message is printed and the transaction rolls back. |
| 62 | |
| 63 | So, in other words, fossil always checks to make sure it can |
| 64 | re-extract a file before it commits a change to that file. |
| 65 | Hence bugs in fossil are unlikely to corrupt the repository in |
| 66 | a way that prevents us from extracting historical versions of |
| 67 | files. |
| 68 | |
| 69 | <h2>Checksum Over All Files In A Check-in</h2> |
| 70 | |
| 71 | Manifest artifacts that define a check-in have two fields (the |
| @@ -102,7 +102,7 @@ | |
| 102 | <a href="http://en.wikipedia.org/wiki/The_Tortoise_and_the_Hare">tortoise</a>: |
| 103 | reliability is more important than raw speed. The developers of |
| 104 | fossil see no merit in getting the wrong answer quickly. |
| 105 | |
| 106 | Fossil may not be the fastest versioning system, but it is "fast enough". |
| 107 | Fossil runs quickly enough to stay out of the developers way. |
| 108 | Most operations complete in under a second. |
| 109 |
+6
-6
| --- www/selfhost.wiki | ||
| +++ www/selfhost.wiki | ||
| @@ -7,23 +7,23 @@ | ||
| 7 | 7 | 2. [http://www2.fossil-scm.org/] |
| 8 | 8 | 3. [http://www3.fossil-scm.org/site.cgi] |
| 9 | 9 | |
| 10 | 10 | |
| 11 | 11 | The canonical repository is (1). Repositories (2) and (3) automatically |
| 12 | -stay in synchronization with (1) via a | |
| 12 | +stay in synchronization with (1) via a | |
| 13 | 13 | <a href="http://en.wikipedia.org/wiki/Cron">cron job</a> that invokes |
| 14 | 14 | "fossil sync" at regular intervals. |
| 15 | 15 | |
| 16 | 16 | Note that the two secondary repositories are more than just read-only mirrors. |
| 17 | 17 | All three servers support full read/write capabilities. |
| 18 | -Changes (such as new tickets or wiki or check-ins) can be implemented | |
| 18 | +Changes (such as new tickets or wiki or check-ins) can be implemented | |
| 19 | 19 | on any of the three servers and those changes automatically propagate to the |
| 20 | 20 | other two servers. |
| 21 | 21 | |
| 22 | 22 | Server (1) runs as a CGI script on a |
| 23 | 23 | <a href="http://www.linode.com/">Linode 1024</a> located in Dallas, TX |
| 24 | -- on the same virtual machine that | |
| 24 | +- on the same virtual machine that | |
| 25 | 25 | hosts <a href="http://www.sqlite.org/">SQLite</a> and over a |
| 26 | 26 | dozen other smaller projects. This demonstrates that Fossil can run on |
| 27 | 27 | a low-power host processor. |
| 28 | 28 | Multiple fossil-based projects can easily be hosted on the same machine, |
| 29 | 29 | even if that machine is itself one of several dozen virtual machines on |
| @@ -34,17 +34,17 @@ | ||
| 34 | 34 | #!/usr/bin/fossil |
| 35 | 35 | repository: /fossil/fossil.fossil |
| 36 | 36 | </pre></blockquote> |
| 37 | 37 | |
| 38 | 38 | Server (3) runs as a CGI script on a shared hosting account at |
| 39 | -<a href="http://www.he.net/">Hurricane Electric</a> in Fremont, CA. | |
| 39 | +<a href="http://www.he.net/">Hurricane Electric</a> in Fremont, CA. | |
| 40 | 40 | This server demonstrates the ability of |
| 41 | 41 | Fossil to run on an economical shared-host web account with no |
| 42 | 42 | privileges beyond port 80 HTTP access and CGI. It is not necessary |
| 43 | 43 | to have a dedicated computer with administrator privileges to run Fossil. |
| 44 | -As far as we are aware, | |
| 45 | -Fossil is the only full-featured configuration management system | |
| 44 | +As far as we are aware, | |
| 45 | +Fossil is the only full-featured configuration management system | |
| 46 | 46 | that can run in |
| 47 | 47 | such a restricted environment. The CGI script that runs on the |
| 48 | 48 | Hurricane Electric server is the same as the CGI script shown above, |
| 49 | 49 | except that the pathnames are modified to suit the environment: |
| 50 | 50 | |
| 51 | 51 |
| --- www/selfhost.wiki | |
| +++ www/selfhost.wiki | |
| @@ -7,23 +7,23 @@ | |
| 7 | 2. [http://www2.fossil-scm.org/] |
| 8 | 3. [http://www3.fossil-scm.org/site.cgi] |
| 9 | |
| 10 | |
| 11 | The canonical repository is (1). Repositories (2) and (3) automatically |
| 12 | stay in synchronization with (1) via a |
| 13 | <a href="http://en.wikipedia.org/wiki/Cron">cron job</a> that invokes |
| 14 | "fossil sync" at regular intervals. |
| 15 | |
| 16 | Note that the two secondary repositories are more than just read-only mirrors. |
| 17 | All three servers support full read/write capabilities. |
| 18 | Changes (such as new tickets or wiki or check-ins) can be implemented |
| 19 | on any of the three servers and those changes automatically propagate to the |
| 20 | other two servers. |
| 21 | |
| 22 | Server (1) runs as a CGI script on a |
| 23 | <a href="http://www.linode.com/">Linode 1024</a> located in Dallas, TX |
| 24 | - on the same virtual machine that |
| 25 | hosts <a href="http://www.sqlite.org/">SQLite</a> and over a |
| 26 | dozen other smaller projects. This demonstrates that Fossil can run on |
| 27 | a low-power host processor. |
| 28 | Multiple fossil-based projects can easily be hosted on the same machine, |
| 29 | even if that machine is itself one of several dozen virtual machines on |
| @@ -34,17 +34,17 @@ | |
| 34 | #!/usr/bin/fossil |
| 35 | repository: /fossil/fossil.fossil |
| 36 | </pre></blockquote> |
| 37 | |
| 38 | Server (3) runs as a CGI script on a shared hosting account at |
| 39 | <a href="http://www.he.net/">Hurricane Electric</a> in Fremont, CA. |
| 40 | This server demonstrates the ability of |
| 41 | Fossil to run on an economical shared-host web account with no |
| 42 | privileges beyond port 80 HTTP access and CGI. It is not necessary |
| 43 | to have a dedicated computer with administrator privileges to run Fossil. |
| 44 | As far as we are aware, |
| 45 | Fossil is the only full-featured configuration management system |
| 46 | that can run in |
| 47 | such a restricted environment. The CGI script that runs on the |
| 48 | Hurricane Electric server is the same as the CGI script shown above, |
| 49 | except that the pathnames are modified to suit the environment: |
| 50 | |
| 51 |
| --- www/selfhost.wiki | |
| +++ www/selfhost.wiki | |
| @@ -7,23 +7,23 @@ | |
| 7 | 2. [http://www2.fossil-scm.org/] |
| 8 | 3. [http://www3.fossil-scm.org/site.cgi] |
| 9 | |
| 10 | |
| 11 | The canonical repository is (1). Repositories (2) and (3) automatically |
| 12 | stay in synchronization with (1) via a |
| 13 | <a href="http://en.wikipedia.org/wiki/Cron">cron job</a> that invokes |
| 14 | "fossil sync" at regular intervals. |
| 15 | |
| 16 | Note that the two secondary repositories are more than just read-only mirrors. |
| 17 | All three servers support full read/write capabilities. |
| 18 | Changes (such as new tickets or wiki or check-ins) can be implemented |
| 19 | on any of the three servers and those changes automatically propagate to the |
| 20 | other two servers. |
| 21 | |
| 22 | Server (1) runs as a CGI script on a |
| 23 | <a href="http://www.linode.com/">Linode 1024</a> located in Dallas, TX |
| 24 | - on the same virtual machine that |
| 25 | hosts <a href="http://www.sqlite.org/">SQLite</a> and over a |
| 26 | dozen other smaller projects. This demonstrates that Fossil can run on |
| 27 | a low-power host processor. |
| 28 | Multiple fossil-based projects can easily be hosted on the same machine, |
| 29 | even if that machine is itself one of several dozen virtual machines on |
| @@ -34,17 +34,17 @@ | |
| 34 | #!/usr/bin/fossil |
| 35 | repository: /fossil/fossil.fossil |
| 36 | </pre></blockquote> |
| 37 | |
| 38 | Server (3) runs as a CGI script on a shared hosting account at |
| 39 | <a href="http://www.he.net/">Hurricane Electric</a> in Fremont, CA. |
| 40 | This server demonstrates the ability of |
| 41 | Fossil to run on an economical shared-host web account with no |
| 42 | privileges beyond port 80 HTTP access and CGI. It is not necessary |
| 43 | to have a dedicated computer with administrator privileges to run Fossil. |
| 44 | As far as we are aware, |
| 45 | Fossil is the only full-featured configuration management system |
| 46 | that can run in |
| 47 | such a restricted environment. The CGI script that runs on the |
| 48 | Hurricane Electric server is the same as the CGI script shown above, |
| 49 | except that the pathnames are modified to suit the environment: |
| 50 | |
| 51 |
+21
-21
| --- www/server.wiki | ||
| +++ www/server.wiki | ||
| @@ -2,11 +2,11 @@ | ||
| 2 | 2 | <h2>Introduction</h2><blockquote> |
| 3 | 3 | <p>A server is not necessary to use Fossil, but a server does help in collaborating with |
| 4 | 4 | peers. A Fossil server also works well as a complete website for a project. |
| 5 | 5 | For example, the complete [https://www.fossil-scm.org/] website, including the |
| 6 | 6 | page you are now reading, |
| 7 | -is just a Fossil server displaying the content of the | |
| 7 | +is just a Fossil server displaying the content of the | |
| 8 | 8 | self-hosting repository for Fossil.</p> |
| 9 | 9 | <p>This article is a guide for setting up your own Fossil server. |
| 10 | 10 | <p>See "[./aboutcgi.wiki|How CGI Works In Fossil]" for background |
| 11 | 11 | information on the underlying CGI technology. |
| 12 | 12 | See "[./sync.wiki|The Fossil Sync Protocol]" for information on the |
| @@ -18,11 +18,11 @@ | ||
| 18 | 18 | <li>A stand-alone server |
| 19 | 19 | <li>Using inetd or xinetd or stunnel |
| 20 | 20 | <li>CGI |
| 21 | 21 | <li>SCGI (a.k.a. SimpleCGI) |
| 22 | 22 | </ol> |
| 23 | -Each of these can serve either a single repository, or a directory hierarchy | |
| 23 | +Each of these can serve either a single repository, or a directory hierarchy | |
| 24 | 24 | containing many repositories with names ending in ".fossil". |
| 25 | 25 | </blockquote> |
| 26 | 26 | <a name="standalone"></a> |
| 27 | 27 | <h2>Standalone server</h2><blockquote> |
| 28 | 28 | The easiest way to set up a Fossil server is to use either the |
| @@ -34,16 +34,16 @@ | ||
| 34 | 34 | <p> |
| 35 | 35 | The <i>REPOSITORY</i> argument is either the name of the repository file, or |
| 36 | 36 | a directory containing many repositories. |
| 37 | 37 | Both of these commands start a Fossil server, usually on TCP port 8080, though |
| 38 | 38 | a higher numbered port might also be used if 8080 is already occupied. You can |
| 39 | -access these using URLs of the form <b>http://localhost:8080/</b>, or if | |
| 39 | +access these using URLs of the form <b>http://localhost:8080/</b>, or if | |
| 40 | 40 | <i>REPOSITORY</i> is a directory, URLs of the form |
| 41 | 41 | <b>http://localhost:8080/</b><i>repo</i><b>/</b> where <i>repo</i> is the base |
| 42 | 42 | name of the repository file without the ".fossil" suffix. |
| 43 | 43 | The difference between "ui" and "server" is that "ui" will |
| 44 | -also start a web browser and points it | |
| 44 | +also start a web browser and point it | |
| 45 | 45 | to the URL mentioned above, and the "ui" command binds to |
| 46 | 46 | the loopback IP address (127.0.0.1) only so that the "ui" command cannot be |
| 47 | 47 | used to serve content to a different machine. |
| 48 | 48 | </p> |
| 49 | 49 | <p> |
| @@ -75,23 +75,23 @@ | ||
| 75 | 75 | need to modify the pathnames for your particular setup. |
| 76 | 76 | The final argument is either the name of the fossil repository to be served, |
| 77 | 77 | or a directory containing multiple repositories. |
| 78 | 78 | </p> |
| 79 | 79 | <p> |
| 80 | -If you use a non-standard TCP port on | |
| 81 | -systems where the port-specification must be a symbolic name and cannot be | |
| 80 | +If you use a non-standard TCP port on | |
| 81 | +systems where the port-specification must be a symbolic name and cannot be | |
| 82 | 82 | numeric, add the desired name and port to /etc/services. For example, if |
| 83 | 83 | you want your Fossil server running on TCP port 12345 instead of 80, you |
| 84 | 84 | will need to add: |
| 85 | 85 | <blockquote> |
| 86 | 86 | <pre> |
| 87 | 87 | fossil 12345/tcp #fossil server |
| 88 | 88 | </pre> |
| 89 | 89 | </blockquote> |
| 90 | -and use the symbolic name ('fossil' in this example) instead of the numeral ('12345') | |
| 91 | -in inetd.conf. For details, see the relevant section in your system's documentation, e.g. | |
| 92 | -the [https://www.freebsd.org/doc/en/books/handbook/network-inetd.html|FreeBSD Handbook] in | |
| 90 | +and use the symbolic name ('fossil' in this example) instead of the numeral ('12345') | |
| 91 | +in inetd.conf. For details, see the relevant section in your system's documentation, e.g. | |
| 92 | +the [https://www.freebsd.org/doc/en/books/handbook/network-inetd.html|FreeBSD Handbook] in | |
| 93 | 93 | case you use FreeBSD. |
| 94 | 94 | </p> |
| 95 | 95 | <p> |
| 96 | 96 | If your system is running xinetd, then the configuration is likely to be |
| 97 | 97 | in the file "/etc/xinetd.conf" or in a subfile of "/etc/xinetd.d". |
| @@ -119,11 +119,11 @@ | ||
| 119 | 119 | jail for the user who owns the fossil repository before reading any information |
| 120 | 120 | off of the wire. |
| 121 | 121 | </p> |
| 122 | 122 | <p> |
| 123 | 123 | Inetd or xinetd must be enabled, and must be (re)started whenever their configuration |
| 124 | -changes - consult your system's documentation for details. | |
| 124 | +changes - consult your system's documentation for details. | |
| 125 | 125 | </p> |
| 126 | 126 | <p> |
| 127 | 127 | [https://www.stunnel.org/ | Stunnel version 5] is an inetd-like process that |
| 128 | 128 | accepts and decodes SSL-encrypted connections. Fossil can be run directly from |
| 129 | 129 | stunnel in a manner similar to inetd and xinetd. This can be used to provide |
| @@ -137,15 +137,15 @@ | ||
| 137 | 137 | TIMEOUTclose = 0 |
| 138 | 138 | exec = /usr/bin/fossil |
| 139 | 139 | execargs = /usr/bin/fossil http /home/fossil/ubercool.fossil --https |
| 140 | 140 | </nowiki></pre></blockquote> |
| 141 | 141 | See the stunnel5 documentation for further details about the /etc/stunnel/stunnel.conf |
| 142 | -configuration file. Note that the [/help/http|fossil http] command should include | |
| 142 | +configuration file. Note that the [/help/http|fossil http] command should include | |
| 143 | 143 | the --https option to let Fossil know to use "https" instead of "http" as the scheme |
| 144 | 144 | on generated hyperlinks. |
| 145 | 145 | <p> |
| 146 | -Using inetd or xinetd or stunnel is a more complex setup | |
| 146 | +Using inetd or xinetd or stunnel is a more complex setup | |
| 147 | 147 | than the "standalone" server, but it has the |
| 148 | 148 | advantage of only using system resources when an actual connection is |
| 149 | 149 | attempted. If no-one ever connects to that port, a Fossil server will |
| 150 | 150 | not (automatically) run. It has the disadvantage of requiring "root" access |
| 151 | 151 | and therefore may not normally be available to lower-priced "shared" servers |
| @@ -155,11 +155,11 @@ | ||
| 155 | 155 | <a name="cgi"></a> |
| 156 | 156 | <h2>Fossil as CGI</h2><blockquote> |
| 157 | 157 | <p> |
| 158 | 158 | A Fossil server can also be run from an ordinary web server as a CGI program. |
| 159 | 159 | This feature allows Fossil to be seamlessly integrated into a larger website. |
| 160 | -CGI is how the [./selfhost.wiki | self-hosting fossil repositories] are | |
| 160 | +CGI is how the [./selfhost.wiki | self-hosting fossil repositories] are | |
| 161 | 161 | implemented. |
| 162 | 162 | </p> |
| 163 | 163 | <p> |
| 164 | 164 | To run Fossil as CGI, create a CGI script (here called "repo") in the CGI directory |
| 165 | 165 | of your web server and having content like this: |
| @@ -184,12 +184,12 @@ | ||
| 184 | 184 | script itself must be executable for the user under which it will run (which often differs |
| 185 | 185 | from the one running the web server - consult your site's documentation or administrator).</li> |
| 186 | 186 | <li>The repository file AND the directory containing it must be writable by the same account |
| 187 | 187 | which executes the Fossil binary (again, this might differ from the WWW user). The directory |
| 188 | 188 | needs to be writable so that sqlite can write its journal files.</li> |
| 189 | -<li>Fossil must be able to create temporary files, the default directory | |
| 190 | -for which depends on the OS. When the CGI process is operating within | |
| 189 | +<li>Fossil must be able to create temporary files, the default directory | |
| 190 | +for which depends on the OS. When the CGI process is operating within | |
| 191 | 191 | a chroot, ensure that this directory exists and is readable/writeable |
| 192 | 192 | by the user who executes the Fossil binary.</li> |
| 193 | 193 | </ul> |
| 194 | 194 | </p> |
| 195 | 195 | |
| @@ -219,11 +219,11 @@ | ||
| 219 | 219 | |
| 220 | 220 | <a name="scgi"></a> |
| 221 | 221 | <h2>Fossil as SCGI</h2><blockquote> |
| 222 | 222 | |
| 223 | 223 | <p> |
| 224 | -The [/help/server|fossil server] command, described above as a way of | |
| 224 | +The [/help/server|fossil server] command, described above as a way of | |
| 225 | 225 | starting a stand-alone web server, can also be used for SCGI. Simply add |
| 226 | 226 | the --scgi command-line option and the stand-alone server will interpret |
| 227 | 227 | and respond to the SimpleCGI or SCGI protocol rather than raw HTTP. This can |
| 228 | 228 | be used in combination with a webserver (such as [http://nginx.org|Nginx]) |
| 229 | 229 | that does not support CGI. A typical Nginx configuration to support SCGI |
| @@ -284,27 +284,27 @@ | ||
| 284 | 284 | </blockquote> |
| 285 | 285 | |
| 286 | 286 | <a name="loadmgmt"></a> |
| 287 | 287 | <h2>Managing Server Load</h2><blockquote> |
| 288 | 288 | <p> |
| 289 | -A Fossil server is very efficient and normally presents a very light | |
| 289 | +A Fossil server is very efficient and normally presents a very light | |
| 290 | 290 | load on the server. |
| 291 | 291 | The Fossil [./selfhost.wiki | self-hosting server] is a 1/24th slice VM at |
| 292 | 292 | [http://www.linode.com | Linode.com] hosting 65 other repositories in |
| 293 | 293 | addition to Fossil (and including some very high-traffic sites such |
| 294 | 294 | as [http://www.sqlite.org] and [http://system.data.sqlite.org]) and |
| 295 | 295 | it has a typical load of 0.05 to 0.1. A single HTTP request to Fossil |
| 296 | 296 | normally takes less than 10 milliseconds of CPU time to complete. So |
| 297 | -requests can be arriving at a continuous rate of 20 or more per second | |
| 297 | +requests can be arriving at a continuous rate of 20 or more per second | |
| 298 | 298 | and the CPU can still be mostly idle. |
| 299 | 299 | <p> |
| 300 | -However, there are some Fossil web pages that can consume large | |
| 300 | +However, there are some Fossil web pages that can consume large | |
| 301 | 301 | amounts of CPU time, especially on repositories with a large number |
| 302 | 302 | of files or with long revision histories. High CPU usage pages include |
| 303 | 303 | [/help?cmd=/zip | /zip], [/help?cmd=/tarball | /tarball], |
| 304 | 304 | [/help?cmd=/annotate | /annotate] and others. On very large repositories, |
| 305 | -these commands can take 15 seconds or more of CPU time. | |
| 305 | +these commands can take 15 seconds or more of CPU time. | |
| 306 | 306 | If these kinds of requests arrive too quickly, the load average on the |
| 307 | 307 | server can grow dramatically, making the server unresponsive. |
| 308 | 308 | <p> |
| 309 | 309 | Fossil provides two capabilities to help avoid server overload problems |
| 310 | 310 | due to excessive requests to expensive pages: |
| @@ -312,11 +312,11 @@ | ||
| 312 | 312 | <li><p>An optional cache is available that remembers the 10 most recently |
| 313 | 313 | requested /zip or /tarball pages and returns the precomputed answer |
| 314 | 314 | if the same page is requested again. |
| 315 | 315 | <li><p>Page requests can be configured to fail with a |
| 316 | 316 | [http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.3 | "503 Server Overload"] |
| 317 | - HTTP error if an expensive request is received while the host load | |
| 317 | + HTTP error if an expensive request is received while the host load | |
| 318 | 318 | average is too high. |
| 319 | 319 | </ol> |
| 320 | 320 | Both of these load-control mechanisms are turned off by default, but they |
| 321 | 321 | are recommended for high-traffic sites. |
| 322 | 322 | <p> |
| 323 | 323 |
| --- www/server.wiki | |
| +++ www/server.wiki | |
| @@ -2,11 +2,11 @@ | |
| 2 | <h2>Introduction</h2><blockquote> |
| 3 | <p>A server is not necessary to use Fossil, but a server does help in collaborating with |
| 4 | peers. A Fossil server also works well as a complete website for a project. |
| 5 | For example, the complete [https://www.fossil-scm.org/] website, including the |
| 6 | page you are now reading, |
| 7 | is just a Fossil server displaying the content of the |
| 8 | self-hosting repository for Fossil.</p> |
| 9 | <p>This article is a guide for setting up your own Fossil server. |
| 10 | <p>See "[./aboutcgi.wiki|How CGI Works In Fossil]" for background |
| 11 | information on the underlying CGI technology. |
| 12 | See "[./sync.wiki|The Fossil Sync Protocol]" for information on the |
| @@ -18,11 +18,11 @@ | |
| 18 | <li>A stand-alone server |
| 19 | <li>Using inetd or xinetd or stunnel |
| 20 | <li>CGI |
| 21 | <li>SCGI (a.k.a. SimpleCGI) |
| 22 | </ol> |
| 23 | Each of these can serve either a single repository, or a directory hierarchy |
| 24 | containing many repositories with names ending in ".fossil". |
| 25 | </blockquote> |
| 26 | <a name="standalone"></a> |
| 27 | <h2>Standalone server</h2><blockquote> |
| 28 | The easiest way to set up a Fossil server is to use either the |
| @@ -34,16 +34,16 @@ | |
| 34 | <p> |
| 35 | The <i>REPOSITORY</i> argument is either the name of the repository file, or |
| 36 | a directory containing many repositories. |
| 37 | Both of these commands start a Fossil server, usually on TCP port 8080, though |
| 38 | a higher numbered port might also be used if 8080 is already occupied. You can |
| 39 | access these using URLs of the form <b>http://localhost:8080/</b>, or if |
| 40 | <i>REPOSITORY</i> is a directory, URLs of the form |
| 41 | <b>http://localhost:8080/</b><i>repo</i><b>/</b> where <i>repo</i> is the base |
| 42 | name of the repository file without the ".fossil" suffix. |
| 43 | The difference between "ui" and "server" is that "ui" will |
| 44 | also start a web browser and points it |
| 45 | to the URL mentioned above, and the "ui" command binds to |
| 46 | the loopback IP address (127.0.0.1) only so that the "ui" command cannot be |
| 47 | used to serve content to a different machine. |
| 48 | </p> |
| 49 | <p> |
| @@ -75,23 +75,23 @@ | |
| 75 | need to modify the pathnames for your particular setup. |
| 76 | The final argument is either the name of the fossil repository to be served, |
| 77 | or a directory containing multiple repositories. |
| 78 | </p> |
| 79 | <p> |
| 80 | If you use a non-standard TCP port on |
| 81 | systems where the port-specification must be a symbolic name and cannot be |
| 82 | numeric, add the desired name and port to /etc/services. For example, if |
| 83 | you want your Fossil server running on TCP port 12345 instead of 80, you |
| 84 | will need to add: |
| 85 | <blockquote> |
| 86 | <pre> |
| 87 | fossil 12345/tcp #fossil server |
| 88 | </pre> |
| 89 | </blockquote> |
| 90 | and use the symbolic name ('fossil' in this example) instead of the numeral ('12345') |
| 91 | in inetd.conf. For details, see the relevant section in your system's documentation, e.g. |
| 92 | the [https://www.freebsd.org/doc/en/books/handbook/network-inetd.html|FreeBSD Handbook] in |
| 93 | case you use FreeBSD. |
| 94 | </p> |
| 95 | <p> |
| 96 | If your system is running xinetd, then the configuration is likely to be |
| 97 | in the file "/etc/xinetd.conf" or in a subfile of "/etc/xinetd.d". |
| @@ -119,11 +119,11 @@ | |
| 119 | jail for the user who owns the fossil repository before reading any information |
| 120 | off of the wire. |
| 121 | </p> |
| 122 | <p> |
| 123 | Inetd or xinetd must be enabled, and must be (re)started whenever their configuration |
| 124 | changes - consult your system's documentation for details. |
| 125 | </p> |
| 126 | <p> |
| 127 | [https://www.stunnel.org/ | Stunnel version 5] is an inetd-like process that |
| 128 | accepts and decodes SSL-encrypted connections. Fossil can be run directly from |
| 129 | stunnel in a manner similar to inetd and xinetd. This can be used to provide |
| @@ -137,15 +137,15 @@ | |
| 137 | TIMEOUTclose = 0 |
| 138 | exec = /usr/bin/fossil |
| 139 | execargs = /usr/bin/fossil http /home/fossil/ubercool.fossil --https |
| 140 | </nowiki></pre></blockquote> |
| 141 | See the stunnel5 documentation for further details about the /etc/stunnel/stunnel.conf |
| 142 | configuration file. Note that the [/help/http|fossil http] command should include |
| 143 | the --https option to let Fossil know to use "https" instead of "http" as the scheme |
| 144 | on generated hyperlinks. |
| 145 | <p> |
| 146 | Using inetd or xinetd or stunnel is a more complex setup |
| 147 | than the "standalone" server, but it has the |
| 148 | advantage of only using system resources when an actual connection is |
| 149 | attempted. If no-one ever connects to that port, a Fossil server will |
| 150 | not (automatically) run. It has the disadvantage of requiring "root" access |
| 151 | and therefore may not normally be available to lower-priced "shared" servers |
| @@ -155,11 +155,11 @@ | |
| 155 | <a name="cgi"></a> |
| 156 | <h2>Fossil as CGI</h2><blockquote> |
| 157 | <p> |
| 158 | A Fossil server can also be run from an ordinary web server as a CGI program. |
| 159 | This feature allows Fossil to be seamlessly integrated into a larger website. |
| 160 | CGI is how the [./selfhost.wiki | self-hosting fossil repositories] are |
| 161 | implemented. |
| 162 | </p> |
| 163 | <p> |
| 164 | To run Fossil as CGI, create a CGI script (here called "repo") in the CGI directory |
| 165 | of your web server and having content like this: |
| @@ -184,12 +184,12 @@ | |
| 184 | script itself must be executable for the user under which it will run (which often differs |
| 185 | from the one running the web server - consult your site's documentation or administrator).</li> |
| 186 | <li>The repository file AND the directory containing it must be writable by the same account |
| 187 | which executes the Fossil binary (again, this might differ from the WWW user). The directory |
| 188 | needs to be writable so that sqlite can write its journal files.</li> |
| 189 | <li>Fossil must be able to create temporary files, the default directory |
| 190 | for which depends on the OS. When the CGI process is operating within |
| 191 | a chroot, ensure that this directory exists and is readable/writeable |
| 192 | by the user who executes the Fossil binary.</li> |
| 193 | </ul> |
| 194 | </p> |
| 195 | |
| @@ -219,11 +219,11 @@ | |
| 219 | |
| 220 | <a name="scgi"></a> |
| 221 | <h2>Fossil as SCGI</h2><blockquote> |
| 222 | |
| 223 | <p> |
| 224 | The [/help/server|fossil server] command, described above as a way of |
| 225 | starting a stand-alone web server, can also be used for SCGI. Simply add |
| 226 | the --scgi command-line option and the stand-alone server will interpret |
| 227 | and respond to the SimpleCGI or SCGI protocol rather than raw HTTP. This can |
| 228 | be used in combination with a webserver (such as [http://nginx.org|Nginx]) |
| 229 | that does not support CGI. A typical Nginx configuration to support SCGI |
| @@ -284,27 +284,27 @@ | |
| 284 | </blockquote> |
| 285 | |
| 286 | <a name="loadmgmt"></a> |
| 287 | <h2>Managing Server Load</h2><blockquote> |
| 288 | <p> |
| 289 | A Fossil server is very efficient and normally presents a very light |
| 290 | load on the server. |
| 291 | The Fossil [./selfhost.wiki | self-hosting server] is a 1/24th slice VM at |
| 292 | [http://www.linode.com | Linode.com] hosting 65 other repositories in |
| 293 | addition to Fossil (and including some very high-traffic sites such |
| 294 | as [http://www.sqlite.org] and [http://system.data.sqlite.org]) and |
| 295 | it has a typical load of 0.05 to 0.1. A single HTTP request to Fossil |
| 296 | normally takes less than 10 milliseconds of CPU time to complete. So |
| 297 | requests can be arriving at a continuous rate of 20 or more per second |
| 298 | and the CPU can still be mostly idle. |
| 299 | <p> |
| 300 | However, there are some Fossil web pages that can consume large |
| 301 | amounts of CPU time, especially on repositories with a large number |
| 302 | of files or with long revision histories. High CPU usage pages include |
| 303 | [/help?cmd=/zip | /zip], [/help?cmd=/tarball | /tarball], |
| 304 | [/help?cmd=/annotate | /annotate] and others. On very large repositories, |
| 305 | these commands can take 15 seconds or more of CPU time. |
| 306 | If these kinds of requests arrive too quickly, the load average on the |
| 307 | server can grow dramatically, making the server unresponsive. |
| 308 | <p> |
| 309 | Fossil provides two capabilities to help avoid server overload problems |
| 310 | due to excessive requests to expensive pages: |
| @@ -312,11 +312,11 @@ | |
| 312 | <li><p>An optional cache is available that remembers the 10 most recently |
| 313 | requested /zip or /tarball pages and returns the precomputed answer |
| 314 | if the same page is requested again. |
| 315 | <li><p>Page requests can be configured to fail with a |
| 316 | [http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.3 | "503 Server Overload"] |
| 317 | HTTP error if an expensive request is received while the host load |
| 318 | average is too high. |
| 319 | </ol> |
| 320 | Both of these load-control mechanisms are turned off by default, but they |
| 321 | are recommended for high-traffic sites. |
| 322 | <p> |
| 323 |
| --- www/server.wiki | |
| +++ www/server.wiki | |
| @@ -2,11 +2,11 @@ | |
| 2 | <h2>Introduction</h2><blockquote> |
| 3 | <p>A server is not necessary to use Fossil, but a server does help in collaborating with |
| 4 | peers. A Fossil server also works well as a complete website for a project. |
| 5 | For example, the complete [https://www.fossil-scm.org/] website, including the |
| 6 | page you are now reading, |
| 7 | is just a Fossil server displaying the content of the |
| 8 | self-hosting repository for Fossil.</p> |
| 9 | <p>This article is a guide for setting up your own Fossil server. |
| 10 | <p>See "[./aboutcgi.wiki|How CGI Works In Fossil]" for background |
| 11 | information on the underlying CGI technology. |
| 12 | See "[./sync.wiki|The Fossil Sync Protocol]" for information on the |
| @@ -18,11 +18,11 @@ | |
| 18 | <li>A stand-alone server |
| 19 | <li>Using inetd or xinetd or stunnel |
| 20 | <li>CGI |
| 21 | <li>SCGI (a.k.a. SimpleCGI) |
| 22 | </ol> |
| 23 | Each of these can serve either a single repository, or a directory hierarchy |
| 24 | containing many repositories with names ending in ".fossil". |
| 25 | </blockquote> |
| 26 | <a name="standalone"></a> |
| 27 | <h2>Standalone server</h2><blockquote> |
| 28 | The easiest way to set up a Fossil server is to use either the |
| @@ -34,16 +34,16 @@ | |
| 34 | <p> |
| 35 | The <i>REPOSITORY</i> argument is either the name of the repository file, or |
| 36 | a directory containing many repositories. |
| 37 | Both of these commands start a Fossil server, usually on TCP port 8080, though |
| 38 | a higher numbered port might also be used if 8080 is already occupied. You can |
| 39 | access these using URLs of the form <b>http://localhost:8080/</b>, or if |
| 40 | <i>REPOSITORY</i> is a directory, URLs of the form |
| 41 | <b>http://localhost:8080/</b><i>repo</i><b>/</b> where <i>repo</i> is the base |
| 42 | name of the repository file without the ".fossil" suffix. |
| 43 | The difference between "ui" and "server" is that "ui" will |
| 44 | also start a web browser and point it |
| 45 | to the URL mentioned above, and the "ui" command binds to |
| 46 | the loopback IP address (127.0.0.1) only so that the "ui" command cannot be |
| 47 | used to serve content to a different machine. |
| 48 | </p> |
| 49 | <p> |
| @@ -75,23 +75,23 @@ | |
| 75 | need to modify the pathnames for your particular setup. |
| 76 | The final argument is either the name of the fossil repository to be served, |
| 77 | or a directory containing multiple repositories. |
| 78 | </p> |
| 79 | <p> |
| 80 | If you use a non-standard TCP port on |
| 81 | systems where the port-specification must be a symbolic name and cannot be |
| 82 | numeric, add the desired name and port to /etc/services. For example, if |
| 83 | you want your Fossil server running on TCP port 12345 instead of 80, you |
| 84 | will need to add: |
| 85 | <blockquote> |
| 86 | <pre> |
| 87 | fossil 12345/tcp #fossil server |
| 88 | </pre> |
| 89 | </blockquote> |
| 90 | and use the symbolic name ('fossil' in this example) instead of the numeral ('12345') |
| 91 | in inetd.conf. For details, see the relevant section in your system's documentation, e.g. |
| 92 | the [https://www.freebsd.org/doc/en/books/handbook/network-inetd.html|FreeBSD Handbook] in |
| 93 | case you use FreeBSD. |
| 94 | </p> |
| 95 | <p> |
| 96 | If your system is running xinetd, then the configuration is likely to be |
| 97 | in the file "/etc/xinetd.conf" or in a subfile of "/etc/xinetd.d". |
| @@ -119,11 +119,11 @@ | |
| 119 | jail for the user who owns the fossil repository before reading any information |
| 120 | off of the wire. |
| 121 | </p> |
| 122 | <p> |
| 123 | Inetd or xinetd must be enabled, and must be (re)started whenever their configuration |
| 124 | changes - consult your system's documentation for details. |
| 125 | </p> |
| 126 | <p> |
| 127 | [https://www.stunnel.org/ | Stunnel version 5] is an inetd-like process that |
| 128 | accepts and decodes SSL-encrypted connections. Fossil can be run directly from |
| 129 | stunnel in a manner similar to inetd and xinetd. This can be used to provide |
| @@ -137,15 +137,15 @@ | |
| 137 | TIMEOUTclose = 0 |
| 138 | exec = /usr/bin/fossil |
| 139 | execargs = /usr/bin/fossil http /home/fossil/ubercool.fossil --https |
| 140 | </nowiki></pre></blockquote> |
| 141 | See the stunnel5 documentation for further details about the /etc/stunnel/stunnel.conf |
| 142 | configuration file. Note that the [/help/http|fossil http] command should include |
| 143 | the --https option to let Fossil know to use "https" instead of "http" as the scheme |
| 144 | on generated hyperlinks. |
| 145 | <p> |
| 146 | Using inetd or xinetd or stunnel is a more complex setup |
| 147 | than the "standalone" server, but it has the |
| 148 | advantage of only using system resources when an actual connection is |
| 149 | attempted. If no-one ever connects to that port, a Fossil server will |
| 150 | not (automatically) run. It has the disadvantage of requiring "root" access |
| 151 | and therefore may not normally be available to lower-priced "shared" servers |
| @@ -155,11 +155,11 @@ | |
| 155 | <a name="cgi"></a> |
| 156 | <h2>Fossil as CGI</h2><blockquote> |
| 157 | <p> |
| 158 | A Fossil server can also be run from an ordinary web server as a CGI program. |
| 159 | This feature allows Fossil to be seamlessly integrated into a larger website. |
| 160 | CGI is how the [./selfhost.wiki | self-hosting fossil repositories] are |
| 161 | implemented. |
| 162 | </p> |
| 163 | <p> |
| 164 | To run Fossil as CGI, create a CGI script (here called "repo") in the CGI directory |
| 165 | of your web server and having content like this: |
| @@ -184,12 +184,12 @@ | |
| 184 | script itself must be executable for the user under which it will run (which often differs |
| 185 | from the one running the web server - consult your site's documentation or administrator).</li> |
| 186 | <li>The repository file AND the directory containing it must be writable by the same account |
| 187 | which executes the Fossil binary (again, this might differ from the WWW user). The directory |
| 188 | needs to be writable so that sqlite can write its journal files.</li> |
| 189 | <li>Fossil must be able to create temporary files, the default directory |
| 190 | for which depends on the OS. When the CGI process is operating within |
| 191 | a chroot, ensure that this directory exists and is readable/writeable |
| 192 | by the user who executes the Fossil binary.</li> |
| 193 | </ul> |
| 194 | </p> |
| 195 | |
| @@ -219,11 +219,11 @@ | |
| 219 | |
| 220 | <a name="scgi"></a> |
| 221 | <h2>Fossil as SCGI</h2><blockquote> |
| 222 | |
| 223 | <p> |
| 224 | The [/help/server|fossil server] command, described above as a way of |
| 225 | starting a stand-alone web server, can also be used for SCGI. Simply add |
| 226 | the --scgi command-line option and the stand-alone server will interpret |
| 227 | and respond to the SimpleCGI or SCGI protocol rather than raw HTTP. This can |
| 228 | be used in combination with a webserver (such as [http://nginx.org|Nginx]) |
| 229 | that does not support CGI. A typical Nginx configuration to support SCGI |
| @@ -284,27 +284,27 @@ | |
| 284 | </blockquote> |
| 285 | |
| 286 | <a name="loadmgmt"></a> |
| 287 | <h2>Managing Server Load</h2><blockquote> |
| 288 | <p> |
| 289 | A Fossil server is very efficient and normally presents a very light |
| 290 | load on the server. |
| 291 | The Fossil [./selfhost.wiki | self-hosting server] is a 1/24th slice VM at |
| 292 | [http://www.linode.com | Linode.com] hosting 65 other repositories in |
| 293 | addition to Fossil (and including some very high-traffic sites such |
| 294 | as [http://www.sqlite.org] and [http://system.data.sqlite.org]) and |
| 295 | it has a typical load of 0.05 to 0.1. A single HTTP request to Fossil |
| 296 | normally takes less than 10 milliseconds of CPU time to complete. So |
| 297 | requests can be arriving at a continuous rate of 20 or more per second |
| 298 | and the CPU can still be mostly idle. |
| 299 | <p> |
| 300 | However, there are some Fossil web pages that can consume large |
| 301 | amounts of CPU time, especially on repositories with a large number |
| 302 | of files or with long revision histories. High CPU usage pages include |
| 303 | [/help?cmd=/zip | /zip], [/help?cmd=/tarball | /tarball], |
| 304 | [/help?cmd=/annotate | /annotate] and others. On very large repositories, |
| 305 | these commands can take 15 seconds or more of CPU time. |
| 306 | If these kinds of requests arrive too quickly, the load average on the |
| 307 | server can grow dramatically, making the server unresponsive. |
| 308 | <p> |
| 309 | Fossil provides two capabilities to help avoid server overload problems |
| 310 | due to excessive requests to expensive pages: |
| @@ -312,11 +312,11 @@ | |
| 312 | <li><p>An optional cache is available that remembers the 10 most recently |
| 313 | requested /zip or /tarball pages and returns the precomputed answer |
| 314 | if the same page is requested again. |
| 315 | <li><p>Page requests can be configured to fail with a |
| 316 | [http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.3 | "503 Server Overload"] |
| 317 | HTTP error if an expensive request is received while the host load |
| 318 | average is too high. |
| 319 | </ol> |
| 320 | Both of these load-control mechanisms are turned off by default, but they |
| 321 | are recommended for high-traffic sites. |
| 322 | <p> |
| 323 |
+3
-3
| --- www/settings.wiki | ||
| +++ www/settings.wiki | ||
| @@ -4,11 +4,11 @@ | ||
| 4 | 4 | |
| 5 | 5 | Settings control the behaviour of fossil. They are set with the |
| 6 | 6 | <tt>fossil settings</tt> command, or through the web interface in |
| 7 | 7 | the Settings page in the Admin section. |
| 8 | 8 | |
| 9 | -For a list of all settings, view the Settings page, or type | |
| 9 | +For a list of all settings, view the Settings page, or type | |
| 10 | 10 | <tt>fossil help settings</tt> from the command line. |
| 11 | 11 | |
| 12 | 12 | |
| 13 | 13 | <h3>Repository settings</h3> |
| 14 | 14 | |
| @@ -16,17 +16,17 @@ | ||
| 16 | 16 | a subset of settings are copied to your local repository. |
| 17 | 17 | |
| 18 | 18 | If you make a change to a setting on your local repository, it is not |
| 19 | 19 | synced back to the server when you <tt>push</tt> or <tt>sync</tt>. If |
| 20 | 20 | you make a change on the server, you need to manually make the change on |
| 21 | -all repositories which are cloned from this repository. | |
| 21 | +all repositories which are cloned from this repository. | |
| 22 | 22 | |
| 23 | 23 | You can also set a setting globally on your local machine. The value |
| 24 | 24 | will be used for all repositories cloned to your machine, unless |
| 25 | 25 | overridden explicitly in a particular repository. Global settings can be |
| 26 | 26 | set by using the <tt>-global</tt> option on the <tt>fossil settings</tt> |
| 27 | -command. | |
| 27 | +command. | |
| 28 | 28 | |
| 29 | 29 | <h3>"Versionable" settings</h3> |
| 30 | 30 | |
| 31 | 31 | Most of the settings control the behaviour of fossil on your local |
| 32 | 32 | machine, largely acting to reflect your preference on how you want to |
| 33 | 33 |
| --- www/settings.wiki | |
| +++ www/settings.wiki | |
| @@ -4,11 +4,11 @@ | |
| 4 | |
| 5 | Settings control the behaviour of fossil. They are set with the |
| 6 | <tt>fossil settings</tt> command, or through the web interface in |
| 7 | the Settings page in the Admin section. |
| 8 | |
| 9 | For a list of all settings, view the Settings page, or type |
| 10 | <tt>fossil help settings</tt> from the command line. |
| 11 | |
| 12 | |
| 13 | <h3>Repository settings</h3> |
| 14 | |
| @@ -16,17 +16,17 @@ | |
| 16 | a subset of settings are copied to your local repository. |
| 17 | |
| 18 | If you make a change to a setting on your local repository, it is not |
| 19 | synced back to the server when you <tt>push</tt> or <tt>sync</tt>. If |
| 20 | you make a change on the server, you need to manually make the change on |
| 21 | all repositories which are cloned from this repository. |
| 22 | |
| 23 | You can also set a setting globally on your local machine. The value |
| 24 | will be used for all repositories cloned to your machine, unless |
| 25 | overridden explicitly in a particular repository. Global settings can be |
| 26 | set by using the <tt>-global</tt> option on the <tt>fossil settings</tt> |
| 27 | command. |
| 28 | |
| 29 | <h3>"Versionable" settings</h3> |
| 30 | |
| 31 | Most of the settings control the behaviour of fossil on your local |
| 32 | machine, largely acting to reflect your preference on how you want to |
| 33 |
| --- www/settings.wiki | |
| +++ www/settings.wiki | |
| @@ -4,11 +4,11 @@ | |
| 4 | |
| 5 | Settings control the behaviour of fossil. They are set with the |
| 6 | <tt>fossil settings</tt> command, or through the web interface in |
| 7 | the Settings page in the Admin section. |
| 8 | |
| 9 | For a list of all settings, view the Settings page, or type |
| 10 | <tt>fossil help settings</tt> from the command line. |
| 11 | |
| 12 | |
| 13 | <h3>Repository settings</h3> |
| 14 | |
| @@ -16,17 +16,17 @@ | |
| 16 | a subset of settings are copied to your local repository. |
| 17 | |
| 18 | If you make a change to a setting on your local repository, it is not |
| 19 | synced back to the server when you <tt>push</tt> or <tt>sync</tt>. If |
| 20 | you make a change on the server, you need to manually make the change on |
| 21 | all repositories which are cloned from this repository. |
| 22 | |
| 23 | You can also set a setting globally on your local machine. The value |
| 24 | will be used for all repositories cloned to your machine, unless |
| 25 | overridden explicitly in a particular repository. Global settings can be |
| 26 | set by using the <tt>-global</tt> option on the <tt>fossil settings</tt> |
| 27 | command. |
| 28 | |
| 29 | <h3>"Versionable" settings</h3> |
| 30 | |
| 31 | Most of the settings control the behaviour of fossil on your local |
| 32 | machine, largely acting to reflect your preference on how you want to |
| 33 |
+10
-10
| --- www/shunning.wiki | ||
| +++ www/shunning.wiki | ||
| @@ -2,11 +2,11 @@ | ||
| 2 | 2 | <h1 align="center">Deleting Content From Fossil</h1> |
| 3 | 3 | |
| 4 | 4 | Fossil is designed to keep all historical content forever. Users |
| 5 | 5 | of Fossil are discouraged from "deleting" content simply because it |
| 6 | 6 | has become obsolete. Old content is part of the historical record |
| 7 | -(part of the "fossil record") and should be maintained indefinitely. | |
| 7 | +(part of the "fossil record") and should be maintained indefinitely. | |
| 8 | 8 | Such is the design intent of Fossil. |
| 9 | 9 | |
| 10 | 10 | Nevertheless, there may occasionally arise legitimate reasons for |
| 11 | 11 | deleting content. Such reasons might include: |
| 12 | 12 | |
| @@ -21,35 +21,35 @@ | ||
| 21 | 21 | disrupting the operation of Fossil. |
| 22 | 22 | |
| 23 | 23 | <h2>Shunning</h2> |
| 24 | 24 | |
| 25 | 25 | Fossil provides a mechanism called "shunning" for removing content from |
| 26 | -a repository. | |
| 26 | +a repository. | |
| 27 | 27 | |
| 28 | 28 | Every Fossil repository maintains a list of the SHA1 hash names of |
| 29 | 29 | "shunned" artifacts. |
| 30 | -Fossil will refuse to push or pull any shunned artifact. | |
| 30 | +Fossil will refuse to push or pull any shunned artifact. | |
| 31 | 31 | Furthermore, all shunned artifacts (but not the shunning list |
| 32 | 32 | itself) are removed from the |
| 33 | 33 | repository whenever the repository is reconstructed using the |
| 34 | 34 | "rebuild" command. |
| 35 | 35 | |
| 36 | 36 | <h3>Shunning lists are local state</h3> |
| 37 | 37 | |
| 38 | 38 | The shunning list is part of the local state of a Fossil repository. |
| 39 | -In other words, shunning does not propagate to a remote repository | |
| 39 | +In other words, shunning does not propagate to a remote repository | |
| 40 | 40 | using the normal "sync" mechanism. An artifact can be |
| 41 | 41 | shunned from one repository but be allowed to exist in another. The fact that |
| 42 | 42 | the shunning list does not propagate is a security feature. If the |
| 43 | 43 | shunning list propagated then a malicious user (or |
| 44 | 44 | a bug in the fossil code) might introduce a shun record that would |
| 45 | -propagate through all repositories in a network and permanently | |
| 45 | +propagate through all repositories in a network and permanently | |
| 46 | 46 | destroy vital information. By refusing to propagate the shunning list, |
| 47 | -Fossil ensures that no remote user will ever be able to remove | |
| 47 | +Fossil ensures that no remote user will ever be able to remove | |
| 48 | 48 | information from your personal repositories without your permission. |
| 49 | 49 | |
| 50 | -The shunning list does not propagate to a remote repository | |
| 50 | +The shunning list does not propagate to a remote repository | |
| 51 | 51 | by the normal "sync" mechanism, |
| 52 | 52 | but it is still possible to copy shuns from one repository to another |
| 53 | 53 | using the "configuration" command: |
| 54 | 54 | |
| 55 | 55 | <b>fossil configuration pull shun</b> <i>remote-url</i><br> |
| @@ -56,12 +56,12 @@ | ||
| 56 | 56 | <b>fossil configuration push shun</b> <i>remote-url</i> |
| 57 | 57 | |
| 58 | 58 | The two command above will pull or push shunning lists from or to |
| 59 | 59 | the <i>remote-url</i> indicated and merge the lists on the receiving |
| 60 | 60 | end. "Admin" privilege on the remote server is required in order to |
| 61 | -push a shun list. In contrast, the shunning list will be automatically | |
| 62 | -received by default as part of a normal client "pull" operation unless | |
| 61 | +push a shun list. In contrast, the shunning list will be automatically | |
| 62 | +received by default as part of a normal client "pull" operation unless | |
| 63 | 63 | disabled by the "<tt>auto-shun</tt>" setting. |
| 64 | 64 | |
| 65 | 65 | Note that the shunning list remains in the repository even after the |
| 66 | 66 | shunned artifact has been removed. This is to prevent the artifact |
| 67 | 67 | from being reintroduced into the repository the next time it syncs with |
| @@ -68,11 +68,11 @@ | ||
| 68 | 68 | another repository that has not shunned the artifact. |
| 69 | 69 | |
| 70 | 70 | <h3>Managing the shunning list</h3> |
| 71 | 71 | |
| 72 | 72 | The complete shunning list for a repository can be viewed by a user |
| 73 | -with "admin" privilege on the "/shun" URL of the web interface to Fossil. | |
| 73 | +with "admin" privilege on the "/shun" URL of the web interface to Fossil. | |
| 74 | 74 | That URL is accessible under the "Admin" button on the default menu |
| 75 | 75 | bar. Items can be added to or removed from the shunning list. "Sync" |
| 76 | 76 | operations are inhibited as soon as the artifact is added to the |
| 77 | 77 | shunning list, but the content of the artifact is not actually removed |
| 78 | 78 | from the repository until the next time the repository is rebuilt. |
| 79 | 79 |
| --- www/shunning.wiki | |
| +++ www/shunning.wiki | |
| @@ -2,11 +2,11 @@ | |
| 2 | <h1 align="center">Deleting Content From Fossil</h1> |
| 3 | |
| 4 | Fossil is designed to keep all historical content forever. Users |
| 5 | of Fossil are discouraged from "deleting" content simply because it |
| 6 | has become obsolete. Old content is part of the historical record |
| 7 | (part of the "fossil record") and should be maintained indefinitely. |
| 8 | Such is the design intent of Fossil. |
| 9 | |
| 10 | Nevertheless, there may occasionally arise legitimate reasons for |
| 11 | deleting content. Such reasons might include: |
| 12 | |
| @@ -21,35 +21,35 @@ | |
| 21 | disrupting the operation of Fossil. |
| 22 | |
| 23 | <h2>Shunning</h2> |
| 24 | |
| 25 | Fossil provides a mechanism called "shunning" for removing content from |
| 26 | a repository. |
| 27 | |
| 28 | Every Fossil repository maintains a list of the SHA1 hash names of |
| 29 | "shunned" artifacts. |
| 30 | Fossil will refuse to push or pull any shunned artifact. |
| 31 | Furthermore, all shunned artifacts (but not the shunning list |
| 32 | itself) are removed from the |
| 33 | repository whenever the repository is reconstructed using the |
| 34 | "rebuild" command. |
| 35 | |
| 36 | <h3>Shunning lists are local state</h3> |
| 37 | |
| 38 | The shunning list is part of the local state of a Fossil repository. |
| 39 | In other words, shunning does not propagate to a remote repository |
| 40 | using the normal "sync" mechanism. An artifact can be |
| 41 | shunned from one repository but be allowed to exist in another. The fact that |
| 42 | the shunning list does not propagate is a security feature. If the |
| 43 | shunning list propagated then a malicious user (or |
| 44 | a bug in the fossil code) might introduce a shun record that would |
| 45 | propagate through all repositories in a network and permanently |
| 46 | destroy vital information. By refusing to propagate the shunning list, |
| 47 | Fossil ensures that no remote user will ever be able to remove |
| 48 | information from your personal repositories without your permission. |
| 49 | |
| 50 | The shunning list does not propagate to a remote repository |
| 51 | by the normal "sync" mechanism, |
| 52 | but it is still possible to copy shuns from one repository to another |
| 53 | using the "configuration" command: |
| 54 | |
| 55 | <b>fossil configuration pull shun</b> <i>remote-url</i><br> |
| @@ -56,12 +56,12 @@ | |
| 56 | <b>fossil configuration push shun</b> <i>remote-url</i> |
| 57 | |
| 58 | The two command above will pull or push shunning lists from or to |
| 59 | the <i>remote-url</i> indicated and merge the lists on the receiving |
| 60 | end. "Admin" privilege on the remote server is required in order to |
| 61 | push a shun list. In contrast, the shunning list will be automatically |
| 62 | received by default as part of a normal client "pull" operation unless |
| 63 | disabled by the "<tt>auto-shun</tt>" setting. |
| 64 | |
| 65 | Note that the shunning list remains in the repository even after the |
| 66 | shunned artifact has been removed. This is to prevent the artifact |
| 67 | from being reintroduced into the repository the next time it syncs with |
| @@ -68,11 +68,11 @@ | |
| 68 | another repository that has not shunned the artifact. |
| 69 | |
| 70 | <h3>Managing the shunning list</h3> |
| 71 | |
| 72 | The complete shunning list for a repository can be viewed by a user |
| 73 | with "admin" privilege on the "/shun" URL of the web interface to Fossil. |
| 74 | That URL is accessible under the "Admin" button on the default menu |
| 75 | bar. Items can be added to or removed from the shunning list. "Sync" |
| 76 | operations are inhibited as soon as the artifact is added to the |
| 77 | shunning list, but the content of the artifact is not actually removed |
| 78 | from the repository until the next time the repository is rebuilt. |
| 79 |
| --- www/shunning.wiki | |
| +++ www/shunning.wiki | |
| @@ -2,11 +2,11 @@ | |
| 2 | <h1 align="center">Deleting Content From Fossil</h1> |
| 3 | |
| 4 | Fossil is designed to keep all historical content forever. Users |
| 5 | of Fossil are discouraged from "deleting" content simply because it |
| 6 | has become obsolete. Old content is part of the historical record |
| 7 | (part of the "fossil record") and should be maintained indefinitely. |
| 8 | Such is the design intent of Fossil. |
| 9 | |
| 10 | Nevertheless, there may occasionally arise legitimate reasons for |
| 11 | deleting content. Such reasons might include: |
| 12 | |
| @@ -21,35 +21,35 @@ | |
| 21 | disrupting the operation of Fossil. |
| 22 | |
| 23 | <h2>Shunning</h2> |
| 24 | |
| 25 | Fossil provides a mechanism called "shunning" for removing content from |
| 26 | a repository. |
| 27 | |
| 28 | Every Fossil repository maintains a list of the SHA1 hash names of |
| 29 | "shunned" artifacts. |
| 30 | Fossil will refuse to push or pull any shunned artifact. |
| 31 | Furthermore, all shunned artifacts (but not the shunning list |
| 32 | itself) are removed from the |
| 33 | repository whenever the repository is reconstructed using the |
| 34 | "rebuild" command. |
| 35 | |
| 36 | <h3>Shunning lists are local state</h3> |
| 37 | |
| 38 | The shunning list is part of the local state of a Fossil repository. |
| 39 | In other words, shunning does not propagate to a remote repository |
| 40 | using the normal "sync" mechanism. An artifact can be |
| 41 | shunned from one repository but be allowed to exist in another. The fact that |
| 42 | the shunning list does not propagate is a security feature. If the |
| 43 | shunning list propagated then a malicious user (or |
| 44 | a bug in the fossil code) might introduce a shun record that would |
| 45 | propagate through all repositories in a network and permanently |
| 46 | destroy vital information. By refusing to propagate the shunning list, |
| 47 | Fossil ensures that no remote user will ever be able to remove |
| 48 | information from your personal repositories without your permission. |
| 49 | |
| 50 | The shunning list does not propagate to a remote repository |
| 51 | by the normal "sync" mechanism, |
| 52 | but it is still possible to copy shuns from one repository to another |
| 53 | using the "configuration" command: |
| 54 | |
| 55 | <b>fossil configuration pull shun</b> <i>remote-url</i><br> |
| @@ -56,12 +56,12 @@ | |
| 56 | <b>fossil configuration push shun</b> <i>remote-url</i> |
| 57 | |
| 58 | The two command above will pull or push shunning lists from or to |
| 59 | the <i>remote-url</i> indicated and merge the lists on the receiving |
| 60 | end. "Admin" privilege on the remote server is required in order to |
| 61 | push a shun list. In contrast, the shunning list will be automatically |
| 62 | received by default as part of a normal client "pull" operation unless |
| 63 | disabled by the "<tt>auto-shun</tt>" setting. |
| 64 | |
| 65 | Note that the shunning list remains in the repository even after the |
| 66 | shunned artifact has been removed. This is to prevent the artifact |
| 67 | from being reintroduced into the repository the next time it syncs with |
| @@ -68,11 +68,11 @@ | |
| 68 | another repository that has not shunned the artifact. |
| 69 | |
| 70 | <h3>Managing the shunning list</h3> |
| 71 | |
| 72 | The complete shunning list for a repository can be viewed by a user |
| 73 | with "admin" privilege on the "/shun" URL of the web interface to Fossil. |
| 74 | That URL is accessible under the "Admin" button on the default menu |
| 75 | bar. Items can be added to or removed from the shunning list. "Sync" |
| 76 | operations are inhibited as soon as the artifact is added to the |
| 77 | shunning list, but the content of the artifact is not actually removed |
| 78 | from the repository until the next time the repository is rebuilt. |
| 79 |
+3
-3
| --- www/stats.wiki | ||
| +++ www/stats.wiki | ||
| @@ -1,9 +1,9 @@ | ||
| 1 | 1 | <title>Fossil Performance</title> |
| 2 | 2 | <h1 align="center">Performance Statistics</h1> |
| 3 | 3 | |
| 4 | -The questions will inevitably arise: How does Fossil perform? | |
| 4 | +The questions will inevitably arise: How does Fossil perform? | |
| 5 | 5 | Does it use a lot of disk space or bandwidth? Is it scalable? |
| 6 | 6 | |
| 7 | 7 | In an attempt to answers these questions, this report looks at several |
| 8 | 8 | projects that use fossil for configuration management and examines how |
| 9 | 9 | well they are working. The following table is a summary of the results. |
| @@ -96,21 +96,21 @@ | ||
| 96 | 96 | every ticket, and every check-in is a separate "artifact". One way to |
| 97 | 97 | think of a Fossil project is as a bag of artifacts. Of course, there is |
| 98 | 98 | a lot more than this going on in Fossil. Many of the artifacts have meaning |
| 99 | 99 | and are related to other artifacts. But at a low level (for example when |
| 100 | 100 | synchronizing two instances of the same project) the only thing that matters |
| 101 | -is the unordered collection of artifacts. In fact, one of the key | |
| 101 | +is the unordered collection of artifacts. In fact, one of the key | |
| 102 | 102 | characteristics of Fossil is that the entire project history can be |
| 103 | 103 | reconstructed simply by scanning the artifacts in an arbitrary order. |
| 104 | 104 | |
| 105 | 105 | The number of check-ins is the number of times that the "commit" command |
| 106 | 106 | has been run. A single check-in might change a 3 or 4 files, or it might |
| 107 | 107 | change dozens or hundreds of files. Regardless of the number of files |
| 108 | 108 | changed, it still only counts as one check-in. |
| 109 | 109 | |
| 110 | 110 | The "Uncompressed Size" is the total size of all the artifacts within |
| 111 | -the repository assuming they were all uncompressed and stored | |
| 111 | +the repository assuming they were all uncompressed and stored | |
| 112 | 112 | separately on the disk. Fossil makes use of delta compression between related |
| 113 | 113 | versions of the same file, and then uses zlib compression on the resulting |
| 114 | 114 | deltas. The total resulting repository size is shown after the uncompressed |
| 115 | 115 | size. |
| 116 | 116 | |
| 117 | 117 |
| --- www/stats.wiki | |
| +++ www/stats.wiki | |
| @@ -1,9 +1,9 @@ | |
| 1 | <title>Fossil Performance</title> |
| 2 | <h1 align="center">Performance Statistics</h1> |
| 3 | |
| 4 | The questions will inevitably arise: How does Fossil perform? |
| 5 | Does it use a lot of disk space or bandwidth? Is it scalable? |
| 6 | |
| 7 | In an attempt to answers these questions, this report looks at several |
| 8 | projects that use fossil for configuration management and examines how |
| 9 | well they are working. The following table is a summary of the results. |
| @@ -96,21 +96,21 @@ | |
| 96 | every ticket, and every check-in is a separate "artifact". One way to |
| 97 | think of a Fossil project is as a bag of artifacts. Of course, there is |
| 98 | a lot more than this going on in Fossil. Many of the artifacts have meaning |
| 99 | and are related to other artifacts. But at a low level (for example when |
| 100 | synchronizing two instances of the same project) the only thing that matters |
| 101 | is the unordered collection of artifacts. In fact, one of the key |
| 102 | characteristics of Fossil is that the entire project history can be |
| 103 | reconstructed simply by scanning the artifacts in an arbitrary order. |
| 104 | |
| 105 | The number of check-ins is the number of times that the "commit" command |
| 106 | has been run. A single check-in might change a 3 or 4 files, or it might |
| 107 | change dozens or hundreds of files. Regardless of the number of files |
| 108 | changed, it still only counts as one check-in. |
| 109 | |
| 110 | The "Uncompressed Size" is the total size of all the artifacts within |
| 111 | the repository assuming they were all uncompressed and stored |
| 112 | separately on the disk. Fossil makes use of delta compression between related |
| 113 | versions of the same file, and then uses zlib compression on the resulting |
| 114 | deltas. The total resulting repository size is shown after the uncompressed |
| 115 | size. |
| 116 | |
| 117 |
| --- www/stats.wiki | |
| +++ www/stats.wiki | |
| @@ -1,9 +1,9 @@ | |
| 1 | <title>Fossil Performance</title> |
| 2 | <h1 align="center">Performance Statistics</h1> |
| 3 | |
| 4 | The questions will inevitably arise: How does Fossil perform? |
| 5 | Does it use a lot of disk space or bandwidth? Is it scalable? |
| 6 | |
| 7 | In an attempt to answers these questions, this report looks at several |
| 8 | projects that use fossil for configuration management and examines how |
| 9 | well they are working. The following table is a summary of the results. |
| @@ -96,21 +96,21 @@ | |
| 96 | every ticket, and every check-in is a separate "artifact". One way to |
| 97 | think of a Fossil project is as a bag of artifacts. Of course, there is |
| 98 | a lot more than this going on in Fossil. Many of the artifacts have meaning |
| 99 | and are related to other artifacts. But at a low level (for example when |
| 100 | synchronizing two instances of the same project) the only thing that matters |
| 101 | is the unordered collection of artifacts. In fact, one of the key |
| 102 | characteristics of Fossil is that the entire project history can be |
| 103 | reconstructed simply by scanning the artifacts in an arbitrary order. |
| 104 | |
| 105 | The number of check-ins is the number of times that the "commit" command |
| 106 | has been run. A single check-in might change a 3 or 4 files, or it might |
| 107 | change dozens or hundreds of files. Regardless of the number of files |
| 108 | changed, it still only counts as one check-in. |
| 109 | |
| 110 | The "Uncompressed Size" is the total size of all the artifacts within |
| 111 | the repository assuming they were all uncompressed and stored |
| 112 | separately on the disk. Fossil makes use of delta compression between related |
| 113 | versions of the same file, and then uses zlib compression on the resulting |
| 114 | deltas. The total resulting repository size is shown after the uncompressed |
| 115 | size. |
| 116 | |
| 117 |
+9
-9
| --- www/sync.wiki | ||
| +++ www/sync.wiki | ||
| @@ -1,8 +1,8 @@ | ||
| 1 | 1 | <title>The Fossil Sync Protocol</title> |
| 2 | 2 | |
| 3 | -<p>This document describes the wire protocol used to synchronize | |
| 3 | +<p>This document describes the wire protocol used to synchronize | |
| 4 | 4 | content between two Fossil repositories.</p> |
| 5 | 5 | |
| 6 | 6 | <h2>1.0 Overview</h2> |
| 7 | 7 | |
| 8 | 8 | <p>The global state of a fossil repository consists of an unordered |
| @@ -22,11 +22,11 @@ | ||
| 22 | 22 | shared to a few hundred.</p> |
| 23 | 23 | |
| 24 | 24 | <p>Each repository also has local state. The local state determines |
| 25 | 25 | the web-page formatting preferences, authorized users, ticket formats, |
| 26 | 26 | and similar information that varies from one repository to another. |
| 27 | -The local state is not using transferred during a sync. Except, | |
| 27 | +The local state is not using transferred during a sync. Except, | |
| 28 | 28 | some local state is transferred during a [/help?cmd=clone|clone] |
| 29 | 29 | in order to initialize the local state of the new repository. And |
| 30 | 30 | the [/help?cmd=configuration|config push] and |
| 31 | 31 | [/help?cmd=configuration|config pull] |
| 32 | 32 | commands can be an administrator to sync local state.</p> |
| @@ -40,15 +40,15 @@ | ||
| 40 | 40 | request.</p> |
| 41 | 41 | |
| 42 | 42 | <p>The server might be running as an independent server |
| 43 | 43 | using the <b>server</b> command, or it might be launched from |
| 44 | 44 | inetd or xinetd using the <b>http</b> command. Or the server might |
| 45 | -be launched from CGI. | |
| 45 | +be launched from CGI. | |
| 46 | 46 | (See "[./server.wiki|How To Configure A Fossil Server]" for details.) |
| 47 | 47 | The specifics of how the server listens |
| 48 | 48 | for incoming HTTP requests is immaterial to this protocol. |
| 49 | -The important point is that the server is listening for requests and | |
| 49 | +The important point is that the server is listening for requests and | |
| 50 | 50 | the client is the issuer of the requests.</p> |
| 51 | 51 | |
| 52 | 52 | <p>A single push, pull, or sync might involve multiple HTTP requests. |
| 53 | 53 | The client maintains state between all requests. But on the server |
| 54 | 54 | side, each request is independent. The server does not preserve |
| @@ -55,11 +55,11 @@ | ||
| 55 | 55 | any information about the client from one request to the next.</p> |
| 56 | 56 | |
| 57 | 57 | <h4>2.0.1 Encrypted Transport</h4> |
| 58 | 58 | |
| 59 | 59 | <p>In the current implementation of Fossil, the server only |
| 60 | -understands HTTP requests. The client can send either | |
| 60 | +understands HTTP requests. The client can send either | |
| 61 | 61 | clear-text HTTP requests or encrypted HTTPS requests. But when |
| 62 | 62 | HTTPS requests are sent, they first must be decrypted by a webserver |
| 63 | 63 | or proxy before being passed to the Fossil server. This limitation |
| 64 | 64 | may be relaxed in a future release.</p> |
| 65 | 65 | |
| @@ -220,11 +220,11 @@ | ||
| 220 | 220 | introduced to improve the speed of the transfer of content by sending the |
| 221 | 221 | compressed artifact directly from the server database to the client.</p> |
| 222 | 222 | |
| 223 | 223 | <p>Compressed File cards are similar to File cards, sharing the same |
| 224 | 224 | in-line "payload" data characteristics and also the same treatment of |
| 225 | -direct content or delta content. It comes in two different formats | |
| 225 | +direct content or delta content. Cfile cards come in two different formats | |
| 226 | 226 | depending on whether the artifact is sent directly or as a delta from |
| 227 | 227 | some other artifact.</p> |
| 228 | 228 | |
| 229 | 229 | <blockquote> |
| 230 | 230 | <b>cfile</b> <i>artifact-id usize csize</i> <b>\n</b> <i>content</i><br> |
| @@ -277,11 +277,11 @@ | ||
| 277 | 277 | for the unversioned file, or "<b>-</b>" for deleted content. |
| 278 | 278 | The <i>size</i> field is the (uncompressed) size of the content |
| 279 | 279 | in bytes. The <i>flags</i> field is an integer which is interpreted |
| 280 | 280 | as an array of bits. The 0x0004 bit of <i>flags</i> indicates that |
| 281 | 281 | the <i>content</i> is to be omitted. The content might be omitted if |
| 282 | -it is too large to transmit, or if the send merely wants to update the | |
| 282 | +it is too large to transmit, or if the sender merely wants to update the | |
| 283 | 283 | modification time of the file without changing the files content. |
| 284 | 284 | The <i>content</i> is the (uncompressed) content of the file. |
| 285 | 285 | |
| 286 | 286 | <p>The receiver should only accept the uvfile card if the hash and |
| 287 | 287 | size match the content and if the mtime is newer than any existing |
| @@ -398,21 +398,21 @@ | ||
| 398 | 398 | identified by the first argument is private on the sender and should |
| 399 | 399 | be ignored unless a "--private" [/help?cmd=sync|sync] is occurring. |
| 400 | 400 | |
| 401 | 401 | <h4>3.6.1 Unversioned Igot Cards</h4> |
| 402 | 402 | |
| 403 | -<p>Zero or more "uvigot" cards are sent from client to server when | |
| 403 | +<p>Zero or more "uvigot" cards are sent from server to client when | |
| 404 | 404 | synchronizing unversioned content. The format of a uvigot card is |
| 405 | 405 | as follows: |
| 406 | 406 | |
| 407 | 407 | <blockquote> |
| 408 | 408 | <b>uvigot</b> <i>name mtime hash size</i> |
| 409 | 409 | </blockquote> |
| 410 | 410 | |
| 411 | 411 | <p>The <i>name</i> argument is the name of an unversioned file. |
| 412 | 412 | The <i>mtime</i> is the last modification time of the unversioned file |
| 413 | -in seconds since 1970. | |
| 413 | +in seconds since 1970. | |
| 414 | 414 | The <i>hash</i> is the SHA1 hash of the unversioned file content, or |
| 415 | 415 | "<b>-</b>" if the file has been deleted. |
| 416 | 416 | The <i>size</i> is the uncompressed size of the file in bytes. |
| 417 | 417 | |
| 418 | 418 | <p>When the server sees a "pragma uv-hash" card for which the hash |
| 419 | 419 |
| --- www/sync.wiki | |
| +++ www/sync.wiki | |
| @@ -1,8 +1,8 @@ | |
| 1 | <title>The Fossil Sync Protocol</title> |
| 2 | |
| 3 | <p>This document describes the wire protocol used to synchronize |
| 4 | content between two Fossil repositories.</p> |
| 5 | |
| 6 | <h2>1.0 Overview</h2> |
| 7 | |
| 8 | <p>The global state of a fossil repository consists of an unordered |
| @@ -22,11 +22,11 @@ | |
| 22 | shared to a few hundred.</p> |
| 23 | |
| 24 | <p>Each repository also has local state. The local state determines |
| 25 | the web-page formatting preferences, authorized users, ticket formats, |
| 26 | and similar information that varies from one repository to another. |
| 27 | The local state is not using transferred during a sync. Except, |
| 28 | some local state is transferred during a [/help?cmd=clone|clone] |
| 29 | in order to initialize the local state of the new repository. And |
| 30 | the [/help?cmd=configuration|config push] and |
| 31 | [/help?cmd=configuration|config pull] |
| 32 | commands can be an administrator to sync local state.</p> |
| @@ -40,15 +40,15 @@ | |
| 40 | request.</p> |
| 41 | |
| 42 | <p>The server might be running as an independent server |
| 43 | using the <b>server</b> command, or it might be launched from |
| 44 | inetd or xinetd using the <b>http</b> command. Or the server might |
| 45 | be launched from CGI. |
| 46 | (See "[./server.wiki|How To Configure A Fossil Server]" for details.) |
| 47 | The specifics of how the server listens |
| 48 | for incoming HTTP requests is immaterial to this protocol. |
| 49 | The important point is that the server is listening for requests and |
| 50 | the client is the issuer of the requests.</p> |
| 51 | |
| 52 | <p>A single push, pull, or sync might involve multiple HTTP requests. |
| 53 | The client maintains state between all requests. But on the server |
| 54 | side, each request is independent. The server does not preserve |
| @@ -55,11 +55,11 @@ | |
| 55 | any information about the client from one request to the next.</p> |
| 56 | |
| 57 | <h4>2.0.1 Encrypted Transport</h4> |
| 58 | |
| 59 | <p>In the current implementation of Fossil, the server only |
| 60 | understands HTTP requests. The client can send either |
| 61 | clear-text HTTP requests or encrypted HTTPS requests. But when |
| 62 | HTTPS requests are sent, they first must be decrypted by a webserver |
| 63 | or proxy before being passed to the Fossil server. This limitation |
| 64 | may be relaxed in a future release.</p> |
| 65 | |
| @@ -220,11 +220,11 @@ | |
| 220 | introduced to improve the speed of the transfer of content by sending the |
| 221 | compressed artifact directly from the server database to the client.</p> |
| 222 | |
| 223 | <p>Compressed File cards are similar to File cards, sharing the same |
| 224 | in-line "payload" data characteristics and also the same treatment of |
| 225 | direct content or delta content. It comes in two different formats |
| 226 | depending on whether the artifact is sent directly or as a delta from |
| 227 | some other artifact.</p> |
| 228 | |
| 229 | <blockquote> |
| 230 | <b>cfile</b> <i>artifact-id usize csize</i> <b>\n</b> <i>content</i><br> |
| @@ -277,11 +277,11 @@ | |
| 277 | for the unversioned file, or "<b>-</b>" for deleted content. |
| 278 | The <i>size</i> field is the (uncompressed) size of the content |
| 279 | in bytes. The <i>flags</i> field is an integer which is interpreted |
| 280 | as an array of bits. The 0x0004 bit of <i>flags</i> indicates that |
| 281 | the <i>content</i> is to be omitted. The content might be omitted if |
| 282 | it is too large to transmit, or if the send merely wants to update the |
| 283 | modification time of the file without changing the files content. |
| 284 | The <i>content</i> is the (uncompressed) content of the file. |
| 285 | |
| 286 | <p>The receiver should only accept the uvfile card if the hash and |
| 287 | size match the content and if the mtime is newer than any existing |
| @@ -398,21 +398,21 @@ | |
| 398 | identified by the first argument is private on the sender and should |
| 399 | be ignored unless a "--private" [/help?cmd=sync|sync] is occurring. |
| 400 | |
| 401 | <h4>3.6.1 Unversioned Igot Cards</h4> |
| 402 | |
| 403 | <p>Zero or more "uvigot" cards are sent from client to server when |
| 404 | synchronizing unversioned content. The format of a uvigot card is |
| 405 | as follows: |
| 406 | |
| 407 | <blockquote> |
| 408 | <b>uvigot</b> <i>name mtime hash size</i> |
| 409 | </blockquote> |
| 410 | |
| 411 | <p>The <i>name</i> argument is the name of an unversioned file. |
| 412 | The <i>mtime</i> is the last modification time of the unversioned file |
| 413 | in seconds since 1970. |
| 414 | The <i>hash</i> is the SHA1 hash of the unversioned file content, or |
| 415 | "<b>-</b>" if the file has been deleted. |
| 416 | The <i>size</i> is the uncompressed size of the file in bytes. |
| 417 | |
| 418 | <p>When the server sees a "pragma uv-hash" card for which the hash |
| 419 |
| --- www/sync.wiki | |
| +++ www/sync.wiki | |
| @@ -1,8 +1,8 @@ | |
| 1 | <title>The Fossil Sync Protocol</title> |
| 2 | |
| 3 | <p>This document describes the wire protocol used to synchronize |
| 4 | content between two Fossil repositories.</p> |
| 5 | |
| 6 | <h2>1.0 Overview</h2> |
| 7 | |
| 8 | <p>The global state of a fossil repository consists of an unordered |
| @@ -22,11 +22,11 @@ | |
| 22 | shared to a few hundred.</p> |
| 23 | |
| 24 | <p>Each repository also has local state. The local state determines |
| 25 | the web-page formatting preferences, authorized users, ticket formats, |
| 26 | and similar information that varies from one repository to another. |
| 27 | The local state is not using transferred during a sync. Except, |
| 28 | some local state is transferred during a [/help?cmd=clone|clone] |
| 29 | in order to initialize the local state of the new repository. And |
| 30 | the [/help?cmd=configuration|config push] and |
| 31 | [/help?cmd=configuration|config pull] |
| 32 | commands can be an administrator to sync local state.</p> |
| @@ -40,15 +40,15 @@ | |
| 40 | request.</p> |
| 41 | |
| 42 | <p>The server might be running as an independent server |
| 43 | using the <b>server</b> command, or it might be launched from |
| 44 | inetd or xinetd using the <b>http</b> command. Or the server might |
| 45 | be launched from CGI. |
| 46 | (See "[./server.wiki|How To Configure A Fossil Server]" for details.) |
| 47 | The specifics of how the server listens |
| 48 | for incoming HTTP requests is immaterial to this protocol. |
| 49 | The important point is that the server is listening for requests and |
| 50 | the client is the issuer of the requests.</p> |
| 51 | |
| 52 | <p>A single push, pull, or sync might involve multiple HTTP requests. |
| 53 | The client maintains state between all requests. But on the server |
| 54 | side, each request is independent. The server does not preserve |
| @@ -55,11 +55,11 @@ | |
| 55 | any information about the client from one request to the next.</p> |
| 56 | |
| 57 | <h4>2.0.1 Encrypted Transport</h4> |
| 58 | |
| 59 | <p>In the current implementation of Fossil, the server only |
| 60 | understands HTTP requests. The client can send either |
| 61 | clear-text HTTP requests or encrypted HTTPS requests. But when |
| 62 | HTTPS requests are sent, they first must be decrypted by a webserver |
| 63 | or proxy before being passed to the Fossil server. This limitation |
| 64 | may be relaxed in a future release.</p> |
| 65 | |
| @@ -220,11 +220,11 @@ | |
| 220 | introduced to improve the speed of the transfer of content by sending the |
| 221 | compressed artifact directly from the server database to the client.</p> |
| 222 | |
| 223 | <p>Compressed File cards are similar to File cards, sharing the same |
| 224 | in-line "payload" data characteristics and also the same treatment of |
| 225 | direct content or delta content. Cfile cards come in two different formats |
| 226 | depending on whether the artifact is sent directly or as a delta from |
| 227 | some other artifact.</p> |
| 228 | |
| 229 | <blockquote> |
| 230 | <b>cfile</b> <i>artifact-id usize csize</i> <b>\n</b> <i>content</i><br> |
| @@ -277,11 +277,11 @@ | |
| 277 | for the unversioned file, or "<b>-</b>" for deleted content. |
| 278 | The <i>size</i> field is the (uncompressed) size of the content |
| 279 | in bytes. The <i>flags</i> field is an integer which is interpreted |
| 280 | as an array of bits. The 0x0004 bit of <i>flags</i> indicates that |
| 281 | the <i>content</i> is to be omitted. The content might be omitted if |
| 282 | it is too large to transmit, or if the sender merely wants to update the |
| 283 | modification time of the file without changing the files content. |
| 284 | The <i>content</i> is the (uncompressed) content of the file. |
| 285 | |
| 286 | <p>The receiver should only accept the uvfile card if the hash and |
| 287 | size match the content and if the mtime is newer than any existing |
| @@ -398,21 +398,21 @@ | |
| 398 | identified by the first argument is private on the sender and should |
| 399 | be ignored unless a "--private" [/help?cmd=sync|sync] is occurring. |
| 400 | |
| 401 | <h4>3.6.1 Unversioned Igot Cards</h4> |
| 402 | |
| 403 | <p>Zero or more "uvigot" cards are sent from server to client when |
| 404 | synchronizing unversioned content. The format of a uvigot card is |
| 405 | as follows: |
| 406 | |
| 407 | <blockquote> |
| 408 | <b>uvigot</b> <i>name mtime hash size</i> |
| 409 | </blockquote> |
| 410 | |
| 411 | <p>The <i>name</i> argument is the name of an unversioned file. |
| 412 | The <i>mtime</i> is the last modification time of the unversioned file |
| 413 | in seconds since 1970. |
| 414 | The <i>hash</i> is the SHA1 hash of the unversioned file content, or |
| 415 | "<b>-</b>" if the file has been deleted. |
| 416 | The <i>size</i> is the uncompressed size of the file in bytes. |
| 417 | |
| 418 | <p>When the server sees a "pragma uv-hash" card for which the hash |
| 419 |
+28
-5
| --- www/th1.md | ||
| +++ www/th1.md | ||
| @@ -164,20 +164,22 @@ | ||
| 164 | 164 | * render |
| 165 | 165 | * repository |
| 166 | 166 | * searchable |
| 167 | 167 | * setParameter |
| 168 | 168 | * setting |
| 169 | + * stime | |
| 169 | 170 | * styleHeader |
| 170 | 171 | * styleFooter |
| 171 | 172 | * tclEval |
| 172 | 173 | * tclExpr |
| 173 | 174 | * tclInvoke |
| 174 | 175 | * tclIsSafe |
| 175 | 176 | * tclMakeSafe |
| 176 | 177 | * tclReady |
| 177 | 178 | * trace |
| 178 | - * stime | |
| 179 | + * unversioned content | |
| 180 | + * unversioned list | |
| 179 | 181 | * utime |
| 180 | 182 | * verifyCsrf |
| 181 | 183 | * wiki |
| 182 | 184 | |
| 183 | 185 | Each of the commands above is documented by a block comment above their |
| @@ -249,11 +251,11 @@ | ||
| 249 | 251 | |
| 250 | 252 | Renders STRING as wiki content; however, only links are handled. No |
| 251 | 253 | other markup is processed. |
| 252 | 254 | |
| 253 | 255 | <a name="dir"></a>TH1 dir Command |
| -------------------------------------------- | ||
| 256 | +--------------------------------- | |
| 254 | 257 | |
| 255 | 258 | * dir CHECKIN ?GLOB? ?DETAILS? |
| 256 | 259 | |
| 257 | 260 | Returns a list containing all files in CHECKIN. If GLOB is given only |
| 258 | 261 | the files matching the pattern GLOB within CHECKIN will be returned. |
| @@ -400,11 +402,11 @@ | ||
| 400 | 402 | |
| 401 | 403 | Returns one more than the number of \n characters in STRING. But |
| 402 | 404 | never returns less than MIN or more than MAX. |
| 403 | 405 | |
| 404 | 406 | <a name="markdown"></a>TH1 markdown Command |
| ---------------------------------------------- | ||
| 407 | +------------------------------------------- | |
| 405 | 408 | |
| 406 | 409 | * markdown STRING |
| 407 | 410 | |
| 408 | 411 | Renders the input string as markdown. The result is a two-element list. |
| 409 | 412 | The first element contains the body, rendered as HTML. The second element |
| @@ -517,10 +519,18 @@ | ||
| 517 | 519 | ----------------------------------------- |
| 518 | 520 | |
| 519 | 521 | * setting name |
| 520 | 522 | |
| 521 | 523 | Gets and returns the value of the specified setting. |
| 524 | + | |
| 525 | +<a name="stime"></a>TH1 stime Command | |
| 526 | +------------------------------------- | |
| 527 | + | |
| 528 | + * stime | |
| 529 | + | |
| 530 | +Returns the number of microseconds of CPU time consumed by the current | |
| 531 | +process in system space. | |
| 522 | 532 | |
| 523 | 533 | <a name="styleHeader"></a>TH1 styleHeader Command |
| 524 | 534 | ------------------------------------------------- |
| 525 | 535 | |
| 526 | 536 | * styleHeader TITLE |
| @@ -577,11 +587,11 @@ | ||
| 577 | 587 | |
| 578 | 588 | Returns non-zero if the Tcl interpreter is "safe". The Tcl interpreter |
| 579 | 589 | will be created automatically if it has not been already. |
| 580 | 590 | |
| 581 | 591 | <a name="tclMakeSafe"></a>TH1 tclMakeSafe Command |
| ---------------------------------------------- | ||
| 592 | +------------------------------------------------- | |
| 582 | 593 | |
| 583 | 594 | **This command requires the Tcl integration feature.** |
| 584 | 595 | |
| 585 | 596 | * tclMakeSafe |
| 586 | 597 | |
| @@ -603,17 +613,26 @@ | ||
| 603 | 613 | |
| 604 | 614 | * trace STRING |
| 605 | 615 | |
| 606 | 616 | Generates a TH1 trace message if TH1 tracing is enabled. |
| 607 | 617 | |
| 608 | -<a name="stime"></a>TH1 stime Command | |
| -------------------------------------- | ||
| 618 | +<a name="unversioned_content"></a>TH1 unversioned content Command | |
| 619 | +----------------------------------------------------------------- | |
| 620 | + | |
| 621 | + * unversioned content FILENAME | |
| 622 | + | |
| 623 | +Attempts to locate the specified unversioned file and return its contents. | |
| 624 | +An error is generated if the repository is not open or the unversioned file | |
| 625 | +cannot be found. | |
| 626 | + | |
| 627 | +<a name="unversioned_list"></a>TH1 unversioned list Command | |
| 628 | +----------------------------------------------------------- | |
| 609 | 629 | |
| 610 | - * stime | |
| 630 | + * unversioned list | |
| 611 | 631 | |
| 612 | -Returns the number of microseconds of CPU time consumed by the current | |
| 613 | -process in system space. | |
| 632 | +Returns a list of the names of all unversioned files held in the local | |
| 633 | +repository. An error is generated if the repository is not open. | |
| 614 | 634 | |
| 615 | 635 | <a name="utime"></a>TH1 utime Command |
| 616 | 636 | ------------------------------------- |
| 617 | 637 | |
| 618 | 638 | * utime |
| 619 | 639 |
| --- www/th1.md | |
| +++ www/th1.md | |
| @@ -164,20 +164,22 @@ | |
| 164 | * render |
| 165 | * repository |
| 166 | * searchable |
| 167 | * setParameter |
| 168 | * setting |
| 169 | * styleHeader |
| 170 | * styleFooter |
| 171 | * tclEval |
| 172 | * tclExpr |
| 173 | * tclInvoke |
| 174 | * tclIsSafe |
| 175 | * tclMakeSafe |
| 176 | * tclReady |
| 177 | * trace |
| 178 | * stime |
| 179 | * utime |
| 180 | * verifyCsrf |
| 181 | * wiki |
| 182 | |
| 183 | Each of the commands above is documented by a block comment above their |
| @@ -249,11 +251,11 @@ | |
| 249 | |
| 250 | Renders STRING as wiki content; however, only links are handled. No |
| 251 | other markup is processed. |
| 252 | |
| 253 | <a name="dir"></a>TH1 dir Command |
| -------------------------------------------- | |
| 254 | |
| 255 | * dir CHECKIN ?GLOB? ?DETAILS? |
| 256 | |
| 257 | Returns a list containing all files in CHECKIN. If GLOB is given only |
| 258 | the files matching the pattern GLOB within CHECKIN will be returned. |
| @@ -400,11 +402,11 @@ | |
| 400 | |
| 401 | Returns one more than the number of \n characters in STRING. But |
| 402 | never returns less than MIN or more than MAX. |
| 403 | |
| 404 | <a name="markdown"></a>TH1 markdown Command |
| ---------------------------------------------- | |
| 405 | |
| 406 | * markdown STRING |
| 407 | |
| 408 | Renders the input string as markdown. The result is a two-element list. |
| 409 | The first element contains the body, rendered as HTML. The second element |
| @@ -517,10 +519,18 @@ | |
| 517 | ----------------------------------------- |
| 518 | |
| 519 | * setting name |
| 520 | |
| 521 | Gets and returns the value of the specified setting. |
| 522 | |
| 523 | <a name="styleHeader"></a>TH1 styleHeader Command |
| 524 | ------------------------------------------------- |
| 525 | |
| 526 | * styleHeader TITLE |
| @@ -577,11 +587,11 @@ | |
| 577 | |
| 578 | Returns non-zero if the Tcl interpreter is "safe". The Tcl interpreter |
| 579 | will be created automatically if it has not been already. |
| 580 | |
| 581 | <a name="tclMakeSafe"></a>TH1 tclMakeSafe Command |
| ---------------------------------------------- | |
| 582 | |
| 583 | **This command requires the Tcl integration feature.** |
| 584 | |
| 585 | * tclMakeSafe |
| 586 | |
| @@ -603,17 +613,26 @@ | |
| 603 | |
| 604 | * trace STRING |
| 605 | |
| 606 | Generates a TH1 trace message if TH1 tracing is enabled. |
| 607 | |
| 608 | <a name="stime"></a>TH1 stime Command |
| -------------------------------------- | |
| 609 | |
| 610 | * stime |
| 611 | |
| 612 | Returns the number of microseconds of CPU time consumed by the current |
| 613 | process in system space. |
| 614 | |
| 615 | <a name="utime"></a>TH1 utime Command |
| 616 | ------------------------------------- |
| 617 | |
| 618 | * utime |
| 619 |
| --- www/th1.md | |
| +++ www/th1.md | |
| @@ -164,20 +164,22 @@ | |
| 164 | * render |
| 165 | * repository |
| 166 | * searchable |
| 167 | * setParameter |
| 168 | * setting |
| 169 | * stime |
| 170 | * styleHeader |
| 171 | * styleFooter |
| 172 | * tclEval |
| 173 | * tclExpr |
| 174 | * tclInvoke |
| 175 | * tclIsSafe |
| 176 | * tclMakeSafe |
| 177 | * tclReady |
| 178 | * trace |
| 179 | * unversioned content |
| 180 | * unversioned list |
| 181 | * utime |
| 182 | * verifyCsrf |
| 183 | * wiki |
| 184 | |
| 185 | Each of the commands above is documented by a block comment above their |
| @@ -249,11 +251,11 @@ | |
| 251 | |
| 252 | Renders STRING as wiki content; however, only links are handled. No |
| 253 | other markup is processed. |
| 254 | |
| 255 | <a name="dir"></a>TH1 dir Command |
| -------------------------------------------- | |
| 256 | --------------------------------- |
| 257 | |
| 258 | * dir CHECKIN ?GLOB? ?DETAILS? |
| 259 | |
| 260 | Returns a list containing all files in CHECKIN. If GLOB is given only |
| 261 | the files matching the pattern GLOB within CHECKIN will be returned. |
| @@ -400,11 +402,11 @@ | |
| 402 | |
| 403 | Returns one more than the number of \n characters in STRING. But |
| 404 | never returns less than MIN or more than MAX. |
| 405 | |
| 406 | <a name="markdown"></a>TH1 markdown Command |
| ---------------------------------------------- | |
| 407 | ------------------------------------------- |
| 408 | |
| 409 | * markdown STRING |
| 410 | |
| 411 | Renders the input string as markdown. The result is a two-element list. |
| 412 | The first element contains the body, rendered as HTML. The second element |
| @@ -517,10 +519,18 @@ | |
| 519 | ----------------------------------------- |
| 520 | |
| 521 | * setting name |
| 522 | |
| 523 | Gets and returns the value of the specified setting. |
| 524 | |
| 525 | <a name="stime"></a>TH1 stime Command |
| 526 | ------------------------------------- |
| 527 | |
| 528 | * stime |
| 529 | |
| 530 | Returns the number of microseconds of CPU time consumed by the current |
| 531 | process in system space. |
| 532 | |
| 533 | <a name="styleHeader"></a>TH1 styleHeader Command |
| 534 | ------------------------------------------------- |
| 535 | |
| 536 | * styleHeader TITLE |
| @@ -577,11 +587,11 @@ | |
| 587 | |
| 588 | Returns non-zero if the Tcl interpreter is "safe". The Tcl interpreter |
| 589 | will be created automatically if it has not been already. |
| 590 | |
| 591 | <a name="tclMakeSafe"></a>TH1 tclMakeSafe Command |
| ---------------------------------------------- | |
| 592 | ------------------------------------------------- |
| 593 | |
| 594 | **This command requires the Tcl integration feature.** |
| 595 | |
| 596 | * tclMakeSafe |
| 597 | |
| @@ -603,17 +613,26 @@ | |
| 613 | |
| 614 | * trace STRING |
| 615 | |
| 616 | Generates a TH1 trace message if TH1 tracing is enabled. |
| 617 | |
| -------------------------------------- | |
| 618 | <a name="unversioned_content"></a>TH1 unversioned content Command |
| 619 | ----------------------------------------------------------------- |
| 620 | |
| 621 | * unversioned content FILENAME |
| 622 | |
| 623 | Attempts to locate the specified unversioned file and return its contents. |
| 624 | An error is generated if the repository is not open or the unversioned file |
| 625 | cannot be found. |
| 626 | |
| 627 | <a name="unversioned_list"></a>TH1 unversioned list Command |
| 628 | ----------------------------------------------------------- |
| 629 | |
| 630 | * unversioned list |
| 631 | |
| 632 | Returns a list of the names of all unversioned files held in the local |
| 633 | repository. An error is generated if the repository is not open. |
| 634 | |
| 635 | <a name="utime"></a>TH1 utime Command |
| 636 | ------------------------------------- |
| 637 | |
| 638 | * utime |
| 639 |
+5
-5
| --- www/theory1.wiki | ||
| +++ www/theory1.wiki | ||
| @@ -16,18 +16,18 @@ | ||
| 16 | 16 | |
| 17 | 17 | <h2>Fossil Is A NoSQL Database</h2> |
| 18 | 18 | |
| 19 | 19 | We begin with the first question: Fossil is not based on a distributed |
| 20 | 20 | NoSQL database because Fossil <u><i>is</i></u> a distributed NoSQL database. |
| 21 | -Fossil is <u>not</u> based on SQLite. | |
| 21 | +Fossil is <u>not</u> based on SQLite. | |
| 22 | 22 | The current implementation of Fossil uses |
| 23 | 23 | SQLite as a local store for the content of the distributed database and as |
| 24 | 24 | a cache for meta-information about the distributed database that is precomputed |
| 25 | 25 | for quick and easy presentation. But the use of SQLite in this role is an |
| 26 | 26 | implementation detail and is not fundamental to the design. Some future |
| 27 | 27 | version of Fossil might do away with SQLite and substitute a pile-of-files or |
| 28 | -a key/value database in place of SQLite. | |
| 28 | +a key/value database in place of SQLite. | |
| 29 | 29 | (Actually, that is very unlikely |
| 30 | 30 | to happen since SQLite works amazingly well in its current role, but the point |
| 31 | 31 | is that omitting SQLite from Fossil is a theoretical possibility.) |
| 32 | 32 | |
| 33 | 33 | The underlying database that Fossil implements has nothing to do with |
| @@ -64,11 +64,11 @@ | ||
| 64 | 64 | a NoSQL database) and there is the local relational database. The |
| 65 | 65 | bag-of-artifacts database has a fixed format and is what defines a Fossil |
| 66 | 66 | repository. Fossil will never modify the file format of the bag-of-artifacts |
| 67 | 67 | database in an incompatible way because to do so would be to make something |
| 68 | 68 | that is no longer "Fossil". The local relational database, on the other hand, |
| 69 | -is a cache that contains information derived from the bag-of-artifacts. | |
| 69 | +is a cache that contains information derived from the bag-of-artifacts. | |
| 70 | 70 | The schema of the local relational database changes from time to time as |
| 71 | 71 | the Fossil implementation is enhanced, and the content is recomputed from |
| 72 | 72 | the unchanging bag of artifacts. The local relational database is an |
| 73 | 73 | implementation detail which currently happens to use SQLite. |
| 74 | 74 | |
| @@ -89,11 +89,11 @@ | ||
| 89 | 89 | the first question. |
| 90 | 90 | |
| 91 | 91 | <h2>SQL Is A High-Level Scripting Language</h2> |
| 92 | 92 | |
| 93 | 93 | The second concern states that Fossil does not use a high-level scripting |
| 94 | -language. But that is not true. Fossil uses SQL (as implemented by SQLite) | |
| 94 | +language. But that is not true. Fossil uses SQL (as implemented by SQLite) | |
| 95 | 95 | as its scripting language. |
| 96 | 96 | |
| 97 | 97 | This misunderstanding likely arises because people fail |
| 98 | 98 | to appreciate that SQL is a programming language. People are taught that SQL |
| 99 | 99 | is a "query language" as if that were somehow different from a |
| @@ -125,11 +125,11 @@ | ||
| 125 | 125 | out using SQL statements. It is true that these SQL statements are glued |
| 126 | 126 | together with C code, but it turns out that C works surprisingly well in |
| 127 | 127 | that role. Several early prototypes of Fossil were written in a scripting |
| 128 | 128 | language (TCL). We normally find that TCL programs are shorter than the |
| 129 | 129 | equivalent C code by a factor of 10 or more. But in the case of Fossil, |
| 130 | -the use of TCL was actually making the code longer and more difficult to | |
| 130 | +the use of TCL was actually making the code longer and more difficult to | |
| 131 | 131 | understand. |
| 132 | 132 | And so in the final design, we switched from TCL to C in order to make |
| 133 | 133 | the code easier to implement and debug. |
| 134 | 134 | |
| 135 | 135 | Without the advantages of having SQLite built in, the design might well |
| 136 | 136 |
| --- www/theory1.wiki | |
| +++ www/theory1.wiki | |
| @@ -16,18 +16,18 @@ | |
| 16 | |
| 17 | <h2>Fossil Is A NoSQL Database</h2> |
| 18 | |
| 19 | We begin with the first question: Fossil is not based on a distributed |
| 20 | NoSQL database because Fossil <u><i>is</i></u> a distributed NoSQL database. |
| 21 | Fossil is <u>not</u> based on SQLite. |
| 22 | The current implementation of Fossil uses |
| 23 | SQLite as a local store for the content of the distributed database and as |
| 24 | a cache for meta-information about the distributed database that is precomputed |
| 25 | for quick and easy presentation. But the use of SQLite in this role is an |
| 26 | implementation detail and is not fundamental to the design. Some future |
| 27 | version of Fossil might do away with SQLite and substitute a pile-of-files or |
| 28 | a key/value database in place of SQLite. |
| 29 | (Actually, that is very unlikely |
| 30 | to happen since SQLite works amazingly well in its current role, but the point |
| 31 | is that omitting SQLite from Fossil is a theoretical possibility.) |
| 32 | |
| 33 | The underlying database that Fossil implements has nothing to do with |
| @@ -64,11 +64,11 @@ | |
| 64 | a NoSQL database) and there is the local relational database. The |
| 65 | bag-of-artifacts database has a fixed format and is what defines a Fossil |
| 66 | repository. Fossil will never modify the file format of the bag-of-artifacts |
| 67 | database in an incompatible way because to do so would be to make something |
| 68 | that is no longer "Fossil". The local relational database, on the other hand, |
| 69 | is a cache that contains information derived from the bag-of-artifacts. |
| 70 | The schema of the local relational database changes from time to time as |
| 71 | the Fossil implementation is enhanced, and the content is recomputed from |
| 72 | the unchanging bag of artifacts. The local relational database is an |
| 73 | implementation detail which currently happens to use SQLite. |
| 74 | |
| @@ -89,11 +89,11 @@ | |
| 89 | the first question. |
| 90 | |
| 91 | <h2>SQL Is A High-Level Scripting Language</h2> |
| 92 | |
| 93 | The second concern states that Fossil does not use a high-level scripting |
| 94 | language. But that is not true. Fossil uses SQL (as implemented by SQLite) |
| 95 | as its scripting language. |
| 96 | |
| 97 | This misunderstanding likely arises because people fail |
| 98 | to appreciate that SQL is a programming language. People are taught that SQL |
| 99 | is a "query language" as if that were somehow different from a |
| @@ -125,11 +125,11 @@ | |
| 125 | out using SQL statements. It is true that these SQL statements are glued |
| 126 | together with C code, but it turns out that C works surprisingly well in |
| 127 | that role. Several early prototypes of Fossil were written in a scripting |
| 128 | language (TCL). We normally find that TCL programs are shorter than the |
| 129 | equivalent C code by a factor of 10 or more. But in the case of Fossil, |
| 130 | the use of TCL was actually making the code longer and more difficult to |
| 131 | understand. |
| 132 | And so in the final design, we switched from TCL to C in order to make |
| 133 | the code easier to implement and debug. |
| 134 | |
| 135 | Without the advantages of having SQLite built in, the design might well |
| 136 |
| --- www/theory1.wiki | |
| +++ www/theory1.wiki | |
| @@ -16,18 +16,18 @@ | |
| 16 | |
| 17 | <h2>Fossil Is A NoSQL Database</h2> |
| 18 | |
| 19 | We begin with the first question: Fossil is not based on a distributed |
| 20 | NoSQL database because Fossil <u><i>is</i></u> a distributed NoSQL database. |
| 21 | Fossil is <u>not</u> based on SQLite. |
| 22 | The current implementation of Fossil uses |
| 23 | SQLite as a local store for the content of the distributed database and as |
| 24 | a cache for meta-information about the distributed database that is precomputed |
| 25 | for quick and easy presentation. But the use of SQLite in this role is an |
| 26 | implementation detail and is not fundamental to the design. Some future |
| 27 | version of Fossil might do away with SQLite and substitute a pile-of-files or |
| 28 | a key/value database in place of SQLite. |
| 29 | (Actually, that is very unlikely |
| 30 | to happen since SQLite works amazingly well in its current role, but the point |
| 31 | is that omitting SQLite from Fossil is a theoretical possibility.) |
| 32 | |
| 33 | The underlying database that Fossil implements has nothing to do with |
| @@ -64,11 +64,11 @@ | |
| 64 | a NoSQL database) and there is the local relational database. The |
| 65 | bag-of-artifacts database has a fixed format and is what defines a Fossil |
| 66 | repository. Fossil will never modify the file format of the bag-of-artifacts |
| 67 | database in an incompatible way because to do so would be to make something |
| 68 | that is no longer "Fossil". The local relational database, on the other hand, |
| 69 | is a cache that contains information derived from the bag-of-artifacts. |
| 70 | The schema of the local relational database changes from time to time as |
| 71 | the Fossil implementation is enhanced, and the content is recomputed from |
| 72 | the unchanging bag of artifacts. The local relational database is an |
| 73 | implementation detail which currently happens to use SQLite. |
| 74 | |
| @@ -89,11 +89,11 @@ | |
| 89 | the first question. |
| 90 | |
| 91 | <h2>SQL Is A High-Level Scripting Language</h2> |
| 92 | |
| 93 | The second concern states that Fossil does not use a high-level scripting |
| 94 | language. But that is not true. Fossil uses SQL (as implemented by SQLite) |
| 95 | as its scripting language. |
| 96 | |
| 97 | This misunderstanding likely arises because people fail |
| 98 | to appreciate that SQL is a programming language. People are taught that SQL |
| 99 | is a "query language" as if that were somehow different from a |
| @@ -125,11 +125,11 @@ | |
| 125 | out using SQL statements. It is true that these SQL statements are glued |
| 126 | together with C code, but it turns out that C works surprisingly well in |
| 127 | that role. Several early prototypes of Fossil were written in a scripting |
| 128 | language (TCL). We normally find that TCL programs are shorter than the |
| 129 | equivalent C code by a factor of 10 or more. But in the case of Fossil, |
| 130 | the use of TCL was actually making the code longer and more difficult to |
| 131 | understand. |
| 132 | And so in the final design, we switched from TCL to C in order to make |
| 133 | the code easier to implement and debug. |
| 134 | |
| 135 | Without the advantages of having SQLite built in, the design might well |
| 136 |
+1
-2
| --- www/webui.wiki | ||
| +++ www/webui.wiki | ||
| @@ -25,12 +25,11 @@ | ||
| 25 | 25 | There are no extra programs to install or setup. |
| 26 | 26 | Everything you need is already pre-configured and built into the |
| 27 | 27 | self-contained, stand-alone Fossil executable. |
| 28 | 28 | |
| 29 | 29 | As an example of how useful this web interface can be, |
| 30 | -the entire [./index.wiki | Fossil website] (except for the | |
| 31 | -[http://www.fossil-scm.org/download.html | download page]), | |
| 30 | +the entire [./index.wiki | Fossil website], | |
| 32 | 31 | including the document you are now reading, |
| 33 | 32 | is rendered using the Fossil web interface, with no enhancements, |
| 34 | 33 | and little customization. |
| 35 | 34 | |
| 36 | 35 | <blockquote> |
| 37 | 36 |
| --- www/webui.wiki | |
| +++ www/webui.wiki | |
| @@ -25,12 +25,11 @@ | |
| 25 | There are no extra programs to install or setup. |
| 26 | Everything you need is already pre-configured and built into the |
| 27 | self-contained, stand-alone Fossil executable. |
| 28 | |
| 29 | As an example of how useful this web interface can be, |
| 30 | the entire [./index.wiki | Fossil website] (except for the |
| 31 | [http://www.fossil-scm.org/download.html | download page]), |
| 32 | including the document you are now reading, |
| 33 | is rendered using the Fossil web interface, with no enhancements, |
| 34 | and little customization. |
| 35 | |
| 36 | <blockquote> |
| 37 |
| --- www/webui.wiki | |
| +++ www/webui.wiki | |
| @@ -25,12 +25,11 @@ | |
| 25 | There are no extra programs to install or setup. |
| 26 | Everything you need is already pre-configured and built into the |
| 27 | self-contained, stand-alone Fossil executable. |
| 28 | |
| 29 | As an example of how useful this web interface can be, |
| 30 | the entire [./index.wiki | Fossil website], |
| 31 | including the document you are now reading, |
| 32 | is rendered using the Fossil web interface, with no enhancements, |
| 33 | and little customization. |
| 34 | |
| 35 | <blockquote> |
| 36 |
+3
-2
| --- www/whyusefossil.wiki | ||
| +++ www/whyusefossil.wiki | ||
| @@ -37,10 +37,11 @@ | ||
| 37 | 37 | <li>Failed disk-drives cause no loss of work |
| 38 | 38 | <li>Avoid wasting time doing manual file copying |
| 39 | 39 | <li>Avoid human errors during manual backups |
| 40 | 40 | </ol> |
| 41 | 41 | </ol> |
| 42 | +<a name='definitions'></a> | |
| 42 | 43 | <li><p><b>Definitions</b></p> |
| 43 | 44 | <ul> |
| 44 | 45 | <li><p><b>Project</b> → |
| 45 | 46 | a collection of computer files that serve some common |
| 46 | 47 | purpose. Often the project is a software application and the |
| @@ -59,12 +60,12 @@ | ||
| 59 | 60 | project that has files scattered hither and yon all over |
| 60 | 61 | the disk. In other words, Fossil only works for projects |
| 61 | 62 | where the files are laid out such that they can be archived |
| 62 | 63 | into a ZIP file or tarball. |
| 63 | 64 | </ul> |
| 64 | - <li><p><b>Repository</b> | |
| 65 | - (also called "repo") → a single file that contains | |
| 65 | + <li><p><b>Repository</b> → | |
| 66 | + (also called "repo") a single file that contains | |
| 66 | 67 | all historical versions of all files in a project. A repo is similar |
| 67 | 68 | to a ZIP archive in that it is a single file that stores compressed |
| 68 | 69 | versions of many other files. Files can be extracted from the |
| 69 | 70 | repo and new files can be added to the repo, just as with a ZIP |
| 70 | 71 | archive. But a repo has other capabilities above and beyond |
| 71 | 72 |
| --- www/whyusefossil.wiki | |
| +++ www/whyusefossil.wiki | |
| @@ -37,10 +37,11 @@ | |
| 37 | <li>Failed disk-drives cause no loss of work |
| 38 | <li>Avoid wasting time doing manual file copying |
| 39 | <li>Avoid human errors during manual backups |
| 40 | </ol> |
| 41 | </ol> |
| 42 | <li><p><b>Definitions</b></p> |
| 43 | <ul> |
| 44 | <li><p><b>Project</b> → |
| 45 | a collection of computer files that serve some common |
| 46 | purpose. Often the project is a software application and the |
| @@ -59,12 +60,12 @@ | |
| 59 | project that has files scattered hither and yon all over |
| 60 | the disk. In other words, Fossil only works for projects |
| 61 | where the files are laid out such that they can be archived |
| 62 | into a ZIP file or tarball. |
| 63 | </ul> |
| 64 | <li><p><b>Repository</b> |
| 65 | (also called "repo") → a single file that contains |
| 66 | all historical versions of all files in a project. A repo is similar |
| 67 | to a ZIP archive in that it is a single file that stores compressed |
| 68 | versions of many other files. Files can be extracted from the |
| 69 | repo and new files can be added to the repo, just as with a ZIP |
| 70 | archive. But a repo has other capabilities above and beyond |
| 71 |
| --- www/whyusefossil.wiki | |
| +++ www/whyusefossil.wiki | |
| @@ -37,10 +37,11 @@ | |
| 37 | <li>Failed disk-drives cause no loss of work |
| 38 | <li>Avoid wasting time doing manual file copying |
| 39 | <li>Avoid human errors during manual backups |
| 40 | </ol> |
| 41 | </ol> |
| 42 | <a name='definitions'></a> |
| 43 | <li><p><b>Definitions</b></p> |
| 44 | <ul> |
| 45 | <li><p><b>Project</b> → |
| 46 | a collection of computer files that serve some common |
| 47 | purpose. Often the project is a software application and the |
| @@ -59,12 +60,12 @@ | |
| 60 | project that has files scattered hither and yon all over |
| 61 | the disk. In other words, Fossil only works for projects |
| 62 | where the files are laid out such that they can be archived |
| 63 | into a ZIP file or tarball. |
| 64 | </ul> |
| 65 | <li><p><b>Repository</b> → |
| 66 | (also called "repo") a single file that contains |
| 67 | all historical versions of all files in a project. A repo is similar |
| 68 | to a ZIP archive in that it is a single file that stores compressed |
| 69 | versions of many other files. Files can be extracted from the |
| 70 | repo and new files can be added to the repo, just as with a ZIP |
| 71 | archive. But a repo has other capabilities above and beyond |
| 72 |
+4
-4
| --- www/wikitheory.wiki | ||
| +++ www/wikitheory.wiki | ||
| @@ -34,26 +34,26 @@ | ||
| 34 | 34 | the wiki page will fork. The web interface will display whichever edit |
| 35 | 35 | was checked in last. The other edit can be found in the history. The |
| 36 | 36 | file format will support merging the branches back together, but there |
| 37 | 37 | is no mechanism in the user interface (yet) to perform the merge. |
| 38 | 38 | |
| 39 | -Every change to a wiki page is a separate | |
| 39 | +Every change to a wiki page is a separate | |
| 40 | 40 | [./fileformat.wiki | control artifact] |
| 41 | 41 | of type [./fileformat.wiki#wikichng | "Wiki Page"]. |
| 42 | 42 | |
| 43 | 43 | <h2>Embedded Documentation</h2> |
| 44 | 44 | |
| 45 | 45 | Files in the source tree that use the ".wiki", ".md", or ".markdown" suffixes |
| 46 | -can be accessed and displayed using special URLs to the fossil server. | |
| 46 | +can be accessed and displayed using special URLs to the fossil server. | |
| 47 | 47 | This allows |
| 48 | -project documentation to be stored in the source tree and accessed | |
| 48 | +project documentation to be stored in the source tree and accessed | |
| 49 | 49 | online. (Details are described [./embeddeddoc.wiki | separately].) |
| 50 | 50 | |
| 51 | 51 | Some projects prefer to store their documentation in wiki. There is nothing |
| 52 | 52 | wrong with that. But other projects prefer to keep documentation as part |
| 53 | 53 | of the source tree, so that it is versioned along with the source tree and |
| 54 | -so that only developers with check-in privileges can change it. | |
| 54 | +so that only developers with check-in privileges can change it. | |
| 55 | 55 | Embedded documentation serves this latter purpose. Both forms of documentation |
| 56 | 56 | use the exact same markup. Some projects may choose to |
| 57 | 57 | use both forms of documentation at the same time. Because the same |
| 58 | 58 | format is used, it is trivial to move a file from wiki to embedded documentation |
| 59 | 59 | or back again as the project evolves. |
| 60 | 60 |
| --- www/wikitheory.wiki | |
| +++ www/wikitheory.wiki | |
| @@ -34,26 +34,26 @@ | |
| 34 | the wiki page will fork. The web interface will display whichever edit |
| 35 | was checked in last. The other edit can be found in the history. The |
| 36 | file format will support merging the branches back together, but there |
| 37 | is no mechanism in the user interface (yet) to perform the merge. |
| 38 | |
| 39 | Every change to a wiki page is a separate |
| 40 | [./fileformat.wiki | control artifact] |
| 41 | of type [./fileformat.wiki#wikichng | "Wiki Page"]. |
| 42 | |
| 43 | <h2>Embedded Documentation</h2> |
| 44 | |
| 45 | Files in the source tree that use the ".wiki", ".md", or ".markdown" suffixes |
| 46 | can be accessed and displayed using special URLs to the fossil server. |
| 47 | This allows |
| 48 | project documentation to be stored in the source tree and accessed |
| 49 | online. (Details are described [./embeddeddoc.wiki | separately].) |
| 50 | |
| 51 | Some projects prefer to store their documentation in wiki. There is nothing |
| 52 | wrong with that. But other projects prefer to keep documentation as part |
| 53 | of the source tree, so that it is versioned along with the source tree and |
| 54 | so that only developers with check-in privileges can change it. |
| 55 | Embedded documentation serves this latter purpose. Both forms of documentation |
| 56 | use the exact same markup. Some projects may choose to |
| 57 | use both forms of documentation at the same time. Because the same |
| 58 | format is used, it is trivial to move a file from wiki to embedded documentation |
| 59 | or back again as the project evolves. |
| 60 |
| --- www/wikitheory.wiki | |
| +++ www/wikitheory.wiki | |
| @@ -34,26 +34,26 @@ | |
| 34 | the wiki page will fork. The web interface will display whichever edit |
| 35 | was checked in last. The other edit can be found in the history. The |
| 36 | file format will support merging the branches back together, but there |
| 37 | is no mechanism in the user interface (yet) to perform the merge. |
| 38 | |
| 39 | Every change to a wiki page is a separate |
| 40 | [./fileformat.wiki | control artifact] |
| 41 | of type [./fileformat.wiki#wikichng | "Wiki Page"]. |
| 42 | |
| 43 | <h2>Embedded Documentation</h2> |
| 44 | |
| 45 | Files in the source tree that use the ".wiki", ".md", or ".markdown" suffixes |
| 46 | can be accessed and displayed using special URLs to the fossil server. |
| 47 | This allows |
| 48 | project documentation to be stored in the source tree and accessed |
| 49 | online. (Details are described [./embeddeddoc.wiki | separately].) |
| 50 | |
| 51 | Some projects prefer to store their documentation in wiki. There is nothing |
| 52 | wrong with that. But other projects prefer to keep documentation as part |
| 53 | of the source tree, so that it is versioned along with the source tree and |
| 54 | so that only developers with check-in privileges can change it. |
| 55 | Embedded documentation serves this latter purpose. Both forms of documentation |
| 56 | use the exact same markup. Some projects may choose to |
| 57 | use both forms of documentation at the same time. Because the same |
| 58 | format is used, it is trivial to move a file from wiki to embedded documentation |
| 59 | or back again as the project evolves. |
| 60 |