Fossil SCM
merge cleanX
Commit
8e94814d8fdab83e038661c8e1fd39a3873fff18
Parent
5b40b55b6f3e35b…
62 files changed
+1
-1
+155
-40
+394
-192
+307
+1
-3
+9
-1
+9
-1
+1
-2
+7
-4
+4
-4
+73
-33
+73
-33
+4
-4
+2
-2
+1
+10
-9
-1
+8
-6
+3
-1
+4
-3
+7
-2
+5
-5
+4
-4
+48
+41
-7
+1
-1
+9
-2
+1
-6
+352
-51
+2
+1
+10
-5
+77
-21
+2
-2
+53
-37
+3
-3
+41
-13
+43
+21
-20
+580
-379
+160
-122
+3
-3
+79
-4
+1
-1
+64
-27
+1
-3
+1
-1
+2
-2
+4
-4
+28
-4
+71
-2
+83
-2
+54
-5
+21
+1
-1
+8
-8
+5
-5
+1
-1
+1
-1
+4
+1
-1
+1
-1
~
src/allrepo.c
~
src/branch.c
~
src/browse.c
~
src/bundle.c
~
src/cgi.c
~
src/checkin.c
~
src/checkin.c
~
src/checkout.c
~
src/clone.c
~
src/content.c
~
src/db.c
~
src/db.c
~
src/descendants.c
~
src/diffcmd.c
~
src/finfo.c
~
src/foci.c
~
src/fusefs.c
~
src/http.c
~
src/http_socket.c
~
src/http_ssl.c
~
src/info.c
~
src/json_branch.c
~
src/json_timeline.c
~
src/main.mk
~
src/makemake.tcl
~
src/markdown.c
~
src/mkversion.c
~
src/moderate.c
~
src/name.c
~
src/publish.c
~
src/purge.c
~
src/rebuild.c
~
src/report.c
~
src/schema.c
~
src/search.c
~
src/setup.c
~
src/shun.c
~
src/sitemap.c
~
src/sqlcmd.c
~
src/sqlite3.c
~
src/sqlite3.h
~
src/stat.c
~
src/style.c
~
src/tag.c
~
src/timeline.c
~
src/undo.c
~
src/xfer.c
~
test/valgrind-www.tcl
~
tools/fossil_chat.tcl
~
win/Makefile.dmc
~
win/Makefile.mingw
~
win/Makefile.mingw.mistachkin
~
win/Makefile.msc
~
www/checkin_names.wiki
~
www/concepts.wiki
~
www/faq.tcl
~
www/fileformat.wiki
~
www/foss-cklist.wiki
~
www/fossil-v-git.wiki
~
www/index.wiki
~
www/mkindex.tcl
~
www/server.wiki
+1
-1
| --- src/allrepo.c | ||
| +++ src/allrepo.c | ||
| @@ -76,11 +76,11 @@ | ||
| 76 | 76 | |
| 77 | 77 | |
| 78 | 78 | /* |
| 79 | 79 | ** COMMAND: all |
| 80 | 80 | ** |
| 81 | -** Usage: %fossil all (changes|clean|extras|ignore|list|ls|pull|push|rebuild|sync) | |
| 81 | +** Usage: %fossil all SUBCOMMAND ... | |
| 82 | 82 | ** |
| 83 | 83 | ** The ~/.fossil file records the location of all repositories for a |
| 84 | 84 | ** user. This command performs certain operations on all repositories |
| 85 | 85 | ** that can be useful before or after a period of disconnected operation. |
| 86 | 86 | ** |
| 87 | 87 |
| --- src/allrepo.c | |
| +++ src/allrepo.c | |
| @@ -76,11 +76,11 @@ | |
| 76 | |
| 77 | |
| 78 | /* |
| 79 | ** COMMAND: all |
| 80 | ** |
| 81 | ** Usage: %fossil all (changes|clean|extras|ignore|list|ls|pull|push|rebuild|sync) |
| 82 | ** |
| 83 | ** The ~/.fossil file records the location of all repositories for a |
| 84 | ** user. This command performs certain operations on all repositories |
| 85 | ** that can be useful before or after a period of disconnected operation. |
| 86 | ** |
| 87 |
| --- src/allrepo.c | |
| +++ src/allrepo.c | |
| @@ -76,11 +76,11 @@ | |
| 76 | |
| 77 | |
| 78 | /* |
| 79 | ** COMMAND: all |
| 80 | ** |
| 81 | ** Usage: %fossil all SUBCOMMAND ... |
| 82 | ** |
| 83 | ** The ~/.fossil file records the location of all repositories for a |
| 84 | ** user. This command performs certain operations on all repositories |
| 85 | ** that can be useful before or after a period of disconnected operation. |
| 86 | ** |
| 87 |
+155
-40
| --- src/branch.c | ||
| +++ src/branch.c | ||
| @@ -179,47 +179,67 @@ | ||
| 179 | 179 | |
| 180 | 180 | /* Do an autosync push, if requested */ |
| 181 | 181 | if( !isPrivate ) autosync_loop(SYNC_PUSH, db_get_int("autosync-tries", 1)); |
| 182 | 182 | } |
| 183 | 183 | |
| 184 | +#if INTERFACE | |
| 185 | +/* | |
| 186 | +** Allows bits in the mBplqFlags parameter to branch_prepare_list_query(). | |
| 187 | +*/ | |
| 188 | +#define BRL_CLOSED_ONLY 0x001 /* Show only closed branches */ | |
| 189 | +#define BRL_OPEN_ONLY 0x002 /* Show only open branches */ | |
| 190 | +#define BRL_BOTH 0x003 /* Show both open and closed branches */ | |
| 191 | +#define BRL_OPEN_CLOSED_MASK 0x003 | |
| 192 | +#define BRL_MTIME 0x004 /* Include lastest check-in time */ | |
| 193 | +#dfeine BRL_ORDERBY_MTIME 0x008 /* Sort by MTIME. (otherwise sort by name)*/ | |
| 194 | + | |
| 195 | +#endif /* INTERFACE */ | |
| 196 | + | |
| 184 | 197 | /* |
| 185 | 198 | ** Prepare a query that will list branches. |
| 186 | 199 | ** |
| 187 | 200 | ** If (which<0) then the query pulls only closed branches. If |
| 188 | 201 | ** (which>0) then the query pulls all (closed and opened) |
| 189 | 202 | ** branches. Else the query pulls currently-opened branches. |
| 190 | 203 | */ |
| 191 | -void branch_prepare_list_query(Stmt *pQuery, int which ){ | |
| 192 | - if( which < 0 ){ | |
| 193 | - db_prepare(pQuery, | |
| 194 | - "SELECT value FROM tagxref" | |
| 195 | - " WHERE tagid=%d AND value NOT NULL " | |
| 196 | - "EXCEPT " | |
| 197 | - "SELECT value FROM tagxref" | |
| 198 | - " WHERE tagid=%d" | |
| 199 | - " AND rid IN leaf" | |
| 200 | - " AND NOT %z" | |
| 201 | - " ORDER BY value COLLATE nocase /*sort*/", | |
| 202 | - TAG_BRANCH, TAG_BRANCH, leaf_is_closed_sql("tagxref.rid") | |
| 203 | - ); | |
| 204 | - }else if( which>0 ){ | |
| 205 | - db_prepare(pQuery, | |
| 206 | - "SELECT DISTINCT value FROM tagxref" | |
| 207 | - " WHERE tagid=%d AND value NOT NULL" | |
| 208 | - " AND rid IN leaf" | |
| 209 | - " ORDER BY value COLLATE nocase /*sort*/", | |
| 210 | - TAG_BRANCH | |
| 211 | - ); | |
| 212 | - }else{ | |
| 213 | - db_prepare(pQuery, | |
| 214 | - "SELECT DISTINCT value FROM tagxref" | |
| 215 | - " WHERE tagid=%d AND value NOT NULL" | |
| 216 | - " AND rid IN leaf" | |
| 217 | - " AND NOT %z" | |
| 218 | - " ORDER BY value COLLATE nocase /*sort*/", | |
| 219 | - TAG_BRANCH, leaf_is_closed_sql("tagxref.rid") | |
| 220 | - ); | |
| 204 | +void branch_prepare_list_query(Stmt *pQuery, int brFlags){ | |
| 205 | + switch( brFlags & BRL_OPEN_CLOSED_MASK ){ | |
| 206 | + case BRL_CLOSED_ONLY: { | |
| 207 | + db_prepare(pQuery, | |
| 208 | + "SELECT value FROM tagxref" | |
| 209 | + " WHERE tagid=%d AND value NOT NULL " | |
| 210 | + "EXCEPT " | |
| 211 | + "SELECT value FROM tagxref" | |
| 212 | + " WHERE tagid=%d" | |
| 213 | + " AND rid IN leaf" | |
| 214 | + " AND NOT %z" | |
| 215 | + " ORDER BY value COLLATE nocase /*sort*/", | |
| 216 | + TAG_BRANCH, TAG_BRANCH, leaf_is_closed_sql("tagxref.rid") | |
| 217 | + ); | |
| 218 | + break; | |
| 219 | + } | |
| 220 | + case BRL_BOTH: { | |
| 221 | + db_prepare(pQuery, | |
| 222 | + "SELECT DISTINCT value FROM tagxref" | |
| 223 | + " WHERE tagid=%d AND value NOT NULL" | |
| 224 | + " AND rid IN leaf" | |
| 225 | + " ORDER BY value COLLATE nocase /*sort*/", | |
| 226 | + TAG_BRANCH | |
| 227 | + ); | |
| 228 | + break; | |
| 229 | + } | |
| 230 | + case BRL_OPEN_ONLY: { | |
| 231 | + db_prepare(pQuery, | |
| 232 | + "SELECT DISTINCT value FROM tagxref" | |
| 233 | + " WHERE tagid=%d AND value NOT NULL" | |
| 234 | + " AND rid IN leaf" | |
| 235 | + " AND NOT %z" | |
| 236 | + " ORDER BY value COLLATE nocase /*sort*/", | |
| 237 | + TAG_BRANCH, leaf_is_closed_sql("tagxref.rid") | |
| 238 | + ); | |
| 239 | + break; | |
| 240 | + } | |
| 221 | 241 | } |
| 222 | 242 | } |
| 223 | 243 | |
| 224 | 244 | |
| 225 | 245 | /* |
| @@ -260,19 +280,20 @@ | ||
| 260 | 280 | branch_new(); |
| 261 | 281 | }else if( (strncmp(zCmd,"list",n)==0)||(strncmp(zCmd, "ls", n)==0) ){ |
| 262 | 282 | Stmt q; |
| 263 | 283 | int vid; |
| 264 | 284 | char *zCurrent = 0; |
| 265 | - int showAll = find_option("all","a",0)!=0; | |
| 266 | - int showClosed = find_option("closed","c",0)!=0; | |
| 285 | + int brFlags = BRL_OPEN_ONLY; | |
| 286 | + if( find_option("all","a",0)!=0 ) brFlags = BRL_BOTH; | |
| 287 | + if( find_option("closed","c",0)!=0 ) brFlags = BRL_CLOSED_ONLY; | |
| 267 | 288 | |
| 268 | 289 | if( g.localOpen ){ |
| 269 | 290 | vid = db_lget_int("checkout", 0); |
| 270 | 291 | zCurrent = db_text(0, "SELECT value FROM tagxref" |
| 271 | 292 | " WHERE rid=%d AND tagid=%d", vid, TAG_BRANCH); |
| 272 | 293 | } |
| 273 | - branch_prepare_list_query(&q, showAll?1:(showClosed?-1:0)); | |
| 294 | + branch_prepare_list_query(&q, brFlags); | |
| 274 | 295 | while( db_step(&q)==SQLITE_ROW ){ |
| 275 | 296 | const char *zBr = db_column_text(&q, 0); |
| 276 | 297 | int isCur = zCurrent!=0 && fossil_strcmp(zCurrent,zBr)==0; |
| 277 | 298 | fossil_print("%s%s\n", (isCur ? "* " : " "), zBr); |
| 278 | 299 | } |
| @@ -280,36 +301,130 @@ | ||
| 280 | 301 | }else{ |
| 281 | 302 | fossil_fatal("branch subcommand should be one of: " |
| 282 | 303 | "new list ls"); |
| 283 | 304 | } |
| 284 | 305 | } |
| 306 | + | |
| 307 | +static char brlistQuery[] = | |
| 308 | +@ SELECT | |
| 309 | +@ tagxref.value, | |
| 310 | +@ max(event.mtime), | |
| 311 | +@ EXISTS(SELECT 1 FROM tagxref AS tx | |
| 312 | +@ WHERE tx.rid=tagxref.rid | |
| 313 | +@ AND tx.tagid=(SELECT tagid FROM tag WHERE tagname='closed') | |
| 314 | +@ AND tx.tagtype>0), | |
| 315 | +@ (SELECT tagxref.value | |
| 316 | +@ FROM plink CROSS JOIN tagxref | |
| 317 | +@ WHERE plink.pid=event.objid | |
| 318 | +@ AND tagxref.rid=plink.cid | |
| 319 | +@ AND tagxref.tagid=(SELECT tagid FROM tag WHERE tagname='branch') | |
| 320 | +@ AND tagtype>0), | |
| 321 | +@ count(*), | |
| 322 | +@ (SELECT uuid FROM blob WHERE rid=tagxref.rid) | |
| 323 | +@ FROM tagxref, tag, event | |
| 324 | +@ WHERE tagxref.tagid=tag.tagid | |
| 325 | +@ AND tagxref.tagtype>0 | |
| 326 | +@ AND tag.tagname='branch' | |
| 327 | +@ AND event.objid=tagxref.rid | |
| 328 | +@ GROUP BY 1 | |
| 329 | +@ ORDER BY 2 DESC; | |
| 330 | +; | |
| 331 | + | |
| 332 | +/* | |
| 333 | +** This is the new-style branch-list page that shows the branch names | |
| 334 | +** together with their ages (time of last check-in) and whether or not | |
| 335 | +** they are closed or merged to another branch. | |
| 336 | +** | |
| 337 | +** Control jumps to this routine from brlist_page() (the /brlist handler) | |
| 338 | +** if there are no query parameters. | |
| 339 | +*/ | |
| 340 | +static void new_brlist_page(void){ | |
| 341 | + Stmt q; | |
| 342 | + double rNow; | |
| 343 | + login_check_credentials(); | |
| 344 | + if( !g.perm.Read ){ login_needed(); return; } | |
| 345 | + style_header("Branches"); | |
| 346 | + login_anonymous_available(); | |
| 347 | + | |
| 348 | + db_prepare(&q, brlistQuery/*works-like:""*/); | |
| 349 | + rNow = db_double(0.0, "SELECT julianday('now')"); | |
| 350 | + @ <div class="brlist"><table id="branchlisttable"> | |
| 351 | + @ <thead><tr> | |
| 352 | + @ <th>Branch Name</th> | |
| 353 | + @ <th>Age</th> | |
| 354 | + @ <th>Checkins</th> | |
| 355 | + @ <th>Status</th> | |
| 356 | + @ <th>Resolution</th> | |
| 357 | + @ </tr></thead><tbody> | |
| 358 | + while( db_step(&q)==SQLITE_ROW ){ | |
| 359 | + const char *zBranch = db_column_text(&q, 0); | |
| 360 | + double rMtime = db_column_double(&q, 1); | |
| 361 | + int isClosed = db_column_int(&q, 2); | |
| 362 | + const char *zMergeTo = db_column_text(&q, 3); | |
| 363 | + int nCkin = db_column_int(&q, 4); | |
| 364 | + const char *zLastCkin = db_column_text(&q, 5); | |
| 365 | + char *zAge = human_readable_age(rNow - rMtime); | |
| 366 | + sqlite3_int64 iMtime = (sqlite3_int64)(rMtime*86400.0); | |
| 367 | + if( zMergeTo && zMergeTo[0]==0 ) zMergeTo = 0; | |
| 368 | + @ <tr> | |
| 369 | + @ <td>%z(href("%R/timeline?n=100&r=%T",zBranch))%h(zBranch)</a></td> | |
| 370 | + @ <td data-sortkey="%016llx(-iMtime)">%s(zAge)</td> | |
| 371 | + @ <td data-sortkey="%08x(-nCkin)">%d(nCkin)</td> | |
| 372 | + fossil_free(zAge); | |
| 373 | + @ <td>%s(isClosed?"closed":"")</td> | |
| 374 | + if( zMergeTo ){ | |
| 375 | + @ <td>merged into | |
| 376 | + @ %z(href("%R/timeline?f=%s",zLastCkin))%h(zMergeTo)</a></td> | |
| 377 | + }else{ | |
| 378 | + @ <td></td> | |
| 379 | + } | |
| 380 | + @ </tr> | |
| 381 | + } | |
| 382 | + @ </tbody></table></div> | |
| 383 | + db_finalize(&q); | |
| 384 | + output_table_sorting_javascript("branchlisttable","tkktt",2); | |
| 385 | + style_footer(); | |
| 386 | +} | |
| 285 | 387 | |
| 286 | 388 | /* |
| 287 | 389 | ** WEBPAGE: brlist |
| 390 | +** Show a list of branches | |
| 391 | +** Query parameters: | |
| 288 | 392 | ** |
| 289 | -** Show a timeline of all branches | |
| 393 | +** all Show all branches | |
| 394 | +** closed Show only closed branches | |
| 395 | +** open Show only open branches (default behavior) | |
| 396 | +** colortest Show all branches with automatic color | |
| 290 | 397 | */ |
| 291 | 398 | void brlist_page(void){ |
| 292 | 399 | Stmt q; |
| 293 | 400 | int cnt; |
| 294 | 401 | int showClosed = P("closed")!=0; |
| 295 | 402 | int showAll = P("all")!=0; |
| 403 | + int showOpen = P("open")!=0; | |
| 296 | 404 | int colorTest = P("colortest")!=0; |
| 405 | + int brFlags = BRL_OPEN_ONLY; | |
| 297 | 406 | |
| 407 | + if( showClosed==0 && showAll==0 && showOpen==0 && colorTest==0 ){ | |
| 408 | + new_brlist_page(); | |
| 409 | + return; | |
| 410 | + } | |
| 298 | 411 | login_check_credentials(); |
| 299 | 412 | if( !g.perm.Read ){ login_needed(); return; } |
| 300 | 413 | if( colorTest ){ |
| 301 | 414 | showClosed = 0; |
| 302 | 415 | showAll = 1; |
| 303 | 416 | } |
| 417 | + if( showAll ) brFlags = BRL_BOTH; | |
| 418 | + if( showClosed ) brFlags = BRL_CLOSED_ONLY; | |
| 304 | 419 | |
| 305 | 420 | style_header("%s", showClosed ? "Closed Branches" : |
| 306 | 421 | showAll ? "All Branches" : "Open Branches"); |
| 307 | 422 | style_submenu_element("Timeline", "Timeline", "brtimeline"); |
| 308 | 423 | if( showClosed ){ |
| 309 | 424 | style_submenu_element("All", "All", "brlist?all"); |
| 310 | - style_submenu_element("Open","Open","brlist"); | |
| 425 | + style_submenu_element("Open","Open","brlist?open"); | |
| 311 | 426 | }else if( showAll ){ |
| 312 | 427 | style_submenu_element("Closed", "Closed", "brlist?closed"); |
| 313 | 428 | style_submenu_element("Open","Open","brlist"); |
| 314 | 429 | }else{ |
| 315 | 430 | style_submenu_element("All", "All", "brlist?all"); |
| @@ -335,21 +450,21 @@ | ||
| 335 | 450 | @ Closed branches are fixed and do not change (unless they are first |
| 336 | 451 | @ reopened).</li> |
| 337 | 452 | @ </ol> |
| 338 | 453 | style_sidebox_end(); |
| 339 | 454 | |
| 340 | - branch_prepare_list_query(&q, showAll?1:(showClosed?-1:0)); | |
| 455 | + branch_prepare_list_query(&q, brFlags); | |
| 341 | 456 | cnt = 0; |
| 342 | 457 | while( db_step(&q)==SQLITE_ROW ){ |
| 343 | 458 | const char *zBr = db_column_text(&q, 0); |
| 344 | 459 | if( cnt==0 ){ |
| 345 | 460 | if( colorTest ){ |
| 346 | 461 | @ <h2>Default background colors for all branches:</h2> |
| 462 | + }else if( showClosed ){ | |
| 463 | + @ <h2>Closed Branches:</h2> | |
| 347 | 464 | }else if( showAll ){ |
| 348 | 465 | @ <h2>All Branches:</h2> |
| 349 | - }else if( showClosed ){ | |
| 350 | - @ <h2>Closed Branches:</h2> | |
| 351 | 466 | }else{ |
| 352 | 467 | @ <h2>Open Branches:</h2> |
| 353 | 468 | } |
| 354 | 469 | @ <ul> |
| 355 | 470 | cnt++; |
| @@ -357,11 +472,11 @@ | ||
| 357 | 472 | if( colorTest ){ |
| 358 | 473 | const char *zColor = hash_color(zBr); |
| 359 | 474 | @ <li><span style="background-color: %s(zColor)"> |
| 360 | 475 | @ %h(zBr) → %s(zColor)</span></li> |
| 361 | 476 | }else{ |
| 362 | - @ <li>%z(href("%R/timeline?r=%T",zBr))%h(zBr)</a></li> | |
| 477 | + @ <li>%z(href("%R/timeline?r=%T&n=200",zBr))%h(zBr)</a></li> | |
| 363 | 478 | } |
| 364 | 479 | } |
| 365 | 480 | if( cnt ){ |
| 366 | 481 | @ </ul> |
| 367 | 482 | } |
| @@ -385,11 +500,11 @@ | ||
| 385 | 500 | " AND tag.tagname GLOB 'sym-*'", |
| 386 | 501 | rid |
| 387 | 502 | ); |
| 388 | 503 | while( db_step(&q)==SQLITE_ROW ){ |
| 389 | 504 | const char *zTagName = db_column_text(&q, 0); |
| 390 | - @ %z(href("%R/timeline?r=%T",zTagName))[timeline]</a> | |
| 505 | + @ %z(href("%R/timeline?r=%T&n=200",zTagName))[timeline]</a> | |
| 391 | 506 | } |
| 392 | 507 | db_finalize(&q); |
| 393 | 508 | } |
| 394 | 509 | |
| 395 | 510 | /* |
| 396 | 511 |
| --- src/branch.c | |
| +++ src/branch.c | |
| @@ -179,47 +179,67 @@ | |
| 179 | |
| 180 | /* Do an autosync push, if requested */ |
| 181 | if( !isPrivate ) autosync_loop(SYNC_PUSH, db_get_int("autosync-tries", 1)); |
| 182 | } |
| 183 | |
| 184 | /* |
| 185 | ** Prepare a query that will list branches. |
| 186 | ** |
| 187 | ** If (which<0) then the query pulls only closed branches. If |
| 188 | ** (which>0) then the query pulls all (closed and opened) |
| 189 | ** branches. Else the query pulls currently-opened branches. |
| 190 | */ |
| 191 | void branch_prepare_list_query(Stmt *pQuery, int which ){ |
| 192 | if( which < 0 ){ |
| 193 | db_prepare(pQuery, |
| 194 | "SELECT value FROM tagxref" |
| 195 | " WHERE tagid=%d AND value NOT NULL " |
| 196 | "EXCEPT " |
| 197 | "SELECT value FROM tagxref" |
| 198 | " WHERE tagid=%d" |
| 199 | " AND rid IN leaf" |
| 200 | " AND NOT %z" |
| 201 | " ORDER BY value COLLATE nocase /*sort*/", |
| 202 | TAG_BRANCH, TAG_BRANCH, leaf_is_closed_sql("tagxref.rid") |
| 203 | ); |
| 204 | }else if( which>0 ){ |
| 205 | db_prepare(pQuery, |
| 206 | "SELECT DISTINCT value FROM tagxref" |
| 207 | " WHERE tagid=%d AND value NOT NULL" |
| 208 | " AND rid IN leaf" |
| 209 | " ORDER BY value COLLATE nocase /*sort*/", |
| 210 | TAG_BRANCH |
| 211 | ); |
| 212 | }else{ |
| 213 | db_prepare(pQuery, |
| 214 | "SELECT DISTINCT value FROM tagxref" |
| 215 | " WHERE tagid=%d AND value NOT NULL" |
| 216 | " AND rid IN leaf" |
| 217 | " AND NOT %z" |
| 218 | " ORDER BY value COLLATE nocase /*sort*/", |
| 219 | TAG_BRANCH, leaf_is_closed_sql("tagxref.rid") |
| 220 | ); |
| 221 | } |
| 222 | } |
| 223 | |
| 224 | |
| 225 | /* |
| @@ -260,19 +280,20 @@ | |
| 260 | branch_new(); |
| 261 | }else if( (strncmp(zCmd,"list",n)==0)||(strncmp(zCmd, "ls", n)==0) ){ |
| 262 | Stmt q; |
| 263 | int vid; |
| 264 | char *zCurrent = 0; |
| 265 | int showAll = find_option("all","a",0)!=0; |
| 266 | int showClosed = find_option("closed","c",0)!=0; |
| 267 | |
| 268 | if( g.localOpen ){ |
| 269 | vid = db_lget_int("checkout", 0); |
| 270 | zCurrent = db_text(0, "SELECT value FROM tagxref" |
| 271 | " WHERE rid=%d AND tagid=%d", vid, TAG_BRANCH); |
| 272 | } |
| 273 | branch_prepare_list_query(&q, showAll?1:(showClosed?-1:0)); |
| 274 | while( db_step(&q)==SQLITE_ROW ){ |
| 275 | const char *zBr = db_column_text(&q, 0); |
| 276 | int isCur = zCurrent!=0 && fossil_strcmp(zCurrent,zBr)==0; |
| 277 | fossil_print("%s%s\n", (isCur ? "* " : " "), zBr); |
| 278 | } |
| @@ -280,36 +301,130 @@ | |
| 280 | }else{ |
| 281 | fossil_fatal("branch subcommand should be one of: " |
| 282 | "new list ls"); |
| 283 | } |
| 284 | } |
| 285 | |
| 286 | /* |
| 287 | ** WEBPAGE: brlist |
| 288 | ** |
| 289 | ** Show a timeline of all branches |
| 290 | */ |
| 291 | void brlist_page(void){ |
| 292 | Stmt q; |
| 293 | int cnt; |
| 294 | int showClosed = P("closed")!=0; |
| 295 | int showAll = P("all")!=0; |
| 296 | int colorTest = P("colortest")!=0; |
| 297 | |
| 298 | login_check_credentials(); |
| 299 | if( !g.perm.Read ){ login_needed(); return; } |
| 300 | if( colorTest ){ |
| 301 | showClosed = 0; |
| 302 | showAll = 1; |
| 303 | } |
| 304 | |
| 305 | style_header("%s", showClosed ? "Closed Branches" : |
| 306 | showAll ? "All Branches" : "Open Branches"); |
| 307 | style_submenu_element("Timeline", "Timeline", "brtimeline"); |
| 308 | if( showClosed ){ |
| 309 | style_submenu_element("All", "All", "brlist?all"); |
| 310 | style_submenu_element("Open","Open","brlist"); |
| 311 | }else if( showAll ){ |
| 312 | style_submenu_element("Closed", "Closed", "brlist?closed"); |
| 313 | style_submenu_element("Open","Open","brlist"); |
| 314 | }else{ |
| 315 | style_submenu_element("All", "All", "brlist?all"); |
| @@ -335,21 +450,21 @@ | |
| 335 | @ Closed branches are fixed and do not change (unless they are first |
| 336 | @ reopened).</li> |
| 337 | @ </ol> |
| 338 | style_sidebox_end(); |
| 339 | |
| 340 | branch_prepare_list_query(&q, showAll?1:(showClosed?-1:0)); |
| 341 | cnt = 0; |
| 342 | while( db_step(&q)==SQLITE_ROW ){ |
| 343 | const char *zBr = db_column_text(&q, 0); |
| 344 | if( cnt==0 ){ |
| 345 | if( colorTest ){ |
| 346 | @ <h2>Default background colors for all branches:</h2> |
| 347 | }else if( showAll ){ |
| 348 | @ <h2>All Branches:</h2> |
| 349 | }else if( showClosed ){ |
| 350 | @ <h2>Closed Branches:</h2> |
| 351 | }else{ |
| 352 | @ <h2>Open Branches:</h2> |
| 353 | } |
| 354 | @ <ul> |
| 355 | cnt++; |
| @@ -357,11 +472,11 @@ | |
| 357 | if( colorTest ){ |
| 358 | const char *zColor = hash_color(zBr); |
| 359 | @ <li><span style="background-color: %s(zColor)"> |
| 360 | @ %h(zBr) → %s(zColor)</span></li> |
| 361 | }else{ |
| 362 | @ <li>%z(href("%R/timeline?r=%T",zBr))%h(zBr)</a></li> |
| 363 | } |
| 364 | } |
| 365 | if( cnt ){ |
| 366 | @ </ul> |
| 367 | } |
| @@ -385,11 +500,11 @@ | |
| 385 | " AND tag.tagname GLOB 'sym-*'", |
| 386 | rid |
| 387 | ); |
| 388 | while( db_step(&q)==SQLITE_ROW ){ |
| 389 | const char *zTagName = db_column_text(&q, 0); |
| 390 | @ %z(href("%R/timeline?r=%T",zTagName))[timeline]</a> |
| 391 | } |
| 392 | db_finalize(&q); |
| 393 | } |
| 394 | |
| 395 | /* |
| 396 |
| --- src/branch.c | |
| +++ src/branch.c | |
| @@ -179,47 +179,67 @@ | |
| 179 | |
| 180 | /* Do an autosync push, if requested */ |
| 181 | if( !isPrivate ) autosync_loop(SYNC_PUSH, db_get_int("autosync-tries", 1)); |
| 182 | } |
| 183 | |
| 184 | #if INTERFACE |
| 185 | /* |
| 186 | ** Allows bits in the mBplqFlags parameter to branch_prepare_list_query(). |
| 187 | */ |
| 188 | #define BRL_CLOSED_ONLY 0x001 /* Show only closed branches */ |
| 189 | #define BRL_OPEN_ONLY 0x002 /* Show only open branches */ |
| 190 | #define BRL_BOTH 0x003 /* Show both open and closed branches */ |
| 191 | #define BRL_OPEN_CLOSED_MASK 0x003 |
| 192 | #define BRL_MTIME 0x004 /* Include lastest check-in time */ |
| 193 | #dfeine BRL_ORDERBY_MTIME 0x008 /* Sort by MTIME. (otherwise sort by name)*/ |
| 194 | |
| 195 | #endif /* INTERFACE */ |
| 196 | |
| 197 | /* |
| 198 | ** Prepare a query that will list branches. |
| 199 | ** |
| 200 | ** If (which<0) then the query pulls only closed branches. If |
| 201 | ** (which>0) then the query pulls all (closed and opened) |
| 202 | ** branches. Else the query pulls currently-opened branches. |
| 203 | */ |
| 204 | void branch_prepare_list_query(Stmt *pQuery, int brFlags){ |
| 205 | switch( brFlags & BRL_OPEN_CLOSED_MASK ){ |
| 206 | case BRL_CLOSED_ONLY: { |
| 207 | db_prepare(pQuery, |
| 208 | "SELECT value FROM tagxref" |
| 209 | " WHERE tagid=%d AND value NOT NULL " |
| 210 | "EXCEPT " |
| 211 | "SELECT value FROM tagxref" |
| 212 | " WHERE tagid=%d" |
| 213 | " AND rid IN leaf" |
| 214 | " AND NOT %z" |
| 215 | " ORDER BY value COLLATE nocase /*sort*/", |
| 216 | TAG_BRANCH, TAG_BRANCH, leaf_is_closed_sql("tagxref.rid") |
| 217 | ); |
| 218 | break; |
| 219 | } |
| 220 | case BRL_BOTH: { |
| 221 | db_prepare(pQuery, |
| 222 | "SELECT DISTINCT value FROM tagxref" |
| 223 | " WHERE tagid=%d AND value NOT NULL" |
| 224 | " AND rid IN leaf" |
| 225 | " ORDER BY value COLLATE nocase /*sort*/", |
| 226 | TAG_BRANCH |
| 227 | ); |
| 228 | break; |
| 229 | } |
| 230 | case BRL_OPEN_ONLY: { |
| 231 | db_prepare(pQuery, |
| 232 | "SELECT DISTINCT value FROM tagxref" |
| 233 | " WHERE tagid=%d AND value NOT NULL" |
| 234 | " AND rid IN leaf" |
| 235 | " AND NOT %z" |
| 236 | " ORDER BY value COLLATE nocase /*sort*/", |
| 237 | TAG_BRANCH, leaf_is_closed_sql("tagxref.rid") |
| 238 | ); |
| 239 | break; |
| 240 | } |
| 241 | } |
| 242 | } |
| 243 | |
| 244 | |
| 245 | /* |
| @@ -260,19 +280,20 @@ | |
| 280 | branch_new(); |
| 281 | }else if( (strncmp(zCmd,"list",n)==0)||(strncmp(zCmd, "ls", n)==0) ){ |
| 282 | Stmt q; |
| 283 | int vid; |
| 284 | char *zCurrent = 0; |
| 285 | int brFlags = BRL_OPEN_ONLY; |
| 286 | if( find_option("all","a",0)!=0 ) brFlags = BRL_BOTH; |
| 287 | if( find_option("closed","c",0)!=0 ) brFlags = BRL_CLOSED_ONLY; |
| 288 | |
| 289 | if( g.localOpen ){ |
| 290 | vid = db_lget_int("checkout", 0); |
| 291 | zCurrent = db_text(0, "SELECT value FROM tagxref" |
| 292 | " WHERE rid=%d AND tagid=%d", vid, TAG_BRANCH); |
| 293 | } |
| 294 | branch_prepare_list_query(&q, brFlags); |
| 295 | while( db_step(&q)==SQLITE_ROW ){ |
| 296 | const char *zBr = db_column_text(&q, 0); |
| 297 | int isCur = zCurrent!=0 && fossil_strcmp(zCurrent,zBr)==0; |
| 298 | fossil_print("%s%s\n", (isCur ? "* " : " "), zBr); |
| 299 | } |
| @@ -280,36 +301,130 @@ | |
| 301 | }else{ |
| 302 | fossil_fatal("branch subcommand should be one of: " |
| 303 | "new list ls"); |
| 304 | } |
| 305 | } |
| 306 | |
| 307 | static char brlistQuery[] = |
| 308 | @ SELECT |
| 309 | @ tagxref.value, |
| 310 | @ max(event.mtime), |
| 311 | @ EXISTS(SELECT 1 FROM tagxref AS tx |
| 312 | @ WHERE tx.rid=tagxref.rid |
| 313 | @ AND tx.tagid=(SELECT tagid FROM tag WHERE tagname='closed') |
| 314 | @ AND tx.tagtype>0), |
| 315 | @ (SELECT tagxref.value |
| 316 | @ FROM plink CROSS JOIN tagxref |
| 317 | @ WHERE plink.pid=event.objid |
| 318 | @ AND tagxref.rid=plink.cid |
| 319 | @ AND tagxref.tagid=(SELECT tagid FROM tag WHERE tagname='branch') |
| 320 | @ AND tagtype>0), |
| 321 | @ count(*), |
| 322 | @ (SELECT uuid FROM blob WHERE rid=tagxref.rid) |
| 323 | @ FROM tagxref, tag, event |
| 324 | @ WHERE tagxref.tagid=tag.tagid |
| 325 | @ AND tagxref.tagtype>0 |
| 326 | @ AND tag.tagname='branch' |
| 327 | @ AND event.objid=tagxref.rid |
| 328 | @ GROUP BY 1 |
| 329 | @ ORDER BY 2 DESC; |
| 330 | ; |
| 331 | |
| 332 | /* |
| 333 | ** This is the new-style branch-list page that shows the branch names |
| 334 | ** together with their ages (time of last check-in) and whether or not |
| 335 | ** they are closed or merged to another branch. |
| 336 | ** |
| 337 | ** Control jumps to this routine from brlist_page() (the /brlist handler) |
| 338 | ** if there are no query parameters. |
| 339 | */ |
| 340 | static void new_brlist_page(void){ |
| 341 | Stmt q; |
| 342 | double rNow; |
| 343 | login_check_credentials(); |
| 344 | if( !g.perm.Read ){ login_needed(); return; } |
| 345 | style_header("Branches"); |
| 346 | login_anonymous_available(); |
| 347 | |
| 348 | db_prepare(&q, brlistQuery/*works-like:""*/); |
| 349 | rNow = db_double(0.0, "SELECT julianday('now')"); |
| 350 | @ <div class="brlist"><table id="branchlisttable"> |
| 351 | @ <thead><tr> |
| 352 | @ <th>Branch Name</th> |
| 353 | @ <th>Age</th> |
| 354 | @ <th>Checkins</th> |
| 355 | @ <th>Status</th> |
| 356 | @ <th>Resolution</th> |
| 357 | @ </tr></thead><tbody> |
| 358 | while( db_step(&q)==SQLITE_ROW ){ |
| 359 | const char *zBranch = db_column_text(&q, 0); |
| 360 | double rMtime = db_column_double(&q, 1); |
| 361 | int isClosed = db_column_int(&q, 2); |
| 362 | const char *zMergeTo = db_column_text(&q, 3); |
| 363 | int nCkin = db_column_int(&q, 4); |
| 364 | const char *zLastCkin = db_column_text(&q, 5); |
| 365 | char *zAge = human_readable_age(rNow - rMtime); |
| 366 | sqlite3_int64 iMtime = (sqlite3_int64)(rMtime*86400.0); |
| 367 | if( zMergeTo && zMergeTo[0]==0 ) zMergeTo = 0; |
| 368 | @ <tr> |
| 369 | @ <td>%z(href("%R/timeline?n=100&r=%T",zBranch))%h(zBranch)</a></td> |
| 370 | @ <td data-sortkey="%016llx(-iMtime)">%s(zAge)</td> |
| 371 | @ <td data-sortkey="%08x(-nCkin)">%d(nCkin)</td> |
| 372 | fossil_free(zAge); |
| 373 | @ <td>%s(isClosed?"closed":"")</td> |
| 374 | if( zMergeTo ){ |
| 375 | @ <td>merged into |
| 376 | @ %z(href("%R/timeline?f=%s",zLastCkin))%h(zMergeTo)</a></td> |
| 377 | }else{ |
| 378 | @ <td></td> |
| 379 | } |
| 380 | @ </tr> |
| 381 | } |
| 382 | @ </tbody></table></div> |
| 383 | db_finalize(&q); |
| 384 | output_table_sorting_javascript("branchlisttable","tkktt",2); |
| 385 | style_footer(); |
| 386 | } |
| 387 | |
| 388 | /* |
| 389 | ** WEBPAGE: brlist |
| 390 | ** Show a list of branches |
| 391 | ** Query parameters: |
| 392 | ** |
| 393 | ** all Show all branches |
| 394 | ** closed Show only closed branches |
| 395 | ** open Show only open branches (default behavior) |
| 396 | ** colortest Show all branches with automatic color |
| 397 | */ |
| 398 | void brlist_page(void){ |
| 399 | Stmt q; |
| 400 | int cnt; |
| 401 | int showClosed = P("closed")!=0; |
| 402 | int showAll = P("all")!=0; |
| 403 | int showOpen = P("open")!=0; |
| 404 | int colorTest = P("colortest")!=0; |
| 405 | int brFlags = BRL_OPEN_ONLY; |
| 406 | |
| 407 | if( showClosed==0 && showAll==0 && showOpen==0 && colorTest==0 ){ |
| 408 | new_brlist_page(); |
| 409 | return; |
| 410 | } |
| 411 | login_check_credentials(); |
| 412 | if( !g.perm.Read ){ login_needed(); return; } |
| 413 | if( colorTest ){ |
| 414 | showClosed = 0; |
| 415 | showAll = 1; |
| 416 | } |
| 417 | if( showAll ) brFlags = BRL_BOTH; |
| 418 | if( showClosed ) brFlags = BRL_CLOSED_ONLY; |
| 419 | |
| 420 | style_header("%s", showClosed ? "Closed Branches" : |
| 421 | showAll ? "All Branches" : "Open Branches"); |
| 422 | style_submenu_element("Timeline", "Timeline", "brtimeline"); |
| 423 | if( showClosed ){ |
| 424 | style_submenu_element("All", "All", "brlist?all"); |
| 425 | style_submenu_element("Open","Open","brlist?open"); |
| 426 | }else if( showAll ){ |
| 427 | style_submenu_element("Closed", "Closed", "brlist?closed"); |
| 428 | style_submenu_element("Open","Open","brlist"); |
| 429 | }else{ |
| 430 | style_submenu_element("All", "All", "brlist?all"); |
| @@ -335,21 +450,21 @@ | |
| 450 | @ Closed branches are fixed and do not change (unless they are first |
| 451 | @ reopened).</li> |
| 452 | @ </ol> |
| 453 | style_sidebox_end(); |
| 454 | |
| 455 | branch_prepare_list_query(&q, brFlags); |
| 456 | cnt = 0; |
| 457 | while( db_step(&q)==SQLITE_ROW ){ |
| 458 | const char *zBr = db_column_text(&q, 0); |
| 459 | if( cnt==0 ){ |
| 460 | if( colorTest ){ |
| 461 | @ <h2>Default background colors for all branches:</h2> |
| 462 | }else if( showClosed ){ |
| 463 | @ <h2>Closed Branches:</h2> |
| 464 | }else if( showAll ){ |
| 465 | @ <h2>All Branches:</h2> |
| 466 | }else{ |
| 467 | @ <h2>Open Branches:</h2> |
| 468 | } |
| 469 | @ <ul> |
| 470 | cnt++; |
| @@ -357,11 +472,11 @@ | |
| 472 | if( colorTest ){ |
| 473 | const char *zColor = hash_color(zBr); |
| 474 | @ <li><span style="background-color: %s(zColor)"> |
| 475 | @ %h(zBr) → %s(zColor)</span></li> |
| 476 | }else{ |
| 477 | @ <li>%z(href("%R/timeline?r=%T&n=200",zBr))%h(zBr)</a></li> |
| 478 | } |
| 479 | } |
| 480 | if( cnt ){ |
| 481 | @ </ul> |
| 482 | } |
| @@ -385,11 +500,11 @@ | |
| 500 | " AND tag.tagname GLOB 'sym-*'", |
| 501 | rid |
| 502 | ); |
| 503 | while( db_step(&q)==SQLITE_ROW ){ |
| 504 | const char *zTagName = db_column_text(&q, 0); |
| 505 | @ %z(href("%R/timeline?r=%T&n=200",zTagName))[timeline]</a> |
| 506 | } |
| 507 | db_finalize(&q); |
| 508 | } |
| 509 | |
| 510 | /* |
| 511 |
+394
-192
| --- src/browse.c | ||
| +++ src/browse.c | ||
| @@ -304,89 +304,206 @@ | ||
| 304 | 304 | |
| 305 | 305 | /* |
| 306 | 306 | ** A single line of the file hierarchy |
| 307 | 307 | */ |
| 308 | 308 | struct FileTreeNode { |
| 309 | - FileTreeNode *pNext; /* Next line in sequence */ | |
| 310 | - FileTreeNode *pPrev; /* Previous line */ | |
| 311 | - FileTreeNode *pParent; /* Directory containing this line */ | |
| 309 | + FileTreeNode *pNext; /* Next entry in an ordered list of them all */ | |
| 310 | + FileTreeNode *pParent; /* Directory containing this entry */ | |
| 311 | + FileTreeNode *pSibling; /* Next element in the same subdirectory */ | |
| 312 | + FileTreeNode *pChild; /* List of child nodes */ | |
| 313 | + FileTreeNode *pLastChild; /* Last child on the pChild list */ | |
| 312 | 314 | char *zName; /* Name of this entry. The "tail" */ |
| 313 | 315 | char *zFullName; /* Full pathname of this entry */ |
| 314 | 316 | char *zUuid; /* SHA1 hash of this file. May be NULL. */ |
| 317 | + double mtime; /* Modification time for this entry */ | |
| 315 | 318 | unsigned nFullName; /* Length of zFullName */ |
| 316 | 319 | unsigned iLevel; /* Levels of parent directories */ |
| 317 | - u8 isDir; /* True if there are children */ | |
| 318 | - u8 isLast; /* True if this is the last child of its parent */ | |
| 319 | 320 | }; |
| 320 | 321 | |
| 321 | 322 | /* |
| 322 | 323 | ** A complete file hierarchy |
| 323 | 324 | */ |
| 324 | 325 | struct FileTree { |
| 325 | 326 | FileTreeNode *pFirst; /* First line of the list */ |
| 326 | 327 | FileTreeNode *pLast; /* Last line of the list */ |
| 328 | + FileTreeNode *pLastTop; /* Last top-level node */ | |
| 327 | 329 | }; |
| 328 | 330 | |
| 329 | 331 | /* |
| 330 | 332 | ** Add one or more new FileTreeNodes to the FileTree object so that the |
| 331 | -** leaf object zPathname is at the end of the node list | |
| 333 | +** leaf object zPathname is at the end of the node list. | |
| 334 | +** | |
| 335 | +** The caller invokes this routine once for each leaf node (each file | |
| 336 | +** as opposed to each directory). This routine fills in any missing | |
| 337 | +** intermediate nodes automatically. | |
| 338 | +** | |
| 339 | +** When constructing a list of FileTreeNodes, all entries that have | |
| 340 | +** a common directory prefix must be added consecutively in order for | |
| 341 | +** the tree to be constructed properly. | |
| 332 | 342 | */ |
| 333 | 343 | static void tree_add_node( |
| 334 | 344 | FileTree *pTree, /* Tree into which nodes are added */ |
| 335 | 345 | const char *zPath, /* The full pathname of file to add */ |
| 336 | - const char *zUuid /* UUID of the file. Might be NULL. */ | |
| 346 | + const char *zUuid, /* UUID of the file. Might be NULL. */ | |
| 347 | + double mtime /* Modification time for this entry */ | |
| 337 | 348 | ){ |
| 338 | 349 | int i; |
| 339 | - FileTreeNode *pParent; | |
| 340 | - FileTreeNode *pChild; | |
| 350 | + FileTreeNode *pParent; /* Parent (directory) of the next node to insert */ | |
| 341 | 351 | |
| 342 | - pChild = pTree->pLast; | |
| 343 | - pParent = pChild ? pChild->pParent : 0; | |
| 352 | + /* Make pParent point to the most recent ancestor of zPath, or | |
| 353 | + ** NULL if there are no prior entires that are a container for zPath. | |
| 354 | + */ | |
| 355 | + pParent = pTree->pLast; | |
| 344 | 356 | while( pParent!=0 && |
| 345 | 357 | ( strncmp(pParent->zFullName, zPath, pParent->nFullName)!=0 |
| 346 | 358 | || zPath[pParent->nFullName]!='/' ) |
| 347 | 359 | ){ |
| 348 | - pChild = pParent; | |
| 349 | - pParent = pChild->pParent; | |
| 360 | + pParent = pParent->pParent; | |
| 350 | 361 | } |
| 351 | 362 | i = pParent ? pParent->nFullName+1 : 0; |
| 352 | - if( pChild ) pChild->isLast = 0; | |
| 353 | 363 | while( zPath[i] ){ |
| 354 | 364 | FileTreeNode *pNew; |
| 355 | 365 | int iStart = i; |
| 356 | 366 | int nByte; |
| 357 | 367 | while( zPath[i] && zPath[i]!='/' ){ i++; } |
| 358 | 368 | nByte = sizeof(*pNew) + i + 1; |
| 359 | 369 | if( zUuid!=0 && zPath[i]==0 ) nByte += UUID_SIZE+1; |
| 360 | 370 | pNew = fossil_malloc( nByte ); |
| 371 | + memset(pNew, 0, sizeof(*pNew)); | |
| 361 | 372 | pNew->zFullName = (char*)&pNew[1]; |
| 362 | 373 | memcpy(pNew->zFullName, zPath, i); |
| 363 | 374 | pNew->zFullName[i] = 0; |
| 364 | 375 | pNew->nFullName = i; |
| 365 | 376 | if( zUuid!=0 && zPath[i]==0 ){ |
| 366 | 377 | pNew->zUuid = pNew->zFullName + i + 1; |
| 367 | 378 | memcpy(pNew->zUuid, zUuid, UUID_SIZE+1); |
| 368 | - }else{ | |
| 369 | - pNew->zUuid = 0; | |
| 370 | 379 | } |
| 371 | 380 | pNew->zName = pNew->zFullName + iStart; |
| 372 | 381 | if( pTree->pLast ){ |
| 373 | 382 | pTree->pLast->pNext = pNew; |
| 374 | 383 | }else{ |
| 375 | 384 | pTree->pFirst = pNew; |
| 376 | 385 | } |
| 377 | - pNew->pPrev = pTree->pLast; | |
| 378 | - pNew->pNext = 0; | |
| 386 | + pTree->pLast = pNew; | |
| 379 | 387 | pNew->pParent = pParent; |
| 380 | - pTree->pLast = pNew; | |
| 381 | - pNew->iLevel = pParent ? pParent->iLevel+1 : 0; | |
| 382 | - pNew->isDir = zPath[i]=='/'; | |
| 383 | - pNew->isLast = 1; | |
| 388 | + if( pParent ){ | |
| 389 | + if( pParent->pChild ){ | |
| 390 | + pParent->pLastChild->pSibling = pNew; | |
| 391 | + }else{ | |
| 392 | + pParent->pChild = pNew; | |
| 393 | + } | |
| 394 | + pNew->iLevel = pParent->iLevel + 1; | |
| 395 | + pParent->pLastChild = pNew; | |
| 396 | + }else{ | |
| 397 | + if( pTree->pLastTop ) pTree->pLastTop->pSibling = pNew; | |
| 398 | + pTree->pLastTop = pNew; | |
| 399 | + } | |
| 400 | + pNew->mtime = mtime; | |
| 384 | 401 | while( zPath[i]=='/' ){ i++; } |
| 385 | 402 | pParent = pNew; |
| 386 | 403 | } |
| 404 | + while( pParent && pParent->pParent ){ | |
| 405 | + if( pParent->pParent->mtime < pParent->mtime ){ | |
| 406 | + pParent->pParent->mtime = pParent->mtime; | |
| 407 | + } | |
| 408 | + pParent = pParent->pParent; | |
| 409 | + } | |
| 410 | +} | |
| 411 | + | |
| 412 | +/* Comparison function for two FileTreeNode objects. Sort first by | |
| 413 | +** mtime (larger numbers first) and then by zName (smaller names first). | |
| 414 | +** | |
| 415 | +** Return negative if pLeft<pRight. | |
| 416 | +** Return positive if pLeft>pRight. | |
| 417 | +** Return zero if pLeft==pRight. | |
| 418 | +*/ | |
| 419 | +static int compareNodes(FileTreeNode *pLeft, FileTreeNode *pRight){ | |
| 420 | + if( pLeft->mtime>pRight->mtime ) return -1; | |
| 421 | + if( pLeft->mtime<pRight->mtime ) return +1; | |
| 422 | + return fossil_stricmp(pLeft->zName, pRight->zName); | |
| 423 | +} | |
| 424 | + | |
| 425 | +/* Merge together two sorted lists of FileTreeNode objects */ | |
| 426 | +static FileTreeNode *mergeNodes(FileTreeNode *pLeft, FileTreeNode *pRight){ | |
| 427 | + FileTreeNode *pEnd; | |
| 428 | + FileTreeNode base; | |
| 429 | + pEnd = &base; | |
| 430 | + while( pLeft && pRight ){ | |
| 431 | + if( compareNodes(pLeft,pRight)<=0 ){ | |
| 432 | + pEnd = pEnd->pSibling = pLeft; | |
| 433 | + pLeft = pLeft->pSibling; | |
| 434 | + }else{ | |
| 435 | + pEnd = pEnd->pSibling = pRight; | |
| 436 | + pRight = pRight->pSibling; | |
| 437 | + } | |
| 438 | + } | |
| 439 | + if( pLeft ){ | |
| 440 | + pEnd->pSibling = pLeft; | |
| 441 | + }else{ | |
| 442 | + pEnd->pSibling = pRight; | |
| 443 | + } | |
| 444 | + return base.pSibling; | |
| 445 | +} | |
| 446 | + | |
| 447 | +/* Sort a list of FileTreeNode objects in mtime order. */ | |
| 448 | +static FileTreeNode *sortNodesByMtime(FileTreeNode *p){ | |
| 449 | + FileTreeNode *a[30]; | |
| 450 | + FileTreeNode *pX; | |
| 451 | + int i; | |
| 452 | + | |
| 453 | + memset(a, 0, sizeof(a)); | |
| 454 | + while( p ){ | |
| 455 | + pX = p; | |
| 456 | + p = pX->pSibling; | |
| 457 | + pX->pSibling = 0; | |
| 458 | + for(i=0; i<count(a)-1 && a[i]!=0; i++){ | |
| 459 | + pX = mergeNodes(a[i], pX); | |
| 460 | + a[i] = 0; | |
| 461 | + } | |
| 462 | + a[i] = mergeNodes(a[i], pX); | |
| 463 | + } | |
| 464 | + pX = 0; | |
| 465 | + for(i=0; i<count(a); i++){ | |
| 466 | + pX = mergeNodes(a[i], pX); | |
| 467 | + } | |
| 468 | + return pX; | |
| 469 | +} | |
| 470 | + | |
| 471 | +/* Sort an entire FileTreeNode tree by mtime | |
| 472 | +** | |
| 473 | +** This routine invalidates the following fields: | |
| 474 | +** | |
| 475 | +** FileTreeNode.pLastChild | |
| 476 | +** FileTreeNode.pNext | |
| 477 | +** | |
| 478 | +** Use relinkTree to reconnect the pNext pointers. | |
| 479 | +*/ | |
| 480 | +static FileTreeNode *sortTreeByMtime(FileTreeNode *p){ | |
| 481 | + FileTreeNode *pX; | |
| 482 | + for(pX=p; pX; pX=pX->pSibling){ | |
| 483 | + if( pX->pChild ) pX->pChild = sortTreeByMtime(pX->pChild); | |
| 484 | + } | |
| 485 | + return sortNodesByMtime(p); | |
| 486 | +} | |
| 487 | + | |
| 488 | +/* Reconstruct the FileTree by reconnecting the FileTreeNode.pNext | |
| 489 | +** fields in sequential order. | |
| 490 | +*/ | |
| 491 | +static void relinkTree(FileTree *pTree, FileTreeNode *pRoot){ | |
| 492 | + while( pRoot ){ | |
| 493 | + if( pTree->pLast ){ | |
| 494 | + pTree->pLast->pNext = pRoot; | |
| 495 | + }else{ | |
| 496 | + pTree->pFirst = pRoot; | |
| 497 | + } | |
| 498 | + pTree->pLast = pRoot; | |
| 499 | + if( pRoot->pChild ) relinkTree(pTree, pRoot->pChild); | |
| 500 | + pRoot = pRoot->pSibling; | |
| 501 | + } | |
| 502 | + if( pTree->pLast ) pTree->pLast->pNext = 0; | |
| 387 | 503 | } |
| 504 | + | |
| 388 | 505 | |
| 389 | 506 | /* |
| 390 | 507 | ** WEBPAGE: tree |
| 391 | 508 | ** |
| 392 | 509 | ** Query parameters: |
| @@ -394,19 +511,23 @@ | ||
| 394 | 511 | ** name=PATH Directory to display. Optional |
| 395 | 512 | ** ci=LABEL Show only files in this check-in. Optional. |
| 396 | 513 | ** re=REGEXP Show only files matching REGEXP. Optional. |
| 397 | 514 | ** expand Begin with the tree fully expanded. |
| 398 | 515 | ** nofiles Show directories (folders) only. Omit files. |
| 516 | +** mtime Order directory elements by decreasing mtime | |
| 399 | 517 | */ |
| 400 | 518 | void page_tree(void){ |
| 401 | 519 | char *zD = fossil_strdup(P("name")); |
| 402 | 520 | int nD = zD ? strlen(zD)+1 : 0; |
| 403 | 521 | const char *zCI = P("ci"); |
| 404 | 522 | int rid = 0; |
| 405 | 523 | char *zUuid = 0; |
| 406 | 524 | Blob dirname; |
| 407 | 525 | Manifest *pM = 0; |
| 526 | + double rNow = 0; | |
| 527 | + char *zNow = 0; | |
| 528 | + int useMtime = atoi(PD("mtime","0")); | |
| 408 | 529 | int nFile = 0; /* Number of files (or folders with "nofiles") */ |
| 409 | 530 | int linkTrunk = 1; /* include link to "trunk" */ |
| 410 | 531 | int linkTip = 1; /* include link to "tip" */ |
| 411 | 532 | const char *zRE; /* the value for the re=REGEXP query parameter */ |
| 412 | 533 | const char *zObjType; /* "files" by default or "folders" for "nofiles" */ |
| @@ -464,14 +585,21 @@ | ||
| 464 | 585 | int trunkRid = symbolic_name_to_rid("tag:trunk", "ci"); |
| 465 | 586 | linkTrunk = trunkRid && rid != trunkRid; |
| 466 | 587 | linkTip = rid != symbolic_name_to_rid("tip", "ci"); |
| 467 | 588 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 468 | 589 | url_add_parameter(&sURI, "ci", zCI); |
| 590 | + rNow = db_double(0.0, "SELECT mtime FROM event WHERE objid=%d", rid); | |
| 591 | + zNow = db_text("", "SELECT datetime(mtime,'localtime')" | |
| 592 | + " FROM event WHERE objid=%d", rid); | |
| 469 | 593 | }else{ |
| 470 | 594 | zCI = 0; |
| 471 | 595 | } |
| 472 | 596 | } |
| 597 | + if( zCI==0 ){ | |
| 598 | + rNow = db_double(0.0, "SELECT max(mtime) FROM event"); | |
| 599 | + zNow = db_text("", "SELECT datetime(max(mtime),'localtime') FROM event"); | |
| 600 | + } | |
| 473 | 601 | |
| 474 | 602 | /* Compute the title of the page */ |
| 475 | 603 | blob_zero(&dirname); |
| 476 | 604 | if( zD ){ |
| 477 | 605 | url_add_parameter(&sURI, "name", zD); |
| @@ -483,10 +611,18 @@ | ||
| 483 | 611 | }else{ |
| 484 | 612 | if( zRE ){ |
| 485 | 613 | blob_appendf(&dirname, "matching \"%s\"", zRE); |
| 486 | 614 | } |
| 487 | 615 | } |
| 616 | + if( useMtime ){ | |
| 617 | + style_submenu_element("Sort By Filename","Sort By Filename", "%s", | |
| 618 | + url_render(&sURI, 0, 0, 0, 0)); | |
| 619 | + url_add_parameter(&sURI, "mtime", "1"); | |
| 620 | + }else{ | |
| 621 | + style_submenu_element("Sort By Time","Sort By Time", "%s", | |
| 622 | + url_render(&sURI, "mtime", "1", 0, 0)); | |
| 623 | + } | |
| 488 | 624 | if( zCI ){ |
| 489 | 625 | style_submenu_element("All", "All", "%s", |
| 490 | 626 | url_render(&sURI, "ci", 0, 0, 0)); |
| 491 | 627 | if( nD==0 && !showDirOnly ){ |
| 492 | 628 | style_submenu_element("File Ages", "File Ages", "%R/fileage?name=%s", |
| @@ -499,87 +635,82 @@ | ||
| 499 | 635 | } |
| 500 | 636 | if( linkTip ){ |
| 501 | 637 | style_submenu_element("Tip", "Tip", "%s", |
| 502 | 638 | url_render(&sURI, "ci", "tip", 0, 0)); |
| 503 | 639 | } |
| 504 | - if( !showDirOnly ){ | |
| 505 | - style_submenu_element("Flat-View", "Flat-View", "%s", | |
| 506 | - url_render(&sURI, "type", "flat", 0, 0)); | |
| 507 | - } | |
| 508 | 640 | |
| 509 | 641 | /* Compute the file hierarchy. |
| 510 | 642 | */ |
| 511 | 643 | if( zCI ){ |
| 512 | - Stmt ins, q; | |
| 513 | - ManifestFile *pFile; | |
| 514 | - | |
| 515 | - db_multi_exec( | |
| 516 | - "CREATE TEMP TABLE filelist(" | |
| 517 | - " x TEXT PRIMARY KEY COLLATE nocase," | |
| 518 | - " uuid TEXT" | |
| 519 | - ") WITHOUT ROWID;" | |
| 644 | + Stmt q; | |
| 645 | + compute_fileage(rid, 0); | |
| 646 | + db_prepare(&q, | |
| 647 | + "SELECT filename.name, blob.uuid, fileage.mtime\n" | |
| 648 | + " FROM fileage, filename, blob\n" | |
| 649 | + " WHERE filename.fnid=fileage.fnid\n" | |
| 650 | + " AND blob.rid=fileage.fid\n" | |
| 651 | + " ORDER BY filename.name COLLATE nocase;" | |
| 520 | 652 | ); |
| 521 | - db_prepare(&ins, "INSERT OR IGNORE INTO filelist VALUES(:f,:u)"); | |
| 522 | - manifest_file_rewind(pM); | |
| 523 | - while( (pFile = manifest_file_next(pM,0))!=0 ){ | |
| 524 | - if( nD>0 | |
| 525 | - && (fossil_strncmp(pFile->zName, zD, nD-1)!=0 | |
| 526 | - || pFile->zName[nD-1]!='/') | |
| 527 | - ){ | |
| 528 | - continue; | |
| 529 | - } | |
| 530 | - if( pRE && re_match(pRE, (const u8*)pFile->zName, -1)==0 ) continue; | |
| 531 | - db_bind_text(&ins, ":f", pFile->zName); | |
| 532 | - db_bind_text(&ins, ":u", pFile->zUuid); | |
| 533 | - db_step(&ins); | |
| 534 | - db_reset(&ins); | |
| 535 | - } | |
| 536 | - db_finalize(&ins); | |
| 537 | - db_prepare(&q, "SELECT x, uuid FROM filelist ORDER BY x"); | |
| 538 | 653 | while( db_step(&q)==SQLITE_ROW ){ |
| 539 | - tree_add_node(&sTree, db_column_text(&q,0), db_column_text(&q,1)); | |
| 654 | + const char *zFile = db_column_text(&q,0); | |
| 655 | + const char *zUuid = db_column_text(&q,1); | |
| 656 | + double mtime = db_column_double(&q,2); | |
| 657 | + if( pRE && re_match(pRE, (const unsigned char*)zFile, -1)==0 ) continue; | |
| 658 | + tree_add_node(&sTree, zFile, zUuid, mtime); | |
| 540 | 659 | nFile++; |
| 541 | 660 | } |
| 542 | 661 | db_finalize(&q); |
| 543 | 662 | }else{ |
| 544 | 663 | Stmt q; |
| 545 | - db_prepare(&q, "SELECT name FROM filename ORDER BY name COLLATE nocase"); | |
| 664 | + db_prepare(&q, | |
| 665 | + "SELECT filename.name, blob.uuid, max(event.mtime)\n" | |
| 666 | + " FROM filename, mlink, blob, event\n" | |
| 667 | + " WHERE mlink.fnid=filename.fnid\n" | |
| 668 | + " AND event.objid=mlink.mid\n" | |
| 669 | + " AND blob.rid=mlink.fid\n" | |
| 670 | + " GROUP BY 1 ORDER BY 1 COLLATE nocase"); | |
| 546 | 671 | while( db_step(&q)==SQLITE_ROW ){ |
| 547 | - const char *z = db_column_text(&q, 0); | |
| 548 | - if( nD>0 && (fossil_strncmp(z, zD, nD-1)!=0 || z[nD-1]!='/') ){ | |
| 672 | + const char *zName = db_column_text(&q, 0); | |
| 673 | + const char *zUuid = db_column_text(&q,1); | |
| 674 | + double mtime = db_column_double(&q,2); | |
| 675 | + if( nD>0 && (fossil_strncmp(zName, zD, nD-1)!=0 || zName[nD-1]!='/') ){ | |
| 549 | 676 | continue; |
| 550 | 677 | } |
| 551 | - if( pRE && re_match(pRE, (const u8*)z, -1)==0 ) continue; | |
| 552 | - tree_add_node(&sTree, z, 0); | |
| 678 | + if( pRE && re_match(pRE, (const u8*)zName, -1)==0 ) continue; | |
| 679 | + tree_add_node(&sTree, zName, zUuid, mtime); | |
| 553 | 680 | nFile++; |
| 554 | 681 | } |
| 555 | 682 | db_finalize(&q); |
| 556 | 683 | } |
| 557 | 684 | |
| 558 | 685 | if( showDirOnly ){ |
| 559 | 686 | for(nFile=0, p=sTree.pFirst; p; p=p->pNext){ |
| 560 | - if( p->isDir && p->nFullName>nD ) nFile++; | |
| 687 | + if( p->pChild!=0 && p->nFullName>nD ) nFile++; | |
| 561 | 688 | } |
| 562 | - zObjType = "folders"; | |
| 689 | + zObjType = "Folders"; | |
| 563 | 690 | style_submenu_element("Files","Files","%s", |
| 564 | 691 | url_render(&sURI,"nofiles",0,0,0)); |
| 565 | 692 | }else{ |
| 566 | - zObjType = "files"; | |
| 693 | + zObjType = "Files"; | |
| 567 | 694 | style_submenu_element("Folders","Folders","%s", |
| 568 | 695 | url_render(&sURI,"nofiles","1",0,0)); |
| 569 | 696 | } |
| 570 | 697 | |
| 571 | 698 | if( zCI ){ |
| 572 | - @ <h2>%d(nFile) %s(zObjType) of check-in | |
| 699 | + @ <h2>%s(zObjType) from | |
| 573 | 700 | if( sqlite3_strnicmp(zCI, zUuid, (int)strlen(zCI))!=0 ){ |
| 574 | 701 | @ "%h(zCI)" |
| 575 | 702 | } |
| 576 | - @ [%z(href("vinfo?name=%s",zUuid))%S(zUuid)</a>] %s(blob_str(&dirname))</h2> | |
| 703 | + @ [%z(href("vinfo?name=%s",zUuid))%S(zUuid)</a>] %s(blob_str(&dirname)) | |
| 577 | 704 | }else{ |
| 578 | 705 | int n = db_int(0, "SELECT count(*) FROM plink"); |
| 579 | - @ <h2>%d(nFile) %s(zObjType) from all %d(n) check-ins | |
| 580 | - @ %s(blob_str(&dirname))</h2> | |
| 706 | + @ <h2>%s(zObjType) from all %d(n) check-ins %s(blob_str(&dirname)) | |
| 707 | + } | |
| 708 | + if( useMtime ){ | |
| 709 | + @ sorted by modification time</h2> | |
| 710 | + }else{ | |
| 711 | + @ sorted by filename</h2> | |
| 581 | 712 | } |
| 582 | 713 | |
| 583 | 714 | |
| 584 | 715 | /* Generate tree of lists. |
| 585 | 716 | ** |
| @@ -596,18 +727,33 @@ | ||
| 596 | 727 | if( nD ){ |
| 597 | 728 | @ <li class="dir last"> |
| 598 | 729 | }else{ |
| 599 | 730 | @ <li class="dir subdir last"> |
| 600 | 731 | } |
| 732 | + @ <div class="filetreeline"> | |
| 601 | 733 | @ %z(href("%s",url_render(&sURI,"name",0,0,0)))%h(zProjectName)</a> |
| 734 | + if( zNow ){ | |
| 735 | + @ <div class="filetreeage">%s(zNow)</div> | |
| 736 | + } | |
| 737 | + @ </div> | |
| 602 | 738 | @ <ul> |
| 739 | + if( useMtime ){ | |
| 740 | + p = sortTreeByMtime(sTree.pFirst); | |
| 741 | + memset(&sTree, 0, sizeof(sTree)); | |
| 742 | + relinkTree(&sTree, p); | |
| 743 | + } | |
| 603 | 744 | for(p=sTree.pFirst, nDir=0; p; p=p->pNext){ |
| 604 | - const char *zLastClass = p->isLast ? " last" : ""; | |
| 605 | - if( p->isDir ){ | |
| 745 | + const char *zLastClass = p->pSibling==0 ? " last" : ""; | |
| 746 | + if( p->pChild ){ | |
| 606 | 747 | const char *zSubdirClass = p->nFullName==nD-1 ? " subdir" : ""; |
| 607 | - @ <li class="dir%s(zSubdirClass)%s(zLastClass)"> | |
| 748 | + @ <li class="dir%s(zSubdirClass)%s(zLastClass)"><div class="filetreeline"> | |
| 608 | 749 | @ %z(href("%s",url_render(&sURI,"name",p->zFullName,0,0)))%h(p->zName)</a> |
| 750 | + if( p->mtime>0.0 ){ | |
| 751 | + char *zAge = human_readable_age(rNow - p->mtime); | |
| 752 | + @ <div class="filetreeage">%s(zAge)</div> | |
| 753 | + } | |
| 754 | + @ </div> | |
| 609 | 755 | if( startExpanded || p->nFullName<=nD ){ |
| 610 | 756 | @ <ul id="dir%d(nDir)"> |
| 611 | 757 | }else{ |
| 612 | 758 | @ <ul id="dir%d(nDir)" class="collapsed"> |
| 613 | 759 | } |
| @@ -614,17 +760,23 @@ | ||
| 614 | 760 | nDir++; |
| 615 | 761 | }else if( !showDirOnly ){ |
| 616 | 762 | const char *zFileClass = fileext_class(p->zName); |
| 617 | 763 | char *zLink; |
| 618 | 764 | if( zCI ){ |
| 619 | - zLink = href("%R/artifact/%s",p->zUuid); | |
| 765 | + zLink = href("%R/artifact/%.16s",p->zUuid); | |
| 620 | 766 | }else{ |
| 621 | 767 | zLink = href("%R/finfo?name=%T",p->zFullName); |
| 622 | 768 | } |
| 623 | - @ <li class="%z(zFileClass)%s(zLastClass)">%z(zLink)%h(p->zName)</a> | |
| 769 | + @ <li class="%z(zFileClass)%s(zLastClass)"><div class="filetreeline"> | |
| 770 | + @ %z(zLink)%h(p->zName)</a> | |
| 771 | + if( p->mtime>0 ){ | |
| 772 | + char *zAge = human_readable_age(rNow - p->mtime); | |
| 773 | + @ <div class="filetreeage">%s(zAge)</div> | |
| 774 | + } | |
| 775 | + @ </div> | |
| 624 | 776 | } |
| 625 | - if( p->isLast ){ | |
| 777 | + if( p->pSibling==0 ){ | |
| 626 | 778 | int nClose = p->iLevel - (p->pNext ? p->pNext->iLevel : 0); |
| 627 | 779 | while( nClose-- > 0 ){ |
| 628 | 780 | @ </ul> |
| 629 | 781 | } |
| 630 | 782 | } |
| @@ -687,16 +839,16 @@ | ||
| 687 | 839 | @ checkState(); |
| 688 | 840 | @ outer_ul.onclick = function(e){ |
| 689 | 841 | @ e = e || window.event; |
| 690 | 842 | @ var a = e.target || e.srcElement; |
| 691 | 843 | @ if( a.nodeName!='A' ) return true; |
| 692 | - @ if( a.parentNode==subdir ){ | |
| 844 | + @ if( a.parentNode.parentNode==subdir ){ | |
| 693 | 845 | @ toggleAll(outer_ul); |
| 694 | 846 | @ return false; |
| 695 | 847 | @ } |
| 696 | 848 | @ if( !belowSubdir(a) ) return true; |
| 697 | - @ var ul = a.nextSibling; | |
| 849 | + @ var ul = a.parentNode.nextSibling; | |
| 698 | 850 | @ while( ul && ul.nodeName!='UL' ) ul = ul.nextSibling; |
| 699 | 851 | @ if( !ul ) return true; /* This is a file link, not a directory */ |
| 700 | 852 | @ toggleDir(ul); |
| 701 | 853 | @ return false; |
| 702 | 854 | @ } |
| @@ -724,87 +876,115 @@ | ||
| 724 | 876 | }else{ |
| 725 | 877 | zClass = mprintf("file"); |
| 726 | 878 | } |
| 727 | 879 | return zClass; |
| 728 | 880 | } |
| 881 | + | |
| 882 | +/* | |
| 883 | +** SQL used to compute the age of all files in checkin :ckin whose | |
| 884 | +** names match :glob | |
| 885 | +*/ | |
| 886 | +static const char zComputeFileAgeSetup[] = | |
| 887 | +@ CREATE TABLE IF NOT EXISTS temp.fileage( | |
| 888 | +@ fnid INTEGER PRIMARY KEY, | |
| 889 | +@ fid INTEGER, | |
| 890 | +@ mid INTEGER, | |
| 891 | +@ mtime DATETIME, | |
| 892 | +@ pathname TEXT | |
| 893 | +@ ); | |
| 894 | +@ CREATE VIRTUAL TABLE IF NOT EXISTS temp.foci USING files_of_checkin; | |
| 895 | +; | |
| 896 | + | |
| 897 | +static const char zComputeFileAgeRun[] = | |
| 898 | +@ WITH RECURSIVE | |
| 899 | +@ ckin(x) AS (VALUES(:ckin) UNION ALL | |
| 900 | +@ SELECT pid FROM ckin, plink WHERE cid=x AND isprim) | |
| 901 | +@ INSERT OR IGNORE INTO fileage(fnid, fid, mid, mtime, pathname) | |
| 902 | +@ SELECT mlink.fnid, mlink.fid, x, event.mtime, filename.name | |
| 903 | +@ FROM ckin, mlink, event, filename | |
| 904 | +@ WHERE mlink.mid=ckin.x | |
| 905 | +@ AND mlink.fnid IN (SELECT fnid FROM foci, filename | |
| 906 | +@ WHERE foci.checkinID=:ckin | |
| 907 | +@ AND filename.name=foci.filename | |
| 908 | +@ AND filename.name GLOB :glob) | |
| 909 | +@ AND filename.fnid=mlink.fnid | |
| 910 | +@ AND event.objid=mlink.mid; | |
| 911 | +; | |
| 912 | + | |
| 729 | 913 | |
| 730 | 914 | /* |
| 731 | 915 | ** Look at all file containing in the version "vid". Construct a |
| 732 | 916 | ** temporary table named "fileage" that contains the file-id for each |
| 733 | 917 | ** files, the pathname, the check-in where the file was added, and the |
| 734 | 918 | ** mtime on that checkin. If zGlob and *zGlob then only files matching |
| 735 | 919 | ** the given glob are computed. |
| 736 | 920 | */ |
| 737 | 921 | int compute_fileage(int vid, const char* zGlob){ |
| 738 | - Manifest *pManifest; | |
| 739 | - ManifestFile *pFile; | |
| 740 | - int nFile = 0; | |
| 741 | - double vmtime; | |
| 742 | - Stmt ins; | |
| 743 | - Stmt q1, q2, q3; | |
| 744 | - Stmt upd; | |
| 745 | - if(zGlob && !*zGlob) zGlob = NULL; | |
| 746 | - db_multi_exec( | |
| 747 | - /*"DROP TABLE IF EXISTS temp.fileage;"*/ | |
| 748 | - "CREATE TEMP TABLE fileage(" | |
| 749 | - " fid INTEGER," | |
| 750 | - " mid INTEGER," | |
| 751 | - " mtime DATETIME," | |
| 752 | - " pathname TEXT" | |
| 753 | - ");" | |
| 754 | - "CREATE INDEX fileage_fid ON fileage(fid);" | |
| 755 | - ); | |
| 756 | - pManifest = manifest_get(vid, CFTYPE_MANIFEST, 0); | |
| 757 | - if( pManifest==0 ) return 1; | |
| 758 | - manifest_file_rewind(pManifest); | |
| 759 | - db_prepare(&ins, | |
| 760 | - "INSERT INTO temp.fileage(fid, pathname)" | |
| 761 | - " SELECT rid, :path FROM blob WHERE uuid=:uuid" | |
| 762 | - ); | |
| 763 | - while( (pFile = manifest_file_next(pManifest, 0))!=0 ){ | |
| 764 | - if( zGlob && sqlite3_strglob(zGlob, pFile->zName)!=0 ) continue; | |
| 765 | - db_bind_text(&ins, ":uuid", pFile->zUuid); | |
| 766 | - db_bind_text(&ins, ":path", pFile->zName); | |
| 767 | - db_step(&ins); | |
| 768 | - db_reset(&ins); | |
| 769 | - nFile++; | |
| 770 | - } | |
| 771 | - db_finalize(&ins); | |
| 772 | - manifest_destroy(pManifest); | |
| 773 | - db_prepare(&q1,"SELECT fid FROM mlink WHERE mid=:mid"); | |
| 774 | - db_prepare(&upd, "UPDATE fileage SET mid=:mid, mtime=:vmtime" | |
| 775 | - " WHERE fid=:fid AND mid IS NULL"); | |
| 776 | - db_prepare(&q2,"SELECT pid FROM plink WHERE cid=:vid AND isprim"); | |
| 777 | - db_prepare(&q3,"SELECT mtime FROM event WHERE objid=:vid"); | |
| 778 | - while( nFile>0 && vid>0 ){ | |
| 779 | - db_bind_int(&q3, ":vid", vid); | |
| 780 | - if( db_step(&q3)==SQLITE_ROW ){ | |
| 781 | - vmtime = db_column_double(&q3, 0); | |
| 782 | - }else{ | |
| 783 | - break; | |
| 784 | - } | |
| 785 | - db_reset(&q3); | |
| 786 | - db_bind_int(&q1, ":mid", vid); | |
| 787 | - db_bind_int(&upd, ":mid", vid); | |
| 788 | - db_bind_double(&upd, ":vmtime", vmtime); | |
| 789 | - while( db_step(&q1)==SQLITE_ROW ){ | |
| 790 | - db_bind_int(&upd, ":fid", db_column_int(&q1, 0)); | |
| 791 | - db_step(&upd); | |
| 792 | - nFile -= db_changes(); | |
| 793 | - db_reset(&upd); | |
| 794 | - } | |
| 795 | - db_reset(&q1); | |
| 796 | - db_bind_int(&q2, ":vid", vid); | |
| 797 | - if( db_step(&q2)!=SQLITE_ROW ) break; | |
| 798 | - vid = db_column_int(&q2, 0); | |
| 799 | - db_reset(&q2); | |
| 800 | - } | |
| 801 | - db_finalize(&q1); | |
| 802 | - db_finalize(&upd); | |
| 803 | - db_finalize(&q2); | |
| 804 | - db_finalize(&q3); | |
| 805 | - return 0; | |
| 922 | + Stmt q; | |
| 923 | + db_multi_exec(zComputeFileAgeSetup /*works-like:"constant"*/); | |
| 924 | + db_prepare(&q, zComputeFileAgeRun /*works-like:"constant"*/); | |
| 925 | + db_bind_int(&q, ":ckin", vid); | |
| 926 | + db_bind_text(&q, ":glob", zGlob && zGlob[0] ? zGlob : "*"); | |
| 927 | + db_exec(&q); | |
| 928 | + db_finalize(&q); | |
| 929 | + return 0; | |
| 930 | +} | |
| 931 | + | |
| 932 | +/* | |
| 933 | +** Render the number of days in rAge as a more human-readable time span. | |
| 934 | +** Different units (seconds, minutes, hours, days, months, years) are | |
| 935 | +** selected depending on the magnitude of rAge. | |
| 936 | +** | |
| 937 | +** The string returned is obtained from fossil_malloc() and should be | |
| 938 | +** freed by the caller. | |
| 939 | +*/ | |
| 940 | +char *human_readable_age(double rAge){ | |
| 941 | + if( rAge*86400.0<120 ){ | |
| 942 | + if( rAge*86400.0<1.0 ){ | |
| 943 | + return mprintf("current"); | |
| 944 | + }else{ | |
| 945 | + return mprintf("%d seconds", (int)(rAge*86400.0)); | |
| 946 | + } | |
| 947 | + }else if( rAge*1440.0<90 ){ | |
| 948 | + return mprintf("%.1f minutes", rAge*1440.0); | |
| 949 | + }else if( rAge*24.0<36 ){ | |
| 950 | + return mprintf("%.1f hours", rAge*24.0); | |
| 951 | + }else if( rAge<365.0 ){ | |
| 952 | + return mprintf("%.1f days", rAge); | |
| 953 | + }else{ | |
| 954 | + return mprintf("%.2f years", rAge/365.0); | |
| 955 | + } | |
| 956 | +} | |
| 957 | + | |
| 958 | +/* | |
| 959 | +** COMMAND: test-fileage | |
| 960 | +** | |
| 961 | +** Usage: %fossil test-fileage CHECKIN | |
| 962 | +*/ | |
| 963 | +void test_fileage_cmd(void){ | |
| 964 | + int mid; | |
| 965 | + Stmt q; | |
| 966 | + const char *zGlob = find_option("glob",0,1); | |
| 967 | + db_find_and_open_repository(0,0); | |
| 968 | + verify_all_options(); | |
| 969 | + if( g.argc!=3 ) usage("test-fileage CHECKIN"); | |
| 970 | + mid = name_to_typed_rid(g.argv[2],"ci"); | |
| 971 | + compute_fileage(mid, zGlob); | |
| 972 | + db_prepare(&q, | |
| 973 | + "SELECT fid, mid, julianday('now') - mtime, pathname" | |
| 974 | + " FROM fileage" | |
| 975 | + ); | |
| 976 | + while( db_step(&q)==SQLITE_ROW ){ | |
| 977 | + char *zAge = human_readable_age(db_column_double(&q,2)); | |
| 978 | + fossil_print("%8d %8d %16s %s\n", | |
| 979 | + db_column_int(&q,0), | |
| 980 | + db_column_int(&q,1), | |
| 981 | + zAge, | |
| 982 | + db_column_text(&q,3)); | |
| 983 | + fossil_free(zAge); | |
| 984 | + } | |
| 985 | + db_finalize(&q); | |
| 806 | 986 | } |
| 807 | 987 | |
| 808 | 988 | /* |
| 809 | 989 | ** WEBPAGE: fileage |
| 810 | 990 | ** |
| @@ -814,72 +994,94 @@ | ||
| 814 | 994 | ** (e.g. *.c or *.txt). |
| 815 | 995 | */ |
| 816 | 996 | void fileage_page(void){ |
| 817 | 997 | int rid; |
| 818 | 998 | const char *zName; |
| 819 | - char *zBaseTime; | |
| 820 | 999 | const char *zGlob; |
| 821 | - Stmt q; | |
| 1000 | + const char *zUuid; | |
| 1001 | + const char *zNow; /* Time of checkin */ | |
| 1002 | + Stmt q1, q2; | |
| 822 | 1003 | double baseTime; |
| 823 | - int lastMid = -1; | |
| 824 | 1004 | login_check_credentials(); |
| 825 | 1005 | if( !g.perm.Read ){ login_needed(); return; } |
| 826 | 1006 | zName = P("name"); |
| 827 | 1007 | if( zName==0 ) zName = "tip"; |
| 828 | 1008 | rid = symbolic_name_to_rid(zName, "ci"); |
| 829 | 1009 | if( rid==0 ){ |
| 830 | 1010 | fossil_fatal("not a valid check-in: %s", zName); |
| 831 | 1011 | } |
| 832 | - style_submenu_element("Tree-View", "Tree-View", "%R/tree?ci=%T", zName); | |
| 1012 | + zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid); | |
| 1013 | + baseTime = db_double(0.0,"SELECT mtime FROM event WHERE objid=%d", rid); | |
| 1014 | + zNow = db_text("", "SELECT datetime(mtime,'localtime') FROM event" | |
| 1015 | + " WHERE objid=%d", rid); | |
| 1016 | + style_submenu_element("Tree-View", "Tree-View", "%R/tree?ci=%T&mtime=1", | |
| 1017 | + zName); | |
| 833 | 1018 | style_header("File Ages"); |
| 834 | 1019 | zGlob = P("glob"); |
| 835 | 1020 | compute_fileage(rid,zGlob); |
| 836 | - baseTime = db_double(0.0, "SELECT mtime FROM event WHERE objid=%d", rid); | |
| 837 | - zBaseTime = db_text("","SELECT datetime(%.20g%s)", baseTime, timeline_utc()); | |
| 838 | - @ <h2>File Ages For Check-in | |
| 839 | - @ %z(href("%R/info?name=%T",zName))%h(zName)</a></h2> | |
| 840 | - @ | |
| 841 | - @ <p>The times given are relative to | |
| 842 | - @ %z(href("%R/timeline?c=%T",zBaseTime))%s(zBaseTime)</a>, which is the | |
| 843 | - @ check-in time for | |
| 844 | - @ %z(href("%R/info?name=%T",zName))%h(zName)</a></p> | |
| 845 | - @ | |
| 846 | - @ <table border=0 cellspacing=0 cellpadding=0> | |
| 847 | - db_prepare(&q, | |
| 848 | - "SELECT mtime, (SELECT uuid FROM blob WHERE rid=fid), mid, pathname" | |
| 849 | - " FROM fileage" | |
| 850 | - " ORDER BY mtime DESC, mid, pathname" | |
| 851 | - ); | |
| 852 | - while( db_step(&q)==SQLITE_ROW ){ | |
| 853 | - double age = baseTime - db_column_double(&q, 0); | |
| 854 | - int mid = db_column_int(&q, 2); | |
| 855 | - const char *zFUuid = db_column_text(&q, 1); | |
| 856 | - char zAge[200]; | |
| 857 | - if( lastMid!=mid ){ | |
| 858 | - @ <tr><td colspan=3><hr></tr> | |
| 859 | - lastMid = mid; | |
| 860 | - if( age*86400.0<120 ){ | |
| 861 | - sqlite3_snprintf(sizeof(zAge), zAge, "%d seconds", (int)(age*86400.0)); | |
| 862 | - }else if( age*1440.0<90 ){ | |
| 863 | - sqlite3_snprintf(sizeof(zAge), zAge, "%.1f minutes", age*1440.0); | |
| 864 | - }else if( age*24.0<36 ){ | |
| 865 | - sqlite3_snprintf(sizeof(zAge), zAge, "%.1f hours", age*24.0); | |
| 866 | - }else if( age<365.0 ){ | |
| 867 | - sqlite3_snprintf(sizeof(zAge), zAge, "%.1f days", age); | |
| 868 | - }else{ | |
| 869 | - sqlite3_snprintf(sizeof(zAge), zAge, "%.2f years", age/365.0); | |
| 870 | - } | |
| 871 | - }else{ | |
| 872 | - zAge[0] = 0; | |
| 873 | - } | |
| 874 | - @ <tr> | |
| 875 | - @ <td>%s(zAge) | |
| 876 | - @ <td width="25"> | |
| 877 | - @ <td>%z(href("%R/artifact/%s?ln", zFUuid))%h(db_column_text(&q, 3))</a> | |
| 878 | - @ </tr> | |
| 879 | - @ | |
| 880 | - } | |
| 881 | - @ <tr><td colspan=3><hr></tr> | |
| 882 | - @ </table> | |
| 883 | - db_finalize(&q); | |
| 1021 | + db_multi_exec("CREATE INDEX fileage_ix1 ON fileage(mid,pathname);"); | |
| 1022 | + | |
| 1023 | + @ <h2>Files in | |
| 1024 | + @ %z(href("%R/info?name=%T",zUuid))[%S(zUuid)]</a> | |
| 1025 | + if( zGlob && zGlob[0] ){ | |
| 1026 | + @ that match "%h(zGlob)" and | |
| 1027 | + } | |
| 1028 | + @ ordered by check-in time</h2> | |
| 1029 | + @ | |
| 1030 | + @ <p>Times are relative to the checkin time for | |
| 1031 | + @ %z(href("%R/ci/%s",zUuid))[%S(zUuid)]</a> which is | |
| 1032 | + @ %z(href("%R/timeline?c=%t",zNow))%s(zNow)</a>.</p> | |
| 1033 | + @ | |
| 1034 | + @ <div class='fileage'><table> | |
| 1035 | + @ <tr><th>Time</th><th>Files</th><th>Checkin</th></tr> | |
| 1036 | + db_prepare(&q1, | |
| 1037 | + "SELECT event.mtime, event.objid, blob.uuid,\n" | |
| 1038 | + " coalesce(event.ecomment,event.comment),\n" | |
| 1039 | + " coalesce(event.euser,event.user),\n" | |
| 1040 | + " coalesce((SELECT value FROM tagxref\n" | |
| 1041 | + " WHERE tagtype>0 AND tagid=%d\n" | |
| 1042 | + " AND rid=event.objid),'trunk')\n" | |
| 1043 | + " FROM event, blob\n" | |
| 1044 | + " WHERE event.objid IN (SELECT mid FROM fileage)\n" | |
| 1045 | + " AND blob.rid=event.objid\n" | |
| 1046 | + " ORDER BY event.mtime DESC;", | |
| 1047 | + TAG_BRANCH | |
| 1048 | + ); | |
| 1049 | + db_prepare(&q2, | |
| 1050 | + "SELECT blob.uuid, filename.name\n" | |
| 1051 | + " FROM fileage, blob, filename\n" | |
| 1052 | + " WHERE fileage.mid=:mid AND filename.fnid=fileage.fnid" | |
| 1053 | + " AND blob.rid=fileage.fid;" | |
| 1054 | + ); | |
| 1055 | + while( db_step(&q1)==SQLITE_ROW ){ | |
| 1056 | + double age = baseTime - db_column_double(&q1, 0); | |
| 1057 | + int mid = db_column_int(&q1, 1); | |
| 1058 | + const char *zUuid = db_column_text(&q1, 2); | |
| 1059 | + const char *zComment = db_column_text(&q1, 3); | |
| 1060 | + const char *zUser = db_column_text(&q1, 4); | |
| 1061 | + const char *zBranch = db_column_text(&q1, 5); | |
| 1062 | + char *zAge = human_readable_age(age); | |
| 1063 | + @ <tr><td>%s(zAge)</td> | |
| 1064 | + @ <td> | |
| 1065 | + db_bind_int(&q2, ":mid", mid); | |
| 1066 | + while( db_step(&q2)==SQLITE_ROW ){ | |
| 1067 | + const char *zFUuid = db_column_text(&q2,0); | |
| 1068 | + const char *zFile = db_column_text(&q2,1); | |
| 1069 | + @ %z(href("%R/artifact/%s",zFUuid))%h(zFile)</a><br> | |
| 1070 | + } | |
| 1071 | + db_reset(&q2); | |
| 1072 | + @ </td> | |
| 1073 | + @ <td> | |
| 1074 | + @ %z(href("%R/info/%s",zUuid))[%S(zUuid)]</a> | |
| 1075 | + @ %W(zComment) (user: | |
| 1076 | + @ %z(href("%R/timeline?u=%t&c=%t&nd&n=200",zUser,zUuid))%h(zUser)</a>, | |
| 1077 | + @ branch: | |
| 1078 | + @ %z(href("%R/timeline?r=%t&c=%t&nd&n=200",zBranch,zUuid))%h(zBranch)</a>) | |
| 1079 | + @ </td></tr> | |
| 1080 | + @ | |
| 1081 | + fossil_free(zAge); | |
| 1082 | + } | |
| 1083 | + @ </table></div> | |
| 1084 | + db_finalize(&q1); | |
| 1085 | + db_finalize(&q2); | |
| 884 | 1086 | style_footer(); |
| 885 | 1087 | } |
| 886 | 1088 | |
| 887 | 1089 | ADDED src/bundle.c |
| --- src/browse.c | |
| +++ src/browse.c | |
| @@ -304,89 +304,206 @@ | |
| 304 | |
| 305 | /* |
| 306 | ** A single line of the file hierarchy |
| 307 | */ |
| 308 | struct FileTreeNode { |
| 309 | FileTreeNode *pNext; /* Next line in sequence */ |
| 310 | FileTreeNode *pPrev; /* Previous line */ |
| 311 | FileTreeNode *pParent; /* Directory containing this line */ |
| 312 | char *zName; /* Name of this entry. The "tail" */ |
| 313 | char *zFullName; /* Full pathname of this entry */ |
| 314 | char *zUuid; /* SHA1 hash of this file. May be NULL. */ |
| 315 | unsigned nFullName; /* Length of zFullName */ |
| 316 | unsigned iLevel; /* Levels of parent directories */ |
| 317 | u8 isDir; /* True if there are children */ |
| 318 | u8 isLast; /* True if this is the last child of its parent */ |
| 319 | }; |
| 320 | |
| 321 | /* |
| 322 | ** A complete file hierarchy |
| 323 | */ |
| 324 | struct FileTree { |
| 325 | FileTreeNode *pFirst; /* First line of the list */ |
| 326 | FileTreeNode *pLast; /* Last line of the list */ |
| 327 | }; |
| 328 | |
| 329 | /* |
| 330 | ** Add one or more new FileTreeNodes to the FileTree object so that the |
| 331 | ** leaf object zPathname is at the end of the node list |
| 332 | */ |
| 333 | static void tree_add_node( |
| 334 | FileTree *pTree, /* Tree into which nodes are added */ |
| 335 | const char *zPath, /* The full pathname of file to add */ |
| 336 | const char *zUuid /* UUID of the file. Might be NULL. */ |
| 337 | ){ |
| 338 | int i; |
| 339 | FileTreeNode *pParent; |
| 340 | FileTreeNode *pChild; |
| 341 | |
| 342 | pChild = pTree->pLast; |
| 343 | pParent = pChild ? pChild->pParent : 0; |
| 344 | while( pParent!=0 && |
| 345 | ( strncmp(pParent->zFullName, zPath, pParent->nFullName)!=0 |
| 346 | || zPath[pParent->nFullName]!='/' ) |
| 347 | ){ |
| 348 | pChild = pParent; |
| 349 | pParent = pChild->pParent; |
| 350 | } |
| 351 | i = pParent ? pParent->nFullName+1 : 0; |
| 352 | if( pChild ) pChild->isLast = 0; |
| 353 | while( zPath[i] ){ |
| 354 | FileTreeNode *pNew; |
| 355 | int iStart = i; |
| 356 | int nByte; |
| 357 | while( zPath[i] && zPath[i]!='/' ){ i++; } |
| 358 | nByte = sizeof(*pNew) + i + 1; |
| 359 | if( zUuid!=0 && zPath[i]==0 ) nByte += UUID_SIZE+1; |
| 360 | pNew = fossil_malloc( nByte ); |
| 361 | pNew->zFullName = (char*)&pNew[1]; |
| 362 | memcpy(pNew->zFullName, zPath, i); |
| 363 | pNew->zFullName[i] = 0; |
| 364 | pNew->nFullName = i; |
| 365 | if( zUuid!=0 && zPath[i]==0 ){ |
| 366 | pNew->zUuid = pNew->zFullName + i + 1; |
| 367 | memcpy(pNew->zUuid, zUuid, UUID_SIZE+1); |
| 368 | }else{ |
| 369 | pNew->zUuid = 0; |
| 370 | } |
| 371 | pNew->zName = pNew->zFullName + iStart; |
| 372 | if( pTree->pLast ){ |
| 373 | pTree->pLast->pNext = pNew; |
| 374 | }else{ |
| 375 | pTree->pFirst = pNew; |
| 376 | } |
| 377 | pNew->pPrev = pTree->pLast; |
| 378 | pNew->pNext = 0; |
| 379 | pNew->pParent = pParent; |
| 380 | pTree->pLast = pNew; |
| 381 | pNew->iLevel = pParent ? pParent->iLevel+1 : 0; |
| 382 | pNew->isDir = zPath[i]=='/'; |
| 383 | pNew->isLast = 1; |
| 384 | while( zPath[i]=='/' ){ i++; } |
| 385 | pParent = pNew; |
| 386 | } |
| 387 | } |
| 388 | |
| 389 | /* |
| 390 | ** WEBPAGE: tree |
| 391 | ** |
| 392 | ** Query parameters: |
| @@ -394,19 +511,23 @@ | |
| 394 | ** name=PATH Directory to display. Optional |
| 395 | ** ci=LABEL Show only files in this check-in. Optional. |
| 396 | ** re=REGEXP Show only files matching REGEXP. Optional. |
| 397 | ** expand Begin with the tree fully expanded. |
| 398 | ** nofiles Show directories (folders) only. Omit files. |
| 399 | */ |
| 400 | void page_tree(void){ |
| 401 | char *zD = fossil_strdup(P("name")); |
| 402 | int nD = zD ? strlen(zD)+1 : 0; |
| 403 | const char *zCI = P("ci"); |
| 404 | int rid = 0; |
| 405 | char *zUuid = 0; |
| 406 | Blob dirname; |
| 407 | Manifest *pM = 0; |
| 408 | int nFile = 0; /* Number of files (or folders with "nofiles") */ |
| 409 | int linkTrunk = 1; /* include link to "trunk" */ |
| 410 | int linkTip = 1; /* include link to "tip" */ |
| 411 | const char *zRE; /* the value for the re=REGEXP query parameter */ |
| 412 | const char *zObjType; /* "files" by default or "folders" for "nofiles" */ |
| @@ -464,14 +585,21 @@ | |
| 464 | int trunkRid = symbolic_name_to_rid("tag:trunk", "ci"); |
| 465 | linkTrunk = trunkRid && rid != trunkRid; |
| 466 | linkTip = rid != symbolic_name_to_rid("tip", "ci"); |
| 467 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 468 | url_add_parameter(&sURI, "ci", zCI); |
| 469 | }else{ |
| 470 | zCI = 0; |
| 471 | } |
| 472 | } |
| 473 | |
| 474 | /* Compute the title of the page */ |
| 475 | blob_zero(&dirname); |
| 476 | if( zD ){ |
| 477 | url_add_parameter(&sURI, "name", zD); |
| @@ -483,10 +611,18 @@ | |
| 483 | }else{ |
| 484 | if( zRE ){ |
| 485 | blob_appendf(&dirname, "matching \"%s\"", zRE); |
| 486 | } |
| 487 | } |
| 488 | if( zCI ){ |
| 489 | style_submenu_element("All", "All", "%s", |
| 490 | url_render(&sURI, "ci", 0, 0, 0)); |
| 491 | if( nD==0 && !showDirOnly ){ |
| 492 | style_submenu_element("File Ages", "File Ages", "%R/fileage?name=%s", |
| @@ -499,87 +635,82 @@ | |
| 499 | } |
| 500 | if( linkTip ){ |
| 501 | style_submenu_element("Tip", "Tip", "%s", |
| 502 | url_render(&sURI, "ci", "tip", 0, 0)); |
| 503 | } |
| 504 | if( !showDirOnly ){ |
| 505 | style_submenu_element("Flat-View", "Flat-View", "%s", |
| 506 | url_render(&sURI, "type", "flat", 0, 0)); |
| 507 | } |
| 508 | |
| 509 | /* Compute the file hierarchy. |
| 510 | */ |
| 511 | if( zCI ){ |
| 512 | Stmt ins, q; |
| 513 | ManifestFile *pFile; |
| 514 | |
| 515 | db_multi_exec( |
| 516 | "CREATE TEMP TABLE filelist(" |
| 517 | " x TEXT PRIMARY KEY COLLATE nocase," |
| 518 | " uuid TEXT" |
| 519 | ") WITHOUT ROWID;" |
| 520 | ); |
| 521 | db_prepare(&ins, "INSERT OR IGNORE INTO filelist VALUES(:f,:u)"); |
| 522 | manifest_file_rewind(pM); |
| 523 | while( (pFile = manifest_file_next(pM,0))!=0 ){ |
| 524 | if( nD>0 |
| 525 | && (fossil_strncmp(pFile->zName, zD, nD-1)!=0 |
| 526 | || pFile->zName[nD-1]!='/') |
| 527 | ){ |
| 528 | continue; |
| 529 | } |
| 530 | if( pRE && re_match(pRE, (const u8*)pFile->zName, -1)==0 ) continue; |
| 531 | db_bind_text(&ins, ":f", pFile->zName); |
| 532 | db_bind_text(&ins, ":u", pFile->zUuid); |
| 533 | db_step(&ins); |
| 534 | db_reset(&ins); |
| 535 | } |
| 536 | db_finalize(&ins); |
| 537 | db_prepare(&q, "SELECT x, uuid FROM filelist ORDER BY x"); |
| 538 | while( db_step(&q)==SQLITE_ROW ){ |
| 539 | tree_add_node(&sTree, db_column_text(&q,0), db_column_text(&q,1)); |
| 540 | nFile++; |
| 541 | } |
| 542 | db_finalize(&q); |
| 543 | }else{ |
| 544 | Stmt q; |
| 545 | db_prepare(&q, "SELECT name FROM filename ORDER BY name COLLATE nocase"); |
| 546 | while( db_step(&q)==SQLITE_ROW ){ |
| 547 | const char *z = db_column_text(&q, 0); |
| 548 | if( nD>0 && (fossil_strncmp(z, zD, nD-1)!=0 || z[nD-1]!='/') ){ |
| 549 | continue; |
| 550 | } |
| 551 | if( pRE && re_match(pRE, (const u8*)z, -1)==0 ) continue; |
| 552 | tree_add_node(&sTree, z, 0); |
| 553 | nFile++; |
| 554 | } |
| 555 | db_finalize(&q); |
| 556 | } |
| 557 | |
| 558 | if( showDirOnly ){ |
| 559 | for(nFile=0, p=sTree.pFirst; p; p=p->pNext){ |
| 560 | if( p->isDir && p->nFullName>nD ) nFile++; |
| 561 | } |
| 562 | zObjType = "folders"; |
| 563 | style_submenu_element("Files","Files","%s", |
| 564 | url_render(&sURI,"nofiles",0,0,0)); |
| 565 | }else{ |
| 566 | zObjType = "files"; |
| 567 | style_submenu_element("Folders","Folders","%s", |
| 568 | url_render(&sURI,"nofiles","1",0,0)); |
| 569 | } |
| 570 | |
| 571 | if( zCI ){ |
| 572 | @ <h2>%d(nFile) %s(zObjType) of check-in |
| 573 | if( sqlite3_strnicmp(zCI, zUuid, (int)strlen(zCI))!=0 ){ |
| 574 | @ "%h(zCI)" |
| 575 | } |
| 576 | @ [%z(href("vinfo?name=%s",zUuid))%S(zUuid)</a>] %s(blob_str(&dirname))</h2> |
| 577 | }else{ |
| 578 | int n = db_int(0, "SELECT count(*) FROM plink"); |
| 579 | @ <h2>%d(nFile) %s(zObjType) from all %d(n) check-ins |
| 580 | @ %s(blob_str(&dirname))</h2> |
| 581 | } |
| 582 | |
| 583 | |
| 584 | /* Generate tree of lists. |
| 585 | ** |
| @@ -596,18 +727,33 @@ | |
| 596 | if( nD ){ |
| 597 | @ <li class="dir last"> |
| 598 | }else{ |
| 599 | @ <li class="dir subdir last"> |
| 600 | } |
| 601 | @ %z(href("%s",url_render(&sURI,"name",0,0,0)))%h(zProjectName)</a> |
| 602 | @ <ul> |
| 603 | for(p=sTree.pFirst, nDir=0; p; p=p->pNext){ |
| 604 | const char *zLastClass = p->isLast ? " last" : ""; |
| 605 | if( p->isDir ){ |
| 606 | const char *zSubdirClass = p->nFullName==nD-1 ? " subdir" : ""; |
| 607 | @ <li class="dir%s(zSubdirClass)%s(zLastClass)"> |
| 608 | @ %z(href("%s",url_render(&sURI,"name",p->zFullName,0,0)))%h(p->zName)</a> |
| 609 | if( startExpanded || p->nFullName<=nD ){ |
| 610 | @ <ul id="dir%d(nDir)"> |
| 611 | }else{ |
| 612 | @ <ul id="dir%d(nDir)" class="collapsed"> |
| 613 | } |
| @@ -614,17 +760,23 @@ | |
| 614 | nDir++; |
| 615 | }else if( !showDirOnly ){ |
| 616 | const char *zFileClass = fileext_class(p->zName); |
| 617 | char *zLink; |
| 618 | if( zCI ){ |
| 619 | zLink = href("%R/artifact/%s",p->zUuid); |
| 620 | }else{ |
| 621 | zLink = href("%R/finfo?name=%T",p->zFullName); |
| 622 | } |
| 623 | @ <li class="%z(zFileClass)%s(zLastClass)">%z(zLink)%h(p->zName)</a> |
| 624 | } |
| 625 | if( p->isLast ){ |
| 626 | int nClose = p->iLevel - (p->pNext ? p->pNext->iLevel : 0); |
| 627 | while( nClose-- > 0 ){ |
| 628 | @ </ul> |
| 629 | } |
| 630 | } |
| @@ -687,16 +839,16 @@ | |
| 687 | @ checkState(); |
| 688 | @ outer_ul.onclick = function(e){ |
| 689 | @ e = e || window.event; |
| 690 | @ var a = e.target || e.srcElement; |
| 691 | @ if( a.nodeName!='A' ) return true; |
| 692 | @ if( a.parentNode==subdir ){ |
| 693 | @ toggleAll(outer_ul); |
| 694 | @ return false; |
| 695 | @ } |
| 696 | @ if( !belowSubdir(a) ) return true; |
| 697 | @ var ul = a.nextSibling; |
| 698 | @ while( ul && ul.nodeName!='UL' ) ul = ul.nextSibling; |
| 699 | @ if( !ul ) return true; /* This is a file link, not a directory */ |
| 700 | @ toggleDir(ul); |
| 701 | @ return false; |
| 702 | @ } |
| @@ -724,87 +876,115 @@ | |
| 724 | }else{ |
| 725 | zClass = mprintf("file"); |
| 726 | } |
| 727 | return zClass; |
| 728 | } |
| 729 | |
| 730 | /* |
| 731 | ** Look at all file containing in the version "vid". Construct a |
| 732 | ** temporary table named "fileage" that contains the file-id for each |
| 733 | ** files, the pathname, the check-in where the file was added, and the |
| 734 | ** mtime on that checkin. If zGlob and *zGlob then only files matching |
| 735 | ** the given glob are computed. |
| 736 | */ |
| 737 | int compute_fileage(int vid, const char* zGlob){ |
| 738 | Manifest *pManifest; |
| 739 | ManifestFile *pFile; |
| 740 | int nFile = 0; |
| 741 | double vmtime; |
| 742 | Stmt ins; |
| 743 | Stmt q1, q2, q3; |
| 744 | Stmt upd; |
| 745 | if(zGlob && !*zGlob) zGlob = NULL; |
| 746 | db_multi_exec( |
| 747 | /*"DROP TABLE IF EXISTS temp.fileage;"*/ |
| 748 | "CREATE TEMP TABLE fileage(" |
| 749 | " fid INTEGER," |
| 750 | " mid INTEGER," |
| 751 | " mtime DATETIME," |
| 752 | " pathname TEXT" |
| 753 | ");" |
| 754 | "CREATE INDEX fileage_fid ON fileage(fid);" |
| 755 | ); |
| 756 | pManifest = manifest_get(vid, CFTYPE_MANIFEST, 0); |
| 757 | if( pManifest==0 ) return 1; |
| 758 | manifest_file_rewind(pManifest); |
| 759 | db_prepare(&ins, |
| 760 | "INSERT INTO temp.fileage(fid, pathname)" |
| 761 | " SELECT rid, :path FROM blob WHERE uuid=:uuid" |
| 762 | ); |
| 763 | while( (pFile = manifest_file_next(pManifest, 0))!=0 ){ |
| 764 | if( zGlob && sqlite3_strglob(zGlob, pFile->zName)!=0 ) continue; |
| 765 | db_bind_text(&ins, ":uuid", pFile->zUuid); |
| 766 | db_bind_text(&ins, ":path", pFile->zName); |
| 767 | db_step(&ins); |
| 768 | db_reset(&ins); |
| 769 | nFile++; |
| 770 | } |
| 771 | db_finalize(&ins); |
| 772 | manifest_destroy(pManifest); |
| 773 | db_prepare(&q1,"SELECT fid FROM mlink WHERE mid=:mid"); |
| 774 | db_prepare(&upd, "UPDATE fileage SET mid=:mid, mtime=:vmtime" |
| 775 | " WHERE fid=:fid AND mid IS NULL"); |
| 776 | db_prepare(&q2,"SELECT pid FROM plink WHERE cid=:vid AND isprim"); |
| 777 | db_prepare(&q3,"SELECT mtime FROM event WHERE objid=:vid"); |
| 778 | while( nFile>0 && vid>0 ){ |
| 779 | db_bind_int(&q3, ":vid", vid); |
| 780 | if( db_step(&q3)==SQLITE_ROW ){ |
| 781 | vmtime = db_column_double(&q3, 0); |
| 782 | }else{ |
| 783 | break; |
| 784 | } |
| 785 | db_reset(&q3); |
| 786 | db_bind_int(&q1, ":mid", vid); |
| 787 | db_bind_int(&upd, ":mid", vid); |
| 788 | db_bind_double(&upd, ":vmtime", vmtime); |
| 789 | while( db_step(&q1)==SQLITE_ROW ){ |
| 790 | db_bind_int(&upd, ":fid", db_column_int(&q1, 0)); |
| 791 | db_step(&upd); |
| 792 | nFile -= db_changes(); |
| 793 | db_reset(&upd); |
| 794 | } |
| 795 | db_reset(&q1); |
| 796 | db_bind_int(&q2, ":vid", vid); |
| 797 | if( db_step(&q2)!=SQLITE_ROW ) break; |
| 798 | vid = db_column_int(&q2, 0); |
| 799 | db_reset(&q2); |
| 800 | } |
| 801 | db_finalize(&q1); |
| 802 | db_finalize(&upd); |
| 803 | db_finalize(&q2); |
| 804 | db_finalize(&q3); |
| 805 | return 0; |
| 806 | } |
| 807 | |
| 808 | /* |
| 809 | ** WEBPAGE: fileage |
| 810 | ** |
| @@ -814,72 +994,94 @@ | |
| 814 | ** (e.g. *.c or *.txt). |
| 815 | */ |
| 816 | void fileage_page(void){ |
| 817 | int rid; |
| 818 | const char *zName; |
| 819 | char *zBaseTime; |
| 820 | const char *zGlob; |
| 821 | Stmt q; |
| 822 | double baseTime; |
| 823 | int lastMid = -1; |
| 824 | login_check_credentials(); |
| 825 | if( !g.perm.Read ){ login_needed(); return; } |
| 826 | zName = P("name"); |
| 827 | if( zName==0 ) zName = "tip"; |
| 828 | rid = symbolic_name_to_rid(zName, "ci"); |
| 829 | if( rid==0 ){ |
| 830 | fossil_fatal("not a valid check-in: %s", zName); |
| 831 | } |
| 832 | style_submenu_element("Tree-View", "Tree-View", "%R/tree?ci=%T", zName); |
| 833 | style_header("File Ages"); |
| 834 | zGlob = P("glob"); |
| 835 | compute_fileage(rid,zGlob); |
| 836 | baseTime = db_double(0.0, "SELECT mtime FROM event WHERE objid=%d", rid); |
| 837 | zBaseTime = db_text("","SELECT datetime(%.20g%s)", baseTime, timeline_utc()); |
| 838 | @ <h2>File Ages For Check-in |
| 839 | @ %z(href("%R/info?name=%T",zName))%h(zName)</a></h2> |
| 840 | @ |
| 841 | @ <p>The times given are relative to |
| 842 | @ %z(href("%R/timeline?c=%T",zBaseTime))%s(zBaseTime)</a>, which is the |
| 843 | @ check-in time for |
| 844 | @ %z(href("%R/info?name=%T",zName))%h(zName)</a></p> |
| 845 | @ |
| 846 | @ <table border=0 cellspacing=0 cellpadding=0> |
| 847 | db_prepare(&q, |
| 848 | "SELECT mtime, (SELECT uuid FROM blob WHERE rid=fid), mid, pathname" |
| 849 | " FROM fileage" |
| 850 | " ORDER BY mtime DESC, mid, pathname" |
| 851 | ); |
| 852 | while( db_step(&q)==SQLITE_ROW ){ |
| 853 | double age = baseTime - db_column_double(&q, 0); |
| 854 | int mid = db_column_int(&q, 2); |
| 855 | const char *zFUuid = db_column_text(&q, 1); |
| 856 | char zAge[200]; |
| 857 | if( lastMid!=mid ){ |
| 858 | @ <tr><td colspan=3><hr></tr> |
| 859 | lastMid = mid; |
| 860 | if( age*86400.0<120 ){ |
| 861 | sqlite3_snprintf(sizeof(zAge), zAge, "%d seconds", (int)(age*86400.0)); |
| 862 | }else if( age*1440.0<90 ){ |
| 863 | sqlite3_snprintf(sizeof(zAge), zAge, "%.1f minutes", age*1440.0); |
| 864 | }else if( age*24.0<36 ){ |
| 865 | sqlite3_snprintf(sizeof(zAge), zAge, "%.1f hours", age*24.0); |
| 866 | }else if( age<365.0 ){ |
| 867 | sqlite3_snprintf(sizeof(zAge), zAge, "%.1f days", age); |
| 868 | }else{ |
| 869 | sqlite3_snprintf(sizeof(zAge), zAge, "%.2f years", age/365.0); |
| 870 | } |
| 871 | }else{ |
| 872 | zAge[0] = 0; |
| 873 | } |
| 874 | @ <tr> |
| 875 | @ <td>%s(zAge) |
| 876 | @ <td width="25"> |
| 877 | @ <td>%z(href("%R/artifact/%s?ln", zFUuid))%h(db_column_text(&q, 3))</a> |
| 878 | @ </tr> |
| 879 | @ |
| 880 | } |
| 881 | @ <tr><td colspan=3><hr></tr> |
| 882 | @ </table> |
| 883 | db_finalize(&q); |
| 884 | style_footer(); |
| 885 | } |
| 886 | |
| 887 | DDED src/bundle.c |
| --- src/browse.c | |
| +++ src/browse.c | |
| @@ -304,89 +304,206 @@ | |
| 304 | |
| 305 | /* |
| 306 | ** A single line of the file hierarchy |
| 307 | */ |
| 308 | struct FileTreeNode { |
| 309 | FileTreeNode *pNext; /* Next entry in an ordered list of them all */ |
| 310 | FileTreeNode *pParent; /* Directory containing this entry */ |
| 311 | FileTreeNode *pSibling; /* Next element in the same subdirectory */ |
| 312 | FileTreeNode *pChild; /* List of child nodes */ |
| 313 | FileTreeNode *pLastChild; /* Last child on the pChild list */ |
| 314 | char *zName; /* Name of this entry. The "tail" */ |
| 315 | char *zFullName; /* Full pathname of this entry */ |
| 316 | char *zUuid; /* SHA1 hash of this file. May be NULL. */ |
| 317 | double mtime; /* Modification time for this entry */ |
| 318 | unsigned nFullName; /* Length of zFullName */ |
| 319 | unsigned iLevel; /* Levels of parent directories */ |
| 320 | }; |
| 321 | |
| 322 | /* |
| 323 | ** A complete file hierarchy |
| 324 | */ |
| 325 | struct FileTree { |
| 326 | FileTreeNode *pFirst; /* First line of the list */ |
| 327 | FileTreeNode *pLast; /* Last line of the list */ |
| 328 | FileTreeNode *pLastTop; /* Last top-level node */ |
| 329 | }; |
| 330 | |
| 331 | /* |
| 332 | ** Add one or more new FileTreeNodes to the FileTree object so that the |
| 333 | ** leaf object zPathname is at the end of the node list. |
| 334 | ** |
| 335 | ** The caller invokes this routine once for each leaf node (each file |
| 336 | ** as opposed to each directory). This routine fills in any missing |
| 337 | ** intermediate nodes automatically. |
| 338 | ** |
| 339 | ** When constructing a list of FileTreeNodes, all entries that have |
| 340 | ** a common directory prefix must be added consecutively in order for |
| 341 | ** the tree to be constructed properly. |
| 342 | */ |
| 343 | static void tree_add_node( |
| 344 | FileTree *pTree, /* Tree into which nodes are added */ |
| 345 | const char *zPath, /* The full pathname of file to add */ |
| 346 | const char *zUuid, /* UUID of the file. Might be NULL. */ |
| 347 | double mtime /* Modification time for this entry */ |
| 348 | ){ |
| 349 | int i; |
| 350 | FileTreeNode *pParent; /* Parent (directory) of the next node to insert */ |
| 351 | |
| 352 | /* Make pParent point to the most recent ancestor of zPath, or |
| 353 | ** NULL if there are no prior entires that are a container for zPath. |
| 354 | */ |
| 355 | pParent = pTree->pLast; |
| 356 | while( pParent!=0 && |
| 357 | ( strncmp(pParent->zFullName, zPath, pParent->nFullName)!=0 |
| 358 | || zPath[pParent->nFullName]!='/' ) |
| 359 | ){ |
| 360 | pParent = pParent->pParent; |
| 361 | } |
| 362 | i = pParent ? pParent->nFullName+1 : 0; |
| 363 | while( zPath[i] ){ |
| 364 | FileTreeNode *pNew; |
| 365 | int iStart = i; |
| 366 | int nByte; |
| 367 | while( zPath[i] && zPath[i]!='/' ){ i++; } |
| 368 | nByte = sizeof(*pNew) + i + 1; |
| 369 | if( zUuid!=0 && zPath[i]==0 ) nByte += UUID_SIZE+1; |
| 370 | pNew = fossil_malloc( nByte ); |
| 371 | memset(pNew, 0, sizeof(*pNew)); |
| 372 | pNew->zFullName = (char*)&pNew[1]; |
| 373 | memcpy(pNew->zFullName, zPath, i); |
| 374 | pNew->zFullName[i] = 0; |
| 375 | pNew->nFullName = i; |
| 376 | if( zUuid!=0 && zPath[i]==0 ){ |
| 377 | pNew->zUuid = pNew->zFullName + i + 1; |
| 378 | memcpy(pNew->zUuid, zUuid, UUID_SIZE+1); |
| 379 | } |
| 380 | pNew->zName = pNew->zFullName + iStart; |
| 381 | if( pTree->pLast ){ |
| 382 | pTree->pLast->pNext = pNew; |
| 383 | }else{ |
| 384 | pTree->pFirst = pNew; |
| 385 | } |
| 386 | pTree->pLast = pNew; |
| 387 | pNew->pParent = pParent; |
| 388 | if( pParent ){ |
| 389 | if( pParent->pChild ){ |
| 390 | pParent->pLastChild->pSibling = pNew; |
| 391 | }else{ |
| 392 | pParent->pChild = pNew; |
| 393 | } |
| 394 | pNew->iLevel = pParent->iLevel + 1; |
| 395 | pParent->pLastChild = pNew; |
| 396 | }else{ |
| 397 | if( pTree->pLastTop ) pTree->pLastTop->pSibling = pNew; |
| 398 | pTree->pLastTop = pNew; |
| 399 | } |
| 400 | pNew->mtime = mtime; |
| 401 | while( zPath[i]=='/' ){ i++; } |
| 402 | pParent = pNew; |
| 403 | } |
| 404 | while( pParent && pParent->pParent ){ |
| 405 | if( pParent->pParent->mtime < pParent->mtime ){ |
| 406 | pParent->pParent->mtime = pParent->mtime; |
| 407 | } |
| 408 | pParent = pParent->pParent; |
| 409 | } |
| 410 | } |
| 411 | |
| 412 | /* Comparison function for two FileTreeNode objects. Sort first by |
| 413 | ** mtime (larger numbers first) and then by zName (smaller names first). |
| 414 | ** |
| 415 | ** Return negative if pLeft<pRight. |
| 416 | ** Return positive if pLeft>pRight. |
| 417 | ** Return zero if pLeft==pRight. |
| 418 | */ |
| 419 | static int compareNodes(FileTreeNode *pLeft, FileTreeNode *pRight){ |
| 420 | if( pLeft->mtime>pRight->mtime ) return -1; |
| 421 | if( pLeft->mtime<pRight->mtime ) return +1; |
| 422 | return fossil_stricmp(pLeft->zName, pRight->zName); |
| 423 | } |
| 424 | |
| 425 | /* Merge together two sorted lists of FileTreeNode objects */ |
| 426 | static FileTreeNode *mergeNodes(FileTreeNode *pLeft, FileTreeNode *pRight){ |
| 427 | FileTreeNode *pEnd; |
| 428 | FileTreeNode base; |
| 429 | pEnd = &base; |
| 430 | while( pLeft && pRight ){ |
| 431 | if( compareNodes(pLeft,pRight)<=0 ){ |
| 432 | pEnd = pEnd->pSibling = pLeft; |
| 433 | pLeft = pLeft->pSibling; |
| 434 | }else{ |
| 435 | pEnd = pEnd->pSibling = pRight; |
| 436 | pRight = pRight->pSibling; |
| 437 | } |
| 438 | } |
| 439 | if( pLeft ){ |
| 440 | pEnd->pSibling = pLeft; |
| 441 | }else{ |
| 442 | pEnd->pSibling = pRight; |
| 443 | } |
| 444 | return base.pSibling; |
| 445 | } |
| 446 | |
| 447 | /* Sort a list of FileTreeNode objects in mtime order. */ |
| 448 | static FileTreeNode *sortNodesByMtime(FileTreeNode *p){ |
| 449 | FileTreeNode *a[30]; |
| 450 | FileTreeNode *pX; |
| 451 | int i; |
| 452 | |
| 453 | memset(a, 0, sizeof(a)); |
| 454 | while( p ){ |
| 455 | pX = p; |
| 456 | p = pX->pSibling; |
| 457 | pX->pSibling = 0; |
| 458 | for(i=0; i<count(a)-1 && a[i]!=0; i++){ |
| 459 | pX = mergeNodes(a[i], pX); |
| 460 | a[i] = 0; |
| 461 | } |
| 462 | a[i] = mergeNodes(a[i], pX); |
| 463 | } |
| 464 | pX = 0; |
| 465 | for(i=0; i<count(a); i++){ |
| 466 | pX = mergeNodes(a[i], pX); |
| 467 | } |
| 468 | return pX; |
| 469 | } |
| 470 | |
| 471 | /* Sort an entire FileTreeNode tree by mtime |
| 472 | ** |
| 473 | ** This routine invalidates the following fields: |
| 474 | ** |
| 475 | ** FileTreeNode.pLastChild |
| 476 | ** FileTreeNode.pNext |
| 477 | ** |
| 478 | ** Use relinkTree to reconnect the pNext pointers. |
| 479 | */ |
| 480 | static FileTreeNode *sortTreeByMtime(FileTreeNode *p){ |
| 481 | FileTreeNode *pX; |
| 482 | for(pX=p; pX; pX=pX->pSibling){ |
| 483 | if( pX->pChild ) pX->pChild = sortTreeByMtime(pX->pChild); |
| 484 | } |
| 485 | return sortNodesByMtime(p); |
| 486 | } |
| 487 | |
| 488 | /* Reconstruct the FileTree by reconnecting the FileTreeNode.pNext |
| 489 | ** fields in sequential order. |
| 490 | */ |
| 491 | static void relinkTree(FileTree *pTree, FileTreeNode *pRoot){ |
| 492 | while( pRoot ){ |
| 493 | if( pTree->pLast ){ |
| 494 | pTree->pLast->pNext = pRoot; |
| 495 | }else{ |
| 496 | pTree->pFirst = pRoot; |
| 497 | } |
| 498 | pTree->pLast = pRoot; |
| 499 | if( pRoot->pChild ) relinkTree(pTree, pRoot->pChild); |
| 500 | pRoot = pRoot->pSibling; |
| 501 | } |
| 502 | if( pTree->pLast ) pTree->pLast->pNext = 0; |
| 503 | } |
| 504 | |
| 505 | |
| 506 | /* |
| 507 | ** WEBPAGE: tree |
| 508 | ** |
| 509 | ** Query parameters: |
| @@ -394,19 +511,23 @@ | |
| 511 | ** name=PATH Directory to display. Optional |
| 512 | ** ci=LABEL Show only files in this check-in. Optional. |
| 513 | ** re=REGEXP Show only files matching REGEXP. Optional. |
| 514 | ** expand Begin with the tree fully expanded. |
| 515 | ** nofiles Show directories (folders) only. Omit files. |
| 516 | ** mtime Order directory elements by decreasing mtime |
| 517 | */ |
| 518 | void page_tree(void){ |
| 519 | char *zD = fossil_strdup(P("name")); |
| 520 | int nD = zD ? strlen(zD)+1 : 0; |
| 521 | const char *zCI = P("ci"); |
| 522 | int rid = 0; |
| 523 | char *zUuid = 0; |
| 524 | Blob dirname; |
| 525 | Manifest *pM = 0; |
| 526 | double rNow = 0; |
| 527 | char *zNow = 0; |
| 528 | int useMtime = atoi(PD("mtime","0")); |
| 529 | int nFile = 0; /* Number of files (or folders with "nofiles") */ |
| 530 | int linkTrunk = 1; /* include link to "trunk" */ |
| 531 | int linkTip = 1; /* include link to "tip" */ |
| 532 | const char *zRE; /* the value for the re=REGEXP query parameter */ |
| 533 | const char *zObjType; /* "files" by default or "folders" for "nofiles" */ |
| @@ -464,14 +585,21 @@ | |
| 585 | int trunkRid = symbolic_name_to_rid("tag:trunk", "ci"); |
| 586 | linkTrunk = trunkRid && rid != trunkRid; |
| 587 | linkTip = rid != symbolic_name_to_rid("tip", "ci"); |
| 588 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 589 | url_add_parameter(&sURI, "ci", zCI); |
| 590 | rNow = db_double(0.0, "SELECT mtime FROM event WHERE objid=%d", rid); |
| 591 | zNow = db_text("", "SELECT datetime(mtime,'localtime')" |
| 592 | " FROM event WHERE objid=%d", rid); |
| 593 | }else{ |
| 594 | zCI = 0; |
| 595 | } |
| 596 | } |
| 597 | if( zCI==0 ){ |
| 598 | rNow = db_double(0.0, "SELECT max(mtime) FROM event"); |
| 599 | zNow = db_text("", "SELECT datetime(max(mtime),'localtime') FROM event"); |
| 600 | } |
| 601 | |
| 602 | /* Compute the title of the page */ |
| 603 | blob_zero(&dirname); |
| 604 | if( zD ){ |
| 605 | url_add_parameter(&sURI, "name", zD); |
| @@ -483,10 +611,18 @@ | |
| 611 | }else{ |
| 612 | if( zRE ){ |
| 613 | blob_appendf(&dirname, "matching \"%s\"", zRE); |
| 614 | } |
| 615 | } |
| 616 | if( useMtime ){ |
| 617 | style_submenu_element("Sort By Filename","Sort By Filename", "%s", |
| 618 | url_render(&sURI, 0, 0, 0, 0)); |
| 619 | url_add_parameter(&sURI, "mtime", "1"); |
| 620 | }else{ |
| 621 | style_submenu_element("Sort By Time","Sort By Time", "%s", |
| 622 | url_render(&sURI, "mtime", "1", 0, 0)); |
| 623 | } |
| 624 | if( zCI ){ |
| 625 | style_submenu_element("All", "All", "%s", |
| 626 | url_render(&sURI, "ci", 0, 0, 0)); |
| 627 | if( nD==0 && !showDirOnly ){ |
| 628 | style_submenu_element("File Ages", "File Ages", "%R/fileage?name=%s", |
| @@ -499,87 +635,82 @@ | |
| 635 | } |
| 636 | if( linkTip ){ |
| 637 | style_submenu_element("Tip", "Tip", "%s", |
| 638 | url_render(&sURI, "ci", "tip", 0, 0)); |
| 639 | } |
| 640 | |
| 641 | /* Compute the file hierarchy. |
| 642 | */ |
| 643 | if( zCI ){ |
| 644 | Stmt q; |
| 645 | compute_fileage(rid, 0); |
| 646 | db_prepare(&q, |
| 647 | "SELECT filename.name, blob.uuid, fileage.mtime\n" |
| 648 | " FROM fileage, filename, blob\n" |
| 649 | " WHERE filename.fnid=fileage.fnid\n" |
| 650 | " AND blob.rid=fileage.fid\n" |
| 651 | " ORDER BY filename.name COLLATE nocase;" |
| 652 | ); |
| 653 | while( db_step(&q)==SQLITE_ROW ){ |
| 654 | const char *zFile = db_column_text(&q,0); |
| 655 | const char *zUuid = db_column_text(&q,1); |
| 656 | double mtime = db_column_double(&q,2); |
| 657 | if( pRE && re_match(pRE, (const unsigned char*)zFile, -1)==0 ) continue; |
| 658 | tree_add_node(&sTree, zFile, zUuid, mtime); |
| 659 | nFile++; |
| 660 | } |
| 661 | db_finalize(&q); |
| 662 | }else{ |
| 663 | Stmt q; |
| 664 | db_prepare(&q, |
| 665 | "SELECT filename.name, blob.uuid, max(event.mtime)\n" |
| 666 | " FROM filename, mlink, blob, event\n" |
| 667 | " WHERE mlink.fnid=filename.fnid\n" |
| 668 | " AND event.objid=mlink.mid\n" |
| 669 | " AND blob.rid=mlink.fid\n" |
| 670 | " GROUP BY 1 ORDER BY 1 COLLATE nocase"); |
| 671 | while( db_step(&q)==SQLITE_ROW ){ |
| 672 | const char *zName = db_column_text(&q, 0); |
| 673 | const char *zUuid = db_column_text(&q,1); |
| 674 | double mtime = db_column_double(&q,2); |
| 675 | if( nD>0 && (fossil_strncmp(zName, zD, nD-1)!=0 || zName[nD-1]!='/') ){ |
| 676 | continue; |
| 677 | } |
| 678 | if( pRE && re_match(pRE, (const u8*)zName, -1)==0 ) continue; |
| 679 | tree_add_node(&sTree, zName, zUuid, mtime); |
| 680 | nFile++; |
| 681 | } |
| 682 | db_finalize(&q); |
| 683 | } |
| 684 | |
| 685 | if( showDirOnly ){ |
| 686 | for(nFile=0, p=sTree.pFirst; p; p=p->pNext){ |
| 687 | if( p->pChild!=0 && p->nFullName>nD ) nFile++; |
| 688 | } |
| 689 | zObjType = "Folders"; |
| 690 | style_submenu_element("Files","Files","%s", |
| 691 | url_render(&sURI,"nofiles",0,0,0)); |
| 692 | }else{ |
| 693 | zObjType = "Files"; |
| 694 | style_submenu_element("Folders","Folders","%s", |
| 695 | url_render(&sURI,"nofiles","1",0,0)); |
| 696 | } |
| 697 | |
| 698 | if( zCI ){ |
| 699 | @ <h2>%s(zObjType) from |
| 700 | if( sqlite3_strnicmp(zCI, zUuid, (int)strlen(zCI))!=0 ){ |
| 701 | @ "%h(zCI)" |
| 702 | } |
| 703 | @ [%z(href("vinfo?name=%s",zUuid))%S(zUuid)</a>] %s(blob_str(&dirname)) |
| 704 | }else{ |
| 705 | int n = db_int(0, "SELECT count(*) FROM plink"); |
| 706 | @ <h2>%s(zObjType) from all %d(n) check-ins %s(blob_str(&dirname)) |
| 707 | } |
| 708 | if( useMtime ){ |
| 709 | @ sorted by modification time</h2> |
| 710 | }else{ |
| 711 | @ sorted by filename</h2> |
| 712 | } |
| 713 | |
| 714 | |
| 715 | /* Generate tree of lists. |
| 716 | ** |
| @@ -596,18 +727,33 @@ | |
| 727 | if( nD ){ |
| 728 | @ <li class="dir last"> |
| 729 | }else{ |
| 730 | @ <li class="dir subdir last"> |
| 731 | } |
| 732 | @ <div class="filetreeline"> |
| 733 | @ %z(href("%s",url_render(&sURI,"name",0,0,0)))%h(zProjectName)</a> |
| 734 | if( zNow ){ |
| 735 | @ <div class="filetreeage">%s(zNow)</div> |
| 736 | } |
| 737 | @ </div> |
| 738 | @ <ul> |
| 739 | if( useMtime ){ |
| 740 | p = sortTreeByMtime(sTree.pFirst); |
| 741 | memset(&sTree, 0, sizeof(sTree)); |
| 742 | relinkTree(&sTree, p); |
| 743 | } |
| 744 | for(p=sTree.pFirst, nDir=0; p; p=p->pNext){ |
| 745 | const char *zLastClass = p->pSibling==0 ? " last" : ""; |
| 746 | if( p->pChild ){ |
| 747 | const char *zSubdirClass = p->nFullName==nD-1 ? " subdir" : ""; |
| 748 | @ <li class="dir%s(zSubdirClass)%s(zLastClass)"><div class="filetreeline"> |
| 749 | @ %z(href("%s",url_render(&sURI,"name",p->zFullName,0,0)))%h(p->zName)</a> |
| 750 | if( p->mtime>0.0 ){ |
| 751 | char *zAge = human_readable_age(rNow - p->mtime); |
| 752 | @ <div class="filetreeage">%s(zAge)</div> |
| 753 | } |
| 754 | @ </div> |
| 755 | if( startExpanded || p->nFullName<=nD ){ |
| 756 | @ <ul id="dir%d(nDir)"> |
| 757 | }else{ |
| 758 | @ <ul id="dir%d(nDir)" class="collapsed"> |
| 759 | } |
| @@ -614,17 +760,23 @@ | |
| 760 | nDir++; |
| 761 | }else if( !showDirOnly ){ |
| 762 | const char *zFileClass = fileext_class(p->zName); |
| 763 | char *zLink; |
| 764 | if( zCI ){ |
| 765 | zLink = href("%R/artifact/%.16s",p->zUuid); |
| 766 | }else{ |
| 767 | zLink = href("%R/finfo?name=%T",p->zFullName); |
| 768 | } |
| 769 | @ <li class="%z(zFileClass)%s(zLastClass)"><div class="filetreeline"> |
| 770 | @ %z(zLink)%h(p->zName)</a> |
| 771 | if( p->mtime>0 ){ |
| 772 | char *zAge = human_readable_age(rNow - p->mtime); |
| 773 | @ <div class="filetreeage">%s(zAge)</div> |
| 774 | } |
| 775 | @ </div> |
| 776 | } |
| 777 | if( p->pSibling==0 ){ |
| 778 | int nClose = p->iLevel - (p->pNext ? p->pNext->iLevel : 0); |
| 779 | while( nClose-- > 0 ){ |
| 780 | @ </ul> |
| 781 | } |
| 782 | } |
| @@ -687,16 +839,16 @@ | |
| 839 | @ checkState(); |
| 840 | @ outer_ul.onclick = function(e){ |
| 841 | @ e = e || window.event; |
| 842 | @ var a = e.target || e.srcElement; |
| 843 | @ if( a.nodeName!='A' ) return true; |
| 844 | @ if( a.parentNode.parentNode==subdir ){ |
| 845 | @ toggleAll(outer_ul); |
| 846 | @ return false; |
| 847 | @ } |
| 848 | @ if( !belowSubdir(a) ) return true; |
| 849 | @ var ul = a.parentNode.nextSibling; |
| 850 | @ while( ul && ul.nodeName!='UL' ) ul = ul.nextSibling; |
| 851 | @ if( !ul ) return true; /* This is a file link, not a directory */ |
| 852 | @ toggleDir(ul); |
| 853 | @ return false; |
| 854 | @ } |
| @@ -724,87 +876,115 @@ | |
| 876 | }else{ |
| 877 | zClass = mprintf("file"); |
| 878 | } |
| 879 | return zClass; |
| 880 | } |
| 881 | |
| 882 | /* |
| 883 | ** SQL used to compute the age of all files in checkin :ckin whose |
| 884 | ** names match :glob |
| 885 | */ |
| 886 | static const char zComputeFileAgeSetup[] = |
| 887 | @ CREATE TABLE IF NOT EXISTS temp.fileage( |
| 888 | @ fnid INTEGER PRIMARY KEY, |
| 889 | @ fid INTEGER, |
| 890 | @ mid INTEGER, |
| 891 | @ mtime DATETIME, |
| 892 | @ pathname TEXT |
| 893 | @ ); |
| 894 | @ CREATE VIRTUAL TABLE IF NOT EXISTS temp.foci USING files_of_checkin; |
| 895 | ; |
| 896 | |
| 897 | static const char zComputeFileAgeRun[] = |
| 898 | @ WITH RECURSIVE |
| 899 | @ ckin(x) AS (VALUES(:ckin) UNION ALL |
| 900 | @ SELECT pid FROM ckin, plink WHERE cid=x AND isprim) |
| 901 | @ INSERT OR IGNORE INTO fileage(fnid, fid, mid, mtime, pathname) |
| 902 | @ SELECT mlink.fnid, mlink.fid, x, event.mtime, filename.name |
| 903 | @ FROM ckin, mlink, event, filename |
| 904 | @ WHERE mlink.mid=ckin.x |
| 905 | @ AND mlink.fnid IN (SELECT fnid FROM foci, filename |
| 906 | @ WHERE foci.checkinID=:ckin |
| 907 | @ AND filename.name=foci.filename |
| 908 | @ AND filename.name GLOB :glob) |
| 909 | @ AND filename.fnid=mlink.fnid |
| 910 | @ AND event.objid=mlink.mid; |
| 911 | ; |
| 912 | |
| 913 | |
| 914 | /* |
| 915 | ** Look at all file containing in the version "vid". Construct a |
| 916 | ** temporary table named "fileage" that contains the file-id for each |
| 917 | ** files, the pathname, the check-in where the file was added, and the |
| 918 | ** mtime on that checkin. If zGlob and *zGlob then only files matching |
| 919 | ** the given glob are computed. |
| 920 | */ |
| 921 | int compute_fileage(int vid, const char* zGlob){ |
| 922 | Stmt q; |
| 923 | db_multi_exec(zComputeFileAgeSetup /*works-like:"constant"*/); |
| 924 | db_prepare(&q, zComputeFileAgeRun /*works-like:"constant"*/); |
| 925 | db_bind_int(&q, ":ckin", vid); |
| 926 | db_bind_text(&q, ":glob", zGlob && zGlob[0] ? zGlob : "*"); |
| 927 | db_exec(&q); |
| 928 | db_finalize(&q); |
| 929 | return 0; |
| 930 | } |
| 931 | |
| 932 | /* |
| 933 | ** Render the number of days in rAge as a more human-readable time span. |
| 934 | ** Different units (seconds, minutes, hours, days, months, years) are |
| 935 | ** selected depending on the magnitude of rAge. |
| 936 | ** |
| 937 | ** The string returned is obtained from fossil_malloc() and should be |
| 938 | ** freed by the caller. |
| 939 | */ |
| 940 | char *human_readable_age(double rAge){ |
| 941 | if( rAge*86400.0<120 ){ |
| 942 | if( rAge*86400.0<1.0 ){ |
| 943 | return mprintf("current"); |
| 944 | }else{ |
| 945 | return mprintf("%d seconds", (int)(rAge*86400.0)); |
| 946 | } |
| 947 | }else if( rAge*1440.0<90 ){ |
| 948 | return mprintf("%.1f minutes", rAge*1440.0); |
| 949 | }else if( rAge*24.0<36 ){ |
| 950 | return mprintf("%.1f hours", rAge*24.0); |
| 951 | }else if( rAge<365.0 ){ |
| 952 | return mprintf("%.1f days", rAge); |
| 953 | }else{ |
| 954 | return mprintf("%.2f years", rAge/365.0); |
| 955 | } |
| 956 | } |
| 957 | |
| 958 | /* |
| 959 | ** COMMAND: test-fileage |
| 960 | ** |
| 961 | ** Usage: %fossil test-fileage CHECKIN |
| 962 | */ |
| 963 | void test_fileage_cmd(void){ |
| 964 | int mid; |
| 965 | Stmt q; |
| 966 | const char *zGlob = find_option("glob",0,1); |
| 967 | db_find_and_open_repository(0,0); |
| 968 | verify_all_options(); |
| 969 | if( g.argc!=3 ) usage("test-fileage CHECKIN"); |
| 970 | mid = name_to_typed_rid(g.argv[2],"ci"); |
| 971 | compute_fileage(mid, zGlob); |
| 972 | db_prepare(&q, |
| 973 | "SELECT fid, mid, julianday('now') - mtime, pathname" |
| 974 | " FROM fileage" |
| 975 | ); |
| 976 | while( db_step(&q)==SQLITE_ROW ){ |
| 977 | char *zAge = human_readable_age(db_column_double(&q,2)); |
| 978 | fossil_print("%8d %8d %16s %s\n", |
| 979 | db_column_int(&q,0), |
| 980 | db_column_int(&q,1), |
| 981 | zAge, |
| 982 | db_column_text(&q,3)); |
| 983 | fossil_free(zAge); |
| 984 | } |
| 985 | db_finalize(&q); |
| 986 | } |
| 987 | |
| 988 | /* |
| 989 | ** WEBPAGE: fileage |
| 990 | ** |
| @@ -814,72 +994,94 @@ | |
| 994 | ** (e.g. *.c or *.txt). |
| 995 | */ |
| 996 | void fileage_page(void){ |
| 997 | int rid; |
| 998 | const char *zName; |
| 999 | const char *zGlob; |
| 1000 | const char *zUuid; |
| 1001 | const char *zNow; /* Time of checkin */ |
| 1002 | Stmt q1, q2; |
| 1003 | double baseTime; |
| 1004 | login_check_credentials(); |
| 1005 | if( !g.perm.Read ){ login_needed(); return; } |
| 1006 | zName = P("name"); |
| 1007 | if( zName==0 ) zName = "tip"; |
| 1008 | rid = symbolic_name_to_rid(zName, "ci"); |
| 1009 | if( rid==0 ){ |
| 1010 | fossil_fatal("not a valid check-in: %s", zName); |
| 1011 | } |
| 1012 | zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 1013 | baseTime = db_double(0.0,"SELECT mtime FROM event WHERE objid=%d", rid); |
| 1014 | zNow = db_text("", "SELECT datetime(mtime,'localtime') FROM event" |
| 1015 | " WHERE objid=%d", rid); |
| 1016 | style_submenu_element("Tree-View", "Tree-View", "%R/tree?ci=%T&mtime=1", |
| 1017 | zName); |
| 1018 | style_header("File Ages"); |
| 1019 | zGlob = P("glob"); |
| 1020 | compute_fileage(rid,zGlob); |
| 1021 | db_multi_exec("CREATE INDEX fileage_ix1 ON fileage(mid,pathname);"); |
| 1022 | |
| 1023 | @ <h2>Files in |
| 1024 | @ %z(href("%R/info?name=%T",zUuid))[%S(zUuid)]</a> |
| 1025 | if( zGlob && zGlob[0] ){ |
| 1026 | @ that match "%h(zGlob)" and |
| 1027 | } |
| 1028 | @ ordered by check-in time</h2> |
| 1029 | @ |
| 1030 | @ <p>Times are relative to the checkin time for |
| 1031 | @ %z(href("%R/ci/%s",zUuid))[%S(zUuid)]</a> which is |
| 1032 | @ %z(href("%R/timeline?c=%t",zNow))%s(zNow)</a>.</p> |
| 1033 | @ |
| 1034 | @ <div class='fileage'><table> |
| 1035 | @ <tr><th>Time</th><th>Files</th><th>Checkin</th></tr> |
| 1036 | db_prepare(&q1, |
| 1037 | "SELECT event.mtime, event.objid, blob.uuid,\n" |
| 1038 | " coalesce(event.ecomment,event.comment),\n" |
| 1039 | " coalesce(event.euser,event.user),\n" |
| 1040 | " coalesce((SELECT value FROM tagxref\n" |
| 1041 | " WHERE tagtype>0 AND tagid=%d\n" |
| 1042 | " AND rid=event.objid),'trunk')\n" |
| 1043 | " FROM event, blob\n" |
| 1044 | " WHERE event.objid IN (SELECT mid FROM fileage)\n" |
| 1045 | " AND blob.rid=event.objid\n" |
| 1046 | " ORDER BY event.mtime DESC;", |
| 1047 | TAG_BRANCH |
| 1048 | ); |
| 1049 | db_prepare(&q2, |
| 1050 | "SELECT blob.uuid, filename.name\n" |
| 1051 | " FROM fileage, blob, filename\n" |
| 1052 | " WHERE fileage.mid=:mid AND filename.fnid=fileage.fnid" |
| 1053 | " AND blob.rid=fileage.fid;" |
| 1054 | ); |
| 1055 | while( db_step(&q1)==SQLITE_ROW ){ |
| 1056 | double age = baseTime - db_column_double(&q1, 0); |
| 1057 | int mid = db_column_int(&q1, 1); |
| 1058 | const char *zUuid = db_column_text(&q1, 2); |
| 1059 | const char *zComment = db_column_text(&q1, 3); |
| 1060 | const char *zUser = db_column_text(&q1, 4); |
| 1061 | const char *zBranch = db_column_text(&q1, 5); |
| 1062 | char *zAge = human_readable_age(age); |
| 1063 | @ <tr><td>%s(zAge)</td> |
| 1064 | @ <td> |
| 1065 | db_bind_int(&q2, ":mid", mid); |
| 1066 | while( db_step(&q2)==SQLITE_ROW ){ |
| 1067 | const char *zFUuid = db_column_text(&q2,0); |
| 1068 | const char *zFile = db_column_text(&q2,1); |
| 1069 | @ %z(href("%R/artifact/%s",zFUuid))%h(zFile)</a><br> |
| 1070 | } |
| 1071 | db_reset(&q2); |
| 1072 | @ </td> |
| 1073 | @ <td> |
| 1074 | @ %z(href("%R/info/%s",zUuid))[%S(zUuid)]</a> |
| 1075 | @ %W(zComment) (user: |
| 1076 | @ %z(href("%R/timeline?u=%t&c=%t&nd&n=200",zUser,zUuid))%h(zUser)</a>, |
| 1077 | @ branch: |
| 1078 | @ %z(href("%R/timeline?r=%t&c=%t&nd&n=200",zBranch,zUuid))%h(zBranch)</a>) |
| 1079 | @ </td></tr> |
| 1080 | @ |
| 1081 | fossil_free(zAge); |
| 1082 | } |
| 1083 | @ </table></div> |
| 1084 | db_finalize(&q1); |
| 1085 | db_finalize(&q2); |
| 1086 | style_footer(); |
| 1087 | } |
| 1088 | |
| 1089 | DDED src/bundle.c |
+307
| --- a/src/bundle.c | ||
| +++ b/src/bundle.c | ||
| @@ -0,0 +1,307 @@ | ||
| 1 | +/* | |
| 2 | +** Copyright (==40** Copyright (c) 2014 D/* | |
| 3 | +** Copyright (c) 2014 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 | +** This file contains code used to implement and manage a "bundle" file. | |
| 20 | +*/ | |
| 21 | +#include "config.h" | |
| 22 | +#include "bundle.h" | |
| 23 | +#include <assert.h> | |
| 24 | + | |
| 25 | +/* | |
| 26 | +** SQL code used to initialize the schema of a bundle. | |
| 27 | +** | |
| 28 | +** The bblob.delta field can be an integer, a text string, or NULL. | |
| 29 | +** If an integer, then the corresponding blobid is the delta basis. | |
| 30 | +** If a text string, then that string is a SHA1 hash for the delta | |
| 31 | +** basis, whister is ainory. If NULL, then | |
| 32 | +** data contains content without delta compression. | |
| 33 | +*/ | |
| 34 | +static const cha r zBundleInit[] = | |
| 35 | +@ CREATE TABLE IF NOT EXISTS "%w".bconfig( | |
| 36 | +@ bcname TEXT, | |
| 37 | +@ bcvalue ANY | |
| 38 | +@ ); | |
| 39 | +@ CREATE TABLE IF NOT EXISTS "%w".bblob( | |
| 40 | +@ blobid INTEGER PRIMARY KEY, -- Blob ID | |
| 41 | +@ uuid TEXT SHA1 NOT NULL, -- hash of expanded blob | |
| 42 | +@ sz INT NOT NULL, -- Size of blob after expansion | |
| 43 | +@ delta ANY, -- Delta compression basis, or NULL | |
| 44 | +@ notes TEXT, -- Description of content | |
| 45 | +@ data BLOB -- compressed content | |
| 46 | +@ ); | |
| 47 | +; | |
| 48 | + | |
| 49 | +/* | |
| 50 | +** Attach a bundle file to the current database connection using the | |
| 51 | +** attachment name zBName. | |
| 52 | +*/ | |
| 53 | +static void bundle_attach_file( | |
| 54 | + const char *zFile, /* Name of the file that contains the bundle */ | |
| 55 | + const char *zBName, /* Attachment name */ | |
| 56 | + int doInit /* Initialize a new bundle, if true */ | |
| 57 | +){ | |
| 58 | + int rc; | |
| 59 | + char *zErrMsg = 0; | |
| 60 | + char *zSql; | |
| 61 | + if( )<0 ){blob.rid=tobundle.rid" | |
| 62 | + _size(zFile, ExtFILE)<0 ){ | |
| 63 | + fossil_fatal("no such file: %s", zFile); | |
| 64 | + } | |
| 65 | + assert( g.db ); | |
| 66 | + zSql = sqlite3_mprintf("ATTAfatalhat string is a SHA1 c = sqlite3_exec(g.db, zSql, 0, 0, &zErrMsg); | |
| 67 | + sqlite3_free(zSql); | |
| 68 | + if( rc!=SQLITE_OK || zErrMsg ){ | |
| 69 | + if( zErrMsg==0 ) zErrMsg = (char*)sqlite3_errmsg(g.db); | |
| 70 | + fossil_fatal("not a valid bundle: %s", zFile); | |
| 71 | + } | |
| 72 | + if( doInit ){ | |
| 73 | + db_multi_exec(zBundleInit /*works-like:"%w%w"*/, zBName, zBName); | |
| 74 | + }else{ | |
| 75 | + sqlite3_stmt *pStmt; | |
| 76 | + zSql = sqlite3_mprintf("SELECT bcname, bcvalue" | |
| 77 | + " FROM \"%w\".bconfig", zBName);panic that string is a SHA1fatalhat string is a SHA1 hash for the delta | |
| 78 | +** basis, whister is presumably in the main repository. If NULL, then | |
| 79 | +** data contains content without delta compression. | |
| 80 | +*/ | |
| 81 | +static const char zBundleInit[] = | |
| 82 | +@ CREATE TABLE IF NOT EXISTS "%w".bconfig( | |
| 83 | +@ bcname TEXT, | |
| 84 | +@ bcvalue ANY | |
| 85 | +@ ); | |
| 86 | +@ CREATE TABLE IF NOT EXISTS "%w".bblob( | |
| 87 | +@ blobid INTEGER Pfatalhat string is a SHA1 hash for the delta | |
| 88 | +** basis, whister is presumably in the main repository. If NULL, then | |
| 89 | +** data contains content without delta compressio} | |
| 90 | +} | |
| 91 | + | |
| 92 | +/* | |
| 93 | +**sociates("ok", 1); | |
| 94 | + | |
| 95 | + /* NULL | |
| 96 | +@ notes TEXT, -- Description of content | |
| 97 | +@ data BLOB -- compressed content | |
| 98 | +@ ); | |
| 99 | +; | |
| 100 | + | |
| 101 | +/* | |
| 102 | +** Attac ter is presumably iHipp | |
| 103 | +** | |
| 104 | +** This program is free software; you can redistribute it and/or | |
| 105 | +** modify it under the terms of the Simplified BSD License (also | |
| 106 | +** known as the "2-Clause License" or "FreeBSD License".) | |
| 107 | + | |
| 108 | +** This program is distributed in the hope that it will be useful, | |
| 109 | +** but without any warranty; without even the implied warranty of | |
| 110 | +** merchantability or fitness for a particular purpose. | |
| 111 | +** | |
| 112 | +** Author contact information: | |
| 113 | +** [email protected] | |
| 114 | +** http://www.hwaci.com/drh/ | |
| 115 | +** | |
| 116 | +******************************************************************************* | |
| 117 | +** | |
| 118 | +** This file contains code used to implement and manage a "bundle" file. | |
| 119 | +*/ | |
| 120 | +#include "config.h" | |
| 121 | +#include "bundle.h" | |
| 122 | +#include <assert.h> | |
| 123 | + | |
| 124 | +/* | |
| 125 | +** SQL code used to initialize the schema of a bundle. | |
| 126 | +** | |
| 127 | +** The bblob.delta field can be an integer, a text string, or NULL. | |
| 128 | +** If an integer, then the corresponding blobid is the delta basis. | |
| 129 | +** If a text string, then that string is a SHA1 hash for the delta | |
| 130 | +** basis, whister is ainory. If NULL, then | |
| 131 | +** data contains content without delta compression. | |
| 132 | +*/ | |
| 133 | +static const char zBundleInit[] = | |
| 134 | +@ CREATE TABLE IF NOT EXISTS "%w/mpressed content | |
| 135 | +@ ); | |
| 136 | +; | |
| 137 | + | |
| 138 | +/* | |
| 139 | +** Attach a bundle file to the current database connection using the | |
| 140 | +** attachment name zBName. | |
| 141 | +*/ | |
| 142 | +static void bundle_attach_file( | |
| 143 | + const char *zFile, /* Name of the file that contains the bundle */ | |
| 144 | + const char *zBName, /* Attachment name */ | |
| 145 | + int doInit /* Initialize a new bundle, if true */ | |
| 146 | +){ | |
| 147 | + int rc; | |
| 148 | + char *zErrMsg = 0; | |
| 149 | + char *zSql; | |
| 150 | + if( )<0 ){blob.rid=tobundle.rid" | |
| 151 | + _size(zFile, ExtFILE)<0 ){ | |
| 152 | + fossil_fatal("no such file: %s", zFile); | |
| 153 | + } | |
| 154 | + assert( g.db ); | |
| 155 | + zSql = sqlite3_mprintf("ATTAfatalhat string is a SHA1 c = sqlite3_exec(g.db, zSql, 0, 0, &zErrMsg); | |
| 156 | + sqlite3_free(zSql); | |
| 157 | + if( rc!=SQLITE_OK || zErrMsg ){ | |
| 158 | + if( zErrMsg==0 ) zErrMsg = (char*)sqlite3_errmsg(g.db); | |
| 159 | + fossil_fatal("not a valid bundle: %s", zFile); | |
| 160 | + } | |
| 161 | + if( doInit ){ | |
| 162 | + db_multi_exec(zBundleInit /*works-like:"%w%w"*/, zBName, zBName); | |
| 163 | + }else{ | |
| 164 | + sqlite3_stmt *pStmt; | |
| 165 | + zSql = sqlite3_mprintf("SELECT bcname, bcvalue" | |
| 166 | + " FROM \"%w\".bconfig", zBName);panic that string is a SHA1fatalhat string is a SHA1 hash for the delta | |
| 167 | +** basis, whister is presumably in the main repository. If NULL, then | |
| 168 | +** data contains content without delta compression. | |
| 169 | +*/ | |
| 170 | +statc const char zBundleInit[] = | |
| 171 | +@ CREATE TABLE IF NOT EXISTS "%w".bconfig( | |
| 172 | +@ bcname TEXT, | |
| 173 | +@ bcvalue ANY | |
| 174 | +@ ); | |
| 175 | +@ CREATE TABLE IF NOT EXISTS "% Pfatalhat string is a SHA1 hash for the delta | |
| 176 | +** basis, whister is presumably in the main reposa contains content without delta compressio} | |
| 177 | +} | |
| 178 | + | |
| 179 | +/* | |
| 180 | +**sociates("ok", 1); | |
| 181 | + | |
| 182 | + /* NULL | |
| 183 | +@ notes TEXT, -- Description of ontent | |
| 184 | +@ data BLOB content | |
| 185 | +@ ); | |
| 186 | +; | |
| 187 | + | |
| 188 | +/* | |
| 189 | +** Attach a bundle file to the current database connection using the | |
| 190 | +** attachment name zBName. | |
| 191 | +*/ | |
| 192 | +static void bundle_attach_file( | |
| 193 | + const char *zFile, /* Name of the file that contains the bundle */ | |
| 194 | + const char *zBName, */ | |
| 195 | +){ | |
| 196 | + int rc; | |
| 197 | + char *zErrMsg = 0; | |
| 198 | + char *zSql; | |
| 199 | + if( !doInit && file_size(zFile, ExtFILE)<0 ){ | |
| 200 | + fossil_fatal("no such file: %s", zFile); | |
| 201 | + } | |
| 202 | + assert( g.db ); | |
| 203 | + zSql = sqlite3_mprintf("ATTACH %Q AS %Q", zFile, zBName); | |
| 204 | + if( zSql==0 ) fossil_fatal("out of memory"); | |
| 205 | + rc = sqlite3_exec(g.db, zSql, 0, 0, &zErrMsg); | |
| 206 | + sqlite3_free(zSql); | |
| 207 | + if( rc!=SQLITE_OK || zErrMsg ){ | |
| 208 | + if( zErrMsg==0 ) zErrMsg = (char*)sqlite3_errmsg(g.db); | |
| 209 | + fossil_fatal("not a valid bundle: %s", zFile); | |
| 210 | + } | |
| 211 | + if( doInit ){ | |
| 212 | + db_multi_exec(zBundleInit /*works-like:"%w%w"*/, zBName, zBName); | |
| 213 | + }else{ | |
| 214 | + sqlite3_stmt *pStmt; | |
| 215 | + zSql = sqlite3_mprintf("SELECT bcname, bcvalue" | |
| 216 | + " FROM \"%w\".bconfig", zBName); | |
| 217 | + if( zSql==0 ) fossil_fatal("out of memory"); | |
| 218 | + rc = sqlite3_prepare(g.db, zSql, -1, &pStmt, 0); | |
| 219 | + if( rc ) fossil_fatal("not a valid bundle: %s", zFile); | |
| 220 | + sqlite3_free(zSql); | |
| 221 | + sqlite3_finalize(pStmt); | |
| 222 | + zSql = sqlite3_mprintf("SELECT blobid, uuid, | |
| 223 | +**makesright (==40** Copyright (c) 2014 D/* | |
| 224 | +** Copyright (c) 2014 D. Richard Hipp | |
| 225 | +** | |
| 226 | +** This program is free software; you can redistribute it and/or | |
| 227 | +** modify it under the terms of the Simplified BSD License (also | |
| 228 | +** known as the "2-Clause License" or "FreeBSD License".) | |
| 229 | + | |
| 230 | +** This program is distributed in the hope that it will be useful, | |
| 231 | +** but without any warranty; without even the implied warranty of | |
| 232 | +** merchantability or fitness for a particular purpose. | |
| 233 | +** | |
| 234 | +** Author contact information: | |
| 235 | +** [email protected] | |
| 236 | +** http://www.hwaci.com/drh/ | |
| 237 | +** | |
| 238 | +******************************************************************************* | |
| 239 | +** | |
| 240 | +** This file contains code used to implement and manage a "bundle" file. | |
| 241 | +*/ | |
| 242 | +#include "config.h" | |
| 243 | +#include "bundle.h" | |
| 244 | +#include <assert.h> | |
| 245 | + | |
| 246 | +/* | |
| 247 | +** SQe schema of a bundle. | |
| 248 | +** | |
| 249 | +** The bblob.delta field can be an integer, a text string, or NULL. | |
| 250 | +** If an integer, then the corresponding blobid is the delta basis. | |
| 251 | +** If a text string, then that string is a SHA1 hash for the delta | |
| 252 | +** basis, whister is presumably in the ain repository. If NULL, then | |
| 253 | +** data contains content without delta compression. | |
| 254 | +*/ | |
| 255 | +static const char zBundleInit[] = | |
| 256 | +@ CREATE TABLE IF NOT EXISTS "%w".bconfig(e ANY | |
| 257 | +@ ); | |
| 258 | +@ CREATE TABLE IF NOT EXISTS "%w".bblob( | |
| 259 | +@ blobid INTEGER PRIMARY KEY, -- Blob ID | |
| 260 | +@ uuid TEXT SHA1 NOT NULL, -- hash of expanded blob | |
| 261 | +@ sz INT NOT NULL, -- Size of blob after expansion | |
| 262 | +@ delta ANY, -- Delta compression basis, or NULL | |
| 263 | +@ notes TEXT, -- Description of content | |
| 264 | +@ data BLOB -- compressed content | |
| 265 | +@ ); | |
| 266 | +; | |
| 267 | + | |
| 268 | +/* | |
| 269 | +** Attach a bundle file to the current database connection using the | |
| 270 | +** attachment name zBName. | |
| 271 | +*/ | |
| 272 | +static void bundle_attach_file( | |
| 273 | + const char *zFile, /* Name of the file that contains the bundle */ | |
| 274 | + const char *zBName, /* Attachment name */ | |
| 275 | + int doInit /* Initialize a new bundle, if true */ | |
| 276 | +){ | |
| 277 | + int rc; | |
| 278 | + char *zErrMsg = 0; | |
| 279 | + char *zSql; | |
| 280 | + if( )<0 ){blob.rid=tobundle.rid" | |
| 281 | + _size(zFile, ExtFILE)<0 ){ | |
| 282 | + fossil_fatal("no such file: %s", zFile); | |
| 283 | + } | |
| 284 | + assert( g.db ); | |
| 285 | + zSql = sqlite3_mprintf("ATTAfatalhat string is a SHA1 c = sqlite3_exec(g.db, zSql, 0, 0, &zErrMsg); | |
| 286 | + sqlite3_free(zSql); | |
| 287 | + if( rc!=SQLITE_OK || zErrMsg ){ | |
| 288 | + if( zErrMsg==0 ) zErrMsg = (char*)sqlite3_errmsg(g.db); | |
| 289 | + fossil_fatal("not a valid bundle: %s", zFile); | |
| 290 | + } | |
| 291 | + if( doInit ){ | |
| 292 | + db_multi_exec(zBundleInit /*works-like:"%w%w"*/, zBName, zBName); | |
| 293 | + }else{ | |
| 294 | + sqlite3_stmt *pStmt; | |
| 295 | + zSql = sqlite3_mprintf("SELECT bcname, bcvalue" | |
| 296 | + " FROM \"%w\".bconfig", zBName);panic that string is a SHA1fatalhat string is a SHA1 hash for the delta | |
| 297 | +** basis, whister is presumably in the main repository. If NULL, then | |
| 298 | +** data contains content without delta compression. | |
| 299 | +*/ | |
| 300 | +static const char zBundleInit[] = | |
| 301 | +@ CREATE TABLE IF NOT EXISTS "%w".bconfig( | |
| 302 | +@ bcname TEXT, | |
| 303 | +@ bcvalue ANY | |
| 304 | +@ ); | |
| 305 | +@ CREATE TABLE IF NOT EXISTS "%w".bblob( | |
| 306 | +@ blobid INTEGER Pfatalhat string is a SHA1 hash for the delta | |
| 307 | +** basis, whist ins |
| --- a/src/bundle.c | |
| +++ b/src/bundle.c | |
| @@ -0,0 +1,307 @@ | |
| --- a/src/bundle.c | |
| +++ b/src/bundle.c | |
| @@ -0,0 +1,307 @@ | |
| 1 | /* |
| 2 | ** Copyright (==40** Copyright (c) 2014 D/* |
| 3 | ** Copyright (c) 2014 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 | ** This file contains code used to implement and manage a "bundle" file. |
| 20 | */ |
| 21 | #include "config.h" |
| 22 | #include "bundle.h" |
| 23 | #include <assert.h> |
| 24 | |
| 25 | /* |
| 26 | ** SQL code used to initialize the schema of a bundle. |
| 27 | ** |
| 28 | ** The bblob.delta field can be an integer, a text string, or NULL. |
| 29 | ** If an integer, then the corresponding blobid is the delta basis. |
| 30 | ** If a text string, then that string is a SHA1 hash for the delta |
| 31 | ** basis, whister is ainory. If NULL, then |
| 32 | ** data contains content without delta compression. |
| 33 | */ |
| 34 | static const cha r zBundleInit[] = |
| 35 | @ CREATE TABLE IF NOT EXISTS "%w".bconfig( |
| 36 | @ bcname TEXT, |
| 37 | @ bcvalue ANY |
| 38 | @ ); |
| 39 | @ CREATE TABLE IF NOT EXISTS "%w".bblob( |
| 40 | @ blobid INTEGER PRIMARY KEY, -- Blob ID |
| 41 | @ uuid TEXT SHA1 NOT NULL, -- hash of expanded blob |
| 42 | @ sz INT NOT NULL, -- Size of blob after expansion |
| 43 | @ delta ANY, -- Delta compression basis, or NULL |
| 44 | @ notes TEXT, -- Description of content |
| 45 | @ data BLOB -- compressed content |
| 46 | @ ); |
| 47 | ; |
| 48 | |
| 49 | /* |
| 50 | ** Attach a bundle file to the current database connection using the |
| 51 | ** attachment name zBName. |
| 52 | */ |
| 53 | static void bundle_attach_file( |
| 54 | const char *zFile, /* Name of the file that contains the bundle */ |
| 55 | const char *zBName, /* Attachment name */ |
| 56 | int doInit /* Initialize a new bundle, if true */ |
| 57 | ){ |
| 58 | int rc; |
| 59 | char *zErrMsg = 0; |
| 60 | char *zSql; |
| 61 | if( )<0 ){blob.rid=tobundle.rid" |
| 62 | _size(zFile, ExtFILE)<0 ){ |
| 63 | fossil_fatal("no such file: %s", zFile); |
| 64 | } |
| 65 | assert( g.db ); |
| 66 | zSql = sqlite3_mprintf("ATTAfatalhat string is a SHA1 c = sqlite3_exec(g.db, zSql, 0, 0, &zErrMsg); |
| 67 | sqlite3_free(zSql); |
| 68 | if( rc!=SQLITE_OK || zErrMsg ){ |
| 69 | if( zErrMsg==0 ) zErrMsg = (char*)sqlite3_errmsg(g.db); |
| 70 | fossil_fatal("not a valid bundle: %s", zFile); |
| 71 | } |
| 72 | if( doInit ){ |
| 73 | db_multi_exec(zBundleInit /*works-like:"%w%w"*/, zBName, zBName); |
| 74 | }else{ |
| 75 | sqlite3_stmt *pStmt; |
| 76 | zSql = sqlite3_mprintf("SELECT bcname, bcvalue" |
| 77 | " FROM \"%w\".bconfig", zBName);panic that string is a SHA1fatalhat string is a SHA1 hash for the delta |
| 78 | ** basis, whister is presumably in the main repository. If NULL, then |
| 79 | ** data contains content without delta compression. |
| 80 | */ |
| 81 | static const char zBundleInit[] = |
| 82 | @ CREATE TABLE IF NOT EXISTS "%w".bconfig( |
| 83 | @ bcname TEXT, |
| 84 | @ bcvalue ANY |
| 85 | @ ); |
| 86 | @ CREATE TABLE IF NOT EXISTS "%w".bblob( |
| 87 | @ blobid INTEGER Pfatalhat string is a SHA1 hash for the delta |
| 88 | ** basis, whister is presumably in the main repository. If NULL, then |
| 89 | ** data contains content without delta compressio} |
| 90 | } |
| 91 | |
| 92 | /* |
| 93 | **sociates("ok", 1); |
| 94 | |
| 95 | /* NULL |
| 96 | @ notes TEXT, -- Description of content |
| 97 | @ data BLOB -- compressed content |
| 98 | @ ); |
| 99 | ; |
| 100 | |
| 101 | /* |
| 102 | ** Attac ter is presumably iHipp |
| 103 | ** |
| 104 | ** This program is free software; you can redistribute it and/or |
| 105 | ** modify it under the terms of the Simplified BSD License (also |
| 106 | ** known as the "2-Clause License" or "FreeBSD License".) |
| 107 | |
| 108 | ** This program is distributed in the hope that it will be useful, |
| 109 | ** but without any warranty; without even the implied warranty of |
| 110 | ** merchantability or fitness for a particular purpose. |
| 111 | ** |
| 112 | ** Author contact information: |
| 113 | ** [email protected] |
| 114 | ** http://www.hwaci.com/drh/ |
| 115 | ** |
| 116 | ******************************************************************************* |
| 117 | ** |
| 118 | ** This file contains code used to implement and manage a "bundle" file. |
| 119 | */ |
| 120 | #include "config.h" |
| 121 | #include "bundle.h" |
| 122 | #include <assert.h> |
| 123 | |
| 124 | /* |
| 125 | ** SQL code used to initialize the schema of a bundle. |
| 126 | ** |
| 127 | ** The bblob.delta field can be an integer, a text string, or NULL. |
| 128 | ** If an integer, then the corresponding blobid is the delta basis. |
| 129 | ** If a text string, then that string is a SHA1 hash for the delta |
| 130 | ** basis, whister is ainory. If NULL, then |
| 131 | ** data contains content without delta compression. |
| 132 | */ |
| 133 | static const char zBundleInit[] = |
| 134 | @ CREATE TABLE IF NOT EXISTS "%w/mpressed content |
| 135 | @ ); |
| 136 | ; |
| 137 | |
| 138 | /* |
| 139 | ** Attach a bundle file to the current database connection using the |
| 140 | ** attachment name zBName. |
| 141 | */ |
| 142 | static void bundle_attach_file( |
| 143 | const char *zFile, /* Name of the file that contains the bundle */ |
| 144 | const char *zBName, /* Attachment name */ |
| 145 | int doInit /* Initialize a new bundle, if true */ |
| 146 | ){ |
| 147 | int rc; |
| 148 | char *zErrMsg = 0; |
| 149 | char *zSql; |
| 150 | if( )<0 ){blob.rid=tobundle.rid" |
| 151 | _size(zFile, ExtFILE)<0 ){ |
| 152 | fossil_fatal("no such file: %s", zFile); |
| 153 | } |
| 154 | assert( g.db ); |
| 155 | zSql = sqlite3_mprintf("ATTAfatalhat string is a SHA1 c = sqlite3_exec(g.db, zSql, 0, 0, &zErrMsg); |
| 156 | sqlite3_free(zSql); |
| 157 | if( rc!=SQLITE_OK || zErrMsg ){ |
| 158 | if( zErrMsg==0 ) zErrMsg = (char*)sqlite3_errmsg(g.db); |
| 159 | fossil_fatal("not a valid bundle: %s", zFile); |
| 160 | } |
| 161 | if( doInit ){ |
| 162 | db_multi_exec(zBundleInit /*works-like:"%w%w"*/, zBName, zBName); |
| 163 | }else{ |
| 164 | sqlite3_stmt *pStmt; |
| 165 | zSql = sqlite3_mprintf("SELECT bcname, bcvalue" |
| 166 | " FROM \"%w\".bconfig", zBName);panic that string is a SHA1fatalhat string is a SHA1 hash for the delta |
| 167 | ** basis, whister is presumably in the main repository. If NULL, then |
| 168 | ** data contains content without delta compression. |
| 169 | */ |
| 170 | statc const char zBundleInit[] = |
| 171 | @ CREATE TABLE IF NOT EXISTS "%w".bconfig( |
| 172 | @ bcname TEXT, |
| 173 | @ bcvalue ANY |
| 174 | @ ); |
| 175 | @ CREATE TABLE IF NOT EXISTS "% Pfatalhat string is a SHA1 hash for the delta |
| 176 | ** basis, whister is presumably in the main reposa contains content without delta compressio} |
| 177 | } |
| 178 | |
| 179 | /* |
| 180 | **sociates("ok", 1); |
| 181 | |
| 182 | /* NULL |
| 183 | @ notes TEXT, -- Description of ontent |
| 184 | @ data BLOB content |
| 185 | @ ); |
| 186 | ; |
| 187 | |
| 188 | /* |
| 189 | ** Attach a bundle file to the current database connection using the |
| 190 | ** attachment name zBName. |
| 191 | */ |
| 192 | static void bundle_attach_file( |
| 193 | const char *zFile, /* Name of the file that contains the bundle */ |
| 194 | const char *zBName, */ |
| 195 | ){ |
| 196 | int rc; |
| 197 | char *zErrMsg = 0; |
| 198 | char *zSql; |
| 199 | if( !doInit && file_size(zFile, ExtFILE)<0 ){ |
| 200 | fossil_fatal("no such file: %s", zFile); |
| 201 | } |
| 202 | assert( g.db ); |
| 203 | zSql = sqlite3_mprintf("ATTACH %Q AS %Q", zFile, zBName); |
| 204 | if( zSql==0 ) fossil_fatal("out of memory"); |
| 205 | rc = sqlite3_exec(g.db, zSql, 0, 0, &zErrMsg); |
| 206 | sqlite3_free(zSql); |
| 207 | if( rc!=SQLITE_OK || zErrMsg ){ |
| 208 | if( zErrMsg==0 ) zErrMsg = (char*)sqlite3_errmsg(g.db); |
| 209 | fossil_fatal("not a valid bundle: %s", zFile); |
| 210 | } |
| 211 | if( doInit ){ |
| 212 | db_multi_exec(zBundleInit /*works-like:"%w%w"*/, zBName, zBName); |
| 213 | }else{ |
| 214 | sqlite3_stmt *pStmt; |
| 215 | zSql = sqlite3_mprintf("SELECT bcname, bcvalue" |
| 216 | " FROM \"%w\".bconfig", zBName); |
| 217 | if( zSql==0 ) fossil_fatal("out of memory"); |
| 218 | rc = sqlite3_prepare(g.db, zSql, -1, &pStmt, 0); |
| 219 | if( rc ) fossil_fatal("not a valid bundle: %s", zFile); |
| 220 | sqlite3_free(zSql); |
| 221 | sqlite3_finalize(pStmt); |
| 222 | zSql = sqlite3_mprintf("SELECT blobid, uuid, |
| 223 | **makesright (==40** Copyright (c) 2014 D/* |
| 224 | ** Copyright (c) 2014 D. Richard Hipp |
| 225 | ** |
| 226 | ** This program is free software; you can redistribute it and/or |
| 227 | ** modify it under the terms of the Simplified BSD License (also |
| 228 | ** known as the "2-Clause License" or "FreeBSD License".) |
| 229 | |
| 230 | ** This program is distributed in the hope that it will be useful, |
| 231 | ** but without any warranty; without even the implied warranty of |
| 232 | ** merchantability or fitness for a particular purpose. |
| 233 | ** |
| 234 | ** Author contact information: |
| 235 | ** [email protected] |
| 236 | ** http://www.hwaci.com/drh/ |
| 237 | ** |
| 238 | ******************************************************************************* |
| 239 | ** |
| 240 | ** This file contains code used to implement and manage a "bundle" file. |
| 241 | */ |
| 242 | #include "config.h" |
| 243 | #include "bundle.h" |
| 244 | #include <assert.h> |
| 245 | |
| 246 | /* |
| 247 | ** SQe schema of a bundle. |
| 248 | ** |
| 249 | ** The bblob.delta field can be an integer, a text string, or NULL. |
| 250 | ** If an integer, then the corresponding blobid is the delta basis. |
| 251 | ** If a text string, then that string is a SHA1 hash for the delta |
| 252 | ** basis, whister is presumably in the ain repository. If NULL, then |
| 253 | ** data contains content without delta compression. |
| 254 | */ |
| 255 | static const char zBundleInit[] = |
| 256 | @ CREATE TABLE IF NOT EXISTS "%w".bconfig(e ANY |
| 257 | @ ); |
| 258 | @ CREATE TABLE IF NOT EXISTS "%w".bblob( |
| 259 | @ blobid INTEGER PRIMARY KEY, -- Blob ID |
| 260 | @ uuid TEXT SHA1 NOT NULL, -- hash of expanded blob |
| 261 | @ sz INT NOT NULL, -- Size of blob after expansion |
| 262 | @ delta ANY, -- Delta compression basis, or NULL |
| 263 | @ notes TEXT, -- Description of content |
| 264 | @ data BLOB -- compressed content |
| 265 | @ ); |
| 266 | ; |
| 267 | |
| 268 | /* |
| 269 | ** Attach a bundle file to the current database connection using the |
| 270 | ** attachment name zBName. |
| 271 | */ |
| 272 | static void bundle_attach_file( |
| 273 | const char *zFile, /* Name of the file that contains the bundle */ |
| 274 | const char *zBName, /* Attachment name */ |
| 275 | int doInit /* Initialize a new bundle, if true */ |
| 276 | ){ |
| 277 | int rc; |
| 278 | char *zErrMsg = 0; |
| 279 | char *zSql; |
| 280 | if( )<0 ){blob.rid=tobundle.rid" |
| 281 | _size(zFile, ExtFILE)<0 ){ |
| 282 | fossil_fatal("no such file: %s", zFile); |
| 283 | } |
| 284 | assert( g.db ); |
| 285 | zSql = sqlite3_mprintf("ATTAfatalhat string is a SHA1 c = sqlite3_exec(g.db, zSql, 0, 0, &zErrMsg); |
| 286 | sqlite3_free(zSql); |
| 287 | if( rc!=SQLITE_OK || zErrMsg ){ |
| 288 | if( zErrMsg==0 ) zErrMsg = (char*)sqlite3_errmsg(g.db); |
| 289 | fossil_fatal("not a valid bundle: %s", zFile); |
| 290 | } |
| 291 | if( doInit ){ |
| 292 | db_multi_exec(zBundleInit /*works-like:"%w%w"*/, zBName, zBName); |
| 293 | }else{ |
| 294 | sqlite3_stmt *pStmt; |
| 295 | zSql = sqlite3_mprintf("SELECT bcname, bcvalue" |
| 296 | " FROM \"%w\".bconfig", zBName);panic that string is a SHA1fatalhat string is a SHA1 hash for the delta |
| 297 | ** basis, whister is presumably in the main repository. If NULL, then |
| 298 | ** data contains content without delta compression. |
| 299 | */ |
| 300 | static const char zBundleInit[] = |
| 301 | @ CREATE TABLE IF NOT EXISTS "%w".bconfig( |
| 302 | @ bcname TEXT, |
| 303 | @ bcvalue ANY |
| 304 | @ ); |
| 305 | @ CREATE TABLE IF NOT EXISTS "%w".bblob( |
| 306 | @ blobid INTEGER Pfatalhat string is a SHA1 hash for the delta |
| 307 | ** basis, whist ins |
+1
-3
| --- src/cgi.c | ||
| +++ src/cgi.c | ||
| @@ -342,13 +342,11 @@ | ||
| 342 | 342 | ** case of most /getfile calls for specific versions, the only way the |
| 343 | 343 | ** content changes is if someone breaks the SCM. And if that happens, a |
| 344 | 344 | ** stale cache is the least of the problem. So we provide an Expires |
| 345 | 345 | ** header set to a reasonable period (default: one week). |
| 346 | 346 | */ |
| 347 | - /*time_t expires = time(0) + atoi(db_config("constant_expires","604800"));*/ | |
| 348 | - time_t expires = time(0) + 604800; | |
| 349 | - fprintf(g.httpOut, "Expires: %s\r\n", cgi_rfc822_datestamp(expires)); | |
| 347 | + fprintf(g.httpOut, "Cache-control: max-age=28800\r\n"); | |
| 350 | 348 | }else{ |
| 351 | 349 | fprintf(g.httpOut, "Cache-control: no-cache\r\n"); |
| 352 | 350 | } |
| 353 | 351 | |
| 354 | 352 | /* Content intended for logged in users should only be cached in |
| 355 | 353 |
| --- src/cgi.c | |
| +++ src/cgi.c | |
| @@ -342,13 +342,11 @@ | |
| 342 | ** case of most /getfile calls for specific versions, the only way the |
| 343 | ** content changes is if someone breaks the SCM. And if that happens, a |
| 344 | ** stale cache is the least of the problem. So we provide an Expires |
| 345 | ** header set to a reasonable period (default: one week). |
| 346 | */ |
| 347 | /*time_t expires = time(0) + atoi(db_config("constant_expires","604800"));*/ |
| 348 | time_t expires = time(0) + 604800; |
| 349 | fprintf(g.httpOut, "Expires: %s\r\n", cgi_rfc822_datestamp(expires)); |
| 350 | }else{ |
| 351 | fprintf(g.httpOut, "Cache-control: no-cache\r\n"); |
| 352 | } |
| 353 | |
| 354 | /* Content intended for logged in users should only be cached in |
| 355 |
| --- src/cgi.c | |
| +++ src/cgi.c | |
| @@ -342,13 +342,11 @@ | |
| 342 | ** case of most /getfile calls for specific versions, the only way the |
| 343 | ** content changes is if someone breaks the SCM. And if that happens, a |
| 344 | ** stale cache is the least of the problem. So we provide an Expires |
| 345 | ** header set to a reasonable period (default: one week). |
| 346 | */ |
| 347 | fprintf(g.httpOut, "Cache-control: max-age=28800\r\n"); |
| 348 | }else{ |
| 349 | fprintf(g.httpOut, "Cache-control: no-cache\r\n"); |
| 350 | } |
| 351 | |
| 352 | /* Content intended for logged in users should only be cached in |
| 353 |
+9
-1
| --- src/checkin.c | ||
| +++ src/checkin.c | ||
| @@ -65,11 +65,11 @@ | ||
| 65 | 65 | |
| 66 | 66 | db_prepare(&q, |
| 67 | 67 | "SELECT pathname, deleted, chnged, rid, coalesce(origname!=pathname,0)" |
| 68 | 68 | " FROM vfile " |
| 69 | 69 | " WHERE is_selected(id) %s" |
| 70 | - " AND (chnged OR deleted OR rid=0 OR pathname!=origname) ORDER BY 1", | |
| 70 | + " AND (chnged OR deleted OR rid=0 OR pathname!=origname) ORDER BY 1 /*scan*/", | |
| 71 | 71 | blob_sql_text(&where) |
| 72 | 72 | ); |
| 73 | 73 | blob_zero(&rewrittenPathname); |
| 74 | 74 | while( db_step(&q)==SQLITE_ROW ){ |
| 75 | 75 | const char *zPathname = db_column_text(&q,0); |
| @@ -497,10 +497,11 @@ | ||
| 497 | 497 | " ORDER BY 1", |
| 498 | 498 | fossil_all_reserved_names(0) |
| 499 | 499 | ); |
| 500 | 500 | db_multi_exec("DELETE FROM sfile WHERE x IN (SELECT pathname FROM vfile)"); |
| 501 | 501 | blob_zero(&rewrittenPathname); |
| 502 | + g.allowSymlinks = 1; /* Report on symbolic links */ | |
| 502 | 503 | while( db_step(&q)==SQLITE_ROW ){ |
| 503 | 504 | zDisplayName = zPathname = db_column_text(&q, 0); |
| 504 | 505 | if( cwdRelative ) { |
| 505 | 506 | char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname); |
| 506 | 507 | file_relative_name(zFullName, &rewrittenPathname, 0); |
| @@ -567,10 +568,11 @@ | ||
| 567 | 568 | ** argument. Matching files, if any, are removed |
| 568 | 569 | ** prior to checking for any empty directories; |
| 569 | 570 | ** therefore, directories that contain only files |
| 570 | 571 | ** that were removed will be removed as well. |
| 571 | 572 | ** -f|--force Remove files without prompting. |
| 573 | +** --verily Shorthand for: -f --emptydirs --dotfiles | |
| 572 | 574 | ** --ignore <CSG> Ignore files matching patterns from the |
| 573 | 575 | ** comma separated list of glob patterns. |
| 574 | 576 | ** --keep <CSG> Keep files matching this comma separated |
| 575 | 577 | ** list of glob patterns. |
| 576 | 578 | ** -n|--dry-run If given, display instead of run actions. |
| @@ -608,10 +610,15 @@ | ||
| 608 | 610 | if( find_option("allckouts",0,0)!=0 ) scanFlags |= SCAN_NESTED; |
| 609 | 611 | zIgnoreFlag = find_option("ignore",0,1); |
| 610 | 612 | verboseFlag = find_option("verbose","v",0)!=0; |
| 611 | 613 | zKeepFlag = find_option("keep",0,1); |
| 612 | 614 | db_must_be_within_tree(); |
| 615 | + if( find_option("verily",0,0)!=0 ){ | |
| 616 | + allFileFlag = allDirFlag = 1; | |
| 617 | + emptyDirsFlag = 1; | |
| 618 | + scanFlags |= SCAN_ALL; | |
| 619 | + } | |
| 613 | 620 | if( zIgnoreFlag==0 ){ |
| 614 | 621 | zIgnoreFlag = db_get("ignore-glob", 0); |
| 615 | 622 | } |
| 616 | 623 | if( zKeepFlag==0 ){ |
| 617 | 624 | zKeepFlag = db_get("keep-glob", 0); |
| @@ -637,10 +644,11 @@ | ||
| 637 | 644 | blob_reset(&extremeAnswer); |
| 638 | 645 | } |
| 639 | 646 | pIgnore = glob_create(zIgnoreFlag); |
| 640 | 647 | pKeep = glob_create(zKeepFlag); |
| 641 | 648 | nRoot = (int)strlen(g.zLocalRoot); |
| 649 | + g.allowSymlinks = 1; /* Find symlinks too */ | |
| 642 | 650 | if( !dirsOnlyFlag ){ |
| 643 | 651 | Stmt q; |
| 644 | 652 | Blob repo; |
| 645 | 653 | locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, |
| 646 | 654 | extremeFlag ? 0 : pIgnore); |
| 647 | 655 |
| --- src/checkin.c | |
| +++ src/checkin.c | |
| @@ -65,11 +65,11 @@ | |
| 65 | |
| 66 | db_prepare(&q, |
| 67 | "SELECT pathname, deleted, chnged, rid, coalesce(origname!=pathname,0)" |
| 68 | " FROM vfile " |
| 69 | " WHERE is_selected(id) %s" |
| 70 | " AND (chnged OR deleted OR rid=0 OR pathname!=origname) ORDER BY 1", |
| 71 | blob_sql_text(&where) |
| 72 | ); |
| 73 | blob_zero(&rewrittenPathname); |
| 74 | while( db_step(&q)==SQLITE_ROW ){ |
| 75 | const char *zPathname = db_column_text(&q,0); |
| @@ -497,10 +497,11 @@ | |
| 497 | " ORDER BY 1", |
| 498 | fossil_all_reserved_names(0) |
| 499 | ); |
| 500 | db_multi_exec("DELETE FROM sfile WHERE x IN (SELECT pathname FROM vfile)"); |
| 501 | blob_zero(&rewrittenPathname); |
| 502 | while( db_step(&q)==SQLITE_ROW ){ |
| 503 | zDisplayName = zPathname = db_column_text(&q, 0); |
| 504 | if( cwdRelative ) { |
| 505 | char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname); |
| 506 | file_relative_name(zFullName, &rewrittenPathname, 0); |
| @@ -567,10 +568,11 @@ | |
| 567 | ** argument. Matching files, if any, are removed |
| 568 | ** prior to checking for any empty directories; |
| 569 | ** therefore, directories that contain only files |
| 570 | ** that were removed will be removed as well. |
| 571 | ** -f|--force Remove files without prompting. |
| 572 | ** --ignore <CSG> Ignore files matching patterns from the |
| 573 | ** comma separated list of glob patterns. |
| 574 | ** --keep <CSG> Keep files matching this comma separated |
| 575 | ** list of glob patterns. |
| 576 | ** -n|--dry-run If given, display instead of run actions. |
| @@ -608,10 +610,15 @@ | |
| 608 | if( find_option("allckouts",0,0)!=0 ) scanFlags |= SCAN_NESTED; |
| 609 | zIgnoreFlag = find_option("ignore",0,1); |
| 610 | verboseFlag = find_option("verbose","v",0)!=0; |
| 611 | zKeepFlag = find_option("keep",0,1); |
| 612 | db_must_be_within_tree(); |
| 613 | if( zIgnoreFlag==0 ){ |
| 614 | zIgnoreFlag = db_get("ignore-glob", 0); |
| 615 | } |
| 616 | if( zKeepFlag==0 ){ |
| 617 | zKeepFlag = db_get("keep-glob", 0); |
| @@ -637,10 +644,11 @@ | |
| 637 | blob_reset(&extremeAnswer); |
| 638 | } |
| 639 | pIgnore = glob_create(zIgnoreFlag); |
| 640 | pKeep = glob_create(zKeepFlag); |
| 641 | nRoot = (int)strlen(g.zLocalRoot); |
| 642 | if( !dirsOnlyFlag ){ |
| 643 | Stmt q; |
| 644 | Blob repo; |
| 645 | locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, |
| 646 | extremeFlag ? 0 : pIgnore); |
| 647 |
| --- src/checkin.c | |
| +++ src/checkin.c | |
| @@ -65,11 +65,11 @@ | |
| 65 | |
| 66 | db_prepare(&q, |
| 67 | "SELECT pathname, deleted, chnged, rid, coalesce(origname!=pathname,0)" |
| 68 | " FROM vfile " |
| 69 | " WHERE is_selected(id) %s" |
| 70 | " AND (chnged OR deleted OR rid=0 OR pathname!=origname) ORDER BY 1 /*scan*/", |
| 71 | blob_sql_text(&where) |
| 72 | ); |
| 73 | blob_zero(&rewrittenPathname); |
| 74 | while( db_step(&q)==SQLITE_ROW ){ |
| 75 | const char *zPathname = db_column_text(&q,0); |
| @@ -497,10 +497,11 @@ | |
| 497 | " ORDER BY 1", |
| 498 | fossil_all_reserved_names(0) |
| 499 | ); |
| 500 | db_multi_exec("DELETE FROM sfile WHERE x IN (SELECT pathname FROM vfile)"); |
| 501 | blob_zero(&rewrittenPathname); |
| 502 | g.allowSymlinks = 1; /* Report on symbolic links */ |
| 503 | while( db_step(&q)==SQLITE_ROW ){ |
| 504 | zDisplayName = zPathname = db_column_text(&q, 0); |
| 505 | if( cwdRelative ) { |
| 506 | char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname); |
| 507 | file_relative_name(zFullName, &rewrittenPathname, 0); |
| @@ -567,10 +568,11 @@ | |
| 568 | ** argument. Matching files, if any, are removed |
| 569 | ** prior to checking for any empty directories; |
| 570 | ** therefore, directories that contain only files |
| 571 | ** that were removed will be removed as well. |
| 572 | ** -f|--force Remove files without prompting. |
| 573 | ** --verily Shorthand for: -f --emptydirs --dotfiles |
| 574 | ** --ignore <CSG> Ignore files matching patterns from the |
| 575 | ** comma separated list of glob patterns. |
| 576 | ** --keep <CSG> Keep files matching this comma separated |
| 577 | ** list of glob patterns. |
| 578 | ** -n|--dry-run If given, display instead of run actions. |
| @@ -608,10 +610,15 @@ | |
| 610 | if( find_option("allckouts",0,0)!=0 ) scanFlags |= SCAN_NESTED; |
| 611 | zIgnoreFlag = find_option("ignore",0,1); |
| 612 | verboseFlag = find_option("verbose","v",0)!=0; |
| 613 | zKeepFlag = find_option("keep",0,1); |
| 614 | db_must_be_within_tree(); |
| 615 | if( find_option("verily",0,0)!=0 ){ |
| 616 | allFileFlag = allDirFlag = 1; |
| 617 | emptyDirsFlag = 1; |
| 618 | scanFlags |= SCAN_ALL; |
| 619 | } |
| 620 | if( zIgnoreFlag==0 ){ |
| 621 | zIgnoreFlag = db_get("ignore-glob", 0); |
| 622 | } |
| 623 | if( zKeepFlag==0 ){ |
| 624 | zKeepFlag = db_get("keep-glob", 0); |
| @@ -637,10 +644,11 @@ | |
| 644 | blob_reset(&extremeAnswer); |
| 645 | } |
| 646 | pIgnore = glob_create(zIgnoreFlag); |
| 647 | pKeep = glob_create(zKeepFlag); |
| 648 | nRoot = (int)strlen(g.zLocalRoot); |
| 649 | g.allowSymlinks = 1; /* Find symlinks too */ |
| 650 | if( !dirsOnlyFlag ){ |
| 651 | Stmt q; |
| 652 | Blob repo; |
| 653 | locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, |
| 654 | extremeFlag ? 0 : pIgnore); |
| 655 |
+9
-1
| --- src/checkin.c | ||
| +++ src/checkin.c | ||
| @@ -65,11 +65,11 @@ | ||
| 65 | 65 | |
| 66 | 66 | db_prepare(&q, |
| 67 | 67 | "SELECT pathname, deleted, chnged, rid, coalesce(origname!=pathname,0)" |
| 68 | 68 | " FROM vfile " |
| 69 | 69 | " WHERE is_selected(id) %s" |
| 70 | - " AND (chnged OR deleted OR rid=0 OR pathname!=origname) ORDER BY 1", | |
| 70 | + " AND (chnged OR deleted OR rid=0 OR pathname!=origname) ORDER BY 1 /*scan*/", | |
| 71 | 71 | blob_sql_text(&where) |
| 72 | 72 | ); |
| 73 | 73 | blob_zero(&rewrittenPathname); |
| 74 | 74 | while( db_step(&q)==SQLITE_ROW ){ |
| 75 | 75 | const char *zPathname = db_column_text(&q,0); |
| @@ -497,10 +497,11 @@ | ||
| 497 | 497 | " ORDER BY 1", |
| 498 | 498 | fossil_all_reserved_names(0) |
| 499 | 499 | ); |
| 500 | 500 | db_multi_exec("DELETE FROM sfile WHERE x IN (SELECT pathname FROM vfile)"); |
| 501 | 501 | blob_zero(&rewrittenPathname); |
| 502 | + g.allowSymlinks = 1; /* Report on symbolic links */ | |
| 502 | 503 | while( db_step(&q)==SQLITE_ROW ){ |
| 503 | 504 | zDisplayName = zPathname = db_column_text(&q, 0); |
| 504 | 505 | if( cwdRelative ) { |
| 505 | 506 | char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname); |
| 506 | 507 | file_relative_name(zFullName, &rewrittenPathname, 0); |
| @@ -567,10 +568,11 @@ | ||
| 567 | 568 | ** argument. Matching files, if any, are removed |
| 568 | 569 | ** prior to checking for any empty directories; |
| 569 | 570 | ** therefore, directories that contain only files |
| 570 | 571 | ** that were removed will be removed as well. |
| 571 | 572 | ** -f|--force Remove files without prompting. |
| 573 | +** --verily Shorthand for: -f --emptydirs --dotfiles | |
| 572 | 574 | ** --ignore <CSG> Ignore files matching patterns from the |
| 573 | 575 | ** comma separated list of glob patterns. |
| 574 | 576 | ** --keep <CSG> Keep files matching this comma separated |
| 575 | 577 | ** list of glob patterns. |
| 576 | 578 | ** -n|--dry-run If given, display instead of run actions. |
| @@ -608,10 +610,15 @@ | ||
| 608 | 610 | if( find_option("allckouts",0,0)!=0 ) scanFlags |= SCAN_NESTED; |
| 609 | 611 | zIgnoreFlag = find_option("ignore",0,1); |
| 610 | 612 | verboseFlag = find_option("verbose","v",0)!=0; |
| 611 | 613 | zKeepFlag = find_option("keep",0,1); |
| 612 | 614 | db_must_be_within_tree(); |
| 615 | + if( find_option("verily",0,0)!=0 ){ | |
| 616 | + allFileFlag = allDirFlag = 1; | |
| 617 | + emptyDirsFlag = 1; | |
| 618 | + scanFlags |= SCAN_ALL; | |
| 619 | + } | |
| 613 | 620 | if( zIgnoreFlag==0 ){ |
| 614 | 621 | zIgnoreFlag = db_get("ignore-glob", 0); |
| 615 | 622 | } |
| 616 | 623 | if( zKeepFlag==0 ){ |
| 617 | 624 | zKeepFlag = db_get("keep-glob", 0); |
| @@ -637,10 +644,11 @@ | ||
| 637 | 644 | blob_reset(&extremeAnswer); |
| 638 | 645 | } |
| 639 | 646 | pIgnore = glob_create(zIgnoreFlag); |
| 640 | 647 | pKeep = glob_create(zKeepFlag); |
| 641 | 648 | nRoot = (int)strlen(g.zLocalRoot); |
| 649 | + g.allowSymlinks = 1; /* Find symlinks too */ | |
| 642 | 650 | if( !dirsOnlyFlag ){ |
| 643 | 651 | Stmt q; |
| 644 | 652 | Blob repo; |
| 645 | 653 | locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, |
| 646 | 654 | extremeFlag ? 0 : pIgnore); |
| 647 | 655 |
| --- src/checkin.c | |
| +++ src/checkin.c | |
| @@ -65,11 +65,11 @@ | |
| 65 | |
| 66 | db_prepare(&q, |
| 67 | "SELECT pathname, deleted, chnged, rid, coalesce(origname!=pathname,0)" |
| 68 | " FROM vfile " |
| 69 | " WHERE is_selected(id) %s" |
| 70 | " AND (chnged OR deleted OR rid=0 OR pathname!=origname) ORDER BY 1", |
| 71 | blob_sql_text(&where) |
| 72 | ); |
| 73 | blob_zero(&rewrittenPathname); |
| 74 | while( db_step(&q)==SQLITE_ROW ){ |
| 75 | const char *zPathname = db_column_text(&q,0); |
| @@ -497,10 +497,11 @@ | |
| 497 | " ORDER BY 1", |
| 498 | fossil_all_reserved_names(0) |
| 499 | ); |
| 500 | db_multi_exec("DELETE FROM sfile WHERE x IN (SELECT pathname FROM vfile)"); |
| 501 | blob_zero(&rewrittenPathname); |
| 502 | while( db_step(&q)==SQLITE_ROW ){ |
| 503 | zDisplayName = zPathname = db_column_text(&q, 0); |
| 504 | if( cwdRelative ) { |
| 505 | char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname); |
| 506 | file_relative_name(zFullName, &rewrittenPathname, 0); |
| @@ -567,10 +568,11 @@ | |
| 567 | ** argument. Matching files, if any, are removed |
| 568 | ** prior to checking for any empty directories; |
| 569 | ** therefore, directories that contain only files |
| 570 | ** that were removed will be removed as well. |
| 571 | ** -f|--force Remove files without prompting. |
| 572 | ** --ignore <CSG> Ignore files matching patterns from the |
| 573 | ** comma separated list of glob patterns. |
| 574 | ** --keep <CSG> Keep files matching this comma separated |
| 575 | ** list of glob patterns. |
| 576 | ** -n|--dry-run If given, display instead of run actions. |
| @@ -608,10 +610,15 @@ | |
| 608 | if( find_option("allckouts",0,0)!=0 ) scanFlags |= SCAN_NESTED; |
| 609 | zIgnoreFlag = find_option("ignore",0,1); |
| 610 | verboseFlag = find_option("verbose","v",0)!=0; |
| 611 | zKeepFlag = find_option("keep",0,1); |
| 612 | db_must_be_within_tree(); |
| 613 | if( zIgnoreFlag==0 ){ |
| 614 | zIgnoreFlag = db_get("ignore-glob", 0); |
| 615 | } |
| 616 | if( zKeepFlag==0 ){ |
| 617 | zKeepFlag = db_get("keep-glob", 0); |
| @@ -637,10 +644,11 @@ | |
| 637 | blob_reset(&extremeAnswer); |
| 638 | } |
| 639 | pIgnore = glob_create(zIgnoreFlag); |
| 640 | pKeep = glob_create(zKeepFlag); |
| 641 | nRoot = (int)strlen(g.zLocalRoot); |
| 642 | if( !dirsOnlyFlag ){ |
| 643 | Stmt q; |
| 644 | Blob repo; |
| 645 | locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, |
| 646 | extremeFlag ? 0 : pIgnore); |
| 647 |
| --- src/checkin.c | |
| +++ src/checkin.c | |
| @@ -65,11 +65,11 @@ | |
| 65 | |
| 66 | db_prepare(&q, |
| 67 | "SELECT pathname, deleted, chnged, rid, coalesce(origname!=pathname,0)" |
| 68 | " FROM vfile " |
| 69 | " WHERE is_selected(id) %s" |
| 70 | " AND (chnged OR deleted OR rid=0 OR pathname!=origname) ORDER BY 1 /*scan*/", |
| 71 | blob_sql_text(&where) |
| 72 | ); |
| 73 | blob_zero(&rewrittenPathname); |
| 74 | while( db_step(&q)==SQLITE_ROW ){ |
| 75 | const char *zPathname = db_column_text(&q,0); |
| @@ -497,10 +497,11 @@ | |
| 497 | " ORDER BY 1", |
| 498 | fossil_all_reserved_names(0) |
| 499 | ); |
| 500 | db_multi_exec("DELETE FROM sfile WHERE x IN (SELECT pathname FROM vfile)"); |
| 501 | blob_zero(&rewrittenPathname); |
| 502 | g.allowSymlinks = 1; /* Report on symbolic links */ |
| 503 | while( db_step(&q)==SQLITE_ROW ){ |
| 504 | zDisplayName = zPathname = db_column_text(&q, 0); |
| 505 | if( cwdRelative ) { |
| 506 | char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname); |
| 507 | file_relative_name(zFullName, &rewrittenPathname, 0); |
| @@ -567,10 +568,11 @@ | |
| 568 | ** argument. Matching files, if any, are removed |
| 569 | ** prior to checking for any empty directories; |
| 570 | ** therefore, directories that contain only files |
| 571 | ** that were removed will be removed as well. |
| 572 | ** -f|--force Remove files without prompting. |
| 573 | ** --verily Shorthand for: -f --emptydirs --dotfiles |
| 574 | ** --ignore <CSG> Ignore files matching patterns from the |
| 575 | ** comma separated list of glob patterns. |
| 576 | ** --keep <CSG> Keep files matching this comma separated |
| 577 | ** list of glob patterns. |
| 578 | ** -n|--dry-run If given, display instead of run actions. |
| @@ -608,10 +610,15 @@ | |
| 610 | if( find_option("allckouts",0,0)!=0 ) scanFlags |= SCAN_NESTED; |
| 611 | zIgnoreFlag = find_option("ignore",0,1); |
| 612 | verboseFlag = find_option("verbose","v",0)!=0; |
| 613 | zKeepFlag = find_option("keep",0,1); |
| 614 | db_must_be_within_tree(); |
| 615 | if( find_option("verily",0,0)!=0 ){ |
| 616 | allFileFlag = allDirFlag = 1; |
| 617 | emptyDirsFlag = 1; |
| 618 | scanFlags |= SCAN_ALL; |
| 619 | } |
| 620 | if( zIgnoreFlag==0 ){ |
| 621 | zIgnoreFlag = db_get("ignore-glob", 0); |
| 622 | } |
| 623 | if( zKeepFlag==0 ){ |
| 624 | zKeepFlag = db_get("keep-glob", 0); |
| @@ -637,10 +644,11 @@ | |
| 644 | blob_reset(&extremeAnswer); |
| 645 | } |
| 646 | pIgnore = glob_create(zIgnoreFlag); |
| 647 | pKeep = glob_create(zKeepFlag); |
| 648 | nRoot = (int)strlen(g.zLocalRoot); |
| 649 | g.allowSymlinks = 1; /* Find symlinks too */ |
| 650 | if( !dirsOnlyFlag ){ |
| 651 | Stmt q; |
| 652 | Blob repo; |
| 653 | locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, |
| 654 | extremeFlag ? 0 : pIgnore); |
| 655 |
+1
-2
| --- src/checkout.c | ||
| +++ src/checkout.c | ||
| @@ -305,12 +305,11 @@ | ||
| 305 | 305 | |
| 306 | 306 | if( !forceFlag && unsaved_changes(0) ){ |
| 307 | 307 | fossil_fatal("there are unsaved changes in the current checkout"); |
| 308 | 308 | } |
| 309 | 309 | if( !forceFlag |
| 310 | - && db_exists("SELECT 1 FROM %s.sqlite_master WHERE name='stash'", | |
| 311 | - db_name("localdb")) | |
| 310 | + && db_table_exists("localdb","stash") | |
| 312 | 311 | && db_exists("SELECT 1 FROM %s.stash", db_name("localdb")) |
| 313 | 312 | ){ |
| 314 | 313 | fossil_fatal("closing the checkout will delete your stash"); |
| 315 | 314 | } |
| 316 | 315 | if( db_is_writeable("repository") ){ |
| 317 | 316 |
| --- src/checkout.c | |
| +++ src/checkout.c | |
| @@ -305,12 +305,11 @@ | |
| 305 | |
| 306 | if( !forceFlag && unsaved_changes(0) ){ |
| 307 | fossil_fatal("there are unsaved changes in the current checkout"); |
| 308 | } |
| 309 | if( !forceFlag |
| 310 | && db_exists("SELECT 1 FROM %s.sqlite_master WHERE name='stash'", |
| 311 | db_name("localdb")) |
| 312 | && db_exists("SELECT 1 FROM %s.stash", db_name("localdb")) |
| 313 | ){ |
| 314 | fossil_fatal("closing the checkout will delete your stash"); |
| 315 | } |
| 316 | if( db_is_writeable("repository") ){ |
| 317 |
| --- src/checkout.c | |
| +++ src/checkout.c | |
| @@ -305,12 +305,11 @@ | |
| 305 | |
| 306 | if( !forceFlag && unsaved_changes(0) ){ |
| 307 | fossil_fatal("there are unsaved changes in the current checkout"); |
| 308 | } |
| 309 | if( !forceFlag |
| 310 | && db_table_exists("localdb","stash") |
| 311 | && db_exists("SELECT 1 FROM %s.stash", db_name("localdb")) |
| 312 | ){ |
| 313 | fossil_fatal("closing the checkout will delete your stash"); |
| 314 | } |
| 315 | if( db_is_writeable("repository") ){ |
| 316 |
+7
-4
| --- src/clone.c | ||
| +++ src/clone.c | ||
| @@ -110,23 +110,26 @@ | ||
| 110 | 110 | ** --once Don't save url. |
| 111 | 111 | ** --private Also clone private branches |
| 112 | 112 | ** --ssl-identity=filename Use the SSL identity if requested by the server |
| 113 | 113 | ** --ssh-command|-c 'command' Use this SSH command |
| 114 | 114 | ** --httpauth|-B 'user:pass' Add HTTP Basic Authorization to requests |
| 115 | +** --verbose Show more statistics in output | |
| 115 | 116 | ** |
| 116 | 117 | ** See also: init |
| 117 | 118 | */ |
| 118 | 119 | void clone_cmd(void){ |
| 119 | 120 | char *zPassword; |
| 120 | 121 | const char *zDefaultUser; /* Optional name of the default user */ |
| 121 | 122 | const char *zHttpAuth; /* HTTP Authorization user:pass information */ |
| 122 | 123 | int nErr = 0; |
| 123 | - int bPrivate = 0; /* Also clone private branches */ | |
| 124 | 124 | int urlFlags = URL_PROMPT_PW | URL_REMEMBER; |
| 125 | + int syncFlags = SYNC_CLONE; | |
| 125 | 126 | |
| 126 | - if( find_option("private",0,0)!=0 ) bPrivate = SYNC_PRIVATE; | |
| 127 | + /* Also clone private branches */ | |
| 128 | + if( find_option("private",0,0)!=0 ) syncFlags |= SYNC_PRIVATE; | |
| 127 | 129 | if( find_option("once",0,0)!=0) urlFlags &= ~URL_REMEMBER; |
| 130 | + if( find_option("verbose",0,0)!=0) syncFlags |= SYNC_VERBOSE; | |
| 128 | 131 | zHttpAuth = find_option("httpauth","B",1); |
| 129 | 132 | zDefaultUser = find_option("admin-user","A",1); |
| 130 | 133 | clone_ssh_find_options(); |
| 131 | 134 | url_proxy_options(); |
| 132 | 135 | |
| @@ -147,11 +150,11 @@ | ||
| 147 | 150 | file_copy(g.url.name, g.argv[3]); |
| 148 | 151 | db_close(1); |
| 149 | 152 | db_open_repository(g.argv[3]); |
| 150 | 153 | db_record_repository_filename(g.argv[3]); |
| 151 | 154 | url_remember(); |
| 152 | - if( !bPrivate ) delete_private_content(); | |
| 155 | + if( !(syncFlags & SYNC_PRIVATE) ) delete_private_content(); | |
| 153 | 156 | shun_artifacts(); |
| 154 | 157 | db_create_default_users(1, zDefaultUser); |
| 155 | 158 | if( zDefaultUser ){ |
| 156 | 159 | g.zLogin = zDefaultUser; |
| 157 | 160 | }else{ |
| @@ -184,11 +187,11 @@ | ||
| 184 | 187 | ); |
| 185 | 188 | url_enable_proxy(0); |
| 186 | 189 | clone_ssh_db_set_options(); |
| 187 | 190 | url_get_password_if_needed(); |
| 188 | 191 | g.xlinkClusterOnly = 1; |
| 189 | - nErr = client_sync(SYNC_CLONE | bPrivate,CONFIGSET_ALL,0); | |
| 192 | + nErr = client_sync(syncFlags,CONFIGSET_ALL,0); | |
| 190 | 193 | g.xlinkClusterOnly = 0; |
| 191 | 194 | verify_cancel(); |
| 192 | 195 | db_end_transaction(0); |
| 193 | 196 | db_close(1); |
| 194 | 197 | if( nErr ){ |
| 195 | 198 |
| --- src/clone.c | |
| +++ src/clone.c | |
| @@ -110,23 +110,26 @@ | |
| 110 | ** --once Don't save url. |
| 111 | ** --private Also clone private branches |
| 112 | ** --ssl-identity=filename Use the SSL identity if requested by the server |
| 113 | ** --ssh-command|-c 'command' Use this SSH command |
| 114 | ** --httpauth|-B 'user:pass' Add HTTP Basic Authorization to requests |
| 115 | ** |
| 116 | ** See also: init |
| 117 | */ |
| 118 | void clone_cmd(void){ |
| 119 | char *zPassword; |
| 120 | const char *zDefaultUser; /* Optional name of the default user */ |
| 121 | const char *zHttpAuth; /* HTTP Authorization user:pass information */ |
| 122 | int nErr = 0; |
| 123 | int bPrivate = 0; /* Also clone private branches */ |
| 124 | int urlFlags = URL_PROMPT_PW | URL_REMEMBER; |
| 125 | |
| 126 | if( find_option("private",0,0)!=0 ) bPrivate = SYNC_PRIVATE; |
| 127 | if( find_option("once",0,0)!=0) urlFlags &= ~URL_REMEMBER; |
| 128 | zHttpAuth = find_option("httpauth","B",1); |
| 129 | zDefaultUser = find_option("admin-user","A",1); |
| 130 | clone_ssh_find_options(); |
| 131 | url_proxy_options(); |
| 132 | |
| @@ -147,11 +150,11 @@ | |
| 147 | file_copy(g.url.name, g.argv[3]); |
| 148 | db_close(1); |
| 149 | db_open_repository(g.argv[3]); |
| 150 | db_record_repository_filename(g.argv[3]); |
| 151 | url_remember(); |
| 152 | if( !bPrivate ) delete_private_content(); |
| 153 | shun_artifacts(); |
| 154 | db_create_default_users(1, zDefaultUser); |
| 155 | if( zDefaultUser ){ |
| 156 | g.zLogin = zDefaultUser; |
| 157 | }else{ |
| @@ -184,11 +187,11 @@ | |
| 184 | ); |
| 185 | url_enable_proxy(0); |
| 186 | clone_ssh_db_set_options(); |
| 187 | url_get_password_if_needed(); |
| 188 | g.xlinkClusterOnly = 1; |
| 189 | nErr = client_sync(SYNC_CLONE | bPrivate,CONFIGSET_ALL,0); |
| 190 | g.xlinkClusterOnly = 0; |
| 191 | verify_cancel(); |
| 192 | db_end_transaction(0); |
| 193 | db_close(1); |
| 194 | if( nErr ){ |
| 195 |
| --- src/clone.c | |
| +++ src/clone.c | |
| @@ -110,23 +110,26 @@ | |
| 110 | ** --once Don't save url. |
| 111 | ** --private Also clone private branches |
| 112 | ** --ssl-identity=filename Use the SSL identity if requested by the server |
| 113 | ** --ssh-command|-c 'command' Use this SSH command |
| 114 | ** --httpauth|-B 'user:pass' Add HTTP Basic Authorization to requests |
| 115 | ** --verbose Show more statistics in output |
| 116 | ** |
| 117 | ** See also: init |
| 118 | */ |
| 119 | void clone_cmd(void){ |
| 120 | char *zPassword; |
| 121 | const char *zDefaultUser; /* Optional name of the default user */ |
| 122 | const char *zHttpAuth; /* HTTP Authorization user:pass information */ |
| 123 | int nErr = 0; |
| 124 | int urlFlags = URL_PROMPT_PW | URL_REMEMBER; |
| 125 | int syncFlags = SYNC_CLONE; |
| 126 | |
| 127 | /* Also clone private branches */ |
| 128 | if( find_option("private",0,0)!=0 ) syncFlags |= SYNC_PRIVATE; |
| 129 | if( find_option("once",0,0)!=0) urlFlags &= ~URL_REMEMBER; |
| 130 | if( find_option("verbose",0,0)!=0) syncFlags |= SYNC_VERBOSE; |
| 131 | zHttpAuth = find_option("httpauth","B",1); |
| 132 | zDefaultUser = find_option("admin-user","A",1); |
| 133 | clone_ssh_find_options(); |
| 134 | url_proxy_options(); |
| 135 | |
| @@ -147,11 +150,11 @@ | |
| 150 | file_copy(g.url.name, g.argv[3]); |
| 151 | db_close(1); |
| 152 | db_open_repository(g.argv[3]); |
| 153 | db_record_repository_filename(g.argv[3]); |
| 154 | url_remember(); |
| 155 | if( !(syncFlags & SYNC_PRIVATE) ) delete_private_content(); |
| 156 | shun_artifacts(); |
| 157 | db_create_default_users(1, zDefaultUser); |
| 158 | if( zDefaultUser ){ |
| 159 | g.zLogin = zDefaultUser; |
| 160 | }else{ |
| @@ -184,11 +187,11 @@ | |
| 187 | ); |
| 188 | url_enable_proxy(0); |
| 189 | clone_ssh_db_set_options(); |
| 190 | url_get_password_if_needed(); |
| 191 | g.xlinkClusterOnly = 1; |
| 192 | nErr = client_sync(syncFlags,CONFIGSET_ALL,0); |
| 193 | g.xlinkClusterOnly = 0; |
| 194 | verify_cancel(); |
| 195 | db_end_transaction(0); |
| 196 | db_close(1); |
| 197 | if( nErr ){ |
| 198 |
+4
-4
| --- src/content.c | ||
| +++ src/content.c | ||
| @@ -567,14 +567,14 @@ | ||
| 567 | 567 | db_exec(&s1); |
| 568 | 568 | rid = db_last_insert_rowid(); |
| 569 | 569 | if( !pBlob ){ |
| 570 | 570 | db_multi_exec("INSERT OR IGNORE INTO phantom VALUES(%d)", rid); |
| 571 | 571 | } |
| 572 | - if( g.markPrivate || isPrivate ){ | |
| 573 | - db_multi_exec("INSERT INTO private VALUES(%d)", rid); | |
| 574 | - markAsUnclustered = 0; | |
| 575 | - } | |
| 572 | + } | |
| 573 | + if( g.markPrivate || isPrivate ){ | |
| 574 | + db_multi_exec("INSERT INTO private VALUES(%d)", rid); | |
| 575 | + markAsUnclustered = 0; | |
| 576 | 576 | } |
| 577 | 577 | if( nBlob==0 ) blob_reset(&cmpr); |
| 578 | 578 | |
| 579 | 579 | /* If the srcId is specified, then the data we just added is |
| 580 | 580 | ** really a delta. Record this fact in the delta table. |
| 581 | 581 |
| --- src/content.c | |
| +++ src/content.c | |
| @@ -567,14 +567,14 @@ | |
| 567 | db_exec(&s1); |
| 568 | rid = db_last_insert_rowid(); |
| 569 | if( !pBlob ){ |
| 570 | db_multi_exec("INSERT OR IGNORE INTO phantom VALUES(%d)", rid); |
| 571 | } |
| 572 | if( g.markPrivate || isPrivate ){ |
| 573 | db_multi_exec("INSERT INTO private VALUES(%d)", rid); |
| 574 | markAsUnclustered = 0; |
| 575 | } |
| 576 | } |
| 577 | if( nBlob==0 ) blob_reset(&cmpr); |
| 578 | |
| 579 | /* If the srcId is specified, then the data we just added is |
| 580 | ** really a delta. Record this fact in the delta table. |
| 581 |
| --- src/content.c | |
| +++ src/content.c | |
| @@ -567,14 +567,14 @@ | |
| 567 | db_exec(&s1); |
| 568 | rid = db_last_insert_rowid(); |
| 569 | if( !pBlob ){ |
| 570 | db_multi_exec("INSERT OR IGNORE INTO phantom VALUES(%d)", rid); |
| 571 | } |
| 572 | } |
| 573 | if( g.markPrivate || isPrivate ){ |
| 574 | db_multi_exec("INSERT INTO private VALUES(%d)", rid); |
| 575 | markAsUnclustered = 0; |
| 576 | } |
| 577 | if( nBlob==0 ) blob_reset(&cmpr); |
| 578 | |
| 579 | /* If the srcId is specified, then the data we just added is |
| 580 | ** really a delta. Record this fact in the delta table. |
| 581 |
M
src/db.c
+73
-33
| --- src/db.c | ||
| +++ src/db.c | ||
| @@ -424,10 +424,13 @@ | ||
| 424 | 424 | |
| 425 | 425 | /* |
| 426 | 426 | ** Extract text, integer, or blob values from the N-th column of the |
| 427 | 427 | ** current row. |
| 428 | 428 | */ |
| 429 | +int db_column_type(Stmt *pStmt, int N){ | |
| 430 | + return sqlite3_column_type(pStmt->pStmt, N); | |
| 431 | +} | |
| 429 | 432 | int db_column_bytes(Stmt *pStmt, int N){ |
| 430 | 433 | return sqlite3_column_bytes(pStmt->pStmt, N); |
| 431 | 434 | } |
| 432 | 435 | int db_column_int(Stmt *pStmt, int N){ |
| 433 | 436 | return sqlite3_column_int(pStmt->pStmt, N); |
| @@ -486,10 +489,50 @@ | ||
| 486 | 489 | while( (rc = db_step(pStmt))==SQLITE_ROW ){} |
| 487 | 490 | rc = db_reset(pStmt); |
| 488 | 491 | db_check_result(rc); |
| 489 | 492 | return rc; |
| 490 | 493 | } |
| 494 | + | |
| 495 | +/* | |
| 496 | +** Print the output of one or more SQL queries on standard output. | |
| 497 | +** This routine is used for debugging purposes only. | |
| 498 | +*/ | |
| 499 | +int db_debug(const char *zSql, ...){ | |
| 500 | + Blob sql; | |
| 501 | + int rc = SQLITE_OK; | |
| 502 | + va_list ap; | |
| 503 | + const char *z, *zEnd; | |
| 504 | + sqlite3_stmt *pStmt; | |
| 505 | + blob_init(&sql, 0, 0); | |
| 506 | + va_start(ap, zSql); | |
| 507 | + blob_vappendf(&sql, zSql, ap); | |
| 508 | + va_end(ap); | |
| 509 | + z = blob_str(&sql); | |
| 510 | + while( rc==SQLITE_OK && z[0] ){ | |
| 511 | + pStmt = 0; | |
| 512 | + rc = sqlite3_prepare_v2(g.db, z, -1, &pStmt, &zEnd); | |
| 513 | + if( rc!=SQLITE_OK ) break; | |
| 514 | + if( pStmt ){ | |
| 515 | + int nRow = 0; | |
| 516 | + db.nPrepare++; | |
| 517 | + while( sqlite3_step(pStmt)==SQLITE_ROW ){ | |
| 518 | + int i, n; | |
| 519 | + if( nRow++ > 0 ) fossil_print("\n"); | |
| 520 | + n = sqlite3_column_count(pStmt); | |
| 521 | + for(i=0; i<n; i++){ | |
| 522 | + fossil_print("%s = %s\n", sqlite3_column_name(pStmt, i), | |
| 523 | + sqlite3_column_text(pStmt,i)); | |
| 524 | + } | |
| 525 | + } | |
| 526 | + rc = sqlite3_finalize(pStmt); | |
| 527 | + if( rc ) db_err("%s: {%.*s}", sqlite3_errmsg(g.db), (int)(zEnd-z), z); | |
| 528 | + } | |
| 529 | + z = zEnd; | |
| 530 | + } | |
| 531 | + blob_reset(&sql); | |
| 532 | + return rc; | |
| 533 | +} | |
| 491 | 534 | |
| 492 | 535 | /* |
| 493 | 536 | ** Execute multiple SQL statements. |
| 494 | 537 | */ |
| 495 | 538 | int db_multi_exec(const char *zSql, ...){ |
| @@ -722,11 +765,11 @@ | ||
| 722 | 765 | arg = (const char*)sqlite3_value_text(argv[0]); |
| 723 | 766 | if(!arg){ |
| 724 | 767 | sqlite3_result_error(context, "Expecting a STRING argument", -1); |
| 725 | 768 | }else{ |
| 726 | 769 | int rid; |
| 727 | - type = (2==argc) ? sqlite3_value_text(argv[1]) : 0; | |
| 770 | + type = (2==argc) ? (const char*)sqlite3_value_text(argv[1]) : 0; | |
| 728 | 771 | if(!type) type = "ci"; |
| 729 | 772 | rid = symbolic_name_to_rid( arg, type ); |
| 730 | 773 | if(rid<0){ |
| 731 | 774 | sqlite3_result_error(context, "Symbolic name is ambiguous.", -1); |
| 732 | 775 | }else if(0==rid){ |
| @@ -915,30 +958,47 @@ | ||
| 915 | 958 | g.zConfigDbType = "configdb"; |
| 916 | 959 | } |
| 917 | 960 | g.zConfigDbName = zDbName; |
| 918 | 961 | } |
| 919 | 962 | |
| 963 | +/* | |
| 964 | +** Return TRUE if zTable exists. | |
| 965 | +*/ | |
| 966 | +int db_table_exists( | |
| 967 | + const char *zDb, /* One of: NULL, "configdb", "localdb", "repository" */ | |
| 968 | + const char *zTable /* Name of table */ | |
| 969 | +){ | |
| 970 | + return sqlite3_table_column_metadata(g.db, | |
| 971 | + zDb ? db_name(zDb) : 0, zTable, 0, | |
| 972 | + 0, 0, 0, 0, 0)==SQLITE_OK; | |
| 973 | +} | |
| 974 | + | |
| 975 | +/* | |
| 976 | +** Return TRUE if zTable exists and contains column zColumn. | |
| 977 | +** Return FALSE if zTable does not exist or if zTable exists | |
| 978 | +** but lacks zColumn. | |
| 979 | +*/ | |
| 980 | +int db_table_has_column( | |
| 981 | + const char *zDb, /* One of: NULL, "config", "localdb", "repository" */ | |
| 982 | + const char *zTable, /* Name of table */ | |
| 983 | + const char *zColumn /* Name of column in table */ | |
| 984 | +){ | |
| 985 | + return sqlite3_table_column_metadata(g.db, | |
| 986 | + zDb ? db_name(zDb) : 0, zTable, zColumn, | |
| 987 | + 0, 0, 0, 0, 0)==SQLITE_OK; | |
| 988 | +} | |
| 920 | 989 | |
| 921 | 990 | /* |
| 922 | 991 | ** Returns TRUE if zTable exists in the local database but lacks column |
| 923 | 992 | ** zColumn |
| 924 | 993 | */ |
| 925 | 994 | static int db_local_table_exists_but_lacks_column( |
| 926 | 995 | const char *zTable, |
| 927 | 996 | const char *zColumn |
| 928 | 997 | ){ |
| 929 | - char *zDef = db_text(0, "SELECT sql FROM %s.sqlite_master" | |
| 930 | - " WHERE name==%Q /*scan*/", | |
| 931 | - db_name("localdb"), zTable); | |
| 932 | - int rc = 0; | |
| 933 | - if( zDef ){ | |
| 934 | - char *zPattern = mprintf("* %s *", zColumn); | |
| 935 | - rc = sqlite3_strglob(zPattern, zDef)!=0; | |
| 936 | - fossil_free(zPattern); | |
| 937 | - fossil_free(zDef); | |
| 938 | - } | |
| 939 | - return rc; | |
| 998 | + return db_table_exists(db_name("localdb"), zTable) | |
| 999 | + && !db_table_has_column(db_name("localdb"), zTable, zColumn); | |
| 940 | 1000 | } |
| 941 | 1001 | |
| 942 | 1002 | /* |
| 943 | 1003 | ** If zDbName is a valid local database file, open it and return |
| 944 | 1004 | ** true. If it is not a valid local database file, return 0. |
| @@ -1212,10 +1272,11 @@ | ||
| 1212 | 1272 | fossil_fatal("not in a local checkout"); |
| 1213 | 1273 | return; |
| 1214 | 1274 | } |
| 1215 | 1275 | db_open_or_attach(zRepo, "test_repo", 0); |
| 1216 | 1276 | db_lset("repository", blob_str(&repo)); |
| 1277 | + db_record_repository_filename(blob_str(&repo)); | |
| 1217 | 1278 | db_close(1); |
| 1218 | 1279 | } |
| 1219 | 1280 | |
| 1220 | 1281 | |
| 1221 | 1282 | /* |
| @@ -2004,31 +2065,10 @@ | ||
| 2004 | 2065 | } |
| 2005 | 2066 | void db_lset_int(const char *zName, int value){ |
| 2006 | 2067 | db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%d)", zName, value); |
| 2007 | 2068 | } |
| 2008 | 2069 | |
| 2009 | -/* | |
| 2010 | -** Returns non-0 if the database (which must be open) table identified | |
| 2011 | -** by zTableName has a column named zColName (case-sensitive), else | |
| 2012 | -** returns 0. | |
| 2013 | -*/ | |
| 2014 | -int db_table_has_column(const char *zTableName, const char *zColName){ | |
| 2015 | - Stmt q = empty_Stmt; | |
| 2016 | - int rc = 0; | |
| 2017 | - db_prepare( &q, "PRAGMA table_info(%Q)", zTableName ); | |
| 2018 | - while(SQLITE_ROW == db_step(&q)){ | |
| 2019 | - /* Columns: (cid, name, type, notnull, dflt_value, pk) */ | |
| 2020 | - const char *zCol = db_column_text(&q, 1); | |
| 2021 | - if( 0==fossil_strcmp(zColName, zCol) ){ | |
| 2022 | - rc = 1; | |
| 2023 | - break; | |
| 2024 | - } | |
| 2025 | - } | |
| 2026 | - db_finalize(&q); | |
| 2027 | - return rc; | |
| 2028 | -} | |
| 2029 | - | |
| 2030 | 2070 | /* |
| 2031 | 2071 | ** Record the name of a local repository in the global_config() database. |
| 2032 | 2072 | ** The repository filename %s is recorded as an entry with a "name" field |
| 2033 | 2073 | ** of the following form: |
| 2034 | 2074 | ** |
| 2035 | 2075 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -424,10 +424,13 @@ | |
| 424 | |
| 425 | /* |
| 426 | ** Extract text, integer, or blob values from the N-th column of the |
| 427 | ** current row. |
| 428 | */ |
| 429 | int db_column_bytes(Stmt *pStmt, int N){ |
| 430 | return sqlite3_column_bytes(pStmt->pStmt, N); |
| 431 | } |
| 432 | int db_column_int(Stmt *pStmt, int N){ |
| 433 | return sqlite3_column_int(pStmt->pStmt, N); |
| @@ -486,10 +489,50 @@ | |
| 486 | while( (rc = db_step(pStmt))==SQLITE_ROW ){} |
| 487 | rc = db_reset(pStmt); |
| 488 | db_check_result(rc); |
| 489 | return rc; |
| 490 | } |
| 491 | |
| 492 | /* |
| 493 | ** Execute multiple SQL statements. |
| 494 | */ |
| 495 | int db_multi_exec(const char *zSql, ...){ |
| @@ -722,11 +765,11 @@ | |
| 722 | arg = (const char*)sqlite3_value_text(argv[0]); |
| 723 | if(!arg){ |
| 724 | sqlite3_result_error(context, "Expecting a STRING argument", -1); |
| 725 | }else{ |
| 726 | int rid; |
| 727 | type = (2==argc) ? sqlite3_value_text(argv[1]) : 0; |
| 728 | if(!type) type = "ci"; |
| 729 | rid = symbolic_name_to_rid( arg, type ); |
| 730 | if(rid<0){ |
| 731 | sqlite3_result_error(context, "Symbolic name is ambiguous.", -1); |
| 732 | }else if(0==rid){ |
| @@ -915,30 +958,47 @@ | |
| 915 | g.zConfigDbType = "configdb"; |
| 916 | } |
| 917 | g.zConfigDbName = zDbName; |
| 918 | } |
| 919 | |
| 920 | |
| 921 | /* |
| 922 | ** Returns TRUE if zTable exists in the local database but lacks column |
| 923 | ** zColumn |
| 924 | */ |
| 925 | static int db_local_table_exists_but_lacks_column( |
| 926 | const char *zTable, |
| 927 | const char *zColumn |
| 928 | ){ |
| 929 | char *zDef = db_text(0, "SELECT sql FROM %s.sqlite_master" |
| 930 | " WHERE name==%Q /*scan*/", |
| 931 | db_name("localdb"), zTable); |
| 932 | int rc = 0; |
| 933 | if( zDef ){ |
| 934 | char *zPattern = mprintf("* %s *", zColumn); |
| 935 | rc = sqlite3_strglob(zPattern, zDef)!=0; |
| 936 | fossil_free(zPattern); |
| 937 | fossil_free(zDef); |
| 938 | } |
| 939 | return rc; |
| 940 | } |
| 941 | |
| 942 | /* |
| 943 | ** If zDbName is a valid local database file, open it and return |
| 944 | ** true. If it is not a valid local database file, return 0. |
| @@ -1212,10 +1272,11 @@ | |
| 1212 | fossil_fatal("not in a local checkout"); |
| 1213 | return; |
| 1214 | } |
| 1215 | db_open_or_attach(zRepo, "test_repo", 0); |
| 1216 | db_lset("repository", blob_str(&repo)); |
| 1217 | db_close(1); |
| 1218 | } |
| 1219 | |
| 1220 | |
| 1221 | /* |
| @@ -2004,31 +2065,10 @@ | |
| 2004 | } |
| 2005 | void db_lset_int(const char *zName, int value){ |
| 2006 | db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%d)", zName, value); |
| 2007 | } |
| 2008 | |
| 2009 | /* |
| 2010 | ** Returns non-0 if the database (which must be open) table identified |
| 2011 | ** by zTableName has a column named zColName (case-sensitive), else |
| 2012 | ** returns 0. |
| 2013 | */ |
| 2014 | int db_table_has_column(const char *zTableName, const char *zColName){ |
| 2015 | Stmt q = empty_Stmt; |
| 2016 | int rc = 0; |
| 2017 | db_prepare( &q, "PRAGMA table_info(%Q)", zTableName ); |
| 2018 | while(SQLITE_ROW == db_step(&q)){ |
| 2019 | /* Columns: (cid, name, type, notnull, dflt_value, pk) */ |
| 2020 | const char *zCol = db_column_text(&q, 1); |
| 2021 | if( 0==fossil_strcmp(zColName, zCol) ){ |
| 2022 | rc = 1; |
| 2023 | break; |
| 2024 | } |
| 2025 | } |
| 2026 | db_finalize(&q); |
| 2027 | return rc; |
| 2028 | } |
| 2029 | |
| 2030 | /* |
| 2031 | ** Record the name of a local repository in the global_config() database. |
| 2032 | ** The repository filename %s is recorded as an entry with a "name" field |
| 2033 | ** of the following form: |
| 2034 | ** |
| 2035 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -424,10 +424,13 @@ | |
| 424 | |
| 425 | /* |
| 426 | ** Extract text, integer, or blob values from the N-th column of the |
| 427 | ** current row. |
| 428 | */ |
| 429 | int db_column_type(Stmt *pStmt, int N){ |
| 430 | return sqlite3_column_type(pStmt->pStmt, N); |
| 431 | } |
| 432 | int db_column_bytes(Stmt *pStmt, int N){ |
| 433 | return sqlite3_column_bytes(pStmt->pStmt, N); |
| 434 | } |
| 435 | int db_column_int(Stmt *pStmt, int N){ |
| 436 | return sqlite3_column_int(pStmt->pStmt, N); |
| @@ -486,10 +489,50 @@ | |
| 489 | while( (rc = db_step(pStmt))==SQLITE_ROW ){} |
| 490 | rc = db_reset(pStmt); |
| 491 | db_check_result(rc); |
| 492 | return rc; |
| 493 | } |
| 494 | |
| 495 | /* |
| 496 | ** Print the output of one or more SQL queries on standard output. |
| 497 | ** This routine is used for debugging purposes only. |
| 498 | */ |
| 499 | int db_debug(const char *zSql, ...){ |
| 500 | Blob sql; |
| 501 | int rc = SQLITE_OK; |
| 502 | va_list ap; |
| 503 | const char *z, *zEnd; |
| 504 | sqlite3_stmt *pStmt; |
| 505 | blob_init(&sql, 0, 0); |
| 506 | va_start(ap, zSql); |
| 507 | blob_vappendf(&sql, zSql, ap); |
| 508 | va_end(ap); |
| 509 | z = blob_str(&sql); |
| 510 | while( rc==SQLITE_OK && z[0] ){ |
| 511 | pStmt = 0; |
| 512 | rc = sqlite3_prepare_v2(g.db, z, -1, &pStmt, &zEnd); |
| 513 | if( rc!=SQLITE_OK ) break; |
| 514 | if( pStmt ){ |
| 515 | int nRow = 0; |
| 516 | db.nPrepare++; |
| 517 | while( sqlite3_step(pStmt)==SQLITE_ROW ){ |
| 518 | int i, n; |
| 519 | if( nRow++ > 0 ) fossil_print("\n"); |
| 520 | n = sqlite3_column_count(pStmt); |
| 521 | for(i=0; i<n; i++){ |
| 522 | fossil_print("%s = %s\n", sqlite3_column_name(pStmt, i), |
| 523 | sqlite3_column_text(pStmt,i)); |
| 524 | } |
| 525 | } |
| 526 | rc = sqlite3_finalize(pStmt); |
| 527 | if( rc ) db_err("%s: {%.*s}", sqlite3_errmsg(g.db), (int)(zEnd-z), z); |
| 528 | } |
| 529 | z = zEnd; |
| 530 | } |
| 531 | blob_reset(&sql); |
| 532 | return rc; |
| 533 | } |
| 534 | |
| 535 | /* |
| 536 | ** Execute multiple SQL statements. |
| 537 | */ |
| 538 | int db_multi_exec(const char *zSql, ...){ |
| @@ -722,11 +765,11 @@ | |
| 765 | arg = (const char*)sqlite3_value_text(argv[0]); |
| 766 | if(!arg){ |
| 767 | sqlite3_result_error(context, "Expecting a STRING argument", -1); |
| 768 | }else{ |
| 769 | int rid; |
| 770 | type = (2==argc) ? (const char*)sqlite3_value_text(argv[1]) : 0; |
| 771 | if(!type) type = "ci"; |
| 772 | rid = symbolic_name_to_rid( arg, type ); |
| 773 | if(rid<0){ |
| 774 | sqlite3_result_error(context, "Symbolic name is ambiguous.", -1); |
| 775 | }else if(0==rid){ |
| @@ -915,30 +958,47 @@ | |
| 958 | g.zConfigDbType = "configdb"; |
| 959 | } |
| 960 | g.zConfigDbName = zDbName; |
| 961 | } |
| 962 | |
| 963 | /* |
| 964 | ** Return TRUE if zTable exists. |
| 965 | */ |
| 966 | int db_table_exists( |
| 967 | const char *zDb, /* One of: NULL, "configdb", "localdb", "repository" */ |
| 968 | const char *zTable /* Name of table */ |
| 969 | ){ |
| 970 | return sqlite3_table_column_metadata(g.db, |
| 971 | zDb ? db_name(zDb) : 0, zTable, 0, |
| 972 | 0, 0, 0, 0, 0)==SQLITE_OK; |
| 973 | } |
| 974 | |
| 975 | /* |
| 976 | ** Return TRUE if zTable exists and contains column zColumn. |
| 977 | ** Return FALSE if zTable does not exist or if zTable exists |
| 978 | ** but lacks zColumn. |
| 979 | */ |
| 980 | int db_table_has_column( |
| 981 | const char *zDb, /* One of: NULL, "config", "localdb", "repository" */ |
| 982 | const char *zTable, /* Name of table */ |
| 983 | const char *zColumn /* Name of column in table */ |
| 984 | ){ |
| 985 | return sqlite3_table_column_metadata(g.db, |
| 986 | zDb ? db_name(zDb) : 0, zTable, zColumn, |
| 987 | 0, 0, 0, 0, 0)==SQLITE_OK; |
| 988 | } |
| 989 | |
| 990 | /* |
| 991 | ** Returns TRUE if zTable exists in the local database but lacks column |
| 992 | ** zColumn |
| 993 | */ |
| 994 | static int db_local_table_exists_but_lacks_column( |
| 995 | const char *zTable, |
| 996 | const char *zColumn |
| 997 | ){ |
| 998 | return db_table_exists(db_name("localdb"), zTable) |
| 999 | && !db_table_has_column(db_name("localdb"), zTable, zColumn); |
| 1000 | } |
| 1001 | |
| 1002 | /* |
| 1003 | ** If zDbName is a valid local database file, open it and return |
| 1004 | ** true. If it is not a valid local database file, return 0. |
| @@ -1212,10 +1272,11 @@ | |
| 1272 | fossil_fatal("not in a local checkout"); |
| 1273 | return; |
| 1274 | } |
| 1275 | db_open_or_attach(zRepo, "test_repo", 0); |
| 1276 | db_lset("repository", blob_str(&repo)); |
| 1277 | db_record_repository_filename(blob_str(&repo)); |
| 1278 | db_close(1); |
| 1279 | } |
| 1280 | |
| 1281 | |
| 1282 | /* |
| @@ -2004,31 +2065,10 @@ | |
| 2065 | } |
| 2066 | void db_lset_int(const char *zName, int value){ |
| 2067 | db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%d)", zName, value); |
| 2068 | } |
| 2069 | |
| 2070 | /* |
| 2071 | ** Record the name of a local repository in the global_config() database. |
| 2072 | ** The repository filename %s is recorded as an entry with a "name" field |
| 2073 | ** of the following form: |
| 2074 | ** |
| 2075 |
M
src/db.c
+73
-33
| --- src/db.c | ||
| +++ src/db.c | ||
| @@ -424,10 +424,13 @@ | ||
| 424 | 424 | |
| 425 | 425 | /* |
| 426 | 426 | ** Extract text, integer, or blob values from the N-th column of the |
| 427 | 427 | ** current row. |
| 428 | 428 | */ |
| 429 | +int db_column_type(Stmt *pStmt, int N){ | |
| 430 | + return sqlite3_column_type(pStmt->pStmt, N); | |
| 431 | +} | |
| 429 | 432 | int db_column_bytes(Stmt *pStmt, int N){ |
| 430 | 433 | return sqlite3_column_bytes(pStmt->pStmt, N); |
| 431 | 434 | } |
| 432 | 435 | int db_column_int(Stmt *pStmt, int N){ |
| 433 | 436 | return sqlite3_column_int(pStmt->pStmt, N); |
| @@ -486,10 +489,50 @@ | ||
| 486 | 489 | while( (rc = db_step(pStmt))==SQLITE_ROW ){} |
| 487 | 490 | rc = db_reset(pStmt); |
| 488 | 491 | db_check_result(rc); |
| 489 | 492 | return rc; |
| 490 | 493 | } |
| 494 | + | |
| 495 | +/* | |
| 496 | +** Print the output of one or more SQL queries on standard output. | |
| 497 | +** This routine is used for debugging purposes only. | |
| 498 | +*/ | |
| 499 | +int db_debug(const char *zSql, ...){ | |
| 500 | + Blob sql; | |
| 501 | + int rc = SQLITE_OK; | |
| 502 | + va_list ap; | |
| 503 | + const char *z, *zEnd; | |
| 504 | + sqlite3_stmt *pStmt; | |
| 505 | + blob_init(&sql, 0, 0); | |
| 506 | + va_start(ap, zSql); | |
| 507 | + blob_vappendf(&sql, zSql, ap); | |
| 508 | + va_end(ap); | |
| 509 | + z = blob_str(&sql); | |
| 510 | + while( rc==SQLITE_OK && z[0] ){ | |
| 511 | + pStmt = 0; | |
| 512 | + rc = sqlite3_prepare_v2(g.db, z, -1, &pStmt, &zEnd); | |
| 513 | + if( rc!=SQLITE_OK ) break; | |
| 514 | + if( pStmt ){ | |
| 515 | + int nRow = 0; | |
| 516 | + db.nPrepare++; | |
| 517 | + while( sqlite3_step(pStmt)==SQLITE_ROW ){ | |
| 518 | + int i, n; | |
| 519 | + if( nRow++ > 0 ) fossil_print("\n"); | |
| 520 | + n = sqlite3_column_count(pStmt); | |
| 521 | + for(i=0; i<n; i++){ | |
| 522 | + fossil_print("%s = %s\n", sqlite3_column_name(pStmt, i), | |
| 523 | + sqlite3_column_text(pStmt,i)); | |
| 524 | + } | |
| 525 | + } | |
| 526 | + rc = sqlite3_finalize(pStmt); | |
| 527 | + if( rc ) db_err("%s: {%.*s}", sqlite3_errmsg(g.db), (int)(zEnd-z), z); | |
| 528 | + } | |
| 529 | + z = zEnd; | |
| 530 | + } | |
| 531 | + blob_reset(&sql); | |
| 532 | + return rc; | |
| 533 | +} | |
| 491 | 534 | |
| 492 | 535 | /* |
| 493 | 536 | ** Execute multiple SQL statements. |
| 494 | 537 | */ |
| 495 | 538 | int db_multi_exec(const char *zSql, ...){ |
| @@ -722,11 +765,11 @@ | ||
| 722 | 765 | arg = (const char*)sqlite3_value_text(argv[0]); |
| 723 | 766 | if(!arg){ |
| 724 | 767 | sqlite3_result_error(context, "Expecting a STRING argument", -1); |
| 725 | 768 | }else{ |
| 726 | 769 | int rid; |
| 727 | - type = (2==argc) ? sqlite3_value_text(argv[1]) : 0; | |
| 770 | + type = (2==argc) ? (const char*)sqlite3_value_text(argv[1]) : 0; | |
| 728 | 771 | if(!type) type = "ci"; |
| 729 | 772 | rid = symbolic_name_to_rid( arg, type ); |
| 730 | 773 | if(rid<0){ |
| 731 | 774 | sqlite3_result_error(context, "Symbolic name is ambiguous.", -1); |
| 732 | 775 | }else if(0==rid){ |
| @@ -915,30 +958,47 @@ | ||
| 915 | 958 | g.zConfigDbType = "configdb"; |
| 916 | 959 | } |
| 917 | 960 | g.zConfigDbName = zDbName; |
| 918 | 961 | } |
| 919 | 962 | |
| 963 | +/* | |
| 964 | +** Return TRUE if zTable exists. | |
| 965 | +*/ | |
| 966 | +int db_table_exists( | |
| 967 | + const char *zDb, /* One of: NULL, "configdb", "localdb", "repository" */ | |
| 968 | + const char *zTable /* Name of table */ | |
| 969 | +){ | |
| 970 | + return sqlite3_table_column_metadata(g.db, | |
| 971 | + zDb ? db_name(zDb) : 0, zTable, 0, | |
| 972 | + 0, 0, 0, 0, 0)==SQLITE_OK; | |
| 973 | +} | |
| 974 | + | |
| 975 | +/* | |
| 976 | +** Return TRUE if zTable exists and contains column zColumn. | |
| 977 | +** Return FALSE if zTable does not exist or if zTable exists | |
| 978 | +** but lacks zColumn. | |
| 979 | +*/ | |
| 980 | +int db_table_has_column( | |
| 981 | + const char *zDb, /* One of: NULL, "config", "localdb", "repository" */ | |
| 982 | + const char *zTable, /* Name of table */ | |
| 983 | + const char *zColumn /* Name of column in table */ | |
| 984 | +){ | |
| 985 | + return sqlite3_table_column_metadata(g.db, | |
| 986 | + zDb ? db_name(zDb) : 0, zTable, zColumn, | |
| 987 | + 0, 0, 0, 0, 0)==SQLITE_OK; | |
| 988 | +} | |
| 920 | 989 | |
| 921 | 990 | /* |
| 922 | 991 | ** Returns TRUE if zTable exists in the local database but lacks column |
| 923 | 992 | ** zColumn |
| 924 | 993 | */ |
| 925 | 994 | static int db_local_table_exists_but_lacks_column( |
| 926 | 995 | const char *zTable, |
| 927 | 996 | const char *zColumn |
| 928 | 997 | ){ |
| 929 | - char *zDef = db_text(0, "SELECT sql FROM %s.sqlite_master" | |
| 930 | - " WHERE name==%Q /*scan*/", | |
| 931 | - db_name("localdb"), zTable); | |
| 932 | - int rc = 0; | |
| 933 | - if( zDef ){ | |
| 934 | - char *zPattern = mprintf("* %s *", zColumn); | |
| 935 | - rc = sqlite3_strglob(zPattern, zDef)!=0; | |
| 936 | - fossil_free(zPattern); | |
| 937 | - fossil_free(zDef); | |
| 938 | - } | |
| 939 | - return rc; | |
| 998 | + return db_table_exists(db_name("localdb"), zTable) | |
| 999 | + && !db_table_has_column(db_name("localdb"), zTable, zColumn); | |
| 940 | 1000 | } |
| 941 | 1001 | |
| 942 | 1002 | /* |
| 943 | 1003 | ** If zDbName is a valid local database file, open it and return |
| 944 | 1004 | ** true. If it is not a valid local database file, return 0. |
| @@ -1212,10 +1272,11 @@ | ||
| 1212 | 1272 | fossil_fatal("not in a local checkout"); |
| 1213 | 1273 | return; |
| 1214 | 1274 | } |
| 1215 | 1275 | db_open_or_attach(zRepo, "test_repo", 0); |
| 1216 | 1276 | db_lset("repository", blob_str(&repo)); |
| 1277 | + db_record_repository_filename(blob_str(&repo)); | |
| 1217 | 1278 | db_close(1); |
| 1218 | 1279 | } |
| 1219 | 1280 | |
| 1220 | 1281 | |
| 1221 | 1282 | /* |
| @@ -2004,31 +2065,10 @@ | ||
| 2004 | 2065 | } |
| 2005 | 2066 | void db_lset_int(const char *zName, int value){ |
| 2006 | 2067 | db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%d)", zName, value); |
| 2007 | 2068 | } |
| 2008 | 2069 | |
| 2009 | -/* | |
| 2010 | -** Returns non-0 if the database (which must be open) table identified | |
| 2011 | -** by zTableName has a column named zColName (case-sensitive), else | |
| 2012 | -** returns 0. | |
| 2013 | -*/ | |
| 2014 | -int db_table_has_column(const char *zTableName, const char *zColName){ | |
| 2015 | - Stmt q = empty_Stmt; | |
| 2016 | - int rc = 0; | |
| 2017 | - db_prepare( &q, "PRAGMA table_info(%Q)", zTableName ); | |
| 2018 | - while(SQLITE_ROW == db_step(&q)){ | |
| 2019 | - /* Columns: (cid, name, type, notnull, dflt_value, pk) */ | |
| 2020 | - const char *zCol = db_column_text(&q, 1); | |
| 2021 | - if( 0==fossil_strcmp(zColName, zCol) ){ | |
| 2022 | - rc = 1; | |
| 2023 | - break; | |
| 2024 | - } | |
| 2025 | - } | |
| 2026 | - db_finalize(&q); | |
| 2027 | - return rc; | |
| 2028 | -} | |
| 2029 | - | |
| 2030 | 2070 | /* |
| 2031 | 2071 | ** Record the name of a local repository in the global_config() database. |
| 2032 | 2072 | ** The repository filename %s is recorded as an entry with a "name" field |
| 2033 | 2073 | ** of the following form: |
| 2034 | 2074 | ** |
| 2035 | 2075 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -424,10 +424,13 @@ | |
| 424 | |
| 425 | /* |
| 426 | ** Extract text, integer, or blob values from the N-th column of the |
| 427 | ** current row. |
| 428 | */ |
| 429 | int db_column_bytes(Stmt *pStmt, int N){ |
| 430 | return sqlite3_column_bytes(pStmt->pStmt, N); |
| 431 | } |
| 432 | int db_column_int(Stmt *pStmt, int N){ |
| 433 | return sqlite3_column_int(pStmt->pStmt, N); |
| @@ -486,10 +489,50 @@ | |
| 486 | while( (rc = db_step(pStmt))==SQLITE_ROW ){} |
| 487 | rc = db_reset(pStmt); |
| 488 | db_check_result(rc); |
| 489 | return rc; |
| 490 | } |
| 491 | |
| 492 | /* |
| 493 | ** Execute multiple SQL statements. |
| 494 | */ |
| 495 | int db_multi_exec(const char *zSql, ...){ |
| @@ -722,11 +765,11 @@ | |
| 722 | arg = (const char*)sqlite3_value_text(argv[0]); |
| 723 | if(!arg){ |
| 724 | sqlite3_result_error(context, "Expecting a STRING argument", -1); |
| 725 | }else{ |
| 726 | int rid; |
| 727 | type = (2==argc) ? sqlite3_value_text(argv[1]) : 0; |
| 728 | if(!type) type = "ci"; |
| 729 | rid = symbolic_name_to_rid( arg, type ); |
| 730 | if(rid<0){ |
| 731 | sqlite3_result_error(context, "Symbolic name is ambiguous.", -1); |
| 732 | }else if(0==rid){ |
| @@ -915,30 +958,47 @@ | |
| 915 | g.zConfigDbType = "configdb"; |
| 916 | } |
| 917 | g.zConfigDbName = zDbName; |
| 918 | } |
| 919 | |
| 920 | |
| 921 | /* |
| 922 | ** Returns TRUE if zTable exists in the local database but lacks column |
| 923 | ** zColumn |
| 924 | */ |
| 925 | static int db_local_table_exists_but_lacks_column( |
| 926 | const char *zTable, |
| 927 | const char *zColumn |
| 928 | ){ |
| 929 | char *zDef = db_text(0, "SELECT sql FROM %s.sqlite_master" |
| 930 | " WHERE name==%Q /*scan*/", |
| 931 | db_name("localdb"), zTable); |
| 932 | int rc = 0; |
| 933 | if( zDef ){ |
| 934 | char *zPattern = mprintf("* %s *", zColumn); |
| 935 | rc = sqlite3_strglob(zPattern, zDef)!=0; |
| 936 | fossil_free(zPattern); |
| 937 | fossil_free(zDef); |
| 938 | } |
| 939 | return rc; |
| 940 | } |
| 941 | |
| 942 | /* |
| 943 | ** If zDbName is a valid local database file, open it and return |
| 944 | ** true. If it is not a valid local database file, return 0. |
| @@ -1212,10 +1272,11 @@ | |
| 1212 | fossil_fatal("not in a local checkout"); |
| 1213 | return; |
| 1214 | } |
| 1215 | db_open_or_attach(zRepo, "test_repo", 0); |
| 1216 | db_lset("repository", blob_str(&repo)); |
| 1217 | db_close(1); |
| 1218 | } |
| 1219 | |
| 1220 | |
| 1221 | /* |
| @@ -2004,31 +2065,10 @@ | |
| 2004 | } |
| 2005 | void db_lset_int(const char *zName, int value){ |
| 2006 | db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%d)", zName, value); |
| 2007 | } |
| 2008 | |
| 2009 | /* |
| 2010 | ** Returns non-0 if the database (which must be open) table identified |
| 2011 | ** by zTableName has a column named zColName (case-sensitive), else |
| 2012 | ** returns 0. |
| 2013 | */ |
| 2014 | int db_table_has_column(const char *zTableName, const char *zColName){ |
| 2015 | Stmt q = empty_Stmt; |
| 2016 | int rc = 0; |
| 2017 | db_prepare( &q, "PRAGMA table_info(%Q)", zTableName ); |
| 2018 | while(SQLITE_ROW == db_step(&q)){ |
| 2019 | /* Columns: (cid, name, type, notnull, dflt_value, pk) */ |
| 2020 | const char *zCol = db_column_text(&q, 1); |
| 2021 | if( 0==fossil_strcmp(zColName, zCol) ){ |
| 2022 | rc = 1; |
| 2023 | break; |
| 2024 | } |
| 2025 | } |
| 2026 | db_finalize(&q); |
| 2027 | return rc; |
| 2028 | } |
| 2029 | |
| 2030 | /* |
| 2031 | ** Record the name of a local repository in the global_config() database. |
| 2032 | ** The repository filename %s is recorded as an entry with a "name" field |
| 2033 | ** of the following form: |
| 2034 | ** |
| 2035 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -424,10 +424,13 @@ | |
| 424 | |
| 425 | /* |
| 426 | ** Extract text, integer, or blob values from the N-th column of the |
| 427 | ** current row. |
| 428 | */ |
| 429 | int db_column_type(Stmt *pStmt, int N){ |
| 430 | return sqlite3_column_type(pStmt->pStmt, N); |
| 431 | } |
| 432 | int db_column_bytes(Stmt *pStmt, int N){ |
| 433 | return sqlite3_column_bytes(pStmt->pStmt, N); |
| 434 | } |
| 435 | int db_column_int(Stmt *pStmt, int N){ |
| 436 | return sqlite3_column_int(pStmt->pStmt, N); |
| @@ -486,10 +489,50 @@ | |
| 489 | while( (rc = db_step(pStmt))==SQLITE_ROW ){} |
| 490 | rc = db_reset(pStmt); |
| 491 | db_check_result(rc); |
| 492 | return rc; |
| 493 | } |
| 494 | |
| 495 | /* |
| 496 | ** Print the output of one or more SQL queries on standard output. |
| 497 | ** This routine is used for debugging purposes only. |
| 498 | */ |
| 499 | int db_debug(const char *zSql, ...){ |
| 500 | Blob sql; |
| 501 | int rc = SQLITE_OK; |
| 502 | va_list ap; |
| 503 | const char *z, *zEnd; |
| 504 | sqlite3_stmt *pStmt; |
| 505 | blob_init(&sql, 0, 0); |
| 506 | va_start(ap, zSql); |
| 507 | blob_vappendf(&sql, zSql, ap); |
| 508 | va_end(ap); |
| 509 | z = blob_str(&sql); |
| 510 | while( rc==SQLITE_OK && z[0] ){ |
| 511 | pStmt = 0; |
| 512 | rc = sqlite3_prepare_v2(g.db, z, -1, &pStmt, &zEnd); |
| 513 | if( rc!=SQLITE_OK ) break; |
| 514 | if( pStmt ){ |
| 515 | int nRow = 0; |
| 516 | db.nPrepare++; |
| 517 | while( sqlite3_step(pStmt)==SQLITE_ROW ){ |
| 518 | int i, n; |
| 519 | if( nRow++ > 0 ) fossil_print("\n"); |
| 520 | n = sqlite3_column_count(pStmt); |
| 521 | for(i=0; i<n; i++){ |
| 522 | fossil_print("%s = %s\n", sqlite3_column_name(pStmt, i), |
| 523 | sqlite3_column_text(pStmt,i)); |
| 524 | } |
| 525 | } |
| 526 | rc = sqlite3_finalize(pStmt); |
| 527 | if( rc ) db_err("%s: {%.*s}", sqlite3_errmsg(g.db), (int)(zEnd-z), z); |
| 528 | } |
| 529 | z = zEnd; |
| 530 | } |
| 531 | blob_reset(&sql); |
| 532 | return rc; |
| 533 | } |
| 534 | |
| 535 | /* |
| 536 | ** Execute multiple SQL statements. |
| 537 | */ |
| 538 | int db_multi_exec(const char *zSql, ...){ |
| @@ -722,11 +765,11 @@ | |
| 765 | arg = (const char*)sqlite3_value_text(argv[0]); |
| 766 | if(!arg){ |
| 767 | sqlite3_result_error(context, "Expecting a STRING argument", -1); |
| 768 | }else{ |
| 769 | int rid; |
| 770 | type = (2==argc) ? (const char*)sqlite3_value_text(argv[1]) : 0; |
| 771 | if(!type) type = "ci"; |
| 772 | rid = symbolic_name_to_rid( arg, type ); |
| 773 | if(rid<0){ |
| 774 | sqlite3_result_error(context, "Symbolic name is ambiguous.", -1); |
| 775 | }else if(0==rid){ |
| @@ -915,30 +958,47 @@ | |
| 958 | g.zConfigDbType = "configdb"; |
| 959 | } |
| 960 | g.zConfigDbName = zDbName; |
| 961 | } |
| 962 | |
| 963 | /* |
| 964 | ** Return TRUE if zTable exists. |
| 965 | */ |
| 966 | int db_table_exists( |
| 967 | const char *zDb, /* One of: NULL, "configdb", "localdb", "repository" */ |
| 968 | const char *zTable /* Name of table */ |
| 969 | ){ |
| 970 | return sqlite3_table_column_metadata(g.db, |
| 971 | zDb ? db_name(zDb) : 0, zTable, 0, |
| 972 | 0, 0, 0, 0, 0)==SQLITE_OK; |
| 973 | } |
| 974 | |
| 975 | /* |
| 976 | ** Return TRUE if zTable exists and contains column zColumn. |
| 977 | ** Return FALSE if zTable does not exist or if zTable exists |
| 978 | ** but lacks zColumn. |
| 979 | */ |
| 980 | int db_table_has_column( |
| 981 | const char *zDb, /* One of: NULL, "config", "localdb", "repository" */ |
| 982 | const char *zTable, /* Name of table */ |
| 983 | const char *zColumn /* Name of column in table */ |
| 984 | ){ |
| 985 | return sqlite3_table_column_metadata(g.db, |
| 986 | zDb ? db_name(zDb) : 0, zTable, zColumn, |
| 987 | 0, 0, 0, 0, 0)==SQLITE_OK; |
| 988 | } |
| 989 | |
| 990 | /* |
| 991 | ** Returns TRUE if zTable exists in the local database but lacks column |
| 992 | ** zColumn |
| 993 | */ |
| 994 | static int db_local_table_exists_but_lacks_column( |
| 995 | const char *zTable, |
| 996 | const char *zColumn |
| 997 | ){ |
| 998 | return db_table_exists(db_name("localdb"), zTable) |
| 999 | && !db_table_has_column(db_name("localdb"), zTable, zColumn); |
| 1000 | } |
| 1001 | |
| 1002 | /* |
| 1003 | ** If zDbName is a valid local database file, open it and return |
| 1004 | ** true. If it is not a valid local database file, return 0. |
| @@ -1212,10 +1272,11 @@ | |
| 1272 | fossil_fatal("not in a local checkout"); |
| 1273 | return; |
| 1274 | } |
| 1275 | db_open_or_attach(zRepo, "test_repo", 0); |
| 1276 | db_lset("repository", blob_str(&repo)); |
| 1277 | db_record_repository_filename(blob_str(&repo)); |
| 1278 | db_close(1); |
| 1279 | } |
| 1280 | |
| 1281 | |
| 1282 | /* |
| @@ -2004,31 +2065,10 @@ | |
| 2065 | } |
| 2066 | void db_lset_int(const char *zName, int value){ |
| 2067 | db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%d)", zName, value); |
| 2068 | } |
| 2069 | |
| 2070 | /* |
| 2071 | ** Record the name of a local repository in the global_config() database. |
| 2072 | ** The repository filename %s is recorded as an entry with a "name" field |
| 2073 | ** of the following form: |
| 2074 | ** |
| 2075 |
+4
-4
| --- src/descendants.c | ||
| +++ src/descendants.c | ||
| @@ -289,14 +289,14 @@ | ||
| 289 | 289 | } |
| 290 | 290 | |
| 291 | 291 | /* |
| 292 | 292 | ** COMMAND: descendants* |
| 293 | 293 | ** |
| 294 | -** Usage: %fossil descendants ?BASELINE-ID? ?OPTIONS? | |
| 294 | +** Usage: %fossil descendants ?CHECKIN? ?OPTIONS? | |
| 295 | 295 | ** |
| 296 | -** Find all leaf descendants of the baseline specified or if the argument | |
| 297 | -** is omitted, of the baseline currently checked out. | |
| 296 | +** Find all leaf descendants of the checkin specified or if the argument | |
| 297 | +** is omitted, of the checkin currently checked out. | |
| 298 | 298 | ** |
| 299 | 299 | ** Options: |
| 300 | 300 | ** -R|--repository FILE Extract info from repository FILE |
| 301 | 301 | ** -W|--width <num> Width of lines (default is to auto-detect). |
| 302 | 302 | ** Must be >20 or 0 (= no limit, resulting in a |
| @@ -334,11 +334,11 @@ | ||
| 334 | 334 | "%s" |
| 335 | 335 | " AND event.objid IN (SELECT rid FROM leaves)" |
| 336 | 336 | " ORDER BY event.mtime DESC", |
| 337 | 337 | timeline_query_for_tty() |
| 338 | 338 | ); |
| 339 | - print_timeline(&q, -20, width, 0); | |
| 339 | + print_timeline(&q, 0, width, 0); | |
| 340 | 340 | db_finalize(&q); |
| 341 | 341 | } |
| 342 | 342 | |
| 343 | 343 | /* |
| 344 | 344 | ** COMMAND: leaves* |
| 345 | 345 |
| --- src/descendants.c | |
| +++ src/descendants.c | |
| @@ -289,14 +289,14 @@ | |
| 289 | } |
| 290 | |
| 291 | /* |
| 292 | ** COMMAND: descendants* |
| 293 | ** |
| 294 | ** Usage: %fossil descendants ?BASELINE-ID? ?OPTIONS? |
| 295 | ** |
| 296 | ** Find all leaf descendants of the baseline specified or if the argument |
| 297 | ** is omitted, of the baseline currently checked out. |
| 298 | ** |
| 299 | ** Options: |
| 300 | ** -R|--repository FILE Extract info from repository FILE |
| 301 | ** -W|--width <num> Width of lines (default is to auto-detect). |
| 302 | ** Must be >20 or 0 (= no limit, resulting in a |
| @@ -334,11 +334,11 @@ | |
| 334 | "%s" |
| 335 | " AND event.objid IN (SELECT rid FROM leaves)" |
| 336 | " ORDER BY event.mtime DESC", |
| 337 | timeline_query_for_tty() |
| 338 | ); |
| 339 | print_timeline(&q, -20, width, 0); |
| 340 | db_finalize(&q); |
| 341 | } |
| 342 | |
| 343 | /* |
| 344 | ** COMMAND: leaves* |
| 345 |
| --- src/descendants.c | |
| +++ src/descendants.c | |
| @@ -289,14 +289,14 @@ | |
| 289 | } |
| 290 | |
| 291 | /* |
| 292 | ** COMMAND: descendants* |
| 293 | ** |
| 294 | ** Usage: %fossil descendants ?CHECKIN? ?OPTIONS? |
| 295 | ** |
| 296 | ** Find all leaf descendants of the checkin specified or if the argument |
| 297 | ** is omitted, of the checkin currently checked out. |
| 298 | ** |
| 299 | ** Options: |
| 300 | ** -R|--repository FILE Extract info from repository FILE |
| 301 | ** -W|--width <num> Width of lines (default is to auto-detect). |
| 302 | ** Must be >20 or 0 (= no limit, resulting in a |
| @@ -334,11 +334,11 @@ | |
| 334 | "%s" |
| 335 | " AND event.objid IN (SELECT rid FROM leaves)" |
| 336 | " ORDER BY event.mtime DESC", |
| 337 | timeline_query_for_tty() |
| 338 | ); |
| 339 | print_timeline(&q, 0, width, 0); |
| 340 | db_finalize(&q); |
| 341 | } |
| 342 | |
| 343 | /* |
| 344 | ** COMMAND: leaves* |
| 345 |
+2
-2
| --- src/diffcmd.c | ||
| +++ src/diffcmd.c | ||
| @@ -363,20 +363,20 @@ | ||
| 363 | 363 | "SELECT pathname, 0, 0, 1, 0, islink" |
| 364 | 364 | " FROM vfile v2" |
| 365 | 365 | " WHERE v2.vid=%d" |
| 366 | 366 | " AND NOT EXISTS(SELECT 1 FROM vfile v1" |
| 367 | 367 | " WHERE v1.vid=%d AND v1.pathname=v2.pathname)" |
| 368 | - " ORDER BY 1", | |
| 368 | + " ORDER BY 1 /*scan*/", | |
| 369 | 369 | rid, vid, rid, vid, vid, rid |
| 370 | 370 | ); |
| 371 | 371 | }else{ |
| 372 | 372 | blob_append_sql(&sql, |
| 373 | 373 | "SELECT pathname, deleted, chnged , rid==0, rid, islink" |
| 374 | 374 | " FROM vfile" |
| 375 | 375 | " WHERE vid=%d" |
| 376 | 376 | " AND (deleted OR chnged OR rid==0)" |
| 377 | - " ORDER BY pathname", | |
| 377 | + " ORDER BY pathname /*scan*/", | |
| 378 | 378 | vid |
| 379 | 379 | ); |
| 380 | 380 | } |
| 381 | 381 | db_prepare(&q, "%s", blob_sql_text(&sql)); |
| 382 | 382 | while( db_step(&q)==SQLITE_ROW ){ |
| 383 | 383 |
| --- src/diffcmd.c | |
| +++ src/diffcmd.c | |
| @@ -363,20 +363,20 @@ | |
| 363 | "SELECT pathname, 0, 0, 1, 0, islink" |
| 364 | " FROM vfile v2" |
| 365 | " WHERE v2.vid=%d" |
| 366 | " AND NOT EXISTS(SELECT 1 FROM vfile v1" |
| 367 | " WHERE v1.vid=%d AND v1.pathname=v2.pathname)" |
| 368 | " ORDER BY 1", |
| 369 | rid, vid, rid, vid, vid, rid |
| 370 | ); |
| 371 | }else{ |
| 372 | blob_append_sql(&sql, |
| 373 | "SELECT pathname, deleted, chnged , rid==0, rid, islink" |
| 374 | " FROM vfile" |
| 375 | " WHERE vid=%d" |
| 376 | " AND (deleted OR chnged OR rid==0)" |
| 377 | " ORDER BY pathname", |
| 378 | vid |
| 379 | ); |
| 380 | } |
| 381 | db_prepare(&q, "%s", blob_sql_text(&sql)); |
| 382 | while( db_step(&q)==SQLITE_ROW ){ |
| 383 |
| --- src/diffcmd.c | |
| +++ src/diffcmd.c | |
| @@ -363,20 +363,20 @@ | |
| 363 | "SELECT pathname, 0, 0, 1, 0, islink" |
| 364 | " FROM vfile v2" |
| 365 | " WHERE v2.vid=%d" |
| 366 | " AND NOT EXISTS(SELECT 1 FROM vfile v1" |
| 367 | " WHERE v1.vid=%d AND v1.pathname=v2.pathname)" |
| 368 | " ORDER BY 1 /*scan*/", |
| 369 | rid, vid, rid, vid, vid, rid |
| 370 | ); |
| 371 | }else{ |
| 372 | blob_append_sql(&sql, |
| 373 | "SELECT pathname, deleted, chnged , rid==0, rid, islink" |
| 374 | " FROM vfile" |
| 375 | " WHERE vid=%d" |
| 376 | " AND (deleted OR chnged OR rid==0)" |
| 377 | " ORDER BY pathname /*scan*/", |
| 378 | vid |
| 379 | ); |
| 380 | } |
| 381 | db_prepare(&q, "%s", blob_sql_text(&sql)); |
| 382 | while( db_step(&q)==SQLITE_ROW ){ |
| 383 |
+1
| --- src/finfo.c | ||
| +++ src/finfo.c | ||
| @@ -495,10 +495,11 @@ | ||
| 495 | 495 | @ <br>fid=%d(frid) pid=%d(fpid) mid=%d(fmid) sz=%d(sz) |
| 496 | 496 | if( srcid ){ |
| 497 | 497 | @ srcid=%d(srcid) |
| 498 | 498 | } |
| 499 | 499 | } |
| 500 | + tag_private_status(frid); | |
| 500 | 501 | @ </td></tr> |
| 501 | 502 | } |
| 502 | 503 | db_finalize(&q); |
| 503 | 504 | if( pGraph ){ |
| 504 | 505 | graph_finish(pGraph, 0); |
| 505 | 506 |
| --- src/finfo.c | |
| +++ src/finfo.c | |
| @@ -495,10 +495,11 @@ | |
| 495 | @ <br>fid=%d(frid) pid=%d(fpid) mid=%d(fmid) sz=%d(sz) |
| 496 | if( srcid ){ |
| 497 | @ srcid=%d(srcid) |
| 498 | } |
| 499 | } |
| 500 | @ </td></tr> |
| 501 | } |
| 502 | db_finalize(&q); |
| 503 | if( pGraph ){ |
| 504 | graph_finish(pGraph, 0); |
| 505 |
| --- src/finfo.c | |
| +++ src/finfo.c | |
| @@ -495,10 +495,11 @@ | |
| 495 | @ <br>fid=%d(frid) pid=%d(fpid) mid=%d(fmid) sz=%d(sz) |
| 496 | if( srcid ){ |
| 497 | @ srcid=%d(srcid) |
| 498 | } |
| 499 | } |
| 500 | tag_private_status(frid); |
| 501 | @ </td></tr> |
| 502 | } |
| 503 | db_finalize(&q); |
| 504 | if( pGraph ){ |
| 505 | graph_finish(pGraph, 0); |
| 506 |
+10
-9
| --- src/foci.c | ||
| +++ src/foci.c | ||
| @@ -46,11 +46,12 @@ | ||
| 46 | 46 | sqlite3_vtab base; /* Base class - must be first */ |
| 47 | 47 | }; |
| 48 | 48 | struct FociCursor { |
| 49 | 49 | sqlite3_vtab_cursor base; /* Base class - must be first */ |
| 50 | 50 | Manifest *pMan; /* Current manifest */ |
| 51 | - int iFile; /* Index of current file */ | |
| 51 | + ManifestFile *pFile; /* Current file */ | |
| 52 | + int iFile; /* File index */ | |
| 52 | 53 | }; |
| 53 | 54 | #endif /* INTERFACE */ |
| 54 | 55 | |
| 55 | 56 | |
| 56 | 57 | /* |
| @@ -104,14 +105,11 @@ | ||
| 104 | 105 | |
| 105 | 106 | /* |
| 106 | 107 | ** Open a new focivfs cursor. |
| 107 | 108 | */ |
| 108 | 109 | static int fociOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ |
| 109 | - FociTable *pTab = (FociTable *)pVTab; | |
| 110 | 110 | FociCursor *pCsr; |
| 111 | - int rc; | |
| 112 | - | |
| 113 | 111 | pCsr = (FociCursor *)sqlite3_malloc(sizeof(FociCursor)); |
| 114 | 112 | memset(pCsr, 0, sizeof(FociCursor)); |
| 115 | 113 | pCsr->base.pVtab = pVTab; |
| 116 | 114 | *ppCursor = (sqlite3_vtab_cursor *)pCsr; |
| 117 | 115 | return SQLITE_OK; |
| @@ -130,17 +128,18 @@ | ||
| 130 | 128 | /* |
| 131 | 129 | ** Move a focivfs cursor to the next entry in the file. |
| 132 | 130 | */ |
| 133 | 131 | static int fociNext(sqlite3_vtab_cursor *pCursor){ |
| 134 | 132 | FociCursor *pCsr = (FociCursor *)pCursor; |
| 133 | + pCsr->pFile = manifest_file_next(pCsr->pMan, 0); | |
| 135 | 134 | pCsr->iFile++; |
| 136 | 135 | return SQLITE_OK; |
| 137 | 136 | } |
| 138 | 137 | |
| 139 | 138 | static int fociEof(sqlite3_vtab_cursor *pCursor){ |
| 140 | 139 | FociCursor *pCsr = (FociCursor *)pCursor; |
| 141 | - return pCsr->pMan==0 || pCsr->iFile>=pCsr->pMan->nFile; | |
| 140 | + return pCsr->pFile==0; | |
| 142 | 141 | } |
| 143 | 142 | |
| 144 | 143 | static int fociFilter( |
| 145 | 144 | sqlite3_vtab_cursor *pCursor, |
| 146 | 145 | int idxNum, const char *idxStr, |
| @@ -149,10 +148,12 @@ | ||
| 149 | 148 | FociCursor *pCur = (FociCursor *)pCursor; |
| 150 | 149 | manifest_destroy(pCur->pMan); |
| 151 | 150 | if( idxNum ){ |
| 152 | 151 | pCur->pMan = manifest_get(sqlite3_value_int(argv[0]), CFTYPE_MANIFEST, 0); |
| 153 | 152 | pCur->iFile = 0; |
| 153 | + manifest_file_rewind(pCur->pMan); | |
| 154 | + pCur->pFile = manifest_file_next(pCur->pMan, 0); | |
| 154 | 155 | }else{ |
| 155 | 156 | pCur->pMan = 0; |
| 156 | 157 | pCur->iFile = 0; |
| 157 | 158 | } |
| 158 | 159 | return SQLITE_OK; |
| @@ -167,23 +168,23 @@ | ||
| 167 | 168 | switch( i ){ |
| 168 | 169 | case 0: /* checkinID */ |
| 169 | 170 | sqlite3_result_int(ctx, pCsr->pMan->rid); |
| 170 | 171 | break; |
| 171 | 172 | case 1: /* filename */ |
| 172 | - sqlite3_result_text(ctx, pCsr->pMan->aFile[pCsr->iFile].zName, -1, | |
| 173 | + sqlite3_result_text(ctx, pCsr->pFile->zName, -1, | |
| 173 | 174 | SQLITE_TRANSIENT); |
| 174 | 175 | break; |
| 175 | 176 | case 2: /* uuid */ |
| 176 | - sqlite3_result_text(ctx, pCsr->pMan->aFile[pCsr->iFile].zUuid, -1, | |
| 177 | + sqlite3_result_text(ctx, pCsr->pFile->zUuid, -1, | |
| 177 | 178 | SQLITE_TRANSIENT); |
| 178 | 179 | break; |
| 179 | 180 | case 3: /* previousName */ |
| 180 | - sqlite3_result_text(ctx, pCsr->pMan->aFile[pCsr->iFile].zPrior, -1, | |
| 181 | + sqlite3_result_text(ctx, pCsr->pFile->zPrior, -1, | |
| 181 | 182 | SQLITE_TRANSIENT); |
| 182 | 183 | break; |
| 183 | 184 | case 4: /* perm */ |
| 184 | - sqlite3_result_text(ctx, pCsr->pMan->aFile[pCsr->iFile].zPerm, -1, | |
| 185 | + sqlite3_result_text(ctx, pCsr->pFile->zPerm, -1, | |
| 185 | 186 | SQLITE_TRANSIENT); |
| 186 | 187 | break; |
| 187 | 188 | } |
| 188 | 189 | return SQLITE_OK; |
| 189 | 190 | } |
| 190 | 191 |
| --- src/foci.c | |
| +++ src/foci.c | |
| @@ -46,11 +46,12 @@ | |
| 46 | sqlite3_vtab base; /* Base class - must be first */ |
| 47 | }; |
| 48 | struct FociCursor { |
| 49 | sqlite3_vtab_cursor base; /* Base class - must be first */ |
| 50 | Manifest *pMan; /* Current manifest */ |
| 51 | int iFile; /* Index of current file */ |
| 52 | }; |
| 53 | #endif /* INTERFACE */ |
| 54 | |
| 55 | |
| 56 | /* |
| @@ -104,14 +105,11 @@ | |
| 104 | |
| 105 | /* |
| 106 | ** Open a new focivfs cursor. |
| 107 | */ |
| 108 | static int fociOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ |
| 109 | FociTable *pTab = (FociTable *)pVTab; |
| 110 | FociCursor *pCsr; |
| 111 | int rc; |
| 112 | |
| 113 | pCsr = (FociCursor *)sqlite3_malloc(sizeof(FociCursor)); |
| 114 | memset(pCsr, 0, sizeof(FociCursor)); |
| 115 | pCsr->base.pVtab = pVTab; |
| 116 | *ppCursor = (sqlite3_vtab_cursor *)pCsr; |
| 117 | return SQLITE_OK; |
| @@ -130,17 +128,18 @@ | |
| 130 | /* |
| 131 | ** Move a focivfs cursor to the next entry in the file. |
| 132 | */ |
| 133 | static int fociNext(sqlite3_vtab_cursor *pCursor){ |
| 134 | FociCursor *pCsr = (FociCursor *)pCursor; |
| 135 | pCsr->iFile++; |
| 136 | return SQLITE_OK; |
| 137 | } |
| 138 | |
| 139 | static int fociEof(sqlite3_vtab_cursor *pCursor){ |
| 140 | FociCursor *pCsr = (FociCursor *)pCursor; |
| 141 | return pCsr->pMan==0 || pCsr->iFile>=pCsr->pMan->nFile; |
| 142 | } |
| 143 | |
| 144 | static int fociFilter( |
| 145 | sqlite3_vtab_cursor *pCursor, |
| 146 | int idxNum, const char *idxStr, |
| @@ -149,10 +148,12 @@ | |
| 149 | FociCursor *pCur = (FociCursor *)pCursor; |
| 150 | manifest_destroy(pCur->pMan); |
| 151 | if( idxNum ){ |
| 152 | pCur->pMan = manifest_get(sqlite3_value_int(argv[0]), CFTYPE_MANIFEST, 0); |
| 153 | pCur->iFile = 0; |
| 154 | }else{ |
| 155 | pCur->pMan = 0; |
| 156 | pCur->iFile = 0; |
| 157 | } |
| 158 | return SQLITE_OK; |
| @@ -167,23 +168,23 @@ | |
| 167 | switch( i ){ |
| 168 | case 0: /* checkinID */ |
| 169 | sqlite3_result_int(ctx, pCsr->pMan->rid); |
| 170 | break; |
| 171 | case 1: /* filename */ |
| 172 | sqlite3_result_text(ctx, pCsr->pMan->aFile[pCsr->iFile].zName, -1, |
| 173 | SQLITE_TRANSIENT); |
| 174 | break; |
| 175 | case 2: /* uuid */ |
| 176 | sqlite3_result_text(ctx, pCsr->pMan->aFile[pCsr->iFile].zUuid, -1, |
| 177 | SQLITE_TRANSIENT); |
| 178 | break; |
| 179 | case 3: /* previousName */ |
| 180 | sqlite3_result_text(ctx, pCsr->pMan->aFile[pCsr->iFile].zPrior, -1, |
| 181 | SQLITE_TRANSIENT); |
| 182 | break; |
| 183 | case 4: /* perm */ |
| 184 | sqlite3_result_text(ctx, pCsr->pMan->aFile[pCsr->iFile].zPerm, -1, |
| 185 | SQLITE_TRANSIENT); |
| 186 | break; |
| 187 | } |
| 188 | return SQLITE_OK; |
| 189 | } |
| 190 |
| --- src/foci.c | |
| +++ src/foci.c | |
| @@ -46,11 +46,12 @@ | |
| 46 | sqlite3_vtab base; /* Base class - must be first */ |
| 47 | }; |
| 48 | struct FociCursor { |
| 49 | sqlite3_vtab_cursor base; /* Base class - must be first */ |
| 50 | Manifest *pMan; /* Current manifest */ |
| 51 | ManifestFile *pFile; /* Current file */ |
| 52 | int iFile; /* File index */ |
| 53 | }; |
| 54 | #endif /* INTERFACE */ |
| 55 | |
| 56 | |
| 57 | /* |
| @@ -104,14 +105,11 @@ | |
| 105 | |
| 106 | /* |
| 107 | ** Open a new focivfs cursor. |
| 108 | */ |
| 109 | static int fociOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ |
| 110 | FociCursor *pCsr; |
| 111 | pCsr = (FociCursor *)sqlite3_malloc(sizeof(FociCursor)); |
| 112 | memset(pCsr, 0, sizeof(FociCursor)); |
| 113 | pCsr->base.pVtab = pVTab; |
| 114 | *ppCursor = (sqlite3_vtab_cursor *)pCsr; |
| 115 | return SQLITE_OK; |
| @@ -130,17 +128,18 @@ | |
| 128 | /* |
| 129 | ** Move a focivfs cursor to the next entry in the file. |
| 130 | */ |
| 131 | static int fociNext(sqlite3_vtab_cursor *pCursor){ |
| 132 | FociCursor *pCsr = (FociCursor *)pCursor; |
| 133 | pCsr->pFile = manifest_file_next(pCsr->pMan, 0); |
| 134 | pCsr->iFile++; |
| 135 | return SQLITE_OK; |
| 136 | } |
| 137 | |
| 138 | static int fociEof(sqlite3_vtab_cursor *pCursor){ |
| 139 | FociCursor *pCsr = (FociCursor *)pCursor; |
| 140 | return pCsr->pFile==0; |
| 141 | } |
| 142 | |
| 143 | static int fociFilter( |
| 144 | sqlite3_vtab_cursor *pCursor, |
| 145 | int idxNum, const char *idxStr, |
| @@ -149,10 +148,12 @@ | |
| 148 | FociCursor *pCur = (FociCursor *)pCursor; |
| 149 | manifest_destroy(pCur->pMan); |
| 150 | if( idxNum ){ |
| 151 | pCur->pMan = manifest_get(sqlite3_value_int(argv[0]), CFTYPE_MANIFEST, 0); |
| 152 | pCur->iFile = 0; |
| 153 | manifest_file_rewind(pCur->pMan); |
| 154 | pCur->pFile = manifest_file_next(pCur->pMan, 0); |
| 155 | }else{ |
| 156 | pCur->pMan = 0; |
| 157 | pCur->iFile = 0; |
| 158 | } |
| 159 | return SQLITE_OK; |
| @@ -167,23 +168,23 @@ | |
| 168 | switch( i ){ |
| 169 | case 0: /* checkinID */ |
| 170 | sqlite3_result_int(ctx, pCsr->pMan->rid); |
| 171 | break; |
| 172 | case 1: /* filename */ |
| 173 | sqlite3_result_text(ctx, pCsr->pFile->zName, -1, |
| 174 | SQLITE_TRANSIENT); |
| 175 | break; |
| 176 | case 2: /* uuid */ |
| 177 | sqlite3_result_text(ctx, pCsr->pFile->zUuid, -1, |
| 178 | SQLITE_TRANSIENT); |
| 179 | break; |
| 180 | case 3: /* previousName */ |
| 181 | sqlite3_result_text(ctx, pCsr->pFile->zPrior, -1, |
| 182 | SQLITE_TRANSIENT); |
| 183 | break; |
| 184 | case 4: /* perm */ |
| 185 | sqlite3_result_text(ctx, pCsr->pFile->zPerm, -1, |
| 186 | SQLITE_TRANSIENT); |
| 187 | break; |
| 188 | } |
| 189 | return SQLITE_OK; |
| 190 | } |
| 191 |
-1
| --- src/fusefs.c | ||
| +++ src/fusefs.c | ||
| @@ -319,11 +319,10 @@ | ||
| 319 | 319 | #ifndef FOSSIL_HAVE_FUSEFS |
| 320 | 320 | fossil_fatal("this build of fossil does not support the fuse filesystem"); |
| 321 | 321 | #else |
| 322 | 322 | char *zMountPoint; |
| 323 | 323 | char *azNewArgv[5]; |
| 324 | - int i; | |
| 325 | 324 | int doDebug = find_option("debug","d",0)!=0; |
| 326 | 325 | |
| 327 | 326 | db_find_and_open_repository(0,0); |
| 328 | 327 | verify_all_options(); |
| 329 | 328 | blob_init(&fusefs.content, 0, 0); |
| 330 | 329 |
| --- src/fusefs.c | |
| +++ src/fusefs.c | |
| @@ -319,11 +319,10 @@ | |
| 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 i; |
| 325 | int doDebug = find_option("debug","d",0)!=0; |
| 326 | |
| 327 | db_find_and_open_repository(0,0); |
| 328 | verify_all_options(); |
| 329 | blob_init(&fusefs.content, 0, 0); |
| 330 |
| --- src/fusefs.c | |
| +++ src/fusefs.c | |
| @@ -319,11 +319,10 @@ | |
| 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); |
| 327 | verify_all_options(); |
| 328 | blob_init(&fusefs.content, 0, 0); |
| 329 |
+8
-6
| --- src/http.c | ||
| +++ src/http.c | ||
| @@ -285,11 +285,11 @@ | ||
| 285 | 285 | g.zHttpAuth = prompt_for_httpauth_creds(); |
| 286 | 286 | transport_close(&g.url); |
| 287 | 287 | return http_exchange(pSend, pReply, useLogin, maxRedirect); |
| 288 | 288 | } |
| 289 | 289 | } |
| 290 | - if( rc!=200 && rc!=302 ){ | |
| 290 | + if( rc!=200 && rc!=301 && rc!=302 ){ | |
| 291 | 291 | int ii; |
| 292 | 292 | for(ii=7; zLine[ii] && zLine[ii]!=' '; ii++){} |
| 293 | 293 | while( zLine[ii]==' ' ) ii++; |
| 294 | 294 | fossil_warning("server says: %s", &zLine[ii]); |
| 295 | 295 | goto write_err; |
| @@ -299,11 +299,11 @@ | ||
| 299 | 299 | }else{ |
| 300 | 300 | closeConnection = 0; |
| 301 | 301 | } |
| 302 | 302 | }else if( g.url.isSsh && fossil_strnicmp(zLine, "status:", 7)==0 ){ |
| 303 | 303 | if( sscanf(zLine, "Status: %d", &rc)!=1 ) goto write_err; |
| 304 | - if( rc!=200 && rc!=302 ){ | |
| 304 | + if( rc!=200 && rc!=301 && rc!=302 ){ | |
| 305 | 305 | int ii; |
| 306 | 306 | for(ii=7; zLine[ii] && zLine[ii]!=' '; ii++){} |
| 307 | 307 | while( zLine[ii]==' ' ) ii++; |
| 308 | 308 | fossil_warning("server says: %s", &zLine[ii]); |
| 309 | 309 | goto write_err; |
| @@ -319,11 +319,12 @@ | ||
| 319 | 319 | if( c=='c' || c=='C' ){ |
| 320 | 320 | closeConnection = 1; |
| 321 | 321 | }else if( c=='k' || c=='K' ){ |
| 322 | 322 | closeConnection = 0; |
| 323 | 323 | } |
| 324 | - }else if( rc==302 && fossil_strnicmp(zLine, "location:", 9)==0 ){ | |
| 324 | + }else if( ( rc==301 || rc==302 ) && | |
| 325 | + fossil_strnicmp(zLine, "location:", 9)==0 ){ | |
| 325 | 326 | int i, j; |
| 326 | 327 | |
| 327 | 328 | if ( --maxRedirect == 0){ |
| 328 | 329 | fossil_warning("redirect limit exceeded"); |
| 329 | 330 | goto write_err; |
| @@ -336,16 +337,17 @@ | ||
| 336 | 337 | j = strlen(zLine) - 1; |
| 337 | 338 | while( j>4 && fossil_strcmp(&zLine[j-4],"/xfer")==0 ){ |
| 338 | 339 | j -= 4; |
| 339 | 340 | zLine[j] = 0; |
| 340 | 341 | } |
| 341 | - fossil_print("redirect to %s\n", &zLine[i]); | |
| 342 | + transport_close(&g.url); | |
| 343 | + transport_global_shutdown(&g.url); | |
| 344 | + fossil_print("redirect with status %d to %s\n", rc, &zLine[i]); | |
| 342 | 345 | url_parse(&zLine[i], 0); |
| 343 | 346 | fSeenHttpAuth = 0; |
| 344 | 347 | if( g.zHttpAuth ) free(g.zHttpAuth); |
| 345 | 348 | g.zHttpAuth = get_httpauth(); |
| 346 | - transport_close(&g.url); | |
| 347 | 349 | return http_exchange(pSend, pReply, useLogin, maxRedirect); |
| 348 | 350 | }else if( fossil_strnicmp(zLine, "content-type: ", 14)==0 ){ |
| 349 | 351 | if( fossil_strnicmp(&zLine[14], "application/x-fossil-debug", -1)==0 ){ |
| 350 | 352 | isCompressed = 0; |
| 351 | 353 | }else if( fossil_strnicmp(&zLine[14], |
| @@ -359,11 +361,11 @@ | ||
| 359 | 361 | if( iLength<0 ){ |
| 360 | 362 | fossil_warning("server did not reply"); |
| 361 | 363 | goto write_err; |
| 362 | 364 | } |
| 363 | 365 | if( rc!=200 ){ |
| 364 | - fossil_warning("\"location:\" missing from 302 redirect reply"); | |
| 366 | + fossil_warning("\"location:\" missing from %d redirect reply", rc); | |
| 365 | 367 | goto write_err; |
| 366 | 368 | } |
| 367 | 369 | |
| 368 | 370 | /* |
| 369 | 371 | ** Extract the reply payload that follows the header |
| 370 | 372 |
| --- src/http.c | |
| +++ src/http.c | |
| @@ -285,11 +285,11 @@ | |
| 285 | g.zHttpAuth = prompt_for_httpauth_creds(); |
| 286 | transport_close(&g.url); |
| 287 | return http_exchange(pSend, pReply, useLogin, maxRedirect); |
| 288 | } |
| 289 | } |
| 290 | if( rc!=200 && rc!=302 ){ |
| 291 | int ii; |
| 292 | for(ii=7; zLine[ii] && zLine[ii]!=' '; ii++){} |
| 293 | while( zLine[ii]==' ' ) ii++; |
| 294 | fossil_warning("server says: %s", &zLine[ii]); |
| 295 | goto write_err; |
| @@ -299,11 +299,11 @@ | |
| 299 | }else{ |
| 300 | closeConnection = 0; |
| 301 | } |
| 302 | }else if( g.url.isSsh && fossil_strnicmp(zLine, "status:", 7)==0 ){ |
| 303 | if( sscanf(zLine, "Status: %d", &rc)!=1 ) goto write_err; |
| 304 | if( rc!=200 && rc!=302 ){ |
| 305 | int ii; |
| 306 | for(ii=7; zLine[ii] && zLine[ii]!=' '; ii++){} |
| 307 | while( zLine[ii]==' ' ) ii++; |
| 308 | fossil_warning("server says: %s", &zLine[ii]); |
| 309 | goto write_err; |
| @@ -319,11 +319,12 @@ | |
| 319 | if( c=='c' || c=='C' ){ |
| 320 | closeConnection = 1; |
| 321 | }else if( c=='k' || c=='K' ){ |
| 322 | closeConnection = 0; |
| 323 | } |
| 324 | }else if( rc==302 && fossil_strnicmp(zLine, "location:", 9)==0 ){ |
| 325 | int i, j; |
| 326 | |
| 327 | if ( --maxRedirect == 0){ |
| 328 | fossil_warning("redirect limit exceeded"); |
| 329 | goto write_err; |
| @@ -336,16 +337,17 @@ | |
| 336 | j = strlen(zLine) - 1; |
| 337 | while( j>4 && fossil_strcmp(&zLine[j-4],"/xfer")==0 ){ |
| 338 | j -= 4; |
| 339 | zLine[j] = 0; |
| 340 | } |
| 341 | fossil_print("redirect to %s\n", &zLine[i]); |
| 342 | url_parse(&zLine[i], 0); |
| 343 | fSeenHttpAuth = 0; |
| 344 | if( g.zHttpAuth ) free(g.zHttpAuth); |
| 345 | g.zHttpAuth = get_httpauth(); |
| 346 | transport_close(&g.url); |
| 347 | return http_exchange(pSend, pReply, useLogin, maxRedirect); |
| 348 | }else if( fossil_strnicmp(zLine, "content-type: ", 14)==0 ){ |
| 349 | if( fossil_strnicmp(&zLine[14], "application/x-fossil-debug", -1)==0 ){ |
| 350 | isCompressed = 0; |
| 351 | }else if( fossil_strnicmp(&zLine[14], |
| @@ -359,11 +361,11 @@ | |
| 359 | if( iLength<0 ){ |
| 360 | fossil_warning("server did not reply"); |
| 361 | goto write_err; |
| 362 | } |
| 363 | if( rc!=200 ){ |
| 364 | fossil_warning("\"location:\" missing from 302 redirect reply"); |
| 365 | goto write_err; |
| 366 | } |
| 367 | |
| 368 | /* |
| 369 | ** Extract the reply payload that follows the header |
| 370 |
| --- src/http.c | |
| +++ src/http.c | |
| @@ -285,11 +285,11 @@ | |
| 285 | g.zHttpAuth = prompt_for_httpauth_creds(); |
| 286 | transport_close(&g.url); |
| 287 | return http_exchange(pSend, pReply, useLogin, maxRedirect); |
| 288 | } |
| 289 | } |
| 290 | if( rc!=200 && rc!=301 && rc!=302 ){ |
| 291 | int ii; |
| 292 | for(ii=7; zLine[ii] && zLine[ii]!=' '; ii++){} |
| 293 | while( zLine[ii]==' ' ) ii++; |
| 294 | fossil_warning("server says: %s", &zLine[ii]); |
| 295 | goto write_err; |
| @@ -299,11 +299,11 @@ | |
| 299 | }else{ |
| 300 | closeConnection = 0; |
| 301 | } |
| 302 | }else if( g.url.isSsh && fossil_strnicmp(zLine, "status:", 7)==0 ){ |
| 303 | if( sscanf(zLine, "Status: %d", &rc)!=1 ) goto write_err; |
| 304 | if( rc!=200 && rc!=301 && rc!=302 ){ |
| 305 | int ii; |
| 306 | for(ii=7; zLine[ii] && zLine[ii]!=' '; ii++){} |
| 307 | while( zLine[ii]==' ' ) ii++; |
| 308 | fossil_warning("server says: %s", &zLine[ii]); |
| 309 | goto write_err; |
| @@ -319,11 +319,12 @@ | |
| 319 | if( c=='c' || c=='C' ){ |
| 320 | closeConnection = 1; |
| 321 | }else if( c=='k' || c=='K' ){ |
| 322 | closeConnection = 0; |
| 323 | } |
| 324 | }else if( ( rc==301 || rc==302 ) && |
| 325 | fossil_strnicmp(zLine, "location:", 9)==0 ){ |
| 326 | int i, j; |
| 327 | |
| 328 | if ( --maxRedirect == 0){ |
| 329 | fossil_warning("redirect limit exceeded"); |
| 330 | goto write_err; |
| @@ -336,16 +337,17 @@ | |
| 337 | j = strlen(zLine) - 1; |
| 338 | while( j>4 && fossil_strcmp(&zLine[j-4],"/xfer")==0 ){ |
| 339 | j -= 4; |
| 340 | zLine[j] = 0; |
| 341 | } |
| 342 | transport_close(&g.url); |
| 343 | transport_global_shutdown(&g.url); |
| 344 | fossil_print("redirect with status %d to %s\n", rc, &zLine[i]); |
| 345 | url_parse(&zLine[i], 0); |
| 346 | fSeenHttpAuth = 0; |
| 347 | if( g.zHttpAuth ) free(g.zHttpAuth); |
| 348 | g.zHttpAuth = get_httpauth(); |
| 349 | return http_exchange(pSend, pReply, useLogin, maxRedirect); |
| 350 | }else if( fossil_strnicmp(zLine, "content-type: ", 14)==0 ){ |
| 351 | if( fossil_strnicmp(&zLine[14], "application/x-fossil-debug", -1)==0 ){ |
| 352 | isCompressed = 0; |
| 353 | }else if( fossil_strnicmp(&zLine[14], |
| @@ -359,11 +361,11 @@ | |
| 361 | if( iLength<0 ){ |
| 362 | fossil_warning("server did not reply"); |
| 363 | goto write_err; |
| 364 | } |
| 365 | if( rc!=200 ){ |
| 366 | fossil_warning("\"location:\" missing from %d redirect reply", rc); |
| 367 | goto write_err; |
| 368 | } |
| 369 | |
| 370 | /* |
| 371 | ** Extract the reply payload that follows the header |
| 372 |
+3
-1
| --- src/http_socket.c | ||
| +++ src/http_socket.c | ||
| @@ -45,10 +45,11 @@ | ||
| 45 | 45 | ** There can only be a single socket connection open at a time. |
| 46 | 46 | ** State information about that socket is stored in the following |
| 47 | 47 | ** local variables: |
| 48 | 48 | */ |
| 49 | 49 | static int socketIsInit = 0; /* True after global initialization */ |
| 50 | +static int addrIsInit = 0; /* True once addr is initialized */ | |
| 50 | 51 | #if defined(_WIN32) |
| 51 | 52 | static WSADATA socketInfo; /* Windows socket initialize data */ |
| 52 | 53 | #endif |
| 53 | 54 | static int iSocket = -1; /* The socket on which we talk to the server */ |
| 54 | 55 | static char *socketErrMsg = 0; /* Text of most recent socket error */ |
| @@ -105,10 +106,11 @@ | ||
| 105 | 106 | WSACleanup(); |
| 106 | 107 | #endif |
| 107 | 108 | socket_clear_errmsg(); |
| 108 | 109 | socketIsInit = 0; |
| 109 | 110 | } |
| 111 | + addrIsInit = 0; | |
| 110 | 112 | } |
| 111 | 113 | |
| 112 | 114 | /* |
| 113 | 115 | ** Close the currently open socket. If no socket is open, this routine |
| 114 | 116 | ** is a no-op. |
| @@ -133,14 +135,14 @@ | ||
| 133 | 135 | ** |
| 134 | 136 | ** Return the number of errors. |
| 135 | 137 | */ |
| 136 | 138 | int socket_open(UrlData *pUrlData){ |
| 137 | 139 | static struct sockaddr_in addr; /* The server address */ |
| 138 | - static int addrIsInit = 0; /* True once addr is initialized */ | |
| 139 | 140 | |
| 140 | 141 | socket_global_init(); |
| 141 | 142 | if( !addrIsInit ){ |
| 143 | + memset(&addr, 0, sizeof(addr)); | |
| 142 | 144 | addr.sin_family = AF_INET; |
| 143 | 145 | addr.sin_port = htons(pUrlData->port); |
| 144 | 146 | *(int*)&addr.sin_addr = inet_addr(pUrlData->name); |
| 145 | 147 | if( -1 == *(int*)&addr.sin_addr ){ |
| 146 | 148 | #ifndef FOSSIL_STATIC_LINK |
| 147 | 149 |
| --- src/http_socket.c | |
| +++ src/http_socket.c | |
| @@ -45,10 +45,11 @@ | |
| 45 | ** There can only be a single socket connection open at a time. |
| 46 | ** State information about that socket is stored in the following |
| 47 | ** local variables: |
| 48 | */ |
| 49 | static int socketIsInit = 0; /* True after global initialization */ |
| 50 | #if defined(_WIN32) |
| 51 | static WSADATA socketInfo; /* Windows socket initialize data */ |
| 52 | #endif |
| 53 | static int iSocket = -1; /* The socket on which we talk to the server */ |
| 54 | static char *socketErrMsg = 0; /* Text of most recent socket error */ |
| @@ -105,10 +106,11 @@ | |
| 105 | WSACleanup(); |
| 106 | #endif |
| 107 | socket_clear_errmsg(); |
| 108 | socketIsInit = 0; |
| 109 | } |
| 110 | } |
| 111 | |
| 112 | /* |
| 113 | ** Close the currently open socket. If no socket is open, this routine |
| 114 | ** is a no-op. |
| @@ -133,14 +135,14 @@ | |
| 133 | ** |
| 134 | ** Return the number of errors. |
| 135 | */ |
| 136 | int socket_open(UrlData *pUrlData){ |
| 137 | static struct sockaddr_in addr; /* The server address */ |
| 138 | static int addrIsInit = 0; /* True once addr is initialized */ |
| 139 | |
| 140 | socket_global_init(); |
| 141 | if( !addrIsInit ){ |
| 142 | addr.sin_family = AF_INET; |
| 143 | addr.sin_port = htons(pUrlData->port); |
| 144 | *(int*)&addr.sin_addr = inet_addr(pUrlData->name); |
| 145 | if( -1 == *(int*)&addr.sin_addr ){ |
| 146 | #ifndef FOSSIL_STATIC_LINK |
| 147 |
| --- src/http_socket.c | |
| +++ src/http_socket.c | |
| @@ -45,10 +45,11 @@ | |
| 45 | ** There can only be a single socket connection open at a time. |
| 46 | ** State information about that socket is stored in the following |
| 47 | ** local variables: |
| 48 | */ |
| 49 | static int socketIsInit = 0; /* True after global initialization */ |
| 50 | static int addrIsInit = 0; /* True once addr is initialized */ |
| 51 | #if defined(_WIN32) |
| 52 | static WSADATA socketInfo; /* Windows socket initialize data */ |
| 53 | #endif |
| 54 | static int iSocket = -1; /* The socket on which we talk to the server */ |
| 55 | static char *socketErrMsg = 0; /* Text of most recent socket error */ |
| @@ -105,10 +106,11 @@ | |
| 106 | WSACleanup(); |
| 107 | #endif |
| 108 | socket_clear_errmsg(); |
| 109 | socketIsInit = 0; |
| 110 | } |
| 111 | addrIsInit = 0; |
| 112 | } |
| 113 | |
| 114 | /* |
| 115 | ** Close the currently open socket. If no socket is open, this routine |
| 116 | ** is a no-op. |
| @@ -133,14 +135,14 @@ | |
| 135 | ** |
| 136 | ** Return the number of errors. |
| 137 | */ |
| 138 | int socket_open(UrlData *pUrlData){ |
| 139 | static struct sockaddr_in addr; /* The server address */ |
| 140 | |
| 141 | socket_global_init(); |
| 142 | if( !addrIsInit ){ |
| 143 | memset(&addr, 0, sizeof(addr)); |
| 144 | addr.sin_family = AF_INET; |
| 145 | addr.sin_port = htons(pUrlData->port); |
| 146 | *(int*)&addr.sin_addr = inet_addr(pUrlData->name); |
| 147 | if( -1 == *(int*)&addr.sin_addr ){ |
| 148 | #ifndef FOSSIL_STATIC_LINK |
| 149 |
+4
-3
| --- src/http_ssl.c | ||
| +++ src/http_ssl.c | ||
| @@ -41,11 +41,11 @@ | ||
| 41 | 41 | ** There can only be a single OpenSSL IO connection open at a time. |
| 42 | 42 | ** State information about that IO is stored in the following |
| 43 | 43 | ** local variables: |
| 44 | 44 | */ |
| 45 | 45 | static int sslIsInit = 0; /* True after global initialization */ |
| 46 | -static BIO *iBio; /* OpenSSL I/O abstraction */ | |
| 46 | +static BIO *iBio = 0; /* OpenSSL I/O abstraction */ | |
| 47 | 47 | static char *sslErrMsg = 0; /* Text of most recent OpenSSL error */ |
| 48 | 48 | static SSL_CTX *sslCtx; /* SSL context */ |
| 49 | 49 | static SSL *ssl; |
| 50 | 50 | |
| 51 | 51 | |
| @@ -99,12 +99,12 @@ | ||
| 99 | 99 | SSL_library_init(); |
| 100 | 100 | SSL_load_error_strings(); |
| 101 | 101 | ERR_load_BIO_strings(); |
| 102 | 102 | OpenSSL_add_all_algorithms(); |
| 103 | 103 | sslCtx = SSL_CTX_new(SSLv23_client_method()); |
| 104 | - /* Disable SSLv2 */ | |
| 105 | - SSL_CTX_set_options(sslCtx, SSL_OP_NO_SSLv2); | |
| 104 | + /* Disable SSLv2 and SSLv3 */ | |
| 105 | + SSL_CTX_set_options(sslCtx, SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3); | |
| 106 | 106 | |
| 107 | 107 | /* Set up acceptable CA root certificates */ |
| 108 | 108 | zCaSetting = db_get("ssl-ca-location", 0); |
| 109 | 109 | if( zCaSetting==0 || zCaSetting[0]=='\0' ){ |
| 110 | 110 | /* CA location not specified, use platform's default certificate store */ |
| @@ -171,10 +171,11 @@ | ||
| 171 | 171 | */ |
| 172 | 172 | void ssl_close(void){ |
| 173 | 173 | if( iBio!=NULL ){ |
| 174 | 174 | (void)BIO_reset(iBio); |
| 175 | 175 | BIO_free_all(iBio); |
| 176 | + iBio = NULL; | |
| 176 | 177 | } |
| 177 | 178 | } |
| 178 | 179 | |
| 179 | 180 | /* See RFC2817 for details */ |
| 180 | 181 | static int establish_proxy_tunnel(UrlData *pUrlData, BIO *bio){ |
| 181 | 182 |
| --- src/http_ssl.c | |
| +++ src/http_ssl.c | |
| @@ -41,11 +41,11 @@ | |
| 41 | ** There can only be a single OpenSSL IO connection open at a time. |
| 42 | ** State information about that IO is stored in the following |
| 43 | ** local variables: |
| 44 | */ |
| 45 | static int sslIsInit = 0; /* True after global initialization */ |
| 46 | static BIO *iBio; /* OpenSSL I/O abstraction */ |
| 47 | static char *sslErrMsg = 0; /* Text of most recent OpenSSL error */ |
| 48 | static SSL_CTX *sslCtx; /* SSL context */ |
| 49 | static SSL *ssl; |
| 50 | |
| 51 | |
| @@ -99,12 +99,12 @@ | |
| 99 | SSL_library_init(); |
| 100 | SSL_load_error_strings(); |
| 101 | ERR_load_BIO_strings(); |
| 102 | OpenSSL_add_all_algorithms(); |
| 103 | sslCtx = SSL_CTX_new(SSLv23_client_method()); |
| 104 | /* Disable SSLv2 */ |
| 105 | SSL_CTX_set_options(sslCtx, SSL_OP_NO_SSLv2); |
| 106 | |
| 107 | /* Set up acceptable CA root certificates */ |
| 108 | zCaSetting = db_get("ssl-ca-location", 0); |
| 109 | if( zCaSetting==0 || zCaSetting[0]=='\0' ){ |
| 110 | /* CA location not specified, use platform's default certificate store */ |
| @@ -171,10 +171,11 @@ | |
| 171 | */ |
| 172 | void ssl_close(void){ |
| 173 | if( iBio!=NULL ){ |
| 174 | (void)BIO_reset(iBio); |
| 175 | BIO_free_all(iBio); |
| 176 | } |
| 177 | } |
| 178 | |
| 179 | /* See RFC2817 for details */ |
| 180 | static int establish_proxy_tunnel(UrlData *pUrlData, BIO *bio){ |
| 181 |
| --- src/http_ssl.c | |
| +++ src/http_ssl.c | |
| @@ -41,11 +41,11 @@ | |
| 41 | ** There can only be a single OpenSSL IO connection open at a time. |
| 42 | ** State information about that IO is stored in the following |
| 43 | ** local variables: |
| 44 | */ |
| 45 | static int sslIsInit = 0; /* True after global initialization */ |
| 46 | static BIO *iBio = 0; /* OpenSSL I/O abstraction */ |
| 47 | static char *sslErrMsg = 0; /* Text of most recent OpenSSL error */ |
| 48 | static SSL_CTX *sslCtx; /* SSL context */ |
| 49 | static SSL *ssl; |
| 50 | |
| 51 | |
| @@ -99,12 +99,12 @@ | |
| 99 | SSL_library_init(); |
| 100 | SSL_load_error_strings(); |
| 101 | ERR_load_BIO_strings(); |
| 102 | OpenSSL_add_all_algorithms(); |
| 103 | sslCtx = SSL_CTX_new(SSLv23_client_method()); |
| 104 | /* Disable SSLv2 and SSLv3 */ |
| 105 | SSL_CTX_set_options(sslCtx, SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3); |
| 106 | |
| 107 | /* Set up acceptable CA root certificates */ |
| 108 | zCaSetting = db_get("ssl-ca-location", 0); |
| 109 | if( zCaSetting==0 || zCaSetting[0]=='\0' ){ |
| 110 | /* CA location not specified, use platform's default certificate store */ |
| @@ -171,10 +171,11 @@ | |
| 171 | */ |
| 172 | void ssl_close(void){ |
| 173 | if( iBio!=NULL ){ |
| 174 | (void)BIO_reset(iBio); |
| 175 | BIO_free_all(iBio); |
| 176 | iBio = NULL; |
| 177 | } |
| 178 | } |
| 179 | |
| 180 | /* See RFC2817 for details */ |
| 181 | static int establish_proxy_tunnel(UrlData *pUrlData, BIO *bio){ |
| 182 |
+7
-2
| --- src/info.c | ||
| +++ src/info.c | ||
| @@ -931,10 +931,11 @@ | ||
| 931 | 931 | }else{ |
| 932 | 932 | @ tags: %h(zTagList), |
| 933 | 933 | } |
| 934 | 934 | @ date: |
| 935 | 935 | hyperlink_to_date(zDate, ")"); |
| 936 | + tag_private_status(rid); | |
| 936 | 937 | } |
| 937 | 938 | db_finalize(&q); |
| 938 | 939 | } |
| 939 | 940 | |
| 940 | 941 | |
| @@ -1203,19 +1204,20 @@ | ||
| 1203 | 1204 | }else{ |
| 1204 | 1205 | @ <li>File |
| 1205 | 1206 | } |
| 1206 | 1207 | objType |= OBJTYPE_CONTENT; |
| 1207 | 1208 | @ %z(href("%R/finfo?name=%T",zName))%h(zName)</a> |
| 1209 | + tag_private_status(rid); | |
| 1208 | 1210 | if( showDetail ){ |
| 1209 | 1211 | @ <ul> |
| 1210 | 1212 | } |
| 1211 | 1213 | prevName = fossil_strdup(zName); |
| 1212 | 1214 | } |
| 1213 | 1215 | if( showDetail ){ |
| 1214 | 1216 | @ <li> |
| 1215 | 1217 | hyperlink_to_date(zDate,""); |
| 1216 | - @ — part of check-in | |
| 1218 | + @ — part of checkin | |
| 1217 | 1219 | hyperlink_to_uuid(zVers); |
| 1218 | 1220 | }else{ |
| 1219 | 1221 | @ — part of checkin |
| 1220 | 1222 | hyperlink_to_uuid(zVers); |
| 1221 | 1223 | @ at |
| @@ -1314,10 +1316,11 @@ | ||
| 1314 | 1316 | hyperlink_to_user(zUser,zDate," on"); |
| 1315 | 1317 | hyperlink_to_date(zDate, "."); |
| 1316 | 1318 | if( pDownloadName && blob_size(pDownloadName)==0 ){ |
| 1317 | 1319 | blob_appendf(pDownloadName, "%.10s.txt", zUuid); |
| 1318 | 1320 | } |
| 1321 | + tag_private_status(rid); | |
| 1319 | 1322 | cnt++; |
| 1320 | 1323 | } |
| 1321 | 1324 | db_finalize(&q); |
| 1322 | 1325 | } |
| 1323 | 1326 | db_prepare(&q, |
| @@ -1357,17 +1360,19 @@ | ||
| 1357 | 1360 | hyperlink_to_date(zDate,"."); |
| 1358 | 1361 | cnt++; |
| 1359 | 1362 | if( pDownloadName && blob_size(pDownloadName)==0 ){ |
| 1360 | 1363 | blob_append(pDownloadName, zFilename, -1); |
| 1361 | 1364 | } |
| 1365 | + tag_private_status(rid); | |
| 1362 | 1366 | } |
| 1363 | 1367 | db_finalize(&q); |
| 1364 | 1368 | if( cnt==0 ){ |
| 1365 | 1369 | @ Control artifact. |
| 1366 | 1370 | if( pDownloadName && blob_size(pDownloadName)==0 ){ |
| 1367 | 1371 | blob_appendf(pDownloadName, "%.10s.txt", zUuid); |
| 1368 | 1372 | } |
| 1373 | + tag_private_status(rid); | |
| 1369 | 1374 | } |
| 1370 | 1375 | return objType; |
| 1371 | 1376 | } |
| 1372 | 1377 | |
| 1373 | 1378 | |
| @@ -1914,11 +1919,11 @@ | ||
| 1914 | 1919 | } |
| 1915 | 1920 | if( strcmp(zModAction,"approve")==0 ){ |
| 1916 | 1921 | moderation_approve(rid); |
| 1917 | 1922 | } |
| 1918 | 1923 | } |
| 1919 | - zTktTitle = db_table_has_column( "ticket", "title" ) | |
| 1924 | + zTktTitle = db_table_has_column("repository", "ticket", "title" ) | |
| 1920 | 1925 | ? db_text("(No title)", "SELECT title FROM ticket WHERE tkt_uuid=%Q", zTktName) |
| 1921 | 1926 | : 0; |
| 1922 | 1927 | style_header("Ticket Change Details"); |
| 1923 | 1928 | style_submenu_element("Raw", "Raw", "%R/artifact/%s", zUuid); |
| 1924 | 1929 | style_submenu_element("History", "History", "%R/tkthistory/%s", zTktName); |
| 1925 | 1930 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -931,10 +931,11 @@ | |
| 931 | }else{ |
| 932 | @ tags: %h(zTagList), |
| 933 | } |
| 934 | @ date: |
| 935 | hyperlink_to_date(zDate, ")"); |
| 936 | } |
| 937 | db_finalize(&q); |
| 938 | } |
| 939 | |
| 940 | |
| @@ -1203,19 +1204,20 @@ | |
| 1203 | }else{ |
| 1204 | @ <li>File |
| 1205 | } |
| 1206 | objType |= OBJTYPE_CONTENT; |
| 1207 | @ %z(href("%R/finfo?name=%T",zName))%h(zName)</a> |
| 1208 | if( showDetail ){ |
| 1209 | @ <ul> |
| 1210 | } |
| 1211 | prevName = fossil_strdup(zName); |
| 1212 | } |
| 1213 | if( showDetail ){ |
| 1214 | @ <li> |
| 1215 | hyperlink_to_date(zDate,""); |
| 1216 | @ — part of check-in |
| 1217 | hyperlink_to_uuid(zVers); |
| 1218 | }else{ |
| 1219 | @ — part of checkin |
| 1220 | hyperlink_to_uuid(zVers); |
| 1221 | @ at |
| @@ -1314,10 +1316,11 @@ | |
| 1314 | hyperlink_to_user(zUser,zDate," on"); |
| 1315 | hyperlink_to_date(zDate, "."); |
| 1316 | if( pDownloadName && blob_size(pDownloadName)==0 ){ |
| 1317 | blob_appendf(pDownloadName, "%.10s.txt", zUuid); |
| 1318 | } |
| 1319 | cnt++; |
| 1320 | } |
| 1321 | db_finalize(&q); |
| 1322 | } |
| 1323 | db_prepare(&q, |
| @@ -1357,17 +1360,19 @@ | |
| 1357 | hyperlink_to_date(zDate,"."); |
| 1358 | cnt++; |
| 1359 | if( pDownloadName && blob_size(pDownloadName)==0 ){ |
| 1360 | blob_append(pDownloadName, zFilename, -1); |
| 1361 | } |
| 1362 | } |
| 1363 | db_finalize(&q); |
| 1364 | if( cnt==0 ){ |
| 1365 | @ Control artifact. |
| 1366 | if( pDownloadName && blob_size(pDownloadName)==0 ){ |
| 1367 | blob_appendf(pDownloadName, "%.10s.txt", zUuid); |
| 1368 | } |
| 1369 | } |
| 1370 | return objType; |
| 1371 | } |
| 1372 | |
| 1373 | |
| @@ -1914,11 +1919,11 @@ | |
| 1914 | } |
| 1915 | if( strcmp(zModAction,"approve")==0 ){ |
| 1916 | moderation_approve(rid); |
| 1917 | } |
| 1918 | } |
| 1919 | zTktTitle = db_table_has_column( "ticket", "title" ) |
| 1920 | ? db_text("(No title)", "SELECT title FROM ticket WHERE tkt_uuid=%Q", zTktName) |
| 1921 | : 0; |
| 1922 | style_header("Ticket Change Details"); |
| 1923 | style_submenu_element("Raw", "Raw", "%R/artifact/%s", zUuid); |
| 1924 | style_submenu_element("History", "History", "%R/tkthistory/%s", zTktName); |
| 1925 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -931,10 +931,11 @@ | |
| 931 | }else{ |
| 932 | @ tags: %h(zTagList), |
| 933 | } |
| 934 | @ date: |
| 935 | hyperlink_to_date(zDate, ")"); |
| 936 | tag_private_status(rid); |
| 937 | } |
| 938 | db_finalize(&q); |
| 939 | } |
| 940 | |
| 941 | |
| @@ -1203,19 +1204,20 @@ | |
| 1204 | }else{ |
| 1205 | @ <li>File |
| 1206 | } |
| 1207 | objType |= OBJTYPE_CONTENT; |
| 1208 | @ %z(href("%R/finfo?name=%T",zName))%h(zName)</a> |
| 1209 | tag_private_status(rid); |
| 1210 | if( showDetail ){ |
| 1211 | @ <ul> |
| 1212 | } |
| 1213 | prevName = fossil_strdup(zName); |
| 1214 | } |
| 1215 | if( showDetail ){ |
| 1216 | @ <li> |
| 1217 | hyperlink_to_date(zDate,""); |
| 1218 | @ — part of checkin |
| 1219 | hyperlink_to_uuid(zVers); |
| 1220 | }else{ |
| 1221 | @ — part of checkin |
| 1222 | hyperlink_to_uuid(zVers); |
| 1223 | @ at |
| @@ -1314,10 +1316,11 @@ | |
| 1316 | hyperlink_to_user(zUser,zDate," on"); |
| 1317 | hyperlink_to_date(zDate, "."); |
| 1318 | if( pDownloadName && blob_size(pDownloadName)==0 ){ |
| 1319 | blob_appendf(pDownloadName, "%.10s.txt", zUuid); |
| 1320 | } |
| 1321 | tag_private_status(rid); |
| 1322 | cnt++; |
| 1323 | } |
| 1324 | db_finalize(&q); |
| 1325 | } |
| 1326 | db_prepare(&q, |
| @@ -1357,17 +1360,19 @@ | |
| 1360 | hyperlink_to_date(zDate,"."); |
| 1361 | cnt++; |
| 1362 | if( pDownloadName && blob_size(pDownloadName)==0 ){ |
| 1363 | blob_append(pDownloadName, zFilename, -1); |
| 1364 | } |
| 1365 | tag_private_status(rid); |
| 1366 | } |
| 1367 | db_finalize(&q); |
| 1368 | if( cnt==0 ){ |
| 1369 | @ Control artifact. |
| 1370 | if( pDownloadName && blob_size(pDownloadName)==0 ){ |
| 1371 | blob_appendf(pDownloadName, "%.10s.txt", zUuid); |
| 1372 | } |
| 1373 | tag_private_status(rid); |
| 1374 | } |
| 1375 | return objType; |
| 1376 | } |
| 1377 | |
| 1378 | |
| @@ -1914,11 +1919,11 @@ | |
| 1919 | } |
| 1920 | if( strcmp(zModAction,"approve")==0 ){ |
| 1921 | moderation_approve(rid); |
| 1922 | } |
| 1923 | } |
| 1924 | zTktTitle = db_table_has_column("repository", "ticket", "title" ) |
| 1925 | ? db_text("(No title)", "SELECT title FROM ticket WHERE tkt_uuid=%Q", zTktName) |
| 1926 | : 0; |
| 1927 | style_header("Ticket Change Details"); |
| 1928 | style_submenu_element("Raw", "Raw", "%R/artifact/%s", zUuid); |
| 1929 | style_submenu_element("History", "History", "%R/tkthistory/%s", zTktName); |
| 1930 |
+5
-5
| --- src/json_branch.c | ||
| +++ src/json_branch.c | ||
| @@ -66,11 +66,11 @@ | ||
| 66 | 66 | cson_value * payV; |
| 67 | 67 | cson_object * pay; |
| 68 | 68 | cson_value * listV; |
| 69 | 69 | cson_array * list; |
| 70 | 70 | char const * range = NULL; |
| 71 | - int which = 0; | |
| 71 | + int branchListFlags = BRL_OPEN_ONLY; | |
| 72 | 72 | char * sawConversionError = NULL; |
| 73 | 73 | Stmt q; |
| 74 | 74 | if( !g.perm.Read ){ |
| 75 | 75 | json_set_err(FSL_JSON_E_DENIED, |
| 76 | 76 | "Requires 'o' permissions."); |
| @@ -102,19 +102,19 @@ | ||
| 102 | 102 | } |
| 103 | 103 | /* Normalize range values... */ |
| 104 | 104 | switch(*range){ |
| 105 | 105 | case 'c': |
| 106 | 106 | range = "closed"; |
| 107 | - which = -1; | |
| 107 | + branchListFlags = BRL_CLOSED_ONLY; | |
| 108 | 108 | break; |
| 109 | 109 | case 'a': |
| 110 | 110 | range = "all"; |
| 111 | - which = 1; | |
| 111 | + branchListFlags = BRL_BOTH; | |
| 112 | 112 | break; |
| 113 | 113 | default: |
| 114 | 114 | range = "open"; |
| 115 | - which = 0; | |
| 115 | + branchListFlags = BRL_OPEN_ONLY; | |
| 116 | 116 | break; |
| 117 | 117 | }; |
| 118 | 118 | cson_object_set(pay,"range",json_new_string(range)); |
| 119 | 119 | |
| 120 | 120 | if( g.localOpen ){ /* add "current" property (branch name). */ |
| @@ -128,11 +128,11 @@ | ||
| 128 | 128 | cson_object_set(pay,"current",json_new_string(zCurrent)); |
| 129 | 129 | } |
| 130 | 130 | } |
| 131 | 131 | |
| 132 | 132 | |
| 133 | - branch_prepare_list_query(&q, which); | |
| 133 | + branch_prepare_list_query(&q, branchListFlags); | |
| 134 | 134 | cson_object_set(pay,"branches",listV); |
| 135 | 135 | while((SQLITE_ROW==db_step(&q))){ |
| 136 | 136 | cson_value * v = cson_sqlite3_column_to_value(q.pStmt,0); |
| 137 | 137 | if(v){ |
| 138 | 138 | cson_array_append(list,v); |
| 139 | 139 |
| --- src/json_branch.c | |
| +++ src/json_branch.c | |
| @@ -66,11 +66,11 @@ | |
| 66 | cson_value * payV; |
| 67 | cson_object * pay; |
| 68 | cson_value * listV; |
| 69 | cson_array * list; |
| 70 | char const * range = NULL; |
| 71 | int which = 0; |
| 72 | char * sawConversionError = NULL; |
| 73 | Stmt q; |
| 74 | if( !g.perm.Read ){ |
| 75 | json_set_err(FSL_JSON_E_DENIED, |
| 76 | "Requires 'o' permissions."); |
| @@ -102,19 +102,19 @@ | |
| 102 | } |
| 103 | /* Normalize range values... */ |
| 104 | switch(*range){ |
| 105 | case 'c': |
| 106 | range = "closed"; |
| 107 | which = -1; |
| 108 | break; |
| 109 | case 'a': |
| 110 | range = "all"; |
| 111 | which = 1; |
| 112 | break; |
| 113 | default: |
| 114 | range = "open"; |
| 115 | which = 0; |
| 116 | break; |
| 117 | }; |
| 118 | cson_object_set(pay,"range",json_new_string(range)); |
| 119 | |
| 120 | if( g.localOpen ){ /* add "current" property (branch name). */ |
| @@ -128,11 +128,11 @@ | |
| 128 | cson_object_set(pay,"current",json_new_string(zCurrent)); |
| 129 | } |
| 130 | } |
| 131 | |
| 132 | |
| 133 | branch_prepare_list_query(&q, which); |
| 134 | cson_object_set(pay,"branches",listV); |
| 135 | while((SQLITE_ROW==db_step(&q))){ |
| 136 | cson_value * v = cson_sqlite3_column_to_value(q.pStmt,0); |
| 137 | if(v){ |
| 138 | cson_array_append(list,v); |
| 139 |
| --- src/json_branch.c | |
| +++ src/json_branch.c | |
| @@ -66,11 +66,11 @@ | |
| 66 | cson_value * payV; |
| 67 | cson_object * pay; |
| 68 | cson_value * listV; |
| 69 | cson_array * list; |
| 70 | char const * range = NULL; |
| 71 | int branchListFlags = BRL_OPEN_ONLY; |
| 72 | char * sawConversionError = NULL; |
| 73 | Stmt q; |
| 74 | if( !g.perm.Read ){ |
| 75 | json_set_err(FSL_JSON_E_DENIED, |
| 76 | "Requires 'o' permissions."); |
| @@ -102,19 +102,19 @@ | |
| 102 | } |
| 103 | /* Normalize range values... */ |
| 104 | switch(*range){ |
| 105 | case 'c': |
| 106 | range = "closed"; |
| 107 | branchListFlags = BRL_CLOSED_ONLY; |
| 108 | break; |
| 109 | case 'a': |
| 110 | range = "all"; |
| 111 | branchListFlags = BRL_BOTH; |
| 112 | break; |
| 113 | default: |
| 114 | range = "open"; |
| 115 | branchListFlags = BRL_OPEN_ONLY; |
| 116 | break; |
| 117 | }; |
| 118 | cson_object_set(pay,"range",json_new_string(range)); |
| 119 | |
| 120 | if( g.localOpen ){ /* add "current" property (branch name). */ |
| @@ -128,11 +128,11 @@ | |
| 128 | cson_object_set(pay,"current",json_new_string(zCurrent)); |
| 129 | } |
| 130 | } |
| 131 | |
| 132 | |
| 133 | branch_prepare_list_query(&q, branchListFlags); |
| 134 | cson_object_set(pay,"branches",listV); |
| 135 | while((SQLITE_ROW==db_step(&q))){ |
| 136 | cson_value * v = cson_sqlite3_column_to_value(q.pStmt,0); |
| 137 | if(v){ |
| 138 | cson_array_append(list,v); |
| 139 |
+4
-4
| --- src/json_timeline.c | ||
| +++ src/json_timeline.c | ||
| @@ -88,20 +88,21 @@ | ||
| 88 | 88 | db_multi_exec("%s", zSql /*safe-for-%s*/); |
| 89 | 89 | } |
| 90 | 90 | |
| 91 | 91 | /* |
| 92 | 92 | ** Return a pointer to a constant string that forms the basis |
| 93 | -** for a timeline query for the JSON interface. | |
| 93 | +** for a timeline query for the JSON interface. It MUST NOT | |
| 94 | +** be used in a formatted string argument. | |
| 94 | 95 | */ |
| 95 | 96 | char const * json_timeline_query(void){ |
| 96 | 97 | /* Field order MUST match that from json_timeline_temp_table()!!! */ |
| 97 | 98 | static const char zBaseSql[] = |
| 98 | 99 | @ SELECT |
| 99 | 100 | @ NULL, |
| 100 | 101 | @ blob.rid, |
| 101 | 102 | @ uuid, |
| 102 | - @ CAST(strftime('%%s',event.mtime) AS INTEGER), | |
| 103 | + @ CAST(strftime('%s',event.mtime) AS INTEGER), | |
| 103 | 104 | @ datetime(event.mtime), |
| 104 | 105 | @ coalesce(ecomment, comment), |
| 105 | 106 | @ coalesce(euser, user), |
| 106 | 107 | @ blob.rid IN leaf, |
| 107 | 108 | @ bgcolor, |
| @@ -544,12 +545,11 @@ | ||
| 544 | 545 | goto error; |
| 545 | 546 | } |
| 546 | 547 | |
| 547 | 548 | #if 0 |
| 548 | 549 | /* only for testing! */ |
| 549 | - tmp = cson_value_new_string(blob_buffer(&sql),strlen(blob_buffer(&sql))); | |
| 550 | - SET("timelineSql"); | |
| 550 | + cson_object_set(pay, "timelineSql", cson_value_new_string(blob_buffer(&sql),strlen(blob_buffer(&sql)))); | |
| 551 | 551 | #endif |
| 552 | 552 | db_multi_exec("%s", blob_buffer(&sql) /*safe-for-%s*/); |
| 553 | 553 | blob_reset(&sql); |
| 554 | 554 | db_prepare(&q, "SELECT" |
| 555 | 555 | " uuid AS uuid," |
| 556 | 556 |
| --- src/json_timeline.c | |
| +++ src/json_timeline.c | |
| @@ -88,20 +88,21 @@ | |
| 88 | db_multi_exec("%s", zSql /*safe-for-%s*/); |
| 89 | } |
| 90 | |
| 91 | /* |
| 92 | ** Return a pointer to a constant string that forms the basis |
| 93 | ** for a timeline query for the JSON interface. |
| 94 | */ |
| 95 | char const * json_timeline_query(void){ |
| 96 | /* Field order MUST match that from json_timeline_temp_table()!!! */ |
| 97 | static const char zBaseSql[] = |
| 98 | @ SELECT |
| 99 | @ NULL, |
| 100 | @ blob.rid, |
| 101 | @ uuid, |
| 102 | @ CAST(strftime('%%s',event.mtime) AS INTEGER), |
| 103 | @ datetime(event.mtime), |
| 104 | @ coalesce(ecomment, comment), |
| 105 | @ coalesce(euser, user), |
| 106 | @ blob.rid IN leaf, |
| 107 | @ bgcolor, |
| @@ -544,12 +545,11 @@ | |
| 544 | goto error; |
| 545 | } |
| 546 | |
| 547 | #if 0 |
| 548 | /* only for testing! */ |
| 549 | tmp = cson_value_new_string(blob_buffer(&sql),strlen(blob_buffer(&sql))); |
| 550 | SET("timelineSql"); |
| 551 | #endif |
| 552 | db_multi_exec("%s", blob_buffer(&sql) /*safe-for-%s*/); |
| 553 | blob_reset(&sql); |
| 554 | db_prepare(&q, "SELECT" |
| 555 | " uuid AS uuid," |
| 556 |
| --- src/json_timeline.c | |
| +++ src/json_timeline.c | |
| @@ -88,20 +88,21 @@ | |
| 88 | db_multi_exec("%s", zSql /*safe-for-%s*/); |
| 89 | } |
| 90 | |
| 91 | /* |
| 92 | ** Return a pointer to a constant string that forms the basis |
| 93 | ** for a timeline query for the JSON interface. It MUST NOT |
| 94 | ** be used in a formatted string argument. |
| 95 | */ |
| 96 | char const * json_timeline_query(void){ |
| 97 | /* Field order MUST match that from json_timeline_temp_table()!!! */ |
| 98 | static const char zBaseSql[] = |
| 99 | @ SELECT |
| 100 | @ NULL, |
| 101 | @ blob.rid, |
| 102 | @ uuid, |
| 103 | @ CAST(strftime('%s',event.mtime) AS INTEGER), |
| 104 | @ datetime(event.mtime), |
| 105 | @ coalesce(ecomment, comment), |
| 106 | @ coalesce(euser, user), |
| 107 | @ blob.rid IN leaf, |
| 108 | @ bgcolor, |
| @@ -544,12 +545,11 @@ | |
| 545 | goto error; |
| 546 | } |
| 547 | |
| 548 | #if 0 |
| 549 | /* only for testing! */ |
| 550 | cson_object_set(pay, "timelineSql", cson_value_new_string(blob_buffer(&sql),strlen(blob_buffer(&sql)))); |
| 551 | #endif |
| 552 | db_multi_exec("%s", blob_buffer(&sql) /*safe-for-%s*/); |
| 553 | blob_reset(&sql); |
| 554 | db_prepare(&q, "SELECT" |
| 555 | " uuid AS uuid," |
| 556 |
+48
| --- src/main.mk | ||
| +++ src/main.mk | ||
| @@ -21,10 +21,11 @@ | ||
| 21 | 21 | $(SRCDIR)/bisect.c \ |
| 22 | 22 | $(SRCDIR)/blob.c \ |
| 23 | 23 | $(SRCDIR)/branch.c \ |
| 24 | 24 | $(SRCDIR)/browse.c \ |
| 25 | 25 | $(SRCDIR)/builtin.c \ |
| 26 | + $(SRCDIR)/bundle.c \ | |
| 26 | 27 | $(SRCDIR)/cache.c \ |
| 27 | 28 | $(SRCDIR)/captcha.c \ |
| 28 | 29 | $(SRCDIR)/cgi.c \ |
| 29 | 30 | $(SRCDIR)/checkin.c \ |
| 30 | 31 | $(SRCDIR)/checkout.c \ |
| @@ -87,19 +88,22 @@ | ||
| 87 | 88 | $(SRCDIR)/path.c \ |
| 88 | 89 | $(SRCDIR)/pivot.c \ |
| 89 | 90 | $(SRCDIR)/popen.c \ |
| 90 | 91 | $(SRCDIR)/pqueue.c \ |
| 91 | 92 | $(SRCDIR)/printf.c \ |
| 93 | + $(SRCDIR)/publish.c \ | |
| 94 | + $(SRCDIR)/purge.c \ | |
| 92 | 95 | $(SRCDIR)/rebuild.c \ |
| 93 | 96 | $(SRCDIR)/regexp.c \ |
| 94 | 97 | $(SRCDIR)/report.c \ |
| 95 | 98 | $(SRCDIR)/rss.c \ |
| 96 | 99 | $(SRCDIR)/schema.c \ |
| 97 | 100 | $(SRCDIR)/search.c \ |
| 98 | 101 | $(SRCDIR)/setup.c \ |
| 99 | 102 | $(SRCDIR)/sha1.c \ |
| 100 | 103 | $(SRCDIR)/shun.c \ |
| 104 | + $(SRCDIR)/sitemap.c \ | |
| 101 | 105 | $(SRCDIR)/skins.c \ |
| 102 | 106 | $(SRCDIR)/sqlcmd.c \ |
| 103 | 107 | $(SRCDIR)/stash.c \ |
| 104 | 108 | $(SRCDIR)/stat.c \ |
| 105 | 109 | $(SRCDIR)/style.c \ |
| @@ -139,10 +143,11 @@ | ||
| 139 | 143 | $(OBJDIR)/bisect_.c \ |
| 140 | 144 | $(OBJDIR)/blob_.c \ |
| 141 | 145 | $(OBJDIR)/branch_.c \ |
| 142 | 146 | $(OBJDIR)/browse_.c \ |
| 143 | 147 | $(OBJDIR)/builtin_.c \ |
| 148 | + $(OBJDIR)/bundle_.c \ | |
| 144 | 149 | $(OBJDIR)/cache_.c \ |
| 145 | 150 | $(OBJDIR)/captcha_.c \ |
| 146 | 151 | $(OBJDIR)/cgi_.c \ |
| 147 | 152 | $(OBJDIR)/checkin_.c \ |
| 148 | 153 | $(OBJDIR)/checkout_.c \ |
| @@ -205,19 +210,22 @@ | ||
| 205 | 210 | $(OBJDIR)/path_.c \ |
| 206 | 211 | $(OBJDIR)/pivot_.c \ |
| 207 | 212 | $(OBJDIR)/popen_.c \ |
| 208 | 213 | $(OBJDIR)/pqueue_.c \ |
| 209 | 214 | $(OBJDIR)/printf_.c \ |
| 215 | + $(OBJDIR)/publish_.c \ | |
| 216 | + $(OBJDIR)/purge_.c \ | |
| 210 | 217 | $(OBJDIR)/rebuild_.c \ |
| 211 | 218 | $(OBJDIR)/regexp_.c \ |
| 212 | 219 | $(OBJDIR)/report_.c \ |
| 213 | 220 | $(OBJDIR)/rss_.c \ |
| 214 | 221 | $(OBJDIR)/schema_.c \ |
| 215 | 222 | $(OBJDIR)/search_.c \ |
| 216 | 223 | $(OBJDIR)/setup_.c \ |
| 217 | 224 | $(OBJDIR)/sha1_.c \ |
| 218 | 225 | $(OBJDIR)/shun_.c \ |
| 226 | + $(OBJDIR)/sitemap_.c \ | |
| 219 | 227 | $(OBJDIR)/skins_.c \ |
| 220 | 228 | $(OBJDIR)/sqlcmd_.c \ |
| 221 | 229 | $(OBJDIR)/stash_.c \ |
| 222 | 230 | $(OBJDIR)/stat_.c \ |
| 223 | 231 | $(OBJDIR)/style_.c \ |
| @@ -254,10 +262,11 @@ | ||
| 254 | 262 | $(OBJDIR)/bisect.o \ |
| 255 | 263 | $(OBJDIR)/blob.o \ |
| 256 | 264 | $(OBJDIR)/branch.o \ |
| 257 | 265 | $(OBJDIR)/browse.o \ |
| 258 | 266 | $(OBJDIR)/builtin.o \ |
| 267 | + $(OBJDIR)/bundle.o \ | |
| 259 | 268 | $(OBJDIR)/cache.o \ |
| 260 | 269 | $(OBJDIR)/captcha.o \ |
| 261 | 270 | $(OBJDIR)/cgi.o \ |
| 262 | 271 | $(OBJDIR)/checkin.o \ |
| 263 | 272 | $(OBJDIR)/checkout.o \ |
| @@ -320,19 +329,22 @@ | ||
| 320 | 329 | $(OBJDIR)/path.o \ |
| 321 | 330 | $(OBJDIR)/pivot.o \ |
| 322 | 331 | $(OBJDIR)/popen.o \ |
| 323 | 332 | $(OBJDIR)/pqueue.o \ |
| 324 | 333 | $(OBJDIR)/printf.o \ |
| 334 | + $(OBJDIR)/publish.o \ | |
| 335 | + $(OBJDIR)/purge.o \ | |
| 325 | 336 | $(OBJDIR)/rebuild.o \ |
| 326 | 337 | $(OBJDIR)/regexp.o \ |
| 327 | 338 | $(OBJDIR)/report.o \ |
| 328 | 339 | $(OBJDIR)/rss.o \ |
| 329 | 340 | $(OBJDIR)/schema.o \ |
| 330 | 341 | $(OBJDIR)/search.o \ |
| 331 | 342 | $(OBJDIR)/setup.o \ |
| 332 | 343 | $(OBJDIR)/sha1.o \ |
| 333 | 344 | $(OBJDIR)/shun.o \ |
| 345 | + $(OBJDIR)/sitemap.o \ | |
| 334 | 346 | $(OBJDIR)/skins.o \ |
| 335 | 347 | $(OBJDIR)/sqlcmd.o \ |
| 336 | 348 | $(OBJDIR)/stash.o \ |
| 337 | 349 | $(OBJDIR)/stat.o \ |
| 338 | 350 | $(OBJDIR)/style.o \ |
| @@ -478,10 +490,11 @@ | ||
| 478 | 490 | $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h \ |
| 479 | 491 | $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h \ |
| 480 | 492 | $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h \ |
| 481 | 493 | $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h \ |
| 482 | 494 | $(OBJDIR)/builtin_.c:$(OBJDIR)/builtin.h \ |
| 495 | + $(OBJDIR)/bundle_.c:$(OBJDIR)/bundle.h \ | |
| 483 | 496 | $(OBJDIR)/cache_.c:$(OBJDIR)/cache.h \ |
| 484 | 497 | $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h \ |
| 485 | 498 | $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h \ |
| 486 | 499 | $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h \ |
| 487 | 500 | $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h \ |
| @@ -544,19 +557,22 @@ | ||
| 544 | 557 | $(OBJDIR)/path_.c:$(OBJDIR)/path.h \ |
| 545 | 558 | $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \ |
| 546 | 559 | $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \ |
| 547 | 560 | $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \ |
| 548 | 561 | $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \ |
| 562 | + $(OBJDIR)/publish_.c:$(OBJDIR)/publish.h \ | |
| 563 | + $(OBJDIR)/purge_.c:$(OBJDIR)/purge.h \ | |
| 549 | 564 | $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h \ |
| 550 | 565 | $(OBJDIR)/regexp_.c:$(OBJDIR)/regexp.h \ |
| 551 | 566 | $(OBJDIR)/report_.c:$(OBJDIR)/report.h \ |
| 552 | 567 | $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \ |
| 553 | 568 | $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \ |
| 554 | 569 | $(OBJDIR)/search_.c:$(OBJDIR)/search.h \ |
| 555 | 570 | $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \ |
| 556 | 571 | $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \ |
| 557 | 572 | $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \ |
| 573 | + $(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \ | |
| 558 | 574 | $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \ |
| 559 | 575 | $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \ |
| 560 | 576 | $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \ |
| 561 | 577 | $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h \ |
| 562 | 578 | $(OBJDIR)/style_.c:$(OBJDIR)/style.h \ |
| @@ -660,10 +676,18 @@ | ||
| 660 | 676 | |
| 661 | 677 | $(OBJDIR)/builtin.o: $(OBJDIR)/builtin_.c $(OBJDIR)/builtin.h $(OBJDIR)/builtin_data.h $(SRCDIR)/config.h |
| 662 | 678 | $(XTCC) -o $(OBJDIR)/builtin.o -c $(OBJDIR)/builtin_.c |
| 663 | 679 | |
| 664 | 680 | $(OBJDIR)/builtin.h: $(OBJDIR)/headers |
| 681 | + | |
| 682 | +$(OBJDIR)/bundle_.c: $(SRCDIR)/bundle.c $(OBJDIR)/translate | |
| 683 | + $(OBJDIR)/translate $(SRCDIR)/bundle.c >$@ | |
| 684 | + | |
| 685 | +$(OBJDIR)/bundle.o: $(OBJDIR)/bundle_.c $(OBJDIR)/bundle.h $(SRCDIR)/config.h | |
| 686 | + $(XTCC) -o $(OBJDIR)/bundle.o -c $(OBJDIR)/bundle_.c | |
| 687 | + | |
| 688 | +$(OBJDIR)/bundle.h: $(OBJDIR)/headers | |
| 665 | 689 | |
| 666 | 690 | $(OBJDIR)/cache_.c: $(SRCDIR)/cache.c $(OBJDIR)/translate |
| 667 | 691 | $(OBJDIR)/translate $(SRCDIR)/cache.c >$@ |
| 668 | 692 | |
| 669 | 693 | $(OBJDIR)/cache.o: $(OBJDIR)/cache_.c $(OBJDIR)/cache.h $(SRCDIR)/config.h |
| @@ -1188,10 +1212,26 @@ | ||
| 1188 | 1212 | |
| 1189 | 1213 | $(OBJDIR)/printf.o: $(OBJDIR)/printf_.c $(OBJDIR)/printf.h $(SRCDIR)/config.h |
| 1190 | 1214 | $(XTCC) -o $(OBJDIR)/printf.o -c $(OBJDIR)/printf_.c |
| 1191 | 1215 | |
| 1192 | 1216 | $(OBJDIR)/printf.h: $(OBJDIR)/headers |
| 1217 | + | |
| 1218 | +$(OBJDIR)/publish_.c: $(SRCDIR)/publish.c $(OBJDIR)/translate | |
| 1219 | + $(OBJDIR)/translate $(SRCDIR)/publish.c >$@ | |
| 1220 | + | |
| 1221 | +$(OBJDIR)/publish.o: $(OBJDIR)/publish_.c $(OBJDIR)/publish.h $(SRCDIR)/config.h | |
| 1222 | + $(XTCC) -o $(OBJDIR)/publish.o -c $(OBJDIR)/publish_.c | |
| 1223 | + | |
| 1224 | +$(OBJDIR)/publish.h: $(OBJDIR)/headers | |
| 1225 | + | |
| 1226 | +$(OBJDIR)/purge_.c: $(SRCDIR)/purge.c $(OBJDIR)/translate | |
| 1227 | + $(OBJDIR)/translate $(SRCDIR)/purge.c >$@ | |
| 1228 | + | |
| 1229 | +$(OBJDIR)/purge.o: $(OBJDIR)/purge_.c $(OBJDIR)/purge.h $(SRCDIR)/config.h | |
| 1230 | + $(XTCC) -o $(OBJDIR)/purge.o -c $(OBJDIR)/purge_.c | |
| 1231 | + | |
| 1232 | +$(OBJDIR)/purge.h: $(OBJDIR)/headers | |
| 1193 | 1233 | |
| 1194 | 1234 | $(OBJDIR)/rebuild_.c: $(SRCDIR)/rebuild.c $(OBJDIR)/translate |
| 1195 | 1235 | $(OBJDIR)/translate $(SRCDIR)/rebuild.c >$@ |
| 1196 | 1236 | |
| 1197 | 1237 | $(OBJDIR)/rebuild.o: $(OBJDIR)/rebuild_.c $(OBJDIR)/rebuild.h $(SRCDIR)/config.h |
| @@ -1260,10 +1300,18 @@ | ||
| 1260 | 1300 | |
| 1261 | 1301 | $(OBJDIR)/shun.o: $(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h |
| 1262 | 1302 | $(XTCC) -o $(OBJDIR)/shun.o -c $(OBJDIR)/shun_.c |
| 1263 | 1303 | |
| 1264 | 1304 | $(OBJDIR)/shun.h: $(OBJDIR)/headers |
| 1305 | + | |
| 1306 | +$(OBJDIR)/sitemap_.c: $(SRCDIR)/sitemap.c $(OBJDIR)/translate | |
| 1307 | + $(OBJDIR)/translate $(SRCDIR)/sitemap.c >$@ | |
| 1308 | + | |
| 1309 | +$(OBJDIR)/sitemap.o: $(OBJDIR)/sitemap_.c $(OBJDIR)/sitemap.h $(SRCDIR)/config.h | |
| 1310 | + $(XTCC) -o $(OBJDIR)/sitemap.o -c $(OBJDIR)/sitemap_.c | |
| 1311 | + | |
| 1312 | +$(OBJDIR)/sitemap.h: $(OBJDIR)/headers | |
| 1265 | 1313 | |
| 1266 | 1314 | $(OBJDIR)/skins_.c: $(SRCDIR)/skins.c $(OBJDIR)/translate |
| 1267 | 1315 | $(OBJDIR)/translate $(SRCDIR)/skins.c >$@ |
| 1268 | 1316 | |
| 1269 | 1317 | $(OBJDIR)/skins.o: $(OBJDIR)/skins_.c $(OBJDIR)/skins.h $(SRCDIR)/config.h |
| 1270 | 1318 |
| --- src/main.mk | |
| +++ src/main.mk | |
| @@ -21,10 +21,11 @@ | |
| 21 | $(SRCDIR)/bisect.c \ |
| 22 | $(SRCDIR)/blob.c \ |
| 23 | $(SRCDIR)/branch.c \ |
| 24 | $(SRCDIR)/browse.c \ |
| 25 | $(SRCDIR)/builtin.c \ |
| 26 | $(SRCDIR)/cache.c \ |
| 27 | $(SRCDIR)/captcha.c \ |
| 28 | $(SRCDIR)/cgi.c \ |
| 29 | $(SRCDIR)/checkin.c \ |
| 30 | $(SRCDIR)/checkout.c \ |
| @@ -87,19 +88,22 @@ | |
| 87 | $(SRCDIR)/path.c \ |
| 88 | $(SRCDIR)/pivot.c \ |
| 89 | $(SRCDIR)/popen.c \ |
| 90 | $(SRCDIR)/pqueue.c \ |
| 91 | $(SRCDIR)/printf.c \ |
| 92 | $(SRCDIR)/rebuild.c \ |
| 93 | $(SRCDIR)/regexp.c \ |
| 94 | $(SRCDIR)/report.c \ |
| 95 | $(SRCDIR)/rss.c \ |
| 96 | $(SRCDIR)/schema.c \ |
| 97 | $(SRCDIR)/search.c \ |
| 98 | $(SRCDIR)/setup.c \ |
| 99 | $(SRCDIR)/sha1.c \ |
| 100 | $(SRCDIR)/shun.c \ |
| 101 | $(SRCDIR)/skins.c \ |
| 102 | $(SRCDIR)/sqlcmd.c \ |
| 103 | $(SRCDIR)/stash.c \ |
| 104 | $(SRCDIR)/stat.c \ |
| 105 | $(SRCDIR)/style.c \ |
| @@ -139,10 +143,11 @@ | |
| 139 | $(OBJDIR)/bisect_.c \ |
| 140 | $(OBJDIR)/blob_.c \ |
| 141 | $(OBJDIR)/branch_.c \ |
| 142 | $(OBJDIR)/browse_.c \ |
| 143 | $(OBJDIR)/builtin_.c \ |
| 144 | $(OBJDIR)/cache_.c \ |
| 145 | $(OBJDIR)/captcha_.c \ |
| 146 | $(OBJDIR)/cgi_.c \ |
| 147 | $(OBJDIR)/checkin_.c \ |
| 148 | $(OBJDIR)/checkout_.c \ |
| @@ -205,19 +210,22 @@ | |
| 205 | $(OBJDIR)/path_.c \ |
| 206 | $(OBJDIR)/pivot_.c \ |
| 207 | $(OBJDIR)/popen_.c \ |
| 208 | $(OBJDIR)/pqueue_.c \ |
| 209 | $(OBJDIR)/printf_.c \ |
| 210 | $(OBJDIR)/rebuild_.c \ |
| 211 | $(OBJDIR)/regexp_.c \ |
| 212 | $(OBJDIR)/report_.c \ |
| 213 | $(OBJDIR)/rss_.c \ |
| 214 | $(OBJDIR)/schema_.c \ |
| 215 | $(OBJDIR)/search_.c \ |
| 216 | $(OBJDIR)/setup_.c \ |
| 217 | $(OBJDIR)/sha1_.c \ |
| 218 | $(OBJDIR)/shun_.c \ |
| 219 | $(OBJDIR)/skins_.c \ |
| 220 | $(OBJDIR)/sqlcmd_.c \ |
| 221 | $(OBJDIR)/stash_.c \ |
| 222 | $(OBJDIR)/stat_.c \ |
| 223 | $(OBJDIR)/style_.c \ |
| @@ -254,10 +262,11 @@ | |
| 254 | $(OBJDIR)/bisect.o \ |
| 255 | $(OBJDIR)/blob.o \ |
| 256 | $(OBJDIR)/branch.o \ |
| 257 | $(OBJDIR)/browse.o \ |
| 258 | $(OBJDIR)/builtin.o \ |
| 259 | $(OBJDIR)/cache.o \ |
| 260 | $(OBJDIR)/captcha.o \ |
| 261 | $(OBJDIR)/cgi.o \ |
| 262 | $(OBJDIR)/checkin.o \ |
| 263 | $(OBJDIR)/checkout.o \ |
| @@ -320,19 +329,22 @@ | |
| 320 | $(OBJDIR)/path.o \ |
| 321 | $(OBJDIR)/pivot.o \ |
| 322 | $(OBJDIR)/popen.o \ |
| 323 | $(OBJDIR)/pqueue.o \ |
| 324 | $(OBJDIR)/printf.o \ |
| 325 | $(OBJDIR)/rebuild.o \ |
| 326 | $(OBJDIR)/regexp.o \ |
| 327 | $(OBJDIR)/report.o \ |
| 328 | $(OBJDIR)/rss.o \ |
| 329 | $(OBJDIR)/schema.o \ |
| 330 | $(OBJDIR)/search.o \ |
| 331 | $(OBJDIR)/setup.o \ |
| 332 | $(OBJDIR)/sha1.o \ |
| 333 | $(OBJDIR)/shun.o \ |
| 334 | $(OBJDIR)/skins.o \ |
| 335 | $(OBJDIR)/sqlcmd.o \ |
| 336 | $(OBJDIR)/stash.o \ |
| 337 | $(OBJDIR)/stat.o \ |
| 338 | $(OBJDIR)/style.o \ |
| @@ -478,10 +490,11 @@ | |
| 478 | $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h \ |
| 479 | $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h \ |
| 480 | $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h \ |
| 481 | $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h \ |
| 482 | $(OBJDIR)/builtin_.c:$(OBJDIR)/builtin.h \ |
| 483 | $(OBJDIR)/cache_.c:$(OBJDIR)/cache.h \ |
| 484 | $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h \ |
| 485 | $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h \ |
| 486 | $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h \ |
| 487 | $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h \ |
| @@ -544,19 +557,22 @@ | |
| 544 | $(OBJDIR)/path_.c:$(OBJDIR)/path.h \ |
| 545 | $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \ |
| 546 | $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \ |
| 547 | $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \ |
| 548 | $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \ |
| 549 | $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h \ |
| 550 | $(OBJDIR)/regexp_.c:$(OBJDIR)/regexp.h \ |
| 551 | $(OBJDIR)/report_.c:$(OBJDIR)/report.h \ |
| 552 | $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \ |
| 553 | $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \ |
| 554 | $(OBJDIR)/search_.c:$(OBJDIR)/search.h \ |
| 555 | $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \ |
| 556 | $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \ |
| 557 | $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \ |
| 558 | $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \ |
| 559 | $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \ |
| 560 | $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \ |
| 561 | $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h \ |
| 562 | $(OBJDIR)/style_.c:$(OBJDIR)/style.h \ |
| @@ -660,10 +676,18 @@ | |
| 660 | |
| 661 | $(OBJDIR)/builtin.o: $(OBJDIR)/builtin_.c $(OBJDIR)/builtin.h $(OBJDIR)/builtin_data.h $(SRCDIR)/config.h |
| 662 | $(XTCC) -o $(OBJDIR)/builtin.o -c $(OBJDIR)/builtin_.c |
| 663 | |
| 664 | $(OBJDIR)/builtin.h: $(OBJDIR)/headers |
| 665 | |
| 666 | $(OBJDIR)/cache_.c: $(SRCDIR)/cache.c $(OBJDIR)/translate |
| 667 | $(OBJDIR)/translate $(SRCDIR)/cache.c >$@ |
| 668 | |
| 669 | $(OBJDIR)/cache.o: $(OBJDIR)/cache_.c $(OBJDIR)/cache.h $(SRCDIR)/config.h |
| @@ -1188,10 +1212,26 @@ | |
| 1188 | |
| 1189 | $(OBJDIR)/printf.o: $(OBJDIR)/printf_.c $(OBJDIR)/printf.h $(SRCDIR)/config.h |
| 1190 | $(XTCC) -o $(OBJDIR)/printf.o -c $(OBJDIR)/printf_.c |
| 1191 | |
| 1192 | $(OBJDIR)/printf.h: $(OBJDIR)/headers |
| 1193 | |
| 1194 | $(OBJDIR)/rebuild_.c: $(SRCDIR)/rebuild.c $(OBJDIR)/translate |
| 1195 | $(OBJDIR)/translate $(SRCDIR)/rebuild.c >$@ |
| 1196 | |
| 1197 | $(OBJDIR)/rebuild.o: $(OBJDIR)/rebuild_.c $(OBJDIR)/rebuild.h $(SRCDIR)/config.h |
| @@ -1260,10 +1300,18 @@ | |
| 1260 | |
| 1261 | $(OBJDIR)/shun.o: $(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h |
| 1262 | $(XTCC) -o $(OBJDIR)/shun.o -c $(OBJDIR)/shun_.c |
| 1263 | |
| 1264 | $(OBJDIR)/shun.h: $(OBJDIR)/headers |
| 1265 | |
| 1266 | $(OBJDIR)/skins_.c: $(SRCDIR)/skins.c $(OBJDIR)/translate |
| 1267 | $(OBJDIR)/translate $(SRCDIR)/skins.c >$@ |
| 1268 | |
| 1269 | $(OBJDIR)/skins.o: $(OBJDIR)/skins_.c $(OBJDIR)/skins.h $(SRCDIR)/config.h |
| 1270 |
| --- src/main.mk | |
| +++ src/main.mk | |
| @@ -21,10 +21,11 @@ | |
| 21 | $(SRCDIR)/bisect.c \ |
| 22 | $(SRCDIR)/blob.c \ |
| 23 | $(SRCDIR)/branch.c \ |
| 24 | $(SRCDIR)/browse.c \ |
| 25 | $(SRCDIR)/builtin.c \ |
| 26 | $(SRCDIR)/bundle.c \ |
| 27 | $(SRCDIR)/cache.c \ |
| 28 | $(SRCDIR)/captcha.c \ |
| 29 | $(SRCDIR)/cgi.c \ |
| 30 | $(SRCDIR)/checkin.c \ |
| 31 | $(SRCDIR)/checkout.c \ |
| @@ -87,19 +88,22 @@ | |
| 88 | $(SRCDIR)/path.c \ |
| 89 | $(SRCDIR)/pivot.c \ |
| 90 | $(SRCDIR)/popen.c \ |
| 91 | $(SRCDIR)/pqueue.c \ |
| 92 | $(SRCDIR)/printf.c \ |
| 93 | $(SRCDIR)/publish.c \ |
| 94 | $(SRCDIR)/purge.c \ |
| 95 | $(SRCDIR)/rebuild.c \ |
| 96 | $(SRCDIR)/regexp.c \ |
| 97 | $(SRCDIR)/report.c \ |
| 98 | $(SRCDIR)/rss.c \ |
| 99 | $(SRCDIR)/schema.c \ |
| 100 | $(SRCDIR)/search.c \ |
| 101 | $(SRCDIR)/setup.c \ |
| 102 | $(SRCDIR)/sha1.c \ |
| 103 | $(SRCDIR)/shun.c \ |
| 104 | $(SRCDIR)/sitemap.c \ |
| 105 | $(SRCDIR)/skins.c \ |
| 106 | $(SRCDIR)/sqlcmd.c \ |
| 107 | $(SRCDIR)/stash.c \ |
| 108 | $(SRCDIR)/stat.c \ |
| 109 | $(SRCDIR)/style.c \ |
| @@ -139,10 +143,11 @@ | |
| 143 | $(OBJDIR)/bisect_.c \ |
| 144 | $(OBJDIR)/blob_.c \ |
| 145 | $(OBJDIR)/branch_.c \ |
| 146 | $(OBJDIR)/browse_.c \ |
| 147 | $(OBJDIR)/builtin_.c \ |
| 148 | $(OBJDIR)/bundle_.c \ |
| 149 | $(OBJDIR)/cache_.c \ |
| 150 | $(OBJDIR)/captcha_.c \ |
| 151 | $(OBJDIR)/cgi_.c \ |
| 152 | $(OBJDIR)/checkin_.c \ |
| 153 | $(OBJDIR)/checkout_.c \ |
| @@ -205,19 +210,22 @@ | |
| 210 | $(OBJDIR)/path_.c \ |
| 211 | $(OBJDIR)/pivot_.c \ |
| 212 | $(OBJDIR)/popen_.c \ |
| 213 | $(OBJDIR)/pqueue_.c \ |
| 214 | $(OBJDIR)/printf_.c \ |
| 215 | $(OBJDIR)/publish_.c \ |
| 216 | $(OBJDIR)/purge_.c \ |
| 217 | $(OBJDIR)/rebuild_.c \ |
| 218 | $(OBJDIR)/regexp_.c \ |
| 219 | $(OBJDIR)/report_.c \ |
| 220 | $(OBJDIR)/rss_.c \ |
| 221 | $(OBJDIR)/schema_.c \ |
| 222 | $(OBJDIR)/search_.c \ |
| 223 | $(OBJDIR)/setup_.c \ |
| 224 | $(OBJDIR)/sha1_.c \ |
| 225 | $(OBJDIR)/shun_.c \ |
| 226 | $(OBJDIR)/sitemap_.c \ |
| 227 | $(OBJDIR)/skins_.c \ |
| 228 | $(OBJDIR)/sqlcmd_.c \ |
| 229 | $(OBJDIR)/stash_.c \ |
| 230 | $(OBJDIR)/stat_.c \ |
| 231 | $(OBJDIR)/style_.c \ |
| @@ -254,10 +262,11 @@ | |
| 262 | $(OBJDIR)/bisect.o \ |
| 263 | $(OBJDIR)/blob.o \ |
| 264 | $(OBJDIR)/branch.o \ |
| 265 | $(OBJDIR)/browse.o \ |
| 266 | $(OBJDIR)/builtin.o \ |
| 267 | $(OBJDIR)/bundle.o \ |
| 268 | $(OBJDIR)/cache.o \ |
| 269 | $(OBJDIR)/captcha.o \ |
| 270 | $(OBJDIR)/cgi.o \ |
| 271 | $(OBJDIR)/checkin.o \ |
| 272 | $(OBJDIR)/checkout.o \ |
| @@ -320,19 +329,22 @@ | |
| 329 | $(OBJDIR)/path.o \ |
| 330 | $(OBJDIR)/pivot.o \ |
| 331 | $(OBJDIR)/popen.o \ |
| 332 | $(OBJDIR)/pqueue.o \ |
| 333 | $(OBJDIR)/printf.o \ |
| 334 | $(OBJDIR)/publish.o \ |
| 335 | $(OBJDIR)/purge.o \ |
| 336 | $(OBJDIR)/rebuild.o \ |
| 337 | $(OBJDIR)/regexp.o \ |
| 338 | $(OBJDIR)/report.o \ |
| 339 | $(OBJDIR)/rss.o \ |
| 340 | $(OBJDIR)/schema.o \ |
| 341 | $(OBJDIR)/search.o \ |
| 342 | $(OBJDIR)/setup.o \ |
| 343 | $(OBJDIR)/sha1.o \ |
| 344 | $(OBJDIR)/shun.o \ |
| 345 | $(OBJDIR)/sitemap.o \ |
| 346 | $(OBJDIR)/skins.o \ |
| 347 | $(OBJDIR)/sqlcmd.o \ |
| 348 | $(OBJDIR)/stash.o \ |
| 349 | $(OBJDIR)/stat.o \ |
| 350 | $(OBJDIR)/style.o \ |
| @@ -478,10 +490,11 @@ | |
| 490 | $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h \ |
| 491 | $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h \ |
| 492 | $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h \ |
| 493 | $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h \ |
| 494 | $(OBJDIR)/builtin_.c:$(OBJDIR)/builtin.h \ |
| 495 | $(OBJDIR)/bundle_.c:$(OBJDIR)/bundle.h \ |
| 496 | $(OBJDIR)/cache_.c:$(OBJDIR)/cache.h \ |
| 497 | $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h \ |
| 498 | $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h \ |
| 499 | $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h \ |
| 500 | $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h \ |
| @@ -544,19 +557,22 @@ | |
| 557 | $(OBJDIR)/path_.c:$(OBJDIR)/path.h \ |
| 558 | $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \ |
| 559 | $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \ |
| 560 | $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \ |
| 561 | $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \ |
| 562 | $(OBJDIR)/publish_.c:$(OBJDIR)/publish.h \ |
| 563 | $(OBJDIR)/purge_.c:$(OBJDIR)/purge.h \ |
| 564 | $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h \ |
| 565 | $(OBJDIR)/regexp_.c:$(OBJDIR)/regexp.h \ |
| 566 | $(OBJDIR)/report_.c:$(OBJDIR)/report.h \ |
| 567 | $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \ |
| 568 | $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \ |
| 569 | $(OBJDIR)/search_.c:$(OBJDIR)/search.h \ |
| 570 | $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \ |
| 571 | $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \ |
| 572 | $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \ |
| 573 | $(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \ |
| 574 | $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \ |
| 575 | $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \ |
| 576 | $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \ |
| 577 | $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h \ |
| 578 | $(OBJDIR)/style_.c:$(OBJDIR)/style.h \ |
| @@ -660,10 +676,18 @@ | |
| 676 | |
| 677 | $(OBJDIR)/builtin.o: $(OBJDIR)/builtin_.c $(OBJDIR)/builtin.h $(OBJDIR)/builtin_data.h $(SRCDIR)/config.h |
| 678 | $(XTCC) -o $(OBJDIR)/builtin.o -c $(OBJDIR)/builtin_.c |
| 679 | |
| 680 | $(OBJDIR)/builtin.h: $(OBJDIR)/headers |
| 681 | |
| 682 | $(OBJDIR)/bundle_.c: $(SRCDIR)/bundle.c $(OBJDIR)/translate |
| 683 | $(OBJDIR)/translate $(SRCDIR)/bundle.c >$@ |
| 684 | |
| 685 | $(OBJDIR)/bundle.o: $(OBJDIR)/bundle_.c $(OBJDIR)/bundle.h $(SRCDIR)/config.h |
| 686 | $(XTCC) -o $(OBJDIR)/bundle.o -c $(OBJDIR)/bundle_.c |
| 687 | |
| 688 | $(OBJDIR)/bundle.h: $(OBJDIR)/headers |
| 689 | |
| 690 | $(OBJDIR)/cache_.c: $(SRCDIR)/cache.c $(OBJDIR)/translate |
| 691 | $(OBJDIR)/translate $(SRCDIR)/cache.c >$@ |
| 692 | |
| 693 | $(OBJDIR)/cache.o: $(OBJDIR)/cache_.c $(OBJDIR)/cache.h $(SRCDIR)/config.h |
| @@ -1188,10 +1212,26 @@ | |
| 1212 | |
| 1213 | $(OBJDIR)/printf.o: $(OBJDIR)/printf_.c $(OBJDIR)/printf.h $(SRCDIR)/config.h |
| 1214 | $(XTCC) -o $(OBJDIR)/printf.o -c $(OBJDIR)/printf_.c |
| 1215 | |
| 1216 | $(OBJDIR)/printf.h: $(OBJDIR)/headers |
| 1217 | |
| 1218 | $(OBJDIR)/publish_.c: $(SRCDIR)/publish.c $(OBJDIR)/translate |
| 1219 | $(OBJDIR)/translate $(SRCDIR)/publish.c >$@ |
| 1220 | |
| 1221 | $(OBJDIR)/publish.o: $(OBJDIR)/publish_.c $(OBJDIR)/publish.h $(SRCDIR)/config.h |
| 1222 | $(XTCC) -o $(OBJDIR)/publish.o -c $(OBJDIR)/publish_.c |
| 1223 | |
| 1224 | $(OBJDIR)/publish.h: $(OBJDIR)/headers |
| 1225 | |
| 1226 | $(OBJDIR)/purge_.c: $(SRCDIR)/purge.c $(OBJDIR)/translate |
| 1227 | $(OBJDIR)/translate $(SRCDIR)/purge.c >$@ |
| 1228 | |
| 1229 | $(OBJDIR)/purge.o: $(OBJDIR)/purge_.c $(OBJDIR)/purge.h $(SRCDIR)/config.h |
| 1230 | $(XTCC) -o $(OBJDIR)/purge.o -c $(OBJDIR)/purge_.c |
| 1231 | |
| 1232 | $(OBJDIR)/purge.h: $(OBJDIR)/headers |
| 1233 | |
| 1234 | $(OBJDIR)/rebuild_.c: $(SRCDIR)/rebuild.c $(OBJDIR)/translate |
| 1235 | $(OBJDIR)/translate $(SRCDIR)/rebuild.c >$@ |
| 1236 | |
| 1237 | $(OBJDIR)/rebuild.o: $(OBJDIR)/rebuild_.c $(OBJDIR)/rebuild.h $(SRCDIR)/config.h |
| @@ -1260,10 +1300,18 @@ | |
| 1300 | |
| 1301 | $(OBJDIR)/shun.o: $(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h |
| 1302 | $(XTCC) -o $(OBJDIR)/shun.o -c $(OBJDIR)/shun_.c |
| 1303 | |
| 1304 | $(OBJDIR)/shun.h: $(OBJDIR)/headers |
| 1305 | |
| 1306 | $(OBJDIR)/sitemap_.c: $(SRCDIR)/sitemap.c $(OBJDIR)/translate |
| 1307 | $(OBJDIR)/translate $(SRCDIR)/sitemap.c >$@ |
| 1308 | |
| 1309 | $(OBJDIR)/sitemap.o: $(OBJDIR)/sitemap_.c $(OBJDIR)/sitemap.h $(SRCDIR)/config.h |
| 1310 | $(XTCC) -o $(OBJDIR)/sitemap.o -c $(OBJDIR)/sitemap_.c |
| 1311 | |
| 1312 | $(OBJDIR)/sitemap.h: $(OBJDIR)/headers |
| 1313 | |
| 1314 | $(OBJDIR)/skins_.c: $(SRCDIR)/skins.c $(OBJDIR)/translate |
| 1315 | $(OBJDIR)/translate $(SRCDIR)/skins.c >$@ |
| 1316 | |
| 1317 | $(OBJDIR)/skins.o: $(OBJDIR)/skins_.c $(OBJDIR)/skins.h $(SRCDIR)/config.h |
| 1318 |
+41
-7
| --- src/makemake.tcl | ||
| +++ src/makemake.tcl | ||
| @@ -28,10 +28,11 @@ | ||
| 28 | 28 | bisect |
| 29 | 29 | blob |
| 30 | 30 | branch |
| 31 | 31 | browse |
| 32 | 32 | builtin |
| 33 | + bundle | |
| 33 | 34 | cache |
| 34 | 35 | captcha |
| 35 | 36 | cgi |
| 36 | 37 | checkin |
| 37 | 38 | checkout |
| @@ -93,19 +94,22 @@ | ||
| 93 | 94 | path |
| 94 | 95 | pivot |
| 95 | 96 | popen |
| 96 | 97 | pqueue |
| 97 | 98 | printf |
| 99 | + publish | |
| 100 | + purge | |
| 98 | 101 | rebuild |
| 99 | 102 | regexp |
| 100 | 103 | report |
| 101 | 104 | rss |
| 102 | 105 | schema |
| 103 | 106 | search |
| 104 | 107 | setup |
| 105 | 108 | sha1 |
| 106 | 109 | shun |
| 110 | + sitemap | |
| 107 | 111 | skins |
| 108 | 112 | sqlcmd |
| 109 | 113 | stash |
| 110 | 114 | stat |
| 111 | 115 | style |
| @@ -510,11 +514,12 @@ | ||
| 510 | 514 | # This is useful when Tcl has been compiled statically with MinGW. |
| 511 | 515 | # |
| 512 | 516 | FOSSIL_TCL_SOURCE = 1 |
| 513 | 517 | |
| 514 | 518 | #### Check if the workaround for the MinGW command line handling needs to |
| 515 | -# be enabled by default. | |
| 519 | +# be enabled by default. This check may be somewhat fragile due to the | |
| 520 | +# use of "findstring". | |
| 516 | 521 | # |
| 517 | 522 | ifndef MINGW_IS_32BIT_ONLY |
| 518 | 523 | ifeq (,$(findstring w64-mingw32,$(PREFIX))) |
| 519 | 524 | MINGW_IS_32BIT_ONLY = 1 |
| 520 | 525 | endif |
| @@ -523,26 +528,46 @@ | ||
| 523 | 528 | #### The directories where the zlib include and library files are located. |
| 524 | 529 | # |
| 525 | 530 | ZINCDIR = $(SRCDIR)/../compat/zlib |
| 526 | 531 | ZLIBDIR = $(SRCDIR)/../compat/zlib |
| 527 | 532 | |
| 533 | +#### Make an attempt to detect if Fossil is being built for the x64 processor | |
| 534 | +# architecture. This check may be somewhat fragile due to "findstring". | |
| 535 | +# | |
| 528 | 536 | ifndef X64 |
| 529 | 537 | ifneq (,$(findstring x86_64-w64-mingw32,$(PREFIX))) |
| 530 | 538 | X64 = 1 |
| 531 | 539 | endif |
| 532 | 540 | endif |
| 533 | 541 | |
| 542 | +#### Determine if the optimized assembly routines provided with zlib should be | |
| 543 | +# used, taking into account whether zlib is actually enabled and the target | |
| 544 | +# processor architecture. | |
| 545 | +# | |
| 534 | 546 | ifndef X64 |
| 535 | 547 | SSLCONFIG = mingw |
| 548 | +ifndef FOSSIL_ENABLE_MINIZ | |
| 536 | 549 | ZLIBCONFIG = LOC="-DASMV -DASMINF" OBJA="inffas86.o match.o" |
| 537 | 550 | LIBTARGETS = $(ZLIBDIR)/inffas86.o $(ZLIBDIR)/match.o |
| 551 | +else | |
| 552 | +ZLIBCONFIG = | |
| 553 | +LIBTARGETS = | |
| 554 | +endif | |
| 538 | 555 | else |
| 539 | 556 | SSLCONFIG = mingw64 |
| 540 | -ZLIBCONFIG = | |
| 557 | +ZLIBCONFIG = | |
| 541 | 558 | LIBTARGETS = |
| 542 | 559 | endif |
| 543 | 560 | |
| 561 | +#### Disable creation of the OpenSSL shared libraries. Also, disable support | |
| 562 | +# for both SSLv2 and SSLv3 (i.e. thereby forcing the use of TLS). | |
| 563 | +# | |
| 564 | +SSLCONFIG += no-ssl2 no-ssl3 no-shared | |
| 565 | + | |
| 566 | +#### When using zlib, make sure that OpenSSL is configured to use the zlib | |
| 567 | +# that Fossil knows about (i.e. the one within the source tree). | |
| 568 | +# | |
| 544 | 569 | ifndef FOSSIL_ENABLE_MINIZ |
| 545 | 570 | SSLCONFIG += --with-zlib-lib=$(PWD)/$(ZLIBDIR) --with-zlib-include=$(PWD)/$(ZLIBDIR) zlib |
| 546 | 571 | endif |
| 547 | 572 | |
| 548 | 573 | #### The directories where the OpenSSL include and library files are located. |
| @@ -1287,23 +1312,32 @@ | ||
| 1287 | 1312 | SSLLIBDIR = $(SSLDIR)\out32 |
| 1288 | 1313 | SSLLFLAGS = /nologo /opt:ref /debug |
| 1289 | 1314 | SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib |
| 1290 | 1315 | !if "$(PLATFORM)"=="amd64" || "$(PLATFORM)"=="x64" |
| 1291 | 1316 | !message Using 'x64' platform for OpenSSL... |
| 1292 | -SSLCONFIG = VC-WIN64A no-asm | |
| 1317 | +# BUGBUG (OpenSSL): Apparently, using "no-ssl*" here breaks the build. | |
| 1318 | +# SSLCONFIG = VC-WIN64A no-asm no-ssl2 no-ssl3 no-shared | |
| 1319 | +SSLCONFIG = VC-WIN64A no-asm no-shared | |
| 1293 | 1320 | SSLSETUP = ms\do_win64a.bat |
| 1294 | 1321 | SSLNMAKE = ms\nt.mak all |
| 1322 | +SSLCFLAGS = -DOPENSSL_NO_SSL2 -DOPENSSL_NO_SSL3 | |
| 1295 | 1323 | !elseif "$(PLATFORM)"=="ia64" |
| 1296 | 1324 | !message Using 'ia64' platform for OpenSSL... |
| 1297 | -SSLCONFIG = VC-WIN64I no-asm | |
| 1325 | +# BUGBUG (OpenSSL): Apparently, using "no-ssl*" here breaks the build. | |
| 1326 | +# SSLCONFIG = VC-WIN64I no-asm no-ssl2 no-ssl3 no-shared | |
| 1327 | +SSLCONFIG = VC-WIN64I no-asm no-shared | |
| 1298 | 1328 | SSLSETUP = ms\do_win64i.bat |
| 1299 | 1329 | SSLNMAKE = ms\nt.mak all |
| 1330 | +SSLCFLAGS = -DOPENSSL_NO_SSL2 -DOPENSSL_NO_SSL3 | |
| 1300 | 1331 | !else |
| 1301 | 1332 | !message Assuming 'x86' platform for OpenSSL... |
| 1302 | -SSLCONFIG = VC-WIN32 no-asm | |
| 1333 | +# BUGBUG (OpenSSL): Apparently, using "no-ssl*" here breaks the build. | |
| 1334 | +# SSLCONFIG = VC-WIN32 no-asm no-ssl2 no-ssl3 no-shared | |
| 1335 | +SSLCONFIG = VC-WIN32 no-asm no-shared | |
| 1303 | 1336 | SSLSETUP = ms\do_ms.bat |
| 1304 | 1337 | SSLNMAKE = ms\nt.mak all |
| 1338 | +SSLCFLAGS = -DOPENSSL_NO_SSL2 -DOPENSSL_NO_SSL3 | |
| 1305 | 1339 | !endif |
| 1306 | 1340 | !endif |
| 1307 | 1341 | |
| 1308 | 1342 | !ifdef FOSSIL_ENABLE_TCL |
| 1309 | 1343 | TCLDIR = $(B)\compat\tcl-8.6 |
| @@ -1472,13 +1506,13 @@ | ||
| 1472 | 1506 | @set PATH=$(PERLDIR);$(PATH) |
| 1473 | 1507 | !endif |
| 1474 | 1508 | @pushd "$(SSLDIR)" && $(PERL) Configure $(SSLCONFIG) && popd |
| 1475 | 1509 | @pushd "$(SSLDIR)" && call $(SSLSETUP) && popd |
| 1476 | 1510 | !ifdef FOSSIL_ENABLE_WINXP |
| 1477 | - @pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) "CC=cl $(XPCFLAGS)" "LFLAGS=$(SSLLFLAGS) $(XPLDFLAGS)" && popd | |
| 1511 | + @pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) "CC=cl $(SSLCFLAGS) $(XPCFLAGS)" "LFLAGS=$(SSLLFLAGS) $(XPLDFLAGS)" && popd | |
| 1478 | 1512 | !else |
| 1479 | - @pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) && popd | |
| 1513 | + @pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) "CC=cl $(SSLCFLAGS)" && popd | |
| 1480 | 1514 | !endif |
| 1481 | 1515 | !endif |
| 1482 | 1516 | |
| 1483 | 1517 | !ifndef FOSSIL_ENABLE_MINIZ |
| 1484 | 1518 | APPTARGETS = $(APPTARGETS) zlib |
| 1485 | 1519 |
| --- src/makemake.tcl | |
| +++ src/makemake.tcl | |
| @@ -28,10 +28,11 @@ | |
| 28 | bisect |
| 29 | blob |
| 30 | branch |
| 31 | browse |
| 32 | builtin |
| 33 | cache |
| 34 | captcha |
| 35 | cgi |
| 36 | checkin |
| 37 | checkout |
| @@ -93,19 +94,22 @@ | |
| 93 | path |
| 94 | pivot |
| 95 | popen |
| 96 | pqueue |
| 97 | printf |
| 98 | rebuild |
| 99 | regexp |
| 100 | report |
| 101 | rss |
| 102 | schema |
| 103 | search |
| 104 | setup |
| 105 | sha1 |
| 106 | shun |
| 107 | skins |
| 108 | sqlcmd |
| 109 | stash |
| 110 | stat |
| 111 | style |
| @@ -510,11 +514,12 @@ | |
| 510 | # This is useful when Tcl has been compiled statically with MinGW. |
| 511 | # |
| 512 | FOSSIL_TCL_SOURCE = 1 |
| 513 | |
| 514 | #### Check if the workaround for the MinGW command line handling needs to |
| 515 | # be enabled by default. |
| 516 | # |
| 517 | ifndef MINGW_IS_32BIT_ONLY |
| 518 | ifeq (,$(findstring w64-mingw32,$(PREFIX))) |
| 519 | MINGW_IS_32BIT_ONLY = 1 |
| 520 | endif |
| @@ -523,26 +528,46 @@ | |
| 523 | #### The directories where the zlib include and library files are located. |
| 524 | # |
| 525 | ZINCDIR = $(SRCDIR)/../compat/zlib |
| 526 | ZLIBDIR = $(SRCDIR)/../compat/zlib |
| 527 | |
| 528 | ifndef X64 |
| 529 | ifneq (,$(findstring x86_64-w64-mingw32,$(PREFIX))) |
| 530 | X64 = 1 |
| 531 | endif |
| 532 | endif |
| 533 | |
| 534 | ifndef X64 |
| 535 | SSLCONFIG = mingw |
| 536 | ZLIBCONFIG = LOC="-DASMV -DASMINF" OBJA="inffas86.o match.o" |
| 537 | LIBTARGETS = $(ZLIBDIR)/inffas86.o $(ZLIBDIR)/match.o |
| 538 | else |
| 539 | SSLCONFIG = mingw64 |
| 540 | ZLIBCONFIG = |
| 541 | LIBTARGETS = |
| 542 | endif |
| 543 | |
| 544 | ifndef FOSSIL_ENABLE_MINIZ |
| 545 | SSLCONFIG += --with-zlib-lib=$(PWD)/$(ZLIBDIR) --with-zlib-include=$(PWD)/$(ZLIBDIR) zlib |
| 546 | endif |
| 547 | |
| 548 | #### The directories where the OpenSSL include and library files are located. |
| @@ -1287,23 +1312,32 @@ | |
| 1287 | SSLLIBDIR = $(SSLDIR)\out32 |
| 1288 | SSLLFLAGS = /nologo /opt:ref /debug |
| 1289 | SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib |
| 1290 | !if "$(PLATFORM)"=="amd64" || "$(PLATFORM)"=="x64" |
| 1291 | !message Using 'x64' platform for OpenSSL... |
| 1292 | SSLCONFIG = VC-WIN64A no-asm |
| 1293 | SSLSETUP = ms\do_win64a.bat |
| 1294 | SSLNMAKE = ms\nt.mak all |
| 1295 | !elseif "$(PLATFORM)"=="ia64" |
| 1296 | !message Using 'ia64' platform for OpenSSL... |
| 1297 | SSLCONFIG = VC-WIN64I no-asm |
| 1298 | SSLSETUP = ms\do_win64i.bat |
| 1299 | SSLNMAKE = ms\nt.mak all |
| 1300 | !else |
| 1301 | !message Assuming 'x86' platform for OpenSSL... |
| 1302 | SSLCONFIG = VC-WIN32 no-asm |
| 1303 | SSLSETUP = ms\do_ms.bat |
| 1304 | SSLNMAKE = ms\nt.mak all |
| 1305 | !endif |
| 1306 | !endif |
| 1307 | |
| 1308 | !ifdef FOSSIL_ENABLE_TCL |
| 1309 | TCLDIR = $(B)\compat\tcl-8.6 |
| @@ -1472,13 +1506,13 @@ | |
| 1472 | @set PATH=$(PERLDIR);$(PATH) |
| 1473 | !endif |
| 1474 | @pushd "$(SSLDIR)" && $(PERL) Configure $(SSLCONFIG) && popd |
| 1475 | @pushd "$(SSLDIR)" && call $(SSLSETUP) && popd |
| 1476 | !ifdef FOSSIL_ENABLE_WINXP |
| 1477 | @pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) "CC=cl $(XPCFLAGS)" "LFLAGS=$(SSLLFLAGS) $(XPLDFLAGS)" && popd |
| 1478 | !else |
| 1479 | @pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) && popd |
| 1480 | !endif |
| 1481 | !endif |
| 1482 | |
| 1483 | !ifndef FOSSIL_ENABLE_MINIZ |
| 1484 | APPTARGETS = $(APPTARGETS) zlib |
| 1485 |
| --- src/makemake.tcl | |
| +++ src/makemake.tcl | |
| @@ -28,10 +28,11 @@ | |
| 28 | bisect |
| 29 | blob |
| 30 | branch |
| 31 | browse |
| 32 | builtin |
| 33 | bundle |
| 34 | cache |
| 35 | captcha |
| 36 | cgi |
| 37 | checkin |
| 38 | checkout |
| @@ -93,19 +94,22 @@ | |
| 94 | path |
| 95 | pivot |
| 96 | popen |
| 97 | pqueue |
| 98 | printf |
| 99 | publish |
| 100 | purge |
| 101 | rebuild |
| 102 | regexp |
| 103 | report |
| 104 | rss |
| 105 | schema |
| 106 | search |
| 107 | setup |
| 108 | sha1 |
| 109 | shun |
| 110 | sitemap |
| 111 | skins |
| 112 | sqlcmd |
| 113 | stash |
| 114 | stat |
| 115 | style |
| @@ -510,11 +514,12 @@ | |
| 514 | # This is useful when Tcl has been compiled statically with MinGW. |
| 515 | # |
| 516 | FOSSIL_TCL_SOURCE = 1 |
| 517 | |
| 518 | #### Check if the workaround for the MinGW command line handling needs to |
| 519 | # be enabled by default. This check may be somewhat fragile due to the |
| 520 | # use of "findstring". |
| 521 | # |
| 522 | ifndef MINGW_IS_32BIT_ONLY |
| 523 | ifeq (,$(findstring w64-mingw32,$(PREFIX))) |
| 524 | MINGW_IS_32BIT_ONLY = 1 |
| 525 | endif |
| @@ -523,26 +528,46 @@ | |
| 528 | #### The directories where the zlib include and library files are located. |
| 529 | # |
| 530 | ZINCDIR = $(SRCDIR)/../compat/zlib |
| 531 | ZLIBDIR = $(SRCDIR)/../compat/zlib |
| 532 | |
| 533 | #### Make an attempt to detect if Fossil is being built for the x64 processor |
| 534 | # architecture. This check may be somewhat fragile due to "findstring". |
| 535 | # |
| 536 | ifndef X64 |
| 537 | ifneq (,$(findstring x86_64-w64-mingw32,$(PREFIX))) |
| 538 | X64 = 1 |
| 539 | endif |
| 540 | endif |
| 541 | |
| 542 | #### Determine if the optimized assembly routines provided with zlib should be |
| 543 | # used, taking into account whether zlib is actually enabled and the target |
| 544 | # processor architecture. |
| 545 | # |
| 546 | ifndef X64 |
| 547 | SSLCONFIG = mingw |
| 548 | ifndef FOSSIL_ENABLE_MINIZ |
| 549 | ZLIBCONFIG = LOC="-DASMV -DASMINF" OBJA="inffas86.o match.o" |
| 550 | LIBTARGETS = $(ZLIBDIR)/inffas86.o $(ZLIBDIR)/match.o |
| 551 | else |
| 552 | ZLIBCONFIG = |
| 553 | LIBTARGETS = |
| 554 | endif |
| 555 | else |
| 556 | SSLCONFIG = mingw64 |
| 557 | ZLIBCONFIG = |
| 558 | LIBTARGETS = |
| 559 | endif |
| 560 | |
| 561 | #### Disable creation of the OpenSSL shared libraries. Also, disable support |
| 562 | # for both SSLv2 and SSLv3 (i.e. thereby forcing the use of TLS). |
| 563 | # |
| 564 | SSLCONFIG += no-ssl2 no-ssl3 no-shared |
| 565 | |
| 566 | #### When using zlib, make sure that OpenSSL is configured to use the zlib |
| 567 | # that Fossil knows about (i.e. the one within the source tree). |
| 568 | # |
| 569 | ifndef FOSSIL_ENABLE_MINIZ |
| 570 | SSLCONFIG += --with-zlib-lib=$(PWD)/$(ZLIBDIR) --with-zlib-include=$(PWD)/$(ZLIBDIR) zlib |
| 571 | endif |
| 572 | |
| 573 | #### The directories where the OpenSSL include and library files are located. |
| @@ -1287,23 +1312,32 @@ | |
| 1312 | SSLLIBDIR = $(SSLDIR)\out32 |
| 1313 | SSLLFLAGS = /nologo /opt:ref /debug |
| 1314 | SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib |
| 1315 | !if "$(PLATFORM)"=="amd64" || "$(PLATFORM)"=="x64" |
| 1316 | !message Using 'x64' platform for OpenSSL... |
| 1317 | # BUGBUG (OpenSSL): Apparently, using "no-ssl*" here breaks the build. |
| 1318 | # SSLCONFIG = VC-WIN64A no-asm no-ssl2 no-ssl3 no-shared |
| 1319 | SSLCONFIG = VC-WIN64A no-asm no-shared |
| 1320 | SSLSETUP = ms\do_win64a.bat |
| 1321 | SSLNMAKE = ms\nt.mak all |
| 1322 | SSLCFLAGS = -DOPENSSL_NO_SSL2 -DOPENSSL_NO_SSL3 |
| 1323 | !elseif "$(PLATFORM)"=="ia64" |
| 1324 | !message Using 'ia64' platform for OpenSSL... |
| 1325 | # BUGBUG (OpenSSL): Apparently, using "no-ssl*" here breaks the build. |
| 1326 | # SSLCONFIG = VC-WIN64I no-asm no-ssl2 no-ssl3 no-shared |
| 1327 | SSLCONFIG = VC-WIN64I no-asm no-shared |
| 1328 | SSLSETUP = ms\do_win64i.bat |
| 1329 | SSLNMAKE = ms\nt.mak all |
| 1330 | SSLCFLAGS = -DOPENSSL_NO_SSL2 -DOPENSSL_NO_SSL3 |
| 1331 | !else |
| 1332 | !message Assuming 'x86' platform for OpenSSL... |
| 1333 | # BUGBUG (OpenSSL): Apparently, using "no-ssl*" here breaks the build. |
| 1334 | # SSLCONFIG = VC-WIN32 no-asm no-ssl2 no-ssl3 no-shared |
| 1335 | SSLCONFIG = VC-WIN32 no-asm no-shared |
| 1336 | SSLSETUP = ms\do_ms.bat |
| 1337 | SSLNMAKE = ms\nt.mak all |
| 1338 | SSLCFLAGS = -DOPENSSL_NO_SSL2 -DOPENSSL_NO_SSL3 |
| 1339 | !endif |
| 1340 | !endif |
| 1341 | |
| 1342 | !ifdef FOSSIL_ENABLE_TCL |
| 1343 | TCLDIR = $(B)\compat\tcl-8.6 |
| @@ -1472,13 +1506,13 @@ | |
| 1506 | @set PATH=$(PERLDIR);$(PATH) |
| 1507 | !endif |
| 1508 | @pushd "$(SSLDIR)" && $(PERL) Configure $(SSLCONFIG) && popd |
| 1509 | @pushd "$(SSLDIR)" && call $(SSLSETUP) && popd |
| 1510 | !ifdef FOSSIL_ENABLE_WINXP |
| 1511 | @pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) "CC=cl $(SSLCFLAGS) $(XPCFLAGS)" "LFLAGS=$(SSLLFLAGS) $(XPLDFLAGS)" && popd |
| 1512 | !else |
| 1513 | @pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) "CC=cl $(SSLCFLAGS)" && popd |
| 1514 | !endif |
| 1515 | !endif |
| 1516 | |
| 1517 | !ifndef FOSSIL_ENABLE_MINIZ |
| 1518 | APPTARGETS = $(APPTARGETS) zlib |
| 1519 |
+1
-1
| --- src/markdown.c | ||
| +++ src/markdown.c | ||
| @@ -2155,11 +2155,11 @@ | ||
| 2155 | 2155 | struct Blob *ib, /* input blob in markdown */ |
| 2156 | 2156 | const struct mkd_renderer *rndrer /* renderer descriptor (callbacks) */ |
| 2157 | 2157 | ){ |
| 2158 | 2158 | struct link_ref *lr; |
| 2159 | 2159 | struct Blob text = BLOB_INITIALIZER; |
| 2160 | - size_t i, beg, end; | |
| 2160 | + size_t i, beg, end = 0; | |
| 2161 | 2161 | struct render rndr; |
| 2162 | 2162 | char *ib_data; |
| 2163 | 2163 | |
| 2164 | 2164 | /* filling the render structure */ |
| 2165 | 2165 | if( !rndrer ) return; |
| 2166 | 2166 |
| --- src/markdown.c | |
| +++ src/markdown.c | |
| @@ -2155,11 +2155,11 @@ | |
| 2155 | struct Blob *ib, /* input blob in markdown */ |
| 2156 | const struct mkd_renderer *rndrer /* renderer descriptor (callbacks) */ |
| 2157 | ){ |
| 2158 | struct link_ref *lr; |
| 2159 | struct Blob text = BLOB_INITIALIZER; |
| 2160 | size_t i, beg, end; |
| 2161 | struct render rndr; |
| 2162 | char *ib_data; |
| 2163 | |
| 2164 | /* filling the render structure */ |
| 2165 | if( !rndrer ) return; |
| 2166 |
| --- src/markdown.c | |
| +++ src/markdown.c | |
| @@ -2155,11 +2155,11 @@ | |
| 2155 | struct Blob *ib, /* input blob in markdown */ |
| 2156 | const struct mkd_renderer *rndrer /* renderer descriptor (callbacks) */ |
| 2157 | ){ |
| 2158 | struct link_ref *lr; |
| 2159 | struct Blob text = BLOB_INITIALIZER; |
| 2160 | size_t i, beg, end = 0; |
| 2161 | struct render rndr; |
| 2162 | char *ib_data; |
| 2163 | |
| 2164 | /* filling the render structure */ |
| 2165 | if( !rndrer ) return; |
| 2166 |
+9
-2
| --- src/mkversion.c | ||
| +++ src/mkversion.c | ||
| @@ -7,10 +7,11 @@ | ||
| 7 | 7 | ** |
| 8 | 8 | ** Note that the manifest.uuid and manifest files are generated by Fossil. |
| 9 | 9 | */ |
| 10 | 10 | #include <stdio.h> |
| 11 | 11 | #include <string.h> |
| 12 | +#include <stdlib.h> | |
| 12 | 13 | |
| 13 | 14 | int main(int argc, char *argv[]){ |
| 14 | 15 | FILE *m,*u,*v; |
| 15 | 16 | char *z; |
| 16 | 17 | int i, x, d; |
| @@ -17,11 +18,14 @@ | ||
| 17 | 18 | char b[1000]; |
| 18 | 19 | char vx[1000]; |
| 19 | 20 | memset(b,0,sizeof(b)); |
| 20 | 21 | memset(vx,0,sizeof(vx)); |
| 21 | 22 | u = fopen(argv[1],"r"); |
| 22 | - fgets(b, sizeof(b)-1,u); | |
| 23 | + if( fgets(b, sizeof(b)-1,u)==0 ){ | |
| 24 | + fprintf(stderr, "malformed manifest.uuid file: %s\n", argv[1]); | |
| 25 | + exit(1); | |
| 26 | + } | |
| 23 | 27 | fclose(u); |
| 24 | 28 | for(z=b; z[0] && z[0]!='\r' && z[0]!='\n'; z++){} |
| 25 | 29 | *z = 0; |
| 26 | 30 | printf("#define MANIFEST_UUID \"%s\"\n",b); |
| 27 | 31 | printf("#define MANIFEST_VERSION \"[%10.10s]\"\n",b); |
| @@ -32,11 +36,14 @@ | ||
| 32 | 36 | printf("#define MANIFEST_YEAR \"%.4s\"\n",b+2); |
| 33 | 37 | } |
| 34 | 38 | } |
| 35 | 39 | fclose(m); |
| 36 | 40 | v = fopen(argv[3],"r"); |
| 37 | - fgets(b, sizeof(b)-1,v); | |
| 41 | + if( fgets(b, sizeof(b)-1,v)==0 ){ | |
| 42 | + fprintf(stderr, "malformed VERSION file: %s\n", argv[3]); | |
| 43 | + exit(1); | |
| 44 | + } | |
| 38 | 45 | fclose(v); |
| 39 | 46 | for(z=b; z[0] && z[0]!='\r' && z[0]!='\n'; z++){} |
| 40 | 47 | *z = 0; |
| 41 | 48 | printf("#define RELEASE_VERSION \"%s\"\n", b); |
| 42 | 49 | x=0; |
| 43 | 50 |
| --- src/mkversion.c | |
| +++ src/mkversion.c | |
| @@ -7,10 +7,11 @@ | |
| 7 | ** |
| 8 | ** Note that the manifest.uuid and manifest files are generated by Fossil. |
| 9 | */ |
| 10 | #include <stdio.h> |
| 11 | #include <string.h> |
| 12 | |
| 13 | int main(int argc, char *argv[]){ |
| 14 | FILE *m,*u,*v; |
| 15 | char *z; |
| 16 | int i, x, d; |
| @@ -17,11 +18,14 @@ | |
| 17 | char b[1000]; |
| 18 | char vx[1000]; |
| 19 | memset(b,0,sizeof(b)); |
| 20 | memset(vx,0,sizeof(vx)); |
| 21 | u = fopen(argv[1],"r"); |
| 22 | fgets(b, sizeof(b)-1,u); |
| 23 | fclose(u); |
| 24 | for(z=b; z[0] && z[0]!='\r' && z[0]!='\n'; z++){} |
| 25 | *z = 0; |
| 26 | printf("#define MANIFEST_UUID \"%s\"\n",b); |
| 27 | printf("#define MANIFEST_VERSION \"[%10.10s]\"\n",b); |
| @@ -32,11 +36,14 @@ | |
| 32 | printf("#define MANIFEST_YEAR \"%.4s\"\n",b+2); |
| 33 | } |
| 34 | } |
| 35 | fclose(m); |
| 36 | v = fopen(argv[3],"r"); |
| 37 | fgets(b, sizeof(b)-1,v); |
| 38 | fclose(v); |
| 39 | for(z=b; z[0] && z[0]!='\r' && z[0]!='\n'; z++){} |
| 40 | *z = 0; |
| 41 | printf("#define RELEASE_VERSION \"%s\"\n", b); |
| 42 | x=0; |
| 43 |
| --- src/mkversion.c | |
| +++ src/mkversion.c | |
| @@ -7,10 +7,11 @@ | |
| 7 | ** |
| 8 | ** Note that the manifest.uuid and manifest files are generated by Fossil. |
| 9 | */ |
| 10 | #include <stdio.h> |
| 11 | #include <string.h> |
| 12 | #include <stdlib.h> |
| 13 | |
| 14 | int main(int argc, char *argv[]){ |
| 15 | FILE *m,*u,*v; |
| 16 | char *z; |
| 17 | int i, x, d; |
| @@ -17,11 +18,14 @@ | |
| 18 | char b[1000]; |
| 19 | char vx[1000]; |
| 20 | memset(b,0,sizeof(b)); |
| 21 | memset(vx,0,sizeof(vx)); |
| 22 | u = fopen(argv[1],"r"); |
| 23 | if( fgets(b, sizeof(b)-1,u)==0 ){ |
| 24 | fprintf(stderr, "malformed manifest.uuid file: %s\n", argv[1]); |
| 25 | exit(1); |
| 26 | } |
| 27 | fclose(u); |
| 28 | for(z=b; z[0] && z[0]!='\r' && z[0]!='\n'; z++){} |
| 29 | *z = 0; |
| 30 | printf("#define MANIFEST_UUID \"%s\"\n",b); |
| 31 | printf("#define MANIFEST_VERSION \"[%10.10s]\"\n",b); |
| @@ -32,11 +36,14 @@ | |
| 36 | printf("#define MANIFEST_YEAR \"%.4s\"\n",b+2); |
| 37 | } |
| 38 | } |
| 39 | fclose(m); |
| 40 | v = fopen(argv[3],"r"); |
| 41 | if( fgets(b, sizeof(b)-1,v)==0 ){ |
| 42 | fprintf(stderr, "malformed VERSION file: %s\n", argv[3]); |
| 43 | exit(1); |
| 44 | } |
| 45 | fclose(v); |
| 46 | for(z=b; z[0] && z[0]!='\r' && z[0]!='\n'; z++){} |
| 47 | *z = 0; |
| 48 | printf("#define RELEASE_VERSION \"%s\"\n", b); |
| 49 | x=0; |
| 50 |
+1
-6
| --- src/moderate.c | ||
| +++ src/moderate.c | ||
| @@ -38,16 +38,11 @@ | ||
| 38 | 38 | |
| 39 | 39 | /* |
| 40 | 40 | ** Return TRUE if the modreq table exists |
| 41 | 41 | */ |
| 42 | 42 | int moderation_table_exists(void){ |
| 43 | - static int modreqExists = -1; | |
| 44 | - if( modreqExists<0 ){ | |
| 45 | - modreqExists = db_exists("SELECT 1 FROM %s.sqlite_master" | |
| 46 | - " WHERE name='modreq'", db_name("repository")); | |
| 47 | - } | |
| 48 | - return modreqExists; | |
| 43 | + return db_table_exists("repository", "modreq"); | |
| 49 | 44 | } |
| 50 | 45 | |
| 51 | 46 | /* |
| 52 | 47 | ** Return TRUE if the object specified is being held for moderation. |
| 53 | 48 | */ |
| 54 | 49 |
| --- src/moderate.c | |
| +++ src/moderate.c | |
| @@ -38,16 +38,11 @@ | |
| 38 | |
| 39 | /* |
| 40 | ** Return TRUE if the modreq table exists |
| 41 | */ |
| 42 | int moderation_table_exists(void){ |
| 43 | static int modreqExists = -1; |
| 44 | if( modreqExists<0 ){ |
| 45 | modreqExists = db_exists("SELECT 1 FROM %s.sqlite_master" |
| 46 | " WHERE name='modreq'", db_name("repository")); |
| 47 | } |
| 48 | return modreqExists; |
| 49 | } |
| 50 | |
| 51 | /* |
| 52 | ** Return TRUE if the object specified is being held for moderation. |
| 53 | */ |
| 54 |
| --- src/moderate.c | |
| +++ src/moderate.c | |
| @@ -38,16 +38,11 @@ | |
| 38 | |
| 39 | /* |
| 40 | ** Return TRUE if the modreq table exists |
| 41 | */ |
| 42 | int moderation_table_exists(void){ |
| 43 | return db_table_exists("repository", "modreq"); |
| 44 | } |
| 45 | |
| 46 | /* |
| 47 | ** Return TRUE if the object specified is being held for moderation. |
| 48 | */ |
| 49 |
+352
-51
| --- src/name.c | ||
| +++ src/name.c | ||
| @@ -42,10 +42,44 @@ | ||
| 42 | 42 | if( z[7]!='-') return 0; |
| 43 | 43 | if( !fossil_isdigit(z[8]) ) return 0; |
| 44 | 44 | if( !fossil_isdigit(z[9]) ) return 0; |
| 45 | 45 | return 1; |
| 46 | 46 | } |
| 47 | + | |
| 48 | +/* | |
| 49 | +** Return the RID that is the "root" of the branch that contains | |
| 50 | +** check-in "rid" if inBranch==0 or the first check-in in the branch | |
| 51 | +** if inBranch==1. | |
| 52 | +*/ | |
| 53 | +int start_of_branch(int rid, int inBranch){ | |
| 54 | + Stmt q; | |
| 55 | + int rc; | |
| 56 | + char *zBr; | |
| 57 | + zBr = db_text("trunk","SELECT value FROM tagxref" | |
| 58 | + " WHERE rid=%d AND tagid=%d" | |
| 59 | + " AND tagtype>0", | |
| 60 | + rid, TAG_BRANCH); | |
| 61 | + db_prepare(&q, | |
| 62 | + "SELECT pid, EXISTS(SELECT 1 FROM tagxref" | |
| 63 | + " WHERE tagid=%d AND tagtype>0" | |
| 64 | + " AND value=%Q AND rid=plink.pid)" | |
| 65 | + " FROM plink" | |
| 66 | + " WHERE cid=:cid AND isprim", | |
| 67 | + TAG_BRANCH, zBr | |
| 68 | + ); | |
| 69 | + fossil_free(zBr); | |
| 70 | + do{ | |
| 71 | + db_reset(&q); | |
| 72 | + db_bind_int(&q, ":cid", rid); | |
| 73 | + rc = db_step(&q); | |
| 74 | + if( rc!=SQLITE_ROW ) break; | |
| 75 | + if( inBranch && db_column_int(&q,1)==0 ) break; | |
| 76 | + rid = db_column_int(&q, 0); | |
| 77 | + }while( db_column_int(&q, 1)==1 && rid>0 ); | |
| 78 | + db_finalize(&q); | |
| 79 | + return rid; | |
| 80 | +} | |
| 47 | 81 | |
| 48 | 82 | /* |
| 49 | 83 | ** Convert a symbolic name into a RID. Acceptable forms: |
| 50 | 84 | ** |
| 51 | 85 | ** * SHA1 hash |
| @@ -66,20 +100,28 @@ | ||
| 66 | 100 | ** Return the RID of the matching artifact. Or return 0 if the name does not |
| 67 | 101 | ** match any known object. Or return -1 if the name is ambiguous. |
| 68 | 102 | ** |
| 69 | 103 | ** The zType parameter specifies the type of artifact: ci, t, w, e, g. |
| 70 | 104 | ** If zType is NULL or "" or "*" then any type of artifact will serve. |
| 105 | +** If zType is "br" then find the first check-in of the named branch | |
| 106 | +** rather than the last. | |
| 71 | 107 | ** zType is "ci" in most use cases since we are usually searching for |
| 72 | 108 | ** a check-in. |
| 73 | 109 | */ |
| 74 | 110 | int symbolic_name_to_rid(const char *zTag, const char *zType){ |
| 75 | 111 | int vid; |
| 76 | 112 | int rid = 0; |
| 77 | 113 | int nTag; |
| 78 | 114 | int i; |
| 115 | + int startOfBranch = 0; | |
| 79 | 116 | |
| 80 | - if( zType==0 || zType[0]==0 ) zType = "*"; | |
| 117 | + if( zType==0 || zType[0]==0 ){ | |
| 118 | + zType = "*"; | |
| 119 | + }else if( zType[0]=='b' ){ | |
| 120 | + zType = "ci"; | |
| 121 | + startOfBranch = 1; | |
| 122 | + } | |
| 81 | 123 | if( zTag==0 || zTag[0]==0 ) return 0; |
| 82 | 124 | |
| 83 | 125 | /* special keyword: "tip" */ |
| 84 | 126 | if( fossil_strcmp(zTag, "tip")==0 && (zType[0]=='*' || zType[0]=='c') ){ |
| 85 | 127 | rid = db_int(0, |
| @@ -151,41 +193,18 @@ | ||
| 151 | 193 | " AND tagxref.tagid=tag.tagid AND tagxref.tagtype>0 " |
| 152 | 194 | " AND event.objid=tagxref.rid " |
| 153 | 195 | " AND event.type GLOB '%q'", |
| 154 | 196 | &zTag[4], zType |
| 155 | 197 | ); |
| 198 | + if( startOfBranch ) rid = start_of_branch(rid,1); | |
| 156 | 199 | return rid; |
| 157 | 200 | } |
| 158 | 201 | |
| 159 | 202 | /* root:TAG -> The origin of the branch */ |
| 160 | 203 | if( memcmp(zTag, "root:", 5)==0 ){ |
| 161 | - Stmt q; | |
| 162 | - int rc; | |
| 163 | - char *zBr; | |
| 164 | 204 | rid = symbolic_name_to_rid(zTag+5, zType); |
| 165 | - zBr = db_text("trunk","SELECT value FROM tagxref" | |
| 166 | - " WHERE rid=%d AND tagid=%d" | |
| 167 | - " AND tagtype>0", | |
| 168 | - rid, TAG_BRANCH); | |
| 169 | - db_prepare(&q, | |
| 170 | - "SELECT pid, EXISTS(SELECT 1 FROM tagxref" | |
| 171 | - " WHERE tagid=%d AND tagtype>0" | |
| 172 | - " AND value=%Q AND rid=plink.pid)" | |
| 173 | - " FROM plink" | |
| 174 | - " WHERE cid=:cid AND isprim", | |
| 175 | - TAG_BRANCH, zBr | |
| 176 | - ); | |
| 177 | - fossil_free(zBr); | |
| 178 | - do{ | |
| 179 | - db_reset(&q); | |
| 180 | - db_bind_int(&q, ":cid", rid); | |
| 181 | - rc = db_step(&q); | |
| 182 | - if( rc!=SQLITE_ROW ) break; | |
| 183 | - rid = db_column_int(&q, 0); | |
| 184 | - }while( db_column_int(&q, 1)==1 && rid>0 ); | |
| 185 | - db_finalize(&q); | |
| 186 | - return rid; | |
| 205 | + return start_of_branch(rid, 0); | |
| 187 | 206 | } |
| 188 | 207 | |
| 189 | 208 | /* symbolic-name ":" date-time */ |
| 190 | 209 | nTag = strlen(zTag); |
| 191 | 210 | for(i=0; i<nTag-10 && zTag[i]!=':'; i++){} |
| @@ -245,11 +264,14 @@ | ||
| 245 | 264 | " AND tagxref.tagid=tag.tagid AND tagxref.tagtype>0 " |
| 246 | 265 | " AND event.objid=tagxref.rid " |
| 247 | 266 | " AND event.type GLOB '%q'", |
| 248 | 267 | zTag, zType |
| 249 | 268 | ); |
| 250 | - if( rid>0 ) return rid; | |
| 269 | + if( rid>0 ){ | |
| 270 | + if( startOfBranch ) rid = start_of_branch(rid,1); | |
| 271 | + return rid; | |
| 272 | + } | |
| 251 | 273 | |
| 252 | 274 | /* Undocumented: numeric tags get translated directly into the RID */ |
| 253 | 275 | if( memcmp(zTag, "rid:", 4)==0 ){ |
| 254 | 276 | zTag += 4; |
| 255 | 277 | for(i=0; fossil_isdigit(zTag[i]); i++){} |
| @@ -324,30 +346,25 @@ | ||
| 324 | 346 | ** name_collisions searches through events, blobs, and tickets for |
| 325 | 347 | ** collisions of a given UUID based on its length on UUIDs no shorter |
| 326 | 348 | ** than 4 characters in length. |
| 327 | 349 | */ |
| 328 | 350 | int name_collisions(const char *zName){ |
| 329 | - Stmt q; | |
| 330 | 351 | int c = 0; /* count of collisions for zName */ |
| 331 | 352 | int nLen; /* length of zName */ |
| 332 | 353 | nLen = strlen(zName); |
| 333 | 354 | if( nLen>=4 && nLen<=UUID_SIZE && validate16(zName, nLen) ){ |
| 334 | - db_prepare(&q, | |
| 335 | - "SELECT count(uuid) FROM" | |
| 336 | - " (SELECT substr(tkt_uuid, 1, %d) AS uuid FROM ticket" | |
| 337 | - " UNION ALL SELECT * FROM" | |
| 338 | - " (SELECT substr(tagname, 7, %d) FROM" | |
| 339 | - " tag WHERE tagname GLOB 'event-*')" | |
| 340 | - " UNION ALL SELECT * FROM" | |
| 341 | - " (SELECT substr(uuid, 1, %d) FROM blob))" | |
| 342 | - " WHERE uuid GLOB '%q*'" | |
| 343 | - " GROUP BY uuid HAVING count(uuid) > 1;", | |
| 344 | - nLen, nLen, nLen, zName); | |
| 345 | - if( db_step(&q)==SQLITE_ROW ){ | |
| 346 | - c = db_column_int(&q, 0); | |
| 347 | - } | |
| 348 | - db_finalize(&q); | |
| 355 | + c = db_int(0, | |
| 356 | + "SELECT" | |
| 357 | + " (SELECT count(*) FROM ticket" | |
| 358 | + " WHERE tkt_uuid GLOB '%q*') +" | |
| 359 | + " (SELECT count(*) FROM tag" | |
| 360 | + " WHERE tagname GLOB 'event-%q*') +" | |
| 361 | + " (SELECT count(*) FROM blob" | |
| 362 | + " WHERE uuid GLOB '%q*');", | |
| 363 | + zName, zName, zName | |
| 364 | + ); | |
| 365 | + if( c<2 ) c = 0; | |
| 349 | 366 | } |
| 350 | 367 | return c; |
| 351 | 368 | } |
| 352 | 369 | |
| 353 | 370 | /* |
| @@ -391,18 +408,15 @@ | ||
| 391 | 408 | int rid; |
| 392 | 409 | |
| 393 | 410 | if( zName==0 || zName[0]==0 ) return 0; |
| 394 | 411 | rid = symbolic_name_to_rid(zName, zType); |
| 395 | 412 | if( rid<0 ){ |
| 396 | - fossil_error(1, "ambiguous name: %s", zName); | |
| 397 | - return 0; | |
| 413 | + fossil_fatal("ambiguous name: %s", zName); | |
| 398 | 414 | }else if( rid==0 ){ |
| 399 | - fossil_error(1, "not found: %s", zName); | |
| 400 | - return 0; | |
| 401 | - }else{ | |
| 402 | - return rid; | |
| 415 | + fossil_fatal("not found: %s", zName); | |
| 403 | 416 | } |
| 417 | + return rid; | |
| 404 | 418 | } |
| 405 | 419 | int name_to_rid(const char *zName){ |
| 406 | 420 | return name_to_typed_rid(zName, "*"); |
| 407 | 421 | } |
| 408 | 422 | |
| @@ -505,11 +519,11 @@ | ||
| 505 | 519 | } |
| 506 | 520 | |
| 507 | 521 | /* |
| 508 | 522 | ** Generate a description of artifact "rid" |
| 509 | 523 | */ |
| 510 | -static void whatis_rid(int rid, int verboseFlag){ | |
| 524 | +void whatis_rid(int rid, int verboseFlag){ | |
| 511 | 525 | Stmt q; |
| 512 | 526 | int cnt; |
| 513 | 527 | |
| 514 | 528 | /* Basic information about the object. */ |
| 515 | 529 | db_prepare(&q, |
| @@ -657,21 +671,23 @@ | ||
| 657 | 671 | void whatis_cmd(void){ |
| 658 | 672 | int rid; |
| 659 | 673 | const char *zName; |
| 660 | 674 | int verboseFlag; |
| 661 | 675 | int i; |
| 676 | + const char *zType = 0; | |
| 662 | 677 | db_find_and_open_repository(0,0); |
| 663 | 678 | verboseFlag = find_option("verbose","v",0)!=0; |
| 679 | + zType = find_option("type",0,1); | |
| 664 | 680 | |
| 665 | 681 | /* We should be done with options.. */ |
| 666 | 682 | verify_all_options(); |
| 667 | 683 | |
| 668 | 684 | if( g.argc<3 ) usage("whatis NAME ..."); |
| 669 | 685 | for(i=2; i<g.argc; i++){ |
| 670 | 686 | zName = g.argv[i]; |
| 671 | 687 | if( i>2 ) fossil_print("%.79c\n",'-'); |
| 672 | - rid = symbolic_name_to_rid(zName, 0); | |
| 688 | + rid = symbolic_name_to_rid(zName, zType); | |
| 673 | 689 | if( rid<0 ){ |
| 674 | 690 | Stmt q; |
| 675 | 691 | int cnt = 0; |
| 676 | 692 | fossil_print("name: %s (ambiguous)\n", zName); |
| 677 | 693 | db_prepare(&q, |
| @@ -757,5 +773,290 @@ | ||
| 757 | 773 | while( db_step(&q)==SQLITE_ROW ){ |
| 758 | 774 | fossil_print("%s\n", db_column_text(&q, 0)); |
| 759 | 775 | } |
| 760 | 776 | db_finalize(&q); |
| 761 | 777 | } |
| 778 | + | |
| 779 | +/* | |
| 780 | +** Schema for the description table | |
| 781 | +*/ | |
| 782 | +static const char zDescTab[] = | |
| 783 | +@ CREATE TEMP TABLE IF NOT EXISTS description( | |
| 784 | +@ rid INTEGER PRIMARY KEY, -- RID of the object | |
| 785 | +@ uuid TEXT, -- SHA1 hash of the object | |
| 786 | +@ ctime DATETIME, -- Time of creation | |
| 787 | +@ isPrivate BOOLEAN DEFAULT 0, -- True for unpublished artifacts | |
| 788 | +@ type TEXT, -- file, checkin, wiki, ticket, etc. | |
| 789 | +@ summary TEXT, -- Summary comment for the object | |
| 790 | +@ detail TEXT -- filename, checkin comment, etc | |
| 791 | +@ ); | |
| 792 | +; | |
| 793 | + | |
| 794 | +/* | |
| 795 | +** Create the description table if it does not already exists. | |
| 796 | +** Populate fields of this table with descriptions for all artifacts | |
| 797 | +** whose RID matches the SQL expression in zWhere. | |
| 798 | +*/ | |
| 799 | +void describe_artifacts(const char *zWhere){ | |
| 800 | + db_multi_exec("%s", zDescTab/*safe-for-%s*/); | |
| 801 | + | |
| 802 | + /* Describe checkins */ | |
| 803 | + db_multi_exec( | |
| 804 | + "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n" | |
| 805 | + "SELECT blob.rid, blob.uuid, event.mtime, 'checkin',\n" | |
| 806 | + " 'checkin on ' || strftime('%%Y-%%m-%%d %%H:%%M',event.mtime)\n" | |
| 807 | + " FROM event, blob\n" | |
| 808 | + " WHERE (event.objid %s) AND event.type='ci'\n" | |
| 809 | + " AND event.objid=blob.rid;", | |
| 810 | + zWhere /*safe-for-%s*/ | |
| 811 | + ); | |
| 812 | + | |
| 813 | + /* Describe files */ | |
| 814 | + db_multi_exec( | |
| 815 | + "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n" | |
| 816 | + "SELECT blob.rid, blob.uuid, event.mtime, 'file', 'file '||filename.name\n" | |
| 817 | + " FROM mlink, blob, event, filename\n" | |
| 818 | + " WHERE (mlink.fid %s)\n" | |
| 819 | + " AND mlink.mid=event.objid\n" | |
| 820 | + " AND filename.fnid=mlink.fnid\n" | |
| 821 | + " AND mlink.fid=blob.rid;", | |
| 822 | + zWhere /*safe-for-%s*/ | |
| 823 | + ); | |
| 824 | + | |
| 825 | + /* Describe tags */ | |
| 826 | + db_multi_exec( | |
| 827 | + "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n" | |
| 828 | + "SELECT blob.rid, blob.uuid, tagxref.mtime, 'tag',\n" | |
| 829 | + " 'tag '||substr((SELECT uuid FROM blob WHERE rid=tagxref.rid),1,16)\n" | |
| 830 | + " FROM tagxref, blob\n" | |
| 831 | + " WHERE (tagxref.srcid %s) AND tagxref.srcid!=tagxref.rid\n" | |
| 832 | + " AND tagxref.srcid=blob.rid;", | |
| 833 | + zWhere /*safe-for-%s*/ | |
| 834 | + ); | |
| 835 | + | |
| 836 | + /* Cluster artifacts */ | |
| 837 | + db_multi_exec( | |
| 838 | + "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n" | |
| 839 | + "SELECT blob.rid, blob.uuid, tagxref.mtime, 'cluster', 'cluster'\n" | |
| 840 | + " FROM tagxref, blob\n" | |
| 841 | + " WHERE (tagxref.rid %s)\n" | |
| 842 | + " AND tagxref.tagid=(SELECT tagid FROM tag WHERE tagname='cluster')\n" | |
| 843 | + " AND blob.rid=tagxref.rid;", | |
| 844 | + zWhere /*safe-for-%s*/ | |
| 845 | + ); | |
| 846 | + | |
| 847 | + /* Ticket change artifacts */ | |
| 848 | + db_multi_exec( | |
| 849 | + "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n" | |
| 850 | + "SELECT blob.rid, blob.uuid, tagxref.mtime, 'ticket',\n" | |
| 851 | + " 'ticket '||substr(tag.tagname,5,21)\n" | |
| 852 | + " FROM tagxref, tag, blob\n" | |
| 853 | + " WHERE (tagxref.rid %s)\n" | |
| 854 | + " AND tag.tagid=tagxref.tagid\n" | |
| 855 | + " AND tag.tagname GLOB 'tkt-*'" | |
| 856 | + " AND blob.rid=tagxref.rid;", | |
| 857 | + zWhere /*safe-for-%s*/ | |
| 858 | + ); | |
| 859 | + | |
| 860 | + /* Wiki edit artifacts */ | |
| 861 | + db_multi_exec( | |
| 862 | + "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n" | |
| 863 | + "SELECT blob.rid, blob.uuid, tagxref.mtime, 'wiki',\n" | |
| 864 | + " printf('wiki \"%%s\"',substr(tag.tagname,6))\n" | |
| 865 | + " FROM tagxref, tag, blob\n" | |
| 866 | + " WHERE (tagxref.rid %s)\n" | |
| 867 | + " AND tag.tagid=tagxref.tagid\n" | |
| 868 | + " AND tag.tagname GLOB 'wiki-*'" | |
| 869 | + " AND blob.rid=tagxref.rid;", | |
| 870 | + zWhere /*safe-for-%s*/ | |
| 871 | + ); | |
| 872 | + | |
| 873 | + /* Event edit artifacts */ | |
| 874 | + db_multi_exec( | |
| 875 | + "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n" | |
| 876 | + "SELECT blob.rid, blob.uuid, tagxref.mtime, 'event',\n" | |
| 877 | + " 'event '||substr(tag.tagname,7)\n" | |
| 878 | + " FROM tagxref, tag, blob\n" | |
| 879 | + " WHERE (tagxref.rid %s)\n" | |
| 880 | + " AND tag.tagid=tagxref.tagid\n" | |
| 881 | + " AND tag.tagname GLOB 'event-*'" | |
| 882 | + " AND blob.rid=tagxref.rid;", | |
| 883 | + zWhere /*safe-for-%s*/ | |
| 884 | + ); | |
| 885 | + | |
| 886 | + /* Attachments */ | |
| 887 | + db_multi_exec( | |
| 888 | + "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n" | |
| 889 | + "SELECT blob.rid, blob.uuid, attachment.mtime, 'attach-control',\n" | |
| 890 | + " 'attachment-control for '||attachment.filename\n" | |
| 891 | + " FROM attachment, blob\n" | |
| 892 | + " WHERE (attachment.attachid %s)\n" | |
| 893 | + " AND blob.rid=attachment.attachid", | |
| 894 | + zWhere /*safe-for-%s*/ | |
| 895 | + ); | |
| 896 | + db_multi_exec( | |
| 897 | + "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n" | |
| 898 | + "SELECT blob.rid, blob.uuid, attachment.mtime, 'attachment',\n" | |
| 899 | + " 'attachment '||attachment.filename\n" | |
| 900 | + " FROM attachment, blob\n" | |
| 901 | + " WHERE (blob.rid %s)\n" | |
| 902 | + " AND blob.rid NOT IN (SELECT rid FROM description)\n" | |
| 903 | + " AND blob.uuid=attachment.src", | |
| 904 | + zWhere /*safe-for-%s*/ | |
| 905 | + ); | |
| 906 | + | |
| 907 | + /* Everything else */ | |
| 908 | + db_multi_exec( | |
| 909 | + "INSERT OR IGNORE INTO description(rid,uuid,type,summary)\n" | |
| 910 | + "SELECT blob.rid, blob.uuid," | |
| 911 | + " CASE WHEN blob.size<0 THEN 'phantom' ELSE '' END,\n" | |
| 912 | + " 'unknown'\n" | |
| 913 | + " FROM blob WHERE (blob.rid %s);", | |
| 914 | + zWhere /*safe-for-%s*/ | |
| 915 | + ); | |
| 916 | + | |
| 917 | + /* Mark private elements */ | |
| 918 | + db_multi_exec( | |
| 919 | + "UPDATE description SET isPrivate=1 WHERE rid IN private" | |
| 920 | + ); | |
| 921 | +} | |
| 922 | + | |
| 923 | +/* | |
| 924 | +** Print the content of the description table on stdout | |
| 925 | +*/ | |
| 926 | +int describe_artifacts_to_stdout(const char *zWhere, const char *zLabel){ | |
| 927 | + Stmt q; | |
| 928 | + int cnt = 0; | |
| 929 | + describe_artifacts(zWhere); | |
| 930 | + db_prepare(&q, | |
| 931 | + "SELECT uuid, summary, isPrivate\n" | |
| 932 | + " FROM description\n" | |
| 933 | + " ORDER BY ctime, type;" | |
| 934 | + ); | |
| 935 | + while( db_step(&q)==SQLITE_ROW ){ | |
| 936 | + if( zLabel ){ | |
| 937 | + fossil_print("%s\n", zLabel); | |
| 938 | + zLabel = 0; | |
| 939 | + } | |
| 940 | + fossil_print(" %.16s %s", db_column_text(&q,0), db_column_text(&q,1)); | |
| 941 | + if( db_column_int(&q,2) ) fossil_print(" (unpublished)"); | |
| 942 | + fossil_print("\n"); | |
| 943 | + cnt++; | |
| 944 | + } | |
| 945 | + db_finalize(&q); | |
| 946 | + db_multi_exec("DELETE FROM description;"); | |
| 947 | + return cnt; | |
| 948 | +} | |
| 949 | + | |
| 950 | +/* | |
| 951 | +** COMMAND: test-describe-artifacts | |
| 952 | +** | |
| 953 | +** Usage: %fossil test-describe-artifacts [--from S] [--count N] | |
| 954 | +** | |
| 955 | +** Display a one-line description of every artifact. | |
| 956 | +*/ | |
| 957 | +void test_describe_artifacts_cmd(void){ | |
| 958 | + int iFrom = 0; | |
| 959 | + int iCnt = 1000000; | |
| 960 | + const char *z; | |
| 961 | + char *zRange; | |
| 962 | + db_find_and_open_repository(0,0); | |
| 963 | + z = find_option("from",0,1); | |
| 964 | + if( z ) iFrom = atoi(z); | |
| 965 | + z = find_option("count",0,1); | |
| 966 | + if( z ) iCnt = atoi(z); | |
| 967 | + zRange = mprintf("BETWEEN %d AND %d", iFrom, iFrom+iCnt-1); | |
| 968 | + describe_artifacts_to_stdout(zRange, 0); | |
| 969 | +} | |
| 970 | + | |
| 971 | +/* | |
| 972 | +** WEBPAGE: bloblist | |
| 973 | +** | |
| 974 | +** Return a page showing all artifacts in the repository. Query parameters: | |
| 975 | +** | |
| 976 | +** n=N Show N artifacts | |
| 977 | +** s=S Start with artifact number S | |
| 978 | +*/ | |
| 979 | +void bloblist_page(void){ | |
| 980 | + Stmt q; | |
| 981 | + int s = atoi(PD("s","0")); | |
| 982 | + int n = atoi(PD("n","5000")); | |
| 983 | + int mx = db_int(0, "SELECT max(rid) FROM blob"); | |
| 984 | + char *zRange; | |
| 985 | + | |
| 986 | + login_check_credentials(); | |
| 987 | + if( !g.perm.Read ){ login_needed(); return; } | |
| 988 | + style_header("List Of Artifacts"); | |
| 989 | + if( mx>n && P("s")==0 ){ | |
| 990 | + int i; | |
| 991 | + @ <p>Select a range of artifacts to view:</p> | |
| 992 | + @ <ul> | |
| 993 | + for(i=1; i<=mx; i+=n){ | |
| 994 | + @ <li> %z(href("%R/bloblist?s=%d&n=%d",i,n)) | |
| 995 | + @ %d(i)..%d(i+n-1<mx?i+n-1:mx)</a> | |
| 996 | + } | |
| 997 | + @ </ul> | |
| 998 | + style_footer(); | |
| 999 | + return; | |
| 1000 | + } | |
| 1001 | + if( mx>n ){ | |
| 1002 | + style_submenu_element("Index", "Index", "bloblist"); | |
| 1003 | + } | |
| 1004 | + zRange = mprintf("BETWEEN %d AND %d", s, s+n-1); | |
| 1005 | + describe_artifacts(zRange); | |
| 1006 | + db_prepare(&q, | |
| 1007 | + "SELECT rid, uuid, summary, isPrivate FROM description ORDER BY rid" | |
| 1008 | + ); | |
| 1009 | + @ <table cellpadding="0" cellspacing="0"> | |
| 1010 | + while( db_step(&q)==SQLITE_ROW ){ | |
| 1011 | + int rid = db_column_int(&q,0); | |
| 1012 | + const char *zUuid = db_column_text(&q, 1); | |
| 1013 | + const char *zDesc = db_column_text(&q, 2); | |
| 1014 | + int isPriv = db_column_int(&q,2); | |
| 1015 | + @ <tr><td align="right">%d(rid)</td> | |
| 1016 | + @ <td> %z(href("%R/info/%s",zUuid))%s(zUuid)</a> </td> | |
| 1017 | + @ <td align="left">%h(zDesc)</td> | |
| 1018 | + if( isPriv ){ | |
| 1019 | + @ <td>(unpublished)</td> | |
| 1020 | + } | |
| 1021 | + @ </tr> | |
| 1022 | + } | |
| 1023 | + @ </table> | |
| 1024 | + db_finalize(&q); | |
| 1025 | + style_footer(); | |
| 1026 | +} | |
| 1027 | + | |
| 1028 | +/* | |
| 1029 | +** COMMAND: test-unsent | |
| 1030 | +** | |
| 1031 | +** Usage: %fossil test-unsent | |
| 1032 | +** | |
| 1033 | +** Show all artifacts in the unsent table | |
| 1034 | +*/ | |
| 1035 | +void test_unsent_cmd(void){ | |
| 1036 | + db_find_and_open_repository(0,0); | |
| 1037 | + describe_artifacts_to_stdout("IN unsent", 0); | |
| 1038 | +} | |
| 1039 | + | |
| 1040 | +/* | |
| 1041 | +** COMMAND: test-unclustered | |
| 1042 | +** | |
| 1043 | +** Usage: %fossil test-unclustered | |
| 1044 | +** | |
| 1045 | +** Show all artifacts in the unclustered table | |
| 1046 | +*/ | |
| 1047 | +void test_unclusterd_cmd(void){ | |
| 1048 | + db_find_and_open_repository(0,0); | |
| 1049 | + describe_artifacts_to_stdout("IN unclustered", 0); | |
| 1050 | +} | |
| 1051 | + | |
| 1052 | +/* | |
| 1053 | +** COMMAND: test-phantoms | |
| 1054 | +** | |
| 1055 | +** Usage: %fossil test-phantoms | |
| 1056 | +** | |
| 1057 | +** Show all phantom artifacts | |
| 1058 | +*/ | |
| 1059 | +void test_phatoms_cmd(void){ | |
| 1060 | + db_find_and_open_repository(0,0); | |
| 1061 | + describe_artifacts_to_stdout("IN (SELECT rid FROM blob WHERE size<0)", 0); | |
| 1062 | +} | |
| 762 | 1063 | |
| 763 | 1064 | ADDED src/publish.c |
| 764 | 1065 | ADDED src/purge.c |
| --- src/name.c | |
| +++ src/name.c | |
| @@ -42,10 +42,44 @@ | |
| 42 | if( z[7]!='-') return 0; |
| 43 | if( !fossil_isdigit(z[8]) ) return 0; |
| 44 | if( !fossil_isdigit(z[9]) ) return 0; |
| 45 | return 1; |
| 46 | } |
| 47 | |
| 48 | /* |
| 49 | ** Convert a symbolic name into a RID. Acceptable forms: |
| 50 | ** |
| 51 | ** * SHA1 hash |
| @@ -66,20 +100,28 @@ | |
| 66 | ** Return the RID of the matching artifact. Or return 0 if the name does not |
| 67 | ** match any known object. Or return -1 if the name is ambiguous. |
| 68 | ** |
| 69 | ** The zType parameter specifies the type of artifact: ci, t, w, e, g. |
| 70 | ** If zType is NULL or "" or "*" then any type of artifact will serve. |
| 71 | ** zType is "ci" in most use cases since we are usually searching for |
| 72 | ** a check-in. |
| 73 | */ |
| 74 | int symbolic_name_to_rid(const char *zTag, const char *zType){ |
| 75 | int vid; |
| 76 | int rid = 0; |
| 77 | int nTag; |
| 78 | int i; |
| 79 | |
| 80 | if( zType==0 || zType[0]==0 ) zType = "*"; |
| 81 | if( zTag==0 || zTag[0]==0 ) return 0; |
| 82 | |
| 83 | /* special keyword: "tip" */ |
| 84 | if( fossil_strcmp(zTag, "tip")==0 && (zType[0]=='*' || zType[0]=='c') ){ |
| 85 | rid = db_int(0, |
| @@ -151,41 +193,18 @@ | |
| 151 | " AND tagxref.tagid=tag.tagid AND tagxref.tagtype>0 " |
| 152 | " AND event.objid=tagxref.rid " |
| 153 | " AND event.type GLOB '%q'", |
| 154 | &zTag[4], zType |
| 155 | ); |
| 156 | return rid; |
| 157 | } |
| 158 | |
| 159 | /* root:TAG -> The origin of the branch */ |
| 160 | if( memcmp(zTag, "root:", 5)==0 ){ |
| 161 | Stmt q; |
| 162 | int rc; |
| 163 | char *zBr; |
| 164 | rid = symbolic_name_to_rid(zTag+5, zType); |
| 165 | zBr = db_text("trunk","SELECT value FROM tagxref" |
| 166 | " WHERE rid=%d AND tagid=%d" |
| 167 | " AND tagtype>0", |
| 168 | rid, TAG_BRANCH); |
| 169 | db_prepare(&q, |
| 170 | "SELECT pid, EXISTS(SELECT 1 FROM tagxref" |
| 171 | " WHERE tagid=%d AND tagtype>0" |
| 172 | " AND value=%Q AND rid=plink.pid)" |
| 173 | " FROM plink" |
| 174 | " WHERE cid=:cid AND isprim", |
| 175 | TAG_BRANCH, zBr |
| 176 | ); |
| 177 | fossil_free(zBr); |
| 178 | do{ |
| 179 | db_reset(&q); |
| 180 | db_bind_int(&q, ":cid", rid); |
| 181 | rc = db_step(&q); |
| 182 | if( rc!=SQLITE_ROW ) break; |
| 183 | rid = db_column_int(&q, 0); |
| 184 | }while( db_column_int(&q, 1)==1 && rid>0 ); |
| 185 | db_finalize(&q); |
| 186 | return rid; |
| 187 | } |
| 188 | |
| 189 | /* symbolic-name ":" date-time */ |
| 190 | nTag = strlen(zTag); |
| 191 | for(i=0; i<nTag-10 && zTag[i]!=':'; i++){} |
| @@ -245,11 +264,14 @@ | |
| 245 | " AND tagxref.tagid=tag.tagid AND tagxref.tagtype>0 " |
| 246 | " AND event.objid=tagxref.rid " |
| 247 | " AND event.type GLOB '%q'", |
| 248 | zTag, zType |
| 249 | ); |
| 250 | if( rid>0 ) return rid; |
| 251 | |
| 252 | /* Undocumented: numeric tags get translated directly into the RID */ |
| 253 | if( memcmp(zTag, "rid:", 4)==0 ){ |
| 254 | zTag += 4; |
| 255 | for(i=0; fossil_isdigit(zTag[i]); i++){} |
| @@ -324,30 +346,25 @@ | |
| 324 | ** name_collisions searches through events, blobs, and tickets for |
| 325 | ** collisions of a given UUID based on its length on UUIDs no shorter |
| 326 | ** than 4 characters in length. |
| 327 | */ |
| 328 | int name_collisions(const char *zName){ |
| 329 | Stmt q; |
| 330 | int c = 0; /* count of collisions for zName */ |
| 331 | int nLen; /* length of zName */ |
| 332 | nLen = strlen(zName); |
| 333 | if( nLen>=4 && nLen<=UUID_SIZE && validate16(zName, nLen) ){ |
| 334 | db_prepare(&q, |
| 335 | "SELECT count(uuid) FROM" |
| 336 | " (SELECT substr(tkt_uuid, 1, %d) AS uuid FROM ticket" |
| 337 | " UNION ALL SELECT * FROM" |
| 338 | " (SELECT substr(tagname, 7, %d) FROM" |
| 339 | " tag WHERE tagname GLOB 'event-*')" |
| 340 | " UNION ALL SELECT * FROM" |
| 341 | " (SELECT substr(uuid, 1, %d) FROM blob))" |
| 342 | " WHERE uuid GLOB '%q*'" |
| 343 | " GROUP BY uuid HAVING count(uuid) > 1;", |
| 344 | nLen, nLen, nLen, zName); |
| 345 | if( db_step(&q)==SQLITE_ROW ){ |
| 346 | c = db_column_int(&q, 0); |
| 347 | } |
| 348 | db_finalize(&q); |
| 349 | } |
| 350 | return c; |
| 351 | } |
| 352 | |
| 353 | /* |
| @@ -391,18 +408,15 @@ | |
| 391 | int rid; |
| 392 | |
| 393 | if( zName==0 || zName[0]==0 ) return 0; |
| 394 | rid = symbolic_name_to_rid(zName, zType); |
| 395 | if( rid<0 ){ |
| 396 | fossil_error(1, "ambiguous name: %s", zName); |
| 397 | return 0; |
| 398 | }else if( rid==0 ){ |
| 399 | fossil_error(1, "not found: %s", zName); |
| 400 | return 0; |
| 401 | }else{ |
| 402 | return rid; |
| 403 | } |
| 404 | } |
| 405 | int name_to_rid(const char *zName){ |
| 406 | return name_to_typed_rid(zName, "*"); |
| 407 | } |
| 408 | |
| @@ -505,11 +519,11 @@ | |
| 505 | } |
| 506 | |
| 507 | /* |
| 508 | ** Generate a description of artifact "rid" |
| 509 | */ |
| 510 | static void whatis_rid(int rid, int verboseFlag){ |
| 511 | Stmt q; |
| 512 | int cnt; |
| 513 | |
| 514 | /* Basic information about the object. */ |
| 515 | db_prepare(&q, |
| @@ -657,21 +671,23 @@ | |
| 657 | void whatis_cmd(void){ |
| 658 | int rid; |
| 659 | const char *zName; |
| 660 | int verboseFlag; |
| 661 | int i; |
| 662 | db_find_and_open_repository(0,0); |
| 663 | verboseFlag = find_option("verbose","v",0)!=0; |
| 664 | |
| 665 | /* We should be done with options.. */ |
| 666 | verify_all_options(); |
| 667 | |
| 668 | if( g.argc<3 ) usage("whatis NAME ..."); |
| 669 | for(i=2; i<g.argc; i++){ |
| 670 | zName = g.argv[i]; |
| 671 | if( i>2 ) fossil_print("%.79c\n",'-'); |
| 672 | rid = symbolic_name_to_rid(zName, 0); |
| 673 | if( rid<0 ){ |
| 674 | Stmt q; |
| 675 | int cnt = 0; |
| 676 | fossil_print("name: %s (ambiguous)\n", zName); |
| 677 | db_prepare(&q, |
| @@ -757,5 +773,290 @@ | |
| 757 | while( db_step(&q)==SQLITE_ROW ){ |
| 758 | fossil_print("%s\n", db_column_text(&q, 0)); |
| 759 | } |
| 760 | db_finalize(&q); |
| 761 | } |
| 762 | |
| 763 | DDED src/publish.c |
| 764 | DDED src/purge.c |
| --- src/name.c | |
| +++ src/name.c | |
| @@ -42,10 +42,44 @@ | |
| 42 | if( z[7]!='-') return 0; |
| 43 | if( !fossil_isdigit(z[8]) ) return 0; |
| 44 | if( !fossil_isdigit(z[9]) ) return 0; |
| 45 | return 1; |
| 46 | } |
| 47 | |
| 48 | /* |
| 49 | ** Return the RID that is the "root" of the branch that contains |
| 50 | ** check-in "rid" if inBranch==0 or the first check-in in the branch |
| 51 | ** if inBranch==1. |
| 52 | */ |
| 53 | int start_of_branch(int rid, int inBranch){ |
| 54 | Stmt q; |
| 55 | int rc; |
| 56 | char *zBr; |
| 57 | zBr = db_text("trunk","SELECT value FROM tagxref" |
| 58 | " WHERE rid=%d AND tagid=%d" |
| 59 | " AND tagtype>0", |
| 60 | rid, TAG_BRANCH); |
| 61 | db_prepare(&q, |
| 62 | "SELECT pid, EXISTS(SELECT 1 FROM tagxref" |
| 63 | " WHERE tagid=%d AND tagtype>0" |
| 64 | " AND value=%Q AND rid=plink.pid)" |
| 65 | " FROM plink" |
| 66 | " WHERE cid=:cid AND isprim", |
| 67 | TAG_BRANCH, zBr |
| 68 | ); |
| 69 | fossil_free(zBr); |
| 70 | do{ |
| 71 | db_reset(&q); |
| 72 | db_bind_int(&q, ":cid", rid); |
| 73 | rc = db_step(&q); |
| 74 | if( rc!=SQLITE_ROW ) break; |
| 75 | if( inBranch && db_column_int(&q,1)==0 ) break; |
| 76 | rid = db_column_int(&q, 0); |
| 77 | }while( db_column_int(&q, 1)==1 && rid>0 ); |
| 78 | db_finalize(&q); |
| 79 | return rid; |
| 80 | } |
| 81 | |
| 82 | /* |
| 83 | ** Convert a symbolic name into a RID. Acceptable forms: |
| 84 | ** |
| 85 | ** * SHA1 hash |
| @@ -66,20 +100,28 @@ | |
| 100 | ** Return the RID of the matching artifact. Or return 0 if the name does not |
| 101 | ** match any known object. Or return -1 if the name is ambiguous. |
| 102 | ** |
| 103 | ** The zType parameter specifies the type of artifact: ci, t, w, e, g. |
| 104 | ** If zType is NULL or "" or "*" then any type of artifact will serve. |
| 105 | ** If zType is "br" then find the first check-in of the named branch |
| 106 | ** rather than the last. |
| 107 | ** zType is "ci" in most use cases since we are usually searching for |
| 108 | ** a check-in. |
| 109 | */ |
| 110 | int symbolic_name_to_rid(const char *zTag, const char *zType){ |
| 111 | int vid; |
| 112 | int rid = 0; |
| 113 | int nTag; |
| 114 | int i; |
| 115 | int startOfBranch = 0; |
| 116 | |
| 117 | if( zType==0 || zType[0]==0 ){ |
| 118 | zType = "*"; |
| 119 | }else if( zType[0]=='b' ){ |
| 120 | zType = "ci"; |
| 121 | startOfBranch = 1; |
| 122 | } |
| 123 | if( zTag==0 || zTag[0]==0 ) return 0; |
| 124 | |
| 125 | /* special keyword: "tip" */ |
| 126 | if( fossil_strcmp(zTag, "tip")==0 && (zType[0]=='*' || zType[0]=='c') ){ |
| 127 | rid = db_int(0, |
| @@ -151,41 +193,18 @@ | |
| 193 | " AND tagxref.tagid=tag.tagid AND tagxref.tagtype>0 " |
| 194 | " AND event.objid=tagxref.rid " |
| 195 | " AND event.type GLOB '%q'", |
| 196 | &zTag[4], zType |
| 197 | ); |
| 198 | if( startOfBranch ) rid = start_of_branch(rid,1); |
| 199 | return rid; |
| 200 | } |
| 201 | |
| 202 | /* root:TAG -> The origin of the branch */ |
| 203 | if( memcmp(zTag, "root:", 5)==0 ){ |
| 204 | rid = symbolic_name_to_rid(zTag+5, zType); |
| 205 | return start_of_branch(rid, 0); |
| 206 | } |
| 207 | |
| 208 | /* symbolic-name ":" date-time */ |
| 209 | nTag = strlen(zTag); |
| 210 | for(i=0; i<nTag-10 && zTag[i]!=':'; i++){} |
| @@ -245,11 +264,14 @@ | |
| 264 | " AND tagxref.tagid=tag.tagid AND tagxref.tagtype>0 " |
| 265 | " AND event.objid=tagxref.rid " |
| 266 | " AND event.type GLOB '%q'", |
| 267 | zTag, zType |
| 268 | ); |
| 269 | if( rid>0 ){ |
| 270 | if( startOfBranch ) rid = start_of_branch(rid,1); |
| 271 | return rid; |
| 272 | } |
| 273 | |
| 274 | /* Undocumented: numeric tags get translated directly into the RID */ |
| 275 | if( memcmp(zTag, "rid:", 4)==0 ){ |
| 276 | zTag += 4; |
| 277 | for(i=0; fossil_isdigit(zTag[i]); i++){} |
| @@ -324,30 +346,25 @@ | |
| 346 | ** name_collisions searches through events, blobs, and tickets for |
| 347 | ** collisions of a given UUID based on its length on UUIDs no shorter |
| 348 | ** than 4 characters in length. |
| 349 | */ |
| 350 | int name_collisions(const char *zName){ |
| 351 | int c = 0; /* count of collisions for zName */ |
| 352 | int nLen; /* length of zName */ |
| 353 | nLen = strlen(zName); |
| 354 | if( nLen>=4 && nLen<=UUID_SIZE && validate16(zName, nLen) ){ |
| 355 | c = db_int(0, |
| 356 | "SELECT" |
| 357 | " (SELECT count(*) FROM ticket" |
| 358 | " WHERE tkt_uuid GLOB '%q*') +" |
| 359 | " (SELECT count(*) FROM tag" |
| 360 | " WHERE tagname GLOB 'event-%q*') +" |
| 361 | " (SELECT count(*) FROM blob" |
| 362 | " WHERE uuid GLOB '%q*');", |
| 363 | zName, zName, zName |
| 364 | ); |
| 365 | if( c<2 ) c = 0; |
| 366 | } |
| 367 | return c; |
| 368 | } |
| 369 | |
| 370 | /* |
| @@ -391,18 +408,15 @@ | |
| 408 | int rid; |
| 409 | |
| 410 | if( zName==0 || zName[0]==0 ) return 0; |
| 411 | rid = symbolic_name_to_rid(zName, zType); |
| 412 | if( rid<0 ){ |
| 413 | fossil_fatal("ambiguous name: %s", zName); |
| 414 | }else if( rid==0 ){ |
| 415 | fossil_fatal("not found: %s", zName); |
| 416 | } |
| 417 | return rid; |
| 418 | } |
| 419 | int name_to_rid(const char *zName){ |
| 420 | return name_to_typed_rid(zName, "*"); |
| 421 | } |
| 422 | |
| @@ -505,11 +519,11 @@ | |
| 519 | } |
| 520 | |
| 521 | /* |
| 522 | ** Generate a description of artifact "rid" |
| 523 | */ |
| 524 | void whatis_rid(int rid, int verboseFlag){ |
| 525 | Stmt q; |
| 526 | int cnt; |
| 527 | |
| 528 | /* Basic information about the object. */ |
| 529 | db_prepare(&q, |
| @@ -657,21 +671,23 @@ | |
| 671 | void whatis_cmd(void){ |
| 672 | int rid; |
| 673 | const char *zName; |
| 674 | int verboseFlag; |
| 675 | int i; |
| 676 | const char *zType = 0; |
| 677 | db_find_and_open_repository(0,0); |
| 678 | verboseFlag = find_option("verbose","v",0)!=0; |
| 679 | zType = find_option("type",0,1); |
| 680 | |
| 681 | /* We should be done with options.. */ |
| 682 | verify_all_options(); |
| 683 | |
| 684 | if( g.argc<3 ) usage("whatis NAME ..."); |
| 685 | for(i=2; i<g.argc; i++){ |
| 686 | zName = g.argv[i]; |
| 687 | if( i>2 ) fossil_print("%.79c\n",'-'); |
| 688 | rid = symbolic_name_to_rid(zName, zType); |
| 689 | if( rid<0 ){ |
| 690 | Stmt q; |
| 691 | int cnt = 0; |
| 692 | fossil_print("name: %s (ambiguous)\n", zName); |
| 693 | db_prepare(&q, |
| @@ -757,5 +773,290 @@ | |
| 773 | while( db_step(&q)==SQLITE_ROW ){ |
| 774 | fossil_print("%s\n", db_column_text(&q, 0)); |
| 775 | } |
| 776 | db_finalize(&q); |
| 777 | } |
| 778 | |
| 779 | /* |
| 780 | ** Schema for the description table |
| 781 | */ |
| 782 | static const char zDescTab[] = |
| 783 | @ CREATE TEMP TABLE IF NOT EXISTS description( |
| 784 | @ rid INTEGER PRIMARY KEY, -- RID of the object |
| 785 | @ uuid TEXT, -- SHA1 hash of the object |
| 786 | @ ctime DATETIME, -- Time of creation |
| 787 | @ isPrivate BOOLEAN DEFAULT 0, -- True for unpublished artifacts |
| 788 | @ type TEXT, -- file, checkin, wiki, ticket, etc. |
| 789 | @ summary TEXT, -- Summary comment for the object |
| 790 | @ detail TEXT -- filename, checkin comment, etc |
| 791 | @ ); |
| 792 | ; |
| 793 | |
| 794 | /* |
| 795 | ** Create the description table if it does not already exists. |
| 796 | ** Populate fields of this table with descriptions for all artifacts |
| 797 | ** whose RID matches the SQL expression in zWhere. |
| 798 | */ |
| 799 | void describe_artifacts(const char *zWhere){ |
| 800 | db_multi_exec("%s", zDescTab/*safe-for-%s*/); |
| 801 | |
| 802 | /* Describe checkins */ |
| 803 | db_multi_exec( |
| 804 | "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n" |
| 805 | "SELECT blob.rid, blob.uuid, event.mtime, 'checkin',\n" |
| 806 | " 'checkin on ' || strftime('%%Y-%%m-%%d %%H:%%M',event.mtime)\n" |
| 807 | " FROM event, blob\n" |
| 808 | " WHERE (event.objid %s) AND event.type='ci'\n" |
| 809 | " AND event.objid=blob.rid;", |
| 810 | zWhere /*safe-for-%s*/ |
| 811 | ); |
| 812 | |
| 813 | /* Describe files */ |
| 814 | db_multi_exec( |
| 815 | "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n" |
| 816 | "SELECT blob.rid, blob.uuid, event.mtime, 'file', 'file '||filename.name\n" |
| 817 | " FROM mlink, blob, event, filename\n" |
| 818 | " WHERE (mlink.fid %s)\n" |
| 819 | " AND mlink.mid=event.objid\n" |
| 820 | " AND filename.fnid=mlink.fnid\n" |
| 821 | " AND mlink.fid=blob.rid;", |
| 822 | zWhere /*safe-for-%s*/ |
| 823 | ); |
| 824 | |
| 825 | /* Describe tags */ |
| 826 | db_multi_exec( |
| 827 | "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n" |
| 828 | "SELECT blob.rid, blob.uuid, tagxref.mtime, 'tag',\n" |
| 829 | " 'tag '||substr((SELECT uuid FROM blob WHERE rid=tagxref.rid),1,16)\n" |
| 830 | " FROM tagxref, blob\n" |
| 831 | " WHERE (tagxref.srcid %s) AND tagxref.srcid!=tagxref.rid\n" |
| 832 | " AND tagxref.srcid=blob.rid;", |
| 833 | zWhere /*safe-for-%s*/ |
| 834 | ); |
| 835 | |
| 836 | /* Cluster artifacts */ |
| 837 | db_multi_exec( |
| 838 | "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n" |
| 839 | "SELECT blob.rid, blob.uuid, tagxref.mtime, 'cluster', 'cluster'\n" |
| 840 | " FROM tagxref, blob\n" |
| 841 | " WHERE (tagxref.rid %s)\n" |
| 842 | " AND tagxref.tagid=(SELECT tagid FROM tag WHERE tagname='cluster')\n" |
| 843 | " AND blob.rid=tagxref.rid;", |
| 844 | zWhere /*safe-for-%s*/ |
| 845 | ); |
| 846 | |
| 847 | /* Ticket change artifacts */ |
| 848 | db_multi_exec( |
| 849 | "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n" |
| 850 | "SELECT blob.rid, blob.uuid, tagxref.mtime, 'ticket',\n" |
| 851 | " 'ticket '||substr(tag.tagname,5,21)\n" |
| 852 | " FROM tagxref, tag, blob\n" |
| 853 | " WHERE (tagxref.rid %s)\n" |
| 854 | " AND tag.tagid=tagxref.tagid\n" |
| 855 | " AND tag.tagname GLOB 'tkt-*'" |
| 856 | " AND blob.rid=tagxref.rid;", |
| 857 | zWhere /*safe-for-%s*/ |
| 858 | ); |
| 859 | |
| 860 | /* Wiki edit artifacts */ |
| 861 | db_multi_exec( |
| 862 | "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n" |
| 863 | "SELECT blob.rid, blob.uuid, tagxref.mtime, 'wiki',\n" |
| 864 | " printf('wiki \"%%s\"',substr(tag.tagname,6))\n" |
| 865 | " FROM tagxref, tag, blob\n" |
| 866 | " WHERE (tagxref.rid %s)\n" |
| 867 | " AND tag.tagid=tagxref.tagid\n" |
| 868 | " AND tag.tagname GLOB 'wiki-*'" |
| 869 | " AND blob.rid=tagxref.rid;", |
| 870 | zWhere /*safe-for-%s*/ |
| 871 | ); |
| 872 | |
| 873 | /* Event edit artifacts */ |
| 874 | db_multi_exec( |
| 875 | "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n" |
| 876 | "SELECT blob.rid, blob.uuid, tagxref.mtime, 'event',\n" |
| 877 | " 'event '||substr(tag.tagname,7)\n" |
| 878 | " FROM tagxref, tag, blob\n" |
| 879 | " WHERE (tagxref.rid %s)\n" |
| 880 | " AND tag.tagid=tagxref.tagid\n" |
| 881 | " AND tag.tagname GLOB 'event-*'" |
| 882 | " AND blob.rid=tagxref.rid;", |
| 883 | zWhere /*safe-for-%s*/ |
| 884 | ); |
| 885 | |
| 886 | /* Attachments */ |
| 887 | db_multi_exec( |
| 888 | "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n" |
| 889 | "SELECT blob.rid, blob.uuid, attachment.mtime, 'attach-control',\n" |
| 890 | " 'attachment-control for '||attachment.filename\n" |
| 891 | " FROM attachment, blob\n" |
| 892 | " WHERE (attachment.attachid %s)\n" |
| 893 | " AND blob.rid=attachment.attachid", |
| 894 | zWhere /*safe-for-%s*/ |
| 895 | ); |
| 896 | db_multi_exec( |
| 897 | "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n" |
| 898 | "SELECT blob.rid, blob.uuid, attachment.mtime, 'attachment',\n" |
| 899 | " 'attachment '||attachment.filename\n" |
| 900 | " FROM attachment, blob\n" |
| 901 | " WHERE (blob.rid %s)\n" |
| 902 | " AND blob.rid NOT IN (SELECT rid FROM description)\n" |
| 903 | " AND blob.uuid=attachment.src", |
| 904 | zWhere /*safe-for-%s*/ |
| 905 | ); |
| 906 | |
| 907 | /* Everything else */ |
| 908 | db_multi_exec( |
| 909 | "INSERT OR IGNORE INTO description(rid,uuid,type,summary)\n" |
| 910 | "SELECT blob.rid, blob.uuid," |
| 911 | " CASE WHEN blob.size<0 THEN 'phantom' ELSE '' END,\n" |
| 912 | " 'unknown'\n" |
| 913 | " FROM blob WHERE (blob.rid %s);", |
| 914 | zWhere /*safe-for-%s*/ |
| 915 | ); |
| 916 | |
| 917 | /* Mark private elements */ |
| 918 | db_multi_exec( |
| 919 | "UPDATE description SET isPrivate=1 WHERE rid IN private" |
| 920 | ); |
| 921 | } |
| 922 | |
| 923 | /* |
| 924 | ** Print the content of the description table on stdout |
| 925 | */ |
| 926 | int describe_artifacts_to_stdout(const char *zWhere, const char *zLabel){ |
| 927 | Stmt q; |
| 928 | int cnt = 0; |
| 929 | describe_artifacts(zWhere); |
| 930 | db_prepare(&q, |
| 931 | "SELECT uuid, summary, isPrivate\n" |
| 932 | " FROM description\n" |
| 933 | " ORDER BY ctime, type;" |
| 934 | ); |
| 935 | while( db_step(&q)==SQLITE_ROW ){ |
| 936 | if( zLabel ){ |
| 937 | fossil_print("%s\n", zLabel); |
| 938 | zLabel = 0; |
| 939 | } |
| 940 | fossil_print(" %.16s %s", db_column_text(&q,0), db_column_text(&q,1)); |
| 941 | if( db_column_int(&q,2) ) fossil_print(" (unpublished)"); |
| 942 | fossil_print("\n"); |
| 943 | cnt++; |
| 944 | } |
| 945 | db_finalize(&q); |
| 946 | db_multi_exec("DELETE FROM description;"); |
| 947 | return cnt; |
| 948 | } |
| 949 | |
| 950 | /* |
| 951 | ** COMMAND: test-describe-artifacts |
| 952 | ** |
| 953 | ** Usage: %fossil test-describe-artifacts [--from S] [--count N] |
| 954 | ** |
| 955 | ** Display a one-line description of every artifact. |
| 956 | */ |
| 957 | void test_describe_artifacts_cmd(void){ |
| 958 | int iFrom = 0; |
| 959 | int iCnt = 1000000; |
| 960 | const char *z; |
| 961 | char *zRange; |
| 962 | db_find_and_open_repository(0,0); |
| 963 | z = find_option("from",0,1); |
| 964 | if( z ) iFrom = atoi(z); |
| 965 | z = find_option("count",0,1); |
| 966 | if( z ) iCnt = atoi(z); |
| 967 | zRange = mprintf("BETWEEN %d AND %d", iFrom, iFrom+iCnt-1); |
| 968 | describe_artifacts_to_stdout(zRange, 0); |
| 969 | } |
| 970 | |
| 971 | /* |
| 972 | ** WEBPAGE: bloblist |
| 973 | ** |
| 974 | ** Return a page showing all artifacts in the repository. Query parameters: |
| 975 | ** |
| 976 | ** n=N Show N artifacts |
| 977 | ** s=S Start with artifact number S |
| 978 | */ |
| 979 | void bloblist_page(void){ |
| 980 | Stmt q; |
| 981 | int s = atoi(PD("s","0")); |
| 982 | int n = atoi(PD("n","5000")); |
| 983 | int mx = db_int(0, "SELECT max(rid) FROM blob"); |
| 984 | char *zRange; |
| 985 | |
| 986 | login_check_credentials(); |
| 987 | if( !g.perm.Read ){ login_needed(); return; } |
| 988 | style_header("List Of Artifacts"); |
| 989 | if( mx>n && P("s")==0 ){ |
| 990 | int i; |
| 991 | @ <p>Select a range of artifacts to view:</p> |
| 992 | @ <ul> |
| 993 | for(i=1; i<=mx; i+=n){ |
| 994 | @ <li> %z(href("%R/bloblist?s=%d&n=%d",i,n)) |
| 995 | @ %d(i)..%d(i+n-1<mx?i+n-1:mx)</a> |
| 996 | } |
| 997 | @ </ul> |
| 998 | style_footer(); |
| 999 | return; |
| 1000 | } |
| 1001 | if( mx>n ){ |
| 1002 | style_submenu_element("Index", "Index", "bloblist"); |
| 1003 | } |
| 1004 | zRange = mprintf("BETWEEN %d AND %d", s, s+n-1); |
| 1005 | describe_artifacts(zRange); |
| 1006 | db_prepare(&q, |
| 1007 | "SELECT rid, uuid, summary, isPrivate FROM description ORDER BY rid" |
| 1008 | ); |
| 1009 | @ <table cellpadding="0" cellspacing="0"> |
| 1010 | while( db_step(&q)==SQLITE_ROW ){ |
| 1011 | int rid = db_column_int(&q,0); |
| 1012 | const char *zUuid = db_column_text(&q, 1); |
| 1013 | const char *zDesc = db_column_text(&q, 2); |
| 1014 | int isPriv = db_column_int(&q,2); |
| 1015 | @ <tr><td align="right">%d(rid)</td> |
| 1016 | @ <td> %z(href("%R/info/%s",zUuid))%s(zUuid)</a> </td> |
| 1017 | @ <td align="left">%h(zDesc)</td> |
| 1018 | if( isPriv ){ |
| 1019 | @ <td>(unpublished)</td> |
| 1020 | } |
| 1021 | @ </tr> |
| 1022 | } |
| 1023 | @ </table> |
| 1024 | db_finalize(&q); |
| 1025 | style_footer(); |
| 1026 | } |
| 1027 | |
| 1028 | /* |
| 1029 | ** COMMAND: test-unsent |
| 1030 | ** |
| 1031 | ** Usage: %fossil test-unsent |
| 1032 | ** |
| 1033 | ** Show all artifacts in the unsent table |
| 1034 | */ |
| 1035 | void test_unsent_cmd(void){ |
| 1036 | db_find_and_open_repository(0,0); |
| 1037 | describe_artifacts_to_stdout("IN unsent", 0); |
| 1038 | } |
| 1039 | |
| 1040 | /* |
| 1041 | ** COMMAND: test-unclustered |
| 1042 | ** |
| 1043 | ** Usage: %fossil test-unclustered |
| 1044 | ** |
| 1045 | ** Show all artifacts in the unclustered table |
| 1046 | */ |
| 1047 | void test_unclusterd_cmd(void){ |
| 1048 | db_find_and_open_repository(0,0); |
| 1049 | describe_artifacts_to_stdout("IN unclustered", 0); |
| 1050 | } |
| 1051 | |
| 1052 | /* |
| 1053 | ** COMMAND: test-phantoms |
| 1054 | ** |
| 1055 | ** Usage: %fossil test-phantoms |
| 1056 | ** |
| 1057 | ** Show all phantom artifacts |
| 1058 | */ |
| 1059 | void test_phatoms_cmd(void){ |
| 1060 | db_find_and_open_repository(0,0); |
| 1061 | describe_artifacts_to_stdout("IN (SELECT rid FROM blob WHERE size<0)", 0); |
| 1062 | } |
| 1063 | |
| 1064 | DDED src/publish.c |
| 1065 | DDED src/purge.c |
+2
| --- a/src/publish.c | ||
| +++ b/src/publish.c | ||
| @@ -0,0 +1,2 @@ | ||
| 1 | +/* | |
| 2 | +** Copyright (c) 2014 D. Richardat |
| --- a/src/publish.c | |
| +++ b/src/publish.c | |
| @@ -0,0 +1,2 @@ | |
| --- a/src/publish.c | |
| +++ b/src/publish.c | |
| @@ -0,0 +1,2 @@ | |
| 1 | /* |
| 2 | ** Copyright (c) 2014 D. Richardat |
+1
| --- a/src/purge.c | ||
| +++ b/src/purge.c | ||
| @@ -0,0 +1 @@ | ||
| 1 | +db_n |
| --- a/src/purge.c | |
| +++ b/src/purge.c | |
| @@ -0,0 +1 @@ | |
| --- a/src/purge.c | |
| +++ b/src/purge.c | |
| @@ -0,0 +1 @@ | |
| 1 | db_n |
+10
-5
| --- src/rebuild.c | ||
| +++ src/rebuild.c | ||
| @@ -348,11 +348,12 @@ | ||
| 348 | 348 | zTable = db_text(0, |
| 349 | 349 | "SELECT name FROM sqlite_master /*scan*/" |
| 350 | 350 | " WHERE type='table'" |
| 351 | 351 | " AND name NOT IN ('admin_log', 'blob','delta','rcvfrom','user'," |
| 352 | 352 | "'config','shun','private','reportfmt'," |
| 353 | - "'concealed','accesslog','modreq')" | |
| 353 | + "'concealed','accesslog','modreq'," | |
| 354 | + "'purgeevent','purgeitem')" | |
| 354 | 355 | " AND name NOT GLOB 'sqlite_*'" |
| 355 | 356 | " AND name NOT GLOB 'fx_*'" |
| 356 | 357 | ); |
| 357 | 358 | if( zTable==0 ) break; |
| 358 | 359 | db_multi_exec("DROP TABLE %Q", zTable); |
| @@ -829,14 +830,18 @@ | ||
| 829 | 830 | "DELETE FROM config WHERE name GLOB 'skin:*';" |
| 830 | 831 | "DELETE FROM config WHERE name GLOB 'subrepo:*';" |
| 831 | 832 | ); |
| 832 | 833 | if( bVerily ){ |
| 833 | 834 | db_multi_exec( |
| 834 | - "DELETE FROM concealed;" | |
| 835 | - "UPDATE rcvfrom SET ipaddr='unknown';" | |
| 836 | - "DROP TABLE IF EXISTS accesslog;" | |
| 837 | - "UPDATE user SET photo=NULL, info='';" | |
| 835 | + "DELETE FROM concealed;\n" | |
| 836 | + "UPDATE rcvfrom SET ipaddr='unknown';\n" | |
| 837 | + "DROP TABLE IF EXISTS accesslog;\n" | |
| 838 | + "UPDATE user SET photo=NULL, info='';\n" | |
| 839 | + "DROP TABLE IF EXISTS purgeevent;\n" | |
| 840 | + "DROP TABLE IF EXISTS purgeitem;\n" | |
| 841 | + "DROP TABLE IF EXISTS admin_log;\n" | |
| 842 | + "DROP TABLE IF EXISTS vcache;\n" | |
| 838 | 843 | ); |
| 839 | 844 | } |
| 840 | 845 | } |
| 841 | 846 | if( !bNeedRebuild ){ |
| 842 | 847 | db_end_transaction(0); |
| 843 | 848 |
| --- src/rebuild.c | |
| +++ src/rebuild.c | |
| @@ -348,11 +348,12 @@ | |
| 348 | zTable = db_text(0, |
| 349 | "SELECT name FROM sqlite_master /*scan*/" |
| 350 | " WHERE type='table'" |
| 351 | " AND name NOT IN ('admin_log', 'blob','delta','rcvfrom','user'," |
| 352 | "'config','shun','private','reportfmt'," |
| 353 | "'concealed','accesslog','modreq')" |
| 354 | " AND name NOT GLOB 'sqlite_*'" |
| 355 | " AND name NOT GLOB 'fx_*'" |
| 356 | ); |
| 357 | if( zTable==0 ) break; |
| 358 | db_multi_exec("DROP TABLE %Q", zTable); |
| @@ -829,14 +830,18 @@ | |
| 829 | "DELETE FROM config WHERE name GLOB 'skin:*';" |
| 830 | "DELETE FROM config WHERE name GLOB 'subrepo:*';" |
| 831 | ); |
| 832 | if( bVerily ){ |
| 833 | db_multi_exec( |
| 834 | "DELETE FROM concealed;" |
| 835 | "UPDATE rcvfrom SET ipaddr='unknown';" |
| 836 | "DROP TABLE IF EXISTS accesslog;" |
| 837 | "UPDATE user SET photo=NULL, info='';" |
| 838 | ); |
| 839 | } |
| 840 | } |
| 841 | if( !bNeedRebuild ){ |
| 842 | db_end_transaction(0); |
| 843 |
| --- src/rebuild.c | |
| +++ src/rebuild.c | |
| @@ -348,11 +348,12 @@ | |
| 348 | zTable = db_text(0, |
| 349 | "SELECT name FROM sqlite_master /*scan*/" |
| 350 | " WHERE type='table'" |
| 351 | " AND name NOT IN ('admin_log', 'blob','delta','rcvfrom','user'," |
| 352 | "'config','shun','private','reportfmt'," |
| 353 | "'concealed','accesslog','modreq'," |
| 354 | "'purgeevent','purgeitem')" |
| 355 | " AND name NOT GLOB 'sqlite_*'" |
| 356 | " AND name NOT GLOB 'fx_*'" |
| 357 | ); |
| 358 | if( zTable==0 ) break; |
| 359 | db_multi_exec("DROP TABLE %Q", zTable); |
| @@ -829,14 +830,18 @@ | |
| 830 | "DELETE FROM config WHERE name GLOB 'skin:*';" |
| 831 | "DELETE FROM config WHERE name GLOB 'subrepo:*';" |
| 832 | ); |
| 833 | if( bVerily ){ |
| 834 | db_multi_exec( |
| 835 | "DELETE FROM concealed;\n" |
| 836 | "UPDATE rcvfrom SET ipaddr='unknown';\n" |
| 837 | "DROP TABLE IF EXISTS accesslog;\n" |
| 838 | "UPDATE user SET photo=NULL, info='';\n" |
| 839 | "DROP TABLE IF EXISTS purgeevent;\n" |
| 840 | "DROP TABLE IF EXISTS purgeitem;\n" |
| 841 | "DROP TABLE IF EXISTS admin_log;\n" |
| 842 | "DROP TABLE IF EXISTS vcache;\n" |
| 843 | ); |
| 844 | } |
| 845 | } |
| 846 | if( !bNeedRebuild ){ |
| 847 | db_end_transaction(0); |
| 848 |
+77
-21
| --- src/report.c | ||
| +++ src/report.c | ||
| @@ -922,42 +922,85 @@ | ||
| 922 | 922 | |
| 923 | 923 | /* |
| 924 | 924 | ** Output Javascript code that will enables sorting of the table with |
| 925 | 925 | ** the id zTableId by clicking. |
| 926 | 926 | ** |
| 927 | -** The javascript is derived from: | |
| 927 | +** The javascript was originally derived from: | |
| 928 | 928 | ** |
| 929 | 929 | ** http://www.webtoolkit.info/sortable-html-table.html |
| 930 | +** | |
| 931 | +** But there have been extensive modifications. | |
| 930 | 932 | ** |
| 931 | 933 | ** This variation allows column types to be expressed using the second |
| 932 | 934 | ** argument. Each character of the second argument represent a column. |
| 933 | -** "t" means sort as text. "n" means sort numerically. "x" means do not | |
| 934 | -** sort on this column. If there are fewer characters in zColumnTypes[] than | |
| 935 | -** their are columns, the all extra columns assume type "t" (text). | |
| 935 | +** | |
| 936 | +** t Sort by text | |
| 937 | +** n Sort numerically | |
| 938 | +** k Sort by the data-sortkey property | |
| 939 | +** x This column is not sortable | |
| 940 | +** | |
| 941 | +** If there are fewer characters in zColumnTypes[] than their are columns, | |
| 942 | +** the all extra columns assume type "t" (text). | |
| 943 | +** | |
| 944 | +** The third parameter is the column that was initially sorted (using 1-based | |
| 945 | +** column numbers, like SQL). Make this value 0 if none of the columns are | |
| 946 | +** initially sorted. Make the value negative if the column is initially sorted | |
| 947 | +** in reverse order. | |
| 948 | +** | |
| 949 | +** Clicking on the same column header twice in a row inverts the sort. | |
| 936 | 950 | */ |
| 937 | -void output_table_sorting_javascript(const char *zTableId, const char *zColumnTypes){ | |
| 951 | +void output_table_sorting_javascript( | |
| 952 | + const char *zTableId, /* ID of table to sort */ | |
| 953 | + const char *zColumnTypes, /* String for column types */ | |
| 954 | + int iInitSort /* Initially sorted column. Leftmost is 1. 0 for NONE */ | |
| 955 | +){ | |
| 938 | 956 | @ <script> |
| 939 | - @ function SortableTable(tableEl,columnTypes){ | |
| 957 | + @ function SortableTable(tableEl,columnTypes,initSort){ | |
| 940 | 958 | @ this.tbody = tableEl.getElementsByTagName('tbody'); |
| 959 | + @ this.columnTypes = columnTypes; | |
| 941 | 960 | @ this.sort = function (cell) { |
| 942 | 961 | @ var column = cell.cellIndex; |
| 943 | - @ var sortFn = cell.sortType=="n" ? this.sortNumeric : this.sortText; | |
| 962 | + @ var sortFn; | |
| 963 | + @ switch( cell.sortType ){ | |
| 964 | + @ case "n": sortFn = this.sortNumeric; break; | |
| 965 | + @ case "t": sortFn = this.sortText; break; | |
| 966 | + @ case "k": sortFn = this.sortKey; break; | |
| 967 | + @ case "x": return; | |
| 968 | + @ } | |
| 944 | 969 | @ this.sortIndex = column; |
| 945 | 970 | @ var newRows = new Array(); |
| 946 | 971 | @ for (j = 0; j < this.tbody[0].rows.length; j++) { |
| 947 | 972 | @ newRows[j] = this.tbody[0].rows[j]; |
| 948 | 973 | @ } |
| 949 | - @ newRows.sort(sortFn); | |
| 950 | - @ if (cell.getAttribute("sortdir") == 'down') { | |
| 951 | - @ newRows.reverse(); | |
| 952 | - @ cell.setAttribute('sortdir','up'); | |
| 953 | - @ } else { | |
| 954 | - @ cell.setAttribute('sortdir','down'); | |
| 974 | + @ if( this.sortIndex==Math.abs(this.prevColumn)-1 ){ | |
| 975 | + @ newRows.reverse(); | |
| 976 | + @ this.prevColumn = -this.prevColumn; | |
| 977 | + @ }else{ | |
| 978 | + @ newRows.sort(sortFn); | |
| 979 | + @ this.prevColumn = this.sortIndex+1; | |
| 955 | 980 | @ } |
| 956 | 981 | @ for (i=0;i<newRows.length;i++) { |
| 957 | 982 | @ this.tbody[0].appendChild(newRows[i]); |
| 958 | 983 | @ } |
| 984 | + @ this.setHdrIcons(); | |
| 985 | + @ } | |
| 986 | + @ this.setHdrIcons = function() { | |
| 987 | + @ for (var i=0; i<this.hdrRow.cells.length; i++) { | |
| 988 | + @ if( this.columnTypes[i]=='x' ) continue; | |
| 989 | + @ var sortType; | |
| 990 | + @ if( this.prevColumn==i+1 ){ | |
| 991 | + @ sortType = 'asc'; | |
| 992 | + @ }else if( this.prevColumn==(-1-i) ){ | |
| 993 | + @ sortType = 'desc' | |
| 994 | + @ }else{ | |
| 995 | + @ sortType = 'none'; | |
| 996 | + @ } | |
| 997 | + @ var hdrCell = this.hdrRow.cells[i]; | |
| 998 | + @ var clsName = hdrCell.className.replace(/\s*\bsort\s*\w+/, ''); | |
| 999 | + @ clsName += ' sort ' + sortType; | |
| 1000 | + @ hdrCell.className = clsName; | |
| 1001 | + @ } | |
| 959 | 1002 | @ } |
| 960 | 1003 | @ this.sortText = function(a,b) { |
| 961 | 1004 | @ var i = thisObject.sortIndex; |
| 962 | 1005 | @ aa = a.cells[i].textContent.replace(/^\W+/,'').toLowerCase(); |
| 963 | 1006 | @ bb = b.cells[i].textContent.replace(/^\W+/,'').toLowerCase(); |
| @@ -971,30 +1014,43 @@ | ||
| 971 | 1014 | @ if (isNaN(aa)) aa = 0; |
| 972 | 1015 | @ bb = parseFloat(b.cells[i].textContent); |
| 973 | 1016 | @ if (isNaN(bb)) bb = 0; |
| 974 | 1017 | @ return aa-bb; |
| 975 | 1018 | @ } |
| 976 | - @ var thisObject = this; | |
| 1019 | + @ this.sortKey = function(a,b) { | |
| 1020 | + @ var i = thisObject.sortIndex; | |
| 1021 | + @ aa = a.cells[i].getAttribute("data-sortkey"); | |
| 1022 | + @ bb = b.cells[i].getAttribute("data-sortkey"); | |
| 1023 | + @ if(aa==bb) return 0; | |
| 1024 | + @ if(aa<bb) return -1; | |
| 1025 | + @ return 1; | |
| 1026 | + @ } | |
| 977 | 1027 | @ var x = tableEl.getElementsByTagName('thead'); |
| 978 | 1028 | @ if(!(this.tbody && this.tbody[0].rows && this.tbody[0].rows.length>0)){ |
| 979 | 1029 | @ return; |
| 980 | 1030 | @ } |
| 981 | 1031 | @ if(x && x[0].rows && x[0].rows.length > 0) { |
| 982 | - @ var sortRow = x[0].rows[0]; | |
| 1032 | + @ this.hdrRow = x[0].rows[0]; | |
| 983 | 1033 | @ } else { |
| 984 | 1034 | @ return; |
| 985 | 1035 | @ } |
| 986 | - @ for (var i=0; i<sortRow.cells.length; i++) { | |
| 987 | - @ sortRow.cells[i].sTable = this; | |
| 988 | - @ sortRow.cells[i].sortType = columnTypes[i] || 't'; | |
| 989 | - @ sortRow.cells[i].onclick = function () { | |
| 1036 | + @ var thisObject = this; | |
| 1037 | + @ this.prevColumn = initSort; | |
| 1038 | + @ for (var i=0; i<this.hdrRow.cells.length; i++) { | |
| 1039 | + @ if( columnTypes[i]=='x' ) continue; | |
| 1040 | + @ var hdrcell = this.hdrRow.cells[i]; | |
| 1041 | + @ hdrcell.sTable = this; | |
| 1042 | + @ hdrcell.style.cursor = "pointer"; | |
| 1043 | + @ hdrcell.sortType = columnTypes[i] || 't'; | |
| 1044 | + @ hdrcell.onclick = function () { | |
| 990 | 1045 | @ this.sTable.sort(this); |
| 991 | 1046 | @ return false; |
| 992 | 1047 | @ } |
| 993 | 1048 | @ } |
| 1049 | + @ this.setHdrIcons() | |
| 994 | 1050 | @ } |
| 995 | - @ var t = new SortableTable(gebi("%s(zTableId)"),"%s(zColumnTypes)"); | |
| 1051 | + @ var t = new SortableTable(gebi("%s(zTableId)"),"%s(zColumnTypes)",%d(iInitSort)); | |
| 996 | 1052 | @ </script> |
| 997 | 1053 | } |
| 998 | 1054 | |
| 999 | 1055 | |
| 1000 | 1056 | /* |
| @@ -1086,11 +1142,11 @@ | ||
| 1086 | 1142 | if( zErr1 ){ |
| 1087 | 1143 | @ <p class="reportError">Error: %h(zErr1)</p> |
| 1088 | 1144 | }else if( zErr2 ){ |
| 1089 | 1145 | @ <p class="reportError">Error: %h(zErr2)</p> |
| 1090 | 1146 | } |
| 1091 | - output_table_sorting_javascript("reportTable",""); | |
| 1147 | + output_table_sorting_javascript("reportTable","",0); | |
| 1092 | 1148 | style_footer(); |
| 1093 | 1149 | }else{ |
| 1094 | 1150 | report_restrict_sql(&zErr1); |
| 1095 | 1151 | db_exec_readonly(g.db, zSql, output_tab_separated, &count, &zErr2); |
| 1096 | 1152 | report_unrestrict_sql(); |
| 1097 | 1153 |
| --- src/report.c | |
| +++ src/report.c | |
| @@ -922,42 +922,85 @@ | |
| 922 | |
| 923 | /* |
| 924 | ** Output Javascript code that will enables sorting of the table with |
| 925 | ** the id zTableId by clicking. |
| 926 | ** |
| 927 | ** The javascript is derived from: |
| 928 | ** |
| 929 | ** http://www.webtoolkit.info/sortable-html-table.html |
| 930 | ** |
| 931 | ** This variation allows column types to be expressed using the second |
| 932 | ** argument. Each character of the second argument represent a column. |
| 933 | ** "t" means sort as text. "n" means sort numerically. "x" means do not |
| 934 | ** sort on this column. If there are fewer characters in zColumnTypes[] than |
| 935 | ** their are columns, the all extra columns assume type "t" (text). |
| 936 | */ |
| 937 | void output_table_sorting_javascript(const char *zTableId, const char *zColumnTypes){ |
| 938 | @ <script> |
| 939 | @ function SortableTable(tableEl,columnTypes){ |
| 940 | @ this.tbody = tableEl.getElementsByTagName('tbody'); |
| 941 | @ this.sort = function (cell) { |
| 942 | @ var column = cell.cellIndex; |
| 943 | @ var sortFn = cell.sortType=="n" ? this.sortNumeric : this.sortText; |
| 944 | @ this.sortIndex = column; |
| 945 | @ var newRows = new Array(); |
| 946 | @ for (j = 0; j < this.tbody[0].rows.length; j++) { |
| 947 | @ newRows[j] = this.tbody[0].rows[j]; |
| 948 | @ } |
| 949 | @ newRows.sort(sortFn); |
| 950 | @ if (cell.getAttribute("sortdir") == 'down') { |
| 951 | @ newRows.reverse(); |
| 952 | @ cell.setAttribute('sortdir','up'); |
| 953 | @ } else { |
| 954 | @ cell.setAttribute('sortdir','down'); |
| 955 | @ } |
| 956 | @ for (i=0;i<newRows.length;i++) { |
| 957 | @ this.tbody[0].appendChild(newRows[i]); |
| 958 | @ } |
| 959 | @ } |
| 960 | @ this.sortText = function(a,b) { |
| 961 | @ var i = thisObject.sortIndex; |
| 962 | @ aa = a.cells[i].textContent.replace(/^\W+/,'').toLowerCase(); |
| 963 | @ bb = b.cells[i].textContent.replace(/^\W+/,'').toLowerCase(); |
| @@ -971,30 +1014,43 @@ | |
| 971 | @ if (isNaN(aa)) aa = 0; |
| 972 | @ bb = parseFloat(b.cells[i].textContent); |
| 973 | @ if (isNaN(bb)) bb = 0; |
| 974 | @ return aa-bb; |
| 975 | @ } |
| 976 | @ var thisObject = this; |
| 977 | @ var x = tableEl.getElementsByTagName('thead'); |
| 978 | @ if(!(this.tbody && this.tbody[0].rows && this.tbody[0].rows.length>0)){ |
| 979 | @ return; |
| 980 | @ } |
| 981 | @ if(x && x[0].rows && x[0].rows.length > 0) { |
| 982 | @ var sortRow = x[0].rows[0]; |
| 983 | @ } else { |
| 984 | @ return; |
| 985 | @ } |
| 986 | @ for (var i=0; i<sortRow.cells.length; i++) { |
| 987 | @ sortRow.cells[i].sTable = this; |
| 988 | @ sortRow.cells[i].sortType = columnTypes[i] || 't'; |
| 989 | @ sortRow.cells[i].onclick = function () { |
| 990 | @ this.sTable.sort(this); |
| 991 | @ return false; |
| 992 | @ } |
| 993 | @ } |
| 994 | @ } |
| 995 | @ var t = new SortableTable(gebi("%s(zTableId)"),"%s(zColumnTypes)"); |
| 996 | @ </script> |
| 997 | } |
| 998 | |
| 999 | |
| 1000 | /* |
| @@ -1086,11 +1142,11 @@ | |
| 1086 | if( zErr1 ){ |
| 1087 | @ <p class="reportError">Error: %h(zErr1)</p> |
| 1088 | }else if( zErr2 ){ |
| 1089 | @ <p class="reportError">Error: %h(zErr2)</p> |
| 1090 | } |
| 1091 | output_table_sorting_javascript("reportTable",""); |
| 1092 | style_footer(); |
| 1093 | }else{ |
| 1094 | report_restrict_sql(&zErr1); |
| 1095 | db_exec_readonly(g.db, zSql, output_tab_separated, &count, &zErr2); |
| 1096 | report_unrestrict_sql(); |
| 1097 |
| --- src/report.c | |
| +++ src/report.c | |
| @@ -922,42 +922,85 @@ | |
| 922 | |
| 923 | /* |
| 924 | ** Output Javascript code that will enables sorting of the table with |
| 925 | ** the id zTableId by clicking. |
| 926 | ** |
| 927 | ** The javascript was originally derived from: |
| 928 | ** |
| 929 | ** http://www.webtoolkit.info/sortable-html-table.html |
| 930 | ** |
| 931 | ** But there have been extensive modifications. |
| 932 | ** |
| 933 | ** This variation allows column types to be expressed using the second |
| 934 | ** argument. Each character of the second argument represent a column. |
| 935 | ** |
| 936 | ** t Sort by text |
| 937 | ** n Sort numerically |
| 938 | ** k Sort by the data-sortkey property |
| 939 | ** x This column is not sortable |
| 940 | ** |
| 941 | ** If there are fewer characters in zColumnTypes[] than their are columns, |
| 942 | ** the all extra columns assume type "t" (text). |
| 943 | ** |
| 944 | ** The third parameter is the column that was initially sorted (using 1-based |
| 945 | ** column numbers, like SQL). Make this value 0 if none of the columns are |
| 946 | ** initially sorted. Make the value negative if the column is initially sorted |
| 947 | ** in reverse order. |
| 948 | ** |
| 949 | ** Clicking on the same column header twice in a row inverts the sort. |
| 950 | */ |
| 951 | void output_table_sorting_javascript( |
| 952 | const char *zTableId, /* ID of table to sort */ |
| 953 | const char *zColumnTypes, /* String for column types */ |
| 954 | int iInitSort /* Initially sorted column. Leftmost is 1. 0 for NONE */ |
| 955 | ){ |
| 956 | @ <script> |
| 957 | @ function SortableTable(tableEl,columnTypes,initSort){ |
| 958 | @ this.tbody = tableEl.getElementsByTagName('tbody'); |
| 959 | @ this.columnTypes = columnTypes; |
| 960 | @ this.sort = function (cell) { |
| 961 | @ var column = cell.cellIndex; |
| 962 | @ var sortFn; |
| 963 | @ switch( cell.sortType ){ |
| 964 | @ case "n": sortFn = this.sortNumeric; break; |
| 965 | @ case "t": sortFn = this.sortText; break; |
| 966 | @ case "k": sortFn = this.sortKey; break; |
| 967 | @ case "x": return; |
| 968 | @ } |
| 969 | @ this.sortIndex = column; |
| 970 | @ var newRows = new Array(); |
| 971 | @ for (j = 0; j < this.tbody[0].rows.length; j++) { |
| 972 | @ newRows[j] = this.tbody[0].rows[j]; |
| 973 | @ } |
| 974 | @ if( this.sortIndex==Math.abs(this.prevColumn)-1 ){ |
| 975 | @ newRows.reverse(); |
| 976 | @ this.prevColumn = -this.prevColumn; |
| 977 | @ }else{ |
| 978 | @ newRows.sort(sortFn); |
| 979 | @ this.prevColumn = this.sortIndex+1; |
| 980 | @ } |
| 981 | @ for (i=0;i<newRows.length;i++) { |
| 982 | @ this.tbody[0].appendChild(newRows[i]); |
| 983 | @ } |
| 984 | @ this.setHdrIcons(); |
| 985 | @ } |
| 986 | @ this.setHdrIcons = function() { |
| 987 | @ for (var i=0; i<this.hdrRow.cells.length; i++) { |
| 988 | @ if( this.columnTypes[i]=='x' ) continue; |
| 989 | @ var sortType; |
| 990 | @ if( this.prevColumn==i+1 ){ |
| 991 | @ sortType = 'asc'; |
| 992 | @ }else if( this.prevColumn==(-1-i) ){ |
| 993 | @ sortType = 'desc' |
| 994 | @ }else{ |
| 995 | @ sortType = 'none'; |
| 996 | @ } |
| 997 | @ var hdrCell = this.hdrRow.cells[i]; |
| 998 | @ var clsName = hdrCell.className.replace(/\s*\bsort\s*\w+/, ''); |
| 999 | @ clsName += ' sort ' + sortType; |
| 1000 | @ hdrCell.className = clsName; |
| 1001 | @ } |
| 1002 | @ } |
| 1003 | @ this.sortText = function(a,b) { |
| 1004 | @ var i = thisObject.sortIndex; |
| 1005 | @ aa = a.cells[i].textContent.replace(/^\W+/,'').toLowerCase(); |
| 1006 | @ bb = b.cells[i].textContent.replace(/^\W+/,'').toLowerCase(); |
| @@ -971,30 +1014,43 @@ | |
| 1014 | @ if (isNaN(aa)) aa = 0; |
| 1015 | @ bb = parseFloat(b.cells[i].textContent); |
| 1016 | @ if (isNaN(bb)) bb = 0; |
| 1017 | @ return aa-bb; |
| 1018 | @ } |
| 1019 | @ this.sortKey = function(a,b) { |
| 1020 | @ var i = thisObject.sortIndex; |
| 1021 | @ aa = a.cells[i].getAttribute("data-sortkey"); |
| 1022 | @ bb = b.cells[i].getAttribute("data-sortkey"); |
| 1023 | @ if(aa==bb) return 0; |
| 1024 | @ if(aa<bb) return -1; |
| 1025 | @ return 1; |
| 1026 | @ } |
| 1027 | @ var x = tableEl.getElementsByTagName('thead'); |
| 1028 | @ if(!(this.tbody && this.tbody[0].rows && this.tbody[0].rows.length>0)){ |
| 1029 | @ return; |
| 1030 | @ } |
| 1031 | @ if(x && x[0].rows && x[0].rows.length > 0) { |
| 1032 | @ this.hdrRow = x[0].rows[0]; |
| 1033 | @ } else { |
| 1034 | @ return; |
| 1035 | @ } |
| 1036 | @ var thisObject = this; |
| 1037 | @ this.prevColumn = initSort; |
| 1038 | @ for (var i=0; i<this.hdrRow.cells.length; i++) { |
| 1039 | @ if( columnTypes[i]=='x' ) continue; |
| 1040 | @ var hdrcell = this.hdrRow.cells[i]; |
| 1041 | @ hdrcell.sTable = this; |
| 1042 | @ hdrcell.style.cursor = "pointer"; |
| 1043 | @ hdrcell.sortType = columnTypes[i] || 't'; |
| 1044 | @ hdrcell.onclick = function () { |
| 1045 | @ this.sTable.sort(this); |
| 1046 | @ return false; |
| 1047 | @ } |
| 1048 | @ } |
| 1049 | @ this.setHdrIcons() |
| 1050 | @ } |
| 1051 | @ var t = new SortableTable(gebi("%s(zTableId)"),"%s(zColumnTypes)",%d(iInitSort)); |
| 1052 | @ </script> |
| 1053 | } |
| 1054 | |
| 1055 | |
| 1056 | /* |
| @@ -1086,11 +1142,11 @@ | |
| 1142 | if( zErr1 ){ |
| 1143 | @ <p class="reportError">Error: %h(zErr1)</p> |
| 1144 | }else if( zErr2 ){ |
| 1145 | @ <p class="reportError">Error: %h(zErr2)</p> |
| 1146 | } |
| 1147 | output_table_sorting_javascript("reportTable","",0); |
| 1148 | style_footer(); |
| 1149 | }else{ |
| 1150 | report_restrict_sql(&zErr1); |
| 1151 | db_exec_readonly(g.db, zSql, output_tab_separated, &count, &zErr2); |
| 1152 | report_unrestrict_sql(); |
| 1153 |
+2
-2
| --- src/schema.c | ||
| +++ src/schema.c | ||
| @@ -81,12 +81,12 @@ | ||
| 81 | 81 | @ uuid TEXT UNIQUE NOT NULL, -- SHA1 hash of the content |
| 82 | 82 | @ content BLOB, -- Compressed content of this record |
| 83 | 83 | @ CHECK( length(uuid)==40 AND rid>0 ) |
| 84 | 84 | @ ); |
| 85 | 85 | @ CREATE TABLE delta( |
| 86 | -@ rid INTEGER PRIMARY KEY, -- Record ID | |
| 87 | -@ srcid INTEGER NOT NULL REFERENCES blob -- Record holding source document | |
| 86 | +@ rid INTEGER PRIMARY KEY, -- BLOB that is delta-compressed | |
| 87 | +@ srcid INTEGER NOT NULL REFERENCES blob -- Baseline for delta-compression | |
| 88 | 88 | @ ); |
| 89 | 89 | @ CREATE INDEX delta_i1 ON delta(srcid); |
| 90 | 90 | @ |
| 91 | 91 | @ ------------------------------------------------------------------------- |
| 92 | 92 | @ -- The BLOB and DELTA tables above hold the "global state" of a Fossil |
| 93 | 93 |
| --- src/schema.c | |
| +++ src/schema.c | |
| @@ -81,12 +81,12 @@ | |
| 81 | @ uuid TEXT UNIQUE NOT NULL, -- SHA1 hash of the content |
| 82 | @ content BLOB, -- Compressed content of this record |
| 83 | @ CHECK( length(uuid)==40 AND rid>0 ) |
| 84 | @ ); |
| 85 | @ CREATE TABLE delta( |
| 86 | @ rid INTEGER PRIMARY KEY, -- Record ID |
| 87 | @ srcid INTEGER NOT NULL REFERENCES blob -- Record holding source document |
| 88 | @ ); |
| 89 | @ CREATE INDEX delta_i1 ON delta(srcid); |
| 90 | @ |
| 91 | @ ------------------------------------------------------------------------- |
| 92 | @ -- The BLOB and DELTA tables above hold the "global state" of a Fossil |
| 93 |
| --- src/schema.c | |
| +++ src/schema.c | |
| @@ -81,12 +81,12 @@ | |
| 81 | @ uuid TEXT UNIQUE NOT NULL, -- SHA1 hash of the content |
| 82 | @ content BLOB, -- Compressed content of this record |
| 83 | @ CHECK( length(uuid)==40 AND rid>0 ) |
| 84 | @ ); |
| 85 | @ CREATE TABLE delta( |
| 86 | @ rid INTEGER PRIMARY KEY, -- BLOB that is delta-compressed |
| 87 | @ srcid INTEGER NOT NULL REFERENCES blob -- Baseline for delta-compression |
| 88 | @ ); |
| 89 | @ CREATE INDEX delta_i1 ON delta(srcid); |
| 90 | @ |
| 91 | @ ------------------------------------------------------------------------- |
| 92 | @ -- The BLOB and DELTA tables above hold the "global state" of a Fossil |
| 93 |
+53
-37
| --- src/search.c | ||
| +++ src/search.c | ||
| @@ -13,27 +13,32 @@ | ||
| 13 | 13 | ** [email protected] |
| 14 | 14 | ** http://www.hwaci.com/drh/ |
| 15 | 15 | ** |
| 16 | 16 | ******************************************************************************* |
| 17 | 17 | ** |
| 18 | -** This file contains code to implement the "/doc" web page and related | |
| 19 | -** pages. | |
| 18 | +** This file contains code to implement a very simple search function | |
| 19 | +** against timeline comments, checkin content, wiki pages, and/or tickets. | |
| 20 | +** | |
| 21 | +** The search is full-text like in that it is looking for words and ignores | |
| 22 | +** punctuation and capitalization. But it is more akin to "grep" in that | |
| 23 | +** it scans the entire corpus for the search, and it does not support the | |
| 24 | +** full functionality of FTS4. | |
| 20 | 25 | */ |
| 21 | 26 | #include "config.h" |
| 22 | 27 | #include "search.h" |
| 23 | 28 | #include <assert.h> |
| 24 | 29 | |
| 25 | 30 | #if INTERFACE |
| 26 | 31 | /* |
| 27 | -** A compiled search patter | |
| 32 | +** A compiled search pattern | |
| 28 | 33 | */ |
| 29 | 34 | struct Search { |
| 30 | - int nTerm; | |
| 31 | - struct srchTerm { | |
| 32 | - char *z; | |
| 33 | - int n; | |
| 34 | - } a[8]; | |
| 35 | + int nTerm; /* Number of search terms */ | |
| 36 | + struct srchTerm { /* For each search term */ | |
| 37 | + char *z; /* Text */ | |
| 38 | + int n; /* length */ | |
| 39 | + } a[8]; | |
| 35 | 40 | }; |
| 36 | 41 | #endif |
| 37 | 42 | |
| 38 | 43 | /* |
| 39 | 44 | ** Compile a search pattern |
| @@ -98,43 +103,47 @@ | ||
| 98 | 103 | ** * 10 bonus points if the first occurrence is an exact match |
| 99 | 104 | ** * 1 additional point for each subsequent match of the same word |
| 100 | 105 | ** * Extra points of two consecutive words of the pattern are consecutive |
| 101 | 106 | ** in the document |
| 102 | 107 | */ |
| 103 | -int search_score(Search *p, const char *zDoc){ | |
| 108 | +int search_score(Search *p, int nDoc, const char **azDoc){ | |
| 104 | 109 | int iPrev = 999; |
| 105 | 110 | int score = 10; |
| 106 | 111 | int iBonus = 0; |
| 107 | - int i, j; | |
| 112 | + int i, j, k; | |
| 113 | + const char *zDoc; | |
| 108 | 114 | unsigned char seen[8]; |
| 109 | 115 | |
| 110 | 116 | memset(seen, 0, sizeof(seen)); |
| 111 | - if( zDoc==0 ) return score; | |
| 112 | - for(i=0; zDoc[i]; i++){ | |
| 113 | - char c = zDoc[i]; | |
| 114 | - if( isBoundary[c&0xff] ) continue; | |
| 115 | - for(j=0; j<p->nTerm; j++){ | |
| 116 | - int n = p->a[j].n; | |
| 117 | - if( sqlite3_strnicmp(p->a[j].z, &zDoc[i], n)==0 ){ | |
| 118 | - score += 1; | |
| 119 | - if( !seen[j] ){ | |
| 120 | - if( isBoundary[zDoc[i+n]&0xff] ) score += 10; | |
| 121 | - seen[j] = 1; | |
| 122 | - } | |
| 123 | - if( j==iPrev+1 ){ | |
| 124 | - score += iBonus; | |
| 125 | - } | |
| 126 | - i += n-1; | |
| 127 | - iPrev = j; | |
| 128 | - iBonus = 50; | |
| 129 | - break; | |
| 130 | - } | |
| 131 | - } | |
| 132 | - iBonus /= 2; | |
| 133 | - while( !isBoundary[zDoc[i]&0xff] ){ i++; } | |
| 134 | - } | |
| 135 | - | |
| 117 | + for(k=0; k<nDoc; k++){ | |
| 118 | + zDoc = azDoc[k]; | |
| 119 | + if( zDoc==0 ) continue; | |
| 120 | + for(i=0; zDoc[i]; i++){ | |
| 121 | + char c = zDoc[i]; | |
| 122 | + if( isBoundary[c&0xff] ) continue; | |
| 123 | + for(j=0; j<p->nTerm; j++){ | |
| 124 | + int n = p->a[j].n; | |
| 125 | + if( sqlite3_strnicmp(p->a[j].z, &zDoc[i], n)==0 ){ | |
| 126 | + score += 1; | |
| 127 | + if( !seen[j] ){ | |
| 128 | + if( isBoundary[zDoc[i+n]&0xff] ) score += 10; | |
| 129 | + seen[j] = 1; | |
| 130 | + } | |
| 131 | + if( j==iPrev+1 ){ | |
| 132 | + score += iBonus; | |
| 133 | + } | |
| 134 | + i += n-1; | |
| 135 | + iPrev = j; | |
| 136 | + iBonus = 50; | |
| 137 | + break; | |
| 138 | + } | |
| 139 | + } | |
| 140 | + iBonus /= 2; | |
| 141 | + while( !isBoundary[zDoc[i]&0xff] ){ i++; } | |
| 142 | + } | |
| 143 | + } | |
| 144 | + | |
| 136 | 145 | /* Every term must be seen or else the score is zero */ |
| 137 | 146 | for(j=0; j<p->nTerm; j++){ |
| 138 | 147 | if( !seen[j] ) return 0; |
| 139 | 148 | } |
| 140 | 149 | |
| @@ -149,21 +158,28 @@ | ||
| 149 | 158 | sqlite3_context *context, |
| 150 | 159 | int argc, |
| 151 | 160 | sqlite3_value **argv |
| 152 | 161 | ){ |
| 153 | 162 | Search *p = (Search*)sqlite3_user_data(context); |
| 154 | - int score = search_score(p, (const char*)sqlite3_value_text(argv[0])); | |
| 163 | + const char **azDoc; | |
| 164 | + int score; | |
| 165 | + int i; | |
| 166 | + | |
| 167 | + azDoc = fossil_malloc( sizeof(const char*)*(argc+1) ); | |
| 168 | + for(i=0; i<argc; i++) azDoc[i] = (const char*)sqlite3_value_text(argv[i]); | |
| 169 | + score = search_score(p, argc, azDoc); | |
| 170 | + fossil_free(azDoc); | |
| 155 | 171 | sqlite3_result_int(context, score); |
| 156 | 172 | } |
| 157 | 173 | |
| 158 | 174 | /* |
| 159 | 175 | ** Register the "score()" SQL function to score its input text |
| 160 | 176 | ** using the given Search object. Once this function is registered, |
| 161 | 177 | ** do not delete the Search object. |
| 162 | 178 | */ |
| 163 | 179 | void search_sql_setup(Search *p){ |
| 164 | - sqlite3_create_function(g.db, "score", 1, SQLITE_UTF8, p, | |
| 180 | + sqlite3_create_function(g.db, "score", -1, SQLITE_UTF8, p, | |
| 165 | 181 | search_score_sqlfunc, 0, 0); |
| 166 | 182 | } |
| 167 | 183 | |
| 168 | 184 | /* |
| 169 | 185 | ** Testing the search function. |
| 170 | 186 |
| --- src/search.c | |
| +++ src/search.c | |
| @@ -13,27 +13,32 @@ | |
| 13 | ** [email protected] |
| 14 | ** http://www.hwaci.com/drh/ |
| 15 | ** |
| 16 | ******************************************************************************* |
| 17 | ** |
| 18 | ** This file contains code to implement the "/doc" web page and related |
| 19 | ** pages. |
| 20 | */ |
| 21 | #include "config.h" |
| 22 | #include "search.h" |
| 23 | #include <assert.h> |
| 24 | |
| 25 | #if INTERFACE |
| 26 | /* |
| 27 | ** A compiled search patter |
| 28 | */ |
| 29 | struct Search { |
| 30 | int nTerm; |
| 31 | struct srchTerm { |
| 32 | char *z; |
| 33 | int n; |
| 34 | } a[8]; |
| 35 | }; |
| 36 | #endif |
| 37 | |
| 38 | /* |
| 39 | ** Compile a search pattern |
| @@ -98,43 +103,47 @@ | |
| 98 | ** * 10 bonus points if the first occurrence is an exact match |
| 99 | ** * 1 additional point for each subsequent match of the same word |
| 100 | ** * Extra points of two consecutive words of the pattern are consecutive |
| 101 | ** in the document |
| 102 | */ |
| 103 | int search_score(Search *p, const char *zDoc){ |
| 104 | int iPrev = 999; |
| 105 | int score = 10; |
| 106 | int iBonus = 0; |
| 107 | int i, j; |
| 108 | unsigned char seen[8]; |
| 109 | |
| 110 | memset(seen, 0, sizeof(seen)); |
| 111 | if( zDoc==0 ) return score; |
| 112 | for(i=0; zDoc[i]; i++){ |
| 113 | char c = zDoc[i]; |
| 114 | if( isBoundary[c&0xff] ) continue; |
| 115 | for(j=0; j<p->nTerm; j++){ |
| 116 | int n = p->a[j].n; |
| 117 | if( sqlite3_strnicmp(p->a[j].z, &zDoc[i], n)==0 ){ |
| 118 | score += 1; |
| 119 | if( !seen[j] ){ |
| 120 | if( isBoundary[zDoc[i+n]&0xff] ) score += 10; |
| 121 | seen[j] = 1; |
| 122 | } |
| 123 | if( j==iPrev+1 ){ |
| 124 | score += iBonus; |
| 125 | } |
| 126 | i += n-1; |
| 127 | iPrev = j; |
| 128 | iBonus = 50; |
| 129 | break; |
| 130 | } |
| 131 | } |
| 132 | iBonus /= 2; |
| 133 | while( !isBoundary[zDoc[i]&0xff] ){ i++; } |
| 134 | } |
| 135 | |
| 136 | /* Every term must be seen or else the score is zero */ |
| 137 | for(j=0; j<p->nTerm; j++){ |
| 138 | if( !seen[j] ) return 0; |
| 139 | } |
| 140 | |
| @@ -149,21 +158,28 @@ | |
| 149 | sqlite3_context *context, |
| 150 | int argc, |
| 151 | sqlite3_value **argv |
| 152 | ){ |
| 153 | Search *p = (Search*)sqlite3_user_data(context); |
| 154 | int score = search_score(p, (const char*)sqlite3_value_text(argv[0])); |
| 155 | sqlite3_result_int(context, score); |
| 156 | } |
| 157 | |
| 158 | /* |
| 159 | ** Register the "score()" SQL function to score its input text |
| 160 | ** using the given Search object. Once this function is registered, |
| 161 | ** do not delete the Search object. |
| 162 | */ |
| 163 | void search_sql_setup(Search *p){ |
| 164 | sqlite3_create_function(g.db, "score", 1, SQLITE_UTF8, p, |
| 165 | search_score_sqlfunc, 0, 0); |
| 166 | } |
| 167 | |
| 168 | /* |
| 169 | ** Testing the search function. |
| 170 |
| --- src/search.c | |
| +++ src/search.c | |
| @@ -13,27 +13,32 @@ | |
| 13 | ** [email protected] |
| 14 | ** http://www.hwaci.com/drh/ |
| 15 | ** |
| 16 | ******************************************************************************* |
| 17 | ** |
| 18 | ** This file contains code to implement a very simple search function |
| 19 | ** against timeline comments, checkin content, wiki pages, and/or tickets. |
| 20 | ** |
| 21 | ** The search is full-text like in that it is looking for words and ignores |
| 22 | ** punctuation and capitalization. But it is more akin to "grep" in that |
| 23 | ** it scans the entire corpus for the search, and it does not support the |
| 24 | ** full functionality of FTS4. |
| 25 | */ |
| 26 | #include "config.h" |
| 27 | #include "search.h" |
| 28 | #include <assert.h> |
| 29 | |
| 30 | #if INTERFACE |
| 31 | /* |
| 32 | ** A compiled search pattern |
| 33 | */ |
| 34 | struct Search { |
| 35 | int nTerm; /* Number of search terms */ |
| 36 | struct srchTerm { /* For each search term */ |
| 37 | char *z; /* Text */ |
| 38 | int n; /* length */ |
| 39 | } a[8]; |
| 40 | }; |
| 41 | #endif |
| 42 | |
| 43 | /* |
| 44 | ** Compile a search pattern |
| @@ -98,43 +103,47 @@ | |
| 103 | ** * 10 bonus points if the first occurrence is an exact match |
| 104 | ** * 1 additional point for each subsequent match of the same word |
| 105 | ** * Extra points of two consecutive words of the pattern are consecutive |
| 106 | ** in the document |
| 107 | */ |
| 108 | int search_score(Search *p, int nDoc, const char **azDoc){ |
| 109 | int iPrev = 999; |
| 110 | int score = 10; |
| 111 | int iBonus = 0; |
| 112 | int i, j, k; |
| 113 | const char *zDoc; |
| 114 | unsigned char seen[8]; |
| 115 | |
| 116 | memset(seen, 0, sizeof(seen)); |
| 117 | for(k=0; k<nDoc; k++){ |
| 118 | zDoc = azDoc[k]; |
| 119 | if( zDoc==0 ) continue; |
| 120 | for(i=0; zDoc[i]; i++){ |
| 121 | char c = zDoc[i]; |
| 122 | if( isBoundary[c&0xff] ) continue; |
| 123 | for(j=0; j<p->nTerm; j++){ |
| 124 | int n = p->a[j].n; |
| 125 | if( sqlite3_strnicmp(p->a[j].z, &zDoc[i], n)==0 ){ |
| 126 | score += 1; |
| 127 | if( !seen[j] ){ |
| 128 | if( isBoundary[zDoc[i+n]&0xff] ) score += 10; |
| 129 | seen[j] = 1; |
| 130 | } |
| 131 | if( j==iPrev+1 ){ |
| 132 | score += iBonus; |
| 133 | } |
| 134 | i += n-1; |
| 135 | iPrev = j; |
| 136 | iBonus = 50; |
| 137 | break; |
| 138 | } |
| 139 | } |
| 140 | iBonus /= 2; |
| 141 | while( !isBoundary[zDoc[i]&0xff] ){ i++; } |
| 142 | } |
| 143 | } |
| 144 | |
| 145 | /* Every term must be seen or else the score is zero */ |
| 146 | for(j=0; j<p->nTerm; j++){ |
| 147 | if( !seen[j] ) return 0; |
| 148 | } |
| 149 | |
| @@ -149,21 +158,28 @@ | |
| 158 | sqlite3_context *context, |
| 159 | int argc, |
| 160 | sqlite3_value **argv |
| 161 | ){ |
| 162 | Search *p = (Search*)sqlite3_user_data(context); |
| 163 | const char **azDoc; |
| 164 | int score; |
| 165 | int i; |
| 166 | |
| 167 | azDoc = fossil_malloc( sizeof(const char*)*(argc+1) ); |
| 168 | for(i=0; i<argc; i++) azDoc[i] = (const char*)sqlite3_value_text(argv[i]); |
| 169 | score = search_score(p, argc, azDoc); |
| 170 | fossil_free(azDoc); |
| 171 | sqlite3_result_int(context, score); |
| 172 | } |
| 173 | |
| 174 | /* |
| 175 | ** Register the "score()" SQL function to score its input text |
| 176 | ** using the given Search object. Once this function is registered, |
| 177 | ** do not delete the Search object. |
| 178 | */ |
| 179 | void search_sql_setup(Search *p){ |
| 180 | sqlite3_create_function(g.db, "score", -1, SQLITE_UTF8, p, |
| 181 | search_score_sqlfunc, 0, 0); |
| 182 | } |
| 183 | |
| 184 | /* |
| 185 | ** Testing the search function. |
| 186 |
+3
-3
| --- src/setup.c | ||
| +++ src/setup.c | ||
| @@ -105,15 +105,15 @@ | ||
| 105 | 105 | "Edit HTML text for an ad unit inserted after the menu bar"); |
| 106 | 106 | setup_menu_entry("Logo", "setup_logo", |
| 107 | 107 | "Change the logo and background images for the server"); |
| 108 | 108 | setup_menu_entry("Shunned", "shun", |
| 109 | 109 | "Show artifacts that are shunned by this repository"); |
| 110 | - setup_menu_entry("Log", "rcvfromlist", | |
| 110 | + setup_menu_entry("Artifact Receipts Log", "rcvfromlist", | |
| 111 | 111 | "A record of received artifacts and their sources"); |
| 112 | - setup_menu_entry("User-Log", "access_log", | |
| 112 | + setup_menu_entry("User Log", "access_log", | |
| 113 | 113 | "A record of login attempts"); |
| 114 | - setup_menu_entry("Admin-Log", "admin_log", | |
| 114 | + setup_menu_entry("Administrative Log", "admin_log", | |
| 115 | 115 | "View the admin_log entries"); |
| 116 | 116 | setup_menu_entry("Stats", "stat", |
| 117 | 117 | "Display repository statistics"); |
| 118 | 118 | setup_menu_entry("SQL", "admin_sql", |
| 119 | 119 | "Enter raw SQL commands"); |
| 120 | 120 |
| --- src/setup.c | |
| +++ src/setup.c | |
| @@ -105,15 +105,15 @@ | |
| 105 | "Edit HTML text for an ad unit inserted after the menu bar"); |
| 106 | setup_menu_entry("Logo", "setup_logo", |
| 107 | "Change the logo and background images for the server"); |
| 108 | setup_menu_entry("Shunned", "shun", |
| 109 | "Show artifacts that are shunned by this repository"); |
| 110 | setup_menu_entry("Log", "rcvfromlist", |
| 111 | "A record of received artifacts and their sources"); |
| 112 | setup_menu_entry("User-Log", "access_log", |
| 113 | "A record of login attempts"); |
| 114 | setup_menu_entry("Admin-Log", "admin_log", |
| 115 | "View the admin_log entries"); |
| 116 | setup_menu_entry("Stats", "stat", |
| 117 | "Display repository statistics"); |
| 118 | setup_menu_entry("SQL", "admin_sql", |
| 119 | "Enter raw SQL commands"); |
| 120 |
| --- src/setup.c | |
| +++ src/setup.c | |
| @@ -105,15 +105,15 @@ | |
| 105 | "Edit HTML text for an ad unit inserted after the menu bar"); |
| 106 | setup_menu_entry("Logo", "setup_logo", |
| 107 | "Change the logo and background images for the server"); |
| 108 | setup_menu_entry("Shunned", "shun", |
| 109 | "Show artifacts that are shunned by this repository"); |
| 110 | setup_menu_entry("Artifact Receipts Log", "rcvfromlist", |
| 111 | "A record of received artifacts and their sources"); |
| 112 | setup_menu_entry("User Log", "access_log", |
| 113 | "A record of login attempts"); |
| 114 | setup_menu_entry("Administrative Log", "admin_log", |
| 115 | "View the admin_log entries"); |
| 116 | setup_menu_entry("Stats", "stat", |
| 117 | "Display repository statistics"); |
| 118 | setup_menu_entry("SQL", "admin_sql", |
| 119 | "Enter raw SQL commands"); |
| 120 |
+41
-13
| --- src/shun.c | ||
| +++ src/shun.c | ||
| @@ -295,37 +295,50 @@ | ||
| 295 | 295 | ** |
| 296 | 296 | ** Show a listing of RCVFROM table entries. |
| 297 | 297 | */ |
| 298 | 298 | void rcvfromlist_page(void){ |
| 299 | 299 | int ofst = atoi(PD("ofst","0")); |
| 300 | + int showAll = P("all")!=0; | |
| 300 | 301 | int cnt; |
| 301 | 302 | Stmt q; |
| 302 | 303 | |
| 303 | 304 | login_check_credentials(); |
| 304 | 305 | if( !g.perm.Admin ){ |
| 305 | 306 | login_needed(); |
| 306 | 307 | } |
| 307 | - style_header("Content Sources"); | |
| 308 | + style_header("Artifact Receipts"); | |
| 309 | + if( showAll ){ | |
| 310 | + ofst = 0; | |
| 311 | + }else{ | |
| 312 | + style_submenu_element("All", "All", "rcvfromlist?all=1"); | |
| 313 | + } | |
| 308 | 314 | if( ofst>0 ){ |
| 309 | 315 | style_submenu_element("Newer", "Newer", "rcvfromlist?ofst=%d", |
| 310 | 316 | ofst>30 ? ofst-30 : 0); |
| 311 | 317 | } |
| 318 | + db_multi_exec( | |
| 319 | + "CREATE TEMP TABLE rcvidUsed(x INTEGER PRIMARY KEY);" | |
| 320 | + "INSERT OR IGNORE INTO rcvidUsed(x) SELECT rcvid FROM blob;" | |
| 321 | + ); | |
| 312 | 322 | db_prepare(&q, |
| 313 | - "SELECT rcvid, login, datetime(rcvfrom.mtime), rcvfrom.ipaddr" | |
| 323 | + "SELECT rcvid, login, datetime(rcvfrom.mtime), rcvfrom.ipaddr," | |
| 324 | + " EXISTS(SELECT 1 FROM rcvidUsed WHERE x=rcvfrom.rcvid)" | |
| 314 | 325 | " FROM rcvfrom LEFT JOIN user USING(uid)" |
| 315 | - " ORDER BY rcvid DESC LIMIT 31 OFFSET %d", | |
| 316 | - ofst | |
| 326 | + " ORDER BY rcvid DESC LIMIT %d OFFSET %d", | |
| 327 | + showAll ? -1 : 31, ofst | |
| 317 | 328 | ); |
| 318 | 329 | @ <p>Whenever new artifacts are added to the repository, either by |
| 319 | 330 | @ push or using the web interface, an entry is made in the RCVFROM table |
| 320 | 331 | @ to record the source of that artifact. This log facilitates |
| 321 | 332 | @ finding and fixing attempts to inject illicit content into the |
| 322 | 333 | @ repository.</p> |
| 323 | 334 | @ |
| 324 | 335 | @ <p>Click on the "rcvid" to show a list of specific artifacts received |
| 325 | 336 | @ by a transaction. After identifying illicit artifacts, remove them |
| 326 | - @ using the "Shun" feature.</p> | |
| 337 | + @ using the "Shun" button. If an "rcvid" is not hyperlinked, that means | |
| 338 | + @ all artifacts associated with that rcvid have already been shunned | |
| 339 | + @ or purged.</p> | |
| 327 | 340 | @ |
| 328 | 341 | @ <table cellpadding="0" cellspacing="0" border="0"> |
| 329 | 342 | @ <tr><th style="padding-right: 15px;text-align: right;">rcvid</th> |
| 330 | 343 | @ <th style="padding-right: 15px;text-align: left;">Date</th> |
| 331 | 344 | @ <th style="padding-right: 15px;text-align: left;">User</th> |
| @@ -334,17 +347,22 @@ | ||
| 334 | 347 | while( db_step(&q)==SQLITE_ROW ){ |
| 335 | 348 | int rcvid = db_column_int(&q, 0); |
| 336 | 349 | const char *zUser = db_column_text(&q, 1); |
| 337 | 350 | const char *zDate = db_column_text(&q, 2); |
| 338 | 351 | const char *zIpAddr = db_column_text(&q, 3); |
| 339 | - if( cnt==30 ){ | |
| 352 | + if( cnt==30 && !showAll ){ | |
| 340 | 353 | style_submenu_element("Older", "Older", |
| 341 | 354 | "rcvfromlist?ofst=%d", ofst+30); |
| 342 | 355 | }else{ |
| 343 | 356 | cnt++; |
| 344 | 357 | @ <tr> |
| 345 | - @ <td style="padding-right: 15px;text-align: right;"><a href="rcvfrom?rcvid=%d(rcvid)">%d(rcvid)</a></td> | |
| 358 | + if( db_column_int(&q,4) ){ | |
| 359 | + @ <td style="padding-right: 15px;text-align: right;"> | |
| 360 | + @ <a href="rcvfrom?rcvid=%d(rcvid)">%d(rcvid)</a></td> | |
| 361 | + }else{ | |
| 362 | + @ <td style="padding-right: 15px;text-align: right;">%d(rcvid)</td> | |
| 363 | + } | |
| 346 | 364 | @ <td style="padding-right: 15px;text-align: left;">%s(zDate)</td> |
| 347 | 365 | @ <td style="padding-right: 15px;text-align: left;">%h(zUser)</td> |
| 348 | 366 | @ <td style="text-align: left;">%s(zIpAddr)</td> |
| 349 | 367 | @ </tr> |
| 350 | 368 | } |
| @@ -365,22 +383,24 @@ | ||
| 365 | 383 | |
| 366 | 384 | login_check_credentials(); |
| 367 | 385 | if( !g.perm.Admin ){ |
| 368 | 386 | login_needed(); |
| 369 | 387 | } |
| 370 | - style_header("Content Source %d", rcvid); | |
| 388 | + style_header("Artifact Receipt %d", rcvid); | |
| 371 | 389 | if( db_exists( |
| 372 | 390 | "SELECT 1 FROM blob WHERE rcvid=%d AND" |
| 373 | 391 | " NOT EXISTS (SELECT 1 FROM shun WHERE shun.uuid=blob.uuid)", rcvid) |
| 374 | 392 | ){ |
| 375 | - style_submenu_element("Shun All", "Shun All", "shun?shun&rcvid=%d#addshun", rcvid); | |
| 393 | + style_submenu_element("Shun All", "Shun All", | |
| 394 | + "shun?shun&rcvid=%d#addshun", rcvid); | |
| 376 | 395 | } |
| 377 | 396 | if( db_exists( |
| 378 | 397 | "SELECT 1 FROM blob WHERE rcvid=%d AND" |
| 379 | 398 | " EXISTS (SELECT 1 FROM shun WHERE shun.uuid=blob.uuid)", rcvid) |
| 380 | 399 | ){ |
| 381 | - style_submenu_element("Unshun All", "Unshun All", "shun?accept&rcvid=%d#delshun", rcvid); | |
| 400 | + style_submenu_element("Unshun All", "Unshun All", | |
| 401 | + "shun?accept&rcvid=%d#delshun", rcvid); | |
| 382 | 402 | } |
| 383 | 403 | db_prepare(&q, |
| 384 | 404 | "SELECT login, datetime(rcvfrom.mtime), rcvfrom.ipaddr" |
| 385 | 405 | " FROM rcvfrom LEFT JOIN user USING(uid)" |
| 386 | 406 | " WHERE rcvid=%d", |
| @@ -399,22 +419,30 @@ | ||
| 399 | 419 | @ <td valign="top">%s(zDate)</td></tr> |
| 400 | 420 | @ <tr><th valign="top" align="right">IP Address:</th> |
| 401 | 421 | @ <td valign="top">%s(zIpAddr)</td></tr> |
| 402 | 422 | } |
| 403 | 423 | db_finalize(&q); |
| 424 | + db_multi_exec( | |
| 425 | + "CREATE TEMP TABLE toshow(rid INTEGER PRIMARY KEY);" | |
| 426 | + "INSERT INTO toshow SELECT rid FROM blob WHERE rcvid=%d", rcvid | |
| 427 | + ); | |
| 428 | + describe_artifacts("IN toshow"); | |
| 404 | 429 | db_prepare(&q, |
| 405 | - "SELECT rid, uuid, size FROM blob WHERE rcvid=%d", rcvid | |
| 430 | + "SELECT blob.rid, blob.uuid, blob.size, description.summary\n" | |
| 431 | + " FROM blob LEFT JOIN description ON (blob.rid=description.rid)" | |
| 432 | + " WHERE blob.rcvid=%d", rcvid | |
| 406 | 433 | ); |
| 407 | 434 | @ <tr><th valign="top" align="right">Artifacts:</th> |
| 408 | 435 | @ <td valign="top"> |
| 409 | 436 | while( db_step(&q)==SQLITE_ROW ){ |
| 410 | - int rid = db_column_int(&q, 0); | |
| 411 | 437 | const char *zUuid = db_column_text(&q, 1); |
| 412 | 438 | int size = db_column_int(&q, 2); |
| 439 | + const char *zDesc = db_column_text(&q, 3); | |
| 440 | + if( zDesc==0 ) zDesc = ""; | |
| 413 | 441 | @ <a href="%s(g.zTop)/info/%s(zUuid)">%s(zUuid)</a> |
| 414 | - @ (rid: %d(rid), size: %d(size))<br /> | |
| 442 | + @ %h(zDesc) (size: %d(size))<br /> | |
| 415 | 443 | } |
| 416 | 444 | @ </td></tr> |
| 417 | 445 | @ </table> |
| 418 | 446 | db_finalize(&q); |
| 419 | 447 | style_footer(); |
| 420 | 448 | } |
| 421 | 449 | |
| 422 | 450 | ADDED src/sitemap.c |
| --- src/shun.c | |
| +++ src/shun.c | |
| @@ -295,37 +295,50 @@ | |
| 295 | ** |
| 296 | ** Show a listing of RCVFROM table entries. |
| 297 | */ |
| 298 | void rcvfromlist_page(void){ |
| 299 | int ofst = atoi(PD("ofst","0")); |
| 300 | int cnt; |
| 301 | Stmt q; |
| 302 | |
| 303 | login_check_credentials(); |
| 304 | if( !g.perm.Admin ){ |
| 305 | login_needed(); |
| 306 | } |
| 307 | style_header("Content Sources"); |
| 308 | if( ofst>0 ){ |
| 309 | style_submenu_element("Newer", "Newer", "rcvfromlist?ofst=%d", |
| 310 | ofst>30 ? ofst-30 : 0); |
| 311 | } |
| 312 | db_prepare(&q, |
| 313 | "SELECT rcvid, login, datetime(rcvfrom.mtime), rcvfrom.ipaddr" |
| 314 | " FROM rcvfrom LEFT JOIN user USING(uid)" |
| 315 | " ORDER BY rcvid DESC LIMIT 31 OFFSET %d", |
| 316 | ofst |
| 317 | ); |
| 318 | @ <p>Whenever new artifacts are added to the repository, either by |
| 319 | @ push or using the web interface, an entry is made in the RCVFROM table |
| 320 | @ to record the source of that artifact. This log facilitates |
| 321 | @ finding and fixing attempts to inject illicit content into the |
| 322 | @ repository.</p> |
| 323 | @ |
| 324 | @ <p>Click on the "rcvid" to show a list of specific artifacts received |
| 325 | @ by a transaction. After identifying illicit artifacts, remove them |
| 326 | @ using the "Shun" feature.</p> |
| 327 | @ |
| 328 | @ <table cellpadding="0" cellspacing="0" border="0"> |
| 329 | @ <tr><th style="padding-right: 15px;text-align: right;">rcvid</th> |
| 330 | @ <th style="padding-right: 15px;text-align: left;">Date</th> |
| 331 | @ <th style="padding-right: 15px;text-align: left;">User</th> |
| @@ -334,17 +347,22 @@ | |
| 334 | while( db_step(&q)==SQLITE_ROW ){ |
| 335 | int rcvid = db_column_int(&q, 0); |
| 336 | const char *zUser = db_column_text(&q, 1); |
| 337 | const char *zDate = db_column_text(&q, 2); |
| 338 | const char *zIpAddr = db_column_text(&q, 3); |
| 339 | if( cnt==30 ){ |
| 340 | style_submenu_element("Older", "Older", |
| 341 | "rcvfromlist?ofst=%d", ofst+30); |
| 342 | }else{ |
| 343 | cnt++; |
| 344 | @ <tr> |
| 345 | @ <td style="padding-right: 15px;text-align: right;"><a href="rcvfrom?rcvid=%d(rcvid)">%d(rcvid)</a></td> |
| 346 | @ <td style="padding-right: 15px;text-align: left;">%s(zDate)</td> |
| 347 | @ <td style="padding-right: 15px;text-align: left;">%h(zUser)</td> |
| 348 | @ <td style="text-align: left;">%s(zIpAddr)</td> |
| 349 | @ </tr> |
| 350 | } |
| @@ -365,22 +383,24 @@ | |
| 365 | |
| 366 | login_check_credentials(); |
| 367 | if( !g.perm.Admin ){ |
| 368 | login_needed(); |
| 369 | } |
| 370 | style_header("Content Source %d", rcvid); |
| 371 | if( db_exists( |
| 372 | "SELECT 1 FROM blob WHERE rcvid=%d AND" |
| 373 | " NOT EXISTS (SELECT 1 FROM shun WHERE shun.uuid=blob.uuid)", rcvid) |
| 374 | ){ |
| 375 | style_submenu_element("Shun All", "Shun All", "shun?shun&rcvid=%d#addshun", rcvid); |
| 376 | } |
| 377 | if( db_exists( |
| 378 | "SELECT 1 FROM blob WHERE rcvid=%d AND" |
| 379 | " EXISTS (SELECT 1 FROM shun WHERE shun.uuid=blob.uuid)", rcvid) |
| 380 | ){ |
| 381 | style_submenu_element("Unshun All", "Unshun All", "shun?accept&rcvid=%d#delshun", rcvid); |
| 382 | } |
| 383 | db_prepare(&q, |
| 384 | "SELECT login, datetime(rcvfrom.mtime), rcvfrom.ipaddr" |
| 385 | " FROM rcvfrom LEFT JOIN user USING(uid)" |
| 386 | " WHERE rcvid=%d", |
| @@ -399,22 +419,30 @@ | |
| 399 | @ <td valign="top">%s(zDate)</td></tr> |
| 400 | @ <tr><th valign="top" align="right">IP Address:</th> |
| 401 | @ <td valign="top">%s(zIpAddr)</td></tr> |
| 402 | } |
| 403 | db_finalize(&q); |
| 404 | db_prepare(&q, |
| 405 | "SELECT rid, uuid, size FROM blob WHERE rcvid=%d", rcvid |
| 406 | ); |
| 407 | @ <tr><th valign="top" align="right">Artifacts:</th> |
| 408 | @ <td valign="top"> |
| 409 | while( db_step(&q)==SQLITE_ROW ){ |
| 410 | int rid = db_column_int(&q, 0); |
| 411 | const char *zUuid = db_column_text(&q, 1); |
| 412 | int size = db_column_int(&q, 2); |
| 413 | @ <a href="%s(g.zTop)/info/%s(zUuid)">%s(zUuid)</a> |
| 414 | @ (rid: %d(rid), size: %d(size))<br /> |
| 415 | } |
| 416 | @ </td></tr> |
| 417 | @ </table> |
| 418 | db_finalize(&q); |
| 419 | style_footer(); |
| 420 | } |
| 421 | |
| 422 | DDED src/sitemap.c |
| --- src/shun.c | |
| +++ src/shun.c | |
| @@ -295,37 +295,50 @@ | |
| 295 | ** |
| 296 | ** Show a listing of RCVFROM table entries. |
| 297 | */ |
| 298 | void rcvfromlist_page(void){ |
| 299 | int ofst = atoi(PD("ofst","0")); |
| 300 | int showAll = P("all")!=0; |
| 301 | int cnt; |
| 302 | Stmt q; |
| 303 | |
| 304 | login_check_credentials(); |
| 305 | if( !g.perm.Admin ){ |
| 306 | login_needed(); |
| 307 | } |
| 308 | style_header("Artifact Receipts"); |
| 309 | if( showAll ){ |
| 310 | ofst = 0; |
| 311 | }else{ |
| 312 | style_submenu_element("All", "All", "rcvfromlist?all=1"); |
| 313 | } |
| 314 | if( ofst>0 ){ |
| 315 | style_submenu_element("Newer", "Newer", "rcvfromlist?ofst=%d", |
| 316 | ofst>30 ? ofst-30 : 0); |
| 317 | } |
| 318 | db_multi_exec( |
| 319 | "CREATE TEMP TABLE rcvidUsed(x INTEGER PRIMARY KEY);" |
| 320 | "INSERT OR IGNORE INTO rcvidUsed(x) SELECT rcvid FROM blob;" |
| 321 | ); |
| 322 | db_prepare(&q, |
| 323 | "SELECT rcvid, login, datetime(rcvfrom.mtime), rcvfrom.ipaddr," |
| 324 | " EXISTS(SELECT 1 FROM rcvidUsed WHERE x=rcvfrom.rcvid)" |
| 325 | " FROM rcvfrom LEFT JOIN user USING(uid)" |
| 326 | " ORDER BY rcvid DESC LIMIT %d OFFSET %d", |
| 327 | showAll ? -1 : 31, ofst |
| 328 | ); |
| 329 | @ <p>Whenever new artifacts are added to the repository, either by |
| 330 | @ push or using the web interface, an entry is made in the RCVFROM table |
| 331 | @ to record the source of that artifact. This log facilitates |
| 332 | @ finding and fixing attempts to inject illicit content into the |
| 333 | @ repository.</p> |
| 334 | @ |
| 335 | @ <p>Click on the "rcvid" to show a list of specific artifacts received |
| 336 | @ by a transaction. After identifying illicit artifacts, remove them |
| 337 | @ using the "Shun" button. If an "rcvid" is not hyperlinked, that means |
| 338 | @ all artifacts associated with that rcvid have already been shunned |
| 339 | @ or purged.</p> |
| 340 | @ |
| 341 | @ <table cellpadding="0" cellspacing="0" border="0"> |
| 342 | @ <tr><th style="padding-right: 15px;text-align: right;">rcvid</th> |
| 343 | @ <th style="padding-right: 15px;text-align: left;">Date</th> |
| 344 | @ <th style="padding-right: 15px;text-align: left;">User</th> |
| @@ -334,17 +347,22 @@ | |
| 347 | while( db_step(&q)==SQLITE_ROW ){ |
| 348 | int rcvid = db_column_int(&q, 0); |
| 349 | const char *zUser = db_column_text(&q, 1); |
| 350 | const char *zDate = db_column_text(&q, 2); |
| 351 | const char *zIpAddr = db_column_text(&q, 3); |
| 352 | if( cnt==30 && !showAll ){ |
| 353 | style_submenu_element("Older", "Older", |
| 354 | "rcvfromlist?ofst=%d", ofst+30); |
| 355 | }else{ |
| 356 | cnt++; |
| 357 | @ <tr> |
| 358 | if( db_column_int(&q,4) ){ |
| 359 | @ <td style="padding-right: 15px;text-align: right;"> |
| 360 | @ <a href="rcvfrom?rcvid=%d(rcvid)">%d(rcvid)</a></td> |
| 361 | }else{ |
| 362 | @ <td style="padding-right: 15px;text-align: right;">%d(rcvid)</td> |
| 363 | } |
| 364 | @ <td style="padding-right: 15px;text-align: left;">%s(zDate)</td> |
| 365 | @ <td style="padding-right: 15px;text-align: left;">%h(zUser)</td> |
| 366 | @ <td style="text-align: left;">%s(zIpAddr)</td> |
| 367 | @ </tr> |
| 368 | } |
| @@ -365,22 +383,24 @@ | |
| 383 | |
| 384 | login_check_credentials(); |
| 385 | if( !g.perm.Admin ){ |
| 386 | login_needed(); |
| 387 | } |
| 388 | style_header("Artifact Receipt %d", rcvid); |
| 389 | if( db_exists( |
| 390 | "SELECT 1 FROM blob WHERE rcvid=%d AND" |
| 391 | " NOT EXISTS (SELECT 1 FROM shun WHERE shun.uuid=blob.uuid)", rcvid) |
| 392 | ){ |
| 393 | style_submenu_element("Shun All", "Shun All", |
| 394 | "shun?shun&rcvid=%d#addshun", rcvid); |
| 395 | } |
| 396 | if( db_exists( |
| 397 | "SELECT 1 FROM blob WHERE rcvid=%d AND" |
| 398 | " EXISTS (SELECT 1 FROM shun WHERE shun.uuid=blob.uuid)", rcvid) |
| 399 | ){ |
| 400 | style_submenu_element("Unshun All", "Unshun All", |
| 401 | "shun?accept&rcvid=%d#delshun", rcvid); |
| 402 | } |
| 403 | db_prepare(&q, |
| 404 | "SELECT login, datetime(rcvfrom.mtime), rcvfrom.ipaddr" |
| 405 | " FROM rcvfrom LEFT JOIN user USING(uid)" |
| 406 | " WHERE rcvid=%d", |
| @@ -399,22 +419,30 @@ | |
| 419 | @ <td valign="top">%s(zDate)</td></tr> |
| 420 | @ <tr><th valign="top" align="right">IP Address:</th> |
| 421 | @ <td valign="top">%s(zIpAddr)</td></tr> |
| 422 | } |
| 423 | db_finalize(&q); |
| 424 | db_multi_exec( |
| 425 | "CREATE TEMP TABLE toshow(rid INTEGER PRIMARY KEY);" |
| 426 | "INSERT INTO toshow SELECT rid FROM blob WHERE rcvid=%d", rcvid |
| 427 | ); |
| 428 | describe_artifacts("IN toshow"); |
| 429 | db_prepare(&q, |
| 430 | "SELECT blob.rid, blob.uuid, blob.size, description.summary\n" |
| 431 | " FROM blob LEFT JOIN description ON (blob.rid=description.rid)" |
| 432 | " WHERE blob.rcvid=%d", rcvid |
| 433 | ); |
| 434 | @ <tr><th valign="top" align="right">Artifacts:</th> |
| 435 | @ <td valign="top"> |
| 436 | while( db_step(&q)==SQLITE_ROW ){ |
| 437 | const char *zUuid = db_column_text(&q, 1); |
| 438 | int size = db_column_int(&q, 2); |
| 439 | const char *zDesc = db_column_text(&q, 3); |
| 440 | if( zDesc==0 ) zDesc = ""; |
| 441 | @ <a href="%s(g.zTop)/info/%s(zUuid)">%s(zUuid)</a> |
| 442 | @ %h(zDesc) (size: %d(size))<br /> |
| 443 | } |
| 444 | @ </td></tr> |
| 445 | @ </table> |
| 446 | db_finalize(&q); |
| 447 | style_footer(); |
| 448 | } |
| 449 | |
| 450 | DDED src/sitemap.c |
+43
| --- a/src/sitemap.c | ||
| +++ b/src/sitemap.c | ||
| @@ -0,0 +1,43 @@ | ||
| 1 | +avtimeline?n=all&imeline?n=all& @ warps"))List of "Timewarp" Check-inTest Pages </ul></li>body_and_footer("sitemap"); | |
| 2 | + } | |
| 3 | +} | |
| 4 | +footer(); | |
| 5 | + } | |
| 6 | +} | |
| 7 | +?name=Sandbox"))SandboxHelphelp"))List of All Commands and Web@mimetype map1style_header("Site Map"); | |
| 8 | +style_footer(); | |
| 9 | +} | |
| 10 | +divul id="sitemap"> | |
| 11 | +</div> | |
| 12 | + style_footer(); | |
| 13 | +} | |
| 14 | +</librlist"))Branchesaglist"))TagsdTktli> | |
| 15 | + style_footer(); | |
| 16 | +} | |
| 17 | +?n=200} | |
| 18 | +line?n=all& @ warps"))List of "Timewarp" Check-inTest Pages </ul></li>body_and_footer("sitemap"); | |
| 19 | + } | |
| 20 | +} | |
| 21 | +footer(); | |
| 22 | + } | |
| 23 | +} | |
| 24 | +?name=Sandboxavtimeline?n=all&imeline?n=all& @ warps"))List of "Timewarp" Check-inTest Pages </ul></li>body_and_footer("sitemap"); | |
| 25 | + } | |
| 26 | +} | |
| 27 | +footer(); | |
| 28 | + @ </p> | |
| 29 | + @ | |
| 30 | +#endifq@N6,W@Rh,X@1B~,b:docsrch"))Search Project DocumeShow an incomplete list of@Uy,q@gW,7O@aw,c@linkest_li> | |
| 31 | + @ <ul>docsrc@ </@@ @ warps"))List of "Timewaavtimeline?n=all&imeline?n=aln=all&namechng"))All check-in@ </@@ </ul> | |
| 32 | + @ </liwi</a> | |
| 33 | + @ <ul> | |
| 34 | +q@N6,W@Rh,X@1B~,b:docsrch"))Se@ omplete list o@ @ warps"))List of "avtimelinew@ @ @ @ @ </ul> | |
| 35 | + @ </li@ </ul> | |
| 36 | + @ </liblobrtifacts</a></li> | |
| 37 | + in<ultree?Branches and Tags</a> | |
| 38 | + @ <uls"))List of "avtimelinew@ @ @ @ @ </ul> | |
| 39 | + @ </li@ </ul> | |
| 40 | + @ </liblobrtifactseline?n=aln=all&namechng"))All cul> | |
| 41 | +q@N6,W@Rh,X@1B~,b:docsrch"))Se@ omplete list o@ @ warps"))List of "avtimelinew@ @ @ @ @ </ul> | |
| 42 | + @ </li@ </ul> | |
| 43 | + @ </liblobrtifactsstat"))Status SummaAdministration0 |
| --- a/src/sitemap.c | |
| +++ b/src/sitemap.c | |
| @@ -0,0 +1,43 @@ | |
| --- a/src/sitemap.c | |
| +++ b/src/sitemap.c | |
| @@ -0,0 +1,43 @@ | |
| 1 | avtimeline?n=all&imeline?n=all& @ warps"))List of "Timewarp" Check-inTest Pages </ul></li>body_and_footer("sitemap"); |
| 2 | } |
| 3 | } |
| 4 | footer(); |
| 5 | } |
| 6 | } |
| 7 | ?name=Sandbox"))SandboxHelphelp"))List of All Commands and Web@mimetype map1style_header("Site Map"); |
| 8 | style_footer(); |
| 9 | } |
| 10 | divul id="sitemap"> |
| 11 | </div> |
| 12 | style_footer(); |
| 13 | } |
| 14 | </librlist"))Branchesaglist"))TagsdTktli> |
| 15 | style_footer(); |
| 16 | } |
| 17 | ?n=200} |
| 18 | line?n=all& @ warps"))List of "Timewarp" Check-inTest Pages </ul></li>body_and_footer("sitemap"); |
| 19 | } |
| 20 | } |
| 21 | footer(); |
| 22 | } |
| 23 | } |
| 24 | ?name=Sandboxavtimeline?n=all&imeline?n=all& @ warps"))List of "Timewarp" Check-inTest Pages </ul></li>body_and_footer("sitemap"); |
| 25 | } |
| 26 | } |
| 27 | footer(); |
| 28 | @ </p> |
| 29 | @ |
| 30 | #endifq@N6,W@Rh,X@1B~,b:docsrch"))Search Project DocumeShow an incomplete list of@Uy,q@gW,7O@aw,c@linkest_li> |
| 31 | @ <ul>docsrc@ </@@ @ warps"))List of "Timewaavtimeline?n=all&imeline?n=aln=all&namechng"))All check-in@ </@@ </ul> |
| 32 | @ </liwi</a> |
| 33 | @ <ul> |
| 34 | q@N6,W@Rh,X@1B~,b:docsrch"))Se@ omplete list o@ @ warps"))List of "avtimelinew@ @ @ @ @ </ul> |
| 35 | @ </li@ </ul> |
| 36 | @ </liblobrtifacts</a></li> |
| 37 | in<ultree?Branches and Tags</a> |
| 38 | @ <uls"))List of "avtimelinew@ @ @ @ @ </ul> |
| 39 | @ </li@ </ul> |
| 40 | @ </liblobrtifactseline?n=aln=all&namechng"))All cul> |
| 41 | q@N6,W@Rh,X@1B~,b:docsrch"))Se@ omplete list o@ @ warps"))List of "avtimelinew@ @ @ @ @ </ul> |
| 42 | @ </li@ </ul> |
| 43 | @ </liblobrtifactsstat"))Status SummaAdministration0 |
+21
-20
| --- src/sqlcmd.c | ||
| +++ src/sqlcmd.c | ||
| @@ -106,10 +106,24 @@ | ||
| 106 | 106 | sqlite3_result_blob(context, pOut, nOut, sqlite3_free); |
| 107 | 107 | }else{ |
| 108 | 108 | sqlite3_result_error(context, "input is not zlib compressed", -1); |
| 109 | 109 | } |
| 110 | 110 | } |
| 111 | + | |
| 112 | +/* | |
| 113 | +** Add the content(), compress(), and decompress() SQL functions to | |
| 114 | +** database connection db. | |
| 115 | +*/ | |
| 116 | +int add_content_sql_commands(sqlite3 *db){ | |
| 117 | + sqlite3_create_function(db, "content", 1, SQLITE_UTF8, 0, | |
| 118 | + sqlcmd_content, 0, 0); | |
| 119 | + sqlite3_create_function(db, "compress", 1, SQLITE_UTF8, 0, | |
| 120 | + sqlcmd_compress, 0, 0); | |
| 121 | + sqlite3_create_function(db, "decompress", 1, SQLITE_UTF8, 0, | |
| 122 | + sqlcmd_decompress, 0, 0); | |
| 123 | + return SQLITE_OK; | |
| 124 | +} | |
| 111 | 125 | |
| 112 | 126 | /* |
| 113 | 127 | ** This is the "automatic extension" initializer that runs right after |
| 114 | 128 | ** the connection to the repository database is opened. Set up the |
| 115 | 129 | ** database connection to be more useful to the human operator. |
| @@ -117,40 +131,27 @@ | ||
| 117 | 131 | static int sqlcmd_autoinit( |
| 118 | 132 | sqlite3 *db, |
| 119 | 133 | const char **pzErrMsg, |
| 120 | 134 | const void *notUsed |
| 121 | 135 | ){ |
| 122 | - char *zSql; | |
| 123 | - int rc = SQLITE_OK; | |
| 124 | - sqlite3_create_function(db, "content", 1, SQLITE_UTF8, 0, | |
| 125 | - sqlcmd_content, 0, 0); | |
| 126 | - sqlite3_create_function(db, "compress", 1, SQLITE_UTF8, 0, | |
| 127 | - sqlcmd_compress, 0, 0); | |
| 128 | - sqlite3_create_function(db, "decompress", 1, SQLITE_UTF8, 0, | |
| 129 | - sqlcmd_decompress, 0, 0); | |
| 136 | + add_content_sql_commands(db); | |
| 130 | 137 | re_add_sql_func(db); |
| 131 | - foci_register(db); | |
| 132 | 138 | g.zMainDbType = "repository"; |
| 139 | + foci_register(db); | |
| 133 | 140 | g.repositoryOpen = 1; |
| 134 | 141 | g.db = db; |
| 135 | - db_open_config(1); | |
| 136 | - if( g.zLocalDbName ){ | |
| 137 | - zSql = sqlite3_mprintf("ATTACH %Q AS localdb;", g.zLocalDbName); | |
| 138 | - rc = sqlite3_exec(db, zSql, 0, 0, 0); | |
| 139 | - sqlite3_free(zSql); | |
| 140 | - } | |
| 141 | - return rc; | |
| 142 | + return SQLITE_OK; | |
| 142 | 143 | } |
| 143 | 144 | |
| 144 | 145 | /* |
| 145 | 146 | ** COMMAND: sqlite3 |
| 146 | 147 | ** |
| 147 | -** Usage: %fossil sqlite3 ?SQL-COMMANDS? ?OPTIONS? | |
| 148 | +** Usage: %fossil sqlite3 ?DATABASE? ?OPTIONS? | |
| 148 | 149 | ** |
| 149 | -** Run the standalone sqlite3 command-line shell on the repository database | |
| 150 | -** for the current checkout, or whatever repository is specified by the | |
| 151 | -** -R command-line option. | |
| 150 | +** Run the standalone sqlite3 command-line shell on DATABASE with OPTIONS. | |
| 151 | +** If DATABASE is omitted, then the repository that serves the working | |
| 152 | +** directory is opened. | |
| 152 | 153 | ** |
| 153 | 154 | ** WARNING: Careless use of this command can corrupt a Fossil repository |
| 154 | 155 | ** in ways that are unrecoverable. Be sure you know what you are doing before |
| 155 | 156 | ** running any SQL commands that modifies the repository database. |
| 156 | 157 | */ |
| 157 | 158 |
| --- src/sqlcmd.c | |
| +++ src/sqlcmd.c | |
| @@ -106,10 +106,24 @@ | |
| 106 | sqlite3_result_blob(context, pOut, nOut, sqlite3_free); |
| 107 | }else{ |
| 108 | sqlite3_result_error(context, "input is not zlib compressed", -1); |
| 109 | } |
| 110 | } |
| 111 | |
| 112 | /* |
| 113 | ** This is the "automatic extension" initializer that runs right after |
| 114 | ** the connection to the repository database is opened. Set up the |
| 115 | ** database connection to be more useful to the human operator. |
| @@ -117,40 +131,27 @@ | |
| 117 | static int sqlcmd_autoinit( |
| 118 | sqlite3 *db, |
| 119 | const char **pzErrMsg, |
| 120 | const void *notUsed |
| 121 | ){ |
| 122 | char *zSql; |
| 123 | int rc = SQLITE_OK; |
| 124 | sqlite3_create_function(db, "content", 1, SQLITE_UTF8, 0, |
| 125 | sqlcmd_content, 0, 0); |
| 126 | sqlite3_create_function(db, "compress", 1, SQLITE_UTF8, 0, |
| 127 | sqlcmd_compress, 0, 0); |
| 128 | sqlite3_create_function(db, "decompress", 1, SQLITE_UTF8, 0, |
| 129 | sqlcmd_decompress, 0, 0); |
| 130 | re_add_sql_func(db); |
| 131 | foci_register(db); |
| 132 | g.zMainDbType = "repository"; |
| 133 | g.repositoryOpen = 1; |
| 134 | g.db = db; |
| 135 | db_open_config(1); |
| 136 | if( g.zLocalDbName ){ |
| 137 | zSql = sqlite3_mprintf("ATTACH %Q AS localdb;", g.zLocalDbName); |
| 138 | rc = sqlite3_exec(db, zSql, 0, 0, 0); |
| 139 | sqlite3_free(zSql); |
| 140 | } |
| 141 | return rc; |
| 142 | } |
| 143 | |
| 144 | /* |
| 145 | ** COMMAND: sqlite3 |
| 146 | ** |
| 147 | ** Usage: %fossil sqlite3 ?SQL-COMMANDS? ?OPTIONS? |
| 148 | ** |
| 149 | ** Run the standalone sqlite3 command-line shell on the repository database |
| 150 | ** for the current checkout, or whatever repository is specified by the |
| 151 | ** -R command-line option. |
| 152 | ** |
| 153 | ** WARNING: Careless use of this command can corrupt a Fossil repository |
| 154 | ** in ways that are unrecoverable. Be sure you know what you are doing before |
| 155 | ** running any SQL commands that modifies the repository database. |
| 156 | */ |
| 157 |
| --- src/sqlcmd.c | |
| +++ src/sqlcmd.c | |
| @@ -106,10 +106,24 @@ | |
| 106 | sqlite3_result_blob(context, pOut, nOut, sqlite3_free); |
| 107 | }else{ |
| 108 | sqlite3_result_error(context, "input is not zlib compressed", -1); |
| 109 | } |
| 110 | } |
| 111 | |
| 112 | /* |
| 113 | ** Add the content(), compress(), and decompress() SQL functions to |
| 114 | ** database connection db. |
| 115 | */ |
| 116 | int add_content_sql_commands(sqlite3 *db){ |
| 117 | sqlite3_create_function(db, "content", 1, SQLITE_UTF8, 0, |
| 118 | sqlcmd_content, 0, 0); |
| 119 | sqlite3_create_function(db, "compress", 1, SQLITE_UTF8, 0, |
| 120 | sqlcmd_compress, 0, 0); |
| 121 | sqlite3_create_function(db, "decompress", 1, SQLITE_UTF8, 0, |
| 122 | sqlcmd_decompress, 0, 0); |
| 123 | return SQLITE_OK; |
| 124 | } |
| 125 | |
| 126 | /* |
| 127 | ** This is the "automatic extension" initializer that runs right after |
| 128 | ** the connection to the repository database is opened. Set up the |
| 129 | ** database connection to be more useful to the human operator. |
| @@ -117,40 +131,27 @@ | |
| 131 | static int sqlcmd_autoinit( |
| 132 | sqlite3 *db, |
| 133 | const char **pzErrMsg, |
| 134 | const void *notUsed |
| 135 | ){ |
| 136 | add_content_sql_commands(db); |
| 137 | re_add_sql_func(db); |
| 138 | g.zMainDbType = "repository"; |
| 139 | foci_register(db); |
| 140 | g.repositoryOpen = 1; |
| 141 | g.db = db; |
| 142 | return SQLITE_OK; |
| 143 | } |
| 144 | |
| 145 | /* |
| 146 | ** COMMAND: sqlite3 |
| 147 | ** |
| 148 | ** Usage: %fossil sqlite3 ?DATABASE? ?OPTIONS? |
| 149 | ** |
| 150 | ** Run the standalone sqlite3 command-line shell on DATABASE with OPTIONS. |
| 151 | ** If DATABASE is omitted, then the repository that serves the working |
| 152 | ** directory is opened. |
| 153 | ** |
| 154 | ** WARNING: Careless use of this command can corrupt a Fossil repository |
| 155 | ** in ways that are unrecoverable. Be sure you know what you are doing before |
| 156 | ** running any SQL commands that modifies the repository database. |
| 157 | */ |
| 158 |
+580
-379
| --- src/sqlite3.c | ||
| +++ src/sqlite3.c | ||
| @@ -231,11 +231,11 @@ | ||
| 231 | 231 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 232 | 232 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 233 | 233 | */ |
| 234 | 234 | #define SQLITE_VERSION "3.8.8" |
| 235 | 235 | #define SQLITE_VERSION_NUMBER 3008008 |
| 236 | -#define SQLITE_SOURCE_ID "2014-11-28 13:35:03 24fa2e9832daaa5d68ee28a00c56c55f97a4da9e" | |
| 236 | +#define SQLITE_SOURCE_ID "2015-01-03 18:59:17 23d4c07eb81db5a5c6beb56b5820f0b6501f1fb6" | |
| 237 | 237 | |
| 238 | 238 | /* |
| 239 | 239 | ** CAPI3REF: Run-Time Library Version Numbers |
| 240 | 240 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 241 | 241 | ** |
| @@ -323,11 +323,11 @@ | ||
| 323 | 323 | ** This interface only reports on the compile-time mutex setting |
| 324 | 324 | ** of the [SQLITE_THREADSAFE] flag. If SQLite is compiled with |
| 325 | 325 | ** SQLITE_THREADSAFE=1 or =2 then mutexes are enabled by default but |
| 326 | 326 | ** can be fully or partially disabled using a call to [sqlite3_config()] |
| 327 | 327 | ** with the verbs [SQLITE_CONFIG_SINGLETHREAD], [SQLITE_CONFIG_MULTITHREAD], |
| 328 | -** or [SQLITE_CONFIG_MUTEX]. ^(The return value of the | |
| 328 | +** or [SQLITE_CONFIG_SERIALIZED]. ^(The return value of the | |
| 329 | 329 | ** sqlite3_threadsafe() function shows only the compile-time setting of |
| 330 | 330 | ** thread safety, not any run-time changes to that setting made by |
| 331 | 331 | ** sqlite3_config(). In other words, the return value from sqlite3_threadsafe() |
| 332 | 332 | ** is unchanged by calls to sqlite3_config().)^ |
| 333 | 333 | ** |
| @@ -1343,11 +1343,11 @@ | ||
| 1343 | 1343 | ** <li> SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED |
| 1344 | 1344 | ** <li> SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE |
| 1345 | 1345 | ** </ul> |
| 1346 | 1346 | ** |
| 1347 | 1347 | ** When unlocking, the same SHARED or EXCLUSIVE flag must be supplied as |
| 1348 | -** was given no the corresponding lock. | |
| 1348 | +** was given on the corresponding lock. | |
| 1349 | 1349 | ** |
| 1350 | 1350 | ** The xShmLock method can transition between unlocked and SHARED or |
| 1351 | 1351 | ** between unlocked and EXCLUSIVE. It cannot transition between SHARED |
| 1352 | 1352 | ** and EXCLUSIVE. |
| 1353 | 1353 | */ |
| @@ -1646,12 +1646,12 @@ | ||
| 1646 | 1646 | ** tracks memory usage, for example. </dd> |
| 1647 | 1647 | ** |
| 1648 | 1648 | ** [[SQLITE_CONFIG_MEMSTATUS]] <dt>SQLITE_CONFIG_MEMSTATUS</dt> |
| 1649 | 1649 | ** <dd> ^The SQLITE_CONFIG_MEMSTATUS option takes single argument of type int, |
| 1650 | 1650 | ** interpreted as a boolean, which enables or disables the collection of |
| 1651 | -** memory allocation statistics. ^(When memory allocation statistics are disabled, the | |
| 1652 | -** following SQLite interfaces become non-operational: | |
| 1651 | +** memory allocation statistics. ^(When memory allocation statistics are | |
| 1652 | +** disabled, the following SQLite interfaces become non-operational: | |
| 1653 | 1653 | ** <ul> |
| 1654 | 1654 | ** <li> [sqlite3_memory_used()] |
| 1655 | 1655 | ** <li> [sqlite3_memory_highwater()] |
| 1656 | 1656 | ** <li> [sqlite3_soft_heap_limit64()] |
| 1657 | 1657 | ** <li> [sqlite3_status()] |
| @@ -1688,14 +1688,15 @@ | ||
| 1688 | 1688 | ** that SQLite can use for the database page cache with the default page |
| 1689 | 1689 | ** cache implementation. |
| 1690 | 1690 | ** This configuration should not be used if an application-define page |
| 1691 | 1691 | ** cache implementation is loaded using the [SQLITE_CONFIG_PCACHE2] |
| 1692 | 1692 | ** configuration option. |
| 1693 | -** ^There are three arguments to SQLITE_CONFIG_PAGECACHE: A pointer to 8-byte aligned | |
| 1693 | +** ^There are three arguments to SQLITE_CONFIG_PAGECACHE: A pointer to | |
| 1694 | +** 8-byte aligned | |
| 1694 | 1695 | ** memory, the size of each page buffer (sz), and the number of pages (N). |
| 1695 | 1696 | ** The sz argument should be the size of the largest database page |
| 1696 | -** (a power of two between 512 and 32768) plus some extra bytes for each | |
| 1697 | +** (a power of two between 512 and 65536) plus some extra bytes for each | |
| 1697 | 1698 | ** page header. ^The number of extra bytes needed by the page header |
| 1698 | 1699 | ** can be determined using the [SQLITE_CONFIG_PCACHE_HDRSZ] option |
| 1699 | 1700 | ** to [sqlite3_config()]. |
| 1700 | 1701 | ** ^It is harmless, apart from the wasted memory, |
| 1701 | 1702 | ** for the sz parameter to be larger than necessary. The first |
| @@ -1708,11 +1709,12 @@ | ||
| 1708 | 1709 | ** SQLite goes to [sqlite3_malloc()] for the additional storage space.</dd> |
| 1709 | 1710 | ** |
| 1710 | 1711 | ** [[SQLITE_CONFIG_HEAP]] <dt>SQLITE_CONFIG_HEAP</dt> |
| 1711 | 1712 | ** <dd> ^The SQLITE_CONFIG_HEAP option specifies a static memory buffer |
| 1712 | 1713 | ** that SQLite will use for all of its dynamic memory allocation needs |
| 1713 | -** beyond those provided for by [SQLITE_CONFIG_SCRATCH] and [SQLITE_CONFIG_PAGECACHE]. | |
| 1714 | +** beyond those provided for by [SQLITE_CONFIG_SCRATCH] and | |
| 1715 | +** [SQLITE_CONFIG_PAGECACHE]. | |
| 1714 | 1716 | ** ^The SQLITE_CONFIG_HEAP option is only available if SQLite is compiled |
| 1715 | 1717 | ** with either [SQLITE_ENABLE_MEMSYS3] or [SQLITE_ENABLE_MEMSYS5] and returns |
| 1716 | 1718 | ** [SQLITE_ERROR] if invoked otherwise. |
| 1717 | 1719 | ** ^There are three arguments to SQLITE_CONFIG_HEAP: |
| 1718 | 1720 | ** An 8-byte aligned pointer to the memory, |
| @@ -1728,13 +1730,13 @@ | ||
| 1728 | 1730 | ** for the minimum allocation size are 2**5 through 2**8.</dd> |
| 1729 | 1731 | ** |
| 1730 | 1732 | ** [[SQLITE_CONFIG_MUTEX]] <dt>SQLITE_CONFIG_MUTEX</dt> |
| 1731 | 1733 | ** <dd> ^(The SQLITE_CONFIG_MUTEX option takes a single argument which is a |
| 1732 | 1734 | ** pointer to an instance of the [sqlite3_mutex_methods] structure. |
| 1733 | -** The argument specifies alternative low-level mutex routines to be used in place | |
| 1734 | -** the mutex routines built into SQLite.)^ ^SQLite makes a copy of the | |
| 1735 | -** content of the [sqlite3_mutex_methods] structure before the call to | |
| 1735 | +** The argument specifies alternative low-level mutex routines to be used | |
| 1736 | +** in place the mutex routines built into SQLite.)^ ^SQLite makes a copy of | |
| 1737 | +** the content of the [sqlite3_mutex_methods] structure before the call to | |
| 1736 | 1738 | ** [sqlite3_config()] returns. ^If SQLite is compiled with |
| 1737 | 1739 | ** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then |
| 1738 | 1740 | ** the entire mutexing subsystem is omitted from the build and hence calls to |
| 1739 | 1741 | ** [sqlite3_config()] with the SQLITE_CONFIG_MUTEX configuration option will |
| 1740 | 1742 | ** return [SQLITE_ERROR].</dd> |
| @@ -1768,12 +1770,12 @@ | ||
| 1768 | 1770 | ** the interface to a custom page cache implementation.)^ |
| 1769 | 1771 | ** ^SQLite makes a copy of the [sqlite3_pcache_methods2] object.</dd> |
| 1770 | 1772 | ** |
| 1771 | 1773 | ** [[SQLITE_CONFIG_GETPCACHE2]] <dt>SQLITE_CONFIG_GETPCACHE2</dt> |
| 1772 | 1774 | ** <dd> ^(The SQLITE_CONFIG_GETPCACHE2 option takes a single argument which |
| 1773 | -** is a pointer to an [sqlite3_pcache_methods2] object. SQLite copies of the current | |
| 1774 | -** page cache implementation into that object.)^ </dd> | |
| 1775 | +** is a pointer to an [sqlite3_pcache_methods2] object. SQLite copies of | |
| 1776 | +** the current page cache implementation into that object.)^ </dd> | |
| 1775 | 1777 | ** |
| 1776 | 1778 | ** [[SQLITE_CONFIG_LOG]] <dt>SQLITE_CONFIG_LOG</dt> |
| 1777 | 1779 | ** <dd> The SQLITE_CONFIG_LOG option is used to configure the SQLite |
| 1778 | 1780 | ** global [error log]. |
| 1779 | 1781 | ** (^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a |
| @@ -1794,12 +1796,13 @@ | ||
| 1794 | 1796 | ** function must be threadsafe. </dd> |
| 1795 | 1797 | ** |
| 1796 | 1798 | ** [[SQLITE_CONFIG_URI]] <dt>SQLITE_CONFIG_URI |
| 1797 | 1799 | ** <dd>^(The SQLITE_CONFIG_URI option takes a single argument of type int. |
| 1798 | 1800 | ** If non-zero, then URI handling is globally enabled. If the parameter is zero, |
| 1799 | -** then URI handling is globally disabled.)^ ^If URI handling is globally enabled, | |
| 1800 | -** all filenames passed to [sqlite3_open()], [sqlite3_open_v2()], [sqlite3_open16()] or | |
| 1801 | +** then URI handling is globally disabled.)^ ^If URI handling is globally | |
| 1802 | +** enabled, all filenames passed to [sqlite3_open()], [sqlite3_open_v2()], | |
| 1803 | +** [sqlite3_open16()] or | |
| 1801 | 1804 | ** specified as part of [ATTACH] commands are interpreted as URIs, regardless |
| 1802 | 1805 | ** of whether or not the [SQLITE_OPEN_URI] flag is set when the database |
| 1803 | 1806 | ** connection is opened. ^If it is globally disabled, filenames are |
| 1804 | 1807 | ** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the |
| 1805 | 1808 | ** database connection is opened. ^(By default, URI handling is globally |
| @@ -1857,22 +1860,33 @@ | ||
| 1857 | 1860 | ** changed to its compile-time default. |
| 1858 | 1861 | ** |
| 1859 | 1862 | ** [[SQLITE_CONFIG_WIN32_HEAPSIZE]] |
| 1860 | 1863 | ** <dt>SQLITE_CONFIG_WIN32_HEAPSIZE |
| 1861 | 1864 | ** <dd>^The SQLITE_CONFIG_WIN32_HEAPSIZE option is only available if SQLite is |
| 1862 | -** compiled for Windows with the [SQLITE_WIN32_MALLOC] pre-processor macro defined. | |
| 1863 | -** ^SQLITE_CONFIG_WIN32_HEAPSIZE takes a 32-bit unsigned integer value | |
| 1865 | +** compiled for Windows with the [SQLITE_WIN32_MALLOC] pre-processor macro | |
| 1866 | +** defined. ^SQLITE_CONFIG_WIN32_HEAPSIZE takes a 32-bit unsigned integer value | |
| 1864 | 1867 | ** that specifies the maximum size of the created heap. |
| 1865 | 1868 | ** </dl> |
| 1866 | 1869 | ** |
| 1867 | 1870 | ** [[SQLITE_CONFIG_PCACHE_HDRSZ]] |
| 1868 | 1871 | ** <dt>SQLITE_CONFIG_PCACHE_HDRSZ |
| 1869 | 1872 | ** <dd>^The SQLITE_CONFIG_PCACHE_HDRSZ option takes a single parameter which |
| 1870 | 1873 | ** is a pointer to an integer and writes into that integer the number of extra |
| 1871 | -** bytes per page required for each page in [SQLITE_CONFIG_PAGECACHE]. The amount of | |
| 1872 | -** extra space required can change depending on the compiler, | |
| 1874 | +** bytes per page required for each page in [SQLITE_CONFIG_PAGECACHE]. | |
| 1875 | +** The amount of extra space required can change depending on the compiler, | |
| 1873 | 1876 | ** target platform, and SQLite version. |
| 1877 | +** | |
| 1878 | +** [[SQLITE_CONFIG_PMASZ]] | |
| 1879 | +** <dt>SQLITE_CONFIG_PMASZ | |
| 1880 | +** <dd>^The SQLITE_CONFIG_PMASZ option takes a single parameter which | |
| 1881 | +** is an unsigned integer and sets the "Minimum PMA Size" for the multithreaded | |
| 1882 | +** sorter to that integer. The default minimum PMA Size is set by the | |
| 1883 | +** [SQLITE_SORTER_PMASZ] compile-time option. New threads are launched | |
| 1884 | +** to help with sort operations when multithreaded sorting | |
| 1885 | +** is enabled (using the [PRAGMA threads] command) and the amount of content | |
| 1886 | +** to be sorted exceeds the page size times the minimum of the | |
| 1887 | +** [PRAGMA cache_size] setting and this value. | |
| 1874 | 1888 | ** </dl> |
| 1875 | 1889 | */ |
| 1876 | 1890 | #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ |
| 1877 | 1891 | #define SQLITE_CONFIG_MULTITHREAD 2 /* nil */ |
| 1878 | 1892 | #define SQLITE_CONFIG_SERIALIZED 3 /* nil */ |
| @@ -1895,10 +1909,11 @@ | ||
| 1895 | 1909 | #define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */ |
| 1896 | 1910 | #define SQLITE_CONFIG_SQLLOG 21 /* xSqllog, void* */ |
| 1897 | 1911 | #define SQLITE_CONFIG_MMAP_SIZE 22 /* sqlite3_int64, sqlite3_int64 */ |
| 1898 | 1912 | #define SQLITE_CONFIG_WIN32_HEAPSIZE 23 /* int nByte */ |
| 1899 | 1913 | #define SQLITE_CONFIG_PCACHE_HDRSZ 24 /* int *psz */ |
| 1914 | +#define SQLITE_CONFIG_PMASZ 25 /* unsigned int szPma */ | |
| 1900 | 1915 | |
| 1901 | 1916 | /* |
| 1902 | 1917 | ** CAPI3REF: Database Connection Configuration Options |
| 1903 | 1918 | ** |
| 1904 | 1919 | ** These constants are the available integer configuration options that |
| @@ -2171,10 +2186,11 @@ | ||
| 2171 | 2186 | SQLITE_API int sqlite3_complete(const char *sql); |
| 2172 | 2187 | SQLITE_API int sqlite3_complete16(const void *sql); |
| 2173 | 2188 | |
| 2174 | 2189 | /* |
| 2175 | 2190 | ** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors |
| 2191 | +** KEYWORDS: {busy-handler callback} {busy handler} | |
| 2176 | 2192 | ** |
| 2177 | 2193 | ** ^The sqlite3_busy_handler(D,X,P) routine sets a callback function X |
| 2178 | 2194 | ** that might be invoked with argument P whenever |
| 2179 | 2195 | ** an attempt is made to access a database table associated with |
| 2180 | 2196 | ** [database connection] D when another thread |
| @@ -2187,11 +2203,11 @@ | ||
| 2187 | 2203 | ** is not NULL, then the callback might be invoked with two arguments. |
| 2188 | 2204 | ** |
| 2189 | 2205 | ** ^The first argument to the busy handler is a copy of the void* pointer which |
| 2190 | 2206 | ** is the third argument to sqlite3_busy_handler(). ^The second argument to |
| 2191 | 2207 | ** the busy handler callback is the number of times that the busy handler has |
| 2192 | -** been invoked for the same locking event. ^If the | |
| 2208 | +** been invoked previously for the same locking event. ^If the | |
| 2193 | 2209 | ** busy callback returns 0, then no additional attempts are made to |
| 2194 | 2210 | ** access the database and [SQLITE_BUSY] is returned |
| 2195 | 2211 | ** to the application. |
| 2196 | 2212 | ** ^If the callback returns non-zero, then another attempt |
| 2197 | 2213 | ** is made to access the database and the cycle repeats. |
| @@ -4642,11 +4658,12 @@ | ||
| 4642 | 4658 | ** If these routines are called from within the different thread |
| 4643 | 4659 | ** than the one containing the application-defined function that received |
| 4644 | 4660 | ** the [sqlite3_context] pointer, the results are undefined. |
| 4645 | 4661 | */ |
| 4646 | 4662 | SQLITE_API void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); |
| 4647 | -SQLITE_API void sqlite3_result_blob64(sqlite3_context*,const void*,sqlite3_uint64,void(*)(void*)); | |
| 4663 | +SQLITE_API void sqlite3_result_blob64(sqlite3_context*,const void*, | |
| 4664 | + sqlite3_uint64,void(*)(void*)); | |
| 4648 | 4665 | SQLITE_API void sqlite3_result_double(sqlite3_context*, double); |
| 4649 | 4666 | SQLITE_API void sqlite3_result_error(sqlite3_context*, const char*, int); |
| 4650 | 4667 | SQLITE_API void sqlite3_result_error16(sqlite3_context*, const void*, int); |
| 4651 | 4668 | SQLITE_API void sqlite3_result_error_toobig(sqlite3_context*); |
| 4652 | 4669 | SQLITE_API void sqlite3_result_error_nomem(sqlite3_context*); |
| @@ -5274,24 +5291,31 @@ | ||
| 5274 | 5291 | |
| 5275 | 5292 | |
| 5276 | 5293 | /* |
| 5277 | 5294 | ** CAPI3REF: Extract Metadata About A Column Of A Table |
| 5278 | 5295 | ** |
| 5279 | -** ^This routine returns metadata about a specific column of a specific | |
| 5280 | -** database table accessible using the [database connection] handle | |
| 5281 | -** passed as the first function argument. | |
| 5296 | +** ^(The sqlite3_table_column_metadata(X,D,T,C,....) routine returns | |
| 5297 | +** information about column C of table T in database D | |
| 5298 | +** on [database connection] X.)^ ^The sqlite3_table_column_metadata() | |
| 5299 | +** interface returns SQLITE_OK and fills in the non-NULL pointers in | |
| 5300 | +** the final five arguments with appropriate values if the specified | |
| 5301 | +** column exists. ^The sqlite3_table_column_metadata() interface returns | |
| 5302 | +** SQLITE_ERROR and if the specified column does not exist. | |
| 5303 | +** ^If the column-name parameter to sqlite3_table_column_metadata() is a | |
| 5304 | +** NULL pointer, then this routine simply checks for the existance of the | |
| 5305 | +** table and returns SQLITE_OK if the table exists and SQLITE_ERROR if it | |
| 5306 | +** does not. | |
| 5282 | 5307 | ** |
| 5283 | 5308 | ** ^The column is identified by the second, third and fourth parameters to |
| 5284 | -** this function. ^The second parameter is either the name of the database | |
| 5309 | +** this function. ^(The second parameter is either the name of the database | |
| 5285 | 5310 | ** (i.e. "main", "temp", or an attached database) containing the specified |
| 5286 | -** table or NULL. ^If it is NULL, then all attached databases are searched | |
| 5311 | +** table or NULL.)^ ^If it is NULL, then all attached databases are searched | |
| 5287 | 5312 | ** for the table using the same algorithm used by the database engine to |
| 5288 | 5313 | ** resolve unqualified table references. |
| 5289 | 5314 | ** |
| 5290 | 5315 | ** ^The third and fourth parameters to this function are the table and column |
| 5291 | -** name of the desired column, respectively. Neither of these parameters | |
| 5292 | -** may be NULL. | |
| 5316 | +** name of the desired column, respectively. | |
| 5293 | 5317 | ** |
| 5294 | 5318 | ** ^Metadata is returned by writing to the memory locations passed as the 5th |
| 5295 | 5319 | ** and subsequent parameters to this function. ^Any of these arguments may be |
| 5296 | 5320 | ** NULL, in which case the corresponding element of metadata is omitted. |
| 5297 | 5321 | ** |
| @@ -5306,36 +5330,33 @@ | ||
| 5306 | 5330 | ** <tr><td> 9th <td> int <td> True if column is [AUTOINCREMENT] |
| 5307 | 5331 | ** </table> |
| 5308 | 5332 | ** </blockquote>)^ |
| 5309 | 5333 | ** |
| 5310 | 5334 | ** ^The memory pointed to by the character pointers returned for the |
| 5311 | -** declaration type and collation sequence is valid only until the next | |
| 5335 | +** declaration type and collation sequence is valid until the next | |
| 5312 | 5336 | ** call to any SQLite API function. |
| 5313 | 5337 | ** |
| 5314 | 5338 | ** ^If the specified table is actually a view, an [error code] is returned. |
| 5315 | 5339 | ** |
| 5316 | -** ^If the specified column is "rowid", "oid" or "_rowid_" and an | |
| 5340 | +** ^If the specified column is "rowid", "oid" or "_rowid_" and the table | |
| 5341 | +** is not a [WITHOUT ROWID] table and an | |
| 5317 | 5342 | ** [INTEGER PRIMARY KEY] column has been explicitly declared, then the output |
| 5318 | 5343 | ** parameters are set for the explicitly declared column. ^(If there is no |
| 5319 | -** explicitly declared [INTEGER PRIMARY KEY] column, then the output | |
| 5320 | -** parameters are set as follows: | |
| 5344 | +** [INTEGER PRIMARY KEY] column, then the outputs | |
| 5345 | +** for the [rowid] are set as follows: | |
| 5321 | 5346 | ** |
| 5322 | 5347 | ** <pre> |
| 5323 | 5348 | ** data type: "INTEGER" |
| 5324 | 5349 | ** collation sequence: "BINARY" |
| 5325 | 5350 | ** not null: 0 |
| 5326 | 5351 | ** primary key: 1 |
| 5327 | 5352 | ** auto increment: 0 |
| 5328 | 5353 | ** </pre>)^ |
| 5329 | 5354 | ** |
| 5330 | -** ^(This function may load one or more schemas from database files. If an | |
| 5331 | -** error occurs during this process, or if the requested table or column | |
| 5332 | -** cannot be found, an [error code] is returned and an error message left | |
| 5333 | -** in the [database connection] (to be retrieved using sqlite3_errmsg()).)^ | |
| 5334 | -** | |
| 5335 | -** ^This API is only available if the library was compiled with the | |
| 5336 | -** [SQLITE_ENABLE_COLUMN_METADATA] C-preprocessor symbol defined. | |
| 5355 | +** ^This function causes all database schemas to be read from disk and | |
| 5356 | +** parsed, if that has not already been done, and returns an error if | |
| 5357 | +** any errors are encountered while loading the schema. | |
| 5337 | 5358 | */ |
| 5338 | 5359 | SQLITE_API int sqlite3_table_column_metadata( |
| 5339 | 5360 | sqlite3 *db, /* Connection handle */ |
| 5340 | 5361 | const char *zDbName, /* Database name or NULL */ |
| 5341 | 5362 | const char *zTableName, /* Table name */ |
| @@ -7298,16 +7319,14 @@ | ||
| 7298 | 7319 | |
| 7299 | 7320 | /* |
| 7300 | 7321 | ** CAPI3REF: Write-Ahead Log Commit Hook |
| 7301 | 7322 | ** |
| 7302 | 7323 | ** ^The [sqlite3_wal_hook()] function is used to register a callback that |
| 7303 | -** will be invoked each time a database connection commits data to a | |
| 7304 | -** [write-ahead log] (i.e. whenever a transaction is committed in | |
| 7305 | -** [journal_mode | journal_mode=WAL mode]). | |
| 7324 | +** is invoked each time data is committed to a database in wal mode. | |
| 7306 | 7325 | ** |
| 7307 | -** ^The callback is invoked by SQLite after the commit has taken place and | |
| 7308 | -** the associated write-lock on the database released, so the implementation | |
| 7326 | +** ^(The callback is invoked by SQLite after the commit has taken place and | |
| 7327 | +** the associated write-lock on the database released)^, so the implementation | |
| 7309 | 7328 | ** may read, write or [checkpoint] the database as required. |
| 7310 | 7329 | ** |
| 7311 | 7330 | ** ^The first parameter passed to the callback function when it is invoked |
| 7312 | 7331 | ** is a copy of the third parameter passed to sqlite3_wal_hook() when |
| 7313 | 7332 | ** registering the callback. ^The second is a copy of the database handle. |
| @@ -7368,101 +7387,118 @@ | ||
| 7368 | 7387 | SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N); |
| 7369 | 7388 | |
| 7370 | 7389 | /* |
| 7371 | 7390 | ** CAPI3REF: Checkpoint a database |
| 7372 | 7391 | ** |
| 7373 | -** ^The [sqlite3_wal_checkpoint(D,X)] interface causes database named X | |
| 7374 | -** on [database connection] D to be [checkpointed]. ^If X is NULL or an | |
| 7375 | -** empty string, then a checkpoint is run on all databases of | |
| 7376 | -** connection D. ^If the database connection D is not in | |
| 7377 | -** [WAL | write-ahead log mode] then this interface is a harmless no-op. | |
| 7378 | -** ^The [sqlite3_wal_checkpoint(D,X)] interface initiates a | |
| 7379 | -** [sqlite3_wal_checkpoint_v2|PASSIVE] checkpoint. | |
| 7380 | -** Use the [sqlite3_wal_checkpoint_v2()] interface to get a FULL | |
| 7381 | -** or RESET checkpoint. | |
| 7382 | -** | |
| 7383 | -** ^The [wal_checkpoint pragma] can be used to invoke this interface | |
| 7384 | -** from SQL. ^The [sqlite3_wal_autocheckpoint()] interface and the | |
| 7385 | -** [wal_autocheckpoint pragma] can be used to cause this interface to be | |
| 7386 | -** run whenever the WAL reaches a certain size threshold. | |
| 7387 | -** | |
| 7388 | -** See also: [sqlite3_wal_checkpoint_v2()] | |
| 7392 | +** ^(The sqlite3_wal_checkpoint(D,X) is equivalent to | |
| 7393 | +** [sqlite3_wal_checkpoint_v2](D,X,[SQLITE_CHECKPOINT_PASSIVE],0,0).)^ | |
| 7394 | +** | |
| 7395 | +** In brief, sqlite3_wal_checkpoint(D,X) causes the content in the | |
| 7396 | +** [write-ahead log] for database X on [database connection] D to be | |
| 7397 | +** transferred into the database file and for the write-ahead log to | |
| 7398 | +** be reset. See the [checkpointing] documentation for addition | |
| 7399 | +** information. | |
| 7400 | +** | |
| 7401 | +** This interface used to be the only way to cause a checkpoint to | |
| 7402 | +** occur. But then the newer and more powerful [sqlite3_wal_checkpoint_v2()] | |
| 7403 | +** interface was added. This interface is retained for backwards | |
| 7404 | +** compatibility and as a convenience for applications that need to manually | |
| 7405 | +** start a callback but which do not need the full power (and corresponding | |
| 7406 | +** complication) of [sqlite3_wal_checkpoint_v2()]. | |
| 7389 | 7407 | */ |
| 7390 | 7408 | SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb); |
| 7391 | 7409 | |
| 7392 | 7410 | /* |
| 7393 | 7411 | ** CAPI3REF: Checkpoint a database |
| 7394 | 7412 | ** |
| 7395 | -** Run a checkpoint operation on WAL database zDb attached to database | |
| 7396 | -** handle db. The specific operation is determined by the value of the | |
| 7397 | -** eMode parameter: | |
| 7413 | +** ^(The sqlite3_wal_checkpoint_v2(D,X,M,L,C) interface runs a checkpoint | |
| 7414 | +** operation on database X of [database connection] D in mode M. Status | |
| 7415 | +** information is written back into integers pointed to by L and C.)^ | |
| 7416 | +** ^(The M parameter must be a valid [checkpoint mode]:)^ | |
| 7398 | 7417 | ** |
| 7399 | 7418 | ** <dl> |
| 7400 | 7419 | ** <dt>SQLITE_CHECKPOINT_PASSIVE<dd> |
| 7401 | -** Checkpoint as many frames as possible without waiting for any database | |
| 7402 | -** readers or writers to finish. Sync the db file if all frames in the log | |
| 7403 | -** are checkpointed. This mode is the same as calling | |
| 7404 | -** sqlite3_wal_checkpoint(). The [sqlite3_busy_handler|busy-handler callback] | |
| 7405 | -** is never invoked. | |
| 7420 | +** ^Checkpoint as many frames as possible without waiting for any database | |
| 7421 | +** readers or writers to finish, then sync the database file if all frames | |
| 7422 | +** in the log were checkpointed. ^The [busy-handler callback] | |
| 7423 | +** is never invoked in the SQLITE_CHECKPOINT_PASSIVE mode. | |
| 7424 | +** ^On the other hand, passive mode might leave the checkpoint unfinished | |
| 7425 | +** if there are concurrent readers or writers. | |
| 7406 | 7426 | ** |
| 7407 | 7427 | ** <dt>SQLITE_CHECKPOINT_FULL<dd> |
| 7408 | -** This mode blocks (it invokes the | |
| 7428 | +** ^This mode blocks (it invokes the | |
| 7409 | 7429 | ** [sqlite3_busy_handler|busy-handler callback]) until there is no |
| 7410 | 7430 | ** database writer and all readers are reading from the most recent database |
| 7411 | -** snapshot. It then checkpoints all frames in the log file and syncs the | |
| 7412 | -** database file. This call blocks database writers while it is running, | |
| 7413 | -** but not database readers. | |
| 7431 | +** snapshot. ^It then checkpoints all frames in the log file and syncs the | |
| 7432 | +** database file. ^This mode blocks new database writers while it is pending, | |
| 7433 | +** but new database readers are allowed to continue unimpeded. | |
| 7414 | 7434 | ** |
| 7415 | 7435 | ** <dt>SQLITE_CHECKPOINT_RESTART<dd> |
| 7416 | -** This mode works the same way as SQLITE_CHECKPOINT_FULL, except after | |
| 7417 | -** checkpointing the log file it blocks (calls the | |
| 7418 | -** [sqlite3_busy_handler|busy-handler callback]) | |
| 7419 | -** until all readers are reading from the database file only. This ensures | |
| 7420 | -** that the next client to write to the database file restarts the log file | |
| 7421 | -** from the beginning. This call blocks database writers while it is running, | |
| 7422 | -** but not database readers. | |
| 7436 | +** ^This mode works the same way as SQLITE_CHECKPOINT_FULL with the addition | |
| 7437 | +** that after checkpointing the log file it blocks (calls the | |
| 7438 | +** [busy-handler callback]) | |
| 7439 | +** until all readers are reading from the database file only. ^This ensures | |
| 7440 | +** that the next writer will restart the log file from the beginning. | |
| 7441 | +** ^Like SQLITE_CHECKPOINT_FULL, this mode blocks new | |
| 7442 | +** database writer attempts while it is pending, but does not impede readers. | |
| 7443 | +** | |
| 7444 | +** <dt>SQLITE_CHECKPOINT_TRUNCATE<dd> | |
| 7445 | +** ^This mode works the same way as SQLITE_CHECKPOINT_RESTART with the | |
| 7446 | +** addition that it also truncates the log file to zero bytes just prior | |
| 7447 | +** to a successful return. | |
| 7423 | 7448 | ** </dl> |
| 7424 | 7449 | ** |
| 7425 | -** If pnLog is not NULL, then *pnLog is set to the total number of frames in | |
| 7426 | -** the log file before returning. If pnCkpt is not NULL, then *pnCkpt is set to | |
| 7427 | -** the total number of checkpointed frames (including any that were already | |
| 7428 | -** checkpointed when this function is called). *pnLog and *pnCkpt may be | |
| 7429 | -** populated even if sqlite3_wal_checkpoint_v2() returns other than SQLITE_OK. | |
| 7430 | -** If no values are available because of an error, they are both set to -1 | |
| 7431 | -** before returning to communicate this to the caller. | |
| 7450 | +** ^If pnLog is not NULL, then *pnLog is set to the total number of frames in | |
| 7451 | +** the log file or to -1 if the checkpoint could not run because | |
| 7452 | +** of an error or because the database is not in [WAL mode]. ^If pnCkpt is not | |
| 7453 | +** NULL,then *pnCkpt is set to the total number of checkpointed frames in the | |
| 7454 | +** log file (including any that were already checkpointed before the function | |
| 7455 | +** was called) or to -1 if the checkpoint could not run due to an error or | |
| 7456 | +** because the database is not in WAL mode. ^Note that upon successful | |
| 7457 | +** completion of an SQLITE_CHECKPOINT_TRUNCATE, the log file will have been | |
| 7458 | +** truncated to zero bytes and so both *pnLog and *pnCkpt will be set to zero. | |
| 7432 | 7459 | ** |
| 7433 | -** All calls obtain an exclusive "checkpoint" lock on the database file. If | |
| 7460 | +** ^All calls obtain an exclusive "checkpoint" lock on the database file. ^If | |
| 7434 | 7461 | ** any other process is running a checkpoint operation at the same time, the |
| 7435 | -** lock cannot be obtained and SQLITE_BUSY is returned. Even if there is a | |
| 7462 | +** lock cannot be obtained and SQLITE_BUSY is returned. ^Even if there is a | |
| 7436 | 7463 | ** busy-handler configured, it will not be invoked in this case. |
| 7437 | 7464 | ** |
| 7438 | -** The SQLITE_CHECKPOINT_FULL and RESTART modes also obtain the exclusive | |
| 7439 | -** "writer" lock on the database file. If the writer lock cannot be obtained | |
| 7440 | -** immediately, and a busy-handler is configured, it is invoked and the writer | |
| 7441 | -** lock retried until either the busy-handler returns 0 or the lock is | |
| 7442 | -** successfully obtained. The busy-handler is also invoked while waiting for | |
| 7443 | -** database readers as described above. If the busy-handler returns 0 before | |
| 7465 | +** ^The SQLITE_CHECKPOINT_FULL, RESTART and TRUNCATE modes also obtain the | |
| 7466 | +** exclusive "writer" lock on the database file. ^If the writer lock cannot be | |
| 7467 | +** obtained immediately, and a busy-handler is configured, it is invoked and | |
| 7468 | +** the writer lock retried until either the busy-handler returns 0 or the lock | |
| 7469 | +** is successfully obtained. ^The busy-handler is also invoked while waiting for | |
| 7470 | +** database readers as described above. ^If the busy-handler returns 0 before | |
| 7444 | 7471 | ** the writer lock is obtained or while waiting for database readers, the |
| 7445 | 7472 | ** checkpoint operation proceeds from that point in the same way as |
| 7446 | 7473 | ** SQLITE_CHECKPOINT_PASSIVE - checkpointing as many frames as possible |
| 7447 | -** without blocking any further. SQLITE_BUSY is returned in this case. | |
| 7474 | +** without blocking any further. ^SQLITE_BUSY is returned in this case. | |
| 7448 | 7475 | ** |
| 7449 | -** If parameter zDb is NULL or points to a zero length string, then the | |
| 7450 | -** specified operation is attempted on all WAL databases. In this case the | |
| 7451 | -** values written to output parameters *pnLog and *pnCkpt are undefined. If | |
| 7476 | +** ^If parameter zDb is NULL or points to a zero length string, then the | |
| 7477 | +** specified operation is attempted on all WAL databases [attached] to | |
| 7478 | +** [database connection] db. In this case the | |
| 7479 | +** values written to output parameters *pnLog and *pnCkpt are undefined. ^If | |
| 7452 | 7480 | ** an SQLITE_BUSY error is encountered when processing one or more of the |
| 7453 | 7481 | ** attached WAL databases, the operation is still attempted on any remaining |
| 7454 | -** attached databases and SQLITE_BUSY is returned to the caller. If any other | |
| 7482 | +** attached databases and SQLITE_BUSY is returned at the end. ^If any other | |
| 7455 | 7483 | ** error occurs while processing an attached database, processing is abandoned |
| 7456 | -** and the error code returned to the caller immediately. If no error | |
| 7484 | +** and the error code is returned to the caller immediately. ^If no error | |
| 7457 | 7485 | ** (SQLITE_BUSY or otherwise) is encountered while processing the attached |
| 7458 | 7486 | ** databases, SQLITE_OK is returned. |
| 7459 | 7487 | ** |
| 7460 | -** If database zDb is the name of an attached database that is not in WAL | |
| 7461 | -** mode, SQLITE_OK is returned and both *pnLog and *pnCkpt set to -1. If | |
| 7488 | +** ^If database zDb is the name of an attached database that is not in WAL | |
| 7489 | +** mode, SQLITE_OK is returned and both *pnLog and *pnCkpt set to -1. ^If | |
| 7462 | 7490 | ** zDb is not NULL (or a zero length string) and is not the name of any |
| 7463 | 7491 | ** attached database, SQLITE_ERROR is returned to the caller. |
| 7492 | +** | |
| 7493 | +** ^Unless it returns SQLITE_MISUSE, | |
| 7494 | +** the sqlite3_wal_checkpoint_v2() interface | |
| 7495 | +** sets the error information that is queried by | |
| 7496 | +** [sqlite3_errcode()] and [sqlite3_errmsg()]. | |
| 7497 | +** | |
| 7498 | +** ^The [PRAGMA wal_checkpoint] command can be used to invoke this interface | |
| 7499 | +** from SQL. | |
| 7464 | 7500 | */ |
| 7465 | 7501 | SQLITE_API int sqlite3_wal_checkpoint_v2( |
| 7466 | 7502 | sqlite3 *db, /* Database handle */ |
| 7467 | 7503 | const char *zDb, /* Name of attached database (or NULL) */ |
| 7468 | 7504 | int eMode, /* SQLITE_CHECKPOINT_* value */ |
| @@ -7469,20 +7505,22 @@ | ||
| 7469 | 7505 | int *pnLog, /* OUT: Size of WAL log in frames */ |
| 7470 | 7506 | int *pnCkpt /* OUT: Total number of frames checkpointed */ |
| 7471 | 7507 | ); |
| 7472 | 7508 | |
| 7473 | 7509 | /* |
| 7474 | -** CAPI3REF: Checkpoint operation parameters | |
| 7510 | +** CAPI3REF: Checkpoint Mode Values | |
| 7511 | +** KEYWORDS: {checkpoint mode} | |
| 7475 | 7512 | ** |
| 7476 | -** These constants can be used as the 3rd parameter to | |
| 7477 | -** [sqlite3_wal_checkpoint_v2()]. See the [sqlite3_wal_checkpoint_v2()] | |
| 7478 | -** documentation for additional information about the meaning and use of | |
| 7479 | -** each of these values. | |
| 7513 | +** These constants define all valid values for the "checkpoint mode" passed | |
| 7514 | +** as the third parameter to the [sqlite3_wal_checkpoint_v2()] interface. | |
| 7515 | +** See the [sqlite3_wal_checkpoint_v2()] documentation for details on the | |
| 7516 | +** meaning of each of these checkpoint modes. | |
| 7480 | 7517 | */ |
| 7481 | -#define SQLITE_CHECKPOINT_PASSIVE 0 | |
| 7482 | -#define SQLITE_CHECKPOINT_FULL 1 | |
| 7483 | -#define SQLITE_CHECKPOINT_RESTART 2 | |
| 7518 | +#define SQLITE_CHECKPOINT_PASSIVE 0 /* Do as much as possible w/o blocking */ | |
| 7519 | +#define SQLITE_CHECKPOINT_FULL 1 /* Wait for writers, then checkpoint */ | |
| 7520 | +#define SQLITE_CHECKPOINT_RESTART 2 /* Like FULL but wait for for readers */ | |
| 7521 | +#define SQLITE_CHECKPOINT_TRUNCATE 3 /* Like RESTART but also truncate WAL */ | |
| 7484 | 7522 | |
| 7485 | 7523 | /* |
| 7486 | 7524 | ** CAPI3REF: Virtual Table Interface Configuration |
| 7487 | 7525 | ** |
| 7488 | 7526 | ** This function may be called by either the [xConnect] or [xCreate] method |
| @@ -7577,16 +7615,16 @@ | ||
| 7577 | 7615 | ** [sqlite3_stmt_scanstatus(S,X,T,V)] interface. Each constant designates a |
| 7578 | 7616 | ** different metric for sqlite3_stmt_scanstatus() to return. |
| 7579 | 7617 | ** |
| 7580 | 7618 | ** <dl> |
| 7581 | 7619 | ** [[SQLITE_SCANSTAT_NLOOP]] <dt>SQLITE_SCANSTAT_NLOOP</dt> |
| 7582 | -** <dd>^The [sqlite3_int64] variable pointed to by the T parameter will be set to the | |
| 7583 | -** total number of times that the X-th loop has run.</dd> | |
| 7620 | +** <dd>^The [sqlite3_int64] variable pointed to by the T parameter will be | |
| 7621 | +** set to the total number of times that the X-th loop has run.</dd> | |
| 7584 | 7622 | ** |
| 7585 | 7623 | ** [[SQLITE_SCANSTAT_NVISIT]] <dt>SQLITE_SCANSTAT_NVISIT</dt> |
| 7586 | -** <dd>^The [sqlite3_int64] variable pointed to by the T parameter will be set to the | |
| 7587 | -** total number of rows examined by all iterations of the X-th loop.</dd> | |
| 7624 | +** <dd>^The [sqlite3_int64] variable pointed to by the T parameter will be set | |
| 7625 | +** to the total number of rows examined by all iterations of the X-th loop.</dd> | |
| 7588 | 7626 | ** |
| 7589 | 7627 | ** [[SQLITE_SCANSTAT_EST]] <dt>SQLITE_SCANSTAT_EST</dt> |
| 7590 | 7628 | ** <dd>^The "double" variable pointed to by the T parameter will be set to the |
| 7591 | 7629 | ** query planner's estimate for the average number of rows output from each |
| 7592 | 7630 | ** iteration of the X-th loop. If the query planner's estimates was accurate, |
| @@ -7593,18 +7631,18 @@ | ||
| 7593 | 7631 | ** then this value will approximate the quotient NVISIT/NLOOP and the |
| 7594 | 7632 | ** product of this value for all prior loops with the same SELECTID will |
| 7595 | 7633 | ** be the NLOOP value for the current loop. |
| 7596 | 7634 | ** |
| 7597 | 7635 | ** [[SQLITE_SCANSTAT_NAME]] <dt>SQLITE_SCANSTAT_NAME</dt> |
| 7598 | -** <dd>^The "const char *" variable pointed to by the T parameter will be set to | |
| 7599 | -** a zero-terminated UTF-8 string containing the name of the index or table used | |
| 7600 | -** for the X-th loop. | |
| 7636 | +** <dd>^The "const char *" variable pointed to by the T parameter will be set | |
| 7637 | +** to a zero-terminated UTF-8 string containing the name of the index or table | |
| 7638 | +** used for the X-th loop. | |
| 7601 | 7639 | ** |
| 7602 | 7640 | ** [[SQLITE_SCANSTAT_EXPLAIN]] <dt>SQLITE_SCANSTAT_EXPLAIN</dt> |
| 7603 | -** <dd>^The "const char *" variable pointed to by the T parameter will be set to | |
| 7604 | -** a zero-terminated UTF-8 string containing the [EXPLAIN QUERY PLAN] description | |
| 7605 | -** for the X-th loop. | |
| 7641 | +** <dd>^The "const char *" variable pointed to by the T parameter will be set | |
| 7642 | +** to a zero-terminated UTF-8 string containing the [EXPLAIN QUERY PLAN] | |
| 7643 | +** description for the X-th loop. | |
| 7606 | 7644 | ** |
| 7607 | 7645 | ** [[SQLITE_SCANSTAT_SELECTID]] <dt>SQLITE_SCANSTAT_SELECT</dt> |
| 7608 | 7646 | ** <dd>^The "int" variable pointed to by the T parameter will be set to the |
| 7609 | 7647 | ** "select-id" for the X-th loop. The select-id identifies which query or |
| 7610 | 7648 | ** subquery the loop is part of. The main query has a select-id of zero. |
| @@ -7623,12 +7661,12 @@ | ||
| 7623 | 7661 | ** CAPI3REF: Prepared Statement Scan Status |
| 7624 | 7662 | ** |
| 7625 | 7663 | ** Return status data for a single loop within query pStmt. |
| 7626 | 7664 | ** |
| 7627 | 7665 | ** The "iScanStatusOp" parameter determines which status information to return. |
| 7628 | -** The "iScanStatusOp" must be one of the [scanstatus options] or the behavior of | |
| 7629 | -** this interface is undefined. | |
| 7666 | +** The "iScanStatusOp" must be one of the [scanstatus options] or the behavior | |
| 7667 | +** of this interface is undefined. | |
| 7630 | 7668 | ** ^The requested measurement is written into a variable pointed to by |
| 7631 | 7669 | ** the "pOut" parameter. |
| 7632 | 7670 | ** Parameter "idx" identifies the specific loop to retrieve statistics for. |
| 7633 | 7671 | ** Loops are numbered starting from zero. ^If idx is out of range - less than |
| 7634 | 7672 | ** zero or greater than or equal to the total number of loops used to implement |
| @@ -9072,11 +9110,11 @@ | ||
| 9072 | 9110 | #define _BTREE_H_ |
| 9073 | 9111 | |
| 9074 | 9112 | /* TODO: This definition is just included so other modules compile. It |
| 9075 | 9113 | ** needs to be revisited. |
| 9076 | 9114 | */ |
| 9077 | -#define SQLITE_N_BTREE_META 10 | |
| 9115 | +#define SQLITE_N_BTREE_META 16 | |
| 9078 | 9116 | |
| 9079 | 9117 | /* |
| 9080 | 9118 | ** If defined as non-zero, auto-vacuum is enabled by default. Otherwise |
| 9081 | 9119 | ** it must be turned on for each database using "PRAGMA auto_vacuum = 1". |
| 9082 | 9120 | */ |
| @@ -9187,10 +9225,15 @@ | ||
| 9187 | 9225 | ** offset = 36 + (idx * 4) |
| 9188 | 9226 | ** |
| 9189 | 9227 | ** For example, the free-page-count field is located at byte offset 36 of |
| 9190 | 9228 | ** the database file header. The incr-vacuum-flag field is located at |
| 9191 | 9229 | ** byte offset 64 (== 36+4*7). |
| 9230 | +** | |
| 9231 | +** The BTREE_DATA_VERSION value is not really a value stored in the header. | |
| 9232 | +** It is a read-only number computed by the pager. But we merge it with | |
| 9233 | +** the header value access routines since its access pattern is the same. | |
| 9234 | +** Call it a "virtual meta value". | |
| 9192 | 9235 | */ |
| 9193 | 9236 | #define BTREE_FREE_PAGE_COUNT 0 |
| 9194 | 9237 | #define BTREE_SCHEMA_VERSION 1 |
| 9195 | 9238 | #define BTREE_FILE_FORMAT 2 |
| 9196 | 9239 | #define BTREE_DEFAULT_CACHE_SIZE 3 |
| @@ -9197,10 +9240,11 @@ | ||
| 9197 | 9240 | #define BTREE_LARGEST_ROOT_PAGE 4 |
| 9198 | 9241 | #define BTREE_TEXT_ENCODING 5 |
| 9199 | 9242 | #define BTREE_USER_VERSION 6 |
| 9200 | 9243 | #define BTREE_INCR_VACUUM 7 |
| 9201 | 9244 | #define BTREE_APPLICATION_ID 8 |
| 9245 | +#define BTREE_DATA_VERSION 15 /* A virtual meta-value */ | |
| 9202 | 9246 | |
| 9203 | 9247 | /* |
| 9204 | 9248 | ** Values that may be OR'd together to form the second argument of an |
| 9205 | 9249 | ** sqlite3BtreeCursorHints() call. |
| 9206 | 9250 | */ |
| @@ -9978,10 +10022,11 @@ | ||
| 9978 | 10022 | SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager); |
| 9979 | 10023 | #endif |
| 9980 | 10024 | |
| 9981 | 10025 | /* Functions used to query pager state and configuration. */ |
| 9982 | 10026 | SQLITE_PRIVATE u8 sqlite3PagerIsreadonly(Pager*); |
| 10027 | +SQLITE_PRIVATE u32 sqlite3PagerDataVersion(Pager*); | |
| 9983 | 10028 | SQLITE_PRIVATE int sqlite3PagerRefcount(Pager*); |
| 9984 | 10029 | SQLITE_PRIVATE int sqlite3PagerMemUsed(Pager*); |
| 9985 | 10030 | SQLITE_PRIVATE const char *sqlite3PagerFilename(Pager*, int); |
| 9986 | 10031 | SQLITE_PRIVATE const sqlite3_vfs *sqlite3PagerVfs(Pager*); |
| 9987 | 10032 | SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager*); |
| @@ -10719,10 +10764,11 @@ | ||
| 10719 | 10764 | i64 szMmap; /* Default mmap_size setting */ |
| 10720 | 10765 | unsigned int openFlags; /* Flags passed to sqlite3_vfs.xOpen() */ |
| 10721 | 10766 | int errCode; /* Most recent error code (SQLITE_*) */ |
| 10722 | 10767 | int errMask; /* & result codes with this before returning */ |
| 10723 | 10768 | u16 dbOptFlags; /* Flags to enable/disable optimizations */ |
| 10769 | + u8 enc; /* Text encoding */ | |
| 10724 | 10770 | u8 autoCommit; /* The auto-commit flag. */ |
| 10725 | 10771 | u8 temp_store; /* 1: file 2: memory 0: default */ |
| 10726 | 10772 | u8 mallocFailed; /* True if we have seen a malloc failure */ |
| 10727 | 10773 | u8 dfltLockMode; /* Default locking-mode for attached dbs */ |
| 10728 | 10774 | signed char nextAutovac; /* Autovac setting after VACUUM if >=0 */ |
| @@ -10820,11 +10866,12 @@ | ||
| 10820 | 10866 | }; |
| 10821 | 10867 | |
| 10822 | 10868 | /* |
| 10823 | 10869 | ** A macro to discover the encoding of a database. |
| 10824 | 10870 | */ |
| 10825 | -#define ENC(db) ((db)->aDb[0].pSchema->enc) | |
| 10871 | +#define SCHEMA_ENC(db) ((db)->aDb[0].pSchema->enc) | |
| 10872 | +#define ENC(db) ((db)->enc) | |
| 10826 | 10873 | |
| 10827 | 10874 | /* |
| 10828 | 10875 | ** Possible values for the sqlite3.flags. |
| 10829 | 10876 | */ |
| 10830 | 10877 | #define SQLITE_VdbeTrace 0x00000001 /* True to trace VDBE execution */ |
| @@ -11444,11 +11491,10 @@ | ||
| 11444 | 11491 | Index *pNext; /* The next index associated with the same table */ |
| 11445 | 11492 | Schema *pSchema; /* Schema containing this index */ |
| 11446 | 11493 | u8 *aSortOrder; /* for each column: True==DESC, False==ASC */ |
| 11447 | 11494 | char **azColl; /* Array of collation sequence names for index */ |
| 11448 | 11495 | Expr *pPartIdxWhere; /* WHERE clause for partial indices */ |
| 11449 | - KeyInfo *pKeyInfo; /* A KeyInfo object suitable for this index */ | |
| 11450 | 11496 | int tnum; /* DB Page containing root of this index */ |
| 11451 | 11497 | LogEst szIdxRow; /* Estimated average row size in bytes */ |
| 11452 | 11498 | u16 nKeyCol; /* Number of columns forming the key */ |
| 11453 | 11499 | u16 nColumn; /* Number of columns stored in the index */ |
| 11454 | 11500 | u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ |
| @@ -11675,11 +11721,11 @@ | ||
| 11675 | 11721 | }; |
| 11676 | 11722 | |
| 11677 | 11723 | /* |
| 11678 | 11724 | ** The following are the meanings of bits in the Expr.flags field. |
| 11679 | 11725 | */ |
| 11680 | -#define EP_FromJoin 0x000001 /* Originated in ON or USING clause of a join */ | |
| 11726 | +#define EP_FromJoin 0x000001 /* Originates in ON/USING clause of outer join */ | |
| 11681 | 11727 | #define EP_Agg 0x000002 /* Contains one or more aggregate functions */ |
| 11682 | 11728 | #define EP_Resolved 0x000004 /* IDs have been resolved to COLUMNs */ |
| 11683 | 11729 | #define EP_Error 0x000008 /* Expression contains one or more errors */ |
| 11684 | 11730 | #define EP_Distinct 0x000010 /* Aggregate function with DISTINCT keyword */ |
| 11685 | 11731 | #define EP_VarSelect 0x000020 /* pSelect is correlated, not constant */ |
| @@ -11695,10 +11741,11 @@ | ||
| 11695 | 11741 | #define EP_Static 0x008000 /* Held in memory not obtained from malloc() */ |
| 11696 | 11742 | #define EP_MemToken 0x010000 /* Need to sqlite3DbFree() Expr.zToken */ |
| 11697 | 11743 | #define EP_NoReduce 0x020000 /* Cannot EXPRDUP_REDUCE this Expr */ |
| 11698 | 11744 | #define EP_Unlikely 0x040000 /* unlikely() or likelihood() function */ |
| 11699 | 11745 | #define EP_Constant 0x080000 /* Node is a constant */ |
| 11746 | +#define EP_CanBeNull 0x100000 /* Can be null despite NOT NULL constraint */ | |
| 11700 | 11747 | |
| 11701 | 11748 | /* |
| 11702 | 11749 | ** These macros can be used to test, set, or clear bits in the |
| 11703 | 11750 | ** Expr.flags field. |
| 11704 | 11751 | */ |
| @@ -12497,10 +12544,11 @@ | ||
| 12497 | 12544 | void *pPage; /* Page cache memory */ |
| 12498 | 12545 | int szPage; /* Size of each page in pPage[] */ |
| 12499 | 12546 | int nPage; /* Number of pages in pPage[] */ |
| 12500 | 12547 | int mxParserStack; /* maximum depth of the parser stack */ |
| 12501 | 12548 | int sharedCacheEnabled; /* true if shared-cache mode enabled */ |
| 12549 | + u32 szPma; /* Maximum Sorter PMA size */ | |
| 12502 | 12550 | /* The above might be initialized to non-zero. The following need to always |
| 12503 | 12551 | ** initially be zero, however. */ |
| 12504 | 12552 | int isInit; /* True after initialization has finished */ |
| 12505 | 12553 | int inProgress; /* True while initialization in progress */ |
| 12506 | 12554 | int isMutexInit; /* True after mutexes are initialized */ |
| @@ -13419,11 +13467,11 @@ | ||
| 13419 | 13467 | ** print I/O tracing messages. |
| 13420 | 13468 | */ |
| 13421 | 13469 | #ifdef SQLITE_ENABLE_IOTRACE |
| 13422 | 13470 | # define IOTRACE(A) if( sqlite3IoTrace ){ sqlite3IoTrace A; } |
| 13423 | 13471 | SQLITE_PRIVATE void sqlite3VdbeIOTraceSql(Vdbe*); |
| 13424 | -SQLITE_PRIVATE void (*sqlite3IoTrace)(const char*,...); | |
| 13472 | +void (*sqlite3IoTrace)(const char*,...); | |
| 13425 | 13473 | #else |
| 13426 | 13474 | # define IOTRACE(A) |
| 13427 | 13475 | # define sqlite3VdbeIOTraceSql(X) |
| 13428 | 13476 | #endif |
| 13429 | 13477 | |
| @@ -13632,10 +13680,17 @@ | ||
| 13632 | 13680 | */ |
| 13633 | 13681 | #ifndef SQLITE_ALLOW_COVERING_INDEX_SCAN |
| 13634 | 13682 | # define SQLITE_ALLOW_COVERING_INDEX_SCAN 1 |
| 13635 | 13683 | #endif |
| 13636 | 13684 | |
| 13685 | +/* The minimum PMA size is set to this value multiplied by the database | |
| 13686 | +** page size in bytes. | |
| 13687 | +*/ | |
| 13688 | +#ifndef SQLITE_SORTER_PMASZ | |
| 13689 | +# define SQLITE_SORTER_PMASZ 250 | |
| 13690 | +#endif | |
| 13691 | + | |
| 13637 | 13692 | /* |
| 13638 | 13693 | ** The following singleton contains the global configuration for |
| 13639 | 13694 | ** the SQLite library. |
| 13640 | 13695 | */ |
| 13641 | 13696 | SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = { |
| @@ -13662,10 +13717,11 @@ | ||
| 13662 | 13717 | (void*)0, /* pPage */ |
| 13663 | 13718 | 0, /* szPage */ |
| 13664 | 13719 | 0, /* nPage */ |
| 13665 | 13720 | 0, /* mxParserStack */ |
| 13666 | 13721 | 0, /* sharedCacheEnabled */ |
| 13722 | + SQLITE_SORTER_PMASZ, /* szPma */ | |
| 13667 | 13723 | /* All the rest should always be initialized to zero */ |
| 13668 | 13724 | 0, /* isInit */ |
| 13669 | 13725 | 0, /* inProgress */ |
| 13670 | 13726 | 0, /* isMutexInit */ |
| 13671 | 13727 | 0, /* isMallocInit */ |
| @@ -19947,10 +20003,16 @@ | ||
| 19947 | 20003 | #endif |
| 19948 | 20004 | } |
| 19949 | 20005 | break; |
| 19950 | 20006 | } |
| 19951 | 20007 | default: { |
| 20008 | +#ifdef SQLITE_ENABLE_API_ARMOR | |
| 20009 | + if( iType-2<0 || iType-2>=ArraySize(winMutex_staticMutexes) ){ | |
| 20010 | + (void)SQLITE_MISUSE_BKPT; | |
| 20011 | + return 0; | |
| 20012 | + } | |
| 20013 | +#endif | |
| 19952 | 20014 | assert( iType-2 >= 0 ); |
| 19953 | 20015 | assert( iType-2 < ArraySize(winMutex_staticMutexes) ); |
| 19954 | 20016 | assert( winMutex_isInit==1 ); |
| 19955 | 20017 | p = &winMutex_staticMutexes[iType-2]; |
| 19956 | 20018 | #ifdef SQLITE_DEBUG |
| @@ -28754,28 +28816,31 @@ | ||
| 28754 | 28816 | do{ |
| 28755 | 28817 | err = osFallocate(pFile->h, buf.st_size, nSize-buf.st_size); |
| 28756 | 28818 | }while( err==EINTR ); |
| 28757 | 28819 | if( err ) return SQLITE_IOERR_WRITE; |
| 28758 | 28820 | #else |
| 28759 | - /* If the OS does not have posix_fallocate(), fake it. First use | |
| 28760 | - ** ftruncate() to set the file size, then write a single byte to | |
| 28761 | - ** the last byte in each block within the extended region. This | |
| 28762 | - ** is the same technique used by glibc to implement posix_fallocate() | |
| 28763 | - ** on systems that do not have a real fallocate() system call. | |
| 28821 | + /* If the OS does not have posix_fallocate(), fake it. Write a | |
| 28822 | + ** single byte to the last byte in each block that falls entirely | |
| 28823 | + ** within the extended region. Then, if required, a single byte | |
| 28824 | + ** at offset (nSize-1), to set the size of the file correctly. | |
| 28825 | + ** This is a similar technique to that used by glibc on systems | |
| 28826 | + ** that do not have a real fallocate() call. | |
| 28764 | 28827 | */ |
| 28765 | 28828 | int nBlk = buf.st_blksize; /* File-system block size */ |
| 28766 | 28829 | i64 iWrite; /* Next offset to write to */ |
| 28767 | 28830 | |
| 28768 | - if( robust_ftruncate(pFile->h, nSize) ){ | |
| 28769 | - pFile->lastErrno = errno; | |
| 28770 | - return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath); | |
| 28771 | - } | |
| 28772 | 28831 | iWrite = ((buf.st_size + 2*nBlk - 1)/nBlk)*nBlk-1; |
| 28773 | - while( iWrite<nSize ){ | |
| 28832 | + assert( iWrite>=buf.st_size ); | |
| 28833 | + assert( (iWrite/nBlk)==((buf.st_size+nBlk-1)/nBlk) ); | |
| 28834 | + assert( ((iWrite+1)%nBlk)==0 ); | |
| 28835 | + for(/*no-op*/; iWrite<nSize; iWrite+=nBlk ){ | |
| 28774 | 28836 | int nWrite = seekAndWrite(pFile, iWrite, "", 1); |
| 28775 | 28837 | if( nWrite!=1 ) return SQLITE_IOERR_WRITE; |
| 28776 | - iWrite += nBlk; | |
| 28838 | + } | |
| 28839 | + if( nSize%nBlk ){ | |
| 28840 | + int nWrite = seekAndWrite(pFile, nSize-1, "", 1); | |
| 28841 | + if( nWrite!=1 ) return SQLITE_IOERR_WRITE; | |
| 28777 | 28842 | } |
| 28778 | 28843 | #endif |
| 28779 | 28844 | } |
| 28780 | 28845 | } |
| 28781 | 28846 | |
| @@ -33989,12 +34054,12 @@ | ||
| 33989 | 34054 | */ |
| 33990 | 34055 | SQLITE_API int sqlite3_win32_reset_heap(){ |
| 33991 | 34056 | int rc; |
| 33992 | 34057 | MUTEX_LOGIC( sqlite3_mutex *pMaster; ) /* The main static mutex */ |
| 33993 | 34058 | MUTEX_LOGIC( sqlite3_mutex *pMem; ) /* The memsys static mutex */ |
| 33994 | - MUTEX_LOGIC( pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); ) | |
| 33995 | - MUTEX_LOGIC( pMem = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM); ) | |
| 34059 | + MUTEX_LOGIC( pMaster = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER); ) | |
| 34060 | + MUTEX_LOGIC( pMem = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM); ) | |
| 33996 | 34061 | sqlite3_mutex_enter(pMaster); |
| 33997 | 34062 | sqlite3_mutex_enter(pMem); |
| 33998 | 34063 | winMemAssertMagic(); |
| 33999 | 34064 | if( winMemGetHeap()!=NULL && winMemGetOwned() && sqlite3_memory_used()==0 ){ |
| 34000 | 34065 | /* |
| @@ -35265,11 +35330,11 @@ | ||
| 35265 | 35330 | sqlite3_file *id, /* File to read from */ |
| 35266 | 35331 | void *pBuf, /* Write content into this buffer */ |
| 35267 | 35332 | int amt, /* Number of bytes to read */ |
| 35268 | 35333 | sqlite3_int64 offset /* Begin reading at this offset */ |
| 35269 | 35334 | ){ |
| 35270 | -#if !SQLITE_OS_WINCE | |
| 35335 | +#if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED) | |
| 35271 | 35336 | OVERLAPPED overlapped; /* The offset for ReadFile. */ |
| 35272 | 35337 | #endif |
| 35273 | 35338 | winFile *pFile = (winFile*)id; /* file handle */ |
| 35274 | 35339 | DWORD nRead; /* Number of bytes actually read from file */ |
| 35275 | 35340 | int nRetry = 0; /* Number of retrys */ |
| @@ -35297,11 +35362,11 @@ | ||
| 35297 | 35362 | offset += nCopy; |
| 35298 | 35363 | } |
| 35299 | 35364 | } |
| 35300 | 35365 | #endif |
| 35301 | 35366 | |
| 35302 | -#if SQLITE_OS_WINCE | |
| 35367 | +#if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED) | |
| 35303 | 35368 | if( winSeekFile(pFile, offset) ){ |
| 35304 | 35369 | OSTRACE(("READ file=%p, rc=SQLITE_FULL\n", pFile->h)); |
| 35305 | 35370 | return SQLITE_FULL; |
| 35306 | 35371 | } |
| 35307 | 35372 | while( !osReadFile(pFile->h, pBuf, amt, &nRead, 0) ){ |
| @@ -35369,32 +35434,32 @@ | ||
| 35369 | 35434 | offset += nCopy; |
| 35370 | 35435 | } |
| 35371 | 35436 | } |
| 35372 | 35437 | #endif |
| 35373 | 35438 | |
| 35374 | -#if SQLITE_OS_WINCE | |
| 35439 | +#if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED) | |
| 35375 | 35440 | rc = winSeekFile(pFile, offset); |
| 35376 | 35441 | if( rc==0 ){ |
| 35377 | 35442 | #else |
| 35378 | 35443 | { |
| 35379 | 35444 | #endif |
| 35380 | -#if !SQLITE_OS_WINCE | |
| 35445 | +#if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED) | |
| 35381 | 35446 | OVERLAPPED overlapped; /* The offset for WriteFile. */ |
| 35382 | 35447 | #endif |
| 35383 | 35448 | u8 *aRem = (u8 *)pBuf; /* Data yet to be written */ |
| 35384 | 35449 | int nRem = amt; /* Number of bytes yet to be written */ |
| 35385 | 35450 | DWORD nWrite; /* Bytes written by each WriteFile() call */ |
| 35386 | 35451 | DWORD lastErrno = NO_ERROR; /* Value returned by GetLastError() */ |
| 35387 | 35452 | |
| 35388 | -#if !SQLITE_OS_WINCE | |
| 35453 | +#if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED) | |
| 35389 | 35454 | memset(&overlapped, 0, sizeof(OVERLAPPED)); |
| 35390 | 35455 | overlapped.Offset = (LONG)(offset & 0xffffffff); |
| 35391 | 35456 | overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff); |
| 35392 | 35457 | #endif |
| 35393 | 35458 | |
| 35394 | 35459 | while( nRem>0 ){ |
| 35395 | -#if SQLITE_OS_WINCE | |
| 35460 | +#if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED) | |
| 35396 | 35461 | if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, 0) ){ |
| 35397 | 35462 | #else |
| 35398 | 35463 | if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, &overlapped) ){ |
| 35399 | 35464 | #endif |
| 35400 | 35465 | if( winRetryIoerr(&nRetry, &lastErrno) ) continue; |
| @@ -35403,11 +35468,11 @@ | ||
| 35403 | 35468 | assert( nWrite==0 || nWrite<=(DWORD)nRem ); |
| 35404 | 35469 | if( nWrite==0 || nWrite>(DWORD)nRem ){ |
| 35405 | 35470 | lastErrno = osGetLastError(); |
| 35406 | 35471 | break; |
| 35407 | 35472 | } |
| 35408 | -#if !SQLITE_OS_WINCE | |
| 35473 | +#if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED) | |
| 35409 | 35474 | offset += nWrite; |
| 35410 | 35475 | overlapped.Offset = (LONG)(offset & 0xffffffff); |
| 35411 | 35476 | overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff); |
| 35412 | 35477 | #endif |
| 35413 | 35478 | aRem += nWrite; |
| @@ -38949,11 +39014,12 @@ | ||
| 38949 | 39014 | SQLITE_PRIVATE int sqlite3PcacheSetPageSize(PCache *pCache, int szPage){ |
| 38950 | 39015 | assert( pCache->nRef==0 && pCache->pDirty==0 ); |
| 38951 | 39016 | if( pCache->szPage ){ |
| 38952 | 39017 | sqlite3_pcache *pNew; |
| 38953 | 39018 | pNew = sqlite3GlobalConfig.pcache2.xCreate( |
| 38954 | - szPage, pCache->szExtra + sizeof(PgHdr), pCache->bPurgeable | |
| 39019 | + szPage, pCache->szExtra + ROUND8(sizeof(PgHdr)), | |
| 39020 | + pCache->bPurgeable | |
| 38955 | 39021 | ); |
| 38956 | 39022 | if( pNew==0 ) return SQLITE_NOMEM; |
| 38957 | 39023 | sqlite3GlobalConfig.pcache2.xCachesize(pNew, numberOfCachePages(pCache)); |
| 38958 | 39024 | if( pCache->pCache ){ |
| 38959 | 39025 | sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache); |
| @@ -39408,11 +39474,11 @@ | ||
| 39408 | 39474 | |
| 39409 | 39475 | /* |
| 39410 | 39476 | ** Return the size of the header added by this middleware layer |
| 39411 | 39477 | ** in the page-cache hierarchy. |
| 39412 | 39478 | */ |
| 39413 | -SQLITE_PRIVATE int sqlite3HeaderSizePcache(void){ return sizeof(PgHdr); } | |
| 39479 | +SQLITE_PRIVATE int sqlite3HeaderSizePcache(void){ return ROUND8(sizeof(PgHdr)); } | |
| 39414 | 39480 | |
| 39415 | 39481 | |
| 39416 | 39482 | #if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG) |
| 39417 | 39483 | /* |
| 39418 | 39484 | ** For all dirty pages currently in the cache, invoke the specified |
| @@ -39724,11 +39790,11 @@ | ||
| 39724 | 39790 | pcache1Free(pPg); |
| 39725 | 39791 | sqlite3_free(p); |
| 39726 | 39792 | pPg = 0; |
| 39727 | 39793 | } |
| 39728 | 39794 | #else |
| 39729 | - pPg = pcache1Alloc(sizeof(PgHdr1) + pCache->szPage + pCache->szExtra); | |
| 39795 | + pPg = pcache1Alloc(ROUND8(sizeof(PgHdr1)) + pCache->szPage + pCache->szExtra); | |
| 39730 | 39796 | p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage]; |
| 39731 | 39797 | #endif |
| 39732 | 39798 | pcache1EnterMutex(pCache->pGroup); |
| 39733 | 39799 | |
| 39734 | 39800 | if( pPg ){ |
| @@ -40412,11 +40478,11 @@ | ||
| 40412 | 40478 | } |
| 40413 | 40479 | |
| 40414 | 40480 | /* |
| 40415 | 40481 | ** Return the size of the header on each page of this PCACHE implementation. |
| 40416 | 40482 | */ |
| 40417 | -SQLITE_PRIVATE int sqlite3HeaderSizePcache1(void){ return sizeof(PgHdr1); } | |
| 40483 | +SQLITE_PRIVATE int sqlite3HeaderSizePcache1(void){ return ROUND8(sizeof(PgHdr1)); } | |
| 40418 | 40484 | |
| 40419 | 40485 | #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT |
| 40420 | 40486 | /* |
| 40421 | 40487 | ** This function is called to free superfluous dynamically allocated memory |
| 40422 | 40488 | ** held by the pager system. Memory in use by any SQLite pager allocated |
| @@ -41770,10 +41836,12 @@ | ||
| 41770 | 41836 | u8 eLock; /* Current lock held on database file */ |
| 41771 | 41837 | u8 changeCountDone; /* Set after incrementing the change-counter */ |
| 41772 | 41838 | u8 setMaster; /* True if a m-j name has been written to jrnl */ |
| 41773 | 41839 | u8 doNotSpill; /* Do not spill the cache when non-zero */ |
| 41774 | 41840 | u8 subjInMemory; /* True to use in-memory sub-journals */ |
| 41841 | + u8 bUseFetch; /* True to use xFetch() */ | |
| 41842 | + u8 hasBeenUsed; /* True if any content previously read from this pager*/ | |
| 41775 | 41843 | Pgno dbSize; /* Number of pages in the database */ |
| 41776 | 41844 | Pgno dbOrigSize; /* dbSize before the current transaction */ |
| 41777 | 41845 | Pgno dbFileSize; /* Number of pages in the database file */ |
| 41778 | 41846 | Pgno dbHintSize; /* Value passed to FCNTL_SIZE_HINT call */ |
| 41779 | 41847 | int errCode; /* One of several kinds of errors */ |
| @@ -41787,13 +41855,13 @@ | ||
| 41787 | 41855 | i64 journalOff; /* Current write offset in the journal file */ |
| 41788 | 41856 | i64 journalHdr; /* Byte offset to previous journal header */ |
| 41789 | 41857 | sqlite3_backup *pBackup; /* Pointer to list of ongoing backup processes */ |
| 41790 | 41858 | PagerSavepoint *aSavepoint; /* Array of active savepoints */ |
| 41791 | 41859 | int nSavepoint; /* Number of elements in aSavepoint[] */ |
| 41860 | + u32 iDataVersion; /* Changes whenever database content changes */ | |
| 41792 | 41861 | char dbFileVers[16]; /* Changes whenever database file changes */ |
| 41793 | 41862 | |
| 41794 | - u8 bUseFetch; /* True to use xFetch() */ | |
| 41795 | 41863 | int nMmapOut; /* Number of mmap pages currently outstanding */ |
| 41796 | 41864 | sqlite3_int64 szMmap; /* Desired maximum mmap size */ |
| 41797 | 41865 | PgHdr *pMmapFreelist; /* List of free mmap page headers (pDirty) */ |
| 41798 | 41866 | /* |
| 41799 | 41867 | ** End of the routinely-changing class members |
| @@ -42805,13 +42873,22 @@ | ||
| 42805 | 42873 | |
| 42806 | 42874 | /* |
| 42807 | 42875 | ** Discard the entire contents of the in-memory page-cache. |
| 42808 | 42876 | */ |
| 42809 | 42877 | static void pager_reset(Pager *pPager){ |
| 42878 | + pPager->iDataVersion++; | |
| 42810 | 42879 | sqlite3BackupRestart(pPager->pBackup); |
| 42811 | 42880 | sqlite3PcacheClear(pPager->pPCache); |
| 42812 | 42881 | } |
| 42882 | + | |
| 42883 | +/* | |
| 42884 | +** Return the pPager->iDataVersion value | |
| 42885 | +*/ | |
| 42886 | +SQLITE_PRIVATE u32 sqlite3PagerDataVersion(Pager *pPager){ | |
| 42887 | + assert( pPager->eState>PAGER_OPEN ); | |
| 42888 | + return pPager->iDataVersion; | |
| 42889 | +} | |
| 42813 | 42890 | |
| 42814 | 42891 | /* |
| 42815 | 42892 | ** Free all structures in the Pager.aSavepoint[] array and set both |
| 42816 | 42893 | ** Pager.aSavepoint and Pager.nSavepoint to zero. Close the sub-journal |
| 42817 | 42894 | ** if it is open and the pager is not in exclusive mode. |
| @@ -45011,11 +45088,11 @@ | ||
| 45011 | 45088 | Pgno pgno, /* Page number */ |
| 45012 | 45089 | void *pData, /* xFetch()'d data for this page */ |
| 45013 | 45090 | PgHdr **ppPage /* OUT: Acquired page object */ |
| 45014 | 45091 | ){ |
| 45015 | 45092 | PgHdr *p; /* Memory mapped page to return */ |
| 45016 | - | |
| 45093 | + | |
| 45017 | 45094 | if( pPager->pMmapFreelist ){ |
| 45018 | 45095 | *ppPage = p = pPager->pMmapFreelist; |
| 45019 | 45096 | pPager->pMmapFreelist = p->pDirty; |
| 45020 | 45097 | p->pDirty = 0; |
| 45021 | 45098 | memset(p->pExtra, 0, pPager->nExtra); |
| @@ -46242,20 +46319,16 @@ | ||
| 46242 | 46319 | assert( (pPager->eLock==SHARED_LOCK) |
| 46243 | 46320 | || (pPager->exclusiveMode && pPager->eLock>SHARED_LOCK) |
| 46244 | 46321 | ); |
| 46245 | 46322 | } |
| 46246 | 46323 | |
| 46247 | - if( !pPager->tempFile && ( | |
| 46248 | - pPager->pBackup | |
| 46249 | - || sqlite3PcachePagecount(pPager->pPCache)>0 | |
| 46250 | - || USEFETCH(pPager) | |
| 46251 | - )){ | |
| 46252 | - /* The shared-lock has just been acquired on the database file | |
| 46253 | - ** and there are already pages in the cache (from a previous | |
| 46254 | - ** read or write transaction). Check to see if the database | |
| 46255 | - ** has been modified. If the database has changed, flush the | |
| 46256 | - ** cache. | |
| 46324 | + if( !pPager->tempFile && pPager->hasBeenUsed ){ | |
| 46325 | + /* The shared-lock has just been acquired then check to | |
| 46326 | + ** see if the database has been modified. If the database has changed, | |
| 46327 | + ** flush the cache. The pPager->hasBeenUsed flag prevents this from | |
| 46328 | + ** occurring on the very first access to a file, in order to save a | |
| 46329 | + ** single unnecessary sqlite3OsRead() call at the start-up. | |
| 46257 | 46330 | ** |
| 46258 | 46331 | ** Database changes is detected by looking at 15 bytes beginning |
| 46259 | 46332 | ** at offset 24 into the file. The first 4 of these 16 bytes are |
| 46260 | 46333 | ** a 32-bit counter that is incremented with each change. The |
| 46261 | 46334 | ** other bytes change randomly with each file change when |
| @@ -46416,10 +46489,11 @@ | ||
| 46416 | 46489 | assert( noContent==0 || bMmapOk==0 ); |
| 46417 | 46490 | |
| 46418 | 46491 | if( pgno==0 ){ |
| 46419 | 46492 | return SQLITE_CORRUPT_BKPT; |
| 46420 | 46493 | } |
| 46494 | + pPager->hasBeenUsed = 1; | |
| 46421 | 46495 | |
| 46422 | 46496 | /* If the pager is in the error state, return an error immediately. |
| 46423 | 46497 | ** Otherwise, request the page from the PCache layer. */ |
| 46424 | 46498 | if( pPager->errCode!=SQLITE_OK ){ |
| 46425 | 46499 | rc = pPager->errCode; |
| @@ -46565,10 +46639,11 @@ | ||
| 46565 | 46639 | sqlite3_pcache_page *pPage; |
| 46566 | 46640 | assert( pPager!=0 ); |
| 46567 | 46641 | assert( pgno!=0 ); |
| 46568 | 46642 | assert( pPager->pPCache!=0 ); |
| 46569 | 46643 | pPage = sqlite3PcacheFetch(pPager->pPCache, pgno, 0); |
| 46644 | + assert( pPage==0 || pPager->hasBeenUsed ); | |
| 46570 | 46645 | return sqlite3PcacheFetchFinish(pPager->pPCache, pgno, pPage); |
| 46571 | 46646 | } |
| 46572 | 46647 | |
| 46573 | 46648 | /* |
| 46574 | 46649 | ** Release a page reference. |
| @@ -47431,10 +47506,11 @@ | ||
| 47431 | 47506 | pPager->eState = PAGER_READER; |
| 47432 | 47507 | return SQLITE_OK; |
| 47433 | 47508 | } |
| 47434 | 47509 | |
| 47435 | 47510 | PAGERTRACE(("COMMIT %d\n", PAGERID(pPager))); |
| 47511 | + pPager->iDataVersion++; | |
| 47436 | 47512 | rc = pager_end_transaction(pPager, pPager->setMaster, 1); |
| 47437 | 47513 | return pager_error(pPager, rc); |
| 47438 | 47514 | } |
| 47439 | 47515 | |
| 47440 | 47516 | /* |
| @@ -48199,11 +48275,12 @@ | ||
| 48199 | 48275 | */ |
| 48200 | 48276 | SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, int eMode, int *pnLog, int *pnCkpt){ |
| 48201 | 48277 | int rc = SQLITE_OK; |
| 48202 | 48278 | if( pPager->pWal ){ |
| 48203 | 48279 | rc = sqlite3WalCheckpoint(pPager->pWal, eMode, |
| 48204 | - pPager->xBusyHandler, pPager->pBusyHandlerArg, | |
| 48280 | + (eMode==SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler), | |
| 48281 | + pPager->pBusyHandlerArg, | |
| 48205 | 48282 | pPager->ckptSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace, |
| 48206 | 48283 | pnLog, pnCkpt |
| 48207 | 48284 | ); |
| 48208 | 48285 | } |
| 48209 | 48286 | return rc; |
| @@ -50009,10 +50086,42 @@ | ||
| 50009 | 50086 | ** Return the page-size in bytes used by the database. |
| 50010 | 50087 | */ |
| 50011 | 50088 | static int walPagesize(Wal *pWal){ |
| 50012 | 50089 | return (pWal->hdr.szPage&0xfe00) + ((pWal->hdr.szPage&0x0001)<<16); |
| 50013 | 50090 | } |
| 50091 | + | |
| 50092 | +/* | |
| 50093 | +** The following is guaranteed when this function is called: | |
| 50094 | +** | |
| 50095 | +** a) the WRITER lock is held, | |
| 50096 | +** b) the entire log file has been checkpointed, and | |
| 50097 | +** c) any existing readers are reading exclusively from the database | |
| 50098 | +** file - there are no readers that may attempt to read a frame from | |
| 50099 | +** the log file. | |
| 50100 | +** | |
| 50101 | +** This function updates the shared-memory structures so that the next | |
| 50102 | +** client to write to the database (which may be this one) does so by | |
| 50103 | +** writing frames into the start of the log file. | |
| 50104 | +** | |
| 50105 | +** The value of parameter salt1 is used as the aSalt[1] value in the | |
| 50106 | +** new wal-index header. It should be passed a pseudo-random value (i.e. | |
| 50107 | +** one obtained from sqlite3_randomness()). | |
| 50108 | +*/ | |
| 50109 | +static void walRestartHdr(Wal *pWal, u32 salt1){ | |
| 50110 | + volatile WalCkptInfo *pInfo = walCkptInfo(pWal); | |
| 50111 | + int i; /* Loop counter */ | |
| 50112 | + u32 *aSalt = pWal->hdr.aSalt; /* Big-endian salt values */ | |
| 50113 | + pWal->nCkpt++; | |
| 50114 | + pWal->hdr.mxFrame = 0; | |
| 50115 | + sqlite3Put4byte((u8*)&aSalt[0], 1 + sqlite3Get4byte((u8*)&aSalt[0])); | |
| 50116 | + memcpy(&pWal->hdr.aSalt[1], &salt1, 4); | |
| 50117 | + walIndexWriteHdr(pWal); | |
| 50118 | + pInfo->nBackfill = 0; | |
| 50119 | + pInfo->aReadMark[1] = 0; | |
| 50120 | + for(i=2; i<WAL_NREADER; i++) pInfo->aReadMark[i] = READMARK_NOT_USED; | |
| 50121 | + assert( pInfo->aReadMark[0]==0 ); | |
| 50122 | +} | |
| 50014 | 50123 | |
| 50015 | 50124 | /* |
| 50016 | 50125 | ** Copy as much content as we can from the WAL back into the database file |
| 50017 | 50126 | ** in response to an sqlite3_wal_checkpoint() request or the equivalent. |
| 50018 | 50127 | ** |
| @@ -50044,11 +50153,11 @@ | ||
| 50044 | 50153 | ** time. |
| 50045 | 50154 | */ |
| 50046 | 50155 | static int walCheckpoint( |
| 50047 | 50156 | Wal *pWal, /* Wal connection */ |
| 50048 | 50157 | int eMode, /* One of PASSIVE, FULL or RESTART */ |
| 50049 | - int (*xBusyCall)(void*), /* Function to call when busy */ | |
| 50158 | + int (*xBusy)(void*), /* Function to call when busy */ | |
| 50050 | 50159 | void *pBusyArg, /* Context argument for xBusyHandler */ |
| 50051 | 50160 | int sync_flags, /* Flags for OsSync() (or 0) */ |
| 50052 | 50161 | u8 *zBuf /* Temporary buffer to use */ |
| 50053 | 50162 | ){ |
| 50054 | 50163 | int rc; /* Return code */ |
| @@ -50058,11 +50167,10 @@ | ||
| 50058 | 50167 | u32 iFrame = 0; /* Wal frame containing data for iDbpage */ |
| 50059 | 50168 | u32 mxSafeFrame; /* Max frame that can be backfilled */ |
| 50060 | 50169 | u32 mxPage; /* Max database page to write */ |
| 50061 | 50170 | int i; /* Loop counter */ |
| 50062 | 50171 | volatile WalCkptInfo *pInfo; /* The checkpoint status information */ |
| 50063 | - int (*xBusy)(void*) = 0; /* Function to call when waiting for locks */ | |
| 50064 | 50172 | |
| 50065 | 50173 | szPage = walPagesize(pWal); |
| 50066 | 50174 | testcase( szPage<=32768 ); |
| 50067 | 50175 | testcase( szPage>=65536 ); |
| 50068 | 50176 | pInfo = walCkptInfo(pWal); |
| @@ -50073,11 +50181,13 @@ | ||
| 50073 | 50181 | if( rc!=SQLITE_OK ){ |
| 50074 | 50182 | return rc; |
| 50075 | 50183 | } |
| 50076 | 50184 | assert( pIter ); |
| 50077 | 50185 | |
| 50078 | - if( eMode!=SQLITE_CHECKPOINT_PASSIVE ) xBusy = xBusyCall; | |
| 50186 | + /* EVIDENCE-OF: R-62920-47450 The busy-handler callback is never invoked | |
| 50187 | + ** in the SQLITE_CHECKPOINT_PASSIVE mode. */ | |
| 50188 | + assert( eMode!=SQLITE_CHECKPOINT_PASSIVE || xBusy==0 ); | |
| 50079 | 50189 | |
| 50080 | 50190 | /* Compute in mxSafeFrame the index of the last frame of the WAL that is |
| 50081 | 50191 | ** safe to write into the database. Frames beyond mxSafeFrame might |
| 50082 | 50192 | ** overwrite database pages that are in use by active readers and thus |
| 50083 | 50193 | ** cannot be backfilled from the WAL. |
| @@ -50162,23 +50272,42 @@ | ||
| 50162 | 50272 | /* Reset the return code so as not to report a checkpoint failure |
| 50163 | 50273 | ** just because there are active readers. */ |
| 50164 | 50274 | rc = SQLITE_OK; |
| 50165 | 50275 | } |
| 50166 | 50276 | |
| 50167 | - /* If this is an SQLITE_CHECKPOINT_RESTART operation, and the entire wal | |
| 50168 | - ** file has been copied into the database file, then block until all | |
| 50169 | - ** readers have finished using the wal file. This ensures that the next | |
| 50170 | - ** process to write to the database restarts the wal file. | |
| 50277 | + /* If this is an SQLITE_CHECKPOINT_RESTART or TRUNCATE operation, and the | |
| 50278 | + ** entire wal file has been copied into the database file, then block | |
| 50279 | + ** until all readers have finished using the wal file. This ensures that | |
| 50280 | + ** the next process to write to the database restarts the wal file. | |
| 50171 | 50281 | */ |
| 50172 | 50282 | if( rc==SQLITE_OK && eMode!=SQLITE_CHECKPOINT_PASSIVE ){ |
| 50173 | 50283 | assert( pWal->writeLock ); |
| 50174 | 50284 | if( pInfo->nBackfill<pWal->hdr.mxFrame ){ |
| 50175 | 50285 | rc = SQLITE_BUSY; |
| 50176 | - }else if( eMode==SQLITE_CHECKPOINT_RESTART ){ | |
| 50286 | + }else if( eMode>=SQLITE_CHECKPOINT_RESTART ){ | |
| 50287 | + u32 salt1; | |
| 50288 | + sqlite3_randomness(4, &salt1); | |
| 50177 | 50289 | assert( mxSafeFrame==pWal->hdr.mxFrame ); |
| 50178 | 50290 | rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(1), WAL_NREADER-1); |
| 50179 | 50291 | if( rc==SQLITE_OK ){ |
| 50292 | + if( eMode==SQLITE_CHECKPOINT_TRUNCATE ){ | |
| 50293 | + /* IMPLEMENTATION-OF: R-44699-57140 This mode works the same way as | |
| 50294 | + ** SQLITE_CHECKPOINT_RESTART with the addition that it also | |
| 50295 | + ** truncates the log file to zero bytes just prior to a | |
| 50296 | + ** successful return. | |
| 50297 | + ** | |
| 50298 | + ** In theory, it might be safe to do this without updating the | |
| 50299 | + ** wal-index header in shared memory, as all subsequent reader or | |
| 50300 | + ** writer clients should see that the entire log file has been | |
| 50301 | + ** checkpointed and behave accordingly. This seems unsafe though, | |
| 50302 | + ** as it would leave the system in a state where the contents of | |
| 50303 | + ** the wal-index header do not match the contents of the | |
| 50304 | + ** file-system. To avoid this, update the wal-index header to | |
| 50305 | + ** indicate that the log file contains zero valid frames. */ | |
| 50306 | + walRestartHdr(pWal, salt1); | |
| 50307 | + rc = sqlite3OsTruncate(pWal->pWalFd, 0); | |
| 50308 | + } | |
| 50180 | 50309 | walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1); |
| 50181 | 50310 | } |
| 50182 | 50311 | } |
| 50183 | 50312 | } |
| 50184 | 50313 | |
| @@ -50747,11 +50876,11 @@ | ||
| 50747 | 50876 | } |
| 50748 | 50877 | nCollide = HASHTABLE_NSLOT; |
| 50749 | 50878 | for(iKey=walHash(pgno); aHash[iKey]; iKey=walNextHash(iKey)){ |
| 50750 | 50879 | u32 iFrame = aHash[iKey] + iZero; |
| 50751 | 50880 | if( iFrame<=iLast && aPgno[aHash[iKey]]==pgno ){ |
| 50752 | - /* assert( iFrame>iRead ); -- not true if there is corruption */ | |
| 50881 | + assert( iFrame>iRead || CORRUPT_DB ); | |
| 50753 | 50882 | iRead = iFrame; |
| 50754 | 50883 | } |
| 50755 | 50884 | if( (nCollide--)==0 ){ |
| 50756 | 50885 | return SQLITE_CORRUPT_BKPT; |
| 50757 | 50886 | } |
| @@ -50960,11 +51089,10 @@ | ||
| 50960 | 51089 | } |
| 50961 | 51090 | |
| 50962 | 51091 | return rc; |
| 50963 | 51092 | } |
| 50964 | 51093 | |
| 50965 | - | |
| 50966 | 51094 | /* |
| 50967 | 51095 | ** This function is called just before writing a set of frames to the log |
| 50968 | 51096 | ** file (see sqlite3WalFrames()). It checks to see if, instead of appending |
| 50969 | 51097 | ** to the current log file, it is possible to overwrite the start of the |
| 50970 | 51098 | ** existing log file with the new frames (i.e. "reset" the log). If so, |
| @@ -50993,24 +51121,12 @@ | ||
| 50993 | 51121 | ** wal-index header to reflect this. |
| 50994 | 51122 | ** |
| 50995 | 51123 | ** In theory it would be Ok to update the cache of the header only |
| 50996 | 51124 | ** at this point. But updating the actual wal-index header is also |
| 50997 | 51125 | ** safe and means there is no special case for sqlite3WalUndo() |
| 50998 | - ** to handle if this transaction is rolled back. | |
| 50999 | - */ | |
| 51000 | - int i; /* Loop counter */ | |
| 51001 | - u32 *aSalt = pWal->hdr.aSalt; /* Big-endian salt values */ | |
| 51002 | - | |
| 51003 | - pWal->nCkpt++; | |
| 51004 | - pWal->hdr.mxFrame = 0; | |
| 51005 | - sqlite3Put4byte((u8*)&aSalt[0], 1 + sqlite3Get4byte((u8*)&aSalt[0])); | |
| 51006 | - aSalt[1] = salt1; | |
| 51007 | - walIndexWriteHdr(pWal); | |
| 51008 | - pInfo->nBackfill = 0; | |
| 51009 | - pInfo->aReadMark[1] = 0; | |
| 51010 | - for(i=2; i<WAL_NREADER; i++) pInfo->aReadMark[i] = READMARK_NOT_USED; | |
| 51011 | - assert( pInfo->aReadMark[0]==0 ); | |
| 51126 | + ** to handle if this transaction is rolled back. */ | |
| 51127 | + walRestartHdr(pWal, salt1); | |
| 51012 | 51128 | walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1); |
| 51013 | 51129 | }else if( rc!=SQLITE_BUSY ){ |
| 51014 | 51130 | return rc; |
| 51015 | 51131 | } |
| 51016 | 51132 | } |
| @@ -51294,11 +51410,11 @@ | ||
| 51294 | 51410 | ** If parameter xBusy is not NULL, it is a pointer to a busy-handler |
| 51295 | 51411 | ** callback. In this case this function runs a blocking checkpoint. |
| 51296 | 51412 | */ |
| 51297 | 51413 | SQLITE_PRIVATE int sqlite3WalCheckpoint( |
| 51298 | 51414 | Wal *pWal, /* Wal connection */ |
| 51299 | - int eMode, /* PASSIVE, FULL or RESTART */ | |
| 51415 | + int eMode, /* PASSIVE, FULL, RESTART, or TRUNCATE */ | |
| 51300 | 51416 | int (*xBusy)(void*), /* Function to call when busy */ |
| 51301 | 51417 | void *pBusyArg, /* Context argument for xBusyHandler */ |
| 51302 | 51418 | int sync_flags, /* Flags to sync db file with (or 0) */ |
| 51303 | 51419 | int nBuf, /* Size of temporary buffer */ |
| 51304 | 51420 | u8 *zBuf, /* Temporary buffer to use */ |
| @@ -51306,40 +51422,54 @@ | ||
| 51306 | 51422 | int *pnCkpt /* OUT: Number of backfilled frames in WAL */ |
| 51307 | 51423 | ){ |
| 51308 | 51424 | int rc; /* Return code */ |
| 51309 | 51425 | int isChanged = 0; /* True if a new wal-index header is loaded */ |
| 51310 | 51426 | int eMode2 = eMode; /* Mode to pass to walCheckpoint() */ |
| 51427 | + int (*xBusy2)(void*) = xBusy; /* Busy handler for eMode2 */ | |
| 51311 | 51428 | |
| 51312 | 51429 | assert( pWal->ckptLock==0 ); |
| 51313 | 51430 | assert( pWal->writeLock==0 ); |
| 51314 | 51431 | |
| 51432 | + /* EVIDENCE-OF: R-62920-47450 The busy-handler callback is never invoked | |
| 51433 | + ** in the SQLITE_CHECKPOINT_PASSIVE mode. */ | |
| 51434 | + assert( eMode!=SQLITE_CHECKPOINT_PASSIVE || xBusy==0 ); | |
| 51435 | + | |
| 51315 | 51436 | if( pWal->readOnly ) return SQLITE_READONLY; |
| 51316 | 51437 | WALTRACE(("WAL%p: checkpoint begins\n", pWal)); |
| 51438 | + | |
| 51439 | + /* IMPLEMENTATION-OF: R-62028-47212 All calls obtain an exclusive | |
| 51440 | + ** "checkpoint" lock on the database file. */ | |
| 51317 | 51441 | rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1); |
| 51318 | 51442 | if( rc ){ |
| 51319 | - /* Usually this is SQLITE_BUSY meaning that another thread or process | |
| 51320 | - ** is already running a checkpoint, or maybe a recovery. But it might | |
| 51321 | - ** also be SQLITE_IOERR. */ | |
| 51443 | + /* EVIDENCE-OF: R-10421-19736 If any other process is running a | |
| 51444 | + ** checkpoint operation at the same time, the lock cannot be obtained and | |
| 51445 | + ** SQLITE_BUSY is returned. | |
| 51446 | + ** EVIDENCE-OF: R-53820-33897 Even if there is a busy-handler configured, | |
| 51447 | + ** it will not be invoked in this case. | |
| 51448 | + */ | |
| 51449 | + testcase( rc==SQLITE_BUSY ); | |
| 51450 | + testcase( xBusy!=0 ); | |
| 51322 | 51451 | return rc; |
| 51323 | 51452 | } |
| 51324 | 51453 | pWal->ckptLock = 1; |
| 51325 | 51454 | |
| 51326 | - /* If this is a blocking-checkpoint, then obtain the write-lock as well | |
| 51327 | - ** to prevent any writers from running while the checkpoint is underway. | |
| 51328 | - ** This has to be done before the call to walIndexReadHdr() below. | |
| 51455 | + /* IMPLEMENTATION-OF: R-59782-36818 The SQLITE_CHECKPOINT_FULL, RESTART and | |
| 51456 | + ** TRUNCATE modes also obtain the exclusive "writer" lock on the database | |
| 51457 | + ** file. | |
| 51329 | 51458 | ** |
| 51330 | - ** If the writer lock cannot be obtained, then a passive checkpoint is | |
| 51331 | - ** run instead. Since the checkpointer is not holding the writer lock, | |
| 51332 | - ** there is no point in blocking waiting for any readers. Assuming no | |
| 51333 | - ** other error occurs, this function will return SQLITE_BUSY to the caller. | |
| 51459 | + ** EVIDENCE-OF: R-60642-04082 If the writer lock cannot be obtained | |
| 51460 | + ** immediately, and a busy-handler is configured, it is invoked and the | |
| 51461 | + ** writer lock retried until either the busy-handler returns 0 or the | |
| 51462 | + ** lock is successfully obtained. | |
| 51334 | 51463 | */ |
| 51335 | 51464 | if( eMode!=SQLITE_CHECKPOINT_PASSIVE ){ |
| 51336 | 51465 | rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_WRITE_LOCK, 1); |
| 51337 | 51466 | if( rc==SQLITE_OK ){ |
| 51338 | 51467 | pWal->writeLock = 1; |
| 51339 | 51468 | }else if( rc==SQLITE_BUSY ){ |
| 51340 | 51469 | eMode2 = SQLITE_CHECKPOINT_PASSIVE; |
| 51470 | + xBusy2 = 0; | |
| 51341 | 51471 | rc = SQLITE_OK; |
| 51342 | 51472 | } |
| 51343 | 51473 | } |
| 51344 | 51474 | |
| 51345 | 51475 | /* Read the wal-index header. */ |
| @@ -51353,11 +51483,11 @@ | ||
| 51353 | 51483 | /* Copy data from the log to the database file. */ |
| 51354 | 51484 | if( rc==SQLITE_OK ){ |
| 51355 | 51485 | if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){ |
| 51356 | 51486 | rc = SQLITE_CORRUPT_BKPT; |
| 51357 | 51487 | }else{ |
| 51358 | - rc = walCheckpoint(pWal, eMode2, xBusy, pBusyArg, sync_flags, zBuf); | |
| 51488 | + rc = walCheckpoint(pWal, eMode2, xBusy2, pBusyArg, sync_flags, zBuf); | |
| 51359 | 51489 | } |
| 51360 | 51490 | |
| 51361 | 51491 | /* If no error occurred, set the output variables. */ |
| 51362 | 51492 | if( rc==SQLITE_OK || rc==SQLITE_BUSY ){ |
| 51363 | 51493 | if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame; |
| @@ -51852,10 +51982,11 @@ | ||
| 51852 | 51982 | u8 inTrans; /* TRANS_NONE, TRANS_READ or TRANS_WRITE */ |
| 51853 | 51983 | u8 sharable; /* True if we can share pBt with another db */ |
| 51854 | 51984 | u8 locked; /* True if db currently has pBt locked */ |
| 51855 | 51985 | int wantToLock; /* Number of nested calls to sqlite3BtreeEnter() */ |
| 51856 | 51986 | int nBackup; /* Number of backup operations reading this btree */ |
| 51987 | + u32 iDataVersion; /* Combines with pBt->pPager->iDataVersion */ | |
| 51857 | 51988 | Btree *pNext; /* List of other sharable Btrees from the same db */ |
| 51858 | 51989 | Btree *pPrev; /* Back pointer of the same list */ |
| 51859 | 51990 | #ifndef SQLITE_OMIT_SHARED_CACHE |
| 51860 | 51991 | BtLock lock; /* Object used to lock page 1 */ |
| 51861 | 51992 | #endif |
| @@ -53821,11 +53952,11 @@ | ||
| 53821 | 53952 | ** to see if defragmentation is necessary. |
| 53822 | 53953 | */ |
| 53823 | 53954 | testcase( gap+2+nByte==top ); |
| 53824 | 53955 | if( gap+2+nByte>top ){ |
| 53825 | 53956 | defragment_page: |
| 53826 | - testcase( pPage->nCell==0 ); | |
| 53957 | + assert( pPage->nCell>0 || CORRUPT_DB ); | |
| 53827 | 53958 | rc = defragmentPage(pPage); |
| 53828 | 53959 | if( rc ) return rc; |
| 53829 | 53960 | top = get2byteNotZero(&data[hdr+5]); |
| 53830 | 53961 | assert( gap+nByte<=top ); |
| 53831 | 53962 | } |
| @@ -56015,10 +56146,11 @@ | ||
| 56015 | 56146 | rc = sqlite3PagerCommitPhaseTwo(pBt->pPager); |
| 56016 | 56147 | if( rc!=SQLITE_OK && bCleanup==0 ){ |
| 56017 | 56148 | sqlite3BtreeLeave(p); |
| 56018 | 56149 | return rc; |
| 56019 | 56150 | } |
| 56151 | + p->iDataVersion--; /* Compensate for pPager->iDataVersion++; */ | |
| 56020 | 56152 | pBt->inTransaction = TRANS_READ; |
| 56021 | 56153 | btreeClearHasContent(pBt); |
| 56022 | 56154 | } |
| 56023 | 56155 | |
| 56024 | 56156 | btreeEndTransaction(p); |
| @@ -56378,11 +56510,11 @@ | ||
| 56378 | 56510 | } |
| 56379 | 56511 | for(i=0; i<=pCur->iPage; i++){ |
| 56380 | 56512 | releasePage(pCur->apPage[i]); |
| 56381 | 56513 | } |
| 56382 | 56514 | unlockBtreeIfUnused(pBt); |
| 56383 | - sqlite3DbFree(pBtree->db, pCur->aOverflow); | |
| 56515 | + sqlite3_free(pCur->aOverflow); | |
| 56384 | 56516 | /* sqlite3_free(pCur); */ |
| 56385 | 56517 | sqlite3BtreeLeave(pBtree); |
| 56386 | 56518 | } |
| 56387 | 56519 | return SQLITE_OK; |
| 56388 | 56520 | } |
| @@ -56672,10 +56804,11 @@ | ||
| 56672 | 56804 | pBuf += a; |
| 56673 | 56805 | amt -= a; |
| 56674 | 56806 | }else{ |
| 56675 | 56807 | offset -= pCur->info.nLocal; |
| 56676 | 56808 | } |
| 56809 | + | |
| 56677 | 56810 | |
| 56678 | 56811 | if( rc==SQLITE_OK && amt>0 ){ |
| 56679 | 56812 | const u32 ovflSize = pBt->usableSize - 4; /* Bytes content per ovfl page */ |
| 56680 | 56813 | Pgno nextPage; |
| 56681 | 56814 | |
| @@ -56690,12 +56823,12 @@ | ||
| 56690 | 56823 | ** means "not yet known" (the cache is lazily populated). |
| 56691 | 56824 | */ |
| 56692 | 56825 | if( eOp!=2 && (pCur->curFlags & BTCF_ValidOvfl)==0 ){ |
| 56693 | 56826 | int nOvfl = (pCur->info.nPayload-pCur->info.nLocal+ovflSize-1)/ovflSize; |
| 56694 | 56827 | if( nOvfl>pCur->nOvflAlloc ){ |
| 56695 | - Pgno *aNew = (Pgno*)sqlite3DbRealloc( | |
| 56696 | - pCur->pBtree->db, pCur->aOverflow, nOvfl*2*sizeof(Pgno) | |
| 56828 | + Pgno *aNew = (Pgno*)sqlite3Realloc( | |
| 56829 | + pCur->aOverflow, nOvfl*2*sizeof(Pgno) | |
| 56697 | 56830 | ); |
| 56698 | 56831 | if( aNew==0 ){ |
| 56699 | 56832 | rc = SQLITE_NOMEM; |
| 56700 | 56833 | }else{ |
| 56701 | 56834 | pCur->nOvflAlloc = nOvfl*2; |
| @@ -56738,10 +56871,11 @@ | ||
| 56738 | 56871 | ** Note that the aOverflow[] array must be allocated because eOp!=2 |
| 56739 | 56872 | ** here. If eOp==2, then offset==0 and this branch is never taken. |
| 56740 | 56873 | */ |
| 56741 | 56874 | assert( eOp!=2 ); |
| 56742 | 56875 | assert( pCur->curFlags & BTCF_ValidOvfl ); |
| 56876 | + assert( pCur->pBtree->db==pBt->db ); | |
| 56743 | 56877 | if( pCur->aOverflow[iIdx+1] ){ |
| 56744 | 56878 | nextPage = pCur->aOverflow[iIdx+1]; |
| 56745 | 56879 | }else{ |
| 56746 | 56880 | rc = getOverflowPage(pBt, nextPage, 0, &nextPage); |
| 56747 | 56881 | } |
| @@ -58881,11 +59015,11 @@ | ||
| 58881 | 59015 | assert( sqlite3_mutex_held(pPage->pBt->mutex) ); |
| 58882 | 59016 | assert( sqlite3PagerIswriteable(pParent->pDbPage) ); |
| 58883 | 59017 | assert( pPage->nOverflow==1 ); |
| 58884 | 59018 | |
| 58885 | 59019 | /* This error condition is now caught prior to reaching this function */ |
| 58886 | - if( pPage->nCell==0 ) return SQLITE_CORRUPT_BKPT; | |
| 59020 | + if( NEVER(pPage->nCell==0) ) return SQLITE_CORRUPT_BKPT; | |
| 58887 | 59021 | |
| 58888 | 59022 | /* Allocate a new page. This page will become the right-sibling of |
| 58889 | 59023 | ** pPage. Make the parent page writable, so that the new divider cell |
| 58890 | 59024 | ** may be inserted. If both these operations are successful, proceed. |
| 58891 | 59025 | */ |
| @@ -59250,11 +59384,11 @@ | ||
| 59250 | 59384 | + nMaxCells*sizeof(u16) /* szCell */ |
| 59251 | 59385 | + pBt->pageSize; /* aSpace1 */ |
| 59252 | 59386 | |
| 59253 | 59387 | /* EVIDENCE-OF: R-28375-38319 SQLite will never request a scratch buffer |
| 59254 | 59388 | ** that is more than 6 times the database page size. */ |
| 59255 | - assert( szScratch<=6*pBt->pageSize ); | |
| 59389 | + assert( szScratch<=6*(int)pBt->pageSize ); | |
| 59256 | 59390 | apCell = sqlite3ScratchMalloc( szScratch ); |
| 59257 | 59391 | if( apCell==0 ){ |
| 59258 | 59392 | rc = SQLITE_NOMEM; |
| 59259 | 59393 | goto balance_cleanup; |
| 59260 | 59394 | } |
| @@ -59324,11 +59458,15 @@ | ||
| 59324 | 59458 | ** pointer of the divider cell */ |
| 59325 | 59459 | memcpy(apCell[nCell], &pOld->aData[8], 4); |
| 59326 | 59460 | }else{ |
| 59327 | 59461 | assert( leafCorrection==4 ); |
| 59328 | 59462 | if( szCell[nCell]<4 ){ |
| 59329 | - /* Do not allow any cells smaller than 4 bytes. */ | |
| 59463 | + /* Do not allow any cells smaller than 4 bytes. If a smaller cell | |
| 59464 | + ** does exist, pad it with 0x00 bytes. */ | |
| 59465 | + assert( szCell[nCell]==3 ); | |
| 59466 | + assert( apCell[nCell]==&aSpace1[iSpace1-3] ); | |
| 59467 | + aSpace1[iSpace1++] = 0x00; | |
| 59330 | 59468 | szCell[nCell] = 4; |
| 59331 | 59469 | } |
| 59332 | 59470 | } |
| 59333 | 59471 | nCell++; |
| 59334 | 59472 | } |
| @@ -59559,11 +59697,15 @@ | ||
| 59559 | 59697 | ** was either part of sibling page iOld (possibly an overflow cell), |
| 59560 | 59698 | ** or else the divider cell to the left of sibling page iOld. So, |
| 59561 | 59699 | ** if sibling page iOld had the same page number as pNew, and if |
| 59562 | 59700 | ** pCell really was a part of sibling page iOld (not a divider or |
| 59563 | 59701 | ** overflow cell), we can skip updating the pointer map entries. */ |
| 59564 | - if( pNew->pgno!=aPgno[iOld] || pCell<aOld || pCell>=&aOld[usableSize] ){ | |
| 59702 | + if( iOld>=nNew | |
| 59703 | + || pNew->pgno!=aPgno[iOld] | |
| 59704 | + || pCell<aOld | |
| 59705 | + || pCell>=&aOld[usableSize] | |
| 59706 | + ){ | |
| 59565 | 59707 | if( !leafCorrection ){ |
| 59566 | 59708 | ptrmapPut(pBt, get4byte(pCell), PTRMAP_BTREE, pNew->pgno, &rc); |
| 59567 | 59709 | } |
| 59568 | 59710 | if( szCell[i]>pNew->minLocal ){ |
| 59569 | 59711 | ptrmapPutOvflPtr(pNew, pCell, &rc); |
| @@ -60632,10 +60774,17 @@ | ||
| 60632 | 60774 | ** is read-only, the others are read/write. |
| 60633 | 60775 | ** |
| 60634 | 60776 | ** The schema layer numbers meta values differently. At the schema |
| 60635 | 60777 | ** layer (and the SetCookie and ReadCookie opcodes) the number of |
| 60636 | 60778 | ** free pages is not visible. So Cookie[0] is the same as Meta[1]. |
| 60779 | +** | |
| 60780 | +** This routine treats Meta[BTREE_DATA_VERSION] as a special case. Instead | |
| 60781 | +** of reading the value out of the header, it instead loads the "DataVersion" | |
| 60782 | +** from the pager. The BTREE_DATA_VERSION value is not actually stored in the | |
| 60783 | +** database file. It is a number computed by the pager. But its access | |
| 60784 | +** pattern is the same as header meta values, and so it is convenient to | |
| 60785 | +** read it from this routine. | |
| 60637 | 60786 | */ |
| 60638 | 60787 | SQLITE_PRIVATE void sqlite3BtreeGetMeta(Btree *p, int idx, u32 *pMeta){ |
| 60639 | 60788 | BtShared *pBt = p->pBt; |
| 60640 | 60789 | |
| 60641 | 60790 | sqlite3BtreeEnter(p); |
| @@ -60642,11 +60791,15 @@ | ||
| 60642 | 60791 | assert( p->inTrans>TRANS_NONE ); |
| 60643 | 60792 | assert( SQLITE_OK==querySharedCacheTableLock(p, MASTER_ROOT, READ_LOCK) ); |
| 60644 | 60793 | assert( pBt->pPage1 ); |
| 60645 | 60794 | assert( idx>=0 && idx<=15 ); |
| 60646 | 60795 | |
| 60647 | - *pMeta = get4byte(&pBt->pPage1->aData[36 + idx*4]); | |
| 60796 | + if( idx==BTREE_DATA_VERSION ){ | |
| 60797 | + *pMeta = sqlite3PagerDataVersion(pBt->pPager) + p->iDataVersion; | |
| 60798 | + }else{ | |
| 60799 | + *pMeta = get4byte(&pBt->pPage1->aData[36 + idx*4]); | |
| 60800 | + } | |
| 60648 | 60801 | |
| 60649 | 60802 | /* If auto-vacuum is disabled in this build and this is an auto-vacuum |
| 60650 | 60803 | ** database, mark the database as read-only. */ |
| 60651 | 60804 | #ifdef SQLITE_OMIT_AUTOVACUUM |
| 60652 | 60805 | if( idx==BTREE_LARGEST_ROOT_PAGE && *pMeta>0 ){ |
| @@ -60733,11 +60886,11 @@ | ||
| 60733 | 60886 | if( pPage->leaf ){ |
| 60734 | 60887 | do { |
| 60735 | 60888 | if( pCur->iPage==0 ){ |
| 60736 | 60889 | /* All pages of the b-tree have been visited. Return successfully. */ |
| 60737 | 60890 | *pnEntry = nEntry; |
| 60738 | - return SQLITE_OK; | |
| 60891 | + return moveToRoot(pCur); | |
| 60739 | 60892 | } |
| 60740 | 60893 | moveToParent(pCur); |
| 60741 | 60894 | }while ( pCur->aiIdx[pCur->iPage]>=pCur->apPage[pCur->iPage]->nCell ); |
| 60742 | 60895 | |
| 60743 | 60896 | pCur->aiIdx[pCur->iPage]++; |
| @@ -61589,11 +61742,11 @@ | ||
| 61589 | 61742 | } |
| 61590 | 61743 | |
| 61591 | 61744 | /* |
| 61592 | 61745 | ** Return the size of the header added to each page by this module. |
| 61593 | 61746 | */ |
| 61594 | -SQLITE_PRIVATE int sqlite3HeaderSizeBtree(void){ return sizeof(MemPage); } | |
| 61747 | +SQLITE_PRIVATE int sqlite3HeaderSizeBtree(void){ return ROUND8(sizeof(MemPage)); } | |
| 61595 | 61748 | |
| 61596 | 61749 | /************** End of btree.c ***********************************************/ |
| 61597 | 61750 | /************** Begin file backup.c ******************************************/ |
| 61598 | 61751 | /* |
| 61599 | 61752 | ** 2009 January 28 |
| @@ -64353,36 +64506,39 @@ | ||
| 64353 | 64506 | ** |
| 64354 | 64507 | ** assert( sqlite3VdbeAssertMayAbort(pParse->pVdbe, pParse->mayAbort) ); |
| 64355 | 64508 | */ |
| 64356 | 64509 | SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){ |
| 64357 | 64510 | int hasAbort = 0; |
| 64511 | + int hasFkCounter = 0; | |
| 64358 | 64512 | Op *pOp; |
| 64359 | 64513 | VdbeOpIter sIter; |
| 64360 | 64514 | memset(&sIter, 0, sizeof(sIter)); |
| 64361 | 64515 | sIter.v = v; |
| 64362 | 64516 | |
| 64363 | 64517 | while( (pOp = opIterNext(&sIter))!=0 ){ |
| 64364 | 64518 | int opcode = pOp->opcode; |
| 64365 | 64519 | if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename |
| 64366 | -#ifndef SQLITE_OMIT_FOREIGN_KEY | |
| 64367 | - || (opcode==OP_FkCounter && pOp->p1==0 && pOp->p2==1) | |
| 64368 | -#endif | |
| 64369 | 64520 | || ((opcode==OP_Halt || opcode==OP_HaltIfNull) |
| 64370 | 64521 | && ((pOp->p1&0xff)==SQLITE_CONSTRAINT && pOp->p2==OE_Abort)) |
| 64371 | 64522 | ){ |
| 64372 | 64523 | hasAbort = 1; |
| 64373 | 64524 | break; |
| 64374 | 64525 | } |
| 64526 | +#ifndef SQLITE_OMIT_FOREIGN_KEY | |
| 64527 | + if( opcode==OP_FkCounter && pOp->p1==0 && pOp->p2==1 ){ | |
| 64528 | + hasFkCounter = 1; | |
| 64529 | + } | |
| 64530 | +#endif | |
| 64375 | 64531 | } |
| 64376 | 64532 | sqlite3DbFree(v->db, sIter.apSub); |
| 64377 | 64533 | |
| 64378 | 64534 | /* Return true if hasAbort==mayAbort. Or if a malloc failure occurred. |
| 64379 | 64535 | ** If malloc failed, then the while() loop above may not have iterated |
| 64380 | 64536 | ** through all opcodes and hasAbort may be set incorrectly. Return |
| 64381 | 64537 | ** true for this case to prevent the assert() in the callers frame |
| 64382 | 64538 | ** from failing. */ |
| 64383 | - return ( v->db->mallocFailed || hasAbort==mayAbort ); | |
| 64539 | + return ( v->db->mallocFailed || hasAbort==mayAbort || hasFkCounter ); | |
| 64384 | 64540 | } |
| 64385 | 64541 | #endif /* SQLITE_DEBUG - the sqlite3AssertMayAbort() function */ |
| 64386 | 64542 | |
| 64387 | 64543 | /* |
| 64388 | 64544 | ** Loop through the program looking for P2 values that are negative |
| @@ -65699,11 +65855,11 @@ | ||
| 65699 | 65855 | for(n=0; n<nVar; n++){ |
| 65700 | 65856 | p->aVar[n].flags = MEM_Null; |
| 65701 | 65857 | p->aVar[n].db = db; |
| 65702 | 65858 | } |
| 65703 | 65859 | } |
| 65704 | - if( p->azVar ){ | |
| 65860 | + if( p->azVar && pParse->nzVar>0 ){ | |
| 65705 | 65861 | p->nzVar = pParse->nzVar; |
| 65706 | 65862 | memcpy(p->azVar, pParse->azVar, p->nzVar*sizeof(p->azVar[0])); |
| 65707 | 65863 | memset(pParse->azVar, 0, pParse->nzVar*sizeof(pParse->azVar[0])); |
| 65708 | 65864 | } |
| 65709 | 65865 | if( p->aMem ){ |
| @@ -68502,11 +68658,14 @@ | ||
| 68502 | 68658 | #ifndef SQLITE_OMIT_WAL |
| 68503 | 68659 | int i; |
| 68504 | 68660 | for(i=0; i<db->nDb; i++){ |
| 68505 | 68661 | Btree *pBt = db->aDb[i].pBt; |
| 68506 | 68662 | if( pBt ){ |
| 68507 | - int nEntry = sqlite3PagerWalCallback(sqlite3BtreePager(pBt)); | |
| 68663 | + int nEntry; | |
| 68664 | + sqlite3BtreeEnter(pBt); | |
| 68665 | + nEntry = sqlite3PagerWalCallback(sqlite3BtreePager(pBt)); | |
| 68666 | + sqlite3BtreeLeave(pBt); | |
| 68508 | 68667 | if( db->xWalCallback && nEntry>0 && rc==SQLITE_OK ){ |
| 68509 | 68668 | rc = db->xWalCallback(db->pWalArg, db, db->aDb[i].zName, nEntry); |
| 68510 | 68669 | } |
| 68511 | 68670 | } |
| 68512 | 68671 | } |
| @@ -68682,11 +68841,10 @@ | ||
| 68682 | 68841 | ** program counter to 0 to ensure that when the statement is |
| 68683 | 68842 | ** finalized or reset the parser error message is available via |
| 68684 | 68843 | ** sqlite3_errmsg() and sqlite3_errcode(). |
| 68685 | 68844 | */ |
| 68686 | 68845 | const char *zErr = (const char *)sqlite3_value_text(db->pErr); |
| 68687 | - assert( zErr!=0 || db->mallocFailed ); | |
| 68688 | 68846 | sqlite3DbFree(db, v->zErrMsg); |
| 68689 | 68847 | if( !db->mallocFailed ){ |
| 68690 | 68848 | v->zErrMsg = sqlite3DbStrDup(db, zErr); |
| 68691 | 68849 | v->rc = rc2; |
| 68692 | 68850 | } else { |
| @@ -75629,12 +75787,12 @@ | ||
| 75629 | 75787 | |
| 75630 | 75788 | #ifndef SQLITE_OMIT_WAL |
| 75631 | 75789 | /* Opcode: Checkpoint P1 P2 P3 * * |
| 75632 | 75790 | ** |
| 75633 | 75791 | ** Checkpoint database P1. This is a no-op if P1 is not currently in |
| 75634 | -** WAL mode. Parameter P2 is one of SQLITE_CHECKPOINT_PASSIVE, FULL | |
| 75635 | -** or RESTART. Write 1 or 0 into mem[P3] if the checkpoint returns | |
| 75792 | +** WAL mode. Parameter P2 is one of SQLITE_CHECKPOINT_PASSIVE, FULL, | |
| 75793 | +** RESTART, or TRUNCATE. Write 1 or 0 into mem[P3] if the checkpoint returns | |
| 75636 | 75794 | ** SQLITE_BUSY or not, respectively. Write the number of pages in the |
| 75637 | 75795 | ** WAL after the checkpoint into mem[P3+1] and the number of pages |
| 75638 | 75796 | ** in the WAL that have been checkpointed after the checkpoint |
| 75639 | 75797 | ** completes into mem[P3+2]. However on an error, mem[P3+1] and |
| 75640 | 75798 | ** mem[P3+2] are initialized to -1. |
| @@ -75648,10 +75806,11 @@ | ||
| 75648 | 75806 | aRes[0] = 0; |
| 75649 | 75807 | aRes[1] = aRes[2] = -1; |
| 75650 | 75808 | assert( pOp->p2==SQLITE_CHECKPOINT_PASSIVE |
| 75651 | 75809 | || pOp->p2==SQLITE_CHECKPOINT_FULL |
| 75652 | 75810 | || pOp->p2==SQLITE_CHECKPOINT_RESTART |
| 75811 | + || pOp->p2==SQLITE_CHECKPOINT_TRUNCATE | |
| 75653 | 75812 | ); |
| 75654 | 75813 | rc = sqlite3Checkpoint(db, pOp->p1, pOp->p2, &aRes[1], &aRes[2]); |
| 75655 | 75814 | if( rc==SQLITE_BUSY ){ |
| 75656 | 75815 | rc = SQLITE_OK; |
| 75657 | 75816 | aRes[0] = 1; |
| @@ -77043,11 +77202,11 @@ | ||
| 77043 | 77202 | /* |
| 77044 | 77203 | ** Hard-coded maximum amount of data to accumulate in memory before flushing |
| 77045 | 77204 | ** to a level 0 PMA. The purpose of this limit is to prevent various integer |
| 77046 | 77205 | ** overflows. 512MiB. |
| 77047 | 77206 | */ |
| 77048 | -#define SQLITE_MAX_MXPMASIZE (1<<29) | |
| 77207 | +#define SQLITE_MAX_PMASZ (1<<29) | |
| 77049 | 77208 | |
| 77050 | 77209 | /* |
| 77051 | 77210 | ** Private objects used by the sorter |
| 77052 | 77211 | */ |
| 77053 | 77212 | typedef struct MergeEngine MergeEngine; /* Merge PMAs together */ |
| @@ -77339,13 +77498,10 @@ | ||
| 77339 | 77498 | ** |
| 77340 | 77499 | ** void *SRVAL(SorterRecord *p) { return (void*)&p[1]; } |
| 77341 | 77500 | */ |
| 77342 | 77501 | #define SRVAL(p) ((void*)((SorterRecord*)(p) + 1)) |
| 77343 | 77502 | |
| 77344 | -/* The minimum PMA size is set to this value multiplied by the database | |
| 77345 | -** page size in bytes. */ | |
| 77346 | -#define SORTER_MIN_WORKING 10 | |
| 77347 | 77503 | |
| 77348 | 77504 | /* Maximum number of PMAs that a single MergeEngine can merge */ |
| 77349 | 77505 | #define SORTER_MAX_MERGE_COUNT 16 |
| 77350 | 77506 | |
| 77351 | 77507 | static int vdbeIncrSwap(IncrMerger*); |
| @@ -77740,14 +77896,15 @@ | ||
| 77740 | 77896 | SortSubtask *pTask = &pSorter->aTask[i]; |
| 77741 | 77897 | pTask->pSorter = pSorter; |
| 77742 | 77898 | } |
| 77743 | 77899 | |
| 77744 | 77900 | if( !sqlite3TempInMemory(db) ){ |
| 77745 | - pSorter->mnPmaSize = SORTER_MIN_WORKING * pgsz; | |
| 77901 | + u32 szPma = sqlite3GlobalConfig.szPma; | |
| 77902 | + pSorter->mnPmaSize = szPma * pgsz; | |
| 77746 | 77903 | mxCache = db->aDb[0].pSchema->cache_size; |
| 77747 | - if( mxCache<SORTER_MIN_WORKING ) mxCache = SORTER_MIN_WORKING; | |
| 77748 | - pSorter->mxPmaSize = MIN((i64)mxCache*pgsz, SQLITE_MAX_MXPMASIZE); | |
| 77904 | + if( mxCache<(int)szPma ) mxCache = (int)szPma; | |
| 77905 | + pSorter->mxPmaSize = MIN((i64)mxCache*pgsz, SQLITE_MAX_PMASZ); | |
| 77749 | 77906 | |
| 77750 | 77907 | /* EVIDENCE-OF: R-26747-61719 When the application provides any amount of |
| 77751 | 77908 | ** scratch memory using SQLITE_CONFIG_SCRATCH, SQLite avoids unnecessary |
| 77752 | 77909 | ** large heap allocations. |
| 77753 | 77910 | */ |
| @@ -78021,16 +78178,16 @@ | ||
| 78021 | 78178 | ** Whether or not the file does end up memory mapped of course depends on |
| 78022 | 78179 | ** the specific VFS implementation. |
| 78023 | 78180 | */ |
| 78024 | 78181 | static void vdbeSorterExtendFile(sqlite3 *db, sqlite3_file *pFd, i64 nByte){ |
| 78025 | 78182 | if( nByte<=(i64)(db->nMaxSorterMmap) && pFd->pMethods->iVersion>=3 ){ |
| 78026 | - int rc = sqlite3OsTruncate(pFd, nByte); | |
| 78027 | - if( rc==SQLITE_OK ){ | |
| 78028 | - void *p = 0; | |
| 78029 | - sqlite3OsFetch(pFd, 0, (int)nByte, &p); | |
| 78030 | - sqlite3OsUnfetch(pFd, 0, p); | |
| 78031 | - } | |
| 78183 | + void *p = 0; | |
| 78184 | + int chunksize = 4*1024; | |
| 78185 | + sqlite3OsFileControlHint(pFd, SQLITE_FCNTL_CHUNK_SIZE, &chunksize); | |
| 78186 | + sqlite3OsFileControlHint(pFd, SQLITE_FCNTL_SIZE_HINT, &nByte); | |
| 78187 | + sqlite3OsFetch(pFd, 0, (int)nByte, &p); | |
| 78188 | + sqlite3OsUnfetch(pFd, 0, p); | |
| 78032 | 78189 | } |
| 78033 | 78190 | } |
| 78034 | 78191 | #else |
| 78035 | 78192 | # define vdbeSorterExtendFile(x,y,z) |
| 78036 | 78193 | #endif |
| @@ -80411,10 +80568,14 @@ | ||
| 80411 | 80568 | } |
| 80412 | 80569 | } |
| 80413 | 80570 | if( pMatch ){ |
| 80414 | 80571 | pExpr->iTable = pMatch->iCursor; |
| 80415 | 80572 | pExpr->pTab = pMatch->pTab; |
| 80573 | + assert( (pMatch->jointype & JT_RIGHT)==0 ); /* RIGHT JOIN not (yet) supported */ | |
| 80574 | + if( (pMatch->jointype & JT_LEFT)!=0 ){ | |
| 80575 | + ExprSetProperty(pExpr, EP_CanBeNull); | |
| 80576 | + } | |
| 80416 | 80577 | pSchema = pExpr->pTab->pSchema; |
| 80417 | 80578 | } |
| 80418 | 80579 | } /* if( pSrcList ) */ |
| 80419 | 80580 | |
| 80420 | 80581 | #ifndef SQLITE_OMIT_TRIGGER |
| @@ -82968,11 +83129,12 @@ | ||
| 82968 | 83129 | case TK_FLOAT: |
| 82969 | 83130 | case TK_BLOB: |
| 82970 | 83131 | return 0; |
| 82971 | 83132 | case TK_COLUMN: |
| 82972 | 83133 | assert( p->pTab!=0 ); |
| 82973 | - return p->iColumn>=0 && p->pTab->aCol[p->iColumn].notNull==0; | |
| 83134 | + return ExprHasProperty(p, EP_CanBeNull) || | |
| 83135 | + (p->iColumn>=0 && p->pTab->aCol[p->iColumn].notNull==0); | |
| 82974 | 83136 | default: |
| 82975 | 83137 | return 1; |
| 82976 | 83138 | } |
| 82977 | 83139 | } |
| 82978 | 83140 | |
| @@ -87203,11 +87365,11 @@ | ||
| 87203 | 87365 | |
| 87204 | 87366 | p->iGet = -1; |
| 87205 | 87367 | p->mxSample = mxSample; |
| 87206 | 87368 | p->nPSample = (tRowcnt)(sqlite3_value_int64(argv[2])/(mxSample/3+1) + 1); |
| 87207 | 87369 | p->current.anLt = &p->current.anEq[nColUp]; |
| 87208 | - p->iPrn = nCol*0x689e962d ^ sqlite3_value_int(argv[2])*0xd0944565; | |
| 87370 | + p->iPrn = 0x689e962d*(u32)nCol ^ 0xd0944565*(u32)sqlite3_value_int(argv[2]); | |
| 87209 | 87371 | |
| 87210 | 87372 | /* Set up the Stat4Accum.a[] and aBest[] arrays */ |
| 87211 | 87373 | p->a = (struct Stat4Sample*)&p->current.anLt[nColUp]; |
| 87212 | 87374 | p->aBest = &p->a[mxSample]; |
| 87213 | 87375 | pSpace = (u8*)(&p->a[mxSample+nCol]); |
| @@ -88351,11 +88513,11 @@ | ||
| 88351 | 88513 | tRowcnt avgEq = 0; |
| 88352 | 88514 | tRowcnt nRow; /* Number of rows in index */ |
| 88353 | 88515 | i64 nSum100 = 0; /* Number of terms contributing to sumEq */ |
| 88354 | 88516 | i64 nDist100; /* Number of distinct values in index */ |
| 88355 | 88517 | |
| 88356 | - if( pIdx->aiRowEst==0 || pIdx->aiRowEst[iCol+1]==0 ){ | |
| 88518 | + if( !pIdx->aiRowEst || iCol>=pIdx->nKeyCol || pIdx->aiRowEst[iCol+1]==0 ){ | |
| 88357 | 88519 | nRow = pFinal->anLt[iCol]; |
| 88358 | 88520 | nDist100 = (i64)100 * pFinal->anDLt[iCol]; |
| 88359 | 88521 | nSample--; |
| 88360 | 88522 | }else{ |
| 88361 | 88523 | nRow = pIdx->aiRowEst[0]; |
| @@ -88796,17 +88958,19 @@ | ||
| 88796 | 88958 | }else if( aNew->pSchema->file_format && aNew->pSchema->enc!=ENC(db) ){ |
| 88797 | 88959 | zErrDyn = sqlite3MPrintf(db, |
| 88798 | 88960 | "attached databases must use the same text encoding as main database"); |
| 88799 | 88961 | rc = SQLITE_ERROR; |
| 88800 | 88962 | } |
| 88963 | + sqlite3BtreeEnter(aNew->pBt); | |
| 88801 | 88964 | pPager = sqlite3BtreePager(aNew->pBt); |
| 88802 | 88965 | sqlite3PagerLockingMode(pPager, db->dfltLockMode); |
| 88803 | 88966 | sqlite3BtreeSecureDelete(aNew->pBt, |
| 88804 | 88967 | sqlite3BtreeSecureDelete(db->aDb[0].pBt,-1) ); |
| 88805 | 88968 | #ifndef SQLITE_OMIT_PAGER_PRAGMAS |
| 88806 | 88969 | sqlite3BtreeSetPagerFlags(aNew->pBt, 3 | (db->flags & PAGER_FLAGS_MASK)); |
| 88807 | 88970 | #endif |
| 88971 | + sqlite3BtreeLeave(aNew->pBt); | |
| 88808 | 88972 | } |
| 88809 | 88973 | aNew->safety_level = 3; |
| 88810 | 88974 | aNew->zName = sqlite3DbStrDup(db, zName); |
| 88811 | 88975 | if( rc==SQLITE_OK && aNew->zName==0 ){ |
| 88812 | 88976 | rc = SQLITE_NOMEM; |
| @@ -89928,11 +90092,10 @@ | ||
| 89928 | 90092 | */ |
| 89929 | 90093 | static void freeIndex(sqlite3 *db, Index *p){ |
| 89930 | 90094 | #ifndef SQLITE_OMIT_ANALYZE |
| 89931 | 90095 | sqlite3DeleteIndexSamples(db, p); |
| 89932 | 90096 | #endif |
| 89933 | - if( db==0 || db->pnBytesFreed==0 ) sqlite3KeyInfoUnref(p->pKeyInfo); | |
| 89934 | 90097 | sqlite3ExprDelete(db, p->pPartIdxWhere); |
| 89935 | 90098 | sqlite3DbFree(db, p->zColAff); |
| 89936 | 90099 | if( p->isResized ) sqlite3DbFree(db, p->azColl); |
| 89937 | 90100 | #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 |
| 89938 | 90101 | sqlite3_free(p->aiRowEst); |
| @@ -91207,10 +91370,23 @@ | ||
| 91207 | 91370 | if( pPk==0 ) return; |
| 91208 | 91371 | pPk->idxType = SQLITE_IDXTYPE_PRIMARYKEY; |
| 91209 | 91372 | pTab->iPKey = -1; |
| 91210 | 91373 | }else{ |
| 91211 | 91374 | pPk = sqlite3PrimaryKeyIndex(pTab); |
| 91375 | + /* | |
| 91376 | + ** Remove all redundant columns from the PRIMARY KEY. For example, change | |
| 91377 | + ** "PRIMARY KEY(a,b,a,b,c,b,c,d)" into just "PRIMARY KEY(a,b,c,d)". Later | |
| 91378 | + ** code assumes the PRIMARY KEY contains no repeated columns. | |
| 91379 | + */ | |
| 91380 | + for(i=j=1; i<pPk->nKeyCol; i++){ | |
| 91381 | + if( hasColumn(pPk->aiColumn, j, pPk->aiColumn[i]) ){ | |
| 91382 | + pPk->nColumn--; | |
| 91383 | + }else{ | |
| 91384 | + pPk->aiColumn[j++] = pPk->aiColumn[i]; | |
| 91385 | + } | |
| 91386 | + } | |
| 91387 | + pPk->nKeyCol = j; | |
| 91212 | 91388 | } |
| 91213 | 91389 | pPk->isCovering = 1; |
| 91214 | 91390 | assert( pPk!=0 ); |
| 91215 | 91391 | nPk = pPk->nKeyCol; |
| 91216 | 91392 | |
| @@ -93683,44 +93859,35 @@ | ||
| 93683 | 93859 | ** |
| 93684 | 93860 | ** The caller should invoke sqlite3KeyInfoUnref() on the returned object |
| 93685 | 93861 | ** when it has finished using it. |
| 93686 | 93862 | */ |
| 93687 | 93863 | SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoOfIndex(Parse *pParse, Index *pIdx){ |
| 93864 | + int i; | |
| 93865 | + int nCol = pIdx->nColumn; | |
| 93866 | + int nKey = pIdx->nKeyCol; | |
| 93867 | + KeyInfo *pKey; | |
| 93688 | 93868 | if( pParse->nErr ) return 0; |
| 93689 | -#ifndef SQLITE_OMIT_SHARED_CACHE | |
| 93690 | - if( pIdx->pKeyInfo && pIdx->pKeyInfo->db!=pParse->db ){ | |
| 93691 | - sqlite3KeyInfoUnref(pIdx->pKeyInfo); | |
| 93692 | - pIdx->pKeyInfo = 0; | |
| 93693 | - } | |
| 93694 | -#endif | |
| 93695 | - if( pIdx->pKeyInfo==0 ){ | |
| 93696 | - int i; | |
| 93697 | - int nCol = pIdx->nColumn; | |
| 93698 | - int nKey = pIdx->nKeyCol; | |
| 93699 | - KeyInfo *pKey; | |
| 93700 | - if( pIdx->uniqNotNull ){ | |
| 93701 | - pKey = sqlite3KeyInfoAlloc(pParse->db, nKey, nCol-nKey); | |
| 93702 | - }else{ | |
| 93703 | - pKey = sqlite3KeyInfoAlloc(pParse->db, nCol, 0); | |
| 93704 | - } | |
| 93705 | - if( pKey ){ | |
| 93706 | - assert( sqlite3KeyInfoIsWriteable(pKey) ); | |
| 93707 | - for(i=0; i<nCol; i++){ | |
| 93708 | - char *zColl = pIdx->azColl[i]; | |
| 93709 | - assert( zColl!=0 ); | |
| 93710 | - pKey->aColl[i] = strcmp(zColl,"BINARY")==0 ? 0 : | |
| 93711 | - sqlite3LocateCollSeq(pParse, zColl); | |
| 93712 | - pKey->aSortOrder[i] = pIdx->aSortOrder[i]; | |
| 93713 | - } | |
| 93714 | - if( pParse->nErr ){ | |
| 93715 | - sqlite3KeyInfoUnref(pKey); | |
| 93716 | - }else{ | |
| 93717 | - pIdx->pKeyInfo = pKey; | |
| 93718 | - } | |
| 93719 | - } | |
| 93720 | - } | |
| 93721 | - return sqlite3KeyInfoRef(pIdx->pKeyInfo); | |
| 93869 | + if( pIdx->uniqNotNull ){ | |
| 93870 | + pKey = sqlite3KeyInfoAlloc(pParse->db, nKey, nCol-nKey); | |
| 93871 | + }else{ | |
| 93872 | + pKey = sqlite3KeyInfoAlloc(pParse->db, nCol, 0); | |
| 93873 | + } | |
| 93874 | + if( pKey ){ | |
| 93875 | + assert( sqlite3KeyInfoIsWriteable(pKey) ); | |
| 93876 | + for(i=0; i<nCol; i++){ | |
| 93877 | + char *zColl = pIdx->azColl[i]; | |
| 93878 | + assert( zColl!=0 ); | |
| 93879 | + pKey->aColl[i] = strcmp(zColl,"BINARY")==0 ? 0 : | |
| 93880 | + sqlite3LocateCollSeq(pParse, zColl); | |
| 93881 | + pKey->aSortOrder[i] = pIdx->aSortOrder[i]; | |
| 93882 | + } | |
| 93883 | + if( pParse->nErr ){ | |
| 93884 | + sqlite3KeyInfoUnref(pKey); | |
| 93885 | + pKey = 0; | |
| 93886 | + } | |
| 93887 | + } | |
| 93888 | + return pKey; | |
| 93722 | 93889 | } |
| 93723 | 93890 | |
| 93724 | 93891 | #ifndef SQLITE_OMIT_CTE |
| 93725 | 93892 | /* |
| 93726 | 93893 | ** This routine is invoked once per CTE by the parser while parsing a |
| @@ -97337,11 +97504,11 @@ | ||
| 97337 | 97504 | assert( nIncr==1 ); |
| 97338 | 97505 | sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY, |
| 97339 | 97506 | OE_Abort, 0, P4_STATIC, P5_ConstraintFK); |
| 97340 | 97507 | }else{ |
| 97341 | 97508 | if( nIncr>0 && pFKey->isDeferred==0 ){ |
| 97342 | - sqlite3ParseToplevel(pParse)->mayAbort = 1; | |
| 97509 | + sqlite3MayAbort(pParse); | |
| 97343 | 97510 | } |
| 97344 | 97511 | sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr); |
| 97345 | 97512 | } |
| 97346 | 97513 | |
| 97347 | 97514 | sqlite3VdbeResolveLabel(v, iOk); |
| @@ -97408,10 +97575,14 @@ | ||
| 97408 | 97575 | ** This function is called to generate code executed when a row is deleted |
| 97409 | 97576 | ** from the parent table of foreign key constraint pFKey and, if pFKey is |
| 97410 | 97577 | ** deferred, when a row is inserted into the same table. When generating |
| 97411 | 97578 | ** code for an SQL UPDATE operation, this function may be called twice - |
| 97412 | 97579 | ** once to "delete" the old row and once to "insert" the new row. |
| 97580 | +** | |
| 97581 | +** Parameter nIncr is passed -1 when inserting a row (as this may decrease | |
| 97582 | +** the number of FK violations in the db) or +1 when deleting one (as this | |
| 97583 | +** may increase the number of FK constraint problems). | |
| 97413 | 97584 | ** |
| 97414 | 97585 | ** The code generated by this function scans through the rows in the child |
| 97415 | 97586 | ** table that correspond to the parent table row being deleted or inserted. |
| 97416 | 97587 | ** For each child row found, one of the following actions is taken: |
| 97417 | 97588 | ** |
| @@ -97525,17 +97696,13 @@ | ||
| 97525 | 97696 | sNameContext.pSrcList = pSrc; |
| 97526 | 97697 | sNameContext.pParse = pParse; |
| 97527 | 97698 | sqlite3ResolveExprNames(&sNameContext, pWhere); |
| 97528 | 97699 | |
| 97529 | 97700 | /* Create VDBE to loop through the entries in pSrc that match the WHERE |
| 97530 | - ** clause. If the constraint is not deferred, throw an exception for | |
| 97531 | - ** each row found. Otherwise, for deferred constraints, increment the | |
| 97532 | - ** deferred constraint counter by nIncr for each row selected. */ | |
| 97701 | + ** clause. For each row found, increment either the deferred or immediate | |
| 97702 | + ** foreign key constraint counter. */ | |
| 97533 | 97703 | pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0); |
| 97534 | - if( nIncr>0 && pFKey->isDeferred==0 ){ | |
| 97535 | - sqlite3ParseToplevel(pParse)->mayAbort = 1; | |
| 97536 | - } | |
| 97537 | 97704 | sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr); |
| 97538 | 97705 | if( pWInfo ){ |
| 97539 | 97706 | sqlite3WhereEnd(pWInfo); |
| 97540 | 97707 | } |
| 97541 | 97708 | |
| @@ -97709,10 +97876,28 @@ | ||
| 97709 | 97876 | } |
| 97710 | 97877 | } |
| 97711 | 97878 | } |
| 97712 | 97879 | return 0; |
| 97713 | 97880 | } |
| 97881 | + | |
| 97882 | +/* | |
| 97883 | +** Return true if the parser passed as the first argument is being | |
| 97884 | +** used to code a trigger that is really a "SET NULL" action belonging | |
| 97885 | +** to trigger pFKey. | |
| 97886 | +*/ | |
| 97887 | +static int isSetNullAction(Parse *pParse, FKey *pFKey){ | |
| 97888 | + Parse *pTop = sqlite3ParseToplevel(pParse); | |
| 97889 | + if( pTop->pTriggerPrg ){ | |
| 97890 | + Trigger *p = pTop->pTriggerPrg->pTrigger; | |
| 97891 | + if( (p==pFKey->apTrigger[0] && pFKey->aAction[0]==OE_SetNull) | |
| 97892 | + || (p==pFKey->apTrigger[1] && pFKey->aAction[1]==OE_SetNull) | |
| 97893 | + ){ | |
| 97894 | + return 1; | |
| 97895 | + } | |
| 97896 | + } | |
| 97897 | + return 0; | |
| 97898 | +} | |
| 97714 | 97899 | |
| 97715 | 97900 | /* |
| 97716 | 97901 | ** This function is called when inserting, deleting or updating a row of |
| 97717 | 97902 | ** table pTab to generate VDBE code to perform foreign key constraint |
| 97718 | 97903 | ** processing for the operation. |
| @@ -97762,11 +97947,11 @@ | ||
| 97762 | 97947 | Index *pIdx = 0; /* Index on key columns in pTo */ |
| 97763 | 97948 | int *aiFree = 0; |
| 97764 | 97949 | int *aiCol; |
| 97765 | 97950 | int iCol; |
| 97766 | 97951 | int i; |
| 97767 | - int isIgnore = 0; | |
| 97952 | + int bIgnore = 0; | |
| 97768 | 97953 | |
| 97769 | 97954 | if( aChange |
| 97770 | 97955 | && sqlite3_stricmp(pTab->zName, pFKey->zTo)!=0 |
| 97771 | 97956 | && fkChildIsModified(pTab, pFKey, aChange, bChngRowid)==0 |
| 97772 | 97957 | ){ |
| @@ -97821,11 +98006,11 @@ | ||
| 97821 | 98006 | ** values read from the parent table are NULL. */ |
| 97822 | 98007 | if( db->xAuth ){ |
| 97823 | 98008 | int rcauth; |
| 97824 | 98009 | char *zCol = pTo->aCol[pIdx ? pIdx->aiColumn[i] : pTo->iPKey].zName; |
| 97825 | 98010 | rcauth = sqlite3AuthReadCol(pParse, pTo->zName, zCol, iDb); |
| 97826 | - isIgnore = (rcauth==SQLITE_IGNORE); | |
| 98011 | + bIgnore = (rcauth==SQLITE_IGNORE); | |
| 97827 | 98012 | } |
| 97828 | 98013 | #endif |
| 97829 | 98014 | } |
| 97830 | 98015 | |
| 97831 | 98016 | /* Take a shared-cache advisory read-lock on the parent table. Allocate |
| @@ -97836,16 +98021,22 @@ | ||
| 97836 | 98021 | |
| 97837 | 98022 | if( regOld!=0 ){ |
| 97838 | 98023 | /* A row is being removed from the child table. Search for the parent. |
| 97839 | 98024 | ** If the parent does not exist, removing the child row resolves an |
| 97840 | 98025 | ** outstanding foreign key constraint violation. */ |
| 97841 | - fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regOld, -1,isIgnore); | |
| 98026 | + fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regOld, -1, bIgnore); | |
| 97842 | 98027 | } |
| 97843 | - if( regNew!=0 ){ | |
| 98028 | + if( regNew!=0 && !isSetNullAction(pParse, pFKey) ){ | |
| 97844 | 98029 | /* A row is being added to the child table. If a parent row cannot |
| 97845 | - ** be found, adding the child row has violated the FK constraint. */ | |
| 97846 | - fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regNew, +1,isIgnore); | |
| 98030 | + ** be found, adding the child row has violated the FK constraint. | |
| 98031 | + ** | |
| 98032 | + ** If this operation is being performed as part of a trigger program | |
| 98033 | + ** that is actually a "SET NULL" action belonging to this very | |
| 98034 | + ** foreign key, then omit this scan altogether. As all child key | |
| 98035 | + ** values are guaranteed to be NULL, it is not possible for adding | |
| 98036 | + ** this row to cause an FK violation. */ | |
| 98037 | + fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regNew, +1, bIgnore); | |
| 97847 | 98038 | } |
| 97848 | 98039 | |
| 97849 | 98040 | sqlite3DbFree(db, aiFree); |
| 97850 | 98041 | } |
| 97851 | 98042 | |
| @@ -97862,12 +98053,12 @@ | ||
| 97862 | 98053 | |
| 97863 | 98054 | if( !pFKey->isDeferred && !(db->flags & SQLITE_DeferFKs) |
| 97864 | 98055 | && !pParse->pToplevel && !pParse->isMultiWrite |
| 97865 | 98056 | ){ |
| 97866 | 98057 | assert( regOld==0 && regNew!=0 ); |
| 97867 | - /* Inserting a single row into a parent table cannot cause an immediate | |
| 97868 | - ** foreign key violation. So do nothing in this case. */ | |
| 98058 | + /* Inserting a single row into a parent table cannot cause (or fix) | |
| 98059 | + ** an immediate foreign key violation. So do nothing in this case. */ | |
| 97869 | 98060 | continue; |
| 97870 | 98061 | } |
| 97871 | 98062 | |
| 97872 | 98063 | if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){ |
| 97873 | 98064 | if( !isIgnoreErrors || db->mallocFailed ) return; |
| @@ -97887,17 +98078,32 @@ | ||
| 97887 | 98078 | |
| 97888 | 98079 | if( regNew!=0 ){ |
| 97889 | 98080 | fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regNew, -1); |
| 97890 | 98081 | } |
| 97891 | 98082 | if( regOld!=0 ){ |
| 97892 | - /* If there is a RESTRICT action configured for the current operation | |
| 97893 | - ** on the parent table of this FK, then throw an exception | |
| 97894 | - ** immediately if the FK constraint is violated, even if this is a | |
| 97895 | - ** deferred trigger. That's what RESTRICT means. To defer checking | |
| 97896 | - ** the constraint, the FK should specify NO ACTION (represented | |
| 97897 | - ** using OE_None). NO ACTION is the default. */ | |
| 98083 | + int eAction = pFKey->aAction[aChange!=0]; | |
| 97898 | 98084 | fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regOld, 1); |
| 98085 | + /* If this is a deferred FK constraint, or a CASCADE or SET NULL | |
| 98086 | + ** action applies, then any foreign key violations caused by | |
| 98087 | + ** removing the parent key will be rectified by the action trigger. | |
| 98088 | + ** So do not set the "may-abort" flag in this case. | |
| 98089 | + ** | |
| 98090 | + ** Note 1: If the FK is declared "ON UPDATE CASCADE", then the | |
| 98091 | + ** may-abort flag will eventually be set on this statement anyway | |
| 98092 | + ** (when this function is called as part of processing the UPDATE | |
| 98093 | + ** within the action trigger). | |
| 98094 | + ** | |
| 98095 | + ** Note 2: At first glance it may seem like SQLite could simply omit | |
| 98096 | + ** all OP_FkCounter related scans when either CASCADE or SET NULL | |
| 98097 | + ** applies. The trouble starts if the CASCADE or SET NULL action | |
| 98098 | + ** trigger causes other triggers or action rules attached to the | |
| 98099 | + ** child table to fire. In these cases the fk constraint counters | |
| 98100 | + ** might be set incorrectly if any OP_FkCounter related scans are | |
| 98101 | + ** omitted. */ | |
| 98102 | + if( !pFKey->isDeferred && eAction!=OE_Cascade && eAction!=OE_SetNull ){ | |
| 98103 | + sqlite3MayAbort(pParse); | |
| 98104 | + } | |
| 97899 | 98105 | } |
| 97900 | 98106 | pItem->zName = 0; |
| 97901 | 98107 | sqlite3SrcListDelete(db, pSrc); |
| 97902 | 98108 | } |
| 97903 | 98109 | sqlite3DbFree(db, aiCol); |
| @@ -100987,11 +101193,10 @@ | ||
| 100987 | 101193 | # define sqlite3_column_database_name16 0 |
| 100988 | 101194 | # define sqlite3_column_table_name 0 |
| 100989 | 101195 | # define sqlite3_column_table_name16 0 |
| 100990 | 101196 | # define sqlite3_column_origin_name 0 |
| 100991 | 101197 | # define sqlite3_column_origin_name16 0 |
| 100992 | -# define sqlite3_table_column_metadata 0 | |
| 100993 | 101198 | #endif |
| 100994 | 101199 | |
| 100995 | 101200 | #ifdef SQLITE_OMIT_AUTHORIZATION |
| 100996 | 101201 | # define sqlite3_set_authorizer 0 |
| 100997 | 101202 | #endif |
| @@ -101797,10 +102002,11 @@ | ||
| 101797 | 102002 | #define PragTyp_KEY 38 |
| 101798 | 102003 | #define PragTyp_REKEY 39 |
| 101799 | 102004 | #define PragTyp_LOCK_STATUS 40 |
| 101800 | 102005 | #define PragTyp_PARSER_TRACE 41 |
| 101801 | 102006 | #define PragFlag_NeedSchema 0x01 |
| 102007 | +#define PragFlag_ReadOnly 0x02 | |
| 101802 | 102008 | static const struct sPragmaNames { |
| 101803 | 102009 | const char *const zName; /* Name of pragma */ |
| 101804 | 102010 | u8 ePragTyp; /* PragTyp_XXX value */ |
| 101805 | 102011 | u8 mPragFlag; /* Zero or more PragFlag_XXX values */ |
| 101806 | 102012 | u32 iArg; /* Extra argument */ |
| @@ -101813,11 +102019,11 @@ | ||
| 101813 | 102019 | #endif |
| 101814 | 102020 | #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) |
| 101815 | 102021 | { /* zName: */ "application_id", |
| 101816 | 102022 | /* ePragTyp: */ PragTyp_HEADER_VALUE, |
| 101817 | 102023 | /* ePragFlag: */ 0, |
| 101818 | - /* iArg: */ 0 }, | |
| 102024 | + /* iArg: */ BTREE_APPLICATION_ID }, | |
| 101819 | 102025 | #endif |
| 101820 | 102026 | #if !defined(SQLITE_OMIT_AUTOVACUUM) |
| 101821 | 102027 | { /* zName: */ "auto_vacuum", |
| 101822 | 102028 | /* ePragTyp: */ PragTyp_AUTO_VACUUM, |
| 101823 | 102029 | /* ePragFlag: */ PragFlag_NeedSchema, |
| @@ -101879,10 +102085,16 @@ | ||
| 101879 | 102085 | { /* zName: */ "data_store_directory", |
| 101880 | 102086 | /* ePragTyp: */ PragTyp_DATA_STORE_DIRECTORY, |
| 101881 | 102087 | /* ePragFlag: */ 0, |
| 101882 | 102088 | /* iArg: */ 0 }, |
| 101883 | 102089 | #endif |
| 102090 | +#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) | |
| 102091 | + { /* zName: */ "data_version", | |
| 102092 | + /* ePragTyp: */ PragTyp_HEADER_VALUE, | |
| 102093 | + /* ePragFlag: */ PragFlag_ReadOnly, | |
| 102094 | + /* iArg: */ BTREE_DATA_VERSION }, | |
| 102095 | +#endif | |
| 101884 | 102096 | #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) |
| 101885 | 102097 | { /* zName: */ "database_list", |
| 101886 | 102098 | /* ePragTyp: */ PragTyp_DATABASE_LIST, |
| 101887 | 102099 | /* ePragFlag: */ PragFlag_NeedSchema, |
| 101888 | 102100 | /* iArg: */ 0 }, |
| @@ -101934,12 +102146,12 @@ | ||
| 101934 | 102146 | #endif |
| 101935 | 102147 | #endif |
| 101936 | 102148 | #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) |
| 101937 | 102149 | { /* zName: */ "freelist_count", |
| 101938 | 102150 | /* ePragTyp: */ PragTyp_HEADER_VALUE, |
| 101939 | - /* ePragFlag: */ 0, | |
| 101940 | - /* iArg: */ 0 }, | |
| 102151 | + /* ePragFlag: */ PragFlag_ReadOnly, | |
| 102152 | + /* iArg: */ BTREE_FREE_PAGE_COUNT }, | |
| 101941 | 102153 | #endif |
| 101942 | 102154 | #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
| 101943 | 102155 | { /* zName: */ "full_column_names", |
| 101944 | 102156 | /* ePragTyp: */ PragTyp_FLAG, |
| 101945 | 102157 | /* ePragFlag: */ 0, |
| @@ -102087,11 +102299,11 @@ | ||
| 102087 | 102299 | #endif |
| 102088 | 102300 | #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) |
| 102089 | 102301 | { /* zName: */ "schema_version", |
| 102090 | 102302 | /* ePragTyp: */ PragTyp_HEADER_VALUE, |
| 102091 | 102303 | /* ePragFlag: */ 0, |
| 102092 | - /* iArg: */ 0 }, | |
| 102304 | + /* iArg: */ BTREE_SCHEMA_VERSION }, | |
| 102093 | 102305 | #endif |
| 102094 | 102306 | #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) |
| 102095 | 102307 | { /* zName: */ "secure_delete", |
| 102096 | 102308 | /* ePragTyp: */ PragTyp_SECURE_DELETE, |
| 102097 | 102309 | /* ePragFlag: */ 0, |
| @@ -102153,11 +102365,11 @@ | ||
| 102153 | 102365 | /* iArg: */ 0 }, |
| 102154 | 102366 | #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) |
| 102155 | 102367 | { /* zName: */ "user_version", |
| 102156 | 102368 | /* ePragTyp: */ PragTyp_HEADER_VALUE, |
| 102157 | 102369 | /* ePragFlag: */ 0, |
| 102158 | - /* iArg: */ 0 }, | |
| 102370 | + /* iArg: */ BTREE_USER_VERSION }, | |
| 102159 | 102371 | #endif |
| 102160 | 102372 | #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
| 102161 | 102373 | #if defined(SQLITE_DEBUG) |
| 102162 | 102374 | { /* zName: */ "vdbe_addoptrace", |
| 102163 | 102375 | /* ePragTyp: */ PragTyp_FLAG, |
| @@ -102196,11 +102408,11 @@ | ||
| 102196 | 102408 | /* ePragTyp: */ PragTyp_FLAG, |
| 102197 | 102409 | /* ePragFlag: */ 0, |
| 102198 | 102410 | /* iArg: */ SQLITE_WriteSchema|SQLITE_RecoveryMode }, |
| 102199 | 102411 | #endif |
| 102200 | 102412 | }; |
| 102201 | -/* Number of pragmas: 57 on by default, 70 total. */ | |
| 102413 | +/* Number of pragmas: 58 on by default, 71 total. */ | |
| 102202 | 102414 | /* End of the automatically generated pragma table. |
| 102203 | 102415 | ***************************************************************************/ |
| 102204 | 102416 | |
| 102205 | 102417 | /* |
| 102206 | 102418 | ** Interpret the given string as a safety level. Return 0 for OFF, |
| @@ -103806,11 +104018,12 @@ | ||
| 103806 | 104018 | !(DbHasProperty(db, 0, DB_SchemaLoaded)) || |
| 103807 | 104019 | DbHasProperty(db, 0, DB_Empty) |
| 103808 | 104020 | ){ |
| 103809 | 104021 | for(pEnc=&encnames[0]; pEnc->zName; pEnc++){ |
| 103810 | 104022 | if( 0==sqlite3StrICmp(zRight, pEnc->zName) ){ |
| 103811 | - ENC(pParse->db) = pEnc->enc ? pEnc->enc : SQLITE_UTF16NATIVE; | |
| 104023 | + SCHEMA_ENC(db) = ENC(db) = | |
| 104024 | + pEnc->enc ? pEnc->enc : SQLITE_UTF16NATIVE; | |
| 103812 | 104025 | break; |
| 103813 | 104026 | } |
| 103814 | 104027 | } |
| 103815 | 104028 | if( !pEnc->zName ){ |
| 103816 | 104029 | sqlite3ErrorMsg(pParse, "unsupported encoding: %s", zRight); |
| @@ -103851,28 +104064,13 @@ | ||
| 103851 | 104064 | ** |
| 103852 | 104065 | ** The user-version is not used internally by SQLite. It may be used by |
| 103853 | 104066 | ** applications for any purpose. |
| 103854 | 104067 | */ |
| 103855 | 104068 | case PragTyp_HEADER_VALUE: { |
| 103856 | - int iCookie; /* Cookie index. 1 for schema-cookie, 6 for user-cookie. */ | |
| 104069 | + int iCookie = aPragmaNames[mid].iArg; /* Which cookie to read or write */ | |
| 103857 | 104070 | sqlite3VdbeUsesBtree(v, iDb); |
| 103858 | - switch( zLeft[0] ){ | |
| 103859 | - case 'a': case 'A': | |
| 103860 | - iCookie = BTREE_APPLICATION_ID; | |
| 103861 | - break; | |
| 103862 | - case 'f': case 'F': | |
| 103863 | - iCookie = BTREE_FREE_PAGE_COUNT; | |
| 103864 | - break; | |
| 103865 | - case 's': case 'S': | |
| 103866 | - iCookie = BTREE_SCHEMA_VERSION; | |
| 103867 | - break; | |
| 103868 | - default: | |
| 103869 | - iCookie = BTREE_USER_VERSION; | |
| 103870 | - break; | |
| 103871 | - } | |
| 103872 | - | |
| 103873 | - if( zRight && iCookie!=BTREE_FREE_PAGE_COUNT ){ | |
| 104071 | + if( zRight && (aPragmaNames[mid].mPragFlag & PragFlag_ReadOnly)==0 ){ | |
| 103874 | 104072 | /* Write the specified cookie value */ |
| 103875 | 104073 | static const VdbeOpList setCookie[] = { |
| 103876 | 104074 | { OP_Transaction, 0, 1, 0}, /* 0 */ |
| 103877 | 104075 | { OP_Integer, 0, 1, 0}, /* 1 */ |
| 103878 | 104076 | { OP_SetCookie, 0, 0, 1}, /* 2 */ |
| @@ -103921,11 +104119,11 @@ | ||
| 103921 | 104119 | break; |
| 103922 | 104120 | #endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ |
| 103923 | 104121 | |
| 103924 | 104122 | #ifndef SQLITE_OMIT_WAL |
| 103925 | 104123 | /* |
| 103926 | - ** PRAGMA [database.]wal_checkpoint = passive|full|restart | |
| 104124 | + ** PRAGMA [database.]wal_checkpoint = passive|full|restart|truncate | |
| 103927 | 104125 | ** |
| 103928 | 104126 | ** Checkpoint the database. |
| 103929 | 104127 | */ |
| 103930 | 104128 | case PragTyp_WAL_CHECKPOINT: { |
| 103931 | 104129 | int iBt = (pId2->z?iDb:SQLITE_MAX_ATTACHED); |
| @@ -103933,10 +104131,12 @@ | ||
| 103933 | 104131 | if( zRight ){ |
| 103934 | 104132 | if( sqlite3StrICmp(zRight, "full")==0 ){ |
| 103935 | 104133 | eMode = SQLITE_CHECKPOINT_FULL; |
| 103936 | 104134 | }else if( sqlite3StrICmp(zRight, "restart")==0 ){ |
| 103937 | 104135 | eMode = SQLITE_CHECKPOINT_RESTART; |
| 104136 | + }else if( sqlite3StrICmp(zRight, "truncate")==0 ){ | |
| 104137 | + eMode = SQLITE_CHECKPOINT_TRUNCATE; | |
| 103938 | 104138 | } |
| 103939 | 104139 | } |
| 103940 | 104140 | sqlite3VdbeSetNumCols(v, 3); |
| 103941 | 104141 | pParse->nMem = 3; |
| 103942 | 104142 | sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "busy", SQLITE_STATIC); |
| @@ -104512,13 +104712,15 @@ | ||
| 104512 | 104712 | SQLITE_PRIVATE int sqlite3Init(sqlite3 *db, char **pzErrMsg){ |
| 104513 | 104713 | int i, rc; |
| 104514 | 104714 | int commit_internal = !(db->flags&SQLITE_InternChanges); |
| 104515 | 104715 | |
| 104516 | 104716 | assert( sqlite3_mutex_held(db->mutex) ); |
| 104717 | + assert( sqlite3BtreeHoldsMutex(db->aDb[0].pBt) ); | |
| 104517 | 104718 | assert( db->init.busy==0 ); |
| 104518 | 104719 | rc = SQLITE_OK; |
| 104519 | 104720 | db->init.busy = 1; |
| 104721 | + ENC(db) = SCHEMA_ENC(db); | |
| 104520 | 104722 | for(i=0; rc==SQLITE_OK && i<db->nDb; i++){ |
| 104521 | 104723 | if( DbHasProperty(db, i, DB_SchemaLoaded) || i==1 ) continue; |
| 104522 | 104724 | rc = sqlite3InitOne(db, i, pzErrMsg); |
| 104523 | 104725 | if( rc ){ |
| 104524 | 104726 | sqlite3ResetOneSchema(db, i); |
| @@ -109840,11 +110042,11 @@ | ||
| 109840 | 110042 | ** |
| 109841 | 110043 | ** SELECT DISTINCT xyz FROM ... ORDER BY xyz |
| 109842 | 110044 | ** |
| 109843 | 110045 | ** is transformed to: |
| 109844 | 110046 | ** |
| 109845 | - ** SELECT xyz FROM ... GROUP BY xyz | |
| 110047 | + ** SELECT xyz FROM ... GROUP BY xyz ORDER BY xyz | |
| 109846 | 110048 | ** |
| 109847 | 110049 | ** The second form is preferred as a single index (or temp-table) may be |
| 109848 | 110050 | ** used for both the ORDER BY and DISTINCT processing. As originally |
| 109849 | 110051 | ** written the query must use a temp-table for at least one of the ORDER |
| 109850 | 110052 | ** BY and DISTINCT, and an index or separate temp-table for the other. |
| @@ -109853,11 +110055,10 @@ | ||
| 109853 | 110055 | && sqlite3ExprListCompare(sSort.pOrderBy, p->pEList, -1)==0 |
| 109854 | 110056 | ){ |
| 109855 | 110057 | p->selFlags &= ~SF_Distinct; |
| 109856 | 110058 | p->pGroupBy = sqlite3ExprListDup(db, p->pEList, 0); |
| 109857 | 110059 | pGroupBy = p->pGroupBy; |
| 109858 | - sSort.pOrderBy = 0; | |
| 109859 | 110060 | /* Notice that even thought SF_Distinct has been cleared from p->selFlags, |
| 109860 | 110061 | ** the sDistinct.isTnct is still set. Hence, isTnct represents the |
| 109861 | 110062 | ** original setting of the SF_Distinct flag, not the current setting */ |
| 109862 | 110063 | assert( sDistinct.isTnct ); |
| 109863 | 110064 | } |
| @@ -110657,11 +110858,11 @@ | ||
| 110657 | 110858 | ){ |
| 110658 | 110859 | int rc; |
| 110659 | 110860 | TabResult res; |
| 110660 | 110861 | |
| 110661 | 110862 | #ifdef SQLITE_ENABLE_API_ARMOR |
| 110662 | - if( pazResult==0 ) return SQLITE_MISUSE_BKPT; | |
| 110863 | + if( !sqlite3SafetyCheckOk(db) || pazResult==0 ) return SQLITE_MISUSE_BKPT; | |
| 110663 | 110864 | #endif |
| 110664 | 110865 | *pazResult = 0; |
| 110665 | 110866 | if( pnColumn ) *pnColumn = 0; |
| 110666 | 110867 | if( pnRow ) *pnRow = 0; |
| 110667 | 110868 | if( pzErrMsg ) *pzErrMsg = 0; |
| @@ -114808,10 +115009,11 @@ | ||
| 114808 | 115009 | memcpy(pWC->a, pOld, sizeof(pWC->a[0])*pWC->nTerm); |
| 114809 | 115010 | if( pOld!=pWC->aStatic ){ |
| 114810 | 115011 | sqlite3DbFree(db, pOld); |
| 114811 | 115012 | } |
| 114812 | 115013 | pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]); |
| 115014 | + memset(&pWC->a[pWC->nTerm], 0, sizeof(pWC->a[0])*(pWC->nSlot-pWC->nTerm)); | |
| 114813 | 115015 | } |
| 114814 | 115016 | pTerm = &pWC->a[idx = pWC->nTerm++]; |
| 114815 | 115017 | if( p && ExprHasProperty(p, EP_Unlikely) ){ |
| 114816 | 115018 | pTerm->truthProb = sqlite3LogEst(p->iTable) - 270; |
| 114817 | 115019 | }else{ |
| @@ -117533,11 +117735,11 @@ | ||
| 117533 | 117735 | WhereLevel *pLvl, /* Level to add scanstatus() entry for */ |
| 117534 | 117736 | int addrExplain /* Address of OP_Explain (or 0) */ |
| 117535 | 117737 | ){ |
| 117536 | 117738 | const char *zObj = 0; |
| 117537 | 117739 | WhereLoop *pLoop = pLvl->pWLoop; |
| 117538 | - if( (pLoop->wsFlags & (WHERE_IPK|WHERE_VIRTUALTABLE))==0 ){ | |
| 117740 | + if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 && pLoop->u.btree.pIndex!=0 ){ | |
| 117539 | 117741 | zObj = pLoop->u.btree.pIndex->zName; |
| 117540 | 117742 | }else{ |
| 117541 | 117743 | zObj = pSrclist->a[pLvl->iFrom].zName; |
| 117542 | 117744 | } |
| 117543 | 117745 | sqlite3VdbeScanStatus( |
| @@ -118177,14 +118379,13 @@ | ||
| 118177 | 118379 | int iTerm; |
| 118178 | 118380 | for(iTerm=0; iTerm<pWC->nTerm; iTerm++){ |
| 118179 | 118381 | Expr *pExpr = pWC->a[iTerm].pExpr; |
| 118180 | 118382 | if( &pWC->a[iTerm] == pTerm ) continue; |
| 118181 | 118383 | if( ExprHasProperty(pExpr, EP_FromJoin) ) continue; |
| 118182 | - testcase( pWC->a[iTerm].wtFlags & TERM_ORINFO ); | |
| 118183 | - testcase( pWC->a[iTerm].wtFlags & TERM_VIRTUAL ); | |
| 118184 | - if( pWC->a[iTerm].wtFlags & (TERM_ORINFO|TERM_VIRTUAL) ) continue; | |
| 118384 | + if( (pWC->a[iTerm].wtFlags & TERM_VIRTUAL)!=0 ) continue; | |
| 118185 | 118385 | if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue; |
| 118386 | + testcase( pWC->a[iTerm].wtFlags & TERM_ORINFO ); | |
| 118186 | 118387 | pExpr = sqlite3ExprDup(db, pExpr, 0); |
| 118187 | 118388 | pAndExpr = sqlite3ExprAnd(db, pAndExpr, pExpr); |
| 118188 | 118389 | } |
| 118189 | 118390 | if( pAndExpr ){ |
| 118190 | 118391 | pAndExpr = sqlite3PExpr(pParse, TK_AND, 0, pAndExpr, 0); |
| @@ -118527,11 +118728,10 @@ | ||
| 118527 | 118728 | sqlite3_free(p->u.vtab.idxStr); |
| 118528 | 118729 | p->u.vtab.needFree = 0; |
| 118529 | 118730 | p->u.vtab.idxStr = 0; |
| 118530 | 118731 | }else if( (p->wsFlags & WHERE_AUTO_INDEX)!=0 && p->u.btree.pIndex!=0 ){ |
| 118531 | 118732 | sqlite3DbFree(db, p->u.btree.pIndex->zColAff); |
| 118532 | - sqlite3KeyInfoUnref(p->u.btree.pIndex->pKeyInfo); | |
| 118533 | 118733 | sqlite3DbFree(db, p->u.btree.pIndex); |
| 118534 | 118734 | p->u.btree.pIndex = 0; |
| 118535 | 118735 | } |
| 118536 | 118736 | } |
| 118537 | 118737 | } |
| @@ -125534,10 +125734,13 @@ | ||
| 125534 | 125734 | u8 enableLookaside; /* Saved value of db->lookaside.bEnabled */ |
| 125535 | 125735 | sqlite3 *db = pParse->db; /* The database connection */ |
| 125536 | 125736 | int mxSqlLen; /* Max length of an SQL string */ |
| 125537 | 125737 | |
| 125538 | 125738 | |
| 125739 | +#ifdef SQLITE_ENABLE_API_ARMOR | |
| 125740 | + if( zSql==0 || pzErrMsg==0 ) return SQLITE_MISUSE_BKPT; | |
| 125741 | +#endif | |
| 125539 | 125742 | mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH]; |
| 125540 | 125743 | if( db->nVdbeActive==0 ){ |
| 125541 | 125744 | db->u1.isInterrupted = 0; |
| 125542 | 125745 | } |
| 125543 | 125746 | pParse->rc = SQLITE_OK; |
| @@ -125772,17 +125975,10 @@ | ||
| 125772 | 125975 | */ |
| 125773 | 125976 | SQLITE_API int sqlite3_complete(const char *zSql){ |
| 125774 | 125977 | u8 state = 0; /* Current state, using numbers defined in header comment */ |
| 125775 | 125978 | u8 token; /* Value of the next token */ |
| 125776 | 125979 | |
| 125777 | -#ifdef SQLITE_ENABLE_API_ARMOR | |
| 125778 | - if( zSql==0 ){ | |
| 125779 | - (void)SQLITE_MISUSE_BKPT; | |
| 125780 | - return 0; | |
| 125781 | - } | |
| 125782 | -#endif | |
| 125783 | - | |
| 125784 | 125980 | #ifndef SQLITE_OMIT_TRIGGER |
| 125785 | 125981 | /* A complex statement machine used to detect the end of a CREATE TRIGGER |
| 125786 | 125982 | ** statement. This is the normal case. |
| 125787 | 125983 | */ |
| 125788 | 125984 | static const u8 trans[8][8] = { |
| @@ -125807,10 +126003,17 @@ | ||
| 125807 | 126003 | /* 0 INVALID: */ { 1, 0, 2, }, |
| 125808 | 126004 | /* 1 START: */ { 1, 1, 2, }, |
| 125809 | 126005 | /* 2 NORMAL: */ { 1, 2, 2, }, |
| 125810 | 126006 | }; |
| 125811 | 126007 | #endif /* SQLITE_OMIT_TRIGGER */ |
| 126008 | + | |
| 126009 | +#ifdef SQLITE_ENABLE_API_ARMOR | |
| 126010 | + if( zSql==0 ){ | |
| 126011 | + (void)SQLITE_MISUSE_BKPT; | |
| 126012 | + return 0; | |
| 126013 | + } | |
| 126014 | +#endif | |
| 125812 | 126015 | |
| 125813 | 126016 | while( *zSql ){ |
| 125814 | 126017 | switch( *zSql ){ |
| 125815 | 126018 | case ';': { /* A semicolon */ |
| 125816 | 126019 | token = tkSEMI; |
| @@ -126109,11 +126312,11 @@ | ||
| 126109 | 126312 | ** If the following function pointer is not NULL and if |
| 126110 | 126313 | ** SQLITE_ENABLE_IOTRACE is enabled, then messages describing |
| 126111 | 126314 | ** I/O active are written using this function. These messages |
| 126112 | 126315 | ** are intended for debugging activity only. |
| 126113 | 126316 | */ |
| 126114 | -SQLITE_PRIVATE void (*sqlite3IoTrace)(const char*, ...) = 0; | |
| 126317 | +/* not-private */ void (*sqlite3IoTrace)(const char*, ...) = 0; | |
| 126115 | 126318 | #endif |
| 126116 | 126319 | |
| 126117 | 126320 | /* |
| 126118 | 126321 | ** If the following global variable points to a string which is the |
| 126119 | 126322 | ** name of a directory, then that directory will be used to store |
| @@ -126318,10 +126521,17 @@ | ||
| 126318 | 126521 | ** routine is not threadsafe. But it is safe to invoke this routine |
| 126319 | 126522 | ** on when SQLite is already shut down. If SQLite is already shut down |
| 126320 | 126523 | ** when this routine is invoked, then this routine is a harmless no-op. |
| 126321 | 126524 | */ |
| 126322 | 126525 | SQLITE_API int sqlite3_shutdown(void){ |
| 126526 | +#ifdef SQLITE_OMIT_WSD | |
| 126527 | + int rc = sqlite3_wsd_init(4096, 24); | |
| 126528 | + if( rc!=SQLITE_OK ){ | |
| 126529 | + return rc; | |
| 126530 | + } | |
| 126531 | +#endif | |
| 126532 | + | |
| 126323 | 126533 | if( sqlite3GlobalConfig.isInit ){ |
| 126324 | 126534 | #ifdef SQLITE_EXTRA_SHUTDOWN |
| 126325 | 126535 | void SQLITE_EXTRA_SHUTDOWN(void); |
| 126326 | 126536 | SQLITE_EXTRA_SHUTDOWN(); |
| 126327 | 126537 | #endif |
| @@ -126633,10 +126843,15 @@ | ||
| 126633 | 126843 | ** heap. */ |
| 126634 | 126844 | sqlite3GlobalConfig.nHeap = va_arg(ap, int); |
| 126635 | 126845 | break; |
| 126636 | 126846 | } |
| 126637 | 126847 | #endif |
| 126848 | + | |
| 126849 | + case SQLITE_CONFIG_PMASZ: { | |
| 126850 | + sqlite3GlobalConfig.szPma = va_arg(ap, unsigned int); | |
| 126851 | + break; | |
| 126852 | + } | |
| 126638 | 126853 | |
| 126639 | 126854 | default: { |
| 126640 | 126855 | rc = SQLITE_ERROR; |
| 126641 | 126856 | break; |
| 126642 | 126857 | } |
| @@ -127983,14 +128198,17 @@ | ||
| 127983 | 128198 | |
| 127984 | 128199 | /* Initialize the output variables to -1 in case an error occurs. */ |
| 127985 | 128200 | if( pnLog ) *pnLog = -1; |
| 127986 | 128201 | if( pnCkpt ) *pnCkpt = -1; |
| 127987 | 128202 | |
| 127988 | - assert( SQLITE_CHECKPOINT_FULL>SQLITE_CHECKPOINT_PASSIVE ); | |
| 127989 | - assert( SQLITE_CHECKPOINT_FULL<SQLITE_CHECKPOINT_RESTART ); | |
| 127990 | - assert( SQLITE_CHECKPOINT_PASSIVE+2==SQLITE_CHECKPOINT_RESTART ); | |
| 127991 | - if( eMode<SQLITE_CHECKPOINT_PASSIVE || eMode>SQLITE_CHECKPOINT_RESTART ){ | |
| 128203 | + assert( SQLITE_CHECKPOINT_PASSIVE==0 ); | |
| 128204 | + assert( SQLITE_CHECKPOINT_FULL==1 ); | |
| 128205 | + assert( SQLITE_CHECKPOINT_RESTART==2 ); | |
| 128206 | + assert( SQLITE_CHECKPOINT_TRUNCATE==3 ); | |
| 128207 | + if( eMode<SQLITE_CHECKPOINT_PASSIVE || eMode>SQLITE_CHECKPOINT_TRUNCATE ){ | |
| 128208 | + /* EVIDENCE-OF: R-03996-12088 The M parameter must be a valid checkpoint | |
| 128209 | + ** mode: */ | |
| 127992 | 128210 | return SQLITE_MISUSE; |
| 127993 | 128211 | } |
| 127994 | 128212 | |
| 127995 | 128213 | sqlite3_mutex_enter(db->mutex); |
| 127996 | 128214 | if( zDb && zDb[0] ){ |
| @@ -128014,11 +128232,13 @@ | ||
| 128014 | 128232 | ** Checkpoint database zDb. If zDb is NULL, or if the buffer zDb points |
| 128015 | 128233 | ** to contains a zero-length string, all attached databases are |
| 128016 | 128234 | ** checkpointed. |
| 128017 | 128235 | */ |
| 128018 | 128236 | SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb){ |
| 128019 | - return sqlite3_wal_checkpoint_v2(db, zDb, SQLITE_CHECKPOINT_PASSIVE, 0, 0); | |
| 128237 | + /* EVIDENCE-OF: R-41613-20553 The sqlite3_wal_checkpoint(D,X) is equivalent to | |
| 128238 | + ** sqlite3_wal_checkpoint_v2(D,X,SQLITE_CHECKPOINT_PASSIVE,0,0). */ | |
| 128239 | + return sqlite3_wal_checkpoint_v2(db,zDb,SQLITE_CHECKPOINT_PASSIVE,0,0); | |
| 128020 | 128240 | } |
| 128021 | 128241 | |
| 128022 | 128242 | #ifndef SQLITE_OMIT_WAL |
| 128023 | 128243 | /* |
| 128024 | 128244 | ** Run a checkpoint on database iDb. This is a no-op if database iDb is |
| @@ -128201,36 +128421,10 @@ | ||
| 128201 | 128421 | */ |
| 128202 | 128422 | SQLITE_API const char *sqlite3_errstr(int rc){ |
| 128203 | 128423 | return sqlite3ErrStr(rc); |
| 128204 | 128424 | } |
| 128205 | 128425 | |
| 128206 | -/* | |
| 128207 | -** Invalidate all cached KeyInfo objects for database connection "db" | |
| 128208 | -*/ | |
| 128209 | -static void invalidateCachedKeyInfo(sqlite3 *db){ | |
| 128210 | - Db *pDb; /* A single database */ | |
| 128211 | - int iDb; /* The database index number */ | |
| 128212 | - HashElem *k; /* For looping over tables in pDb */ | |
| 128213 | - Table *pTab; /* A table in the database */ | |
| 128214 | - Index *pIdx; /* Each index */ | |
| 128215 | - | |
| 128216 | - for(iDb=0, pDb=db->aDb; iDb<db->nDb; iDb++, pDb++){ | |
| 128217 | - if( pDb->pBt==0 ) continue; | |
| 128218 | - sqlite3BtreeEnter(pDb->pBt); | |
| 128219 | - for(k=sqliteHashFirst(&pDb->pSchema->tblHash); k; k=sqliteHashNext(k)){ | |
| 128220 | - pTab = (Table*)sqliteHashData(k); | |
| 128221 | - for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ | |
| 128222 | - if( pIdx->pKeyInfo && pIdx->pKeyInfo->db==db ){ | |
| 128223 | - sqlite3KeyInfoUnref(pIdx->pKeyInfo); | |
| 128224 | - pIdx->pKeyInfo = 0; | |
| 128225 | - } | |
| 128226 | - } | |
| 128227 | - } | |
| 128228 | - sqlite3BtreeLeave(pDb->pBt); | |
| 128229 | - } | |
| 128230 | -} | |
| 128231 | - | |
| 128232 | 128426 | /* |
| 128233 | 128427 | ** Create a new collating function for database "db". The name is zName |
| 128234 | 128428 | ** and the encoding is enc. |
| 128235 | 128429 | */ |
| 128236 | 128430 | static int createCollation( |
| @@ -128270,11 +128464,10 @@ | ||
| 128270 | 128464 | sqlite3ErrorWithMsg(db, SQLITE_BUSY, |
| 128271 | 128465 | "unable to delete/modify collation sequence due to active statements"); |
| 128272 | 128466 | return SQLITE_BUSY; |
| 128273 | 128467 | } |
| 128274 | 128468 | sqlite3ExpirePreparedStatements(db); |
| 128275 | - invalidateCachedKeyInfo(db); | |
| 128276 | 128469 | |
| 128277 | 128470 | /* If collation sequence pColl was created directly by a call to |
| 128278 | 128471 | ** sqlite3_create_collation, and not generated by synthCollSeq(), |
| 128279 | 128472 | ** then any copies made by synthCollSeq() need to be invalidated. |
| 128280 | 128473 | ** Also, collation destructor - CollSeq.xDel() - function may need |
| @@ -128775,10 +128968,13 @@ | ||
| 128775 | 128968 | | SQLITE_RecTriggers |
| 128776 | 128969 | #endif |
| 128777 | 128970 | #if defined(SQLITE_DEFAULT_FOREIGN_KEYS) && SQLITE_DEFAULT_FOREIGN_KEYS |
| 128778 | 128971 | | SQLITE_ForeignKeys |
| 128779 | 128972 | #endif |
| 128973 | +#if defined(SQLITE_REVERSE_UNORDERED_SELECTS) | |
| 128974 | + | SQLITE_ReverseOrder | |
| 128975 | +#endif | |
| 128780 | 128976 | ; |
| 128781 | 128977 | sqlite3HashInit(&db->aCollSeq); |
| 128782 | 128978 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 128783 | 128979 | sqlite3HashInit(&db->aModule); |
| 128784 | 128980 | #endif |
| @@ -128822,11 +129018,14 @@ | ||
| 128822 | 129018 | rc = SQLITE_NOMEM; |
| 128823 | 129019 | } |
| 128824 | 129020 | sqlite3Error(db, rc); |
| 128825 | 129021 | goto opendb_out; |
| 128826 | 129022 | } |
| 129023 | + sqlite3BtreeEnter(db->aDb[0].pBt); | |
| 128827 | 129024 | db->aDb[0].pSchema = sqlite3SchemaGet(db, db->aDb[0].pBt); |
| 129025 | + if( !db->mallocFailed ) ENC(db) = SCHEMA_ENC(db); | |
| 129026 | + sqlite3BtreeLeave(db->aDb[0].pBt); | |
| 128828 | 129027 | db->aDb[1].pSchema = sqlite3SchemaGet(db, 0); |
| 128829 | 129028 | |
| 128830 | 129029 | /* The default safety_level for the main database is 'full'; for the temp |
| 128831 | 129030 | ** database it is 'NONE'. This matches the pager layer defaults. |
| 128832 | 129031 | */ |
| @@ -128980,11 +129179,11 @@ | ||
| 128980 | 129179 | if( zFilename8 ){ |
| 128981 | 129180 | rc = openDatabase(zFilename8, ppDb, |
| 128982 | 129181 | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0); |
| 128983 | 129182 | assert( *ppDb || rc==SQLITE_NOMEM ); |
| 128984 | 129183 | if( rc==SQLITE_OK && !DbHasProperty(*ppDb, 0, DB_SchemaLoaded) ){ |
| 128985 | - ENC(*ppDb) = SQLITE_UTF16NATIVE; | |
| 129184 | + SCHEMA_ENC(*ppDb) = ENC(*ppDb) = SQLITE_UTF16NATIVE; | |
| 128986 | 129185 | } |
| 128987 | 129186 | }else{ |
| 128988 | 129187 | rc = SQLITE_NOMEM; |
| 128989 | 129188 | } |
| 128990 | 129189 | sqlite3ValueFree(pVal); |
| @@ -129176,11 +129375,10 @@ | ||
| 129176 | 129375 | |
| 129177 | 129376 | /* |
| 129178 | 129377 | ** Return meta information about a specific column of a database table. |
| 129179 | 129378 | ** See comment in sqlite3.h (sqlite.h.in) for details. |
| 129180 | 129379 | */ |
| 129181 | -#ifdef SQLITE_ENABLE_COLUMN_METADATA | |
| 129182 | 129380 | SQLITE_API int sqlite3_table_column_metadata( |
| 129183 | 129381 | sqlite3 *db, /* Connection handle */ |
| 129184 | 129382 | const char *zDbName, /* Database name or NULL */ |
| 129185 | 129383 | const char *zTableName, /* Table name */ |
| 129186 | 129384 | const char *zColumnName, /* Column name */ |
| @@ -129216,25 +129414,27 @@ | ||
| 129216 | 129414 | pTab = 0; |
| 129217 | 129415 | goto error_out; |
| 129218 | 129416 | } |
| 129219 | 129417 | |
| 129220 | 129418 | /* Find the column for which info is requested */ |
| 129221 | - if( sqlite3IsRowid(zColumnName) ){ | |
| 129222 | - iCol = pTab->iPKey; | |
| 129223 | - if( iCol>=0 ){ | |
| 129224 | - pCol = &pTab->aCol[iCol]; | |
| 129225 | - } | |
| 129419 | + if( zColumnName==0 ){ | |
| 129420 | + /* Query for existance of table only */ | |
| 129226 | 129421 | }else{ |
| 129227 | 129422 | for(iCol=0; iCol<pTab->nCol; iCol++){ |
| 129228 | 129423 | pCol = &pTab->aCol[iCol]; |
| 129229 | 129424 | if( 0==sqlite3StrICmp(pCol->zName, zColumnName) ){ |
| 129230 | 129425 | break; |
| 129231 | 129426 | } |
| 129232 | 129427 | } |
| 129233 | 129428 | if( iCol==pTab->nCol ){ |
| 129234 | - pTab = 0; | |
| 129235 | - goto error_out; | |
| 129429 | + if( HasRowid(pTab) && sqlite3IsRowid(zColumnName) ){ | |
| 129430 | + iCol = pTab->iPKey; | |
| 129431 | + pCol = iCol>=0 ? &pTab->aCol[iCol] : 0; | |
| 129432 | + }else{ | |
| 129433 | + pTab = 0; | |
| 129434 | + goto error_out; | |
| 129435 | + } | |
| 129236 | 129436 | } |
| 129237 | 129437 | } |
| 129238 | 129438 | |
| 129239 | 129439 | /* The following block stores the meta information that will be returned |
| 129240 | 129440 | ** to the caller in local variables zDataType, zCollSeq, notnull, primarykey |
| @@ -129283,11 +129483,10 @@ | ||
| 129283 | 129483 | sqlite3DbFree(db, zErrMsg); |
| 129284 | 129484 | rc = sqlite3ApiExit(db, rc); |
| 129285 | 129485 | sqlite3_mutex_leave(db->mutex); |
| 129286 | 129486 | return rc; |
| 129287 | 129487 | } |
| 129288 | -#endif | |
| 129289 | 129488 | |
| 129290 | 129489 | /* |
| 129291 | 129490 | ** Sleep for a little while. Return the amount of time slept. |
| 129292 | 129491 | */ |
| 129293 | 129492 | SQLITE_API int sqlite3_sleep(int ms){ |
| @@ -129722,32 +129921,34 @@ | ||
| 129722 | 129921 | /* |
| 129723 | 129922 | ** Return the filename of the database associated with a database |
| 129724 | 129923 | ** connection. |
| 129725 | 129924 | */ |
| 129726 | 129925 | SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName){ |
| 129926 | + Btree *pBt; | |
| 129727 | 129927 | #ifdef SQLITE_ENABLE_API_ARMOR |
| 129728 | 129928 | if( !sqlite3SafetyCheckOk(db) ){ |
| 129729 | 129929 | (void)SQLITE_MISUSE_BKPT; |
| 129730 | 129930 | return 0; |
| 129731 | 129931 | } |
| 129732 | 129932 | #endif |
| 129733 | - Btree *pBt = sqlite3DbNameToBtree(db, zDbName); | |
| 129933 | + pBt = sqlite3DbNameToBtree(db, zDbName); | |
| 129734 | 129934 | return pBt ? sqlite3BtreeGetFilename(pBt) : 0; |
| 129735 | 129935 | } |
| 129736 | 129936 | |
| 129737 | 129937 | /* |
| 129738 | 129938 | ** Return 1 if database is read-only or 0 if read/write. Return -1 if |
| 129739 | 129939 | ** no such database exists. |
| 129740 | 129940 | */ |
| 129741 | 129941 | SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName){ |
| 129942 | + Btree *pBt; | |
| 129742 | 129943 | #ifdef SQLITE_ENABLE_API_ARMOR |
| 129743 | 129944 | if( !sqlite3SafetyCheckOk(db) ){ |
| 129744 | 129945 | (void)SQLITE_MISUSE_BKPT; |
| 129745 | 129946 | return -1; |
| 129746 | 129947 | } |
| 129747 | 129948 | #endif |
| 129748 | - Btree *pBt = sqlite3DbNameToBtree(db, zDbName); | |
| 129949 | + pBt = sqlite3DbNameToBtree(db, zDbName); | |
| 129749 | 129950 | return pBt ? sqlite3BtreeIsReadonly(pBt) : -1; |
| 129750 | 129951 | } |
| 129751 | 129952 | |
| 129752 | 129953 | /************** End of main.c ************************************************/ |
| 129753 | 129954 | /************** Begin file notify.c ******************************************/ |
| @@ -139164,11 +139365,11 @@ | ||
| 139164 | 139365 | ** Return true if the m-value for z is 1 or more. In other words, |
| 139165 | 139366 | ** return true if z contains at least one vowel that is followed |
| 139166 | 139367 | ** by a consonant. |
| 139167 | 139368 | ** |
| 139168 | 139369 | ** In this routine z[] is in reverse order. So we are really looking |
| 139169 | -** for an instance of of a consonant followed by a vowel. | |
| 139370 | +** for an instance of a consonant followed by a vowel. | |
| 139170 | 139371 | */ |
| 139171 | 139372 | static int m_gt_0(const char *z){ |
| 139172 | 139373 | while( isVowel(z) ){ z++; } |
| 139173 | 139374 | if( *z==0 ) return 0; |
| 139174 | 139375 | while( isConsonant(z) ){ z++; } |
| @@ -149954,11 +150155,11 @@ | ||
| 149954 | 150155 | } |
| 149955 | 150156 | i = pCur->nPoint++; |
| 149956 | 150157 | pNew = pCur->aPoint + i; |
| 149957 | 150158 | pNew->rScore = rScore; |
| 149958 | 150159 | pNew->iLevel = iLevel; |
| 149959 | - assert( iLevel>=0 && iLevel<=RTREE_MAX_DEPTH ); | |
| 150160 | + assert( iLevel<=RTREE_MAX_DEPTH ); | |
| 149960 | 150161 | while( i>0 ){ |
| 149961 | 150162 | RtreeSearchPoint *pParent; |
| 149962 | 150163 | j = (i-1)/2; |
| 149963 | 150164 | pParent = pCur->aPoint + j; |
| 149964 | 150165 | if( rtreeSearchPointCompare(pNew, pParent)>=0 ) break; |
| 149965 | 150166 |
| --- src/sqlite3.c | |
| +++ src/sqlite3.c | |
| @@ -231,11 +231,11 @@ | |
| 231 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 232 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 233 | */ |
| 234 | #define SQLITE_VERSION "3.8.8" |
| 235 | #define SQLITE_VERSION_NUMBER 3008008 |
| 236 | #define SQLITE_SOURCE_ID "2014-11-28 13:35:03 24fa2e9832daaa5d68ee28a00c56c55f97a4da9e" |
| 237 | |
| 238 | /* |
| 239 | ** CAPI3REF: Run-Time Library Version Numbers |
| 240 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 241 | ** |
| @@ -323,11 +323,11 @@ | |
| 323 | ** This interface only reports on the compile-time mutex setting |
| 324 | ** of the [SQLITE_THREADSAFE] flag. If SQLite is compiled with |
| 325 | ** SQLITE_THREADSAFE=1 or =2 then mutexes are enabled by default but |
| 326 | ** can be fully or partially disabled using a call to [sqlite3_config()] |
| 327 | ** with the verbs [SQLITE_CONFIG_SINGLETHREAD], [SQLITE_CONFIG_MULTITHREAD], |
| 328 | ** or [SQLITE_CONFIG_MUTEX]. ^(The return value of the |
| 329 | ** sqlite3_threadsafe() function shows only the compile-time setting of |
| 330 | ** thread safety, not any run-time changes to that setting made by |
| 331 | ** sqlite3_config(). In other words, the return value from sqlite3_threadsafe() |
| 332 | ** is unchanged by calls to sqlite3_config().)^ |
| 333 | ** |
| @@ -1343,11 +1343,11 @@ | |
| 1343 | ** <li> SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED |
| 1344 | ** <li> SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE |
| 1345 | ** </ul> |
| 1346 | ** |
| 1347 | ** When unlocking, the same SHARED or EXCLUSIVE flag must be supplied as |
| 1348 | ** was given no the corresponding lock. |
| 1349 | ** |
| 1350 | ** The xShmLock method can transition between unlocked and SHARED or |
| 1351 | ** between unlocked and EXCLUSIVE. It cannot transition between SHARED |
| 1352 | ** and EXCLUSIVE. |
| 1353 | */ |
| @@ -1646,12 +1646,12 @@ | |
| 1646 | ** tracks memory usage, for example. </dd> |
| 1647 | ** |
| 1648 | ** [[SQLITE_CONFIG_MEMSTATUS]] <dt>SQLITE_CONFIG_MEMSTATUS</dt> |
| 1649 | ** <dd> ^The SQLITE_CONFIG_MEMSTATUS option takes single argument of type int, |
| 1650 | ** interpreted as a boolean, which enables or disables the collection of |
| 1651 | ** memory allocation statistics. ^(When memory allocation statistics are disabled, the |
| 1652 | ** following SQLite interfaces become non-operational: |
| 1653 | ** <ul> |
| 1654 | ** <li> [sqlite3_memory_used()] |
| 1655 | ** <li> [sqlite3_memory_highwater()] |
| 1656 | ** <li> [sqlite3_soft_heap_limit64()] |
| 1657 | ** <li> [sqlite3_status()] |
| @@ -1688,14 +1688,15 @@ | |
| 1688 | ** that SQLite can use for the database page cache with the default page |
| 1689 | ** cache implementation. |
| 1690 | ** This configuration should not be used if an application-define page |
| 1691 | ** cache implementation is loaded using the [SQLITE_CONFIG_PCACHE2] |
| 1692 | ** configuration option. |
| 1693 | ** ^There are three arguments to SQLITE_CONFIG_PAGECACHE: A pointer to 8-byte aligned |
| 1694 | ** memory, the size of each page buffer (sz), and the number of pages (N). |
| 1695 | ** The sz argument should be the size of the largest database page |
| 1696 | ** (a power of two between 512 and 32768) plus some extra bytes for each |
| 1697 | ** page header. ^The number of extra bytes needed by the page header |
| 1698 | ** can be determined using the [SQLITE_CONFIG_PCACHE_HDRSZ] option |
| 1699 | ** to [sqlite3_config()]. |
| 1700 | ** ^It is harmless, apart from the wasted memory, |
| 1701 | ** for the sz parameter to be larger than necessary. The first |
| @@ -1708,11 +1709,12 @@ | |
| 1708 | ** SQLite goes to [sqlite3_malloc()] for the additional storage space.</dd> |
| 1709 | ** |
| 1710 | ** [[SQLITE_CONFIG_HEAP]] <dt>SQLITE_CONFIG_HEAP</dt> |
| 1711 | ** <dd> ^The SQLITE_CONFIG_HEAP option specifies a static memory buffer |
| 1712 | ** that SQLite will use for all of its dynamic memory allocation needs |
| 1713 | ** beyond those provided for by [SQLITE_CONFIG_SCRATCH] and [SQLITE_CONFIG_PAGECACHE]. |
| 1714 | ** ^The SQLITE_CONFIG_HEAP option is only available if SQLite is compiled |
| 1715 | ** with either [SQLITE_ENABLE_MEMSYS3] or [SQLITE_ENABLE_MEMSYS5] and returns |
| 1716 | ** [SQLITE_ERROR] if invoked otherwise. |
| 1717 | ** ^There are three arguments to SQLITE_CONFIG_HEAP: |
| 1718 | ** An 8-byte aligned pointer to the memory, |
| @@ -1728,13 +1730,13 @@ | |
| 1728 | ** for the minimum allocation size are 2**5 through 2**8.</dd> |
| 1729 | ** |
| 1730 | ** [[SQLITE_CONFIG_MUTEX]] <dt>SQLITE_CONFIG_MUTEX</dt> |
| 1731 | ** <dd> ^(The SQLITE_CONFIG_MUTEX option takes a single argument which is a |
| 1732 | ** pointer to an instance of the [sqlite3_mutex_methods] structure. |
| 1733 | ** The argument specifies alternative low-level mutex routines to be used in place |
| 1734 | ** the mutex routines built into SQLite.)^ ^SQLite makes a copy of the |
| 1735 | ** content of the [sqlite3_mutex_methods] structure before the call to |
| 1736 | ** [sqlite3_config()] returns. ^If SQLite is compiled with |
| 1737 | ** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then |
| 1738 | ** the entire mutexing subsystem is omitted from the build and hence calls to |
| 1739 | ** [sqlite3_config()] with the SQLITE_CONFIG_MUTEX configuration option will |
| 1740 | ** return [SQLITE_ERROR].</dd> |
| @@ -1768,12 +1770,12 @@ | |
| 1768 | ** the interface to a custom page cache implementation.)^ |
| 1769 | ** ^SQLite makes a copy of the [sqlite3_pcache_methods2] object.</dd> |
| 1770 | ** |
| 1771 | ** [[SQLITE_CONFIG_GETPCACHE2]] <dt>SQLITE_CONFIG_GETPCACHE2</dt> |
| 1772 | ** <dd> ^(The SQLITE_CONFIG_GETPCACHE2 option takes a single argument which |
| 1773 | ** is a pointer to an [sqlite3_pcache_methods2] object. SQLite copies of the current |
| 1774 | ** page cache implementation into that object.)^ </dd> |
| 1775 | ** |
| 1776 | ** [[SQLITE_CONFIG_LOG]] <dt>SQLITE_CONFIG_LOG</dt> |
| 1777 | ** <dd> The SQLITE_CONFIG_LOG option is used to configure the SQLite |
| 1778 | ** global [error log]. |
| 1779 | ** (^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a |
| @@ -1794,12 +1796,13 @@ | |
| 1794 | ** function must be threadsafe. </dd> |
| 1795 | ** |
| 1796 | ** [[SQLITE_CONFIG_URI]] <dt>SQLITE_CONFIG_URI |
| 1797 | ** <dd>^(The SQLITE_CONFIG_URI option takes a single argument of type int. |
| 1798 | ** If non-zero, then URI handling is globally enabled. If the parameter is zero, |
| 1799 | ** then URI handling is globally disabled.)^ ^If URI handling is globally enabled, |
| 1800 | ** all filenames passed to [sqlite3_open()], [sqlite3_open_v2()], [sqlite3_open16()] or |
| 1801 | ** specified as part of [ATTACH] commands are interpreted as URIs, regardless |
| 1802 | ** of whether or not the [SQLITE_OPEN_URI] flag is set when the database |
| 1803 | ** connection is opened. ^If it is globally disabled, filenames are |
| 1804 | ** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the |
| 1805 | ** database connection is opened. ^(By default, URI handling is globally |
| @@ -1857,22 +1860,33 @@ | |
| 1857 | ** changed to its compile-time default. |
| 1858 | ** |
| 1859 | ** [[SQLITE_CONFIG_WIN32_HEAPSIZE]] |
| 1860 | ** <dt>SQLITE_CONFIG_WIN32_HEAPSIZE |
| 1861 | ** <dd>^The SQLITE_CONFIG_WIN32_HEAPSIZE option is only available if SQLite is |
| 1862 | ** compiled for Windows with the [SQLITE_WIN32_MALLOC] pre-processor macro defined. |
| 1863 | ** ^SQLITE_CONFIG_WIN32_HEAPSIZE takes a 32-bit unsigned integer value |
| 1864 | ** that specifies the maximum size of the created heap. |
| 1865 | ** </dl> |
| 1866 | ** |
| 1867 | ** [[SQLITE_CONFIG_PCACHE_HDRSZ]] |
| 1868 | ** <dt>SQLITE_CONFIG_PCACHE_HDRSZ |
| 1869 | ** <dd>^The SQLITE_CONFIG_PCACHE_HDRSZ option takes a single parameter which |
| 1870 | ** is a pointer to an integer and writes into that integer the number of extra |
| 1871 | ** bytes per page required for each page in [SQLITE_CONFIG_PAGECACHE]. The amount of |
| 1872 | ** extra space required can change depending on the compiler, |
| 1873 | ** target platform, and SQLite version. |
| 1874 | ** </dl> |
| 1875 | */ |
| 1876 | #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ |
| 1877 | #define SQLITE_CONFIG_MULTITHREAD 2 /* nil */ |
| 1878 | #define SQLITE_CONFIG_SERIALIZED 3 /* nil */ |
| @@ -1895,10 +1909,11 @@ | |
| 1895 | #define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */ |
| 1896 | #define SQLITE_CONFIG_SQLLOG 21 /* xSqllog, void* */ |
| 1897 | #define SQLITE_CONFIG_MMAP_SIZE 22 /* sqlite3_int64, sqlite3_int64 */ |
| 1898 | #define SQLITE_CONFIG_WIN32_HEAPSIZE 23 /* int nByte */ |
| 1899 | #define SQLITE_CONFIG_PCACHE_HDRSZ 24 /* int *psz */ |
| 1900 | |
| 1901 | /* |
| 1902 | ** CAPI3REF: Database Connection Configuration Options |
| 1903 | ** |
| 1904 | ** These constants are the available integer configuration options that |
| @@ -2171,10 +2186,11 @@ | |
| 2171 | SQLITE_API int sqlite3_complete(const char *sql); |
| 2172 | SQLITE_API int sqlite3_complete16(const void *sql); |
| 2173 | |
| 2174 | /* |
| 2175 | ** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors |
| 2176 | ** |
| 2177 | ** ^The sqlite3_busy_handler(D,X,P) routine sets a callback function X |
| 2178 | ** that might be invoked with argument P whenever |
| 2179 | ** an attempt is made to access a database table associated with |
| 2180 | ** [database connection] D when another thread |
| @@ -2187,11 +2203,11 @@ | |
| 2187 | ** is not NULL, then the callback might be invoked with two arguments. |
| 2188 | ** |
| 2189 | ** ^The first argument to the busy handler is a copy of the void* pointer which |
| 2190 | ** is the third argument to sqlite3_busy_handler(). ^The second argument to |
| 2191 | ** the busy handler callback is the number of times that the busy handler has |
| 2192 | ** been invoked for the same locking event. ^If the |
| 2193 | ** busy callback returns 0, then no additional attempts are made to |
| 2194 | ** access the database and [SQLITE_BUSY] is returned |
| 2195 | ** to the application. |
| 2196 | ** ^If the callback returns non-zero, then another attempt |
| 2197 | ** is made to access the database and the cycle repeats. |
| @@ -4642,11 +4658,12 @@ | |
| 4642 | ** If these routines are called from within the different thread |
| 4643 | ** than the one containing the application-defined function that received |
| 4644 | ** the [sqlite3_context] pointer, the results are undefined. |
| 4645 | */ |
| 4646 | SQLITE_API void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); |
| 4647 | SQLITE_API void sqlite3_result_blob64(sqlite3_context*,const void*,sqlite3_uint64,void(*)(void*)); |
| 4648 | SQLITE_API void sqlite3_result_double(sqlite3_context*, double); |
| 4649 | SQLITE_API void sqlite3_result_error(sqlite3_context*, const char*, int); |
| 4650 | SQLITE_API void sqlite3_result_error16(sqlite3_context*, const void*, int); |
| 4651 | SQLITE_API void sqlite3_result_error_toobig(sqlite3_context*); |
| 4652 | SQLITE_API void sqlite3_result_error_nomem(sqlite3_context*); |
| @@ -5274,24 +5291,31 @@ | |
| 5274 | |
| 5275 | |
| 5276 | /* |
| 5277 | ** CAPI3REF: Extract Metadata About A Column Of A Table |
| 5278 | ** |
| 5279 | ** ^This routine returns metadata about a specific column of a specific |
| 5280 | ** database table accessible using the [database connection] handle |
| 5281 | ** passed as the first function argument. |
| 5282 | ** |
| 5283 | ** ^The column is identified by the second, third and fourth parameters to |
| 5284 | ** this function. ^The second parameter is either the name of the database |
| 5285 | ** (i.e. "main", "temp", or an attached database) containing the specified |
| 5286 | ** table or NULL. ^If it is NULL, then all attached databases are searched |
| 5287 | ** for the table using the same algorithm used by the database engine to |
| 5288 | ** resolve unqualified table references. |
| 5289 | ** |
| 5290 | ** ^The third and fourth parameters to this function are the table and column |
| 5291 | ** name of the desired column, respectively. Neither of these parameters |
| 5292 | ** may be NULL. |
| 5293 | ** |
| 5294 | ** ^Metadata is returned by writing to the memory locations passed as the 5th |
| 5295 | ** and subsequent parameters to this function. ^Any of these arguments may be |
| 5296 | ** NULL, in which case the corresponding element of metadata is omitted. |
| 5297 | ** |
| @@ -5306,36 +5330,33 @@ | |
| 5306 | ** <tr><td> 9th <td> int <td> True if column is [AUTOINCREMENT] |
| 5307 | ** </table> |
| 5308 | ** </blockquote>)^ |
| 5309 | ** |
| 5310 | ** ^The memory pointed to by the character pointers returned for the |
| 5311 | ** declaration type and collation sequence is valid only until the next |
| 5312 | ** call to any SQLite API function. |
| 5313 | ** |
| 5314 | ** ^If the specified table is actually a view, an [error code] is returned. |
| 5315 | ** |
| 5316 | ** ^If the specified column is "rowid", "oid" or "_rowid_" and an |
| 5317 | ** [INTEGER PRIMARY KEY] column has been explicitly declared, then the output |
| 5318 | ** parameters are set for the explicitly declared column. ^(If there is no |
| 5319 | ** explicitly declared [INTEGER PRIMARY KEY] column, then the output |
| 5320 | ** parameters are set as follows: |
| 5321 | ** |
| 5322 | ** <pre> |
| 5323 | ** data type: "INTEGER" |
| 5324 | ** collation sequence: "BINARY" |
| 5325 | ** not null: 0 |
| 5326 | ** primary key: 1 |
| 5327 | ** auto increment: 0 |
| 5328 | ** </pre>)^ |
| 5329 | ** |
| 5330 | ** ^(This function may load one or more schemas from database files. If an |
| 5331 | ** error occurs during this process, or if the requested table or column |
| 5332 | ** cannot be found, an [error code] is returned and an error message left |
| 5333 | ** in the [database connection] (to be retrieved using sqlite3_errmsg()).)^ |
| 5334 | ** |
| 5335 | ** ^This API is only available if the library was compiled with the |
| 5336 | ** [SQLITE_ENABLE_COLUMN_METADATA] C-preprocessor symbol defined. |
| 5337 | */ |
| 5338 | SQLITE_API int sqlite3_table_column_metadata( |
| 5339 | sqlite3 *db, /* Connection handle */ |
| 5340 | const char *zDbName, /* Database name or NULL */ |
| 5341 | const char *zTableName, /* Table name */ |
| @@ -7298,16 +7319,14 @@ | |
| 7298 | |
| 7299 | /* |
| 7300 | ** CAPI3REF: Write-Ahead Log Commit Hook |
| 7301 | ** |
| 7302 | ** ^The [sqlite3_wal_hook()] function is used to register a callback that |
| 7303 | ** will be invoked each time a database connection commits data to a |
| 7304 | ** [write-ahead log] (i.e. whenever a transaction is committed in |
| 7305 | ** [journal_mode | journal_mode=WAL mode]). |
| 7306 | ** |
| 7307 | ** ^The callback is invoked by SQLite after the commit has taken place and |
| 7308 | ** the associated write-lock on the database released, so the implementation |
| 7309 | ** may read, write or [checkpoint] the database as required. |
| 7310 | ** |
| 7311 | ** ^The first parameter passed to the callback function when it is invoked |
| 7312 | ** is a copy of the third parameter passed to sqlite3_wal_hook() when |
| 7313 | ** registering the callback. ^The second is a copy of the database handle. |
| @@ -7368,101 +7387,118 @@ | |
| 7368 | SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N); |
| 7369 | |
| 7370 | /* |
| 7371 | ** CAPI3REF: Checkpoint a database |
| 7372 | ** |
| 7373 | ** ^The [sqlite3_wal_checkpoint(D,X)] interface causes database named X |
| 7374 | ** on [database connection] D to be [checkpointed]. ^If X is NULL or an |
| 7375 | ** empty string, then a checkpoint is run on all databases of |
| 7376 | ** connection D. ^If the database connection D is not in |
| 7377 | ** [WAL | write-ahead log mode] then this interface is a harmless no-op. |
| 7378 | ** ^The [sqlite3_wal_checkpoint(D,X)] interface initiates a |
| 7379 | ** [sqlite3_wal_checkpoint_v2|PASSIVE] checkpoint. |
| 7380 | ** Use the [sqlite3_wal_checkpoint_v2()] interface to get a FULL |
| 7381 | ** or RESET checkpoint. |
| 7382 | ** |
| 7383 | ** ^The [wal_checkpoint pragma] can be used to invoke this interface |
| 7384 | ** from SQL. ^The [sqlite3_wal_autocheckpoint()] interface and the |
| 7385 | ** [wal_autocheckpoint pragma] can be used to cause this interface to be |
| 7386 | ** run whenever the WAL reaches a certain size threshold. |
| 7387 | ** |
| 7388 | ** See also: [sqlite3_wal_checkpoint_v2()] |
| 7389 | */ |
| 7390 | SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb); |
| 7391 | |
| 7392 | /* |
| 7393 | ** CAPI3REF: Checkpoint a database |
| 7394 | ** |
| 7395 | ** Run a checkpoint operation on WAL database zDb attached to database |
| 7396 | ** handle db. The specific operation is determined by the value of the |
| 7397 | ** eMode parameter: |
| 7398 | ** |
| 7399 | ** <dl> |
| 7400 | ** <dt>SQLITE_CHECKPOINT_PASSIVE<dd> |
| 7401 | ** Checkpoint as many frames as possible without waiting for any database |
| 7402 | ** readers or writers to finish. Sync the db file if all frames in the log |
| 7403 | ** are checkpointed. This mode is the same as calling |
| 7404 | ** sqlite3_wal_checkpoint(). The [sqlite3_busy_handler|busy-handler callback] |
| 7405 | ** is never invoked. |
| 7406 | ** |
| 7407 | ** <dt>SQLITE_CHECKPOINT_FULL<dd> |
| 7408 | ** This mode blocks (it invokes the |
| 7409 | ** [sqlite3_busy_handler|busy-handler callback]) until there is no |
| 7410 | ** database writer and all readers are reading from the most recent database |
| 7411 | ** snapshot. It then checkpoints all frames in the log file and syncs the |
| 7412 | ** database file. This call blocks database writers while it is running, |
| 7413 | ** but not database readers. |
| 7414 | ** |
| 7415 | ** <dt>SQLITE_CHECKPOINT_RESTART<dd> |
| 7416 | ** This mode works the same way as SQLITE_CHECKPOINT_FULL, except after |
| 7417 | ** checkpointing the log file it blocks (calls the |
| 7418 | ** [sqlite3_busy_handler|busy-handler callback]) |
| 7419 | ** until all readers are reading from the database file only. This ensures |
| 7420 | ** that the next client to write to the database file restarts the log file |
| 7421 | ** from the beginning. This call blocks database writers while it is running, |
| 7422 | ** but not database readers. |
| 7423 | ** </dl> |
| 7424 | ** |
| 7425 | ** If pnLog is not NULL, then *pnLog is set to the total number of frames in |
| 7426 | ** the log file before returning. If pnCkpt is not NULL, then *pnCkpt is set to |
| 7427 | ** the total number of checkpointed frames (including any that were already |
| 7428 | ** checkpointed when this function is called). *pnLog and *pnCkpt may be |
| 7429 | ** populated even if sqlite3_wal_checkpoint_v2() returns other than SQLITE_OK. |
| 7430 | ** If no values are available because of an error, they are both set to -1 |
| 7431 | ** before returning to communicate this to the caller. |
| 7432 | ** |
| 7433 | ** All calls obtain an exclusive "checkpoint" lock on the database file. If |
| 7434 | ** any other process is running a checkpoint operation at the same time, the |
| 7435 | ** lock cannot be obtained and SQLITE_BUSY is returned. Even if there is a |
| 7436 | ** busy-handler configured, it will not be invoked in this case. |
| 7437 | ** |
| 7438 | ** The SQLITE_CHECKPOINT_FULL and RESTART modes also obtain the exclusive |
| 7439 | ** "writer" lock on the database file. If the writer lock cannot be obtained |
| 7440 | ** immediately, and a busy-handler is configured, it is invoked and the writer |
| 7441 | ** lock retried until either the busy-handler returns 0 or the lock is |
| 7442 | ** successfully obtained. The busy-handler is also invoked while waiting for |
| 7443 | ** database readers as described above. If the busy-handler returns 0 before |
| 7444 | ** the writer lock is obtained or while waiting for database readers, the |
| 7445 | ** checkpoint operation proceeds from that point in the same way as |
| 7446 | ** SQLITE_CHECKPOINT_PASSIVE - checkpointing as many frames as possible |
| 7447 | ** without blocking any further. SQLITE_BUSY is returned in this case. |
| 7448 | ** |
| 7449 | ** If parameter zDb is NULL or points to a zero length string, then the |
| 7450 | ** specified operation is attempted on all WAL databases. In this case the |
| 7451 | ** values written to output parameters *pnLog and *pnCkpt are undefined. If |
| 7452 | ** an SQLITE_BUSY error is encountered when processing one or more of the |
| 7453 | ** attached WAL databases, the operation is still attempted on any remaining |
| 7454 | ** attached databases and SQLITE_BUSY is returned to the caller. If any other |
| 7455 | ** error occurs while processing an attached database, processing is abandoned |
| 7456 | ** and the error code returned to the caller immediately. If no error |
| 7457 | ** (SQLITE_BUSY or otherwise) is encountered while processing the attached |
| 7458 | ** databases, SQLITE_OK is returned. |
| 7459 | ** |
| 7460 | ** If database zDb is the name of an attached database that is not in WAL |
| 7461 | ** mode, SQLITE_OK is returned and both *pnLog and *pnCkpt set to -1. If |
| 7462 | ** zDb is not NULL (or a zero length string) and is not the name of any |
| 7463 | ** attached database, SQLITE_ERROR is returned to the caller. |
| 7464 | */ |
| 7465 | SQLITE_API int sqlite3_wal_checkpoint_v2( |
| 7466 | sqlite3 *db, /* Database handle */ |
| 7467 | const char *zDb, /* Name of attached database (or NULL) */ |
| 7468 | int eMode, /* SQLITE_CHECKPOINT_* value */ |
| @@ -7469,20 +7505,22 @@ | |
| 7469 | int *pnLog, /* OUT: Size of WAL log in frames */ |
| 7470 | int *pnCkpt /* OUT: Total number of frames checkpointed */ |
| 7471 | ); |
| 7472 | |
| 7473 | /* |
| 7474 | ** CAPI3REF: Checkpoint operation parameters |
| 7475 | ** |
| 7476 | ** These constants can be used as the 3rd parameter to |
| 7477 | ** [sqlite3_wal_checkpoint_v2()]. See the [sqlite3_wal_checkpoint_v2()] |
| 7478 | ** documentation for additional information about the meaning and use of |
| 7479 | ** each of these values. |
| 7480 | */ |
| 7481 | #define SQLITE_CHECKPOINT_PASSIVE 0 |
| 7482 | #define SQLITE_CHECKPOINT_FULL 1 |
| 7483 | #define SQLITE_CHECKPOINT_RESTART 2 |
| 7484 | |
| 7485 | /* |
| 7486 | ** CAPI3REF: Virtual Table Interface Configuration |
| 7487 | ** |
| 7488 | ** This function may be called by either the [xConnect] or [xCreate] method |
| @@ -7577,16 +7615,16 @@ | |
| 7577 | ** [sqlite3_stmt_scanstatus(S,X,T,V)] interface. Each constant designates a |
| 7578 | ** different metric for sqlite3_stmt_scanstatus() to return. |
| 7579 | ** |
| 7580 | ** <dl> |
| 7581 | ** [[SQLITE_SCANSTAT_NLOOP]] <dt>SQLITE_SCANSTAT_NLOOP</dt> |
| 7582 | ** <dd>^The [sqlite3_int64] variable pointed to by the T parameter will be set to the |
| 7583 | ** total number of times that the X-th loop has run.</dd> |
| 7584 | ** |
| 7585 | ** [[SQLITE_SCANSTAT_NVISIT]] <dt>SQLITE_SCANSTAT_NVISIT</dt> |
| 7586 | ** <dd>^The [sqlite3_int64] variable pointed to by the T parameter will be set to the |
| 7587 | ** total number of rows examined by all iterations of the X-th loop.</dd> |
| 7588 | ** |
| 7589 | ** [[SQLITE_SCANSTAT_EST]] <dt>SQLITE_SCANSTAT_EST</dt> |
| 7590 | ** <dd>^The "double" variable pointed to by the T parameter will be set to the |
| 7591 | ** query planner's estimate for the average number of rows output from each |
| 7592 | ** iteration of the X-th loop. If the query planner's estimates was accurate, |
| @@ -7593,18 +7631,18 @@ | |
| 7593 | ** then this value will approximate the quotient NVISIT/NLOOP and the |
| 7594 | ** product of this value for all prior loops with the same SELECTID will |
| 7595 | ** be the NLOOP value for the current loop. |
| 7596 | ** |
| 7597 | ** [[SQLITE_SCANSTAT_NAME]] <dt>SQLITE_SCANSTAT_NAME</dt> |
| 7598 | ** <dd>^The "const char *" variable pointed to by the T parameter will be set to |
| 7599 | ** a zero-terminated UTF-8 string containing the name of the index or table used |
| 7600 | ** for the X-th loop. |
| 7601 | ** |
| 7602 | ** [[SQLITE_SCANSTAT_EXPLAIN]] <dt>SQLITE_SCANSTAT_EXPLAIN</dt> |
| 7603 | ** <dd>^The "const char *" variable pointed to by the T parameter will be set to |
| 7604 | ** a zero-terminated UTF-8 string containing the [EXPLAIN QUERY PLAN] description |
| 7605 | ** for the X-th loop. |
| 7606 | ** |
| 7607 | ** [[SQLITE_SCANSTAT_SELECTID]] <dt>SQLITE_SCANSTAT_SELECT</dt> |
| 7608 | ** <dd>^The "int" variable pointed to by the T parameter will be set to the |
| 7609 | ** "select-id" for the X-th loop. The select-id identifies which query or |
| 7610 | ** subquery the loop is part of. The main query has a select-id of zero. |
| @@ -7623,12 +7661,12 @@ | |
| 7623 | ** CAPI3REF: Prepared Statement Scan Status |
| 7624 | ** |
| 7625 | ** Return status data for a single loop within query pStmt. |
| 7626 | ** |
| 7627 | ** The "iScanStatusOp" parameter determines which status information to return. |
| 7628 | ** The "iScanStatusOp" must be one of the [scanstatus options] or the behavior of |
| 7629 | ** this interface is undefined. |
| 7630 | ** ^The requested measurement is written into a variable pointed to by |
| 7631 | ** the "pOut" parameter. |
| 7632 | ** Parameter "idx" identifies the specific loop to retrieve statistics for. |
| 7633 | ** Loops are numbered starting from zero. ^If idx is out of range - less than |
| 7634 | ** zero or greater than or equal to the total number of loops used to implement |
| @@ -9072,11 +9110,11 @@ | |
| 9072 | #define _BTREE_H_ |
| 9073 | |
| 9074 | /* TODO: This definition is just included so other modules compile. It |
| 9075 | ** needs to be revisited. |
| 9076 | */ |
| 9077 | #define SQLITE_N_BTREE_META 10 |
| 9078 | |
| 9079 | /* |
| 9080 | ** If defined as non-zero, auto-vacuum is enabled by default. Otherwise |
| 9081 | ** it must be turned on for each database using "PRAGMA auto_vacuum = 1". |
| 9082 | */ |
| @@ -9187,10 +9225,15 @@ | |
| 9187 | ** offset = 36 + (idx * 4) |
| 9188 | ** |
| 9189 | ** For example, the free-page-count field is located at byte offset 36 of |
| 9190 | ** the database file header. The incr-vacuum-flag field is located at |
| 9191 | ** byte offset 64 (== 36+4*7). |
| 9192 | */ |
| 9193 | #define BTREE_FREE_PAGE_COUNT 0 |
| 9194 | #define BTREE_SCHEMA_VERSION 1 |
| 9195 | #define BTREE_FILE_FORMAT 2 |
| 9196 | #define BTREE_DEFAULT_CACHE_SIZE 3 |
| @@ -9197,10 +9240,11 @@ | |
| 9197 | #define BTREE_LARGEST_ROOT_PAGE 4 |
| 9198 | #define BTREE_TEXT_ENCODING 5 |
| 9199 | #define BTREE_USER_VERSION 6 |
| 9200 | #define BTREE_INCR_VACUUM 7 |
| 9201 | #define BTREE_APPLICATION_ID 8 |
| 9202 | |
| 9203 | /* |
| 9204 | ** Values that may be OR'd together to form the second argument of an |
| 9205 | ** sqlite3BtreeCursorHints() call. |
| 9206 | */ |
| @@ -9978,10 +10022,11 @@ | |
| 9978 | SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager); |
| 9979 | #endif |
| 9980 | |
| 9981 | /* Functions used to query pager state and configuration. */ |
| 9982 | SQLITE_PRIVATE u8 sqlite3PagerIsreadonly(Pager*); |
| 9983 | SQLITE_PRIVATE int sqlite3PagerRefcount(Pager*); |
| 9984 | SQLITE_PRIVATE int sqlite3PagerMemUsed(Pager*); |
| 9985 | SQLITE_PRIVATE const char *sqlite3PagerFilename(Pager*, int); |
| 9986 | SQLITE_PRIVATE const sqlite3_vfs *sqlite3PagerVfs(Pager*); |
| 9987 | SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager*); |
| @@ -10719,10 +10764,11 @@ | |
| 10719 | i64 szMmap; /* Default mmap_size setting */ |
| 10720 | unsigned int openFlags; /* Flags passed to sqlite3_vfs.xOpen() */ |
| 10721 | int errCode; /* Most recent error code (SQLITE_*) */ |
| 10722 | int errMask; /* & result codes with this before returning */ |
| 10723 | u16 dbOptFlags; /* Flags to enable/disable optimizations */ |
| 10724 | u8 autoCommit; /* The auto-commit flag. */ |
| 10725 | u8 temp_store; /* 1: file 2: memory 0: default */ |
| 10726 | u8 mallocFailed; /* True if we have seen a malloc failure */ |
| 10727 | u8 dfltLockMode; /* Default locking-mode for attached dbs */ |
| 10728 | signed char nextAutovac; /* Autovac setting after VACUUM if >=0 */ |
| @@ -10820,11 +10866,12 @@ | |
| 10820 | }; |
| 10821 | |
| 10822 | /* |
| 10823 | ** A macro to discover the encoding of a database. |
| 10824 | */ |
| 10825 | #define ENC(db) ((db)->aDb[0].pSchema->enc) |
| 10826 | |
| 10827 | /* |
| 10828 | ** Possible values for the sqlite3.flags. |
| 10829 | */ |
| 10830 | #define SQLITE_VdbeTrace 0x00000001 /* True to trace VDBE execution */ |
| @@ -11444,11 +11491,10 @@ | |
| 11444 | Index *pNext; /* The next index associated with the same table */ |
| 11445 | Schema *pSchema; /* Schema containing this index */ |
| 11446 | u8 *aSortOrder; /* for each column: True==DESC, False==ASC */ |
| 11447 | char **azColl; /* Array of collation sequence names for index */ |
| 11448 | Expr *pPartIdxWhere; /* WHERE clause for partial indices */ |
| 11449 | KeyInfo *pKeyInfo; /* A KeyInfo object suitable for this index */ |
| 11450 | int tnum; /* DB Page containing root of this index */ |
| 11451 | LogEst szIdxRow; /* Estimated average row size in bytes */ |
| 11452 | u16 nKeyCol; /* Number of columns forming the key */ |
| 11453 | u16 nColumn; /* Number of columns stored in the index */ |
| 11454 | u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ |
| @@ -11675,11 +11721,11 @@ | |
| 11675 | }; |
| 11676 | |
| 11677 | /* |
| 11678 | ** The following are the meanings of bits in the Expr.flags field. |
| 11679 | */ |
| 11680 | #define EP_FromJoin 0x000001 /* Originated in ON or USING clause of a join */ |
| 11681 | #define EP_Agg 0x000002 /* Contains one or more aggregate functions */ |
| 11682 | #define EP_Resolved 0x000004 /* IDs have been resolved to COLUMNs */ |
| 11683 | #define EP_Error 0x000008 /* Expression contains one or more errors */ |
| 11684 | #define EP_Distinct 0x000010 /* Aggregate function with DISTINCT keyword */ |
| 11685 | #define EP_VarSelect 0x000020 /* pSelect is correlated, not constant */ |
| @@ -11695,10 +11741,11 @@ | |
| 11695 | #define EP_Static 0x008000 /* Held in memory not obtained from malloc() */ |
| 11696 | #define EP_MemToken 0x010000 /* Need to sqlite3DbFree() Expr.zToken */ |
| 11697 | #define EP_NoReduce 0x020000 /* Cannot EXPRDUP_REDUCE this Expr */ |
| 11698 | #define EP_Unlikely 0x040000 /* unlikely() or likelihood() function */ |
| 11699 | #define EP_Constant 0x080000 /* Node is a constant */ |
| 11700 | |
| 11701 | /* |
| 11702 | ** These macros can be used to test, set, or clear bits in the |
| 11703 | ** Expr.flags field. |
| 11704 | */ |
| @@ -12497,10 +12544,11 @@ | |
| 12497 | void *pPage; /* Page cache memory */ |
| 12498 | int szPage; /* Size of each page in pPage[] */ |
| 12499 | int nPage; /* Number of pages in pPage[] */ |
| 12500 | int mxParserStack; /* maximum depth of the parser stack */ |
| 12501 | int sharedCacheEnabled; /* true if shared-cache mode enabled */ |
| 12502 | /* The above might be initialized to non-zero. The following need to always |
| 12503 | ** initially be zero, however. */ |
| 12504 | int isInit; /* True after initialization has finished */ |
| 12505 | int inProgress; /* True while initialization in progress */ |
| 12506 | int isMutexInit; /* True after mutexes are initialized */ |
| @@ -13419,11 +13467,11 @@ | |
| 13419 | ** print I/O tracing messages. |
| 13420 | */ |
| 13421 | #ifdef SQLITE_ENABLE_IOTRACE |
| 13422 | # define IOTRACE(A) if( sqlite3IoTrace ){ sqlite3IoTrace A; } |
| 13423 | SQLITE_PRIVATE void sqlite3VdbeIOTraceSql(Vdbe*); |
| 13424 | SQLITE_PRIVATE void (*sqlite3IoTrace)(const char*,...); |
| 13425 | #else |
| 13426 | # define IOTRACE(A) |
| 13427 | # define sqlite3VdbeIOTraceSql(X) |
| 13428 | #endif |
| 13429 | |
| @@ -13632,10 +13680,17 @@ | |
| 13632 | */ |
| 13633 | #ifndef SQLITE_ALLOW_COVERING_INDEX_SCAN |
| 13634 | # define SQLITE_ALLOW_COVERING_INDEX_SCAN 1 |
| 13635 | #endif |
| 13636 | |
| 13637 | /* |
| 13638 | ** The following singleton contains the global configuration for |
| 13639 | ** the SQLite library. |
| 13640 | */ |
| 13641 | SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = { |
| @@ -13662,10 +13717,11 @@ | |
| 13662 | (void*)0, /* pPage */ |
| 13663 | 0, /* szPage */ |
| 13664 | 0, /* nPage */ |
| 13665 | 0, /* mxParserStack */ |
| 13666 | 0, /* sharedCacheEnabled */ |
| 13667 | /* All the rest should always be initialized to zero */ |
| 13668 | 0, /* isInit */ |
| 13669 | 0, /* inProgress */ |
| 13670 | 0, /* isMutexInit */ |
| 13671 | 0, /* isMallocInit */ |
| @@ -19947,10 +20003,16 @@ | |
| 19947 | #endif |
| 19948 | } |
| 19949 | break; |
| 19950 | } |
| 19951 | default: { |
| 19952 | assert( iType-2 >= 0 ); |
| 19953 | assert( iType-2 < ArraySize(winMutex_staticMutexes) ); |
| 19954 | assert( winMutex_isInit==1 ); |
| 19955 | p = &winMutex_staticMutexes[iType-2]; |
| 19956 | #ifdef SQLITE_DEBUG |
| @@ -28754,28 +28816,31 @@ | |
| 28754 | do{ |
| 28755 | err = osFallocate(pFile->h, buf.st_size, nSize-buf.st_size); |
| 28756 | }while( err==EINTR ); |
| 28757 | if( err ) return SQLITE_IOERR_WRITE; |
| 28758 | #else |
| 28759 | /* If the OS does not have posix_fallocate(), fake it. First use |
| 28760 | ** ftruncate() to set the file size, then write a single byte to |
| 28761 | ** the last byte in each block within the extended region. This |
| 28762 | ** is the same technique used by glibc to implement posix_fallocate() |
| 28763 | ** on systems that do not have a real fallocate() system call. |
| 28764 | */ |
| 28765 | int nBlk = buf.st_blksize; /* File-system block size */ |
| 28766 | i64 iWrite; /* Next offset to write to */ |
| 28767 | |
| 28768 | if( robust_ftruncate(pFile->h, nSize) ){ |
| 28769 | pFile->lastErrno = errno; |
| 28770 | return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath); |
| 28771 | } |
| 28772 | iWrite = ((buf.st_size + 2*nBlk - 1)/nBlk)*nBlk-1; |
| 28773 | while( iWrite<nSize ){ |
| 28774 | int nWrite = seekAndWrite(pFile, iWrite, "", 1); |
| 28775 | if( nWrite!=1 ) return SQLITE_IOERR_WRITE; |
| 28776 | iWrite += nBlk; |
| 28777 | } |
| 28778 | #endif |
| 28779 | } |
| 28780 | } |
| 28781 | |
| @@ -33989,12 +34054,12 @@ | |
| 33989 | */ |
| 33990 | SQLITE_API int sqlite3_win32_reset_heap(){ |
| 33991 | int rc; |
| 33992 | MUTEX_LOGIC( sqlite3_mutex *pMaster; ) /* The main static mutex */ |
| 33993 | MUTEX_LOGIC( sqlite3_mutex *pMem; ) /* The memsys static mutex */ |
| 33994 | MUTEX_LOGIC( pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); ) |
| 33995 | MUTEX_LOGIC( pMem = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM); ) |
| 33996 | sqlite3_mutex_enter(pMaster); |
| 33997 | sqlite3_mutex_enter(pMem); |
| 33998 | winMemAssertMagic(); |
| 33999 | if( winMemGetHeap()!=NULL && winMemGetOwned() && sqlite3_memory_used()==0 ){ |
| 34000 | /* |
| @@ -35265,11 +35330,11 @@ | |
| 35265 | sqlite3_file *id, /* File to read from */ |
| 35266 | void *pBuf, /* Write content into this buffer */ |
| 35267 | int amt, /* Number of bytes to read */ |
| 35268 | sqlite3_int64 offset /* Begin reading at this offset */ |
| 35269 | ){ |
| 35270 | #if !SQLITE_OS_WINCE |
| 35271 | OVERLAPPED overlapped; /* The offset for ReadFile. */ |
| 35272 | #endif |
| 35273 | winFile *pFile = (winFile*)id; /* file handle */ |
| 35274 | DWORD nRead; /* Number of bytes actually read from file */ |
| 35275 | int nRetry = 0; /* Number of retrys */ |
| @@ -35297,11 +35362,11 @@ | |
| 35297 | offset += nCopy; |
| 35298 | } |
| 35299 | } |
| 35300 | #endif |
| 35301 | |
| 35302 | #if SQLITE_OS_WINCE |
| 35303 | if( winSeekFile(pFile, offset) ){ |
| 35304 | OSTRACE(("READ file=%p, rc=SQLITE_FULL\n", pFile->h)); |
| 35305 | return SQLITE_FULL; |
| 35306 | } |
| 35307 | while( !osReadFile(pFile->h, pBuf, amt, &nRead, 0) ){ |
| @@ -35369,32 +35434,32 @@ | |
| 35369 | offset += nCopy; |
| 35370 | } |
| 35371 | } |
| 35372 | #endif |
| 35373 | |
| 35374 | #if SQLITE_OS_WINCE |
| 35375 | rc = winSeekFile(pFile, offset); |
| 35376 | if( rc==0 ){ |
| 35377 | #else |
| 35378 | { |
| 35379 | #endif |
| 35380 | #if !SQLITE_OS_WINCE |
| 35381 | OVERLAPPED overlapped; /* The offset for WriteFile. */ |
| 35382 | #endif |
| 35383 | u8 *aRem = (u8 *)pBuf; /* Data yet to be written */ |
| 35384 | int nRem = amt; /* Number of bytes yet to be written */ |
| 35385 | DWORD nWrite; /* Bytes written by each WriteFile() call */ |
| 35386 | DWORD lastErrno = NO_ERROR; /* Value returned by GetLastError() */ |
| 35387 | |
| 35388 | #if !SQLITE_OS_WINCE |
| 35389 | memset(&overlapped, 0, sizeof(OVERLAPPED)); |
| 35390 | overlapped.Offset = (LONG)(offset & 0xffffffff); |
| 35391 | overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff); |
| 35392 | #endif |
| 35393 | |
| 35394 | while( nRem>0 ){ |
| 35395 | #if SQLITE_OS_WINCE |
| 35396 | if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, 0) ){ |
| 35397 | #else |
| 35398 | if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, &overlapped) ){ |
| 35399 | #endif |
| 35400 | if( winRetryIoerr(&nRetry, &lastErrno) ) continue; |
| @@ -35403,11 +35468,11 @@ | |
| 35403 | assert( nWrite==0 || nWrite<=(DWORD)nRem ); |
| 35404 | if( nWrite==0 || nWrite>(DWORD)nRem ){ |
| 35405 | lastErrno = osGetLastError(); |
| 35406 | break; |
| 35407 | } |
| 35408 | #if !SQLITE_OS_WINCE |
| 35409 | offset += nWrite; |
| 35410 | overlapped.Offset = (LONG)(offset & 0xffffffff); |
| 35411 | overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff); |
| 35412 | #endif |
| 35413 | aRem += nWrite; |
| @@ -38949,11 +39014,12 @@ | |
| 38949 | SQLITE_PRIVATE int sqlite3PcacheSetPageSize(PCache *pCache, int szPage){ |
| 38950 | assert( pCache->nRef==0 && pCache->pDirty==0 ); |
| 38951 | if( pCache->szPage ){ |
| 38952 | sqlite3_pcache *pNew; |
| 38953 | pNew = sqlite3GlobalConfig.pcache2.xCreate( |
| 38954 | szPage, pCache->szExtra + sizeof(PgHdr), pCache->bPurgeable |
| 38955 | ); |
| 38956 | if( pNew==0 ) return SQLITE_NOMEM; |
| 38957 | sqlite3GlobalConfig.pcache2.xCachesize(pNew, numberOfCachePages(pCache)); |
| 38958 | if( pCache->pCache ){ |
| 38959 | sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache); |
| @@ -39408,11 +39474,11 @@ | |
| 39408 | |
| 39409 | /* |
| 39410 | ** Return the size of the header added by this middleware layer |
| 39411 | ** in the page-cache hierarchy. |
| 39412 | */ |
| 39413 | SQLITE_PRIVATE int sqlite3HeaderSizePcache(void){ return sizeof(PgHdr); } |
| 39414 | |
| 39415 | |
| 39416 | #if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG) |
| 39417 | /* |
| 39418 | ** For all dirty pages currently in the cache, invoke the specified |
| @@ -39724,11 +39790,11 @@ | |
| 39724 | pcache1Free(pPg); |
| 39725 | sqlite3_free(p); |
| 39726 | pPg = 0; |
| 39727 | } |
| 39728 | #else |
| 39729 | pPg = pcache1Alloc(sizeof(PgHdr1) + pCache->szPage + pCache->szExtra); |
| 39730 | p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage]; |
| 39731 | #endif |
| 39732 | pcache1EnterMutex(pCache->pGroup); |
| 39733 | |
| 39734 | if( pPg ){ |
| @@ -40412,11 +40478,11 @@ | |
| 40412 | } |
| 40413 | |
| 40414 | /* |
| 40415 | ** Return the size of the header on each page of this PCACHE implementation. |
| 40416 | */ |
| 40417 | SQLITE_PRIVATE int sqlite3HeaderSizePcache1(void){ return sizeof(PgHdr1); } |
| 40418 | |
| 40419 | #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT |
| 40420 | /* |
| 40421 | ** This function is called to free superfluous dynamically allocated memory |
| 40422 | ** held by the pager system. Memory in use by any SQLite pager allocated |
| @@ -41770,10 +41836,12 @@ | |
| 41770 | u8 eLock; /* Current lock held on database file */ |
| 41771 | u8 changeCountDone; /* Set after incrementing the change-counter */ |
| 41772 | u8 setMaster; /* True if a m-j name has been written to jrnl */ |
| 41773 | u8 doNotSpill; /* Do not spill the cache when non-zero */ |
| 41774 | u8 subjInMemory; /* True to use in-memory sub-journals */ |
| 41775 | Pgno dbSize; /* Number of pages in the database */ |
| 41776 | Pgno dbOrigSize; /* dbSize before the current transaction */ |
| 41777 | Pgno dbFileSize; /* Number of pages in the database file */ |
| 41778 | Pgno dbHintSize; /* Value passed to FCNTL_SIZE_HINT call */ |
| 41779 | int errCode; /* One of several kinds of errors */ |
| @@ -41787,13 +41855,13 @@ | |
| 41787 | i64 journalOff; /* Current write offset in the journal file */ |
| 41788 | i64 journalHdr; /* Byte offset to previous journal header */ |
| 41789 | sqlite3_backup *pBackup; /* Pointer to list of ongoing backup processes */ |
| 41790 | PagerSavepoint *aSavepoint; /* Array of active savepoints */ |
| 41791 | int nSavepoint; /* Number of elements in aSavepoint[] */ |
| 41792 | char dbFileVers[16]; /* Changes whenever database file changes */ |
| 41793 | |
| 41794 | u8 bUseFetch; /* True to use xFetch() */ |
| 41795 | int nMmapOut; /* Number of mmap pages currently outstanding */ |
| 41796 | sqlite3_int64 szMmap; /* Desired maximum mmap size */ |
| 41797 | PgHdr *pMmapFreelist; /* List of free mmap page headers (pDirty) */ |
| 41798 | /* |
| 41799 | ** End of the routinely-changing class members |
| @@ -42805,13 +42873,22 @@ | |
| 42805 | |
| 42806 | /* |
| 42807 | ** Discard the entire contents of the in-memory page-cache. |
| 42808 | */ |
| 42809 | static void pager_reset(Pager *pPager){ |
| 42810 | sqlite3BackupRestart(pPager->pBackup); |
| 42811 | sqlite3PcacheClear(pPager->pPCache); |
| 42812 | } |
| 42813 | |
| 42814 | /* |
| 42815 | ** Free all structures in the Pager.aSavepoint[] array and set both |
| 42816 | ** Pager.aSavepoint and Pager.nSavepoint to zero. Close the sub-journal |
| 42817 | ** if it is open and the pager is not in exclusive mode. |
| @@ -45011,11 +45088,11 @@ | |
| 45011 | Pgno pgno, /* Page number */ |
| 45012 | void *pData, /* xFetch()'d data for this page */ |
| 45013 | PgHdr **ppPage /* OUT: Acquired page object */ |
| 45014 | ){ |
| 45015 | PgHdr *p; /* Memory mapped page to return */ |
| 45016 | |
| 45017 | if( pPager->pMmapFreelist ){ |
| 45018 | *ppPage = p = pPager->pMmapFreelist; |
| 45019 | pPager->pMmapFreelist = p->pDirty; |
| 45020 | p->pDirty = 0; |
| 45021 | memset(p->pExtra, 0, pPager->nExtra); |
| @@ -46242,20 +46319,16 @@ | |
| 46242 | assert( (pPager->eLock==SHARED_LOCK) |
| 46243 | || (pPager->exclusiveMode && pPager->eLock>SHARED_LOCK) |
| 46244 | ); |
| 46245 | } |
| 46246 | |
| 46247 | if( !pPager->tempFile && ( |
| 46248 | pPager->pBackup |
| 46249 | || sqlite3PcachePagecount(pPager->pPCache)>0 |
| 46250 | || USEFETCH(pPager) |
| 46251 | )){ |
| 46252 | /* The shared-lock has just been acquired on the database file |
| 46253 | ** and there are already pages in the cache (from a previous |
| 46254 | ** read or write transaction). Check to see if the database |
| 46255 | ** has been modified. If the database has changed, flush the |
| 46256 | ** cache. |
| 46257 | ** |
| 46258 | ** Database changes is detected by looking at 15 bytes beginning |
| 46259 | ** at offset 24 into the file. The first 4 of these 16 bytes are |
| 46260 | ** a 32-bit counter that is incremented with each change. The |
| 46261 | ** other bytes change randomly with each file change when |
| @@ -46416,10 +46489,11 @@ | |
| 46416 | assert( noContent==0 || bMmapOk==0 ); |
| 46417 | |
| 46418 | if( pgno==0 ){ |
| 46419 | return SQLITE_CORRUPT_BKPT; |
| 46420 | } |
| 46421 | |
| 46422 | /* If the pager is in the error state, return an error immediately. |
| 46423 | ** Otherwise, request the page from the PCache layer. */ |
| 46424 | if( pPager->errCode!=SQLITE_OK ){ |
| 46425 | rc = pPager->errCode; |
| @@ -46565,10 +46639,11 @@ | |
| 46565 | sqlite3_pcache_page *pPage; |
| 46566 | assert( pPager!=0 ); |
| 46567 | assert( pgno!=0 ); |
| 46568 | assert( pPager->pPCache!=0 ); |
| 46569 | pPage = sqlite3PcacheFetch(pPager->pPCache, pgno, 0); |
| 46570 | return sqlite3PcacheFetchFinish(pPager->pPCache, pgno, pPage); |
| 46571 | } |
| 46572 | |
| 46573 | /* |
| 46574 | ** Release a page reference. |
| @@ -47431,10 +47506,11 @@ | |
| 47431 | pPager->eState = PAGER_READER; |
| 47432 | return SQLITE_OK; |
| 47433 | } |
| 47434 | |
| 47435 | PAGERTRACE(("COMMIT %d\n", PAGERID(pPager))); |
| 47436 | rc = pager_end_transaction(pPager, pPager->setMaster, 1); |
| 47437 | return pager_error(pPager, rc); |
| 47438 | } |
| 47439 | |
| 47440 | /* |
| @@ -48199,11 +48275,12 @@ | |
| 48199 | */ |
| 48200 | SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, int eMode, int *pnLog, int *pnCkpt){ |
| 48201 | int rc = SQLITE_OK; |
| 48202 | if( pPager->pWal ){ |
| 48203 | rc = sqlite3WalCheckpoint(pPager->pWal, eMode, |
| 48204 | pPager->xBusyHandler, pPager->pBusyHandlerArg, |
| 48205 | pPager->ckptSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace, |
| 48206 | pnLog, pnCkpt |
| 48207 | ); |
| 48208 | } |
| 48209 | return rc; |
| @@ -50009,10 +50086,42 @@ | |
| 50009 | ** Return the page-size in bytes used by the database. |
| 50010 | */ |
| 50011 | static int walPagesize(Wal *pWal){ |
| 50012 | return (pWal->hdr.szPage&0xfe00) + ((pWal->hdr.szPage&0x0001)<<16); |
| 50013 | } |
| 50014 | |
| 50015 | /* |
| 50016 | ** Copy as much content as we can from the WAL back into the database file |
| 50017 | ** in response to an sqlite3_wal_checkpoint() request or the equivalent. |
| 50018 | ** |
| @@ -50044,11 +50153,11 @@ | |
| 50044 | ** time. |
| 50045 | */ |
| 50046 | static int walCheckpoint( |
| 50047 | Wal *pWal, /* Wal connection */ |
| 50048 | int eMode, /* One of PASSIVE, FULL or RESTART */ |
| 50049 | int (*xBusyCall)(void*), /* Function to call when busy */ |
| 50050 | void *pBusyArg, /* Context argument for xBusyHandler */ |
| 50051 | int sync_flags, /* Flags for OsSync() (or 0) */ |
| 50052 | u8 *zBuf /* Temporary buffer to use */ |
| 50053 | ){ |
| 50054 | int rc; /* Return code */ |
| @@ -50058,11 +50167,10 @@ | |
| 50058 | u32 iFrame = 0; /* Wal frame containing data for iDbpage */ |
| 50059 | u32 mxSafeFrame; /* Max frame that can be backfilled */ |
| 50060 | u32 mxPage; /* Max database page to write */ |
| 50061 | int i; /* Loop counter */ |
| 50062 | volatile WalCkptInfo *pInfo; /* The checkpoint status information */ |
| 50063 | int (*xBusy)(void*) = 0; /* Function to call when waiting for locks */ |
| 50064 | |
| 50065 | szPage = walPagesize(pWal); |
| 50066 | testcase( szPage<=32768 ); |
| 50067 | testcase( szPage>=65536 ); |
| 50068 | pInfo = walCkptInfo(pWal); |
| @@ -50073,11 +50181,13 @@ | |
| 50073 | if( rc!=SQLITE_OK ){ |
| 50074 | return rc; |
| 50075 | } |
| 50076 | assert( pIter ); |
| 50077 | |
| 50078 | if( eMode!=SQLITE_CHECKPOINT_PASSIVE ) xBusy = xBusyCall; |
| 50079 | |
| 50080 | /* Compute in mxSafeFrame the index of the last frame of the WAL that is |
| 50081 | ** safe to write into the database. Frames beyond mxSafeFrame might |
| 50082 | ** overwrite database pages that are in use by active readers and thus |
| 50083 | ** cannot be backfilled from the WAL. |
| @@ -50162,23 +50272,42 @@ | |
| 50162 | /* Reset the return code so as not to report a checkpoint failure |
| 50163 | ** just because there are active readers. */ |
| 50164 | rc = SQLITE_OK; |
| 50165 | } |
| 50166 | |
| 50167 | /* If this is an SQLITE_CHECKPOINT_RESTART operation, and the entire wal |
| 50168 | ** file has been copied into the database file, then block until all |
| 50169 | ** readers have finished using the wal file. This ensures that the next |
| 50170 | ** process to write to the database restarts the wal file. |
| 50171 | */ |
| 50172 | if( rc==SQLITE_OK && eMode!=SQLITE_CHECKPOINT_PASSIVE ){ |
| 50173 | assert( pWal->writeLock ); |
| 50174 | if( pInfo->nBackfill<pWal->hdr.mxFrame ){ |
| 50175 | rc = SQLITE_BUSY; |
| 50176 | }else if( eMode==SQLITE_CHECKPOINT_RESTART ){ |
| 50177 | assert( mxSafeFrame==pWal->hdr.mxFrame ); |
| 50178 | rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(1), WAL_NREADER-1); |
| 50179 | if( rc==SQLITE_OK ){ |
| 50180 | walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1); |
| 50181 | } |
| 50182 | } |
| 50183 | } |
| 50184 | |
| @@ -50747,11 +50876,11 @@ | |
| 50747 | } |
| 50748 | nCollide = HASHTABLE_NSLOT; |
| 50749 | for(iKey=walHash(pgno); aHash[iKey]; iKey=walNextHash(iKey)){ |
| 50750 | u32 iFrame = aHash[iKey] + iZero; |
| 50751 | if( iFrame<=iLast && aPgno[aHash[iKey]]==pgno ){ |
| 50752 | /* assert( iFrame>iRead ); -- not true if there is corruption */ |
| 50753 | iRead = iFrame; |
| 50754 | } |
| 50755 | if( (nCollide--)==0 ){ |
| 50756 | return SQLITE_CORRUPT_BKPT; |
| 50757 | } |
| @@ -50960,11 +51089,10 @@ | |
| 50960 | } |
| 50961 | |
| 50962 | return rc; |
| 50963 | } |
| 50964 | |
| 50965 | |
| 50966 | /* |
| 50967 | ** This function is called just before writing a set of frames to the log |
| 50968 | ** file (see sqlite3WalFrames()). It checks to see if, instead of appending |
| 50969 | ** to the current log file, it is possible to overwrite the start of the |
| 50970 | ** existing log file with the new frames (i.e. "reset" the log). If so, |
| @@ -50993,24 +51121,12 @@ | |
| 50993 | ** wal-index header to reflect this. |
| 50994 | ** |
| 50995 | ** In theory it would be Ok to update the cache of the header only |
| 50996 | ** at this point. But updating the actual wal-index header is also |
| 50997 | ** safe and means there is no special case for sqlite3WalUndo() |
| 50998 | ** to handle if this transaction is rolled back. |
| 50999 | */ |
| 51000 | int i; /* Loop counter */ |
| 51001 | u32 *aSalt = pWal->hdr.aSalt; /* Big-endian salt values */ |
| 51002 | |
| 51003 | pWal->nCkpt++; |
| 51004 | pWal->hdr.mxFrame = 0; |
| 51005 | sqlite3Put4byte((u8*)&aSalt[0], 1 + sqlite3Get4byte((u8*)&aSalt[0])); |
| 51006 | aSalt[1] = salt1; |
| 51007 | walIndexWriteHdr(pWal); |
| 51008 | pInfo->nBackfill = 0; |
| 51009 | pInfo->aReadMark[1] = 0; |
| 51010 | for(i=2; i<WAL_NREADER; i++) pInfo->aReadMark[i] = READMARK_NOT_USED; |
| 51011 | assert( pInfo->aReadMark[0]==0 ); |
| 51012 | walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1); |
| 51013 | }else if( rc!=SQLITE_BUSY ){ |
| 51014 | return rc; |
| 51015 | } |
| 51016 | } |
| @@ -51294,11 +51410,11 @@ | |
| 51294 | ** If parameter xBusy is not NULL, it is a pointer to a busy-handler |
| 51295 | ** callback. In this case this function runs a blocking checkpoint. |
| 51296 | */ |
| 51297 | SQLITE_PRIVATE int sqlite3WalCheckpoint( |
| 51298 | Wal *pWal, /* Wal connection */ |
| 51299 | int eMode, /* PASSIVE, FULL or RESTART */ |
| 51300 | int (*xBusy)(void*), /* Function to call when busy */ |
| 51301 | void *pBusyArg, /* Context argument for xBusyHandler */ |
| 51302 | int sync_flags, /* Flags to sync db file with (or 0) */ |
| 51303 | int nBuf, /* Size of temporary buffer */ |
| 51304 | u8 *zBuf, /* Temporary buffer to use */ |
| @@ -51306,40 +51422,54 @@ | |
| 51306 | int *pnCkpt /* OUT: Number of backfilled frames in WAL */ |
| 51307 | ){ |
| 51308 | int rc; /* Return code */ |
| 51309 | int isChanged = 0; /* True if a new wal-index header is loaded */ |
| 51310 | int eMode2 = eMode; /* Mode to pass to walCheckpoint() */ |
| 51311 | |
| 51312 | assert( pWal->ckptLock==0 ); |
| 51313 | assert( pWal->writeLock==0 ); |
| 51314 | |
| 51315 | if( pWal->readOnly ) return SQLITE_READONLY; |
| 51316 | WALTRACE(("WAL%p: checkpoint begins\n", pWal)); |
| 51317 | rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1); |
| 51318 | if( rc ){ |
| 51319 | /* Usually this is SQLITE_BUSY meaning that another thread or process |
| 51320 | ** is already running a checkpoint, or maybe a recovery. But it might |
| 51321 | ** also be SQLITE_IOERR. */ |
| 51322 | return rc; |
| 51323 | } |
| 51324 | pWal->ckptLock = 1; |
| 51325 | |
| 51326 | /* If this is a blocking-checkpoint, then obtain the write-lock as well |
| 51327 | ** to prevent any writers from running while the checkpoint is underway. |
| 51328 | ** This has to be done before the call to walIndexReadHdr() below. |
| 51329 | ** |
| 51330 | ** If the writer lock cannot be obtained, then a passive checkpoint is |
| 51331 | ** run instead. Since the checkpointer is not holding the writer lock, |
| 51332 | ** there is no point in blocking waiting for any readers. Assuming no |
| 51333 | ** other error occurs, this function will return SQLITE_BUSY to the caller. |
| 51334 | */ |
| 51335 | if( eMode!=SQLITE_CHECKPOINT_PASSIVE ){ |
| 51336 | rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_WRITE_LOCK, 1); |
| 51337 | if( rc==SQLITE_OK ){ |
| 51338 | pWal->writeLock = 1; |
| 51339 | }else if( rc==SQLITE_BUSY ){ |
| 51340 | eMode2 = SQLITE_CHECKPOINT_PASSIVE; |
| 51341 | rc = SQLITE_OK; |
| 51342 | } |
| 51343 | } |
| 51344 | |
| 51345 | /* Read the wal-index header. */ |
| @@ -51353,11 +51483,11 @@ | |
| 51353 | /* Copy data from the log to the database file. */ |
| 51354 | if( rc==SQLITE_OK ){ |
| 51355 | if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){ |
| 51356 | rc = SQLITE_CORRUPT_BKPT; |
| 51357 | }else{ |
| 51358 | rc = walCheckpoint(pWal, eMode2, xBusy, pBusyArg, sync_flags, zBuf); |
| 51359 | } |
| 51360 | |
| 51361 | /* If no error occurred, set the output variables. */ |
| 51362 | if( rc==SQLITE_OK || rc==SQLITE_BUSY ){ |
| 51363 | if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame; |
| @@ -51852,10 +51982,11 @@ | |
| 51852 | u8 inTrans; /* TRANS_NONE, TRANS_READ or TRANS_WRITE */ |
| 51853 | u8 sharable; /* True if we can share pBt with another db */ |
| 51854 | u8 locked; /* True if db currently has pBt locked */ |
| 51855 | int wantToLock; /* Number of nested calls to sqlite3BtreeEnter() */ |
| 51856 | int nBackup; /* Number of backup operations reading this btree */ |
| 51857 | Btree *pNext; /* List of other sharable Btrees from the same db */ |
| 51858 | Btree *pPrev; /* Back pointer of the same list */ |
| 51859 | #ifndef SQLITE_OMIT_SHARED_CACHE |
| 51860 | BtLock lock; /* Object used to lock page 1 */ |
| 51861 | #endif |
| @@ -53821,11 +53952,11 @@ | |
| 53821 | ** to see if defragmentation is necessary. |
| 53822 | */ |
| 53823 | testcase( gap+2+nByte==top ); |
| 53824 | if( gap+2+nByte>top ){ |
| 53825 | defragment_page: |
| 53826 | testcase( pPage->nCell==0 ); |
| 53827 | rc = defragmentPage(pPage); |
| 53828 | if( rc ) return rc; |
| 53829 | top = get2byteNotZero(&data[hdr+5]); |
| 53830 | assert( gap+nByte<=top ); |
| 53831 | } |
| @@ -56015,10 +56146,11 @@ | |
| 56015 | rc = sqlite3PagerCommitPhaseTwo(pBt->pPager); |
| 56016 | if( rc!=SQLITE_OK && bCleanup==0 ){ |
| 56017 | sqlite3BtreeLeave(p); |
| 56018 | return rc; |
| 56019 | } |
| 56020 | pBt->inTransaction = TRANS_READ; |
| 56021 | btreeClearHasContent(pBt); |
| 56022 | } |
| 56023 | |
| 56024 | btreeEndTransaction(p); |
| @@ -56378,11 +56510,11 @@ | |
| 56378 | } |
| 56379 | for(i=0; i<=pCur->iPage; i++){ |
| 56380 | releasePage(pCur->apPage[i]); |
| 56381 | } |
| 56382 | unlockBtreeIfUnused(pBt); |
| 56383 | sqlite3DbFree(pBtree->db, pCur->aOverflow); |
| 56384 | /* sqlite3_free(pCur); */ |
| 56385 | sqlite3BtreeLeave(pBtree); |
| 56386 | } |
| 56387 | return SQLITE_OK; |
| 56388 | } |
| @@ -56672,10 +56804,11 @@ | |
| 56672 | pBuf += a; |
| 56673 | amt -= a; |
| 56674 | }else{ |
| 56675 | offset -= pCur->info.nLocal; |
| 56676 | } |
| 56677 | |
| 56678 | if( rc==SQLITE_OK && amt>0 ){ |
| 56679 | const u32 ovflSize = pBt->usableSize - 4; /* Bytes content per ovfl page */ |
| 56680 | Pgno nextPage; |
| 56681 | |
| @@ -56690,12 +56823,12 @@ | |
| 56690 | ** means "not yet known" (the cache is lazily populated). |
| 56691 | */ |
| 56692 | if( eOp!=2 && (pCur->curFlags & BTCF_ValidOvfl)==0 ){ |
| 56693 | int nOvfl = (pCur->info.nPayload-pCur->info.nLocal+ovflSize-1)/ovflSize; |
| 56694 | if( nOvfl>pCur->nOvflAlloc ){ |
| 56695 | Pgno *aNew = (Pgno*)sqlite3DbRealloc( |
| 56696 | pCur->pBtree->db, pCur->aOverflow, nOvfl*2*sizeof(Pgno) |
| 56697 | ); |
| 56698 | if( aNew==0 ){ |
| 56699 | rc = SQLITE_NOMEM; |
| 56700 | }else{ |
| 56701 | pCur->nOvflAlloc = nOvfl*2; |
| @@ -56738,10 +56871,11 @@ | |
| 56738 | ** Note that the aOverflow[] array must be allocated because eOp!=2 |
| 56739 | ** here. If eOp==2, then offset==0 and this branch is never taken. |
| 56740 | */ |
| 56741 | assert( eOp!=2 ); |
| 56742 | assert( pCur->curFlags & BTCF_ValidOvfl ); |
| 56743 | if( pCur->aOverflow[iIdx+1] ){ |
| 56744 | nextPage = pCur->aOverflow[iIdx+1]; |
| 56745 | }else{ |
| 56746 | rc = getOverflowPage(pBt, nextPage, 0, &nextPage); |
| 56747 | } |
| @@ -58881,11 +59015,11 @@ | |
| 58881 | assert( sqlite3_mutex_held(pPage->pBt->mutex) ); |
| 58882 | assert( sqlite3PagerIswriteable(pParent->pDbPage) ); |
| 58883 | assert( pPage->nOverflow==1 ); |
| 58884 | |
| 58885 | /* This error condition is now caught prior to reaching this function */ |
| 58886 | if( pPage->nCell==0 ) return SQLITE_CORRUPT_BKPT; |
| 58887 | |
| 58888 | /* Allocate a new page. This page will become the right-sibling of |
| 58889 | ** pPage. Make the parent page writable, so that the new divider cell |
| 58890 | ** may be inserted. If both these operations are successful, proceed. |
| 58891 | */ |
| @@ -59250,11 +59384,11 @@ | |
| 59250 | + nMaxCells*sizeof(u16) /* szCell */ |
| 59251 | + pBt->pageSize; /* aSpace1 */ |
| 59252 | |
| 59253 | /* EVIDENCE-OF: R-28375-38319 SQLite will never request a scratch buffer |
| 59254 | ** that is more than 6 times the database page size. */ |
| 59255 | assert( szScratch<=6*pBt->pageSize ); |
| 59256 | apCell = sqlite3ScratchMalloc( szScratch ); |
| 59257 | if( apCell==0 ){ |
| 59258 | rc = SQLITE_NOMEM; |
| 59259 | goto balance_cleanup; |
| 59260 | } |
| @@ -59324,11 +59458,15 @@ | |
| 59324 | ** pointer of the divider cell */ |
| 59325 | memcpy(apCell[nCell], &pOld->aData[8], 4); |
| 59326 | }else{ |
| 59327 | assert( leafCorrection==4 ); |
| 59328 | if( szCell[nCell]<4 ){ |
| 59329 | /* Do not allow any cells smaller than 4 bytes. */ |
| 59330 | szCell[nCell] = 4; |
| 59331 | } |
| 59332 | } |
| 59333 | nCell++; |
| 59334 | } |
| @@ -59559,11 +59697,15 @@ | |
| 59559 | ** was either part of sibling page iOld (possibly an overflow cell), |
| 59560 | ** or else the divider cell to the left of sibling page iOld. So, |
| 59561 | ** if sibling page iOld had the same page number as pNew, and if |
| 59562 | ** pCell really was a part of sibling page iOld (not a divider or |
| 59563 | ** overflow cell), we can skip updating the pointer map entries. */ |
| 59564 | if( pNew->pgno!=aPgno[iOld] || pCell<aOld || pCell>=&aOld[usableSize] ){ |
| 59565 | if( !leafCorrection ){ |
| 59566 | ptrmapPut(pBt, get4byte(pCell), PTRMAP_BTREE, pNew->pgno, &rc); |
| 59567 | } |
| 59568 | if( szCell[i]>pNew->minLocal ){ |
| 59569 | ptrmapPutOvflPtr(pNew, pCell, &rc); |
| @@ -60632,10 +60774,17 @@ | |
| 60632 | ** is read-only, the others are read/write. |
| 60633 | ** |
| 60634 | ** The schema layer numbers meta values differently. At the schema |
| 60635 | ** layer (and the SetCookie and ReadCookie opcodes) the number of |
| 60636 | ** free pages is not visible. So Cookie[0] is the same as Meta[1]. |
| 60637 | */ |
| 60638 | SQLITE_PRIVATE void sqlite3BtreeGetMeta(Btree *p, int idx, u32 *pMeta){ |
| 60639 | BtShared *pBt = p->pBt; |
| 60640 | |
| 60641 | sqlite3BtreeEnter(p); |
| @@ -60642,11 +60791,15 @@ | |
| 60642 | assert( p->inTrans>TRANS_NONE ); |
| 60643 | assert( SQLITE_OK==querySharedCacheTableLock(p, MASTER_ROOT, READ_LOCK) ); |
| 60644 | assert( pBt->pPage1 ); |
| 60645 | assert( idx>=0 && idx<=15 ); |
| 60646 | |
| 60647 | *pMeta = get4byte(&pBt->pPage1->aData[36 + idx*4]); |
| 60648 | |
| 60649 | /* If auto-vacuum is disabled in this build and this is an auto-vacuum |
| 60650 | ** database, mark the database as read-only. */ |
| 60651 | #ifdef SQLITE_OMIT_AUTOVACUUM |
| 60652 | if( idx==BTREE_LARGEST_ROOT_PAGE && *pMeta>0 ){ |
| @@ -60733,11 +60886,11 @@ | |
| 60733 | if( pPage->leaf ){ |
| 60734 | do { |
| 60735 | if( pCur->iPage==0 ){ |
| 60736 | /* All pages of the b-tree have been visited. Return successfully. */ |
| 60737 | *pnEntry = nEntry; |
| 60738 | return SQLITE_OK; |
| 60739 | } |
| 60740 | moveToParent(pCur); |
| 60741 | }while ( pCur->aiIdx[pCur->iPage]>=pCur->apPage[pCur->iPage]->nCell ); |
| 60742 | |
| 60743 | pCur->aiIdx[pCur->iPage]++; |
| @@ -61589,11 +61742,11 @@ | |
| 61589 | } |
| 61590 | |
| 61591 | /* |
| 61592 | ** Return the size of the header added to each page by this module. |
| 61593 | */ |
| 61594 | SQLITE_PRIVATE int sqlite3HeaderSizeBtree(void){ return sizeof(MemPage); } |
| 61595 | |
| 61596 | /************** End of btree.c ***********************************************/ |
| 61597 | /************** Begin file backup.c ******************************************/ |
| 61598 | /* |
| 61599 | ** 2009 January 28 |
| @@ -64353,36 +64506,39 @@ | |
| 64353 | ** |
| 64354 | ** assert( sqlite3VdbeAssertMayAbort(pParse->pVdbe, pParse->mayAbort) ); |
| 64355 | */ |
| 64356 | SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){ |
| 64357 | int hasAbort = 0; |
| 64358 | Op *pOp; |
| 64359 | VdbeOpIter sIter; |
| 64360 | memset(&sIter, 0, sizeof(sIter)); |
| 64361 | sIter.v = v; |
| 64362 | |
| 64363 | while( (pOp = opIterNext(&sIter))!=0 ){ |
| 64364 | int opcode = pOp->opcode; |
| 64365 | if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename |
| 64366 | #ifndef SQLITE_OMIT_FOREIGN_KEY |
| 64367 | || (opcode==OP_FkCounter && pOp->p1==0 && pOp->p2==1) |
| 64368 | #endif |
| 64369 | || ((opcode==OP_Halt || opcode==OP_HaltIfNull) |
| 64370 | && ((pOp->p1&0xff)==SQLITE_CONSTRAINT && pOp->p2==OE_Abort)) |
| 64371 | ){ |
| 64372 | hasAbort = 1; |
| 64373 | break; |
| 64374 | } |
| 64375 | } |
| 64376 | sqlite3DbFree(v->db, sIter.apSub); |
| 64377 | |
| 64378 | /* Return true if hasAbort==mayAbort. Or if a malloc failure occurred. |
| 64379 | ** If malloc failed, then the while() loop above may not have iterated |
| 64380 | ** through all opcodes and hasAbort may be set incorrectly. Return |
| 64381 | ** true for this case to prevent the assert() in the callers frame |
| 64382 | ** from failing. */ |
| 64383 | return ( v->db->mallocFailed || hasAbort==mayAbort ); |
| 64384 | } |
| 64385 | #endif /* SQLITE_DEBUG - the sqlite3AssertMayAbort() function */ |
| 64386 | |
| 64387 | /* |
| 64388 | ** Loop through the program looking for P2 values that are negative |
| @@ -65699,11 +65855,11 @@ | |
| 65699 | for(n=0; n<nVar; n++){ |
| 65700 | p->aVar[n].flags = MEM_Null; |
| 65701 | p->aVar[n].db = db; |
| 65702 | } |
| 65703 | } |
| 65704 | if( p->azVar ){ |
| 65705 | p->nzVar = pParse->nzVar; |
| 65706 | memcpy(p->azVar, pParse->azVar, p->nzVar*sizeof(p->azVar[0])); |
| 65707 | memset(pParse->azVar, 0, pParse->nzVar*sizeof(pParse->azVar[0])); |
| 65708 | } |
| 65709 | if( p->aMem ){ |
| @@ -68502,11 +68658,14 @@ | |
| 68502 | #ifndef SQLITE_OMIT_WAL |
| 68503 | int i; |
| 68504 | for(i=0; i<db->nDb; i++){ |
| 68505 | Btree *pBt = db->aDb[i].pBt; |
| 68506 | if( pBt ){ |
| 68507 | int nEntry = sqlite3PagerWalCallback(sqlite3BtreePager(pBt)); |
| 68508 | if( db->xWalCallback && nEntry>0 && rc==SQLITE_OK ){ |
| 68509 | rc = db->xWalCallback(db->pWalArg, db, db->aDb[i].zName, nEntry); |
| 68510 | } |
| 68511 | } |
| 68512 | } |
| @@ -68682,11 +68841,10 @@ | |
| 68682 | ** program counter to 0 to ensure that when the statement is |
| 68683 | ** finalized or reset the parser error message is available via |
| 68684 | ** sqlite3_errmsg() and sqlite3_errcode(). |
| 68685 | */ |
| 68686 | const char *zErr = (const char *)sqlite3_value_text(db->pErr); |
| 68687 | assert( zErr!=0 || db->mallocFailed ); |
| 68688 | sqlite3DbFree(db, v->zErrMsg); |
| 68689 | if( !db->mallocFailed ){ |
| 68690 | v->zErrMsg = sqlite3DbStrDup(db, zErr); |
| 68691 | v->rc = rc2; |
| 68692 | } else { |
| @@ -75629,12 +75787,12 @@ | |
| 75629 | |
| 75630 | #ifndef SQLITE_OMIT_WAL |
| 75631 | /* Opcode: Checkpoint P1 P2 P3 * * |
| 75632 | ** |
| 75633 | ** Checkpoint database P1. This is a no-op if P1 is not currently in |
| 75634 | ** WAL mode. Parameter P2 is one of SQLITE_CHECKPOINT_PASSIVE, FULL |
| 75635 | ** or RESTART. Write 1 or 0 into mem[P3] if the checkpoint returns |
| 75636 | ** SQLITE_BUSY or not, respectively. Write the number of pages in the |
| 75637 | ** WAL after the checkpoint into mem[P3+1] and the number of pages |
| 75638 | ** in the WAL that have been checkpointed after the checkpoint |
| 75639 | ** completes into mem[P3+2]. However on an error, mem[P3+1] and |
| 75640 | ** mem[P3+2] are initialized to -1. |
| @@ -75648,10 +75806,11 @@ | |
| 75648 | aRes[0] = 0; |
| 75649 | aRes[1] = aRes[2] = -1; |
| 75650 | assert( pOp->p2==SQLITE_CHECKPOINT_PASSIVE |
| 75651 | || pOp->p2==SQLITE_CHECKPOINT_FULL |
| 75652 | || pOp->p2==SQLITE_CHECKPOINT_RESTART |
| 75653 | ); |
| 75654 | rc = sqlite3Checkpoint(db, pOp->p1, pOp->p2, &aRes[1], &aRes[2]); |
| 75655 | if( rc==SQLITE_BUSY ){ |
| 75656 | rc = SQLITE_OK; |
| 75657 | aRes[0] = 1; |
| @@ -77043,11 +77202,11 @@ | |
| 77043 | /* |
| 77044 | ** Hard-coded maximum amount of data to accumulate in memory before flushing |
| 77045 | ** to a level 0 PMA. The purpose of this limit is to prevent various integer |
| 77046 | ** overflows. 512MiB. |
| 77047 | */ |
| 77048 | #define SQLITE_MAX_MXPMASIZE (1<<29) |
| 77049 | |
| 77050 | /* |
| 77051 | ** Private objects used by the sorter |
| 77052 | */ |
| 77053 | typedef struct MergeEngine MergeEngine; /* Merge PMAs together */ |
| @@ -77339,13 +77498,10 @@ | |
| 77339 | ** |
| 77340 | ** void *SRVAL(SorterRecord *p) { return (void*)&p[1]; } |
| 77341 | */ |
| 77342 | #define SRVAL(p) ((void*)((SorterRecord*)(p) + 1)) |
| 77343 | |
| 77344 | /* The minimum PMA size is set to this value multiplied by the database |
| 77345 | ** page size in bytes. */ |
| 77346 | #define SORTER_MIN_WORKING 10 |
| 77347 | |
| 77348 | /* Maximum number of PMAs that a single MergeEngine can merge */ |
| 77349 | #define SORTER_MAX_MERGE_COUNT 16 |
| 77350 | |
| 77351 | static int vdbeIncrSwap(IncrMerger*); |
| @@ -77740,14 +77896,15 @@ | |
| 77740 | SortSubtask *pTask = &pSorter->aTask[i]; |
| 77741 | pTask->pSorter = pSorter; |
| 77742 | } |
| 77743 | |
| 77744 | if( !sqlite3TempInMemory(db) ){ |
| 77745 | pSorter->mnPmaSize = SORTER_MIN_WORKING * pgsz; |
| 77746 | mxCache = db->aDb[0].pSchema->cache_size; |
| 77747 | if( mxCache<SORTER_MIN_WORKING ) mxCache = SORTER_MIN_WORKING; |
| 77748 | pSorter->mxPmaSize = MIN((i64)mxCache*pgsz, SQLITE_MAX_MXPMASIZE); |
| 77749 | |
| 77750 | /* EVIDENCE-OF: R-26747-61719 When the application provides any amount of |
| 77751 | ** scratch memory using SQLITE_CONFIG_SCRATCH, SQLite avoids unnecessary |
| 77752 | ** large heap allocations. |
| 77753 | */ |
| @@ -78021,16 +78178,16 @@ | |
| 78021 | ** Whether or not the file does end up memory mapped of course depends on |
| 78022 | ** the specific VFS implementation. |
| 78023 | */ |
| 78024 | static void vdbeSorterExtendFile(sqlite3 *db, sqlite3_file *pFd, i64 nByte){ |
| 78025 | if( nByte<=(i64)(db->nMaxSorterMmap) && pFd->pMethods->iVersion>=3 ){ |
| 78026 | int rc = sqlite3OsTruncate(pFd, nByte); |
| 78027 | if( rc==SQLITE_OK ){ |
| 78028 | void *p = 0; |
| 78029 | sqlite3OsFetch(pFd, 0, (int)nByte, &p); |
| 78030 | sqlite3OsUnfetch(pFd, 0, p); |
| 78031 | } |
| 78032 | } |
| 78033 | } |
| 78034 | #else |
| 78035 | # define vdbeSorterExtendFile(x,y,z) |
| 78036 | #endif |
| @@ -80411,10 +80568,14 @@ | |
| 80411 | } |
| 80412 | } |
| 80413 | if( pMatch ){ |
| 80414 | pExpr->iTable = pMatch->iCursor; |
| 80415 | pExpr->pTab = pMatch->pTab; |
| 80416 | pSchema = pExpr->pTab->pSchema; |
| 80417 | } |
| 80418 | } /* if( pSrcList ) */ |
| 80419 | |
| 80420 | #ifndef SQLITE_OMIT_TRIGGER |
| @@ -82968,11 +83129,12 @@ | |
| 82968 | case TK_FLOAT: |
| 82969 | case TK_BLOB: |
| 82970 | return 0; |
| 82971 | case TK_COLUMN: |
| 82972 | assert( p->pTab!=0 ); |
| 82973 | return p->iColumn>=0 && p->pTab->aCol[p->iColumn].notNull==0; |
| 82974 | default: |
| 82975 | return 1; |
| 82976 | } |
| 82977 | } |
| 82978 | |
| @@ -87203,11 +87365,11 @@ | |
| 87203 | |
| 87204 | p->iGet = -1; |
| 87205 | p->mxSample = mxSample; |
| 87206 | p->nPSample = (tRowcnt)(sqlite3_value_int64(argv[2])/(mxSample/3+1) + 1); |
| 87207 | p->current.anLt = &p->current.anEq[nColUp]; |
| 87208 | p->iPrn = nCol*0x689e962d ^ sqlite3_value_int(argv[2])*0xd0944565; |
| 87209 | |
| 87210 | /* Set up the Stat4Accum.a[] and aBest[] arrays */ |
| 87211 | p->a = (struct Stat4Sample*)&p->current.anLt[nColUp]; |
| 87212 | p->aBest = &p->a[mxSample]; |
| 87213 | pSpace = (u8*)(&p->a[mxSample+nCol]); |
| @@ -88351,11 +88513,11 @@ | |
| 88351 | tRowcnt avgEq = 0; |
| 88352 | tRowcnt nRow; /* Number of rows in index */ |
| 88353 | i64 nSum100 = 0; /* Number of terms contributing to sumEq */ |
| 88354 | i64 nDist100; /* Number of distinct values in index */ |
| 88355 | |
| 88356 | if( pIdx->aiRowEst==0 || pIdx->aiRowEst[iCol+1]==0 ){ |
| 88357 | nRow = pFinal->anLt[iCol]; |
| 88358 | nDist100 = (i64)100 * pFinal->anDLt[iCol]; |
| 88359 | nSample--; |
| 88360 | }else{ |
| 88361 | nRow = pIdx->aiRowEst[0]; |
| @@ -88796,17 +88958,19 @@ | |
| 88796 | }else if( aNew->pSchema->file_format && aNew->pSchema->enc!=ENC(db) ){ |
| 88797 | zErrDyn = sqlite3MPrintf(db, |
| 88798 | "attached databases must use the same text encoding as main database"); |
| 88799 | rc = SQLITE_ERROR; |
| 88800 | } |
| 88801 | pPager = sqlite3BtreePager(aNew->pBt); |
| 88802 | sqlite3PagerLockingMode(pPager, db->dfltLockMode); |
| 88803 | sqlite3BtreeSecureDelete(aNew->pBt, |
| 88804 | sqlite3BtreeSecureDelete(db->aDb[0].pBt,-1) ); |
| 88805 | #ifndef SQLITE_OMIT_PAGER_PRAGMAS |
| 88806 | sqlite3BtreeSetPagerFlags(aNew->pBt, 3 | (db->flags & PAGER_FLAGS_MASK)); |
| 88807 | #endif |
| 88808 | } |
| 88809 | aNew->safety_level = 3; |
| 88810 | aNew->zName = sqlite3DbStrDup(db, zName); |
| 88811 | if( rc==SQLITE_OK && aNew->zName==0 ){ |
| 88812 | rc = SQLITE_NOMEM; |
| @@ -89928,11 +90092,10 @@ | |
| 89928 | */ |
| 89929 | static void freeIndex(sqlite3 *db, Index *p){ |
| 89930 | #ifndef SQLITE_OMIT_ANALYZE |
| 89931 | sqlite3DeleteIndexSamples(db, p); |
| 89932 | #endif |
| 89933 | if( db==0 || db->pnBytesFreed==0 ) sqlite3KeyInfoUnref(p->pKeyInfo); |
| 89934 | sqlite3ExprDelete(db, p->pPartIdxWhere); |
| 89935 | sqlite3DbFree(db, p->zColAff); |
| 89936 | if( p->isResized ) sqlite3DbFree(db, p->azColl); |
| 89937 | #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 |
| 89938 | sqlite3_free(p->aiRowEst); |
| @@ -91207,10 +91370,23 @@ | |
| 91207 | if( pPk==0 ) return; |
| 91208 | pPk->idxType = SQLITE_IDXTYPE_PRIMARYKEY; |
| 91209 | pTab->iPKey = -1; |
| 91210 | }else{ |
| 91211 | pPk = sqlite3PrimaryKeyIndex(pTab); |
| 91212 | } |
| 91213 | pPk->isCovering = 1; |
| 91214 | assert( pPk!=0 ); |
| 91215 | nPk = pPk->nKeyCol; |
| 91216 | |
| @@ -93683,44 +93859,35 @@ | |
| 93683 | ** |
| 93684 | ** The caller should invoke sqlite3KeyInfoUnref() on the returned object |
| 93685 | ** when it has finished using it. |
| 93686 | */ |
| 93687 | SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoOfIndex(Parse *pParse, Index *pIdx){ |
| 93688 | if( pParse->nErr ) return 0; |
| 93689 | #ifndef SQLITE_OMIT_SHARED_CACHE |
| 93690 | if( pIdx->pKeyInfo && pIdx->pKeyInfo->db!=pParse->db ){ |
| 93691 | sqlite3KeyInfoUnref(pIdx->pKeyInfo); |
| 93692 | pIdx->pKeyInfo = 0; |
| 93693 | } |
| 93694 | #endif |
| 93695 | if( pIdx->pKeyInfo==0 ){ |
| 93696 | int i; |
| 93697 | int nCol = pIdx->nColumn; |
| 93698 | int nKey = pIdx->nKeyCol; |
| 93699 | KeyInfo *pKey; |
| 93700 | if( pIdx->uniqNotNull ){ |
| 93701 | pKey = sqlite3KeyInfoAlloc(pParse->db, nKey, nCol-nKey); |
| 93702 | }else{ |
| 93703 | pKey = sqlite3KeyInfoAlloc(pParse->db, nCol, 0); |
| 93704 | } |
| 93705 | if( pKey ){ |
| 93706 | assert( sqlite3KeyInfoIsWriteable(pKey) ); |
| 93707 | for(i=0; i<nCol; i++){ |
| 93708 | char *zColl = pIdx->azColl[i]; |
| 93709 | assert( zColl!=0 ); |
| 93710 | pKey->aColl[i] = strcmp(zColl,"BINARY")==0 ? 0 : |
| 93711 | sqlite3LocateCollSeq(pParse, zColl); |
| 93712 | pKey->aSortOrder[i] = pIdx->aSortOrder[i]; |
| 93713 | } |
| 93714 | if( pParse->nErr ){ |
| 93715 | sqlite3KeyInfoUnref(pKey); |
| 93716 | }else{ |
| 93717 | pIdx->pKeyInfo = pKey; |
| 93718 | } |
| 93719 | } |
| 93720 | } |
| 93721 | return sqlite3KeyInfoRef(pIdx->pKeyInfo); |
| 93722 | } |
| 93723 | |
| 93724 | #ifndef SQLITE_OMIT_CTE |
| 93725 | /* |
| 93726 | ** This routine is invoked once per CTE by the parser while parsing a |
| @@ -97337,11 +97504,11 @@ | |
| 97337 | assert( nIncr==1 ); |
| 97338 | sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY, |
| 97339 | OE_Abort, 0, P4_STATIC, P5_ConstraintFK); |
| 97340 | }else{ |
| 97341 | if( nIncr>0 && pFKey->isDeferred==0 ){ |
| 97342 | sqlite3ParseToplevel(pParse)->mayAbort = 1; |
| 97343 | } |
| 97344 | sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr); |
| 97345 | } |
| 97346 | |
| 97347 | sqlite3VdbeResolveLabel(v, iOk); |
| @@ -97408,10 +97575,14 @@ | |
| 97408 | ** This function is called to generate code executed when a row is deleted |
| 97409 | ** from the parent table of foreign key constraint pFKey and, if pFKey is |
| 97410 | ** deferred, when a row is inserted into the same table. When generating |
| 97411 | ** code for an SQL UPDATE operation, this function may be called twice - |
| 97412 | ** once to "delete" the old row and once to "insert" the new row. |
| 97413 | ** |
| 97414 | ** The code generated by this function scans through the rows in the child |
| 97415 | ** table that correspond to the parent table row being deleted or inserted. |
| 97416 | ** For each child row found, one of the following actions is taken: |
| 97417 | ** |
| @@ -97525,17 +97696,13 @@ | |
| 97525 | sNameContext.pSrcList = pSrc; |
| 97526 | sNameContext.pParse = pParse; |
| 97527 | sqlite3ResolveExprNames(&sNameContext, pWhere); |
| 97528 | |
| 97529 | /* Create VDBE to loop through the entries in pSrc that match the WHERE |
| 97530 | ** clause. If the constraint is not deferred, throw an exception for |
| 97531 | ** each row found. Otherwise, for deferred constraints, increment the |
| 97532 | ** deferred constraint counter by nIncr for each row selected. */ |
| 97533 | pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0); |
| 97534 | if( nIncr>0 && pFKey->isDeferred==0 ){ |
| 97535 | sqlite3ParseToplevel(pParse)->mayAbort = 1; |
| 97536 | } |
| 97537 | sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr); |
| 97538 | if( pWInfo ){ |
| 97539 | sqlite3WhereEnd(pWInfo); |
| 97540 | } |
| 97541 | |
| @@ -97709,10 +97876,28 @@ | |
| 97709 | } |
| 97710 | } |
| 97711 | } |
| 97712 | return 0; |
| 97713 | } |
| 97714 | |
| 97715 | /* |
| 97716 | ** This function is called when inserting, deleting or updating a row of |
| 97717 | ** table pTab to generate VDBE code to perform foreign key constraint |
| 97718 | ** processing for the operation. |
| @@ -97762,11 +97947,11 @@ | |
| 97762 | Index *pIdx = 0; /* Index on key columns in pTo */ |
| 97763 | int *aiFree = 0; |
| 97764 | int *aiCol; |
| 97765 | int iCol; |
| 97766 | int i; |
| 97767 | int isIgnore = 0; |
| 97768 | |
| 97769 | if( aChange |
| 97770 | && sqlite3_stricmp(pTab->zName, pFKey->zTo)!=0 |
| 97771 | && fkChildIsModified(pTab, pFKey, aChange, bChngRowid)==0 |
| 97772 | ){ |
| @@ -97821,11 +98006,11 @@ | |
| 97821 | ** values read from the parent table are NULL. */ |
| 97822 | if( db->xAuth ){ |
| 97823 | int rcauth; |
| 97824 | char *zCol = pTo->aCol[pIdx ? pIdx->aiColumn[i] : pTo->iPKey].zName; |
| 97825 | rcauth = sqlite3AuthReadCol(pParse, pTo->zName, zCol, iDb); |
| 97826 | isIgnore = (rcauth==SQLITE_IGNORE); |
| 97827 | } |
| 97828 | #endif |
| 97829 | } |
| 97830 | |
| 97831 | /* Take a shared-cache advisory read-lock on the parent table. Allocate |
| @@ -97836,16 +98021,22 @@ | |
| 97836 | |
| 97837 | if( regOld!=0 ){ |
| 97838 | /* A row is being removed from the child table. Search for the parent. |
| 97839 | ** If the parent does not exist, removing the child row resolves an |
| 97840 | ** outstanding foreign key constraint violation. */ |
| 97841 | fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regOld, -1,isIgnore); |
| 97842 | } |
| 97843 | if( regNew!=0 ){ |
| 97844 | /* A row is being added to the child table. If a parent row cannot |
| 97845 | ** be found, adding the child row has violated the FK constraint. */ |
| 97846 | fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regNew, +1,isIgnore); |
| 97847 | } |
| 97848 | |
| 97849 | sqlite3DbFree(db, aiFree); |
| 97850 | } |
| 97851 | |
| @@ -97862,12 +98053,12 @@ | |
| 97862 | |
| 97863 | if( !pFKey->isDeferred && !(db->flags & SQLITE_DeferFKs) |
| 97864 | && !pParse->pToplevel && !pParse->isMultiWrite |
| 97865 | ){ |
| 97866 | assert( regOld==0 && regNew!=0 ); |
| 97867 | /* Inserting a single row into a parent table cannot cause an immediate |
| 97868 | ** foreign key violation. So do nothing in this case. */ |
| 97869 | continue; |
| 97870 | } |
| 97871 | |
| 97872 | if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){ |
| 97873 | if( !isIgnoreErrors || db->mallocFailed ) return; |
| @@ -97887,17 +98078,32 @@ | |
| 97887 | |
| 97888 | if( regNew!=0 ){ |
| 97889 | fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regNew, -1); |
| 97890 | } |
| 97891 | if( regOld!=0 ){ |
| 97892 | /* If there is a RESTRICT action configured for the current operation |
| 97893 | ** on the parent table of this FK, then throw an exception |
| 97894 | ** immediately if the FK constraint is violated, even if this is a |
| 97895 | ** deferred trigger. That's what RESTRICT means. To defer checking |
| 97896 | ** the constraint, the FK should specify NO ACTION (represented |
| 97897 | ** using OE_None). NO ACTION is the default. */ |
| 97898 | fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regOld, 1); |
| 97899 | } |
| 97900 | pItem->zName = 0; |
| 97901 | sqlite3SrcListDelete(db, pSrc); |
| 97902 | } |
| 97903 | sqlite3DbFree(db, aiCol); |
| @@ -100987,11 +101193,10 @@ | |
| 100987 | # define sqlite3_column_database_name16 0 |
| 100988 | # define sqlite3_column_table_name 0 |
| 100989 | # define sqlite3_column_table_name16 0 |
| 100990 | # define sqlite3_column_origin_name 0 |
| 100991 | # define sqlite3_column_origin_name16 0 |
| 100992 | # define sqlite3_table_column_metadata 0 |
| 100993 | #endif |
| 100994 | |
| 100995 | #ifdef SQLITE_OMIT_AUTHORIZATION |
| 100996 | # define sqlite3_set_authorizer 0 |
| 100997 | #endif |
| @@ -101797,10 +102002,11 @@ | |
| 101797 | #define PragTyp_KEY 38 |
| 101798 | #define PragTyp_REKEY 39 |
| 101799 | #define PragTyp_LOCK_STATUS 40 |
| 101800 | #define PragTyp_PARSER_TRACE 41 |
| 101801 | #define PragFlag_NeedSchema 0x01 |
| 101802 | static const struct sPragmaNames { |
| 101803 | const char *const zName; /* Name of pragma */ |
| 101804 | u8 ePragTyp; /* PragTyp_XXX value */ |
| 101805 | u8 mPragFlag; /* Zero or more PragFlag_XXX values */ |
| 101806 | u32 iArg; /* Extra argument */ |
| @@ -101813,11 +102019,11 @@ | |
| 101813 | #endif |
| 101814 | #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) |
| 101815 | { /* zName: */ "application_id", |
| 101816 | /* ePragTyp: */ PragTyp_HEADER_VALUE, |
| 101817 | /* ePragFlag: */ 0, |
| 101818 | /* iArg: */ 0 }, |
| 101819 | #endif |
| 101820 | #if !defined(SQLITE_OMIT_AUTOVACUUM) |
| 101821 | { /* zName: */ "auto_vacuum", |
| 101822 | /* ePragTyp: */ PragTyp_AUTO_VACUUM, |
| 101823 | /* ePragFlag: */ PragFlag_NeedSchema, |
| @@ -101879,10 +102085,16 @@ | |
| 101879 | { /* zName: */ "data_store_directory", |
| 101880 | /* ePragTyp: */ PragTyp_DATA_STORE_DIRECTORY, |
| 101881 | /* ePragFlag: */ 0, |
| 101882 | /* iArg: */ 0 }, |
| 101883 | #endif |
| 101884 | #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) |
| 101885 | { /* zName: */ "database_list", |
| 101886 | /* ePragTyp: */ PragTyp_DATABASE_LIST, |
| 101887 | /* ePragFlag: */ PragFlag_NeedSchema, |
| 101888 | /* iArg: */ 0 }, |
| @@ -101934,12 +102146,12 @@ | |
| 101934 | #endif |
| 101935 | #endif |
| 101936 | #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) |
| 101937 | { /* zName: */ "freelist_count", |
| 101938 | /* ePragTyp: */ PragTyp_HEADER_VALUE, |
| 101939 | /* ePragFlag: */ 0, |
| 101940 | /* iArg: */ 0 }, |
| 101941 | #endif |
| 101942 | #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
| 101943 | { /* zName: */ "full_column_names", |
| 101944 | /* ePragTyp: */ PragTyp_FLAG, |
| 101945 | /* ePragFlag: */ 0, |
| @@ -102087,11 +102299,11 @@ | |
| 102087 | #endif |
| 102088 | #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) |
| 102089 | { /* zName: */ "schema_version", |
| 102090 | /* ePragTyp: */ PragTyp_HEADER_VALUE, |
| 102091 | /* ePragFlag: */ 0, |
| 102092 | /* iArg: */ 0 }, |
| 102093 | #endif |
| 102094 | #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) |
| 102095 | { /* zName: */ "secure_delete", |
| 102096 | /* ePragTyp: */ PragTyp_SECURE_DELETE, |
| 102097 | /* ePragFlag: */ 0, |
| @@ -102153,11 +102365,11 @@ | |
| 102153 | /* iArg: */ 0 }, |
| 102154 | #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) |
| 102155 | { /* zName: */ "user_version", |
| 102156 | /* ePragTyp: */ PragTyp_HEADER_VALUE, |
| 102157 | /* ePragFlag: */ 0, |
| 102158 | /* iArg: */ 0 }, |
| 102159 | #endif |
| 102160 | #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
| 102161 | #if defined(SQLITE_DEBUG) |
| 102162 | { /* zName: */ "vdbe_addoptrace", |
| 102163 | /* ePragTyp: */ PragTyp_FLAG, |
| @@ -102196,11 +102408,11 @@ | |
| 102196 | /* ePragTyp: */ PragTyp_FLAG, |
| 102197 | /* ePragFlag: */ 0, |
| 102198 | /* iArg: */ SQLITE_WriteSchema|SQLITE_RecoveryMode }, |
| 102199 | #endif |
| 102200 | }; |
| 102201 | /* Number of pragmas: 57 on by default, 70 total. */ |
| 102202 | /* End of the automatically generated pragma table. |
| 102203 | ***************************************************************************/ |
| 102204 | |
| 102205 | /* |
| 102206 | ** Interpret the given string as a safety level. Return 0 for OFF, |
| @@ -103806,11 +104018,12 @@ | |
| 103806 | !(DbHasProperty(db, 0, DB_SchemaLoaded)) || |
| 103807 | DbHasProperty(db, 0, DB_Empty) |
| 103808 | ){ |
| 103809 | for(pEnc=&encnames[0]; pEnc->zName; pEnc++){ |
| 103810 | if( 0==sqlite3StrICmp(zRight, pEnc->zName) ){ |
| 103811 | ENC(pParse->db) = pEnc->enc ? pEnc->enc : SQLITE_UTF16NATIVE; |
| 103812 | break; |
| 103813 | } |
| 103814 | } |
| 103815 | if( !pEnc->zName ){ |
| 103816 | sqlite3ErrorMsg(pParse, "unsupported encoding: %s", zRight); |
| @@ -103851,28 +104064,13 @@ | |
| 103851 | ** |
| 103852 | ** The user-version is not used internally by SQLite. It may be used by |
| 103853 | ** applications for any purpose. |
| 103854 | */ |
| 103855 | case PragTyp_HEADER_VALUE: { |
| 103856 | int iCookie; /* Cookie index. 1 for schema-cookie, 6 for user-cookie. */ |
| 103857 | sqlite3VdbeUsesBtree(v, iDb); |
| 103858 | switch( zLeft[0] ){ |
| 103859 | case 'a': case 'A': |
| 103860 | iCookie = BTREE_APPLICATION_ID; |
| 103861 | break; |
| 103862 | case 'f': case 'F': |
| 103863 | iCookie = BTREE_FREE_PAGE_COUNT; |
| 103864 | break; |
| 103865 | case 's': case 'S': |
| 103866 | iCookie = BTREE_SCHEMA_VERSION; |
| 103867 | break; |
| 103868 | default: |
| 103869 | iCookie = BTREE_USER_VERSION; |
| 103870 | break; |
| 103871 | } |
| 103872 | |
| 103873 | if( zRight && iCookie!=BTREE_FREE_PAGE_COUNT ){ |
| 103874 | /* Write the specified cookie value */ |
| 103875 | static const VdbeOpList setCookie[] = { |
| 103876 | { OP_Transaction, 0, 1, 0}, /* 0 */ |
| 103877 | { OP_Integer, 0, 1, 0}, /* 1 */ |
| 103878 | { OP_SetCookie, 0, 0, 1}, /* 2 */ |
| @@ -103921,11 +104119,11 @@ | |
| 103921 | break; |
| 103922 | #endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ |
| 103923 | |
| 103924 | #ifndef SQLITE_OMIT_WAL |
| 103925 | /* |
| 103926 | ** PRAGMA [database.]wal_checkpoint = passive|full|restart |
| 103927 | ** |
| 103928 | ** Checkpoint the database. |
| 103929 | */ |
| 103930 | case PragTyp_WAL_CHECKPOINT: { |
| 103931 | int iBt = (pId2->z?iDb:SQLITE_MAX_ATTACHED); |
| @@ -103933,10 +104131,12 @@ | |
| 103933 | if( zRight ){ |
| 103934 | if( sqlite3StrICmp(zRight, "full")==0 ){ |
| 103935 | eMode = SQLITE_CHECKPOINT_FULL; |
| 103936 | }else if( sqlite3StrICmp(zRight, "restart")==0 ){ |
| 103937 | eMode = SQLITE_CHECKPOINT_RESTART; |
| 103938 | } |
| 103939 | } |
| 103940 | sqlite3VdbeSetNumCols(v, 3); |
| 103941 | pParse->nMem = 3; |
| 103942 | sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "busy", SQLITE_STATIC); |
| @@ -104512,13 +104712,15 @@ | |
| 104512 | SQLITE_PRIVATE int sqlite3Init(sqlite3 *db, char **pzErrMsg){ |
| 104513 | int i, rc; |
| 104514 | int commit_internal = !(db->flags&SQLITE_InternChanges); |
| 104515 | |
| 104516 | assert( sqlite3_mutex_held(db->mutex) ); |
| 104517 | assert( db->init.busy==0 ); |
| 104518 | rc = SQLITE_OK; |
| 104519 | db->init.busy = 1; |
| 104520 | for(i=0; rc==SQLITE_OK && i<db->nDb; i++){ |
| 104521 | if( DbHasProperty(db, i, DB_SchemaLoaded) || i==1 ) continue; |
| 104522 | rc = sqlite3InitOne(db, i, pzErrMsg); |
| 104523 | if( rc ){ |
| 104524 | sqlite3ResetOneSchema(db, i); |
| @@ -109840,11 +110042,11 @@ | |
| 109840 | ** |
| 109841 | ** SELECT DISTINCT xyz FROM ... ORDER BY xyz |
| 109842 | ** |
| 109843 | ** is transformed to: |
| 109844 | ** |
| 109845 | ** SELECT xyz FROM ... GROUP BY xyz |
| 109846 | ** |
| 109847 | ** The second form is preferred as a single index (or temp-table) may be |
| 109848 | ** used for both the ORDER BY and DISTINCT processing. As originally |
| 109849 | ** written the query must use a temp-table for at least one of the ORDER |
| 109850 | ** BY and DISTINCT, and an index or separate temp-table for the other. |
| @@ -109853,11 +110055,10 @@ | |
| 109853 | && sqlite3ExprListCompare(sSort.pOrderBy, p->pEList, -1)==0 |
| 109854 | ){ |
| 109855 | p->selFlags &= ~SF_Distinct; |
| 109856 | p->pGroupBy = sqlite3ExprListDup(db, p->pEList, 0); |
| 109857 | pGroupBy = p->pGroupBy; |
| 109858 | sSort.pOrderBy = 0; |
| 109859 | /* Notice that even thought SF_Distinct has been cleared from p->selFlags, |
| 109860 | ** the sDistinct.isTnct is still set. Hence, isTnct represents the |
| 109861 | ** original setting of the SF_Distinct flag, not the current setting */ |
| 109862 | assert( sDistinct.isTnct ); |
| 109863 | } |
| @@ -110657,11 +110858,11 @@ | |
| 110657 | ){ |
| 110658 | int rc; |
| 110659 | TabResult res; |
| 110660 | |
| 110661 | #ifdef SQLITE_ENABLE_API_ARMOR |
| 110662 | if( pazResult==0 ) return SQLITE_MISUSE_BKPT; |
| 110663 | #endif |
| 110664 | *pazResult = 0; |
| 110665 | if( pnColumn ) *pnColumn = 0; |
| 110666 | if( pnRow ) *pnRow = 0; |
| 110667 | if( pzErrMsg ) *pzErrMsg = 0; |
| @@ -114808,10 +115009,11 @@ | |
| 114808 | memcpy(pWC->a, pOld, sizeof(pWC->a[0])*pWC->nTerm); |
| 114809 | if( pOld!=pWC->aStatic ){ |
| 114810 | sqlite3DbFree(db, pOld); |
| 114811 | } |
| 114812 | pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]); |
| 114813 | } |
| 114814 | pTerm = &pWC->a[idx = pWC->nTerm++]; |
| 114815 | if( p && ExprHasProperty(p, EP_Unlikely) ){ |
| 114816 | pTerm->truthProb = sqlite3LogEst(p->iTable) - 270; |
| 114817 | }else{ |
| @@ -117533,11 +117735,11 @@ | |
| 117533 | WhereLevel *pLvl, /* Level to add scanstatus() entry for */ |
| 117534 | int addrExplain /* Address of OP_Explain (or 0) */ |
| 117535 | ){ |
| 117536 | const char *zObj = 0; |
| 117537 | WhereLoop *pLoop = pLvl->pWLoop; |
| 117538 | if( (pLoop->wsFlags & (WHERE_IPK|WHERE_VIRTUALTABLE))==0 ){ |
| 117539 | zObj = pLoop->u.btree.pIndex->zName; |
| 117540 | }else{ |
| 117541 | zObj = pSrclist->a[pLvl->iFrom].zName; |
| 117542 | } |
| 117543 | sqlite3VdbeScanStatus( |
| @@ -118177,14 +118379,13 @@ | |
| 118177 | int iTerm; |
| 118178 | for(iTerm=0; iTerm<pWC->nTerm; iTerm++){ |
| 118179 | Expr *pExpr = pWC->a[iTerm].pExpr; |
| 118180 | if( &pWC->a[iTerm] == pTerm ) continue; |
| 118181 | if( ExprHasProperty(pExpr, EP_FromJoin) ) continue; |
| 118182 | testcase( pWC->a[iTerm].wtFlags & TERM_ORINFO ); |
| 118183 | testcase( pWC->a[iTerm].wtFlags & TERM_VIRTUAL ); |
| 118184 | if( pWC->a[iTerm].wtFlags & (TERM_ORINFO|TERM_VIRTUAL) ) continue; |
| 118185 | if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue; |
| 118186 | pExpr = sqlite3ExprDup(db, pExpr, 0); |
| 118187 | pAndExpr = sqlite3ExprAnd(db, pAndExpr, pExpr); |
| 118188 | } |
| 118189 | if( pAndExpr ){ |
| 118190 | pAndExpr = sqlite3PExpr(pParse, TK_AND, 0, pAndExpr, 0); |
| @@ -118527,11 +118728,10 @@ | |
| 118527 | sqlite3_free(p->u.vtab.idxStr); |
| 118528 | p->u.vtab.needFree = 0; |
| 118529 | p->u.vtab.idxStr = 0; |
| 118530 | }else if( (p->wsFlags & WHERE_AUTO_INDEX)!=0 && p->u.btree.pIndex!=0 ){ |
| 118531 | sqlite3DbFree(db, p->u.btree.pIndex->zColAff); |
| 118532 | sqlite3KeyInfoUnref(p->u.btree.pIndex->pKeyInfo); |
| 118533 | sqlite3DbFree(db, p->u.btree.pIndex); |
| 118534 | p->u.btree.pIndex = 0; |
| 118535 | } |
| 118536 | } |
| 118537 | } |
| @@ -125534,10 +125734,13 @@ | |
| 125534 | u8 enableLookaside; /* Saved value of db->lookaside.bEnabled */ |
| 125535 | sqlite3 *db = pParse->db; /* The database connection */ |
| 125536 | int mxSqlLen; /* Max length of an SQL string */ |
| 125537 | |
| 125538 | |
| 125539 | mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH]; |
| 125540 | if( db->nVdbeActive==0 ){ |
| 125541 | db->u1.isInterrupted = 0; |
| 125542 | } |
| 125543 | pParse->rc = SQLITE_OK; |
| @@ -125772,17 +125975,10 @@ | |
| 125772 | */ |
| 125773 | SQLITE_API int sqlite3_complete(const char *zSql){ |
| 125774 | u8 state = 0; /* Current state, using numbers defined in header comment */ |
| 125775 | u8 token; /* Value of the next token */ |
| 125776 | |
| 125777 | #ifdef SQLITE_ENABLE_API_ARMOR |
| 125778 | if( zSql==0 ){ |
| 125779 | (void)SQLITE_MISUSE_BKPT; |
| 125780 | return 0; |
| 125781 | } |
| 125782 | #endif |
| 125783 | |
| 125784 | #ifndef SQLITE_OMIT_TRIGGER |
| 125785 | /* A complex statement machine used to detect the end of a CREATE TRIGGER |
| 125786 | ** statement. This is the normal case. |
| 125787 | */ |
| 125788 | static const u8 trans[8][8] = { |
| @@ -125807,10 +126003,17 @@ | |
| 125807 | /* 0 INVALID: */ { 1, 0, 2, }, |
| 125808 | /* 1 START: */ { 1, 1, 2, }, |
| 125809 | /* 2 NORMAL: */ { 1, 2, 2, }, |
| 125810 | }; |
| 125811 | #endif /* SQLITE_OMIT_TRIGGER */ |
| 125812 | |
| 125813 | while( *zSql ){ |
| 125814 | switch( *zSql ){ |
| 125815 | case ';': { /* A semicolon */ |
| 125816 | token = tkSEMI; |
| @@ -126109,11 +126312,11 @@ | |
| 126109 | ** If the following function pointer is not NULL and if |
| 126110 | ** SQLITE_ENABLE_IOTRACE is enabled, then messages describing |
| 126111 | ** I/O active are written using this function. These messages |
| 126112 | ** are intended for debugging activity only. |
| 126113 | */ |
| 126114 | SQLITE_PRIVATE void (*sqlite3IoTrace)(const char*, ...) = 0; |
| 126115 | #endif |
| 126116 | |
| 126117 | /* |
| 126118 | ** If the following global variable points to a string which is the |
| 126119 | ** name of a directory, then that directory will be used to store |
| @@ -126318,10 +126521,17 @@ | |
| 126318 | ** routine is not threadsafe. But it is safe to invoke this routine |
| 126319 | ** on when SQLite is already shut down. If SQLite is already shut down |
| 126320 | ** when this routine is invoked, then this routine is a harmless no-op. |
| 126321 | */ |
| 126322 | SQLITE_API int sqlite3_shutdown(void){ |
| 126323 | if( sqlite3GlobalConfig.isInit ){ |
| 126324 | #ifdef SQLITE_EXTRA_SHUTDOWN |
| 126325 | void SQLITE_EXTRA_SHUTDOWN(void); |
| 126326 | SQLITE_EXTRA_SHUTDOWN(); |
| 126327 | #endif |
| @@ -126633,10 +126843,15 @@ | |
| 126633 | ** heap. */ |
| 126634 | sqlite3GlobalConfig.nHeap = va_arg(ap, int); |
| 126635 | break; |
| 126636 | } |
| 126637 | #endif |
| 126638 | |
| 126639 | default: { |
| 126640 | rc = SQLITE_ERROR; |
| 126641 | break; |
| 126642 | } |
| @@ -127983,14 +128198,17 @@ | |
| 127983 | |
| 127984 | /* Initialize the output variables to -1 in case an error occurs. */ |
| 127985 | if( pnLog ) *pnLog = -1; |
| 127986 | if( pnCkpt ) *pnCkpt = -1; |
| 127987 | |
| 127988 | assert( SQLITE_CHECKPOINT_FULL>SQLITE_CHECKPOINT_PASSIVE ); |
| 127989 | assert( SQLITE_CHECKPOINT_FULL<SQLITE_CHECKPOINT_RESTART ); |
| 127990 | assert( SQLITE_CHECKPOINT_PASSIVE+2==SQLITE_CHECKPOINT_RESTART ); |
| 127991 | if( eMode<SQLITE_CHECKPOINT_PASSIVE || eMode>SQLITE_CHECKPOINT_RESTART ){ |
| 127992 | return SQLITE_MISUSE; |
| 127993 | } |
| 127994 | |
| 127995 | sqlite3_mutex_enter(db->mutex); |
| 127996 | if( zDb && zDb[0] ){ |
| @@ -128014,11 +128232,13 @@ | |
| 128014 | ** Checkpoint database zDb. If zDb is NULL, or if the buffer zDb points |
| 128015 | ** to contains a zero-length string, all attached databases are |
| 128016 | ** checkpointed. |
| 128017 | */ |
| 128018 | SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb){ |
| 128019 | return sqlite3_wal_checkpoint_v2(db, zDb, SQLITE_CHECKPOINT_PASSIVE, 0, 0); |
| 128020 | } |
| 128021 | |
| 128022 | #ifndef SQLITE_OMIT_WAL |
| 128023 | /* |
| 128024 | ** Run a checkpoint on database iDb. This is a no-op if database iDb is |
| @@ -128201,36 +128421,10 @@ | |
| 128201 | */ |
| 128202 | SQLITE_API const char *sqlite3_errstr(int rc){ |
| 128203 | return sqlite3ErrStr(rc); |
| 128204 | } |
| 128205 | |
| 128206 | /* |
| 128207 | ** Invalidate all cached KeyInfo objects for database connection "db" |
| 128208 | */ |
| 128209 | static void invalidateCachedKeyInfo(sqlite3 *db){ |
| 128210 | Db *pDb; /* A single database */ |
| 128211 | int iDb; /* The database index number */ |
| 128212 | HashElem *k; /* For looping over tables in pDb */ |
| 128213 | Table *pTab; /* A table in the database */ |
| 128214 | Index *pIdx; /* Each index */ |
| 128215 | |
| 128216 | for(iDb=0, pDb=db->aDb; iDb<db->nDb; iDb++, pDb++){ |
| 128217 | if( pDb->pBt==0 ) continue; |
| 128218 | sqlite3BtreeEnter(pDb->pBt); |
| 128219 | for(k=sqliteHashFirst(&pDb->pSchema->tblHash); k; k=sqliteHashNext(k)){ |
| 128220 | pTab = (Table*)sqliteHashData(k); |
| 128221 | for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ |
| 128222 | if( pIdx->pKeyInfo && pIdx->pKeyInfo->db==db ){ |
| 128223 | sqlite3KeyInfoUnref(pIdx->pKeyInfo); |
| 128224 | pIdx->pKeyInfo = 0; |
| 128225 | } |
| 128226 | } |
| 128227 | } |
| 128228 | sqlite3BtreeLeave(pDb->pBt); |
| 128229 | } |
| 128230 | } |
| 128231 | |
| 128232 | /* |
| 128233 | ** Create a new collating function for database "db". The name is zName |
| 128234 | ** and the encoding is enc. |
| 128235 | */ |
| 128236 | static int createCollation( |
| @@ -128270,11 +128464,10 @@ | |
| 128270 | sqlite3ErrorWithMsg(db, SQLITE_BUSY, |
| 128271 | "unable to delete/modify collation sequence due to active statements"); |
| 128272 | return SQLITE_BUSY; |
| 128273 | } |
| 128274 | sqlite3ExpirePreparedStatements(db); |
| 128275 | invalidateCachedKeyInfo(db); |
| 128276 | |
| 128277 | /* If collation sequence pColl was created directly by a call to |
| 128278 | ** sqlite3_create_collation, and not generated by synthCollSeq(), |
| 128279 | ** then any copies made by synthCollSeq() need to be invalidated. |
| 128280 | ** Also, collation destructor - CollSeq.xDel() - function may need |
| @@ -128775,10 +128968,13 @@ | |
| 128775 | | SQLITE_RecTriggers |
| 128776 | #endif |
| 128777 | #if defined(SQLITE_DEFAULT_FOREIGN_KEYS) && SQLITE_DEFAULT_FOREIGN_KEYS |
| 128778 | | SQLITE_ForeignKeys |
| 128779 | #endif |
| 128780 | ; |
| 128781 | sqlite3HashInit(&db->aCollSeq); |
| 128782 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 128783 | sqlite3HashInit(&db->aModule); |
| 128784 | #endif |
| @@ -128822,11 +129018,14 @@ | |
| 128822 | rc = SQLITE_NOMEM; |
| 128823 | } |
| 128824 | sqlite3Error(db, rc); |
| 128825 | goto opendb_out; |
| 128826 | } |
| 128827 | db->aDb[0].pSchema = sqlite3SchemaGet(db, db->aDb[0].pBt); |
| 128828 | db->aDb[1].pSchema = sqlite3SchemaGet(db, 0); |
| 128829 | |
| 128830 | /* The default safety_level for the main database is 'full'; for the temp |
| 128831 | ** database it is 'NONE'. This matches the pager layer defaults. |
| 128832 | */ |
| @@ -128980,11 +129179,11 @@ | |
| 128980 | if( zFilename8 ){ |
| 128981 | rc = openDatabase(zFilename8, ppDb, |
| 128982 | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0); |
| 128983 | assert( *ppDb || rc==SQLITE_NOMEM ); |
| 128984 | if( rc==SQLITE_OK && !DbHasProperty(*ppDb, 0, DB_SchemaLoaded) ){ |
| 128985 | ENC(*ppDb) = SQLITE_UTF16NATIVE; |
| 128986 | } |
| 128987 | }else{ |
| 128988 | rc = SQLITE_NOMEM; |
| 128989 | } |
| 128990 | sqlite3ValueFree(pVal); |
| @@ -129176,11 +129375,10 @@ | |
| 129176 | |
| 129177 | /* |
| 129178 | ** Return meta information about a specific column of a database table. |
| 129179 | ** See comment in sqlite3.h (sqlite.h.in) for details. |
| 129180 | */ |
| 129181 | #ifdef SQLITE_ENABLE_COLUMN_METADATA |
| 129182 | SQLITE_API int sqlite3_table_column_metadata( |
| 129183 | sqlite3 *db, /* Connection handle */ |
| 129184 | const char *zDbName, /* Database name or NULL */ |
| 129185 | const char *zTableName, /* Table name */ |
| 129186 | const char *zColumnName, /* Column name */ |
| @@ -129216,25 +129414,27 @@ | |
| 129216 | pTab = 0; |
| 129217 | goto error_out; |
| 129218 | } |
| 129219 | |
| 129220 | /* Find the column for which info is requested */ |
| 129221 | if( sqlite3IsRowid(zColumnName) ){ |
| 129222 | iCol = pTab->iPKey; |
| 129223 | if( iCol>=0 ){ |
| 129224 | pCol = &pTab->aCol[iCol]; |
| 129225 | } |
| 129226 | }else{ |
| 129227 | for(iCol=0; iCol<pTab->nCol; iCol++){ |
| 129228 | pCol = &pTab->aCol[iCol]; |
| 129229 | if( 0==sqlite3StrICmp(pCol->zName, zColumnName) ){ |
| 129230 | break; |
| 129231 | } |
| 129232 | } |
| 129233 | if( iCol==pTab->nCol ){ |
| 129234 | pTab = 0; |
| 129235 | goto error_out; |
| 129236 | } |
| 129237 | } |
| 129238 | |
| 129239 | /* The following block stores the meta information that will be returned |
| 129240 | ** to the caller in local variables zDataType, zCollSeq, notnull, primarykey |
| @@ -129283,11 +129483,10 @@ | |
| 129283 | sqlite3DbFree(db, zErrMsg); |
| 129284 | rc = sqlite3ApiExit(db, rc); |
| 129285 | sqlite3_mutex_leave(db->mutex); |
| 129286 | return rc; |
| 129287 | } |
| 129288 | #endif |
| 129289 | |
| 129290 | /* |
| 129291 | ** Sleep for a little while. Return the amount of time slept. |
| 129292 | */ |
| 129293 | SQLITE_API int sqlite3_sleep(int ms){ |
| @@ -129722,32 +129921,34 @@ | |
| 129722 | /* |
| 129723 | ** Return the filename of the database associated with a database |
| 129724 | ** connection. |
| 129725 | */ |
| 129726 | SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName){ |
| 129727 | #ifdef SQLITE_ENABLE_API_ARMOR |
| 129728 | if( !sqlite3SafetyCheckOk(db) ){ |
| 129729 | (void)SQLITE_MISUSE_BKPT; |
| 129730 | return 0; |
| 129731 | } |
| 129732 | #endif |
| 129733 | Btree *pBt = sqlite3DbNameToBtree(db, zDbName); |
| 129734 | return pBt ? sqlite3BtreeGetFilename(pBt) : 0; |
| 129735 | } |
| 129736 | |
| 129737 | /* |
| 129738 | ** Return 1 if database is read-only or 0 if read/write. Return -1 if |
| 129739 | ** no such database exists. |
| 129740 | */ |
| 129741 | SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName){ |
| 129742 | #ifdef SQLITE_ENABLE_API_ARMOR |
| 129743 | if( !sqlite3SafetyCheckOk(db) ){ |
| 129744 | (void)SQLITE_MISUSE_BKPT; |
| 129745 | return -1; |
| 129746 | } |
| 129747 | #endif |
| 129748 | Btree *pBt = sqlite3DbNameToBtree(db, zDbName); |
| 129749 | return pBt ? sqlite3BtreeIsReadonly(pBt) : -1; |
| 129750 | } |
| 129751 | |
| 129752 | /************** End of main.c ************************************************/ |
| 129753 | /************** Begin file notify.c ******************************************/ |
| @@ -139164,11 +139365,11 @@ | |
| 139164 | ** Return true if the m-value for z is 1 or more. In other words, |
| 139165 | ** return true if z contains at least one vowel that is followed |
| 139166 | ** by a consonant. |
| 139167 | ** |
| 139168 | ** In this routine z[] is in reverse order. So we are really looking |
| 139169 | ** for an instance of of a consonant followed by a vowel. |
| 139170 | */ |
| 139171 | static int m_gt_0(const char *z){ |
| 139172 | while( isVowel(z) ){ z++; } |
| 139173 | if( *z==0 ) return 0; |
| 139174 | while( isConsonant(z) ){ z++; } |
| @@ -149954,11 +150155,11 @@ | |
| 149954 | } |
| 149955 | i = pCur->nPoint++; |
| 149956 | pNew = pCur->aPoint + i; |
| 149957 | pNew->rScore = rScore; |
| 149958 | pNew->iLevel = iLevel; |
| 149959 | assert( iLevel>=0 && iLevel<=RTREE_MAX_DEPTH ); |
| 149960 | while( i>0 ){ |
| 149961 | RtreeSearchPoint *pParent; |
| 149962 | j = (i-1)/2; |
| 149963 | pParent = pCur->aPoint + j; |
| 149964 | if( rtreeSearchPointCompare(pNew, pParent)>=0 ) break; |
| 149965 |
| --- src/sqlite3.c | |
| +++ src/sqlite3.c | |
| @@ -231,11 +231,11 @@ | |
| 231 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 232 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 233 | */ |
| 234 | #define SQLITE_VERSION "3.8.8" |
| 235 | #define SQLITE_VERSION_NUMBER 3008008 |
| 236 | #define SQLITE_SOURCE_ID "2015-01-03 18:59:17 23d4c07eb81db5a5c6beb56b5820f0b6501f1fb6" |
| 237 | |
| 238 | /* |
| 239 | ** CAPI3REF: Run-Time Library Version Numbers |
| 240 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 241 | ** |
| @@ -323,11 +323,11 @@ | |
| 323 | ** This interface only reports on the compile-time mutex setting |
| 324 | ** of the [SQLITE_THREADSAFE] flag. If SQLite is compiled with |
| 325 | ** SQLITE_THREADSAFE=1 or =2 then mutexes are enabled by default but |
| 326 | ** can be fully or partially disabled using a call to [sqlite3_config()] |
| 327 | ** with the verbs [SQLITE_CONFIG_SINGLETHREAD], [SQLITE_CONFIG_MULTITHREAD], |
| 328 | ** or [SQLITE_CONFIG_SERIALIZED]. ^(The return value of the |
| 329 | ** sqlite3_threadsafe() function shows only the compile-time setting of |
| 330 | ** thread safety, not any run-time changes to that setting made by |
| 331 | ** sqlite3_config(). In other words, the return value from sqlite3_threadsafe() |
| 332 | ** is unchanged by calls to sqlite3_config().)^ |
| 333 | ** |
| @@ -1343,11 +1343,11 @@ | |
| 1343 | ** <li> SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED |
| 1344 | ** <li> SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE |
| 1345 | ** </ul> |
| 1346 | ** |
| 1347 | ** When unlocking, the same SHARED or EXCLUSIVE flag must be supplied as |
| 1348 | ** was given on the corresponding lock. |
| 1349 | ** |
| 1350 | ** The xShmLock method can transition between unlocked and SHARED or |
| 1351 | ** between unlocked and EXCLUSIVE. It cannot transition between SHARED |
| 1352 | ** and EXCLUSIVE. |
| 1353 | */ |
| @@ -1646,12 +1646,12 @@ | |
| 1646 | ** tracks memory usage, for example. </dd> |
| 1647 | ** |
| 1648 | ** [[SQLITE_CONFIG_MEMSTATUS]] <dt>SQLITE_CONFIG_MEMSTATUS</dt> |
| 1649 | ** <dd> ^The SQLITE_CONFIG_MEMSTATUS option takes single argument of type int, |
| 1650 | ** interpreted as a boolean, which enables or disables the collection of |
| 1651 | ** memory allocation statistics. ^(When memory allocation statistics are |
| 1652 | ** disabled, the following SQLite interfaces become non-operational: |
| 1653 | ** <ul> |
| 1654 | ** <li> [sqlite3_memory_used()] |
| 1655 | ** <li> [sqlite3_memory_highwater()] |
| 1656 | ** <li> [sqlite3_soft_heap_limit64()] |
| 1657 | ** <li> [sqlite3_status()] |
| @@ -1688,14 +1688,15 @@ | |
| 1688 | ** that SQLite can use for the database page cache with the default page |
| 1689 | ** cache implementation. |
| 1690 | ** This configuration should not be used if an application-define page |
| 1691 | ** cache implementation is loaded using the [SQLITE_CONFIG_PCACHE2] |
| 1692 | ** configuration option. |
| 1693 | ** ^There are three arguments to SQLITE_CONFIG_PAGECACHE: A pointer to |
| 1694 | ** 8-byte aligned |
| 1695 | ** memory, the size of each page buffer (sz), and the number of pages (N). |
| 1696 | ** The sz argument should be the size of the largest database page |
| 1697 | ** (a power of two between 512 and 65536) plus some extra bytes for each |
| 1698 | ** page header. ^The number of extra bytes needed by the page header |
| 1699 | ** can be determined using the [SQLITE_CONFIG_PCACHE_HDRSZ] option |
| 1700 | ** to [sqlite3_config()]. |
| 1701 | ** ^It is harmless, apart from the wasted memory, |
| 1702 | ** for the sz parameter to be larger than necessary. The first |
| @@ -1708,11 +1709,12 @@ | |
| 1709 | ** SQLite goes to [sqlite3_malloc()] for the additional storage space.</dd> |
| 1710 | ** |
| 1711 | ** [[SQLITE_CONFIG_HEAP]] <dt>SQLITE_CONFIG_HEAP</dt> |
| 1712 | ** <dd> ^The SQLITE_CONFIG_HEAP option specifies a static memory buffer |
| 1713 | ** that SQLite will use for all of its dynamic memory allocation needs |
| 1714 | ** beyond those provided for by [SQLITE_CONFIG_SCRATCH] and |
| 1715 | ** [SQLITE_CONFIG_PAGECACHE]. |
| 1716 | ** ^The SQLITE_CONFIG_HEAP option is only available if SQLite is compiled |
| 1717 | ** with either [SQLITE_ENABLE_MEMSYS3] or [SQLITE_ENABLE_MEMSYS5] and returns |
| 1718 | ** [SQLITE_ERROR] if invoked otherwise. |
| 1719 | ** ^There are three arguments to SQLITE_CONFIG_HEAP: |
| 1720 | ** An 8-byte aligned pointer to the memory, |
| @@ -1728,13 +1730,13 @@ | |
| 1730 | ** for the minimum allocation size are 2**5 through 2**8.</dd> |
| 1731 | ** |
| 1732 | ** [[SQLITE_CONFIG_MUTEX]] <dt>SQLITE_CONFIG_MUTEX</dt> |
| 1733 | ** <dd> ^(The SQLITE_CONFIG_MUTEX option takes a single argument which is a |
| 1734 | ** pointer to an instance of the [sqlite3_mutex_methods] structure. |
| 1735 | ** The argument specifies alternative low-level mutex routines to be used |
| 1736 | ** in place the mutex routines built into SQLite.)^ ^SQLite makes a copy of |
| 1737 | ** the content of the [sqlite3_mutex_methods] structure before the call to |
| 1738 | ** [sqlite3_config()] returns. ^If SQLite is compiled with |
| 1739 | ** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then |
| 1740 | ** the entire mutexing subsystem is omitted from the build and hence calls to |
| 1741 | ** [sqlite3_config()] with the SQLITE_CONFIG_MUTEX configuration option will |
| 1742 | ** return [SQLITE_ERROR].</dd> |
| @@ -1768,12 +1770,12 @@ | |
| 1770 | ** the interface to a custom page cache implementation.)^ |
| 1771 | ** ^SQLite makes a copy of the [sqlite3_pcache_methods2] object.</dd> |
| 1772 | ** |
| 1773 | ** [[SQLITE_CONFIG_GETPCACHE2]] <dt>SQLITE_CONFIG_GETPCACHE2</dt> |
| 1774 | ** <dd> ^(The SQLITE_CONFIG_GETPCACHE2 option takes a single argument which |
| 1775 | ** is a pointer to an [sqlite3_pcache_methods2] object. SQLite copies of |
| 1776 | ** the current page cache implementation into that object.)^ </dd> |
| 1777 | ** |
| 1778 | ** [[SQLITE_CONFIG_LOG]] <dt>SQLITE_CONFIG_LOG</dt> |
| 1779 | ** <dd> The SQLITE_CONFIG_LOG option is used to configure the SQLite |
| 1780 | ** global [error log]. |
| 1781 | ** (^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a |
| @@ -1794,12 +1796,13 @@ | |
| 1796 | ** function must be threadsafe. </dd> |
| 1797 | ** |
| 1798 | ** [[SQLITE_CONFIG_URI]] <dt>SQLITE_CONFIG_URI |
| 1799 | ** <dd>^(The SQLITE_CONFIG_URI option takes a single argument of type int. |
| 1800 | ** If non-zero, then URI handling is globally enabled. If the parameter is zero, |
| 1801 | ** then URI handling is globally disabled.)^ ^If URI handling is globally |
| 1802 | ** enabled, all filenames passed to [sqlite3_open()], [sqlite3_open_v2()], |
| 1803 | ** [sqlite3_open16()] or |
| 1804 | ** specified as part of [ATTACH] commands are interpreted as URIs, regardless |
| 1805 | ** of whether or not the [SQLITE_OPEN_URI] flag is set when the database |
| 1806 | ** connection is opened. ^If it is globally disabled, filenames are |
| 1807 | ** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the |
| 1808 | ** database connection is opened. ^(By default, URI handling is globally |
| @@ -1857,22 +1860,33 @@ | |
| 1860 | ** changed to its compile-time default. |
| 1861 | ** |
| 1862 | ** [[SQLITE_CONFIG_WIN32_HEAPSIZE]] |
| 1863 | ** <dt>SQLITE_CONFIG_WIN32_HEAPSIZE |
| 1864 | ** <dd>^The SQLITE_CONFIG_WIN32_HEAPSIZE option is only available if SQLite is |
| 1865 | ** compiled for Windows with the [SQLITE_WIN32_MALLOC] pre-processor macro |
| 1866 | ** defined. ^SQLITE_CONFIG_WIN32_HEAPSIZE takes a 32-bit unsigned integer value |
| 1867 | ** that specifies the maximum size of the created heap. |
| 1868 | ** </dl> |
| 1869 | ** |
| 1870 | ** [[SQLITE_CONFIG_PCACHE_HDRSZ]] |
| 1871 | ** <dt>SQLITE_CONFIG_PCACHE_HDRSZ |
| 1872 | ** <dd>^The SQLITE_CONFIG_PCACHE_HDRSZ option takes a single parameter which |
| 1873 | ** is a pointer to an integer and writes into that integer the number of extra |
| 1874 | ** bytes per page required for each page in [SQLITE_CONFIG_PAGECACHE]. |
| 1875 | ** The amount of extra space required can change depending on the compiler, |
| 1876 | ** target platform, and SQLite version. |
| 1877 | ** |
| 1878 | ** [[SQLITE_CONFIG_PMASZ]] |
| 1879 | ** <dt>SQLITE_CONFIG_PMASZ |
| 1880 | ** <dd>^The SQLITE_CONFIG_PMASZ option takes a single parameter which |
| 1881 | ** is an unsigned integer and sets the "Minimum PMA Size" for the multithreaded |
| 1882 | ** sorter to that integer. The default minimum PMA Size is set by the |
| 1883 | ** [SQLITE_SORTER_PMASZ] compile-time option. New threads are launched |
| 1884 | ** to help with sort operations when multithreaded sorting |
| 1885 | ** is enabled (using the [PRAGMA threads] command) and the amount of content |
| 1886 | ** to be sorted exceeds the page size times the minimum of the |
| 1887 | ** [PRAGMA cache_size] setting and this value. |
| 1888 | ** </dl> |
| 1889 | */ |
| 1890 | #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ |
| 1891 | #define SQLITE_CONFIG_MULTITHREAD 2 /* nil */ |
| 1892 | #define SQLITE_CONFIG_SERIALIZED 3 /* nil */ |
| @@ -1895,10 +1909,11 @@ | |
| 1909 | #define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */ |
| 1910 | #define SQLITE_CONFIG_SQLLOG 21 /* xSqllog, void* */ |
| 1911 | #define SQLITE_CONFIG_MMAP_SIZE 22 /* sqlite3_int64, sqlite3_int64 */ |
| 1912 | #define SQLITE_CONFIG_WIN32_HEAPSIZE 23 /* int nByte */ |
| 1913 | #define SQLITE_CONFIG_PCACHE_HDRSZ 24 /* int *psz */ |
| 1914 | #define SQLITE_CONFIG_PMASZ 25 /* unsigned int szPma */ |
| 1915 | |
| 1916 | /* |
| 1917 | ** CAPI3REF: Database Connection Configuration Options |
| 1918 | ** |
| 1919 | ** These constants are the available integer configuration options that |
| @@ -2171,10 +2186,11 @@ | |
| 2186 | SQLITE_API int sqlite3_complete(const char *sql); |
| 2187 | SQLITE_API int sqlite3_complete16(const void *sql); |
| 2188 | |
| 2189 | /* |
| 2190 | ** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors |
| 2191 | ** KEYWORDS: {busy-handler callback} {busy handler} |
| 2192 | ** |
| 2193 | ** ^The sqlite3_busy_handler(D,X,P) routine sets a callback function X |
| 2194 | ** that might be invoked with argument P whenever |
| 2195 | ** an attempt is made to access a database table associated with |
| 2196 | ** [database connection] D when another thread |
| @@ -2187,11 +2203,11 @@ | |
| 2203 | ** is not NULL, then the callback might be invoked with two arguments. |
| 2204 | ** |
| 2205 | ** ^The first argument to the busy handler is a copy of the void* pointer which |
| 2206 | ** is the third argument to sqlite3_busy_handler(). ^The second argument to |
| 2207 | ** the busy handler callback is the number of times that the busy handler has |
| 2208 | ** been invoked previously for the same locking event. ^If the |
| 2209 | ** busy callback returns 0, then no additional attempts are made to |
| 2210 | ** access the database and [SQLITE_BUSY] is returned |
| 2211 | ** to the application. |
| 2212 | ** ^If the callback returns non-zero, then another attempt |
| 2213 | ** is made to access the database and the cycle repeats. |
| @@ -4642,11 +4658,12 @@ | |
| 4658 | ** If these routines are called from within the different thread |
| 4659 | ** than the one containing the application-defined function that received |
| 4660 | ** the [sqlite3_context] pointer, the results are undefined. |
| 4661 | */ |
| 4662 | SQLITE_API void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); |
| 4663 | SQLITE_API void sqlite3_result_blob64(sqlite3_context*,const void*, |
| 4664 | sqlite3_uint64,void(*)(void*)); |
| 4665 | SQLITE_API void sqlite3_result_double(sqlite3_context*, double); |
| 4666 | SQLITE_API void sqlite3_result_error(sqlite3_context*, const char*, int); |
| 4667 | SQLITE_API void sqlite3_result_error16(sqlite3_context*, const void*, int); |
| 4668 | SQLITE_API void sqlite3_result_error_toobig(sqlite3_context*); |
| 4669 | SQLITE_API void sqlite3_result_error_nomem(sqlite3_context*); |
| @@ -5274,24 +5291,31 @@ | |
| 5291 | |
| 5292 | |
| 5293 | /* |
| 5294 | ** CAPI3REF: Extract Metadata About A Column Of A Table |
| 5295 | ** |
| 5296 | ** ^(The sqlite3_table_column_metadata(X,D,T,C,....) routine returns |
| 5297 | ** information about column C of table T in database D |
| 5298 | ** on [database connection] X.)^ ^The sqlite3_table_column_metadata() |
| 5299 | ** interface returns SQLITE_OK and fills in the non-NULL pointers in |
| 5300 | ** the final five arguments with appropriate values if the specified |
| 5301 | ** column exists. ^The sqlite3_table_column_metadata() interface returns |
| 5302 | ** SQLITE_ERROR and if the specified column does not exist. |
| 5303 | ** ^If the column-name parameter to sqlite3_table_column_metadata() is a |
| 5304 | ** NULL pointer, then this routine simply checks for the existance of the |
| 5305 | ** table and returns SQLITE_OK if the table exists and SQLITE_ERROR if it |
| 5306 | ** does not. |
| 5307 | ** |
| 5308 | ** ^The column is identified by the second, third and fourth parameters to |
| 5309 | ** this function. ^(The second parameter is either the name of the database |
| 5310 | ** (i.e. "main", "temp", or an attached database) containing the specified |
| 5311 | ** table or NULL.)^ ^If it is NULL, then all attached databases are searched |
| 5312 | ** for the table using the same algorithm used by the database engine to |
| 5313 | ** resolve unqualified table references. |
| 5314 | ** |
| 5315 | ** ^The third and fourth parameters to this function are the table and column |
| 5316 | ** name of the desired column, respectively. |
| 5317 | ** |
| 5318 | ** ^Metadata is returned by writing to the memory locations passed as the 5th |
| 5319 | ** and subsequent parameters to this function. ^Any of these arguments may be |
| 5320 | ** NULL, in which case the corresponding element of metadata is omitted. |
| 5321 | ** |
| @@ -5306,36 +5330,33 @@ | |
| 5330 | ** <tr><td> 9th <td> int <td> True if column is [AUTOINCREMENT] |
| 5331 | ** </table> |
| 5332 | ** </blockquote>)^ |
| 5333 | ** |
| 5334 | ** ^The memory pointed to by the character pointers returned for the |
| 5335 | ** declaration type and collation sequence is valid until the next |
| 5336 | ** call to any SQLite API function. |
| 5337 | ** |
| 5338 | ** ^If the specified table is actually a view, an [error code] is returned. |
| 5339 | ** |
| 5340 | ** ^If the specified column is "rowid", "oid" or "_rowid_" and the table |
| 5341 | ** is not a [WITHOUT ROWID] table and an |
| 5342 | ** [INTEGER PRIMARY KEY] column has been explicitly declared, then the output |
| 5343 | ** parameters are set for the explicitly declared column. ^(If there is no |
| 5344 | ** [INTEGER PRIMARY KEY] column, then the outputs |
| 5345 | ** for the [rowid] are set as follows: |
| 5346 | ** |
| 5347 | ** <pre> |
| 5348 | ** data type: "INTEGER" |
| 5349 | ** collation sequence: "BINARY" |
| 5350 | ** not null: 0 |
| 5351 | ** primary key: 1 |
| 5352 | ** auto increment: 0 |
| 5353 | ** </pre>)^ |
| 5354 | ** |
| 5355 | ** ^This function causes all database schemas to be read from disk and |
| 5356 | ** parsed, if that has not already been done, and returns an error if |
| 5357 | ** any errors are encountered while loading the schema. |
| 5358 | */ |
| 5359 | SQLITE_API int sqlite3_table_column_metadata( |
| 5360 | sqlite3 *db, /* Connection handle */ |
| 5361 | const char *zDbName, /* Database name or NULL */ |
| 5362 | const char *zTableName, /* Table name */ |
| @@ -7298,16 +7319,14 @@ | |
| 7319 | |
| 7320 | /* |
| 7321 | ** CAPI3REF: Write-Ahead Log Commit Hook |
| 7322 | ** |
| 7323 | ** ^The [sqlite3_wal_hook()] function is used to register a callback that |
| 7324 | ** is invoked each time data is committed to a database in wal mode. |
| 7325 | ** |
| 7326 | ** ^(The callback is invoked by SQLite after the commit has taken place and |
| 7327 | ** the associated write-lock on the database released)^, so the implementation |
| 7328 | ** may read, write or [checkpoint] the database as required. |
| 7329 | ** |
| 7330 | ** ^The first parameter passed to the callback function when it is invoked |
| 7331 | ** is a copy of the third parameter passed to sqlite3_wal_hook() when |
| 7332 | ** registering the callback. ^The second is a copy of the database handle. |
| @@ -7368,101 +7387,118 @@ | |
| 7387 | SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N); |
| 7388 | |
| 7389 | /* |
| 7390 | ** CAPI3REF: Checkpoint a database |
| 7391 | ** |
| 7392 | ** ^(The sqlite3_wal_checkpoint(D,X) is equivalent to |
| 7393 | ** [sqlite3_wal_checkpoint_v2](D,X,[SQLITE_CHECKPOINT_PASSIVE],0,0).)^ |
| 7394 | ** |
| 7395 | ** In brief, sqlite3_wal_checkpoint(D,X) causes the content in the |
| 7396 | ** [write-ahead log] for database X on [database connection] D to be |
| 7397 | ** transferred into the database file and for the write-ahead log to |
| 7398 | ** be reset. See the [checkpointing] documentation for addition |
| 7399 | ** information. |
| 7400 | ** |
| 7401 | ** This interface used to be the only way to cause a checkpoint to |
| 7402 | ** occur. But then the newer and more powerful [sqlite3_wal_checkpoint_v2()] |
| 7403 | ** interface was added. This interface is retained for backwards |
| 7404 | ** compatibility and as a convenience for applications that need to manually |
| 7405 | ** start a callback but which do not need the full power (and corresponding |
| 7406 | ** complication) of [sqlite3_wal_checkpoint_v2()]. |
| 7407 | */ |
| 7408 | SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb); |
| 7409 | |
| 7410 | /* |
| 7411 | ** CAPI3REF: Checkpoint a database |
| 7412 | ** |
| 7413 | ** ^(The sqlite3_wal_checkpoint_v2(D,X,M,L,C) interface runs a checkpoint |
| 7414 | ** operation on database X of [database connection] D in mode M. Status |
| 7415 | ** information is written back into integers pointed to by L and C.)^ |
| 7416 | ** ^(The M parameter must be a valid [checkpoint mode]:)^ |
| 7417 | ** |
| 7418 | ** <dl> |
| 7419 | ** <dt>SQLITE_CHECKPOINT_PASSIVE<dd> |
| 7420 | ** ^Checkpoint as many frames as possible without waiting for any database |
| 7421 | ** readers or writers to finish, then sync the database file if all frames |
| 7422 | ** in the log were checkpointed. ^The [busy-handler callback] |
| 7423 | ** is never invoked in the SQLITE_CHECKPOINT_PASSIVE mode. |
| 7424 | ** ^On the other hand, passive mode might leave the checkpoint unfinished |
| 7425 | ** if there are concurrent readers or writers. |
| 7426 | ** |
| 7427 | ** <dt>SQLITE_CHECKPOINT_FULL<dd> |
| 7428 | ** ^This mode blocks (it invokes the |
| 7429 | ** [sqlite3_busy_handler|busy-handler callback]) until there is no |
| 7430 | ** database writer and all readers are reading from the most recent database |
| 7431 | ** snapshot. ^It then checkpoints all frames in the log file and syncs the |
| 7432 | ** database file. ^This mode blocks new database writers while it is pending, |
| 7433 | ** but new database readers are allowed to continue unimpeded. |
| 7434 | ** |
| 7435 | ** <dt>SQLITE_CHECKPOINT_RESTART<dd> |
| 7436 | ** ^This mode works the same way as SQLITE_CHECKPOINT_FULL with the addition |
| 7437 | ** that after checkpointing the log file it blocks (calls the |
| 7438 | ** [busy-handler callback]) |
| 7439 | ** until all readers are reading from the database file only. ^This ensures |
| 7440 | ** that the next writer will restart the log file from the beginning. |
| 7441 | ** ^Like SQLITE_CHECKPOINT_FULL, this mode blocks new |
| 7442 | ** database writer attempts while it is pending, but does not impede readers. |
| 7443 | ** |
| 7444 | ** <dt>SQLITE_CHECKPOINT_TRUNCATE<dd> |
| 7445 | ** ^This mode works the same way as SQLITE_CHECKPOINT_RESTART with the |
| 7446 | ** addition that it also truncates the log file to zero bytes just prior |
| 7447 | ** to a successful return. |
| 7448 | ** </dl> |
| 7449 | ** |
| 7450 | ** ^If pnLog is not NULL, then *pnLog is set to the total number of frames in |
| 7451 | ** the log file or to -1 if the checkpoint could not run because |
| 7452 | ** of an error or because the database is not in [WAL mode]. ^If pnCkpt is not |
| 7453 | ** NULL,then *pnCkpt is set to the total number of checkpointed frames in the |
| 7454 | ** log file (including any that were already checkpointed before the function |
| 7455 | ** was called) or to -1 if the checkpoint could not run due to an error or |
| 7456 | ** because the database is not in WAL mode. ^Note that upon successful |
| 7457 | ** completion of an SQLITE_CHECKPOINT_TRUNCATE, the log file will have been |
| 7458 | ** truncated to zero bytes and so both *pnLog and *pnCkpt will be set to zero. |
| 7459 | ** |
| 7460 | ** ^All calls obtain an exclusive "checkpoint" lock on the database file. ^If |
| 7461 | ** any other process is running a checkpoint operation at the same time, the |
| 7462 | ** lock cannot be obtained and SQLITE_BUSY is returned. ^Even if there is a |
| 7463 | ** busy-handler configured, it will not be invoked in this case. |
| 7464 | ** |
| 7465 | ** ^The SQLITE_CHECKPOINT_FULL, RESTART and TRUNCATE modes also obtain the |
| 7466 | ** exclusive "writer" lock on the database file. ^If the writer lock cannot be |
| 7467 | ** obtained immediately, and a busy-handler is configured, it is invoked and |
| 7468 | ** the writer lock retried until either the busy-handler returns 0 or the lock |
| 7469 | ** is successfully obtained. ^The busy-handler is also invoked while waiting for |
| 7470 | ** database readers as described above. ^If the busy-handler returns 0 before |
| 7471 | ** the writer lock is obtained or while waiting for database readers, the |
| 7472 | ** checkpoint operation proceeds from that point in the same way as |
| 7473 | ** SQLITE_CHECKPOINT_PASSIVE - checkpointing as many frames as possible |
| 7474 | ** without blocking any further. ^SQLITE_BUSY is returned in this case. |
| 7475 | ** |
| 7476 | ** ^If parameter zDb is NULL or points to a zero length string, then the |
| 7477 | ** specified operation is attempted on all WAL databases [attached] to |
| 7478 | ** [database connection] db. In this case the |
| 7479 | ** values written to output parameters *pnLog and *pnCkpt are undefined. ^If |
| 7480 | ** an SQLITE_BUSY error is encountered when processing one or more of the |
| 7481 | ** attached WAL databases, the operation is still attempted on any remaining |
| 7482 | ** attached databases and SQLITE_BUSY is returned at the end. ^If any other |
| 7483 | ** error occurs while processing an attached database, processing is abandoned |
| 7484 | ** and the error code is returned to the caller immediately. ^If no error |
| 7485 | ** (SQLITE_BUSY or otherwise) is encountered while processing the attached |
| 7486 | ** databases, SQLITE_OK is returned. |
| 7487 | ** |
| 7488 | ** ^If database zDb is the name of an attached database that is not in WAL |
| 7489 | ** mode, SQLITE_OK is returned and both *pnLog and *pnCkpt set to -1. ^If |
| 7490 | ** zDb is not NULL (or a zero length string) and is not the name of any |
| 7491 | ** attached database, SQLITE_ERROR is returned to the caller. |
| 7492 | ** |
| 7493 | ** ^Unless it returns SQLITE_MISUSE, |
| 7494 | ** the sqlite3_wal_checkpoint_v2() interface |
| 7495 | ** sets the error information that is queried by |
| 7496 | ** [sqlite3_errcode()] and [sqlite3_errmsg()]. |
| 7497 | ** |
| 7498 | ** ^The [PRAGMA wal_checkpoint] command can be used to invoke this interface |
| 7499 | ** from SQL. |
| 7500 | */ |
| 7501 | SQLITE_API int sqlite3_wal_checkpoint_v2( |
| 7502 | sqlite3 *db, /* Database handle */ |
| 7503 | const char *zDb, /* Name of attached database (or NULL) */ |
| 7504 | int eMode, /* SQLITE_CHECKPOINT_* value */ |
| @@ -7469,20 +7505,22 @@ | |
| 7505 | int *pnLog, /* OUT: Size of WAL log in frames */ |
| 7506 | int *pnCkpt /* OUT: Total number of frames checkpointed */ |
| 7507 | ); |
| 7508 | |
| 7509 | /* |
| 7510 | ** CAPI3REF: Checkpoint Mode Values |
| 7511 | ** KEYWORDS: {checkpoint mode} |
| 7512 | ** |
| 7513 | ** These constants define all valid values for the "checkpoint mode" passed |
| 7514 | ** as the third parameter to the [sqlite3_wal_checkpoint_v2()] interface. |
| 7515 | ** See the [sqlite3_wal_checkpoint_v2()] documentation for details on the |
| 7516 | ** meaning of each of these checkpoint modes. |
| 7517 | */ |
| 7518 | #define SQLITE_CHECKPOINT_PASSIVE 0 /* Do as much as possible w/o blocking */ |
| 7519 | #define SQLITE_CHECKPOINT_FULL 1 /* Wait for writers, then checkpoint */ |
| 7520 | #define SQLITE_CHECKPOINT_RESTART 2 /* Like FULL but wait for for readers */ |
| 7521 | #define SQLITE_CHECKPOINT_TRUNCATE 3 /* Like RESTART but also truncate WAL */ |
| 7522 | |
| 7523 | /* |
| 7524 | ** CAPI3REF: Virtual Table Interface Configuration |
| 7525 | ** |
| 7526 | ** This function may be called by either the [xConnect] or [xCreate] method |
| @@ -7577,16 +7615,16 @@ | |
| 7615 | ** [sqlite3_stmt_scanstatus(S,X,T,V)] interface. Each constant designates a |
| 7616 | ** different metric for sqlite3_stmt_scanstatus() to return. |
| 7617 | ** |
| 7618 | ** <dl> |
| 7619 | ** [[SQLITE_SCANSTAT_NLOOP]] <dt>SQLITE_SCANSTAT_NLOOP</dt> |
| 7620 | ** <dd>^The [sqlite3_int64] variable pointed to by the T parameter will be |
| 7621 | ** set to the total number of times that the X-th loop has run.</dd> |
| 7622 | ** |
| 7623 | ** [[SQLITE_SCANSTAT_NVISIT]] <dt>SQLITE_SCANSTAT_NVISIT</dt> |
| 7624 | ** <dd>^The [sqlite3_int64] variable pointed to by the T parameter will be set |
| 7625 | ** to the total number of rows examined by all iterations of the X-th loop.</dd> |
| 7626 | ** |
| 7627 | ** [[SQLITE_SCANSTAT_EST]] <dt>SQLITE_SCANSTAT_EST</dt> |
| 7628 | ** <dd>^The "double" variable pointed to by the T parameter will be set to the |
| 7629 | ** query planner's estimate for the average number of rows output from each |
| 7630 | ** iteration of the X-th loop. If the query planner's estimates was accurate, |
| @@ -7593,18 +7631,18 @@ | |
| 7631 | ** then this value will approximate the quotient NVISIT/NLOOP and the |
| 7632 | ** product of this value for all prior loops with the same SELECTID will |
| 7633 | ** be the NLOOP value for the current loop. |
| 7634 | ** |
| 7635 | ** [[SQLITE_SCANSTAT_NAME]] <dt>SQLITE_SCANSTAT_NAME</dt> |
| 7636 | ** <dd>^The "const char *" variable pointed to by the T parameter will be set |
| 7637 | ** to a zero-terminated UTF-8 string containing the name of the index or table |
| 7638 | ** used for the X-th loop. |
| 7639 | ** |
| 7640 | ** [[SQLITE_SCANSTAT_EXPLAIN]] <dt>SQLITE_SCANSTAT_EXPLAIN</dt> |
| 7641 | ** <dd>^The "const char *" variable pointed to by the T parameter will be set |
| 7642 | ** to a zero-terminated UTF-8 string containing the [EXPLAIN QUERY PLAN] |
| 7643 | ** description for the X-th loop. |
| 7644 | ** |
| 7645 | ** [[SQLITE_SCANSTAT_SELECTID]] <dt>SQLITE_SCANSTAT_SELECT</dt> |
| 7646 | ** <dd>^The "int" variable pointed to by the T parameter will be set to the |
| 7647 | ** "select-id" for the X-th loop. The select-id identifies which query or |
| 7648 | ** subquery the loop is part of. The main query has a select-id of zero. |
| @@ -7623,12 +7661,12 @@ | |
| 7661 | ** CAPI3REF: Prepared Statement Scan Status |
| 7662 | ** |
| 7663 | ** Return status data for a single loop within query pStmt. |
| 7664 | ** |
| 7665 | ** The "iScanStatusOp" parameter determines which status information to return. |
| 7666 | ** The "iScanStatusOp" must be one of the [scanstatus options] or the behavior |
| 7667 | ** of this interface is undefined. |
| 7668 | ** ^The requested measurement is written into a variable pointed to by |
| 7669 | ** the "pOut" parameter. |
| 7670 | ** Parameter "idx" identifies the specific loop to retrieve statistics for. |
| 7671 | ** Loops are numbered starting from zero. ^If idx is out of range - less than |
| 7672 | ** zero or greater than or equal to the total number of loops used to implement |
| @@ -9072,11 +9110,11 @@ | |
| 9110 | #define _BTREE_H_ |
| 9111 | |
| 9112 | /* TODO: This definition is just included so other modules compile. It |
| 9113 | ** needs to be revisited. |
| 9114 | */ |
| 9115 | #define SQLITE_N_BTREE_META 16 |
| 9116 | |
| 9117 | /* |
| 9118 | ** If defined as non-zero, auto-vacuum is enabled by default. Otherwise |
| 9119 | ** it must be turned on for each database using "PRAGMA auto_vacuum = 1". |
| 9120 | */ |
| @@ -9187,10 +9225,15 @@ | |
| 9225 | ** offset = 36 + (idx * 4) |
| 9226 | ** |
| 9227 | ** For example, the free-page-count field is located at byte offset 36 of |
| 9228 | ** the database file header. The incr-vacuum-flag field is located at |
| 9229 | ** byte offset 64 (== 36+4*7). |
| 9230 | ** |
| 9231 | ** The BTREE_DATA_VERSION value is not really a value stored in the header. |
| 9232 | ** It is a read-only number computed by the pager. But we merge it with |
| 9233 | ** the header value access routines since its access pattern is the same. |
| 9234 | ** Call it a "virtual meta value". |
| 9235 | */ |
| 9236 | #define BTREE_FREE_PAGE_COUNT 0 |
| 9237 | #define BTREE_SCHEMA_VERSION 1 |
| 9238 | #define BTREE_FILE_FORMAT 2 |
| 9239 | #define BTREE_DEFAULT_CACHE_SIZE 3 |
| @@ -9197,10 +9240,11 @@ | |
| 9240 | #define BTREE_LARGEST_ROOT_PAGE 4 |
| 9241 | #define BTREE_TEXT_ENCODING 5 |
| 9242 | #define BTREE_USER_VERSION 6 |
| 9243 | #define BTREE_INCR_VACUUM 7 |
| 9244 | #define BTREE_APPLICATION_ID 8 |
| 9245 | #define BTREE_DATA_VERSION 15 /* A virtual meta-value */ |
| 9246 | |
| 9247 | /* |
| 9248 | ** Values that may be OR'd together to form the second argument of an |
| 9249 | ** sqlite3BtreeCursorHints() call. |
| 9250 | */ |
| @@ -9978,10 +10022,11 @@ | |
| 10022 | SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager); |
| 10023 | #endif |
| 10024 | |
| 10025 | /* Functions used to query pager state and configuration. */ |
| 10026 | SQLITE_PRIVATE u8 sqlite3PagerIsreadonly(Pager*); |
| 10027 | SQLITE_PRIVATE u32 sqlite3PagerDataVersion(Pager*); |
| 10028 | SQLITE_PRIVATE int sqlite3PagerRefcount(Pager*); |
| 10029 | SQLITE_PRIVATE int sqlite3PagerMemUsed(Pager*); |
| 10030 | SQLITE_PRIVATE const char *sqlite3PagerFilename(Pager*, int); |
| 10031 | SQLITE_PRIVATE const sqlite3_vfs *sqlite3PagerVfs(Pager*); |
| 10032 | SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager*); |
| @@ -10719,10 +10764,11 @@ | |
| 10764 | i64 szMmap; /* Default mmap_size setting */ |
| 10765 | unsigned int openFlags; /* Flags passed to sqlite3_vfs.xOpen() */ |
| 10766 | int errCode; /* Most recent error code (SQLITE_*) */ |
| 10767 | int errMask; /* & result codes with this before returning */ |
| 10768 | u16 dbOptFlags; /* Flags to enable/disable optimizations */ |
| 10769 | u8 enc; /* Text encoding */ |
| 10770 | u8 autoCommit; /* The auto-commit flag. */ |
| 10771 | u8 temp_store; /* 1: file 2: memory 0: default */ |
| 10772 | u8 mallocFailed; /* True if we have seen a malloc failure */ |
| 10773 | u8 dfltLockMode; /* Default locking-mode for attached dbs */ |
| 10774 | signed char nextAutovac; /* Autovac setting after VACUUM if >=0 */ |
| @@ -10820,11 +10866,12 @@ | |
| 10866 | }; |
| 10867 | |
| 10868 | /* |
| 10869 | ** A macro to discover the encoding of a database. |
| 10870 | */ |
| 10871 | #define SCHEMA_ENC(db) ((db)->aDb[0].pSchema->enc) |
| 10872 | #define ENC(db) ((db)->enc) |
| 10873 | |
| 10874 | /* |
| 10875 | ** Possible values for the sqlite3.flags. |
| 10876 | */ |
| 10877 | #define SQLITE_VdbeTrace 0x00000001 /* True to trace VDBE execution */ |
| @@ -11444,11 +11491,10 @@ | |
| 11491 | Index *pNext; /* The next index associated with the same table */ |
| 11492 | Schema *pSchema; /* Schema containing this index */ |
| 11493 | u8 *aSortOrder; /* for each column: True==DESC, False==ASC */ |
| 11494 | char **azColl; /* Array of collation sequence names for index */ |
| 11495 | Expr *pPartIdxWhere; /* WHERE clause for partial indices */ |
| 11496 | int tnum; /* DB Page containing root of this index */ |
| 11497 | LogEst szIdxRow; /* Estimated average row size in bytes */ |
| 11498 | u16 nKeyCol; /* Number of columns forming the key */ |
| 11499 | u16 nColumn; /* Number of columns stored in the index */ |
| 11500 | u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ |
| @@ -11675,11 +11721,11 @@ | |
| 11721 | }; |
| 11722 | |
| 11723 | /* |
| 11724 | ** The following are the meanings of bits in the Expr.flags field. |
| 11725 | */ |
| 11726 | #define EP_FromJoin 0x000001 /* Originates in ON/USING clause of outer join */ |
| 11727 | #define EP_Agg 0x000002 /* Contains one or more aggregate functions */ |
| 11728 | #define EP_Resolved 0x000004 /* IDs have been resolved to COLUMNs */ |
| 11729 | #define EP_Error 0x000008 /* Expression contains one or more errors */ |
| 11730 | #define EP_Distinct 0x000010 /* Aggregate function with DISTINCT keyword */ |
| 11731 | #define EP_VarSelect 0x000020 /* pSelect is correlated, not constant */ |
| @@ -11695,10 +11741,11 @@ | |
| 11741 | #define EP_Static 0x008000 /* Held in memory not obtained from malloc() */ |
| 11742 | #define EP_MemToken 0x010000 /* Need to sqlite3DbFree() Expr.zToken */ |
| 11743 | #define EP_NoReduce 0x020000 /* Cannot EXPRDUP_REDUCE this Expr */ |
| 11744 | #define EP_Unlikely 0x040000 /* unlikely() or likelihood() function */ |
| 11745 | #define EP_Constant 0x080000 /* Node is a constant */ |
| 11746 | #define EP_CanBeNull 0x100000 /* Can be null despite NOT NULL constraint */ |
| 11747 | |
| 11748 | /* |
| 11749 | ** These macros can be used to test, set, or clear bits in the |
| 11750 | ** Expr.flags field. |
| 11751 | */ |
| @@ -12497,10 +12544,11 @@ | |
| 12544 | void *pPage; /* Page cache memory */ |
| 12545 | int szPage; /* Size of each page in pPage[] */ |
| 12546 | int nPage; /* Number of pages in pPage[] */ |
| 12547 | int mxParserStack; /* maximum depth of the parser stack */ |
| 12548 | int sharedCacheEnabled; /* true if shared-cache mode enabled */ |
| 12549 | u32 szPma; /* Maximum Sorter PMA size */ |
| 12550 | /* The above might be initialized to non-zero. The following need to always |
| 12551 | ** initially be zero, however. */ |
| 12552 | int isInit; /* True after initialization has finished */ |
| 12553 | int inProgress; /* True while initialization in progress */ |
| 12554 | int isMutexInit; /* True after mutexes are initialized */ |
| @@ -13419,11 +13467,11 @@ | |
| 13467 | ** print I/O tracing messages. |
| 13468 | */ |
| 13469 | #ifdef SQLITE_ENABLE_IOTRACE |
| 13470 | # define IOTRACE(A) if( sqlite3IoTrace ){ sqlite3IoTrace A; } |
| 13471 | SQLITE_PRIVATE void sqlite3VdbeIOTraceSql(Vdbe*); |
| 13472 | void (*sqlite3IoTrace)(const char*,...); |
| 13473 | #else |
| 13474 | # define IOTRACE(A) |
| 13475 | # define sqlite3VdbeIOTraceSql(X) |
| 13476 | #endif |
| 13477 | |
| @@ -13632,10 +13680,17 @@ | |
| 13680 | */ |
| 13681 | #ifndef SQLITE_ALLOW_COVERING_INDEX_SCAN |
| 13682 | # define SQLITE_ALLOW_COVERING_INDEX_SCAN 1 |
| 13683 | #endif |
| 13684 | |
| 13685 | /* The minimum PMA size is set to this value multiplied by the database |
| 13686 | ** page size in bytes. |
| 13687 | */ |
| 13688 | #ifndef SQLITE_SORTER_PMASZ |
| 13689 | # define SQLITE_SORTER_PMASZ 250 |
| 13690 | #endif |
| 13691 | |
| 13692 | /* |
| 13693 | ** The following singleton contains the global configuration for |
| 13694 | ** the SQLite library. |
| 13695 | */ |
| 13696 | SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = { |
| @@ -13662,10 +13717,11 @@ | |
| 13717 | (void*)0, /* pPage */ |
| 13718 | 0, /* szPage */ |
| 13719 | 0, /* nPage */ |
| 13720 | 0, /* mxParserStack */ |
| 13721 | 0, /* sharedCacheEnabled */ |
| 13722 | SQLITE_SORTER_PMASZ, /* szPma */ |
| 13723 | /* All the rest should always be initialized to zero */ |
| 13724 | 0, /* isInit */ |
| 13725 | 0, /* inProgress */ |
| 13726 | 0, /* isMutexInit */ |
| 13727 | 0, /* isMallocInit */ |
| @@ -19947,10 +20003,16 @@ | |
| 20003 | #endif |
| 20004 | } |
| 20005 | break; |
| 20006 | } |
| 20007 | default: { |
| 20008 | #ifdef SQLITE_ENABLE_API_ARMOR |
| 20009 | if( iType-2<0 || iType-2>=ArraySize(winMutex_staticMutexes) ){ |
| 20010 | (void)SQLITE_MISUSE_BKPT; |
| 20011 | return 0; |
| 20012 | } |
| 20013 | #endif |
| 20014 | assert( iType-2 >= 0 ); |
| 20015 | assert( iType-2 < ArraySize(winMutex_staticMutexes) ); |
| 20016 | assert( winMutex_isInit==1 ); |
| 20017 | p = &winMutex_staticMutexes[iType-2]; |
| 20018 | #ifdef SQLITE_DEBUG |
| @@ -28754,28 +28816,31 @@ | |
| 28816 | do{ |
| 28817 | err = osFallocate(pFile->h, buf.st_size, nSize-buf.st_size); |
| 28818 | }while( err==EINTR ); |
| 28819 | if( err ) return SQLITE_IOERR_WRITE; |
| 28820 | #else |
| 28821 | /* If the OS does not have posix_fallocate(), fake it. Write a |
| 28822 | ** single byte to the last byte in each block that falls entirely |
| 28823 | ** within the extended region. Then, if required, a single byte |
| 28824 | ** at offset (nSize-1), to set the size of the file correctly. |
| 28825 | ** This is a similar technique to that used by glibc on systems |
| 28826 | ** that do not have a real fallocate() call. |
| 28827 | */ |
| 28828 | int nBlk = buf.st_blksize; /* File-system block size */ |
| 28829 | i64 iWrite; /* Next offset to write to */ |
| 28830 | |
| 28831 | iWrite = ((buf.st_size + 2*nBlk - 1)/nBlk)*nBlk-1; |
| 28832 | assert( iWrite>=buf.st_size ); |
| 28833 | assert( (iWrite/nBlk)==((buf.st_size+nBlk-1)/nBlk) ); |
| 28834 | assert( ((iWrite+1)%nBlk)==0 ); |
| 28835 | for(/*no-op*/; iWrite<nSize; iWrite+=nBlk ){ |
| 28836 | int nWrite = seekAndWrite(pFile, iWrite, "", 1); |
| 28837 | if( nWrite!=1 ) return SQLITE_IOERR_WRITE; |
| 28838 | } |
| 28839 | if( nSize%nBlk ){ |
| 28840 | int nWrite = seekAndWrite(pFile, nSize-1, "", 1); |
| 28841 | if( nWrite!=1 ) return SQLITE_IOERR_WRITE; |
| 28842 | } |
| 28843 | #endif |
| 28844 | } |
| 28845 | } |
| 28846 | |
| @@ -33989,12 +34054,12 @@ | |
| 34054 | */ |
| 34055 | SQLITE_API int sqlite3_win32_reset_heap(){ |
| 34056 | int rc; |
| 34057 | MUTEX_LOGIC( sqlite3_mutex *pMaster; ) /* The main static mutex */ |
| 34058 | MUTEX_LOGIC( sqlite3_mutex *pMem; ) /* The memsys static mutex */ |
| 34059 | MUTEX_LOGIC( pMaster = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER); ) |
| 34060 | MUTEX_LOGIC( pMem = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM); ) |
| 34061 | sqlite3_mutex_enter(pMaster); |
| 34062 | sqlite3_mutex_enter(pMem); |
| 34063 | winMemAssertMagic(); |
| 34064 | if( winMemGetHeap()!=NULL && winMemGetOwned() && sqlite3_memory_used()==0 ){ |
| 34065 | /* |
| @@ -35265,11 +35330,11 @@ | |
| 35330 | sqlite3_file *id, /* File to read from */ |
| 35331 | void *pBuf, /* Write content into this buffer */ |
| 35332 | int amt, /* Number of bytes to read */ |
| 35333 | sqlite3_int64 offset /* Begin reading at this offset */ |
| 35334 | ){ |
| 35335 | #if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED) |
| 35336 | OVERLAPPED overlapped; /* The offset for ReadFile. */ |
| 35337 | #endif |
| 35338 | winFile *pFile = (winFile*)id; /* file handle */ |
| 35339 | DWORD nRead; /* Number of bytes actually read from file */ |
| 35340 | int nRetry = 0; /* Number of retrys */ |
| @@ -35297,11 +35362,11 @@ | |
| 35362 | offset += nCopy; |
| 35363 | } |
| 35364 | } |
| 35365 | #endif |
| 35366 | |
| 35367 | #if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED) |
| 35368 | if( winSeekFile(pFile, offset) ){ |
| 35369 | OSTRACE(("READ file=%p, rc=SQLITE_FULL\n", pFile->h)); |
| 35370 | return SQLITE_FULL; |
| 35371 | } |
| 35372 | while( !osReadFile(pFile->h, pBuf, amt, &nRead, 0) ){ |
| @@ -35369,32 +35434,32 @@ | |
| 35434 | offset += nCopy; |
| 35435 | } |
| 35436 | } |
| 35437 | #endif |
| 35438 | |
| 35439 | #if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED) |
| 35440 | rc = winSeekFile(pFile, offset); |
| 35441 | if( rc==0 ){ |
| 35442 | #else |
| 35443 | { |
| 35444 | #endif |
| 35445 | #if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED) |
| 35446 | OVERLAPPED overlapped; /* The offset for WriteFile. */ |
| 35447 | #endif |
| 35448 | u8 *aRem = (u8 *)pBuf; /* Data yet to be written */ |
| 35449 | int nRem = amt; /* Number of bytes yet to be written */ |
| 35450 | DWORD nWrite; /* Bytes written by each WriteFile() call */ |
| 35451 | DWORD lastErrno = NO_ERROR; /* Value returned by GetLastError() */ |
| 35452 | |
| 35453 | #if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED) |
| 35454 | memset(&overlapped, 0, sizeof(OVERLAPPED)); |
| 35455 | overlapped.Offset = (LONG)(offset & 0xffffffff); |
| 35456 | overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff); |
| 35457 | #endif |
| 35458 | |
| 35459 | while( nRem>0 ){ |
| 35460 | #if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED) |
| 35461 | if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, 0) ){ |
| 35462 | #else |
| 35463 | if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, &overlapped) ){ |
| 35464 | #endif |
| 35465 | if( winRetryIoerr(&nRetry, &lastErrno) ) continue; |
| @@ -35403,11 +35468,11 @@ | |
| 35468 | assert( nWrite==0 || nWrite<=(DWORD)nRem ); |
| 35469 | if( nWrite==0 || nWrite>(DWORD)nRem ){ |
| 35470 | lastErrno = osGetLastError(); |
| 35471 | break; |
| 35472 | } |
| 35473 | #if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED) |
| 35474 | offset += nWrite; |
| 35475 | overlapped.Offset = (LONG)(offset & 0xffffffff); |
| 35476 | overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff); |
| 35477 | #endif |
| 35478 | aRem += nWrite; |
| @@ -38949,11 +39014,12 @@ | |
| 39014 | SQLITE_PRIVATE int sqlite3PcacheSetPageSize(PCache *pCache, int szPage){ |
| 39015 | assert( pCache->nRef==0 && pCache->pDirty==0 ); |
| 39016 | if( pCache->szPage ){ |
| 39017 | sqlite3_pcache *pNew; |
| 39018 | pNew = sqlite3GlobalConfig.pcache2.xCreate( |
| 39019 | szPage, pCache->szExtra + ROUND8(sizeof(PgHdr)), |
| 39020 | pCache->bPurgeable |
| 39021 | ); |
| 39022 | if( pNew==0 ) return SQLITE_NOMEM; |
| 39023 | sqlite3GlobalConfig.pcache2.xCachesize(pNew, numberOfCachePages(pCache)); |
| 39024 | if( pCache->pCache ){ |
| 39025 | sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache); |
| @@ -39408,11 +39474,11 @@ | |
| 39474 | |
| 39475 | /* |
| 39476 | ** Return the size of the header added by this middleware layer |
| 39477 | ** in the page-cache hierarchy. |
| 39478 | */ |
| 39479 | SQLITE_PRIVATE int sqlite3HeaderSizePcache(void){ return ROUND8(sizeof(PgHdr)); } |
| 39480 | |
| 39481 | |
| 39482 | #if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG) |
| 39483 | /* |
| 39484 | ** For all dirty pages currently in the cache, invoke the specified |
| @@ -39724,11 +39790,11 @@ | |
| 39790 | pcache1Free(pPg); |
| 39791 | sqlite3_free(p); |
| 39792 | pPg = 0; |
| 39793 | } |
| 39794 | #else |
| 39795 | pPg = pcache1Alloc(ROUND8(sizeof(PgHdr1)) + pCache->szPage + pCache->szExtra); |
| 39796 | p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage]; |
| 39797 | #endif |
| 39798 | pcache1EnterMutex(pCache->pGroup); |
| 39799 | |
| 39800 | if( pPg ){ |
| @@ -40412,11 +40478,11 @@ | |
| 40478 | } |
| 40479 | |
| 40480 | /* |
| 40481 | ** Return the size of the header on each page of this PCACHE implementation. |
| 40482 | */ |
| 40483 | SQLITE_PRIVATE int sqlite3HeaderSizePcache1(void){ return ROUND8(sizeof(PgHdr1)); } |
| 40484 | |
| 40485 | #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT |
| 40486 | /* |
| 40487 | ** This function is called to free superfluous dynamically allocated memory |
| 40488 | ** held by the pager system. Memory in use by any SQLite pager allocated |
| @@ -41770,10 +41836,12 @@ | |
| 41836 | u8 eLock; /* Current lock held on database file */ |
| 41837 | u8 changeCountDone; /* Set after incrementing the change-counter */ |
| 41838 | u8 setMaster; /* True if a m-j name has been written to jrnl */ |
| 41839 | u8 doNotSpill; /* Do not spill the cache when non-zero */ |
| 41840 | u8 subjInMemory; /* True to use in-memory sub-journals */ |
| 41841 | u8 bUseFetch; /* True to use xFetch() */ |
| 41842 | u8 hasBeenUsed; /* True if any content previously read from this pager*/ |
| 41843 | Pgno dbSize; /* Number of pages in the database */ |
| 41844 | Pgno dbOrigSize; /* dbSize before the current transaction */ |
| 41845 | Pgno dbFileSize; /* Number of pages in the database file */ |
| 41846 | Pgno dbHintSize; /* Value passed to FCNTL_SIZE_HINT call */ |
| 41847 | int errCode; /* One of several kinds of errors */ |
| @@ -41787,13 +41855,13 @@ | |
| 41855 | i64 journalOff; /* Current write offset in the journal file */ |
| 41856 | i64 journalHdr; /* Byte offset to previous journal header */ |
| 41857 | sqlite3_backup *pBackup; /* Pointer to list of ongoing backup processes */ |
| 41858 | PagerSavepoint *aSavepoint; /* Array of active savepoints */ |
| 41859 | int nSavepoint; /* Number of elements in aSavepoint[] */ |
| 41860 | u32 iDataVersion; /* Changes whenever database content changes */ |
| 41861 | char dbFileVers[16]; /* Changes whenever database file changes */ |
| 41862 | |
| 41863 | int nMmapOut; /* Number of mmap pages currently outstanding */ |
| 41864 | sqlite3_int64 szMmap; /* Desired maximum mmap size */ |
| 41865 | PgHdr *pMmapFreelist; /* List of free mmap page headers (pDirty) */ |
| 41866 | /* |
| 41867 | ** End of the routinely-changing class members |
| @@ -42805,13 +42873,22 @@ | |
| 42873 | |
| 42874 | /* |
| 42875 | ** Discard the entire contents of the in-memory page-cache. |
| 42876 | */ |
| 42877 | static void pager_reset(Pager *pPager){ |
| 42878 | pPager->iDataVersion++; |
| 42879 | sqlite3BackupRestart(pPager->pBackup); |
| 42880 | sqlite3PcacheClear(pPager->pPCache); |
| 42881 | } |
| 42882 | |
| 42883 | /* |
| 42884 | ** Return the pPager->iDataVersion value |
| 42885 | */ |
| 42886 | SQLITE_PRIVATE u32 sqlite3PagerDataVersion(Pager *pPager){ |
| 42887 | assert( pPager->eState>PAGER_OPEN ); |
| 42888 | return pPager->iDataVersion; |
| 42889 | } |
| 42890 | |
| 42891 | /* |
| 42892 | ** Free all structures in the Pager.aSavepoint[] array and set both |
| 42893 | ** Pager.aSavepoint and Pager.nSavepoint to zero. Close the sub-journal |
| 42894 | ** if it is open and the pager is not in exclusive mode. |
| @@ -45011,11 +45088,11 @@ | |
| 45088 | Pgno pgno, /* Page number */ |
| 45089 | void *pData, /* xFetch()'d data for this page */ |
| 45090 | PgHdr **ppPage /* OUT: Acquired page object */ |
| 45091 | ){ |
| 45092 | PgHdr *p; /* Memory mapped page to return */ |
| 45093 | |
| 45094 | if( pPager->pMmapFreelist ){ |
| 45095 | *ppPage = p = pPager->pMmapFreelist; |
| 45096 | pPager->pMmapFreelist = p->pDirty; |
| 45097 | p->pDirty = 0; |
| 45098 | memset(p->pExtra, 0, pPager->nExtra); |
| @@ -46242,20 +46319,16 @@ | |
| 46319 | assert( (pPager->eLock==SHARED_LOCK) |
| 46320 | || (pPager->exclusiveMode && pPager->eLock>SHARED_LOCK) |
| 46321 | ); |
| 46322 | } |
| 46323 | |
| 46324 | if( !pPager->tempFile && pPager->hasBeenUsed ){ |
| 46325 | /* The shared-lock has just been acquired then check to |
| 46326 | ** see if the database has been modified. If the database has changed, |
| 46327 | ** flush the cache. The pPager->hasBeenUsed flag prevents this from |
| 46328 | ** occurring on the very first access to a file, in order to save a |
| 46329 | ** single unnecessary sqlite3OsRead() call at the start-up. |
| 46330 | ** |
| 46331 | ** Database changes is detected by looking at 15 bytes beginning |
| 46332 | ** at offset 24 into the file. The first 4 of these 16 bytes are |
| 46333 | ** a 32-bit counter that is incremented with each change. The |
| 46334 | ** other bytes change randomly with each file change when |
| @@ -46416,10 +46489,11 @@ | |
| 46489 | assert( noContent==0 || bMmapOk==0 ); |
| 46490 | |
| 46491 | if( pgno==0 ){ |
| 46492 | return SQLITE_CORRUPT_BKPT; |
| 46493 | } |
| 46494 | pPager->hasBeenUsed = 1; |
| 46495 | |
| 46496 | /* If the pager is in the error state, return an error immediately. |
| 46497 | ** Otherwise, request the page from the PCache layer. */ |
| 46498 | if( pPager->errCode!=SQLITE_OK ){ |
| 46499 | rc = pPager->errCode; |
| @@ -46565,10 +46639,11 @@ | |
| 46639 | sqlite3_pcache_page *pPage; |
| 46640 | assert( pPager!=0 ); |
| 46641 | assert( pgno!=0 ); |
| 46642 | assert( pPager->pPCache!=0 ); |
| 46643 | pPage = sqlite3PcacheFetch(pPager->pPCache, pgno, 0); |
| 46644 | assert( pPage==0 || pPager->hasBeenUsed ); |
| 46645 | return sqlite3PcacheFetchFinish(pPager->pPCache, pgno, pPage); |
| 46646 | } |
| 46647 | |
| 46648 | /* |
| 46649 | ** Release a page reference. |
| @@ -47431,10 +47506,11 @@ | |
| 47506 | pPager->eState = PAGER_READER; |
| 47507 | return SQLITE_OK; |
| 47508 | } |
| 47509 | |
| 47510 | PAGERTRACE(("COMMIT %d\n", PAGERID(pPager))); |
| 47511 | pPager->iDataVersion++; |
| 47512 | rc = pager_end_transaction(pPager, pPager->setMaster, 1); |
| 47513 | return pager_error(pPager, rc); |
| 47514 | } |
| 47515 | |
| 47516 | /* |
| @@ -48199,11 +48275,12 @@ | |
| 48275 | */ |
| 48276 | SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, int eMode, int *pnLog, int *pnCkpt){ |
| 48277 | int rc = SQLITE_OK; |
| 48278 | if( pPager->pWal ){ |
| 48279 | rc = sqlite3WalCheckpoint(pPager->pWal, eMode, |
| 48280 | (eMode==SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler), |
| 48281 | pPager->pBusyHandlerArg, |
| 48282 | pPager->ckptSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace, |
| 48283 | pnLog, pnCkpt |
| 48284 | ); |
| 48285 | } |
| 48286 | return rc; |
| @@ -50009,10 +50086,42 @@ | |
| 50086 | ** Return the page-size in bytes used by the database. |
| 50087 | */ |
| 50088 | static int walPagesize(Wal *pWal){ |
| 50089 | return (pWal->hdr.szPage&0xfe00) + ((pWal->hdr.szPage&0x0001)<<16); |
| 50090 | } |
| 50091 | |
| 50092 | /* |
| 50093 | ** The following is guaranteed when this function is called: |
| 50094 | ** |
| 50095 | ** a) the WRITER lock is held, |
| 50096 | ** b) the entire log file has been checkpointed, and |
| 50097 | ** c) any existing readers are reading exclusively from the database |
| 50098 | ** file - there are no readers that may attempt to read a frame from |
| 50099 | ** the log file. |
| 50100 | ** |
| 50101 | ** This function updates the shared-memory structures so that the next |
| 50102 | ** client to write to the database (which may be this one) does so by |
| 50103 | ** writing frames into the start of the log file. |
| 50104 | ** |
| 50105 | ** The value of parameter salt1 is used as the aSalt[1] value in the |
| 50106 | ** new wal-index header. It should be passed a pseudo-random value (i.e. |
| 50107 | ** one obtained from sqlite3_randomness()). |
| 50108 | */ |
| 50109 | static void walRestartHdr(Wal *pWal, u32 salt1){ |
| 50110 | volatile WalCkptInfo *pInfo = walCkptInfo(pWal); |
| 50111 | int i; /* Loop counter */ |
| 50112 | u32 *aSalt = pWal->hdr.aSalt; /* Big-endian salt values */ |
| 50113 | pWal->nCkpt++; |
| 50114 | pWal->hdr.mxFrame = 0; |
| 50115 | sqlite3Put4byte((u8*)&aSalt[0], 1 + sqlite3Get4byte((u8*)&aSalt[0])); |
| 50116 | memcpy(&pWal->hdr.aSalt[1], &salt1, 4); |
| 50117 | walIndexWriteHdr(pWal); |
| 50118 | pInfo->nBackfill = 0; |
| 50119 | pInfo->aReadMark[1] = 0; |
| 50120 | for(i=2; i<WAL_NREADER; i++) pInfo->aReadMark[i] = READMARK_NOT_USED; |
| 50121 | assert( pInfo->aReadMark[0]==0 ); |
| 50122 | } |
| 50123 | |
| 50124 | /* |
| 50125 | ** Copy as much content as we can from the WAL back into the database file |
| 50126 | ** in response to an sqlite3_wal_checkpoint() request or the equivalent. |
| 50127 | ** |
| @@ -50044,11 +50153,11 @@ | |
| 50153 | ** time. |
| 50154 | */ |
| 50155 | static int walCheckpoint( |
| 50156 | Wal *pWal, /* Wal connection */ |
| 50157 | int eMode, /* One of PASSIVE, FULL or RESTART */ |
| 50158 | int (*xBusy)(void*), /* Function to call when busy */ |
| 50159 | void *pBusyArg, /* Context argument for xBusyHandler */ |
| 50160 | int sync_flags, /* Flags for OsSync() (or 0) */ |
| 50161 | u8 *zBuf /* Temporary buffer to use */ |
| 50162 | ){ |
| 50163 | int rc; /* Return code */ |
| @@ -50058,11 +50167,10 @@ | |
| 50167 | u32 iFrame = 0; /* Wal frame containing data for iDbpage */ |
| 50168 | u32 mxSafeFrame; /* Max frame that can be backfilled */ |
| 50169 | u32 mxPage; /* Max database page to write */ |
| 50170 | int i; /* Loop counter */ |
| 50171 | volatile WalCkptInfo *pInfo; /* The checkpoint status information */ |
| 50172 | |
| 50173 | szPage = walPagesize(pWal); |
| 50174 | testcase( szPage<=32768 ); |
| 50175 | testcase( szPage>=65536 ); |
| 50176 | pInfo = walCkptInfo(pWal); |
| @@ -50073,11 +50181,13 @@ | |
| 50181 | if( rc!=SQLITE_OK ){ |
| 50182 | return rc; |
| 50183 | } |
| 50184 | assert( pIter ); |
| 50185 | |
| 50186 | /* EVIDENCE-OF: R-62920-47450 The busy-handler callback is never invoked |
| 50187 | ** in the SQLITE_CHECKPOINT_PASSIVE mode. */ |
| 50188 | assert( eMode!=SQLITE_CHECKPOINT_PASSIVE || xBusy==0 ); |
| 50189 | |
| 50190 | /* Compute in mxSafeFrame the index of the last frame of the WAL that is |
| 50191 | ** safe to write into the database. Frames beyond mxSafeFrame might |
| 50192 | ** overwrite database pages that are in use by active readers and thus |
| 50193 | ** cannot be backfilled from the WAL. |
| @@ -50162,23 +50272,42 @@ | |
| 50272 | /* Reset the return code so as not to report a checkpoint failure |
| 50273 | ** just because there are active readers. */ |
| 50274 | rc = SQLITE_OK; |
| 50275 | } |
| 50276 | |
| 50277 | /* If this is an SQLITE_CHECKPOINT_RESTART or TRUNCATE operation, and the |
| 50278 | ** entire wal file has been copied into the database file, then block |
| 50279 | ** until all readers have finished using the wal file. This ensures that |
| 50280 | ** the next process to write to the database restarts the wal file. |
| 50281 | */ |
| 50282 | if( rc==SQLITE_OK && eMode!=SQLITE_CHECKPOINT_PASSIVE ){ |
| 50283 | assert( pWal->writeLock ); |
| 50284 | if( pInfo->nBackfill<pWal->hdr.mxFrame ){ |
| 50285 | rc = SQLITE_BUSY; |
| 50286 | }else if( eMode>=SQLITE_CHECKPOINT_RESTART ){ |
| 50287 | u32 salt1; |
| 50288 | sqlite3_randomness(4, &salt1); |
| 50289 | assert( mxSafeFrame==pWal->hdr.mxFrame ); |
| 50290 | rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(1), WAL_NREADER-1); |
| 50291 | if( rc==SQLITE_OK ){ |
| 50292 | if( eMode==SQLITE_CHECKPOINT_TRUNCATE ){ |
| 50293 | /* IMPLEMENTATION-OF: R-44699-57140 This mode works the same way as |
| 50294 | ** SQLITE_CHECKPOINT_RESTART with the addition that it also |
| 50295 | ** truncates the log file to zero bytes just prior to a |
| 50296 | ** successful return. |
| 50297 | ** |
| 50298 | ** In theory, it might be safe to do this without updating the |
| 50299 | ** wal-index header in shared memory, as all subsequent reader or |
| 50300 | ** writer clients should see that the entire log file has been |
| 50301 | ** checkpointed and behave accordingly. This seems unsafe though, |
| 50302 | ** as it would leave the system in a state where the contents of |
| 50303 | ** the wal-index header do not match the contents of the |
| 50304 | ** file-system. To avoid this, update the wal-index header to |
| 50305 | ** indicate that the log file contains zero valid frames. */ |
| 50306 | walRestartHdr(pWal, salt1); |
| 50307 | rc = sqlite3OsTruncate(pWal->pWalFd, 0); |
| 50308 | } |
| 50309 | walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1); |
| 50310 | } |
| 50311 | } |
| 50312 | } |
| 50313 | |
| @@ -50747,11 +50876,11 @@ | |
| 50876 | } |
| 50877 | nCollide = HASHTABLE_NSLOT; |
| 50878 | for(iKey=walHash(pgno); aHash[iKey]; iKey=walNextHash(iKey)){ |
| 50879 | u32 iFrame = aHash[iKey] + iZero; |
| 50880 | if( iFrame<=iLast && aPgno[aHash[iKey]]==pgno ){ |
| 50881 | assert( iFrame>iRead || CORRUPT_DB ); |
| 50882 | iRead = iFrame; |
| 50883 | } |
| 50884 | if( (nCollide--)==0 ){ |
| 50885 | return SQLITE_CORRUPT_BKPT; |
| 50886 | } |
| @@ -50960,11 +51089,10 @@ | |
| 51089 | } |
| 51090 | |
| 51091 | return rc; |
| 51092 | } |
| 51093 | |
| 51094 | /* |
| 51095 | ** This function is called just before writing a set of frames to the log |
| 51096 | ** file (see sqlite3WalFrames()). It checks to see if, instead of appending |
| 51097 | ** to the current log file, it is possible to overwrite the start of the |
| 51098 | ** existing log file with the new frames (i.e. "reset" the log). If so, |
| @@ -50993,24 +51121,12 @@ | |
| 51121 | ** wal-index header to reflect this. |
| 51122 | ** |
| 51123 | ** In theory it would be Ok to update the cache of the header only |
| 51124 | ** at this point. But updating the actual wal-index header is also |
| 51125 | ** safe and means there is no special case for sqlite3WalUndo() |
| 51126 | ** to handle if this transaction is rolled back. */ |
| 51127 | walRestartHdr(pWal, salt1); |
| 51128 | walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1); |
| 51129 | }else if( rc!=SQLITE_BUSY ){ |
| 51130 | return rc; |
| 51131 | } |
| 51132 | } |
| @@ -51294,11 +51410,11 @@ | |
| 51410 | ** If parameter xBusy is not NULL, it is a pointer to a busy-handler |
| 51411 | ** callback. In this case this function runs a blocking checkpoint. |
| 51412 | */ |
| 51413 | SQLITE_PRIVATE int sqlite3WalCheckpoint( |
| 51414 | Wal *pWal, /* Wal connection */ |
| 51415 | int eMode, /* PASSIVE, FULL, RESTART, or TRUNCATE */ |
| 51416 | int (*xBusy)(void*), /* Function to call when busy */ |
| 51417 | void *pBusyArg, /* Context argument for xBusyHandler */ |
| 51418 | int sync_flags, /* Flags to sync db file with (or 0) */ |
| 51419 | int nBuf, /* Size of temporary buffer */ |
| 51420 | u8 *zBuf, /* Temporary buffer to use */ |
| @@ -51306,40 +51422,54 @@ | |
| 51422 | int *pnCkpt /* OUT: Number of backfilled frames in WAL */ |
| 51423 | ){ |
| 51424 | int rc; /* Return code */ |
| 51425 | int isChanged = 0; /* True if a new wal-index header is loaded */ |
| 51426 | int eMode2 = eMode; /* Mode to pass to walCheckpoint() */ |
| 51427 | int (*xBusy2)(void*) = xBusy; /* Busy handler for eMode2 */ |
| 51428 | |
| 51429 | assert( pWal->ckptLock==0 ); |
| 51430 | assert( pWal->writeLock==0 ); |
| 51431 | |
| 51432 | /* EVIDENCE-OF: R-62920-47450 The busy-handler callback is never invoked |
| 51433 | ** in the SQLITE_CHECKPOINT_PASSIVE mode. */ |
| 51434 | assert( eMode!=SQLITE_CHECKPOINT_PASSIVE || xBusy==0 ); |
| 51435 | |
| 51436 | if( pWal->readOnly ) return SQLITE_READONLY; |
| 51437 | WALTRACE(("WAL%p: checkpoint begins\n", pWal)); |
| 51438 | |
| 51439 | /* IMPLEMENTATION-OF: R-62028-47212 All calls obtain an exclusive |
| 51440 | ** "checkpoint" lock on the database file. */ |
| 51441 | rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1); |
| 51442 | if( rc ){ |
| 51443 | /* EVIDENCE-OF: R-10421-19736 If any other process is running a |
| 51444 | ** checkpoint operation at the same time, the lock cannot be obtained and |
| 51445 | ** SQLITE_BUSY is returned. |
| 51446 | ** EVIDENCE-OF: R-53820-33897 Even if there is a busy-handler configured, |
| 51447 | ** it will not be invoked in this case. |
| 51448 | */ |
| 51449 | testcase( rc==SQLITE_BUSY ); |
| 51450 | testcase( xBusy!=0 ); |
| 51451 | return rc; |
| 51452 | } |
| 51453 | pWal->ckptLock = 1; |
| 51454 | |
| 51455 | /* IMPLEMENTATION-OF: R-59782-36818 The SQLITE_CHECKPOINT_FULL, RESTART and |
| 51456 | ** TRUNCATE modes also obtain the exclusive "writer" lock on the database |
| 51457 | ** file. |
| 51458 | ** |
| 51459 | ** EVIDENCE-OF: R-60642-04082 If the writer lock cannot be obtained |
| 51460 | ** immediately, and a busy-handler is configured, it is invoked and the |
| 51461 | ** writer lock retried until either the busy-handler returns 0 or the |
| 51462 | ** lock is successfully obtained. |
| 51463 | */ |
| 51464 | if( eMode!=SQLITE_CHECKPOINT_PASSIVE ){ |
| 51465 | rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_WRITE_LOCK, 1); |
| 51466 | if( rc==SQLITE_OK ){ |
| 51467 | pWal->writeLock = 1; |
| 51468 | }else if( rc==SQLITE_BUSY ){ |
| 51469 | eMode2 = SQLITE_CHECKPOINT_PASSIVE; |
| 51470 | xBusy2 = 0; |
| 51471 | rc = SQLITE_OK; |
| 51472 | } |
| 51473 | } |
| 51474 | |
| 51475 | /* Read the wal-index header. */ |
| @@ -51353,11 +51483,11 @@ | |
| 51483 | /* Copy data from the log to the database file. */ |
| 51484 | if( rc==SQLITE_OK ){ |
| 51485 | if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){ |
| 51486 | rc = SQLITE_CORRUPT_BKPT; |
| 51487 | }else{ |
| 51488 | rc = walCheckpoint(pWal, eMode2, xBusy2, pBusyArg, sync_flags, zBuf); |
| 51489 | } |
| 51490 | |
| 51491 | /* If no error occurred, set the output variables. */ |
| 51492 | if( rc==SQLITE_OK || rc==SQLITE_BUSY ){ |
| 51493 | if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame; |
| @@ -51852,10 +51982,11 @@ | |
| 51982 | u8 inTrans; /* TRANS_NONE, TRANS_READ or TRANS_WRITE */ |
| 51983 | u8 sharable; /* True if we can share pBt with another db */ |
| 51984 | u8 locked; /* True if db currently has pBt locked */ |
| 51985 | int wantToLock; /* Number of nested calls to sqlite3BtreeEnter() */ |
| 51986 | int nBackup; /* Number of backup operations reading this btree */ |
| 51987 | u32 iDataVersion; /* Combines with pBt->pPager->iDataVersion */ |
| 51988 | Btree *pNext; /* List of other sharable Btrees from the same db */ |
| 51989 | Btree *pPrev; /* Back pointer of the same list */ |
| 51990 | #ifndef SQLITE_OMIT_SHARED_CACHE |
| 51991 | BtLock lock; /* Object used to lock page 1 */ |
| 51992 | #endif |
| @@ -53821,11 +53952,11 @@ | |
| 53952 | ** to see if defragmentation is necessary. |
| 53953 | */ |
| 53954 | testcase( gap+2+nByte==top ); |
| 53955 | if( gap+2+nByte>top ){ |
| 53956 | defragment_page: |
| 53957 | assert( pPage->nCell>0 || CORRUPT_DB ); |
| 53958 | rc = defragmentPage(pPage); |
| 53959 | if( rc ) return rc; |
| 53960 | top = get2byteNotZero(&data[hdr+5]); |
| 53961 | assert( gap+nByte<=top ); |
| 53962 | } |
| @@ -56015,10 +56146,11 @@ | |
| 56146 | rc = sqlite3PagerCommitPhaseTwo(pBt->pPager); |
| 56147 | if( rc!=SQLITE_OK && bCleanup==0 ){ |
| 56148 | sqlite3BtreeLeave(p); |
| 56149 | return rc; |
| 56150 | } |
| 56151 | p->iDataVersion--; /* Compensate for pPager->iDataVersion++; */ |
| 56152 | pBt->inTransaction = TRANS_READ; |
| 56153 | btreeClearHasContent(pBt); |
| 56154 | } |
| 56155 | |
| 56156 | btreeEndTransaction(p); |
| @@ -56378,11 +56510,11 @@ | |
| 56510 | } |
| 56511 | for(i=0; i<=pCur->iPage; i++){ |
| 56512 | releasePage(pCur->apPage[i]); |
| 56513 | } |
| 56514 | unlockBtreeIfUnused(pBt); |
| 56515 | sqlite3_free(pCur->aOverflow); |
| 56516 | /* sqlite3_free(pCur); */ |
| 56517 | sqlite3BtreeLeave(pBtree); |
| 56518 | } |
| 56519 | return SQLITE_OK; |
| 56520 | } |
| @@ -56672,10 +56804,11 @@ | |
| 56804 | pBuf += a; |
| 56805 | amt -= a; |
| 56806 | }else{ |
| 56807 | offset -= pCur->info.nLocal; |
| 56808 | } |
| 56809 | |
| 56810 | |
| 56811 | if( rc==SQLITE_OK && amt>0 ){ |
| 56812 | const u32 ovflSize = pBt->usableSize - 4; /* Bytes content per ovfl page */ |
| 56813 | Pgno nextPage; |
| 56814 | |
| @@ -56690,12 +56823,12 @@ | |
| 56823 | ** means "not yet known" (the cache is lazily populated). |
| 56824 | */ |
| 56825 | if( eOp!=2 && (pCur->curFlags & BTCF_ValidOvfl)==0 ){ |
| 56826 | int nOvfl = (pCur->info.nPayload-pCur->info.nLocal+ovflSize-1)/ovflSize; |
| 56827 | if( nOvfl>pCur->nOvflAlloc ){ |
| 56828 | Pgno *aNew = (Pgno*)sqlite3Realloc( |
| 56829 | pCur->aOverflow, nOvfl*2*sizeof(Pgno) |
| 56830 | ); |
| 56831 | if( aNew==0 ){ |
| 56832 | rc = SQLITE_NOMEM; |
| 56833 | }else{ |
| 56834 | pCur->nOvflAlloc = nOvfl*2; |
| @@ -56738,10 +56871,11 @@ | |
| 56871 | ** Note that the aOverflow[] array must be allocated because eOp!=2 |
| 56872 | ** here. If eOp==2, then offset==0 and this branch is never taken. |
| 56873 | */ |
| 56874 | assert( eOp!=2 ); |
| 56875 | assert( pCur->curFlags & BTCF_ValidOvfl ); |
| 56876 | assert( pCur->pBtree->db==pBt->db ); |
| 56877 | if( pCur->aOverflow[iIdx+1] ){ |
| 56878 | nextPage = pCur->aOverflow[iIdx+1]; |
| 56879 | }else{ |
| 56880 | rc = getOverflowPage(pBt, nextPage, 0, &nextPage); |
| 56881 | } |
| @@ -58881,11 +59015,11 @@ | |
| 59015 | assert( sqlite3_mutex_held(pPage->pBt->mutex) ); |
| 59016 | assert( sqlite3PagerIswriteable(pParent->pDbPage) ); |
| 59017 | assert( pPage->nOverflow==1 ); |
| 59018 | |
| 59019 | /* This error condition is now caught prior to reaching this function */ |
| 59020 | if( NEVER(pPage->nCell==0) ) return SQLITE_CORRUPT_BKPT; |
| 59021 | |
| 59022 | /* Allocate a new page. This page will become the right-sibling of |
| 59023 | ** pPage. Make the parent page writable, so that the new divider cell |
| 59024 | ** may be inserted. If both these operations are successful, proceed. |
| 59025 | */ |
| @@ -59250,11 +59384,11 @@ | |
| 59384 | + nMaxCells*sizeof(u16) /* szCell */ |
| 59385 | + pBt->pageSize; /* aSpace1 */ |
| 59386 | |
| 59387 | /* EVIDENCE-OF: R-28375-38319 SQLite will never request a scratch buffer |
| 59388 | ** that is more than 6 times the database page size. */ |
| 59389 | assert( szScratch<=6*(int)pBt->pageSize ); |
| 59390 | apCell = sqlite3ScratchMalloc( szScratch ); |
| 59391 | if( apCell==0 ){ |
| 59392 | rc = SQLITE_NOMEM; |
| 59393 | goto balance_cleanup; |
| 59394 | } |
| @@ -59324,11 +59458,15 @@ | |
| 59458 | ** pointer of the divider cell */ |
| 59459 | memcpy(apCell[nCell], &pOld->aData[8], 4); |
| 59460 | }else{ |
| 59461 | assert( leafCorrection==4 ); |
| 59462 | if( szCell[nCell]<4 ){ |
| 59463 | /* Do not allow any cells smaller than 4 bytes. If a smaller cell |
| 59464 | ** does exist, pad it with 0x00 bytes. */ |
| 59465 | assert( szCell[nCell]==3 ); |
| 59466 | assert( apCell[nCell]==&aSpace1[iSpace1-3] ); |
| 59467 | aSpace1[iSpace1++] = 0x00; |
| 59468 | szCell[nCell] = 4; |
| 59469 | } |
| 59470 | } |
| 59471 | nCell++; |
| 59472 | } |
| @@ -59559,11 +59697,15 @@ | |
| 59697 | ** was either part of sibling page iOld (possibly an overflow cell), |
| 59698 | ** or else the divider cell to the left of sibling page iOld. So, |
| 59699 | ** if sibling page iOld had the same page number as pNew, and if |
| 59700 | ** pCell really was a part of sibling page iOld (not a divider or |
| 59701 | ** overflow cell), we can skip updating the pointer map entries. */ |
| 59702 | if( iOld>=nNew |
| 59703 | || pNew->pgno!=aPgno[iOld] |
| 59704 | || pCell<aOld |
| 59705 | || pCell>=&aOld[usableSize] |
| 59706 | ){ |
| 59707 | if( !leafCorrection ){ |
| 59708 | ptrmapPut(pBt, get4byte(pCell), PTRMAP_BTREE, pNew->pgno, &rc); |
| 59709 | } |
| 59710 | if( szCell[i]>pNew->minLocal ){ |
| 59711 | ptrmapPutOvflPtr(pNew, pCell, &rc); |
| @@ -60632,10 +60774,17 @@ | |
| 60774 | ** is read-only, the others are read/write. |
| 60775 | ** |
| 60776 | ** The schema layer numbers meta values differently. At the schema |
| 60777 | ** layer (and the SetCookie and ReadCookie opcodes) the number of |
| 60778 | ** free pages is not visible. So Cookie[0] is the same as Meta[1]. |
| 60779 | ** |
| 60780 | ** This routine treats Meta[BTREE_DATA_VERSION] as a special case. Instead |
| 60781 | ** of reading the value out of the header, it instead loads the "DataVersion" |
| 60782 | ** from the pager. The BTREE_DATA_VERSION value is not actually stored in the |
| 60783 | ** database file. It is a number computed by the pager. But its access |
| 60784 | ** pattern is the same as header meta values, and so it is convenient to |
| 60785 | ** read it from this routine. |
| 60786 | */ |
| 60787 | SQLITE_PRIVATE void sqlite3BtreeGetMeta(Btree *p, int idx, u32 *pMeta){ |
| 60788 | BtShared *pBt = p->pBt; |
| 60789 | |
| 60790 | sqlite3BtreeEnter(p); |
| @@ -60642,11 +60791,15 @@ | |
| 60791 | assert( p->inTrans>TRANS_NONE ); |
| 60792 | assert( SQLITE_OK==querySharedCacheTableLock(p, MASTER_ROOT, READ_LOCK) ); |
| 60793 | assert( pBt->pPage1 ); |
| 60794 | assert( idx>=0 && idx<=15 ); |
| 60795 | |
| 60796 | if( idx==BTREE_DATA_VERSION ){ |
| 60797 | *pMeta = sqlite3PagerDataVersion(pBt->pPager) + p->iDataVersion; |
| 60798 | }else{ |
| 60799 | *pMeta = get4byte(&pBt->pPage1->aData[36 + idx*4]); |
| 60800 | } |
| 60801 | |
| 60802 | /* If auto-vacuum is disabled in this build and this is an auto-vacuum |
| 60803 | ** database, mark the database as read-only. */ |
| 60804 | #ifdef SQLITE_OMIT_AUTOVACUUM |
| 60805 | if( idx==BTREE_LARGEST_ROOT_PAGE && *pMeta>0 ){ |
| @@ -60733,11 +60886,11 @@ | |
| 60886 | if( pPage->leaf ){ |
| 60887 | do { |
| 60888 | if( pCur->iPage==0 ){ |
| 60889 | /* All pages of the b-tree have been visited. Return successfully. */ |
| 60890 | *pnEntry = nEntry; |
| 60891 | return moveToRoot(pCur); |
| 60892 | } |
| 60893 | moveToParent(pCur); |
| 60894 | }while ( pCur->aiIdx[pCur->iPage]>=pCur->apPage[pCur->iPage]->nCell ); |
| 60895 | |
| 60896 | pCur->aiIdx[pCur->iPage]++; |
| @@ -61589,11 +61742,11 @@ | |
| 61742 | } |
| 61743 | |
| 61744 | /* |
| 61745 | ** Return the size of the header added to each page by this module. |
| 61746 | */ |
| 61747 | SQLITE_PRIVATE int sqlite3HeaderSizeBtree(void){ return ROUND8(sizeof(MemPage)); } |
| 61748 | |
| 61749 | /************** End of btree.c ***********************************************/ |
| 61750 | /************** Begin file backup.c ******************************************/ |
| 61751 | /* |
| 61752 | ** 2009 January 28 |
| @@ -64353,36 +64506,39 @@ | |
| 64506 | ** |
| 64507 | ** assert( sqlite3VdbeAssertMayAbort(pParse->pVdbe, pParse->mayAbort) ); |
| 64508 | */ |
| 64509 | SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){ |
| 64510 | int hasAbort = 0; |
| 64511 | int hasFkCounter = 0; |
| 64512 | Op *pOp; |
| 64513 | VdbeOpIter sIter; |
| 64514 | memset(&sIter, 0, sizeof(sIter)); |
| 64515 | sIter.v = v; |
| 64516 | |
| 64517 | while( (pOp = opIterNext(&sIter))!=0 ){ |
| 64518 | int opcode = pOp->opcode; |
| 64519 | if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename |
| 64520 | || ((opcode==OP_Halt || opcode==OP_HaltIfNull) |
| 64521 | && ((pOp->p1&0xff)==SQLITE_CONSTRAINT && pOp->p2==OE_Abort)) |
| 64522 | ){ |
| 64523 | hasAbort = 1; |
| 64524 | break; |
| 64525 | } |
| 64526 | #ifndef SQLITE_OMIT_FOREIGN_KEY |
| 64527 | if( opcode==OP_FkCounter && pOp->p1==0 && pOp->p2==1 ){ |
| 64528 | hasFkCounter = 1; |
| 64529 | } |
| 64530 | #endif |
| 64531 | } |
| 64532 | sqlite3DbFree(v->db, sIter.apSub); |
| 64533 | |
| 64534 | /* Return true if hasAbort==mayAbort. Or if a malloc failure occurred. |
| 64535 | ** If malloc failed, then the while() loop above may not have iterated |
| 64536 | ** through all opcodes and hasAbort may be set incorrectly. Return |
| 64537 | ** true for this case to prevent the assert() in the callers frame |
| 64538 | ** from failing. */ |
| 64539 | return ( v->db->mallocFailed || hasAbort==mayAbort || hasFkCounter ); |
| 64540 | } |
| 64541 | #endif /* SQLITE_DEBUG - the sqlite3AssertMayAbort() function */ |
| 64542 | |
| 64543 | /* |
| 64544 | ** Loop through the program looking for P2 values that are negative |
| @@ -65699,11 +65855,11 @@ | |
| 65855 | for(n=0; n<nVar; n++){ |
| 65856 | p->aVar[n].flags = MEM_Null; |
| 65857 | p->aVar[n].db = db; |
| 65858 | } |
| 65859 | } |
| 65860 | if( p->azVar && pParse->nzVar>0 ){ |
| 65861 | p->nzVar = pParse->nzVar; |
| 65862 | memcpy(p->azVar, pParse->azVar, p->nzVar*sizeof(p->azVar[0])); |
| 65863 | memset(pParse->azVar, 0, pParse->nzVar*sizeof(pParse->azVar[0])); |
| 65864 | } |
| 65865 | if( p->aMem ){ |
| @@ -68502,11 +68658,14 @@ | |
| 68658 | #ifndef SQLITE_OMIT_WAL |
| 68659 | int i; |
| 68660 | for(i=0; i<db->nDb; i++){ |
| 68661 | Btree *pBt = db->aDb[i].pBt; |
| 68662 | if( pBt ){ |
| 68663 | int nEntry; |
| 68664 | sqlite3BtreeEnter(pBt); |
| 68665 | nEntry = sqlite3PagerWalCallback(sqlite3BtreePager(pBt)); |
| 68666 | sqlite3BtreeLeave(pBt); |
| 68667 | if( db->xWalCallback && nEntry>0 && rc==SQLITE_OK ){ |
| 68668 | rc = db->xWalCallback(db->pWalArg, db, db->aDb[i].zName, nEntry); |
| 68669 | } |
| 68670 | } |
| 68671 | } |
| @@ -68682,11 +68841,10 @@ | |
| 68841 | ** program counter to 0 to ensure that when the statement is |
| 68842 | ** finalized or reset the parser error message is available via |
| 68843 | ** sqlite3_errmsg() and sqlite3_errcode(). |
| 68844 | */ |
| 68845 | const char *zErr = (const char *)sqlite3_value_text(db->pErr); |
| 68846 | sqlite3DbFree(db, v->zErrMsg); |
| 68847 | if( !db->mallocFailed ){ |
| 68848 | v->zErrMsg = sqlite3DbStrDup(db, zErr); |
| 68849 | v->rc = rc2; |
| 68850 | } else { |
| @@ -75629,12 +75787,12 @@ | |
| 75787 | |
| 75788 | #ifndef SQLITE_OMIT_WAL |
| 75789 | /* Opcode: Checkpoint P1 P2 P3 * * |
| 75790 | ** |
| 75791 | ** Checkpoint database P1. This is a no-op if P1 is not currently in |
| 75792 | ** WAL mode. Parameter P2 is one of SQLITE_CHECKPOINT_PASSIVE, FULL, |
| 75793 | ** RESTART, or TRUNCATE. Write 1 or 0 into mem[P3] if the checkpoint returns |
| 75794 | ** SQLITE_BUSY or not, respectively. Write the number of pages in the |
| 75795 | ** WAL after the checkpoint into mem[P3+1] and the number of pages |
| 75796 | ** in the WAL that have been checkpointed after the checkpoint |
| 75797 | ** completes into mem[P3+2]. However on an error, mem[P3+1] and |
| 75798 | ** mem[P3+2] are initialized to -1. |
| @@ -75648,10 +75806,11 @@ | |
| 75806 | aRes[0] = 0; |
| 75807 | aRes[1] = aRes[2] = -1; |
| 75808 | assert( pOp->p2==SQLITE_CHECKPOINT_PASSIVE |
| 75809 | || pOp->p2==SQLITE_CHECKPOINT_FULL |
| 75810 | || pOp->p2==SQLITE_CHECKPOINT_RESTART |
| 75811 | || pOp->p2==SQLITE_CHECKPOINT_TRUNCATE |
| 75812 | ); |
| 75813 | rc = sqlite3Checkpoint(db, pOp->p1, pOp->p2, &aRes[1], &aRes[2]); |
| 75814 | if( rc==SQLITE_BUSY ){ |
| 75815 | rc = SQLITE_OK; |
| 75816 | aRes[0] = 1; |
| @@ -77043,11 +77202,11 @@ | |
| 77202 | /* |
| 77203 | ** Hard-coded maximum amount of data to accumulate in memory before flushing |
| 77204 | ** to a level 0 PMA. The purpose of this limit is to prevent various integer |
| 77205 | ** overflows. 512MiB. |
| 77206 | */ |
| 77207 | #define SQLITE_MAX_PMASZ (1<<29) |
| 77208 | |
| 77209 | /* |
| 77210 | ** Private objects used by the sorter |
| 77211 | */ |
| 77212 | typedef struct MergeEngine MergeEngine; /* Merge PMAs together */ |
| @@ -77339,13 +77498,10 @@ | |
| 77498 | ** |
| 77499 | ** void *SRVAL(SorterRecord *p) { return (void*)&p[1]; } |
| 77500 | */ |
| 77501 | #define SRVAL(p) ((void*)((SorterRecord*)(p) + 1)) |
| 77502 | |
| 77503 | |
| 77504 | /* Maximum number of PMAs that a single MergeEngine can merge */ |
| 77505 | #define SORTER_MAX_MERGE_COUNT 16 |
| 77506 | |
| 77507 | static int vdbeIncrSwap(IncrMerger*); |
| @@ -77740,14 +77896,15 @@ | |
| 77896 | SortSubtask *pTask = &pSorter->aTask[i]; |
| 77897 | pTask->pSorter = pSorter; |
| 77898 | } |
| 77899 | |
| 77900 | if( !sqlite3TempInMemory(db) ){ |
| 77901 | u32 szPma = sqlite3GlobalConfig.szPma; |
| 77902 | pSorter->mnPmaSize = szPma * pgsz; |
| 77903 | mxCache = db->aDb[0].pSchema->cache_size; |
| 77904 | if( mxCache<(int)szPma ) mxCache = (int)szPma; |
| 77905 | pSorter->mxPmaSize = MIN((i64)mxCache*pgsz, SQLITE_MAX_PMASZ); |
| 77906 | |
| 77907 | /* EVIDENCE-OF: R-26747-61719 When the application provides any amount of |
| 77908 | ** scratch memory using SQLITE_CONFIG_SCRATCH, SQLite avoids unnecessary |
| 77909 | ** large heap allocations. |
| 77910 | */ |
| @@ -78021,16 +78178,16 @@ | |
| 78178 | ** Whether or not the file does end up memory mapped of course depends on |
| 78179 | ** the specific VFS implementation. |
| 78180 | */ |
| 78181 | static void vdbeSorterExtendFile(sqlite3 *db, sqlite3_file *pFd, i64 nByte){ |
| 78182 | if( nByte<=(i64)(db->nMaxSorterMmap) && pFd->pMethods->iVersion>=3 ){ |
| 78183 | void *p = 0; |
| 78184 | int chunksize = 4*1024; |
| 78185 | sqlite3OsFileControlHint(pFd, SQLITE_FCNTL_CHUNK_SIZE, &chunksize); |
| 78186 | sqlite3OsFileControlHint(pFd, SQLITE_FCNTL_SIZE_HINT, &nByte); |
| 78187 | sqlite3OsFetch(pFd, 0, (int)nByte, &p); |
| 78188 | sqlite3OsUnfetch(pFd, 0, p); |
| 78189 | } |
| 78190 | } |
| 78191 | #else |
| 78192 | # define vdbeSorterExtendFile(x,y,z) |
| 78193 | #endif |
| @@ -80411,10 +80568,14 @@ | |
| 80568 | } |
| 80569 | } |
| 80570 | if( pMatch ){ |
| 80571 | pExpr->iTable = pMatch->iCursor; |
| 80572 | pExpr->pTab = pMatch->pTab; |
| 80573 | assert( (pMatch->jointype & JT_RIGHT)==0 ); /* RIGHT JOIN not (yet) supported */ |
| 80574 | if( (pMatch->jointype & JT_LEFT)!=0 ){ |
| 80575 | ExprSetProperty(pExpr, EP_CanBeNull); |
| 80576 | } |
| 80577 | pSchema = pExpr->pTab->pSchema; |
| 80578 | } |
| 80579 | } /* if( pSrcList ) */ |
| 80580 | |
| 80581 | #ifndef SQLITE_OMIT_TRIGGER |
| @@ -82968,11 +83129,12 @@ | |
| 83129 | case TK_FLOAT: |
| 83130 | case TK_BLOB: |
| 83131 | return 0; |
| 83132 | case TK_COLUMN: |
| 83133 | assert( p->pTab!=0 ); |
| 83134 | return ExprHasProperty(p, EP_CanBeNull) || |
| 83135 | (p->iColumn>=0 && p->pTab->aCol[p->iColumn].notNull==0); |
| 83136 | default: |
| 83137 | return 1; |
| 83138 | } |
| 83139 | } |
| 83140 | |
| @@ -87203,11 +87365,11 @@ | |
| 87365 | |
| 87366 | p->iGet = -1; |
| 87367 | p->mxSample = mxSample; |
| 87368 | p->nPSample = (tRowcnt)(sqlite3_value_int64(argv[2])/(mxSample/3+1) + 1); |
| 87369 | p->current.anLt = &p->current.anEq[nColUp]; |
| 87370 | p->iPrn = 0x689e962d*(u32)nCol ^ 0xd0944565*(u32)sqlite3_value_int(argv[2]); |
| 87371 | |
| 87372 | /* Set up the Stat4Accum.a[] and aBest[] arrays */ |
| 87373 | p->a = (struct Stat4Sample*)&p->current.anLt[nColUp]; |
| 87374 | p->aBest = &p->a[mxSample]; |
| 87375 | pSpace = (u8*)(&p->a[mxSample+nCol]); |
| @@ -88351,11 +88513,11 @@ | |
| 88513 | tRowcnt avgEq = 0; |
| 88514 | tRowcnt nRow; /* Number of rows in index */ |
| 88515 | i64 nSum100 = 0; /* Number of terms contributing to sumEq */ |
| 88516 | i64 nDist100; /* Number of distinct values in index */ |
| 88517 | |
| 88518 | if( !pIdx->aiRowEst || iCol>=pIdx->nKeyCol || pIdx->aiRowEst[iCol+1]==0 ){ |
| 88519 | nRow = pFinal->anLt[iCol]; |
| 88520 | nDist100 = (i64)100 * pFinal->anDLt[iCol]; |
| 88521 | nSample--; |
| 88522 | }else{ |
| 88523 | nRow = pIdx->aiRowEst[0]; |
| @@ -88796,17 +88958,19 @@ | |
| 88958 | }else if( aNew->pSchema->file_format && aNew->pSchema->enc!=ENC(db) ){ |
| 88959 | zErrDyn = sqlite3MPrintf(db, |
| 88960 | "attached databases must use the same text encoding as main database"); |
| 88961 | rc = SQLITE_ERROR; |
| 88962 | } |
| 88963 | sqlite3BtreeEnter(aNew->pBt); |
| 88964 | pPager = sqlite3BtreePager(aNew->pBt); |
| 88965 | sqlite3PagerLockingMode(pPager, db->dfltLockMode); |
| 88966 | sqlite3BtreeSecureDelete(aNew->pBt, |
| 88967 | sqlite3BtreeSecureDelete(db->aDb[0].pBt,-1) ); |
| 88968 | #ifndef SQLITE_OMIT_PAGER_PRAGMAS |
| 88969 | sqlite3BtreeSetPagerFlags(aNew->pBt, 3 | (db->flags & PAGER_FLAGS_MASK)); |
| 88970 | #endif |
| 88971 | sqlite3BtreeLeave(aNew->pBt); |
| 88972 | } |
| 88973 | aNew->safety_level = 3; |
| 88974 | aNew->zName = sqlite3DbStrDup(db, zName); |
| 88975 | if( rc==SQLITE_OK && aNew->zName==0 ){ |
| 88976 | rc = SQLITE_NOMEM; |
| @@ -89928,11 +90092,10 @@ | |
| 90092 | */ |
| 90093 | static void freeIndex(sqlite3 *db, Index *p){ |
| 90094 | #ifndef SQLITE_OMIT_ANALYZE |
| 90095 | sqlite3DeleteIndexSamples(db, p); |
| 90096 | #endif |
| 90097 | sqlite3ExprDelete(db, p->pPartIdxWhere); |
| 90098 | sqlite3DbFree(db, p->zColAff); |
| 90099 | if( p->isResized ) sqlite3DbFree(db, p->azColl); |
| 90100 | #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 |
| 90101 | sqlite3_free(p->aiRowEst); |
| @@ -91207,10 +91370,23 @@ | |
| 91370 | if( pPk==0 ) return; |
| 91371 | pPk->idxType = SQLITE_IDXTYPE_PRIMARYKEY; |
| 91372 | pTab->iPKey = -1; |
| 91373 | }else{ |
| 91374 | pPk = sqlite3PrimaryKeyIndex(pTab); |
| 91375 | /* |
| 91376 | ** Remove all redundant columns from the PRIMARY KEY. For example, change |
| 91377 | ** "PRIMARY KEY(a,b,a,b,c,b,c,d)" into just "PRIMARY KEY(a,b,c,d)". Later |
| 91378 | ** code assumes the PRIMARY KEY contains no repeated columns. |
| 91379 | */ |
| 91380 | for(i=j=1; i<pPk->nKeyCol; i++){ |
| 91381 | if( hasColumn(pPk->aiColumn, j, pPk->aiColumn[i]) ){ |
| 91382 | pPk->nColumn--; |
| 91383 | }else{ |
| 91384 | pPk->aiColumn[j++] = pPk->aiColumn[i]; |
| 91385 | } |
| 91386 | } |
| 91387 | pPk->nKeyCol = j; |
| 91388 | } |
| 91389 | pPk->isCovering = 1; |
| 91390 | assert( pPk!=0 ); |
| 91391 | nPk = pPk->nKeyCol; |
| 91392 | |
| @@ -93683,44 +93859,35 @@ | |
| 93859 | ** |
| 93860 | ** The caller should invoke sqlite3KeyInfoUnref() on the returned object |
| 93861 | ** when it has finished using it. |
| 93862 | */ |
| 93863 | SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoOfIndex(Parse *pParse, Index *pIdx){ |
| 93864 | int i; |
| 93865 | int nCol = pIdx->nColumn; |
| 93866 | int nKey = pIdx->nKeyCol; |
| 93867 | KeyInfo *pKey; |
| 93868 | if( pParse->nErr ) return 0; |
| 93869 | if( pIdx->uniqNotNull ){ |
| 93870 | pKey = sqlite3KeyInfoAlloc(pParse->db, nKey, nCol-nKey); |
| 93871 | }else{ |
| 93872 | pKey = sqlite3KeyInfoAlloc(pParse->db, nCol, 0); |
| 93873 | } |
| 93874 | if( pKey ){ |
| 93875 | assert( sqlite3KeyInfoIsWriteable(pKey) ); |
| 93876 | for(i=0; i<nCol; i++){ |
| 93877 | char *zColl = pIdx->azColl[i]; |
| 93878 | assert( zColl!=0 ); |
| 93879 | pKey->aColl[i] = strcmp(zColl,"BINARY")==0 ? 0 : |
| 93880 | sqlite3LocateCollSeq(pParse, zColl); |
| 93881 | pKey->aSortOrder[i] = pIdx->aSortOrder[i]; |
| 93882 | } |
| 93883 | if( pParse->nErr ){ |
| 93884 | sqlite3KeyInfoUnref(pKey); |
| 93885 | pKey = 0; |
| 93886 | } |
| 93887 | } |
| 93888 | return pKey; |
| 93889 | } |
| 93890 | |
| 93891 | #ifndef SQLITE_OMIT_CTE |
| 93892 | /* |
| 93893 | ** This routine is invoked once per CTE by the parser while parsing a |
| @@ -97337,11 +97504,11 @@ | |
| 97504 | assert( nIncr==1 ); |
| 97505 | sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY, |
| 97506 | OE_Abort, 0, P4_STATIC, P5_ConstraintFK); |
| 97507 | }else{ |
| 97508 | if( nIncr>0 && pFKey->isDeferred==0 ){ |
| 97509 | sqlite3MayAbort(pParse); |
| 97510 | } |
| 97511 | sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr); |
| 97512 | } |
| 97513 | |
| 97514 | sqlite3VdbeResolveLabel(v, iOk); |
| @@ -97408,10 +97575,14 @@ | |
| 97575 | ** This function is called to generate code executed when a row is deleted |
| 97576 | ** from the parent table of foreign key constraint pFKey and, if pFKey is |
| 97577 | ** deferred, when a row is inserted into the same table. When generating |
| 97578 | ** code for an SQL UPDATE operation, this function may be called twice - |
| 97579 | ** once to "delete" the old row and once to "insert" the new row. |
| 97580 | ** |
| 97581 | ** Parameter nIncr is passed -1 when inserting a row (as this may decrease |
| 97582 | ** the number of FK violations in the db) or +1 when deleting one (as this |
| 97583 | ** may increase the number of FK constraint problems). |
| 97584 | ** |
| 97585 | ** The code generated by this function scans through the rows in the child |
| 97586 | ** table that correspond to the parent table row being deleted or inserted. |
| 97587 | ** For each child row found, one of the following actions is taken: |
| 97588 | ** |
| @@ -97525,17 +97696,13 @@ | |
| 97696 | sNameContext.pSrcList = pSrc; |
| 97697 | sNameContext.pParse = pParse; |
| 97698 | sqlite3ResolveExprNames(&sNameContext, pWhere); |
| 97699 | |
| 97700 | /* Create VDBE to loop through the entries in pSrc that match the WHERE |
| 97701 | ** clause. For each row found, increment either the deferred or immediate |
| 97702 | ** foreign key constraint counter. */ |
| 97703 | pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0); |
| 97704 | sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr); |
| 97705 | if( pWInfo ){ |
| 97706 | sqlite3WhereEnd(pWInfo); |
| 97707 | } |
| 97708 | |
| @@ -97709,10 +97876,28 @@ | |
| 97876 | } |
| 97877 | } |
| 97878 | } |
| 97879 | return 0; |
| 97880 | } |
| 97881 | |
| 97882 | /* |
| 97883 | ** Return true if the parser passed as the first argument is being |
| 97884 | ** used to code a trigger that is really a "SET NULL" action belonging |
| 97885 | ** to trigger pFKey. |
| 97886 | */ |
| 97887 | static int isSetNullAction(Parse *pParse, FKey *pFKey){ |
| 97888 | Parse *pTop = sqlite3ParseToplevel(pParse); |
| 97889 | if( pTop->pTriggerPrg ){ |
| 97890 | Trigger *p = pTop->pTriggerPrg->pTrigger; |
| 97891 | if( (p==pFKey->apTrigger[0] && pFKey->aAction[0]==OE_SetNull) |
| 97892 | || (p==pFKey->apTrigger[1] && pFKey->aAction[1]==OE_SetNull) |
| 97893 | ){ |
| 97894 | return 1; |
| 97895 | } |
| 97896 | } |
| 97897 | return 0; |
| 97898 | } |
| 97899 | |
| 97900 | /* |
| 97901 | ** This function is called when inserting, deleting or updating a row of |
| 97902 | ** table pTab to generate VDBE code to perform foreign key constraint |
| 97903 | ** processing for the operation. |
| @@ -97762,11 +97947,11 @@ | |
| 97947 | Index *pIdx = 0; /* Index on key columns in pTo */ |
| 97948 | int *aiFree = 0; |
| 97949 | int *aiCol; |
| 97950 | int iCol; |
| 97951 | int i; |
| 97952 | int bIgnore = 0; |
| 97953 | |
| 97954 | if( aChange |
| 97955 | && sqlite3_stricmp(pTab->zName, pFKey->zTo)!=0 |
| 97956 | && fkChildIsModified(pTab, pFKey, aChange, bChngRowid)==0 |
| 97957 | ){ |
| @@ -97821,11 +98006,11 @@ | |
| 98006 | ** values read from the parent table are NULL. */ |
| 98007 | if( db->xAuth ){ |
| 98008 | int rcauth; |
| 98009 | char *zCol = pTo->aCol[pIdx ? pIdx->aiColumn[i] : pTo->iPKey].zName; |
| 98010 | rcauth = sqlite3AuthReadCol(pParse, pTo->zName, zCol, iDb); |
| 98011 | bIgnore = (rcauth==SQLITE_IGNORE); |
| 98012 | } |
| 98013 | #endif |
| 98014 | } |
| 98015 | |
| 98016 | /* Take a shared-cache advisory read-lock on the parent table. Allocate |
| @@ -97836,16 +98021,22 @@ | |
| 98021 | |
| 98022 | if( regOld!=0 ){ |
| 98023 | /* A row is being removed from the child table. Search for the parent. |
| 98024 | ** If the parent does not exist, removing the child row resolves an |
| 98025 | ** outstanding foreign key constraint violation. */ |
| 98026 | fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regOld, -1, bIgnore); |
| 98027 | } |
| 98028 | if( regNew!=0 && !isSetNullAction(pParse, pFKey) ){ |
| 98029 | /* A row is being added to the child table. If a parent row cannot |
| 98030 | ** be found, adding the child row has violated the FK constraint. |
| 98031 | ** |
| 98032 | ** If this operation is being performed as part of a trigger program |
| 98033 | ** that is actually a "SET NULL" action belonging to this very |
| 98034 | ** foreign key, then omit this scan altogether. As all child key |
| 98035 | ** values are guaranteed to be NULL, it is not possible for adding |
| 98036 | ** this row to cause an FK violation. */ |
| 98037 | fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regNew, +1, bIgnore); |
| 98038 | } |
| 98039 | |
| 98040 | sqlite3DbFree(db, aiFree); |
| 98041 | } |
| 98042 | |
| @@ -97862,12 +98053,12 @@ | |
| 98053 | |
| 98054 | if( !pFKey->isDeferred && !(db->flags & SQLITE_DeferFKs) |
| 98055 | && !pParse->pToplevel && !pParse->isMultiWrite |
| 98056 | ){ |
| 98057 | assert( regOld==0 && regNew!=0 ); |
| 98058 | /* Inserting a single row into a parent table cannot cause (or fix) |
| 98059 | ** an immediate foreign key violation. So do nothing in this case. */ |
| 98060 | continue; |
| 98061 | } |
| 98062 | |
| 98063 | if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){ |
| 98064 | if( !isIgnoreErrors || db->mallocFailed ) return; |
| @@ -97887,17 +98078,32 @@ | |
| 98078 | |
| 98079 | if( regNew!=0 ){ |
| 98080 | fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regNew, -1); |
| 98081 | } |
| 98082 | if( regOld!=0 ){ |
| 98083 | int eAction = pFKey->aAction[aChange!=0]; |
| 98084 | fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regOld, 1); |
| 98085 | /* If this is a deferred FK constraint, or a CASCADE or SET NULL |
| 98086 | ** action applies, then any foreign key violations caused by |
| 98087 | ** removing the parent key will be rectified by the action trigger. |
| 98088 | ** So do not set the "may-abort" flag in this case. |
| 98089 | ** |
| 98090 | ** Note 1: If the FK is declared "ON UPDATE CASCADE", then the |
| 98091 | ** may-abort flag will eventually be set on this statement anyway |
| 98092 | ** (when this function is called as part of processing the UPDATE |
| 98093 | ** within the action trigger). |
| 98094 | ** |
| 98095 | ** Note 2: At first glance it may seem like SQLite could simply omit |
| 98096 | ** all OP_FkCounter related scans when either CASCADE or SET NULL |
| 98097 | ** applies. The trouble starts if the CASCADE or SET NULL action |
| 98098 | ** trigger causes other triggers or action rules attached to the |
| 98099 | ** child table to fire. In these cases the fk constraint counters |
| 98100 | ** might be set incorrectly if any OP_FkCounter related scans are |
| 98101 | ** omitted. */ |
| 98102 | if( !pFKey->isDeferred && eAction!=OE_Cascade && eAction!=OE_SetNull ){ |
| 98103 | sqlite3MayAbort(pParse); |
| 98104 | } |
| 98105 | } |
| 98106 | pItem->zName = 0; |
| 98107 | sqlite3SrcListDelete(db, pSrc); |
| 98108 | } |
| 98109 | sqlite3DbFree(db, aiCol); |
| @@ -100987,11 +101193,10 @@ | |
| 101193 | # define sqlite3_column_database_name16 0 |
| 101194 | # define sqlite3_column_table_name 0 |
| 101195 | # define sqlite3_column_table_name16 0 |
| 101196 | # define sqlite3_column_origin_name 0 |
| 101197 | # define sqlite3_column_origin_name16 0 |
| 101198 | #endif |
| 101199 | |
| 101200 | #ifdef SQLITE_OMIT_AUTHORIZATION |
| 101201 | # define sqlite3_set_authorizer 0 |
| 101202 | #endif |
| @@ -101797,10 +102002,11 @@ | |
| 102002 | #define PragTyp_KEY 38 |
| 102003 | #define PragTyp_REKEY 39 |
| 102004 | #define PragTyp_LOCK_STATUS 40 |
| 102005 | #define PragTyp_PARSER_TRACE 41 |
| 102006 | #define PragFlag_NeedSchema 0x01 |
| 102007 | #define PragFlag_ReadOnly 0x02 |
| 102008 | static const struct sPragmaNames { |
| 102009 | const char *const zName; /* Name of pragma */ |
| 102010 | u8 ePragTyp; /* PragTyp_XXX value */ |
| 102011 | u8 mPragFlag; /* Zero or more PragFlag_XXX values */ |
| 102012 | u32 iArg; /* Extra argument */ |
| @@ -101813,11 +102019,11 @@ | |
| 102019 | #endif |
| 102020 | #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) |
| 102021 | { /* zName: */ "application_id", |
| 102022 | /* ePragTyp: */ PragTyp_HEADER_VALUE, |
| 102023 | /* ePragFlag: */ 0, |
| 102024 | /* iArg: */ BTREE_APPLICATION_ID }, |
| 102025 | #endif |
| 102026 | #if !defined(SQLITE_OMIT_AUTOVACUUM) |
| 102027 | { /* zName: */ "auto_vacuum", |
| 102028 | /* ePragTyp: */ PragTyp_AUTO_VACUUM, |
| 102029 | /* ePragFlag: */ PragFlag_NeedSchema, |
| @@ -101879,10 +102085,16 @@ | |
| 102085 | { /* zName: */ "data_store_directory", |
| 102086 | /* ePragTyp: */ PragTyp_DATA_STORE_DIRECTORY, |
| 102087 | /* ePragFlag: */ 0, |
| 102088 | /* iArg: */ 0 }, |
| 102089 | #endif |
| 102090 | #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) |
| 102091 | { /* zName: */ "data_version", |
| 102092 | /* ePragTyp: */ PragTyp_HEADER_VALUE, |
| 102093 | /* ePragFlag: */ PragFlag_ReadOnly, |
| 102094 | /* iArg: */ BTREE_DATA_VERSION }, |
| 102095 | #endif |
| 102096 | #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) |
| 102097 | { /* zName: */ "database_list", |
| 102098 | /* ePragTyp: */ PragTyp_DATABASE_LIST, |
| 102099 | /* ePragFlag: */ PragFlag_NeedSchema, |
| 102100 | /* iArg: */ 0 }, |
| @@ -101934,12 +102146,12 @@ | |
| 102146 | #endif |
| 102147 | #endif |
| 102148 | #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) |
| 102149 | { /* zName: */ "freelist_count", |
| 102150 | /* ePragTyp: */ PragTyp_HEADER_VALUE, |
| 102151 | /* ePragFlag: */ PragFlag_ReadOnly, |
| 102152 | /* iArg: */ BTREE_FREE_PAGE_COUNT }, |
| 102153 | #endif |
| 102154 | #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
| 102155 | { /* zName: */ "full_column_names", |
| 102156 | /* ePragTyp: */ PragTyp_FLAG, |
| 102157 | /* ePragFlag: */ 0, |
| @@ -102087,11 +102299,11 @@ | |
| 102299 | #endif |
| 102300 | #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) |
| 102301 | { /* zName: */ "schema_version", |
| 102302 | /* ePragTyp: */ PragTyp_HEADER_VALUE, |
| 102303 | /* ePragFlag: */ 0, |
| 102304 | /* iArg: */ BTREE_SCHEMA_VERSION }, |
| 102305 | #endif |
| 102306 | #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) |
| 102307 | { /* zName: */ "secure_delete", |
| 102308 | /* ePragTyp: */ PragTyp_SECURE_DELETE, |
| 102309 | /* ePragFlag: */ 0, |
| @@ -102153,11 +102365,11 @@ | |
| 102365 | /* iArg: */ 0 }, |
| 102366 | #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) |
| 102367 | { /* zName: */ "user_version", |
| 102368 | /* ePragTyp: */ PragTyp_HEADER_VALUE, |
| 102369 | /* ePragFlag: */ 0, |
| 102370 | /* iArg: */ BTREE_USER_VERSION }, |
| 102371 | #endif |
| 102372 | #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
| 102373 | #if defined(SQLITE_DEBUG) |
| 102374 | { /* zName: */ "vdbe_addoptrace", |
| 102375 | /* ePragTyp: */ PragTyp_FLAG, |
| @@ -102196,11 +102408,11 @@ | |
| 102408 | /* ePragTyp: */ PragTyp_FLAG, |
| 102409 | /* ePragFlag: */ 0, |
| 102410 | /* iArg: */ SQLITE_WriteSchema|SQLITE_RecoveryMode }, |
| 102411 | #endif |
| 102412 | }; |
| 102413 | /* Number of pragmas: 58 on by default, 71 total. */ |
| 102414 | /* End of the automatically generated pragma table. |
| 102415 | ***************************************************************************/ |
| 102416 | |
| 102417 | /* |
| 102418 | ** Interpret the given string as a safety level. Return 0 for OFF, |
| @@ -103806,11 +104018,12 @@ | |
| 104018 | !(DbHasProperty(db, 0, DB_SchemaLoaded)) || |
| 104019 | DbHasProperty(db, 0, DB_Empty) |
| 104020 | ){ |
| 104021 | for(pEnc=&encnames[0]; pEnc->zName; pEnc++){ |
| 104022 | if( 0==sqlite3StrICmp(zRight, pEnc->zName) ){ |
| 104023 | SCHEMA_ENC(db) = ENC(db) = |
| 104024 | pEnc->enc ? pEnc->enc : SQLITE_UTF16NATIVE; |
| 104025 | break; |
| 104026 | } |
| 104027 | } |
| 104028 | if( !pEnc->zName ){ |
| 104029 | sqlite3ErrorMsg(pParse, "unsupported encoding: %s", zRight); |
| @@ -103851,28 +104064,13 @@ | |
| 104064 | ** |
| 104065 | ** The user-version is not used internally by SQLite. It may be used by |
| 104066 | ** applications for any purpose. |
| 104067 | */ |
| 104068 | case PragTyp_HEADER_VALUE: { |
| 104069 | int iCookie = aPragmaNames[mid].iArg; /* Which cookie to read or write */ |
| 104070 | sqlite3VdbeUsesBtree(v, iDb); |
| 104071 | if( zRight && (aPragmaNames[mid].mPragFlag & PragFlag_ReadOnly)==0 ){ |
| 104072 | /* Write the specified cookie value */ |
| 104073 | static const VdbeOpList setCookie[] = { |
| 104074 | { OP_Transaction, 0, 1, 0}, /* 0 */ |
| 104075 | { OP_Integer, 0, 1, 0}, /* 1 */ |
| 104076 | { OP_SetCookie, 0, 0, 1}, /* 2 */ |
| @@ -103921,11 +104119,11 @@ | |
| 104119 | break; |
| 104120 | #endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ |
| 104121 | |
| 104122 | #ifndef SQLITE_OMIT_WAL |
| 104123 | /* |
| 104124 | ** PRAGMA [database.]wal_checkpoint = passive|full|restart|truncate |
| 104125 | ** |
| 104126 | ** Checkpoint the database. |
| 104127 | */ |
| 104128 | case PragTyp_WAL_CHECKPOINT: { |
| 104129 | int iBt = (pId2->z?iDb:SQLITE_MAX_ATTACHED); |
| @@ -103933,10 +104131,12 @@ | |
| 104131 | if( zRight ){ |
| 104132 | if( sqlite3StrICmp(zRight, "full")==0 ){ |
| 104133 | eMode = SQLITE_CHECKPOINT_FULL; |
| 104134 | }else if( sqlite3StrICmp(zRight, "restart")==0 ){ |
| 104135 | eMode = SQLITE_CHECKPOINT_RESTART; |
| 104136 | }else if( sqlite3StrICmp(zRight, "truncate")==0 ){ |
| 104137 | eMode = SQLITE_CHECKPOINT_TRUNCATE; |
| 104138 | } |
| 104139 | } |
| 104140 | sqlite3VdbeSetNumCols(v, 3); |
| 104141 | pParse->nMem = 3; |
| 104142 | sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "busy", SQLITE_STATIC); |
| @@ -104512,13 +104712,15 @@ | |
| 104712 | SQLITE_PRIVATE int sqlite3Init(sqlite3 *db, char **pzErrMsg){ |
| 104713 | int i, rc; |
| 104714 | int commit_internal = !(db->flags&SQLITE_InternChanges); |
| 104715 | |
| 104716 | assert( sqlite3_mutex_held(db->mutex) ); |
| 104717 | assert( sqlite3BtreeHoldsMutex(db->aDb[0].pBt) ); |
| 104718 | assert( db->init.busy==0 ); |
| 104719 | rc = SQLITE_OK; |
| 104720 | db->init.busy = 1; |
| 104721 | ENC(db) = SCHEMA_ENC(db); |
| 104722 | for(i=0; rc==SQLITE_OK && i<db->nDb; i++){ |
| 104723 | if( DbHasProperty(db, i, DB_SchemaLoaded) || i==1 ) continue; |
| 104724 | rc = sqlite3InitOne(db, i, pzErrMsg); |
| 104725 | if( rc ){ |
| 104726 | sqlite3ResetOneSchema(db, i); |
| @@ -109840,11 +110042,11 @@ | |
| 110042 | ** |
| 110043 | ** SELECT DISTINCT xyz FROM ... ORDER BY xyz |
| 110044 | ** |
| 110045 | ** is transformed to: |
| 110046 | ** |
| 110047 | ** SELECT xyz FROM ... GROUP BY xyz ORDER BY xyz |
| 110048 | ** |
| 110049 | ** The second form is preferred as a single index (or temp-table) may be |
| 110050 | ** used for both the ORDER BY and DISTINCT processing. As originally |
| 110051 | ** written the query must use a temp-table for at least one of the ORDER |
| 110052 | ** BY and DISTINCT, and an index or separate temp-table for the other. |
| @@ -109853,11 +110055,10 @@ | |
| 110055 | && sqlite3ExprListCompare(sSort.pOrderBy, p->pEList, -1)==0 |
| 110056 | ){ |
| 110057 | p->selFlags &= ~SF_Distinct; |
| 110058 | p->pGroupBy = sqlite3ExprListDup(db, p->pEList, 0); |
| 110059 | pGroupBy = p->pGroupBy; |
| 110060 | /* Notice that even thought SF_Distinct has been cleared from p->selFlags, |
| 110061 | ** the sDistinct.isTnct is still set. Hence, isTnct represents the |
| 110062 | ** original setting of the SF_Distinct flag, not the current setting */ |
| 110063 | assert( sDistinct.isTnct ); |
| 110064 | } |
| @@ -110657,11 +110858,11 @@ | |
| 110858 | ){ |
| 110859 | int rc; |
| 110860 | TabResult res; |
| 110861 | |
| 110862 | #ifdef SQLITE_ENABLE_API_ARMOR |
| 110863 | if( !sqlite3SafetyCheckOk(db) || pazResult==0 ) return SQLITE_MISUSE_BKPT; |
| 110864 | #endif |
| 110865 | *pazResult = 0; |
| 110866 | if( pnColumn ) *pnColumn = 0; |
| 110867 | if( pnRow ) *pnRow = 0; |
| 110868 | if( pzErrMsg ) *pzErrMsg = 0; |
| @@ -114808,10 +115009,11 @@ | |
| 115009 | memcpy(pWC->a, pOld, sizeof(pWC->a[0])*pWC->nTerm); |
| 115010 | if( pOld!=pWC->aStatic ){ |
| 115011 | sqlite3DbFree(db, pOld); |
| 115012 | } |
| 115013 | pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]); |
| 115014 | memset(&pWC->a[pWC->nTerm], 0, sizeof(pWC->a[0])*(pWC->nSlot-pWC->nTerm)); |
| 115015 | } |
| 115016 | pTerm = &pWC->a[idx = pWC->nTerm++]; |
| 115017 | if( p && ExprHasProperty(p, EP_Unlikely) ){ |
| 115018 | pTerm->truthProb = sqlite3LogEst(p->iTable) - 270; |
| 115019 | }else{ |
| @@ -117533,11 +117735,11 @@ | |
| 117735 | WhereLevel *pLvl, /* Level to add scanstatus() entry for */ |
| 117736 | int addrExplain /* Address of OP_Explain (or 0) */ |
| 117737 | ){ |
| 117738 | const char *zObj = 0; |
| 117739 | WhereLoop *pLoop = pLvl->pWLoop; |
| 117740 | if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 && pLoop->u.btree.pIndex!=0 ){ |
| 117741 | zObj = pLoop->u.btree.pIndex->zName; |
| 117742 | }else{ |
| 117743 | zObj = pSrclist->a[pLvl->iFrom].zName; |
| 117744 | } |
| 117745 | sqlite3VdbeScanStatus( |
| @@ -118177,14 +118379,13 @@ | |
| 118379 | int iTerm; |
| 118380 | for(iTerm=0; iTerm<pWC->nTerm; iTerm++){ |
| 118381 | Expr *pExpr = pWC->a[iTerm].pExpr; |
| 118382 | if( &pWC->a[iTerm] == pTerm ) continue; |
| 118383 | if( ExprHasProperty(pExpr, EP_FromJoin) ) continue; |
| 118384 | if( (pWC->a[iTerm].wtFlags & TERM_VIRTUAL)!=0 ) continue; |
| 118385 | if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue; |
| 118386 | testcase( pWC->a[iTerm].wtFlags & TERM_ORINFO ); |
| 118387 | pExpr = sqlite3ExprDup(db, pExpr, 0); |
| 118388 | pAndExpr = sqlite3ExprAnd(db, pAndExpr, pExpr); |
| 118389 | } |
| 118390 | if( pAndExpr ){ |
| 118391 | pAndExpr = sqlite3PExpr(pParse, TK_AND, 0, pAndExpr, 0); |
| @@ -118527,11 +118728,10 @@ | |
| 118728 | sqlite3_free(p->u.vtab.idxStr); |
| 118729 | p->u.vtab.needFree = 0; |
| 118730 | p->u.vtab.idxStr = 0; |
| 118731 | }else if( (p->wsFlags & WHERE_AUTO_INDEX)!=0 && p->u.btree.pIndex!=0 ){ |
| 118732 | sqlite3DbFree(db, p->u.btree.pIndex->zColAff); |
| 118733 | sqlite3DbFree(db, p->u.btree.pIndex); |
| 118734 | p->u.btree.pIndex = 0; |
| 118735 | } |
| 118736 | } |
| 118737 | } |
| @@ -125534,10 +125734,13 @@ | |
| 125734 | u8 enableLookaside; /* Saved value of db->lookaside.bEnabled */ |
| 125735 | sqlite3 *db = pParse->db; /* The database connection */ |
| 125736 | int mxSqlLen; /* Max length of an SQL string */ |
| 125737 | |
| 125738 | |
| 125739 | #ifdef SQLITE_ENABLE_API_ARMOR |
| 125740 | if( zSql==0 || pzErrMsg==0 ) return SQLITE_MISUSE_BKPT; |
| 125741 | #endif |
| 125742 | mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH]; |
| 125743 | if( db->nVdbeActive==0 ){ |
| 125744 | db->u1.isInterrupted = 0; |
| 125745 | } |
| 125746 | pParse->rc = SQLITE_OK; |
| @@ -125772,17 +125975,10 @@ | |
| 125975 | */ |
| 125976 | SQLITE_API int sqlite3_complete(const char *zSql){ |
| 125977 | u8 state = 0; /* Current state, using numbers defined in header comment */ |
| 125978 | u8 token; /* Value of the next token */ |
| 125979 | |
| 125980 | #ifndef SQLITE_OMIT_TRIGGER |
| 125981 | /* A complex statement machine used to detect the end of a CREATE TRIGGER |
| 125982 | ** statement. This is the normal case. |
| 125983 | */ |
| 125984 | static const u8 trans[8][8] = { |
| @@ -125807,10 +126003,17 @@ | |
| 126003 | /* 0 INVALID: */ { 1, 0, 2, }, |
| 126004 | /* 1 START: */ { 1, 1, 2, }, |
| 126005 | /* 2 NORMAL: */ { 1, 2, 2, }, |
| 126006 | }; |
| 126007 | #endif /* SQLITE_OMIT_TRIGGER */ |
| 126008 | |
| 126009 | #ifdef SQLITE_ENABLE_API_ARMOR |
| 126010 | if( zSql==0 ){ |
| 126011 | (void)SQLITE_MISUSE_BKPT; |
| 126012 | return 0; |
| 126013 | } |
| 126014 | #endif |
| 126015 | |
| 126016 | while( *zSql ){ |
| 126017 | switch( *zSql ){ |
| 126018 | case ';': { /* A semicolon */ |
| 126019 | token = tkSEMI; |
| @@ -126109,11 +126312,11 @@ | |
| 126312 | ** If the following function pointer is not NULL and if |
| 126313 | ** SQLITE_ENABLE_IOTRACE is enabled, then messages describing |
| 126314 | ** I/O active are written using this function. These messages |
| 126315 | ** are intended for debugging activity only. |
| 126316 | */ |
| 126317 | /* not-private */ void (*sqlite3IoTrace)(const char*, ...) = 0; |
| 126318 | #endif |
| 126319 | |
| 126320 | /* |
| 126321 | ** If the following global variable points to a string which is the |
| 126322 | ** name of a directory, then that directory will be used to store |
| @@ -126318,10 +126521,17 @@ | |
| 126521 | ** routine is not threadsafe. But it is safe to invoke this routine |
| 126522 | ** on when SQLite is already shut down. If SQLite is already shut down |
| 126523 | ** when this routine is invoked, then this routine is a harmless no-op. |
| 126524 | */ |
| 126525 | SQLITE_API int sqlite3_shutdown(void){ |
| 126526 | #ifdef SQLITE_OMIT_WSD |
| 126527 | int rc = sqlite3_wsd_init(4096, 24); |
| 126528 | if( rc!=SQLITE_OK ){ |
| 126529 | return rc; |
| 126530 | } |
| 126531 | #endif |
| 126532 | |
| 126533 | if( sqlite3GlobalConfig.isInit ){ |
| 126534 | #ifdef SQLITE_EXTRA_SHUTDOWN |
| 126535 | void SQLITE_EXTRA_SHUTDOWN(void); |
| 126536 | SQLITE_EXTRA_SHUTDOWN(); |
| 126537 | #endif |
| @@ -126633,10 +126843,15 @@ | |
| 126843 | ** heap. */ |
| 126844 | sqlite3GlobalConfig.nHeap = va_arg(ap, int); |
| 126845 | break; |
| 126846 | } |
| 126847 | #endif |
| 126848 | |
| 126849 | case SQLITE_CONFIG_PMASZ: { |
| 126850 | sqlite3GlobalConfig.szPma = va_arg(ap, unsigned int); |
| 126851 | break; |
| 126852 | } |
| 126853 | |
| 126854 | default: { |
| 126855 | rc = SQLITE_ERROR; |
| 126856 | break; |
| 126857 | } |
| @@ -127983,14 +128198,17 @@ | |
| 128198 | |
| 128199 | /* Initialize the output variables to -1 in case an error occurs. */ |
| 128200 | if( pnLog ) *pnLog = -1; |
| 128201 | if( pnCkpt ) *pnCkpt = -1; |
| 128202 | |
| 128203 | assert( SQLITE_CHECKPOINT_PASSIVE==0 ); |
| 128204 | assert( SQLITE_CHECKPOINT_FULL==1 ); |
| 128205 | assert( SQLITE_CHECKPOINT_RESTART==2 ); |
| 128206 | assert( SQLITE_CHECKPOINT_TRUNCATE==3 ); |
| 128207 | if( eMode<SQLITE_CHECKPOINT_PASSIVE || eMode>SQLITE_CHECKPOINT_TRUNCATE ){ |
| 128208 | /* EVIDENCE-OF: R-03996-12088 The M parameter must be a valid checkpoint |
| 128209 | ** mode: */ |
| 128210 | return SQLITE_MISUSE; |
| 128211 | } |
| 128212 | |
| 128213 | sqlite3_mutex_enter(db->mutex); |
| 128214 | if( zDb && zDb[0] ){ |
| @@ -128014,11 +128232,13 @@ | |
| 128232 | ** Checkpoint database zDb. If zDb is NULL, or if the buffer zDb points |
| 128233 | ** to contains a zero-length string, all attached databases are |
| 128234 | ** checkpointed. |
| 128235 | */ |
| 128236 | SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb){ |
| 128237 | /* EVIDENCE-OF: R-41613-20553 The sqlite3_wal_checkpoint(D,X) is equivalent to |
| 128238 | ** sqlite3_wal_checkpoint_v2(D,X,SQLITE_CHECKPOINT_PASSIVE,0,0). */ |
| 128239 | return sqlite3_wal_checkpoint_v2(db,zDb,SQLITE_CHECKPOINT_PASSIVE,0,0); |
| 128240 | } |
| 128241 | |
| 128242 | #ifndef SQLITE_OMIT_WAL |
| 128243 | /* |
| 128244 | ** Run a checkpoint on database iDb. This is a no-op if database iDb is |
| @@ -128201,36 +128421,10 @@ | |
| 128421 | */ |
| 128422 | SQLITE_API const char *sqlite3_errstr(int rc){ |
| 128423 | return sqlite3ErrStr(rc); |
| 128424 | } |
| 128425 | |
| 128426 | /* |
| 128427 | ** Create a new collating function for database "db". The name is zName |
| 128428 | ** and the encoding is enc. |
| 128429 | */ |
| 128430 | static int createCollation( |
| @@ -128270,11 +128464,10 @@ | |
| 128464 | sqlite3ErrorWithMsg(db, SQLITE_BUSY, |
| 128465 | "unable to delete/modify collation sequence due to active statements"); |
| 128466 | return SQLITE_BUSY; |
| 128467 | } |
| 128468 | sqlite3ExpirePreparedStatements(db); |
| 128469 | |
| 128470 | /* If collation sequence pColl was created directly by a call to |
| 128471 | ** sqlite3_create_collation, and not generated by synthCollSeq(), |
| 128472 | ** then any copies made by synthCollSeq() need to be invalidated. |
| 128473 | ** Also, collation destructor - CollSeq.xDel() - function may need |
| @@ -128775,10 +128968,13 @@ | |
| 128968 | | SQLITE_RecTriggers |
| 128969 | #endif |
| 128970 | #if defined(SQLITE_DEFAULT_FOREIGN_KEYS) && SQLITE_DEFAULT_FOREIGN_KEYS |
| 128971 | | SQLITE_ForeignKeys |
| 128972 | #endif |
| 128973 | #if defined(SQLITE_REVERSE_UNORDERED_SELECTS) |
| 128974 | | SQLITE_ReverseOrder |
| 128975 | #endif |
| 128976 | ; |
| 128977 | sqlite3HashInit(&db->aCollSeq); |
| 128978 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 128979 | sqlite3HashInit(&db->aModule); |
| 128980 | #endif |
| @@ -128822,11 +129018,14 @@ | |
| 129018 | rc = SQLITE_NOMEM; |
| 129019 | } |
| 129020 | sqlite3Error(db, rc); |
| 129021 | goto opendb_out; |
| 129022 | } |
| 129023 | sqlite3BtreeEnter(db->aDb[0].pBt); |
| 129024 | db->aDb[0].pSchema = sqlite3SchemaGet(db, db->aDb[0].pBt); |
| 129025 | if( !db->mallocFailed ) ENC(db) = SCHEMA_ENC(db); |
| 129026 | sqlite3BtreeLeave(db->aDb[0].pBt); |
| 129027 | db->aDb[1].pSchema = sqlite3SchemaGet(db, 0); |
| 129028 | |
| 129029 | /* The default safety_level for the main database is 'full'; for the temp |
| 129030 | ** database it is 'NONE'. This matches the pager layer defaults. |
| 129031 | */ |
| @@ -128980,11 +129179,11 @@ | |
| 129179 | if( zFilename8 ){ |
| 129180 | rc = openDatabase(zFilename8, ppDb, |
| 129181 | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0); |
| 129182 | assert( *ppDb || rc==SQLITE_NOMEM ); |
| 129183 | if( rc==SQLITE_OK && !DbHasProperty(*ppDb, 0, DB_SchemaLoaded) ){ |
| 129184 | SCHEMA_ENC(*ppDb) = ENC(*ppDb) = SQLITE_UTF16NATIVE; |
| 129185 | } |
| 129186 | }else{ |
| 129187 | rc = SQLITE_NOMEM; |
| 129188 | } |
| 129189 | sqlite3ValueFree(pVal); |
| @@ -129176,11 +129375,10 @@ | |
| 129375 | |
| 129376 | /* |
| 129377 | ** Return meta information about a specific column of a database table. |
| 129378 | ** See comment in sqlite3.h (sqlite.h.in) for details. |
| 129379 | */ |
| 129380 | SQLITE_API int sqlite3_table_column_metadata( |
| 129381 | sqlite3 *db, /* Connection handle */ |
| 129382 | const char *zDbName, /* Database name or NULL */ |
| 129383 | const char *zTableName, /* Table name */ |
| 129384 | const char *zColumnName, /* Column name */ |
| @@ -129216,25 +129414,27 @@ | |
| 129414 | pTab = 0; |
| 129415 | goto error_out; |
| 129416 | } |
| 129417 | |
| 129418 | /* Find the column for which info is requested */ |
| 129419 | if( zColumnName==0 ){ |
| 129420 | /* Query for existance of table only */ |
| 129421 | }else{ |
| 129422 | for(iCol=0; iCol<pTab->nCol; iCol++){ |
| 129423 | pCol = &pTab->aCol[iCol]; |
| 129424 | if( 0==sqlite3StrICmp(pCol->zName, zColumnName) ){ |
| 129425 | break; |
| 129426 | } |
| 129427 | } |
| 129428 | if( iCol==pTab->nCol ){ |
| 129429 | if( HasRowid(pTab) && sqlite3IsRowid(zColumnName) ){ |
| 129430 | iCol = pTab->iPKey; |
| 129431 | pCol = iCol>=0 ? &pTab->aCol[iCol] : 0; |
| 129432 | }else{ |
| 129433 | pTab = 0; |
| 129434 | goto error_out; |
| 129435 | } |
| 129436 | } |
| 129437 | } |
| 129438 | |
| 129439 | /* The following block stores the meta information that will be returned |
| 129440 | ** to the caller in local variables zDataType, zCollSeq, notnull, primarykey |
| @@ -129283,11 +129483,10 @@ | |
| 129483 | sqlite3DbFree(db, zErrMsg); |
| 129484 | rc = sqlite3ApiExit(db, rc); |
| 129485 | sqlite3_mutex_leave(db->mutex); |
| 129486 | return rc; |
| 129487 | } |
| 129488 | |
| 129489 | /* |
| 129490 | ** Sleep for a little while. Return the amount of time slept. |
| 129491 | */ |
| 129492 | SQLITE_API int sqlite3_sleep(int ms){ |
| @@ -129722,32 +129921,34 @@ | |
| 129921 | /* |
| 129922 | ** Return the filename of the database associated with a database |
| 129923 | ** connection. |
| 129924 | */ |
| 129925 | SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName){ |
| 129926 | Btree *pBt; |
| 129927 | #ifdef SQLITE_ENABLE_API_ARMOR |
| 129928 | if( !sqlite3SafetyCheckOk(db) ){ |
| 129929 | (void)SQLITE_MISUSE_BKPT; |
| 129930 | return 0; |
| 129931 | } |
| 129932 | #endif |
| 129933 | pBt = sqlite3DbNameToBtree(db, zDbName); |
| 129934 | return pBt ? sqlite3BtreeGetFilename(pBt) : 0; |
| 129935 | } |
| 129936 | |
| 129937 | /* |
| 129938 | ** Return 1 if database is read-only or 0 if read/write. Return -1 if |
| 129939 | ** no such database exists. |
| 129940 | */ |
| 129941 | SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName){ |
| 129942 | Btree *pBt; |
| 129943 | #ifdef SQLITE_ENABLE_API_ARMOR |
| 129944 | if( !sqlite3SafetyCheckOk(db) ){ |
| 129945 | (void)SQLITE_MISUSE_BKPT; |
| 129946 | return -1; |
| 129947 | } |
| 129948 | #endif |
| 129949 | pBt = sqlite3DbNameToBtree(db, zDbName); |
| 129950 | return pBt ? sqlite3BtreeIsReadonly(pBt) : -1; |
| 129951 | } |
| 129952 | |
| 129953 | /************** End of main.c ************************************************/ |
| 129954 | /************** Begin file notify.c ******************************************/ |
| @@ -139164,11 +139365,11 @@ | |
| 139365 | ** Return true if the m-value for z is 1 or more. In other words, |
| 139366 | ** return true if z contains at least one vowel that is followed |
| 139367 | ** by a consonant. |
| 139368 | ** |
| 139369 | ** In this routine z[] is in reverse order. So we are really looking |
| 139370 | ** for an instance of a consonant followed by a vowel. |
| 139371 | */ |
| 139372 | static int m_gt_0(const char *z){ |
| 139373 | while( isVowel(z) ){ z++; } |
| 139374 | if( *z==0 ) return 0; |
| 139375 | while( isConsonant(z) ){ z++; } |
| @@ -149954,11 +150155,11 @@ | |
| 150155 | } |
| 150156 | i = pCur->nPoint++; |
| 150157 | pNew = pCur->aPoint + i; |
| 150158 | pNew->rScore = rScore; |
| 150159 | pNew->iLevel = iLevel; |
| 150160 | assert( iLevel<=RTREE_MAX_DEPTH ); |
| 150161 | while( i>0 ){ |
| 150162 | RtreeSearchPoint *pParent; |
| 150163 | j = (i-1)/2; |
| 150164 | pParent = pCur->aPoint + j; |
| 150165 | if( rtreeSearchPointCompare(pNew, pParent)>=0 ) break; |
| 150166 |
+160
-122
| --- src/sqlite3.h | ||
| +++ src/sqlite3.h | ||
| @@ -107,11 +107,11 @@ | ||
| 107 | 107 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 108 | 108 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 109 | 109 | */ |
| 110 | 110 | #define SQLITE_VERSION "3.8.8" |
| 111 | 111 | #define SQLITE_VERSION_NUMBER 3008008 |
| 112 | -#define SQLITE_SOURCE_ID "2014-11-28 13:35:03 24fa2e9832daaa5d68ee28a00c56c55f97a4da9e" | |
| 112 | +#define SQLITE_SOURCE_ID "2015-01-03 18:59:17 23d4c07eb81db5a5c6beb56b5820f0b6501f1fb6" | |
| 113 | 113 | |
| 114 | 114 | /* |
| 115 | 115 | ** CAPI3REF: Run-Time Library Version Numbers |
| 116 | 116 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 117 | 117 | ** |
| @@ -199,11 +199,11 @@ | ||
| 199 | 199 | ** This interface only reports on the compile-time mutex setting |
| 200 | 200 | ** of the [SQLITE_THREADSAFE] flag. If SQLite is compiled with |
| 201 | 201 | ** SQLITE_THREADSAFE=1 or =2 then mutexes are enabled by default but |
| 202 | 202 | ** can be fully or partially disabled using a call to [sqlite3_config()] |
| 203 | 203 | ** with the verbs [SQLITE_CONFIG_SINGLETHREAD], [SQLITE_CONFIG_MULTITHREAD], |
| 204 | -** or [SQLITE_CONFIG_MUTEX]. ^(The return value of the | |
| 204 | +** or [SQLITE_CONFIG_SERIALIZED]. ^(The return value of the | |
| 205 | 205 | ** sqlite3_threadsafe() function shows only the compile-time setting of |
| 206 | 206 | ** thread safety, not any run-time changes to that setting made by |
| 207 | 207 | ** sqlite3_config(). In other words, the return value from sqlite3_threadsafe() |
| 208 | 208 | ** is unchanged by calls to sqlite3_config().)^ |
| 209 | 209 | ** |
| @@ -1219,11 +1219,11 @@ | ||
| 1219 | 1219 | ** <li> SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED |
| 1220 | 1220 | ** <li> SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE |
| 1221 | 1221 | ** </ul> |
| 1222 | 1222 | ** |
| 1223 | 1223 | ** When unlocking, the same SHARED or EXCLUSIVE flag must be supplied as |
| 1224 | -** was given no the corresponding lock. | |
| 1224 | +** was given on the corresponding lock. | |
| 1225 | 1225 | ** |
| 1226 | 1226 | ** The xShmLock method can transition between unlocked and SHARED or |
| 1227 | 1227 | ** between unlocked and EXCLUSIVE. It cannot transition between SHARED |
| 1228 | 1228 | ** and EXCLUSIVE. |
| 1229 | 1229 | */ |
| @@ -1522,12 +1522,12 @@ | ||
| 1522 | 1522 | ** tracks memory usage, for example. </dd> |
| 1523 | 1523 | ** |
| 1524 | 1524 | ** [[SQLITE_CONFIG_MEMSTATUS]] <dt>SQLITE_CONFIG_MEMSTATUS</dt> |
| 1525 | 1525 | ** <dd> ^The SQLITE_CONFIG_MEMSTATUS option takes single argument of type int, |
| 1526 | 1526 | ** interpreted as a boolean, which enables or disables the collection of |
| 1527 | -** memory allocation statistics. ^(When memory allocation statistics are disabled, the | |
| 1528 | -** following SQLite interfaces become non-operational: | |
| 1527 | +** memory allocation statistics. ^(When memory allocation statistics are | |
| 1528 | +** disabled, the following SQLite interfaces become non-operational: | |
| 1529 | 1529 | ** <ul> |
| 1530 | 1530 | ** <li> [sqlite3_memory_used()] |
| 1531 | 1531 | ** <li> [sqlite3_memory_highwater()] |
| 1532 | 1532 | ** <li> [sqlite3_soft_heap_limit64()] |
| 1533 | 1533 | ** <li> [sqlite3_status()] |
| @@ -1564,14 +1564,15 @@ | ||
| 1564 | 1564 | ** that SQLite can use for the database page cache with the default page |
| 1565 | 1565 | ** cache implementation. |
| 1566 | 1566 | ** This configuration should not be used if an application-define page |
| 1567 | 1567 | ** cache implementation is loaded using the [SQLITE_CONFIG_PCACHE2] |
| 1568 | 1568 | ** configuration option. |
| 1569 | -** ^There are three arguments to SQLITE_CONFIG_PAGECACHE: A pointer to 8-byte aligned | |
| 1569 | +** ^There are three arguments to SQLITE_CONFIG_PAGECACHE: A pointer to | |
| 1570 | +** 8-byte aligned | |
| 1570 | 1571 | ** memory, the size of each page buffer (sz), and the number of pages (N). |
| 1571 | 1572 | ** The sz argument should be the size of the largest database page |
| 1572 | -** (a power of two between 512 and 32768) plus some extra bytes for each | |
| 1573 | +** (a power of two between 512 and 65536) plus some extra bytes for each | |
| 1573 | 1574 | ** page header. ^The number of extra bytes needed by the page header |
| 1574 | 1575 | ** can be determined using the [SQLITE_CONFIG_PCACHE_HDRSZ] option |
| 1575 | 1576 | ** to [sqlite3_config()]. |
| 1576 | 1577 | ** ^It is harmless, apart from the wasted memory, |
| 1577 | 1578 | ** for the sz parameter to be larger than necessary. The first |
| @@ -1584,11 +1585,12 @@ | ||
| 1584 | 1585 | ** SQLite goes to [sqlite3_malloc()] for the additional storage space.</dd> |
| 1585 | 1586 | ** |
| 1586 | 1587 | ** [[SQLITE_CONFIG_HEAP]] <dt>SQLITE_CONFIG_HEAP</dt> |
| 1587 | 1588 | ** <dd> ^The SQLITE_CONFIG_HEAP option specifies a static memory buffer |
| 1588 | 1589 | ** that SQLite will use for all of its dynamic memory allocation needs |
| 1589 | -** beyond those provided for by [SQLITE_CONFIG_SCRATCH] and [SQLITE_CONFIG_PAGECACHE]. | |
| 1590 | +** beyond those provided for by [SQLITE_CONFIG_SCRATCH] and | |
| 1591 | +** [SQLITE_CONFIG_PAGECACHE]. | |
| 1590 | 1592 | ** ^The SQLITE_CONFIG_HEAP option is only available if SQLite is compiled |
| 1591 | 1593 | ** with either [SQLITE_ENABLE_MEMSYS3] or [SQLITE_ENABLE_MEMSYS5] and returns |
| 1592 | 1594 | ** [SQLITE_ERROR] if invoked otherwise. |
| 1593 | 1595 | ** ^There are three arguments to SQLITE_CONFIG_HEAP: |
| 1594 | 1596 | ** An 8-byte aligned pointer to the memory, |
| @@ -1604,13 +1606,13 @@ | ||
| 1604 | 1606 | ** for the minimum allocation size are 2**5 through 2**8.</dd> |
| 1605 | 1607 | ** |
| 1606 | 1608 | ** [[SQLITE_CONFIG_MUTEX]] <dt>SQLITE_CONFIG_MUTEX</dt> |
| 1607 | 1609 | ** <dd> ^(The SQLITE_CONFIG_MUTEX option takes a single argument which is a |
| 1608 | 1610 | ** pointer to an instance of the [sqlite3_mutex_methods] structure. |
| 1609 | -** The argument specifies alternative low-level mutex routines to be used in place | |
| 1610 | -** the mutex routines built into SQLite.)^ ^SQLite makes a copy of the | |
| 1611 | -** content of the [sqlite3_mutex_methods] structure before the call to | |
| 1611 | +** The argument specifies alternative low-level mutex routines to be used | |
| 1612 | +** in place the mutex routines built into SQLite.)^ ^SQLite makes a copy of | |
| 1613 | +** the content of the [sqlite3_mutex_methods] structure before the call to | |
| 1612 | 1614 | ** [sqlite3_config()] returns. ^If SQLite is compiled with |
| 1613 | 1615 | ** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then |
| 1614 | 1616 | ** the entire mutexing subsystem is omitted from the build and hence calls to |
| 1615 | 1617 | ** [sqlite3_config()] with the SQLITE_CONFIG_MUTEX configuration option will |
| 1616 | 1618 | ** return [SQLITE_ERROR].</dd> |
| @@ -1644,12 +1646,12 @@ | ||
| 1644 | 1646 | ** the interface to a custom page cache implementation.)^ |
| 1645 | 1647 | ** ^SQLite makes a copy of the [sqlite3_pcache_methods2] object.</dd> |
| 1646 | 1648 | ** |
| 1647 | 1649 | ** [[SQLITE_CONFIG_GETPCACHE2]] <dt>SQLITE_CONFIG_GETPCACHE2</dt> |
| 1648 | 1650 | ** <dd> ^(The SQLITE_CONFIG_GETPCACHE2 option takes a single argument which |
| 1649 | -** is a pointer to an [sqlite3_pcache_methods2] object. SQLite copies of the current | |
| 1650 | -** page cache implementation into that object.)^ </dd> | |
| 1651 | +** is a pointer to an [sqlite3_pcache_methods2] object. SQLite copies of | |
| 1652 | +** the current page cache implementation into that object.)^ </dd> | |
| 1651 | 1653 | ** |
| 1652 | 1654 | ** [[SQLITE_CONFIG_LOG]] <dt>SQLITE_CONFIG_LOG</dt> |
| 1653 | 1655 | ** <dd> The SQLITE_CONFIG_LOG option is used to configure the SQLite |
| 1654 | 1656 | ** global [error log]. |
| 1655 | 1657 | ** (^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a |
| @@ -1670,12 +1672,13 @@ | ||
| 1670 | 1672 | ** function must be threadsafe. </dd> |
| 1671 | 1673 | ** |
| 1672 | 1674 | ** [[SQLITE_CONFIG_URI]] <dt>SQLITE_CONFIG_URI |
| 1673 | 1675 | ** <dd>^(The SQLITE_CONFIG_URI option takes a single argument of type int. |
| 1674 | 1676 | ** If non-zero, then URI handling is globally enabled. If the parameter is zero, |
| 1675 | -** then URI handling is globally disabled.)^ ^If URI handling is globally enabled, | |
| 1676 | -** all filenames passed to [sqlite3_open()], [sqlite3_open_v2()], [sqlite3_open16()] or | |
| 1677 | +** then URI handling is globally disabled.)^ ^If URI handling is globally | |
| 1678 | +** enabled, all filenames passed to [sqlite3_open()], [sqlite3_open_v2()], | |
| 1679 | +** [sqlite3_open16()] or | |
| 1677 | 1680 | ** specified as part of [ATTACH] commands are interpreted as URIs, regardless |
| 1678 | 1681 | ** of whether or not the [SQLITE_OPEN_URI] flag is set when the database |
| 1679 | 1682 | ** connection is opened. ^If it is globally disabled, filenames are |
| 1680 | 1683 | ** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the |
| 1681 | 1684 | ** database connection is opened. ^(By default, URI handling is globally |
| @@ -1733,22 +1736,33 @@ | ||
| 1733 | 1736 | ** changed to its compile-time default. |
| 1734 | 1737 | ** |
| 1735 | 1738 | ** [[SQLITE_CONFIG_WIN32_HEAPSIZE]] |
| 1736 | 1739 | ** <dt>SQLITE_CONFIG_WIN32_HEAPSIZE |
| 1737 | 1740 | ** <dd>^The SQLITE_CONFIG_WIN32_HEAPSIZE option is only available if SQLite is |
| 1738 | -** compiled for Windows with the [SQLITE_WIN32_MALLOC] pre-processor macro defined. | |
| 1739 | -** ^SQLITE_CONFIG_WIN32_HEAPSIZE takes a 32-bit unsigned integer value | |
| 1741 | +** compiled for Windows with the [SQLITE_WIN32_MALLOC] pre-processor macro | |
| 1742 | +** defined. ^SQLITE_CONFIG_WIN32_HEAPSIZE takes a 32-bit unsigned integer value | |
| 1740 | 1743 | ** that specifies the maximum size of the created heap. |
| 1741 | 1744 | ** </dl> |
| 1742 | 1745 | ** |
| 1743 | 1746 | ** [[SQLITE_CONFIG_PCACHE_HDRSZ]] |
| 1744 | 1747 | ** <dt>SQLITE_CONFIG_PCACHE_HDRSZ |
| 1745 | 1748 | ** <dd>^The SQLITE_CONFIG_PCACHE_HDRSZ option takes a single parameter which |
| 1746 | 1749 | ** is a pointer to an integer and writes into that integer the number of extra |
| 1747 | -** bytes per page required for each page in [SQLITE_CONFIG_PAGECACHE]. The amount of | |
| 1748 | -** extra space required can change depending on the compiler, | |
| 1750 | +** bytes per page required for each page in [SQLITE_CONFIG_PAGECACHE]. | |
| 1751 | +** The amount of extra space required can change depending on the compiler, | |
| 1749 | 1752 | ** target platform, and SQLite version. |
| 1753 | +** | |
| 1754 | +** [[SQLITE_CONFIG_PMASZ]] | |
| 1755 | +** <dt>SQLITE_CONFIG_PMASZ | |
| 1756 | +** <dd>^The SQLITE_CONFIG_PMASZ option takes a single parameter which | |
| 1757 | +** is an unsigned integer and sets the "Minimum PMA Size" for the multithreaded | |
| 1758 | +** sorter to that integer. The default minimum PMA Size is set by the | |
| 1759 | +** [SQLITE_SORTER_PMASZ] compile-time option. New threads are launched | |
| 1760 | +** to help with sort operations when multithreaded sorting | |
| 1761 | +** is enabled (using the [PRAGMA threads] command) and the amount of content | |
| 1762 | +** to be sorted exceeds the page size times the minimum of the | |
| 1763 | +** [PRAGMA cache_size] setting and this value. | |
| 1750 | 1764 | ** </dl> |
| 1751 | 1765 | */ |
| 1752 | 1766 | #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ |
| 1753 | 1767 | #define SQLITE_CONFIG_MULTITHREAD 2 /* nil */ |
| 1754 | 1768 | #define SQLITE_CONFIG_SERIALIZED 3 /* nil */ |
| @@ -1771,10 +1785,11 @@ | ||
| 1771 | 1785 | #define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */ |
| 1772 | 1786 | #define SQLITE_CONFIG_SQLLOG 21 /* xSqllog, void* */ |
| 1773 | 1787 | #define SQLITE_CONFIG_MMAP_SIZE 22 /* sqlite3_int64, sqlite3_int64 */ |
| 1774 | 1788 | #define SQLITE_CONFIG_WIN32_HEAPSIZE 23 /* int nByte */ |
| 1775 | 1789 | #define SQLITE_CONFIG_PCACHE_HDRSZ 24 /* int *psz */ |
| 1790 | +#define SQLITE_CONFIG_PMASZ 25 /* unsigned int szPma */ | |
| 1776 | 1791 | |
| 1777 | 1792 | /* |
| 1778 | 1793 | ** CAPI3REF: Database Connection Configuration Options |
| 1779 | 1794 | ** |
| 1780 | 1795 | ** These constants are the available integer configuration options that |
| @@ -2047,10 +2062,11 @@ | ||
| 2047 | 2062 | SQLITE_API int sqlite3_complete(const char *sql); |
| 2048 | 2063 | SQLITE_API int sqlite3_complete16(const void *sql); |
| 2049 | 2064 | |
| 2050 | 2065 | /* |
| 2051 | 2066 | ** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors |
| 2067 | +** KEYWORDS: {busy-handler callback} {busy handler} | |
| 2052 | 2068 | ** |
| 2053 | 2069 | ** ^The sqlite3_busy_handler(D,X,P) routine sets a callback function X |
| 2054 | 2070 | ** that might be invoked with argument P whenever |
| 2055 | 2071 | ** an attempt is made to access a database table associated with |
| 2056 | 2072 | ** [database connection] D when another thread |
| @@ -2063,11 +2079,11 @@ | ||
| 2063 | 2079 | ** is not NULL, then the callback might be invoked with two arguments. |
| 2064 | 2080 | ** |
| 2065 | 2081 | ** ^The first argument to the busy handler is a copy of the void* pointer which |
| 2066 | 2082 | ** is the third argument to sqlite3_busy_handler(). ^The second argument to |
| 2067 | 2083 | ** the busy handler callback is the number of times that the busy handler has |
| 2068 | -** been invoked for the same locking event. ^If the | |
| 2084 | +** been invoked previously for the same locking event. ^If the | |
| 2069 | 2085 | ** busy callback returns 0, then no additional attempts are made to |
| 2070 | 2086 | ** access the database and [SQLITE_BUSY] is returned |
| 2071 | 2087 | ** to the application. |
| 2072 | 2088 | ** ^If the callback returns non-zero, then another attempt |
| 2073 | 2089 | ** is made to access the database and the cycle repeats. |
| @@ -4518,11 +4534,12 @@ | ||
| 4518 | 4534 | ** If these routines are called from within the different thread |
| 4519 | 4535 | ** than the one containing the application-defined function that received |
| 4520 | 4536 | ** the [sqlite3_context] pointer, the results are undefined. |
| 4521 | 4537 | */ |
| 4522 | 4538 | SQLITE_API void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); |
| 4523 | -SQLITE_API void sqlite3_result_blob64(sqlite3_context*,const void*,sqlite3_uint64,void(*)(void*)); | |
| 4539 | +SQLITE_API void sqlite3_result_blob64(sqlite3_context*,const void*, | |
| 4540 | + sqlite3_uint64,void(*)(void*)); | |
| 4524 | 4541 | SQLITE_API void sqlite3_result_double(sqlite3_context*, double); |
| 4525 | 4542 | SQLITE_API void sqlite3_result_error(sqlite3_context*, const char*, int); |
| 4526 | 4543 | SQLITE_API void sqlite3_result_error16(sqlite3_context*, const void*, int); |
| 4527 | 4544 | SQLITE_API void sqlite3_result_error_toobig(sqlite3_context*); |
| 4528 | 4545 | SQLITE_API void sqlite3_result_error_nomem(sqlite3_context*); |
| @@ -5150,24 +5167,31 @@ | ||
| 5150 | 5167 | |
| 5151 | 5168 | |
| 5152 | 5169 | /* |
| 5153 | 5170 | ** CAPI3REF: Extract Metadata About A Column Of A Table |
| 5154 | 5171 | ** |
| 5155 | -** ^This routine returns metadata about a specific column of a specific | |
| 5156 | -** database table accessible using the [database connection] handle | |
| 5157 | -** passed as the first function argument. | |
| 5172 | +** ^(The sqlite3_table_column_metadata(X,D,T,C,....) routine returns | |
| 5173 | +** information about column C of table T in database D | |
| 5174 | +** on [database connection] X.)^ ^The sqlite3_table_column_metadata() | |
| 5175 | +** interface returns SQLITE_OK and fills in the non-NULL pointers in | |
| 5176 | +** the final five arguments with appropriate values if the specified | |
| 5177 | +** column exists. ^The sqlite3_table_column_metadata() interface returns | |
| 5178 | +** SQLITE_ERROR and if the specified column does not exist. | |
| 5179 | +** ^If the column-name parameter to sqlite3_table_column_metadata() is a | |
| 5180 | +** NULL pointer, then this routine simply checks for the existance of the | |
| 5181 | +** table and returns SQLITE_OK if the table exists and SQLITE_ERROR if it | |
| 5182 | +** does not. | |
| 5158 | 5183 | ** |
| 5159 | 5184 | ** ^The column is identified by the second, third and fourth parameters to |
| 5160 | -** this function. ^The second parameter is either the name of the database | |
| 5185 | +** this function. ^(The second parameter is either the name of the database | |
| 5161 | 5186 | ** (i.e. "main", "temp", or an attached database) containing the specified |
| 5162 | -** table or NULL. ^If it is NULL, then all attached databases are searched | |
| 5187 | +** table or NULL.)^ ^If it is NULL, then all attached databases are searched | |
| 5163 | 5188 | ** for the table using the same algorithm used by the database engine to |
| 5164 | 5189 | ** resolve unqualified table references. |
| 5165 | 5190 | ** |
| 5166 | 5191 | ** ^The third and fourth parameters to this function are the table and column |
| 5167 | -** name of the desired column, respectively. Neither of these parameters | |
| 5168 | -** may be NULL. | |
| 5192 | +** name of the desired column, respectively. | |
| 5169 | 5193 | ** |
| 5170 | 5194 | ** ^Metadata is returned by writing to the memory locations passed as the 5th |
| 5171 | 5195 | ** and subsequent parameters to this function. ^Any of these arguments may be |
| 5172 | 5196 | ** NULL, in which case the corresponding element of metadata is omitted. |
| 5173 | 5197 | ** |
| @@ -5182,36 +5206,33 @@ | ||
| 5182 | 5206 | ** <tr><td> 9th <td> int <td> True if column is [AUTOINCREMENT] |
| 5183 | 5207 | ** </table> |
| 5184 | 5208 | ** </blockquote>)^ |
| 5185 | 5209 | ** |
| 5186 | 5210 | ** ^The memory pointed to by the character pointers returned for the |
| 5187 | -** declaration type and collation sequence is valid only until the next | |
| 5211 | +** declaration type and collation sequence is valid until the next | |
| 5188 | 5212 | ** call to any SQLite API function. |
| 5189 | 5213 | ** |
| 5190 | 5214 | ** ^If the specified table is actually a view, an [error code] is returned. |
| 5191 | 5215 | ** |
| 5192 | -** ^If the specified column is "rowid", "oid" or "_rowid_" and an | |
| 5216 | +** ^If the specified column is "rowid", "oid" or "_rowid_" and the table | |
| 5217 | +** is not a [WITHOUT ROWID] table and an | |
| 5193 | 5218 | ** [INTEGER PRIMARY KEY] column has been explicitly declared, then the output |
| 5194 | 5219 | ** parameters are set for the explicitly declared column. ^(If there is no |
| 5195 | -** explicitly declared [INTEGER PRIMARY KEY] column, then the output | |
| 5196 | -** parameters are set as follows: | |
| 5220 | +** [INTEGER PRIMARY KEY] column, then the outputs | |
| 5221 | +** for the [rowid] are set as follows: | |
| 5197 | 5222 | ** |
| 5198 | 5223 | ** <pre> |
| 5199 | 5224 | ** data type: "INTEGER" |
| 5200 | 5225 | ** collation sequence: "BINARY" |
| 5201 | 5226 | ** not null: 0 |
| 5202 | 5227 | ** primary key: 1 |
| 5203 | 5228 | ** auto increment: 0 |
| 5204 | 5229 | ** </pre>)^ |
| 5205 | 5230 | ** |
| 5206 | -** ^(This function may load one or more schemas from database files. If an | |
| 5207 | -** error occurs during this process, or if the requested table or column | |
| 5208 | -** cannot be found, an [error code] is returned and an error message left | |
| 5209 | -** in the [database connection] (to be retrieved using sqlite3_errmsg()).)^ | |
| 5210 | -** | |
| 5211 | -** ^This API is only available if the library was compiled with the | |
| 5212 | -** [SQLITE_ENABLE_COLUMN_METADATA] C-preprocessor symbol defined. | |
| 5231 | +** ^This function causes all database schemas to be read from disk and | |
| 5232 | +** parsed, if that has not already been done, and returns an error if | |
| 5233 | +** any errors are encountered while loading the schema. | |
| 5213 | 5234 | */ |
| 5214 | 5235 | SQLITE_API int sqlite3_table_column_metadata( |
| 5215 | 5236 | sqlite3 *db, /* Connection handle */ |
| 5216 | 5237 | const char *zDbName, /* Database name or NULL */ |
| 5217 | 5238 | const char *zTableName, /* Table name */ |
| @@ -7174,16 +7195,14 @@ | ||
| 7174 | 7195 | |
| 7175 | 7196 | /* |
| 7176 | 7197 | ** CAPI3REF: Write-Ahead Log Commit Hook |
| 7177 | 7198 | ** |
| 7178 | 7199 | ** ^The [sqlite3_wal_hook()] function is used to register a callback that |
| 7179 | -** will be invoked each time a database connection commits data to a | |
| 7180 | -** [write-ahead log] (i.e. whenever a transaction is committed in | |
| 7181 | -** [journal_mode | journal_mode=WAL mode]). | |
| 7200 | +** is invoked each time data is committed to a database in wal mode. | |
| 7182 | 7201 | ** |
| 7183 | -** ^The callback is invoked by SQLite after the commit has taken place and | |
| 7184 | -** the associated write-lock on the database released, so the implementation | |
| 7202 | +** ^(The callback is invoked by SQLite after the commit has taken place and | |
| 7203 | +** the associated write-lock on the database released)^, so the implementation | |
| 7185 | 7204 | ** may read, write or [checkpoint] the database as required. |
| 7186 | 7205 | ** |
| 7187 | 7206 | ** ^The first parameter passed to the callback function when it is invoked |
| 7188 | 7207 | ** is a copy of the third parameter passed to sqlite3_wal_hook() when |
| 7189 | 7208 | ** registering the callback. ^The second is a copy of the database handle. |
| @@ -7244,101 +7263,118 @@ | ||
| 7244 | 7263 | SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N); |
| 7245 | 7264 | |
| 7246 | 7265 | /* |
| 7247 | 7266 | ** CAPI3REF: Checkpoint a database |
| 7248 | 7267 | ** |
| 7249 | -** ^The [sqlite3_wal_checkpoint(D,X)] interface causes database named X | |
| 7250 | -** on [database connection] D to be [checkpointed]. ^If X is NULL or an | |
| 7251 | -** empty string, then a checkpoint is run on all databases of | |
| 7252 | -** connection D. ^If the database connection D is not in | |
| 7253 | -** [WAL | write-ahead log mode] then this interface is a harmless no-op. | |
| 7254 | -** ^The [sqlite3_wal_checkpoint(D,X)] interface initiates a | |
| 7255 | -** [sqlite3_wal_checkpoint_v2|PASSIVE] checkpoint. | |
| 7256 | -** Use the [sqlite3_wal_checkpoint_v2()] interface to get a FULL | |
| 7257 | -** or RESET checkpoint. | |
| 7258 | -** | |
| 7259 | -** ^The [wal_checkpoint pragma] can be used to invoke this interface | |
| 7260 | -** from SQL. ^The [sqlite3_wal_autocheckpoint()] interface and the | |
| 7261 | -** [wal_autocheckpoint pragma] can be used to cause this interface to be | |
| 7262 | -** run whenever the WAL reaches a certain size threshold. | |
| 7263 | -** | |
| 7264 | -** See also: [sqlite3_wal_checkpoint_v2()] | |
| 7268 | +** ^(The sqlite3_wal_checkpoint(D,X) is equivalent to | |
| 7269 | +** [sqlite3_wal_checkpoint_v2](D,X,[SQLITE_CHECKPOINT_PASSIVE],0,0).)^ | |
| 7270 | +** | |
| 7271 | +** In brief, sqlite3_wal_checkpoint(D,X) causes the content in the | |
| 7272 | +** [write-ahead log] for database X on [database connection] D to be | |
| 7273 | +** transferred into the database file and for the write-ahead log to | |
| 7274 | +** be reset. See the [checkpointing] documentation for addition | |
| 7275 | +** information. | |
| 7276 | +** | |
| 7277 | +** This interface used to be the only way to cause a checkpoint to | |
| 7278 | +** occur. But then the newer and more powerful [sqlite3_wal_checkpoint_v2()] | |
| 7279 | +** interface was added. This interface is retained for backwards | |
| 7280 | +** compatibility and as a convenience for applications that need to manually | |
| 7281 | +** start a callback but which do not need the full power (and corresponding | |
| 7282 | +** complication) of [sqlite3_wal_checkpoint_v2()]. | |
| 7265 | 7283 | */ |
| 7266 | 7284 | SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb); |
| 7267 | 7285 | |
| 7268 | 7286 | /* |
| 7269 | 7287 | ** CAPI3REF: Checkpoint a database |
| 7270 | 7288 | ** |
| 7271 | -** Run a checkpoint operation on WAL database zDb attached to database | |
| 7272 | -** handle db. The specific operation is determined by the value of the | |
| 7273 | -** eMode parameter: | |
| 7289 | +** ^(The sqlite3_wal_checkpoint_v2(D,X,M,L,C) interface runs a checkpoint | |
| 7290 | +** operation on database X of [database connection] D in mode M. Status | |
| 7291 | +** information is written back into integers pointed to by L and C.)^ | |
| 7292 | +** ^(The M parameter must be a valid [checkpoint mode]:)^ | |
| 7274 | 7293 | ** |
| 7275 | 7294 | ** <dl> |
| 7276 | 7295 | ** <dt>SQLITE_CHECKPOINT_PASSIVE<dd> |
| 7277 | -** Checkpoint as many frames as possible without waiting for any database | |
| 7278 | -** readers or writers to finish. Sync the db file if all frames in the log | |
| 7279 | -** are checkpointed. This mode is the same as calling | |
| 7280 | -** sqlite3_wal_checkpoint(). The [sqlite3_busy_handler|busy-handler callback] | |
| 7281 | -** is never invoked. | |
| 7296 | +** ^Checkpoint as many frames as possible without waiting for any database | |
| 7297 | +** readers or writers to finish, then sync the database file if all frames | |
| 7298 | +** in the log were checkpointed. ^The [busy-handler callback] | |
| 7299 | +** is never invoked in the SQLITE_CHECKPOINT_PASSIVE mode. | |
| 7300 | +** ^On the other hand, passive mode might leave the checkpoint unfinished | |
| 7301 | +** if there are concurrent readers or writers. | |
| 7282 | 7302 | ** |
| 7283 | 7303 | ** <dt>SQLITE_CHECKPOINT_FULL<dd> |
| 7284 | -** This mode blocks (it invokes the | |
| 7304 | +** ^This mode blocks (it invokes the | |
| 7285 | 7305 | ** [sqlite3_busy_handler|busy-handler callback]) until there is no |
| 7286 | 7306 | ** database writer and all readers are reading from the most recent database |
| 7287 | -** snapshot. It then checkpoints all frames in the log file and syncs the | |
| 7288 | -** database file. This call blocks database writers while it is running, | |
| 7289 | -** but not database readers. | |
| 7307 | +** snapshot. ^It then checkpoints all frames in the log file and syncs the | |
| 7308 | +** database file. ^This mode blocks new database writers while it is pending, | |
| 7309 | +** but new database readers are allowed to continue unimpeded. | |
| 7290 | 7310 | ** |
| 7291 | 7311 | ** <dt>SQLITE_CHECKPOINT_RESTART<dd> |
| 7292 | -** This mode works the same way as SQLITE_CHECKPOINT_FULL, except after | |
| 7293 | -** checkpointing the log file it blocks (calls the | |
| 7294 | -** [sqlite3_busy_handler|busy-handler callback]) | |
| 7295 | -** until all readers are reading from the database file only. This ensures | |
| 7296 | -** that the next client to write to the database file restarts the log file | |
| 7297 | -** from the beginning. This call blocks database writers while it is running, | |
| 7298 | -** but not database readers. | |
| 7312 | +** ^This mode works the same way as SQLITE_CHECKPOINT_FULL with the addition | |
| 7313 | +** that after checkpointing the log file it blocks (calls the | |
| 7314 | +** [busy-handler callback]) | |
| 7315 | +** until all readers are reading from the database file only. ^This ensures | |
| 7316 | +** that the next writer will restart the log file from the beginning. | |
| 7317 | +** ^Like SQLITE_CHECKPOINT_FULL, this mode blocks new | |
| 7318 | +** database writer attempts while it is pending, but does not impede readers. | |
| 7319 | +** | |
| 7320 | +** <dt>SQLITE_CHECKPOINT_TRUNCATE<dd> | |
| 7321 | +** ^This mode works the same way as SQLITE_CHECKPOINT_RESTART with the | |
| 7322 | +** addition that it also truncates the log file to zero bytes just prior | |
| 7323 | +** to a successful return. | |
| 7299 | 7324 | ** </dl> |
| 7300 | 7325 | ** |
| 7301 | -** If pnLog is not NULL, then *pnLog is set to the total number of frames in | |
| 7302 | -** the log file before returning. If pnCkpt is not NULL, then *pnCkpt is set to | |
| 7303 | -** the total number of checkpointed frames (including any that were already | |
| 7304 | -** checkpointed when this function is called). *pnLog and *pnCkpt may be | |
| 7305 | -** populated even if sqlite3_wal_checkpoint_v2() returns other than SQLITE_OK. | |
| 7306 | -** If no values are available because of an error, they are both set to -1 | |
| 7307 | -** before returning to communicate this to the caller. | |
| 7326 | +** ^If pnLog is not NULL, then *pnLog is set to the total number of frames in | |
| 7327 | +** the log file or to -1 if the checkpoint could not run because | |
| 7328 | +** of an error or because the database is not in [WAL mode]. ^If pnCkpt is not | |
| 7329 | +** NULL,then *pnCkpt is set to the total number of checkpointed frames in the | |
| 7330 | +** log file (including any that were already checkpointed before the function | |
| 7331 | +** was called) or to -1 if the checkpoint could not run due to an error or | |
| 7332 | +** because the database is not in WAL mode. ^Note that upon successful | |
| 7333 | +** completion of an SQLITE_CHECKPOINT_TRUNCATE, the log file will have been | |
| 7334 | +** truncated to zero bytes and so both *pnLog and *pnCkpt will be set to zero. | |
| 7308 | 7335 | ** |
| 7309 | -** All calls obtain an exclusive "checkpoint" lock on the database file. If | |
| 7336 | +** ^All calls obtain an exclusive "checkpoint" lock on the database file. ^If | |
| 7310 | 7337 | ** any other process is running a checkpoint operation at the same time, the |
| 7311 | -** lock cannot be obtained and SQLITE_BUSY is returned. Even if there is a | |
| 7338 | +** lock cannot be obtained and SQLITE_BUSY is returned. ^Even if there is a | |
| 7312 | 7339 | ** busy-handler configured, it will not be invoked in this case. |
| 7313 | 7340 | ** |
| 7314 | -** The SQLITE_CHECKPOINT_FULL and RESTART modes also obtain the exclusive | |
| 7315 | -** "writer" lock on the database file. If the writer lock cannot be obtained | |
| 7316 | -** immediately, and a busy-handler is configured, it is invoked and the writer | |
| 7317 | -** lock retried until either the busy-handler returns 0 or the lock is | |
| 7318 | -** successfully obtained. The busy-handler is also invoked while waiting for | |
| 7319 | -** database readers as described above. If the busy-handler returns 0 before | |
| 7341 | +** ^The SQLITE_CHECKPOINT_FULL, RESTART and TRUNCATE modes also obtain the | |
| 7342 | +** exclusive "writer" lock on the database file. ^If the writer lock cannot be | |
| 7343 | +** obtained immediately, and a busy-handler is configured, it is invoked and | |
| 7344 | +** the writer lock retried until either the busy-handler returns 0 or the lock | |
| 7345 | +** is successfully obtained. ^The busy-handler is also invoked while waiting for | |
| 7346 | +** database readers as described above. ^If the busy-handler returns 0 before | |
| 7320 | 7347 | ** the writer lock is obtained or while waiting for database readers, the |
| 7321 | 7348 | ** checkpoint operation proceeds from that point in the same way as |
| 7322 | 7349 | ** SQLITE_CHECKPOINT_PASSIVE - checkpointing as many frames as possible |
| 7323 | -** without blocking any further. SQLITE_BUSY is returned in this case. | |
| 7350 | +** without blocking any further. ^SQLITE_BUSY is returned in this case. | |
| 7324 | 7351 | ** |
| 7325 | -** If parameter zDb is NULL or points to a zero length string, then the | |
| 7326 | -** specified operation is attempted on all WAL databases. In this case the | |
| 7327 | -** values written to output parameters *pnLog and *pnCkpt are undefined. If | |
| 7352 | +** ^If parameter zDb is NULL or points to a zero length string, then the | |
| 7353 | +** specified operation is attempted on all WAL databases [attached] to | |
| 7354 | +** [database connection] db. In this case the | |
| 7355 | +** values written to output parameters *pnLog and *pnCkpt are undefined. ^If | |
| 7328 | 7356 | ** an SQLITE_BUSY error is encountered when processing one or more of the |
| 7329 | 7357 | ** attached WAL databases, the operation is still attempted on any remaining |
| 7330 | -** attached databases and SQLITE_BUSY is returned to the caller. If any other | |
| 7358 | +** attached databases and SQLITE_BUSY is returned at the end. ^If any other | |
| 7331 | 7359 | ** error occurs while processing an attached database, processing is abandoned |
| 7332 | -** and the error code returned to the caller immediately. If no error | |
| 7360 | +** and the error code is returned to the caller immediately. ^If no error | |
| 7333 | 7361 | ** (SQLITE_BUSY or otherwise) is encountered while processing the attached |
| 7334 | 7362 | ** databases, SQLITE_OK is returned. |
| 7335 | 7363 | ** |
| 7336 | -** If database zDb is the name of an attached database that is not in WAL | |
| 7337 | -** mode, SQLITE_OK is returned and both *pnLog and *pnCkpt set to -1. If | |
| 7364 | +** ^If database zDb is the name of an attached database that is not in WAL | |
| 7365 | +** mode, SQLITE_OK is returned and both *pnLog and *pnCkpt set to -1. ^If | |
| 7338 | 7366 | ** zDb is not NULL (or a zero length string) and is not the name of any |
| 7339 | 7367 | ** attached database, SQLITE_ERROR is returned to the caller. |
| 7368 | +** | |
| 7369 | +** ^Unless it returns SQLITE_MISUSE, | |
| 7370 | +** the sqlite3_wal_checkpoint_v2() interface | |
| 7371 | +** sets the error information that is queried by | |
| 7372 | +** [sqlite3_errcode()] and [sqlite3_errmsg()]. | |
| 7373 | +** | |
| 7374 | +** ^The [PRAGMA wal_checkpoint] command can be used to invoke this interface | |
| 7375 | +** from SQL. | |
| 7340 | 7376 | */ |
| 7341 | 7377 | SQLITE_API int sqlite3_wal_checkpoint_v2( |
| 7342 | 7378 | sqlite3 *db, /* Database handle */ |
| 7343 | 7379 | const char *zDb, /* Name of attached database (or NULL) */ |
| 7344 | 7380 | int eMode, /* SQLITE_CHECKPOINT_* value */ |
| @@ -7345,20 +7381,22 @@ | ||
| 7345 | 7381 | int *pnLog, /* OUT: Size of WAL log in frames */ |
| 7346 | 7382 | int *pnCkpt /* OUT: Total number of frames checkpointed */ |
| 7347 | 7383 | ); |
| 7348 | 7384 | |
| 7349 | 7385 | /* |
| 7350 | -** CAPI3REF: Checkpoint operation parameters | |
| 7386 | +** CAPI3REF: Checkpoint Mode Values | |
| 7387 | +** KEYWORDS: {checkpoint mode} | |
| 7351 | 7388 | ** |
| 7352 | -** These constants can be used as the 3rd parameter to | |
| 7353 | -** [sqlite3_wal_checkpoint_v2()]. See the [sqlite3_wal_checkpoint_v2()] | |
| 7354 | -** documentation for additional information about the meaning and use of | |
| 7355 | -** each of these values. | |
| 7389 | +** These constants define all valid values for the "checkpoint mode" passed | |
| 7390 | +** as the third parameter to the [sqlite3_wal_checkpoint_v2()] interface. | |
| 7391 | +** See the [sqlite3_wal_checkpoint_v2()] documentation for details on the | |
| 7392 | +** meaning of each of these checkpoint modes. | |
| 7356 | 7393 | */ |
| 7357 | -#define SQLITE_CHECKPOINT_PASSIVE 0 | |
| 7358 | -#define SQLITE_CHECKPOINT_FULL 1 | |
| 7359 | -#define SQLITE_CHECKPOINT_RESTART 2 | |
| 7394 | +#define SQLITE_CHECKPOINT_PASSIVE 0 /* Do as much as possible w/o blocking */ | |
| 7395 | +#define SQLITE_CHECKPOINT_FULL 1 /* Wait for writers, then checkpoint */ | |
| 7396 | +#define SQLITE_CHECKPOINT_RESTART 2 /* Like FULL but wait for for readers */ | |
| 7397 | +#define SQLITE_CHECKPOINT_TRUNCATE 3 /* Like RESTART but also truncate WAL */ | |
| 7360 | 7398 | |
| 7361 | 7399 | /* |
| 7362 | 7400 | ** CAPI3REF: Virtual Table Interface Configuration |
| 7363 | 7401 | ** |
| 7364 | 7402 | ** This function may be called by either the [xConnect] or [xCreate] method |
| @@ -7453,16 +7491,16 @@ | ||
| 7453 | 7491 | ** [sqlite3_stmt_scanstatus(S,X,T,V)] interface. Each constant designates a |
| 7454 | 7492 | ** different metric for sqlite3_stmt_scanstatus() to return. |
| 7455 | 7493 | ** |
| 7456 | 7494 | ** <dl> |
| 7457 | 7495 | ** [[SQLITE_SCANSTAT_NLOOP]] <dt>SQLITE_SCANSTAT_NLOOP</dt> |
| 7458 | -** <dd>^The [sqlite3_int64] variable pointed to by the T parameter will be set to the | |
| 7459 | -** total number of times that the X-th loop has run.</dd> | |
| 7496 | +** <dd>^The [sqlite3_int64] variable pointed to by the T parameter will be | |
| 7497 | +** set to the total number of times that the X-th loop has run.</dd> | |
| 7460 | 7498 | ** |
| 7461 | 7499 | ** [[SQLITE_SCANSTAT_NVISIT]] <dt>SQLITE_SCANSTAT_NVISIT</dt> |
| 7462 | -** <dd>^The [sqlite3_int64] variable pointed to by the T parameter will be set to the | |
| 7463 | -** total number of rows examined by all iterations of the X-th loop.</dd> | |
| 7500 | +** <dd>^The [sqlite3_int64] variable pointed to by the T parameter will be set | |
| 7501 | +** to the total number of rows examined by all iterations of the X-th loop.</dd> | |
| 7464 | 7502 | ** |
| 7465 | 7503 | ** [[SQLITE_SCANSTAT_EST]] <dt>SQLITE_SCANSTAT_EST</dt> |
| 7466 | 7504 | ** <dd>^The "double" variable pointed to by the T parameter will be set to the |
| 7467 | 7505 | ** query planner's estimate for the average number of rows output from each |
| 7468 | 7506 | ** iteration of the X-th loop. If the query planner's estimates was accurate, |
| @@ -7469,18 +7507,18 @@ | ||
| 7469 | 7507 | ** then this value will approximate the quotient NVISIT/NLOOP and the |
| 7470 | 7508 | ** product of this value for all prior loops with the same SELECTID will |
| 7471 | 7509 | ** be the NLOOP value for the current loop. |
| 7472 | 7510 | ** |
| 7473 | 7511 | ** [[SQLITE_SCANSTAT_NAME]] <dt>SQLITE_SCANSTAT_NAME</dt> |
| 7474 | -** <dd>^The "const char *" variable pointed to by the T parameter will be set to | |
| 7475 | -** a zero-terminated UTF-8 string containing the name of the index or table used | |
| 7476 | -** for the X-th loop. | |
| 7512 | +** <dd>^The "const char *" variable pointed to by the T parameter will be set | |
| 7513 | +** to a zero-terminated UTF-8 string containing the name of the index or table | |
| 7514 | +** used for the X-th loop. | |
| 7477 | 7515 | ** |
| 7478 | 7516 | ** [[SQLITE_SCANSTAT_EXPLAIN]] <dt>SQLITE_SCANSTAT_EXPLAIN</dt> |
| 7479 | -** <dd>^The "const char *" variable pointed to by the T parameter will be set to | |
| 7480 | -** a zero-terminated UTF-8 string containing the [EXPLAIN QUERY PLAN] description | |
| 7481 | -** for the X-th loop. | |
| 7517 | +** <dd>^The "const char *" variable pointed to by the T parameter will be set | |
| 7518 | +** to a zero-terminated UTF-8 string containing the [EXPLAIN QUERY PLAN] | |
| 7519 | +** description for the X-th loop. | |
| 7482 | 7520 | ** |
| 7483 | 7521 | ** [[SQLITE_SCANSTAT_SELECTID]] <dt>SQLITE_SCANSTAT_SELECT</dt> |
| 7484 | 7522 | ** <dd>^The "int" variable pointed to by the T parameter will be set to the |
| 7485 | 7523 | ** "select-id" for the X-th loop. The select-id identifies which query or |
| 7486 | 7524 | ** subquery the loop is part of. The main query has a select-id of zero. |
| @@ -7499,12 +7537,12 @@ | ||
| 7499 | 7537 | ** CAPI3REF: Prepared Statement Scan Status |
| 7500 | 7538 | ** |
| 7501 | 7539 | ** Return status data for a single loop within query pStmt. |
| 7502 | 7540 | ** |
| 7503 | 7541 | ** The "iScanStatusOp" parameter determines which status information to return. |
| 7504 | -** The "iScanStatusOp" must be one of the [scanstatus options] or the behavior of | |
| 7505 | -** this interface is undefined. | |
| 7542 | +** The "iScanStatusOp" must be one of the [scanstatus options] or the behavior | |
| 7543 | +** of this interface is undefined. | |
| 7506 | 7544 | ** ^The requested measurement is written into a variable pointed to by |
| 7507 | 7545 | ** the "pOut" parameter. |
| 7508 | 7546 | ** Parameter "idx" identifies the specific loop to retrieve statistics for. |
| 7509 | 7547 | ** Loops are numbered starting from zero. ^If idx is out of range - less than |
| 7510 | 7548 | ** zero or greater than or equal to the total number of loops used to implement |
| 7511 | 7549 |
| --- src/sqlite3.h | |
| +++ src/sqlite3.h | |
| @@ -107,11 +107,11 @@ | |
| 107 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 108 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 109 | */ |
| 110 | #define SQLITE_VERSION "3.8.8" |
| 111 | #define SQLITE_VERSION_NUMBER 3008008 |
| 112 | #define SQLITE_SOURCE_ID "2014-11-28 13:35:03 24fa2e9832daaa5d68ee28a00c56c55f97a4da9e" |
| 113 | |
| 114 | /* |
| 115 | ** CAPI3REF: Run-Time Library Version Numbers |
| 116 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 117 | ** |
| @@ -199,11 +199,11 @@ | |
| 199 | ** This interface only reports on the compile-time mutex setting |
| 200 | ** of the [SQLITE_THREADSAFE] flag. If SQLite is compiled with |
| 201 | ** SQLITE_THREADSAFE=1 or =2 then mutexes are enabled by default but |
| 202 | ** can be fully or partially disabled using a call to [sqlite3_config()] |
| 203 | ** with the verbs [SQLITE_CONFIG_SINGLETHREAD], [SQLITE_CONFIG_MULTITHREAD], |
| 204 | ** or [SQLITE_CONFIG_MUTEX]. ^(The return value of the |
| 205 | ** sqlite3_threadsafe() function shows only the compile-time setting of |
| 206 | ** thread safety, not any run-time changes to that setting made by |
| 207 | ** sqlite3_config(). In other words, the return value from sqlite3_threadsafe() |
| 208 | ** is unchanged by calls to sqlite3_config().)^ |
| 209 | ** |
| @@ -1219,11 +1219,11 @@ | |
| 1219 | ** <li> SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED |
| 1220 | ** <li> SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE |
| 1221 | ** </ul> |
| 1222 | ** |
| 1223 | ** When unlocking, the same SHARED or EXCLUSIVE flag must be supplied as |
| 1224 | ** was given no the corresponding lock. |
| 1225 | ** |
| 1226 | ** The xShmLock method can transition between unlocked and SHARED or |
| 1227 | ** between unlocked and EXCLUSIVE. It cannot transition between SHARED |
| 1228 | ** and EXCLUSIVE. |
| 1229 | */ |
| @@ -1522,12 +1522,12 @@ | |
| 1522 | ** tracks memory usage, for example. </dd> |
| 1523 | ** |
| 1524 | ** [[SQLITE_CONFIG_MEMSTATUS]] <dt>SQLITE_CONFIG_MEMSTATUS</dt> |
| 1525 | ** <dd> ^The SQLITE_CONFIG_MEMSTATUS option takes single argument of type int, |
| 1526 | ** interpreted as a boolean, which enables or disables the collection of |
| 1527 | ** memory allocation statistics. ^(When memory allocation statistics are disabled, the |
| 1528 | ** following SQLite interfaces become non-operational: |
| 1529 | ** <ul> |
| 1530 | ** <li> [sqlite3_memory_used()] |
| 1531 | ** <li> [sqlite3_memory_highwater()] |
| 1532 | ** <li> [sqlite3_soft_heap_limit64()] |
| 1533 | ** <li> [sqlite3_status()] |
| @@ -1564,14 +1564,15 @@ | |
| 1564 | ** that SQLite can use for the database page cache with the default page |
| 1565 | ** cache implementation. |
| 1566 | ** This configuration should not be used if an application-define page |
| 1567 | ** cache implementation is loaded using the [SQLITE_CONFIG_PCACHE2] |
| 1568 | ** configuration option. |
| 1569 | ** ^There are three arguments to SQLITE_CONFIG_PAGECACHE: A pointer to 8-byte aligned |
| 1570 | ** memory, the size of each page buffer (sz), and the number of pages (N). |
| 1571 | ** The sz argument should be the size of the largest database page |
| 1572 | ** (a power of two between 512 and 32768) plus some extra bytes for each |
| 1573 | ** page header. ^The number of extra bytes needed by the page header |
| 1574 | ** can be determined using the [SQLITE_CONFIG_PCACHE_HDRSZ] option |
| 1575 | ** to [sqlite3_config()]. |
| 1576 | ** ^It is harmless, apart from the wasted memory, |
| 1577 | ** for the sz parameter to be larger than necessary. The first |
| @@ -1584,11 +1585,12 @@ | |
| 1584 | ** SQLite goes to [sqlite3_malloc()] for the additional storage space.</dd> |
| 1585 | ** |
| 1586 | ** [[SQLITE_CONFIG_HEAP]] <dt>SQLITE_CONFIG_HEAP</dt> |
| 1587 | ** <dd> ^The SQLITE_CONFIG_HEAP option specifies a static memory buffer |
| 1588 | ** that SQLite will use for all of its dynamic memory allocation needs |
| 1589 | ** beyond those provided for by [SQLITE_CONFIG_SCRATCH] and [SQLITE_CONFIG_PAGECACHE]. |
| 1590 | ** ^The SQLITE_CONFIG_HEAP option is only available if SQLite is compiled |
| 1591 | ** with either [SQLITE_ENABLE_MEMSYS3] or [SQLITE_ENABLE_MEMSYS5] and returns |
| 1592 | ** [SQLITE_ERROR] if invoked otherwise. |
| 1593 | ** ^There are three arguments to SQLITE_CONFIG_HEAP: |
| 1594 | ** An 8-byte aligned pointer to the memory, |
| @@ -1604,13 +1606,13 @@ | |
| 1604 | ** for the minimum allocation size are 2**5 through 2**8.</dd> |
| 1605 | ** |
| 1606 | ** [[SQLITE_CONFIG_MUTEX]] <dt>SQLITE_CONFIG_MUTEX</dt> |
| 1607 | ** <dd> ^(The SQLITE_CONFIG_MUTEX option takes a single argument which is a |
| 1608 | ** pointer to an instance of the [sqlite3_mutex_methods] structure. |
| 1609 | ** The argument specifies alternative low-level mutex routines to be used in place |
| 1610 | ** the mutex routines built into SQLite.)^ ^SQLite makes a copy of the |
| 1611 | ** content of the [sqlite3_mutex_methods] structure before the call to |
| 1612 | ** [sqlite3_config()] returns. ^If SQLite is compiled with |
| 1613 | ** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then |
| 1614 | ** the entire mutexing subsystem is omitted from the build and hence calls to |
| 1615 | ** [sqlite3_config()] with the SQLITE_CONFIG_MUTEX configuration option will |
| 1616 | ** return [SQLITE_ERROR].</dd> |
| @@ -1644,12 +1646,12 @@ | |
| 1644 | ** the interface to a custom page cache implementation.)^ |
| 1645 | ** ^SQLite makes a copy of the [sqlite3_pcache_methods2] object.</dd> |
| 1646 | ** |
| 1647 | ** [[SQLITE_CONFIG_GETPCACHE2]] <dt>SQLITE_CONFIG_GETPCACHE2</dt> |
| 1648 | ** <dd> ^(The SQLITE_CONFIG_GETPCACHE2 option takes a single argument which |
| 1649 | ** is a pointer to an [sqlite3_pcache_methods2] object. SQLite copies of the current |
| 1650 | ** page cache implementation into that object.)^ </dd> |
| 1651 | ** |
| 1652 | ** [[SQLITE_CONFIG_LOG]] <dt>SQLITE_CONFIG_LOG</dt> |
| 1653 | ** <dd> The SQLITE_CONFIG_LOG option is used to configure the SQLite |
| 1654 | ** global [error log]. |
| 1655 | ** (^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a |
| @@ -1670,12 +1672,13 @@ | |
| 1670 | ** function must be threadsafe. </dd> |
| 1671 | ** |
| 1672 | ** [[SQLITE_CONFIG_URI]] <dt>SQLITE_CONFIG_URI |
| 1673 | ** <dd>^(The SQLITE_CONFIG_URI option takes a single argument of type int. |
| 1674 | ** If non-zero, then URI handling is globally enabled. If the parameter is zero, |
| 1675 | ** then URI handling is globally disabled.)^ ^If URI handling is globally enabled, |
| 1676 | ** all filenames passed to [sqlite3_open()], [sqlite3_open_v2()], [sqlite3_open16()] or |
| 1677 | ** specified as part of [ATTACH] commands are interpreted as URIs, regardless |
| 1678 | ** of whether or not the [SQLITE_OPEN_URI] flag is set when the database |
| 1679 | ** connection is opened. ^If it is globally disabled, filenames are |
| 1680 | ** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the |
| 1681 | ** database connection is opened. ^(By default, URI handling is globally |
| @@ -1733,22 +1736,33 @@ | |
| 1733 | ** changed to its compile-time default. |
| 1734 | ** |
| 1735 | ** [[SQLITE_CONFIG_WIN32_HEAPSIZE]] |
| 1736 | ** <dt>SQLITE_CONFIG_WIN32_HEAPSIZE |
| 1737 | ** <dd>^The SQLITE_CONFIG_WIN32_HEAPSIZE option is only available if SQLite is |
| 1738 | ** compiled for Windows with the [SQLITE_WIN32_MALLOC] pre-processor macro defined. |
| 1739 | ** ^SQLITE_CONFIG_WIN32_HEAPSIZE takes a 32-bit unsigned integer value |
| 1740 | ** that specifies the maximum size of the created heap. |
| 1741 | ** </dl> |
| 1742 | ** |
| 1743 | ** [[SQLITE_CONFIG_PCACHE_HDRSZ]] |
| 1744 | ** <dt>SQLITE_CONFIG_PCACHE_HDRSZ |
| 1745 | ** <dd>^The SQLITE_CONFIG_PCACHE_HDRSZ option takes a single parameter which |
| 1746 | ** is a pointer to an integer and writes into that integer the number of extra |
| 1747 | ** bytes per page required for each page in [SQLITE_CONFIG_PAGECACHE]. The amount of |
| 1748 | ** extra space required can change depending on the compiler, |
| 1749 | ** target platform, and SQLite version. |
| 1750 | ** </dl> |
| 1751 | */ |
| 1752 | #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ |
| 1753 | #define SQLITE_CONFIG_MULTITHREAD 2 /* nil */ |
| 1754 | #define SQLITE_CONFIG_SERIALIZED 3 /* nil */ |
| @@ -1771,10 +1785,11 @@ | |
| 1771 | #define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */ |
| 1772 | #define SQLITE_CONFIG_SQLLOG 21 /* xSqllog, void* */ |
| 1773 | #define SQLITE_CONFIG_MMAP_SIZE 22 /* sqlite3_int64, sqlite3_int64 */ |
| 1774 | #define SQLITE_CONFIG_WIN32_HEAPSIZE 23 /* int nByte */ |
| 1775 | #define SQLITE_CONFIG_PCACHE_HDRSZ 24 /* int *psz */ |
| 1776 | |
| 1777 | /* |
| 1778 | ** CAPI3REF: Database Connection Configuration Options |
| 1779 | ** |
| 1780 | ** These constants are the available integer configuration options that |
| @@ -2047,10 +2062,11 @@ | |
| 2047 | SQLITE_API int sqlite3_complete(const char *sql); |
| 2048 | SQLITE_API int sqlite3_complete16(const void *sql); |
| 2049 | |
| 2050 | /* |
| 2051 | ** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors |
| 2052 | ** |
| 2053 | ** ^The sqlite3_busy_handler(D,X,P) routine sets a callback function X |
| 2054 | ** that might be invoked with argument P whenever |
| 2055 | ** an attempt is made to access a database table associated with |
| 2056 | ** [database connection] D when another thread |
| @@ -2063,11 +2079,11 @@ | |
| 2063 | ** is not NULL, then the callback might be invoked with two arguments. |
| 2064 | ** |
| 2065 | ** ^The first argument to the busy handler is a copy of the void* pointer which |
| 2066 | ** is the third argument to sqlite3_busy_handler(). ^The second argument to |
| 2067 | ** the busy handler callback is the number of times that the busy handler has |
| 2068 | ** been invoked for the same locking event. ^If the |
| 2069 | ** busy callback returns 0, then no additional attempts are made to |
| 2070 | ** access the database and [SQLITE_BUSY] is returned |
| 2071 | ** to the application. |
| 2072 | ** ^If the callback returns non-zero, then another attempt |
| 2073 | ** is made to access the database and the cycle repeats. |
| @@ -4518,11 +4534,12 @@ | |
| 4518 | ** If these routines are called from within the different thread |
| 4519 | ** than the one containing the application-defined function that received |
| 4520 | ** the [sqlite3_context] pointer, the results are undefined. |
| 4521 | */ |
| 4522 | SQLITE_API void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); |
| 4523 | SQLITE_API void sqlite3_result_blob64(sqlite3_context*,const void*,sqlite3_uint64,void(*)(void*)); |
| 4524 | SQLITE_API void sqlite3_result_double(sqlite3_context*, double); |
| 4525 | SQLITE_API void sqlite3_result_error(sqlite3_context*, const char*, int); |
| 4526 | SQLITE_API void sqlite3_result_error16(sqlite3_context*, const void*, int); |
| 4527 | SQLITE_API void sqlite3_result_error_toobig(sqlite3_context*); |
| 4528 | SQLITE_API void sqlite3_result_error_nomem(sqlite3_context*); |
| @@ -5150,24 +5167,31 @@ | |
| 5150 | |
| 5151 | |
| 5152 | /* |
| 5153 | ** CAPI3REF: Extract Metadata About A Column Of A Table |
| 5154 | ** |
| 5155 | ** ^This routine returns metadata about a specific column of a specific |
| 5156 | ** database table accessible using the [database connection] handle |
| 5157 | ** passed as the first function argument. |
| 5158 | ** |
| 5159 | ** ^The column is identified by the second, third and fourth parameters to |
| 5160 | ** this function. ^The second parameter is either the name of the database |
| 5161 | ** (i.e. "main", "temp", or an attached database) containing the specified |
| 5162 | ** table or NULL. ^If it is NULL, then all attached databases are searched |
| 5163 | ** for the table using the same algorithm used by the database engine to |
| 5164 | ** resolve unqualified table references. |
| 5165 | ** |
| 5166 | ** ^The third and fourth parameters to this function are the table and column |
| 5167 | ** name of the desired column, respectively. Neither of these parameters |
| 5168 | ** may be NULL. |
| 5169 | ** |
| 5170 | ** ^Metadata is returned by writing to the memory locations passed as the 5th |
| 5171 | ** and subsequent parameters to this function. ^Any of these arguments may be |
| 5172 | ** NULL, in which case the corresponding element of metadata is omitted. |
| 5173 | ** |
| @@ -5182,36 +5206,33 @@ | |
| 5182 | ** <tr><td> 9th <td> int <td> True if column is [AUTOINCREMENT] |
| 5183 | ** </table> |
| 5184 | ** </blockquote>)^ |
| 5185 | ** |
| 5186 | ** ^The memory pointed to by the character pointers returned for the |
| 5187 | ** declaration type and collation sequence is valid only until the next |
| 5188 | ** call to any SQLite API function. |
| 5189 | ** |
| 5190 | ** ^If the specified table is actually a view, an [error code] is returned. |
| 5191 | ** |
| 5192 | ** ^If the specified column is "rowid", "oid" or "_rowid_" and an |
| 5193 | ** [INTEGER PRIMARY KEY] column has been explicitly declared, then the output |
| 5194 | ** parameters are set for the explicitly declared column. ^(If there is no |
| 5195 | ** explicitly declared [INTEGER PRIMARY KEY] column, then the output |
| 5196 | ** parameters are set as follows: |
| 5197 | ** |
| 5198 | ** <pre> |
| 5199 | ** data type: "INTEGER" |
| 5200 | ** collation sequence: "BINARY" |
| 5201 | ** not null: 0 |
| 5202 | ** primary key: 1 |
| 5203 | ** auto increment: 0 |
| 5204 | ** </pre>)^ |
| 5205 | ** |
| 5206 | ** ^(This function may load one or more schemas from database files. If an |
| 5207 | ** error occurs during this process, or if the requested table or column |
| 5208 | ** cannot be found, an [error code] is returned and an error message left |
| 5209 | ** in the [database connection] (to be retrieved using sqlite3_errmsg()).)^ |
| 5210 | ** |
| 5211 | ** ^This API is only available if the library was compiled with the |
| 5212 | ** [SQLITE_ENABLE_COLUMN_METADATA] C-preprocessor symbol defined. |
| 5213 | */ |
| 5214 | SQLITE_API int sqlite3_table_column_metadata( |
| 5215 | sqlite3 *db, /* Connection handle */ |
| 5216 | const char *zDbName, /* Database name or NULL */ |
| 5217 | const char *zTableName, /* Table name */ |
| @@ -7174,16 +7195,14 @@ | |
| 7174 | |
| 7175 | /* |
| 7176 | ** CAPI3REF: Write-Ahead Log Commit Hook |
| 7177 | ** |
| 7178 | ** ^The [sqlite3_wal_hook()] function is used to register a callback that |
| 7179 | ** will be invoked each time a database connection commits data to a |
| 7180 | ** [write-ahead log] (i.e. whenever a transaction is committed in |
| 7181 | ** [journal_mode | journal_mode=WAL mode]). |
| 7182 | ** |
| 7183 | ** ^The callback is invoked by SQLite after the commit has taken place and |
| 7184 | ** the associated write-lock on the database released, so the implementation |
| 7185 | ** may read, write or [checkpoint] the database as required. |
| 7186 | ** |
| 7187 | ** ^The first parameter passed to the callback function when it is invoked |
| 7188 | ** is a copy of the third parameter passed to sqlite3_wal_hook() when |
| 7189 | ** registering the callback. ^The second is a copy of the database handle. |
| @@ -7244,101 +7263,118 @@ | |
| 7244 | SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N); |
| 7245 | |
| 7246 | /* |
| 7247 | ** CAPI3REF: Checkpoint a database |
| 7248 | ** |
| 7249 | ** ^The [sqlite3_wal_checkpoint(D,X)] interface causes database named X |
| 7250 | ** on [database connection] D to be [checkpointed]. ^If X is NULL or an |
| 7251 | ** empty string, then a checkpoint is run on all databases of |
| 7252 | ** connection D. ^If the database connection D is not in |
| 7253 | ** [WAL | write-ahead log mode] then this interface is a harmless no-op. |
| 7254 | ** ^The [sqlite3_wal_checkpoint(D,X)] interface initiates a |
| 7255 | ** [sqlite3_wal_checkpoint_v2|PASSIVE] checkpoint. |
| 7256 | ** Use the [sqlite3_wal_checkpoint_v2()] interface to get a FULL |
| 7257 | ** or RESET checkpoint. |
| 7258 | ** |
| 7259 | ** ^The [wal_checkpoint pragma] can be used to invoke this interface |
| 7260 | ** from SQL. ^The [sqlite3_wal_autocheckpoint()] interface and the |
| 7261 | ** [wal_autocheckpoint pragma] can be used to cause this interface to be |
| 7262 | ** run whenever the WAL reaches a certain size threshold. |
| 7263 | ** |
| 7264 | ** See also: [sqlite3_wal_checkpoint_v2()] |
| 7265 | */ |
| 7266 | SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb); |
| 7267 | |
| 7268 | /* |
| 7269 | ** CAPI3REF: Checkpoint a database |
| 7270 | ** |
| 7271 | ** Run a checkpoint operation on WAL database zDb attached to database |
| 7272 | ** handle db. The specific operation is determined by the value of the |
| 7273 | ** eMode parameter: |
| 7274 | ** |
| 7275 | ** <dl> |
| 7276 | ** <dt>SQLITE_CHECKPOINT_PASSIVE<dd> |
| 7277 | ** Checkpoint as many frames as possible without waiting for any database |
| 7278 | ** readers or writers to finish. Sync the db file if all frames in the log |
| 7279 | ** are checkpointed. This mode is the same as calling |
| 7280 | ** sqlite3_wal_checkpoint(). The [sqlite3_busy_handler|busy-handler callback] |
| 7281 | ** is never invoked. |
| 7282 | ** |
| 7283 | ** <dt>SQLITE_CHECKPOINT_FULL<dd> |
| 7284 | ** This mode blocks (it invokes the |
| 7285 | ** [sqlite3_busy_handler|busy-handler callback]) until there is no |
| 7286 | ** database writer and all readers are reading from the most recent database |
| 7287 | ** snapshot. It then checkpoints all frames in the log file and syncs the |
| 7288 | ** database file. This call blocks database writers while it is running, |
| 7289 | ** but not database readers. |
| 7290 | ** |
| 7291 | ** <dt>SQLITE_CHECKPOINT_RESTART<dd> |
| 7292 | ** This mode works the same way as SQLITE_CHECKPOINT_FULL, except after |
| 7293 | ** checkpointing the log file it blocks (calls the |
| 7294 | ** [sqlite3_busy_handler|busy-handler callback]) |
| 7295 | ** until all readers are reading from the database file only. This ensures |
| 7296 | ** that the next client to write to the database file restarts the log file |
| 7297 | ** from the beginning. This call blocks database writers while it is running, |
| 7298 | ** but not database readers. |
| 7299 | ** </dl> |
| 7300 | ** |
| 7301 | ** If pnLog is not NULL, then *pnLog is set to the total number of frames in |
| 7302 | ** the log file before returning. If pnCkpt is not NULL, then *pnCkpt is set to |
| 7303 | ** the total number of checkpointed frames (including any that were already |
| 7304 | ** checkpointed when this function is called). *pnLog and *pnCkpt may be |
| 7305 | ** populated even if sqlite3_wal_checkpoint_v2() returns other than SQLITE_OK. |
| 7306 | ** If no values are available because of an error, they are both set to -1 |
| 7307 | ** before returning to communicate this to the caller. |
| 7308 | ** |
| 7309 | ** All calls obtain an exclusive "checkpoint" lock on the database file. If |
| 7310 | ** any other process is running a checkpoint operation at the same time, the |
| 7311 | ** lock cannot be obtained and SQLITE_BUSY is returned. Even if there is a |
| 7312 | ** busy-handler configured, it will not be invoked in this case. |
| 7313 | ** |
| 7314 | ** The SQLITE_CHECKPOINT_FULL and RESTART modes also obtain the exclusive |
| 7315 | ** "writer" lock on the database file. If the writer lock cannot be obtained |
| 7316 | ** immediately, and a busy-handler is configured, it is invoked and the writer |
| 7317 | ** lock retried until either the busy-handler returns 0 or the lock is |
| 7318 | ** successfully obtained. The busy-handler is also invoked while waiting for |
| 7319 | ** database readers as described above. If the busy-handler returns 0 before |
| 7320 | ** the writer lock is obtained or while waiting for database readers, the |
| 7321 | ** checkpoint operation proceeds from that point in the same way as |
| 7322 | ** SQLITE_CHECKPOINT_PASSIVE - checkpointing as many frames as possible |
| 7323 | ** without blocking any further. SQLITE_BUSY is returned in this case. |
| 7324 | ** |
| 7325 | ** If parameter zDb is NULL or points to a zero length string, then the |
| 7326 | ** specified operation is attempted on all WAL databases. In this case the |
| 7327 | ** values written to output parameters *pnLog and *pnCkpt are undefined. If |
| 7328 | ** an SQLITE_BUSY error is encountered when processing one or more of the |
| 7329 | ** attached WAL databases, the operation is still attempted on any remaining |
| 7330 | ** attached databases and SQLITE_BUSY is returned to the caller. If any other |
| 7331 | ** error occurs while processing an attached database, processing is abandoned |
| 7332 | ** and the error code returned to the caller immediately. If no error |
| 7333 | ** (SQLITE_BUSY or otherwise) is encountered while processing the attached |
| 7334 | ** databases, SQLITE_OK is returned. |
| 7335 | ** |
| 7336 | ** If database zDb is the name of an attached database that is not in WAL |
| 7337 | ** mode, SQLITE_OK is returned and both *pnLog and *pnCkpt set to -1. If |
| 7338 | ** zDb is not NULL (or a zero length string) and is not the name of any |
| 7339 | ** attached database, SQLITE_ERROR is returned to the caller. |
| 7340 | */ |
| 7341 | SQLITE_API int sqlite3_wal_checkpoint_v2( |
| 7342 | sqlite3 *db, /* Database handle */ |
| 7343 | const char *zDb, /* Name of attached database (or NULL) */ |
| 7344 | int eMode, /* SQLITE_CHECKPOINT_* value */ |
| @@ -7345,20 +7381,22 @@ | |
| 7345 | int *pnLog, /* OUT: Size of WAL log in frames */ |
| 7346 | int *pnCkpt /* OUT: Total number of frames checkpointed */ |
| 7347 | ); |
| 7348 | |
| 7349 | /* |
| 7350 | ** CAPI3REF: Checkpoint operation parameters |
| 7351 | ** |
| 7352 | ** These constants can be used as the 3rd parameter to |
| 7353 | ** [sqlite3_wal_checkpoint_v2()]. See the [sqlite3_wal_checkpoint_v2()] |
| 7354 | ** documentation for additional information about the meaning and use of |
| 7355 | ** each of these values. |
| 7356 | */ |
| 7357 | #define SQLITE_CHECKPOINT_PASSIVE 0 |
| 7358 | #define SQLITE_CHECKPOINT_FULL 1 |
| 7359 | #define SQLITE_CHECKPOINT_RESTART 2 |
| 7360 | |
| 7361 | /* |
| 7362 | ** CAPI3REF: Virtual Table Interface Configuration |
| 7363 | ** |
| 7364 | ** This function may be called by either the [xConnect] or [xCreate] method |
| @@ -7453,16 +7491,16 @@ | |
| 7453 | ** [sqlite3_stmt_scanstatus(S,X,T,V)] interface. Each constant designates a |
| 7454 | ** different metric for sqlite3_stmt_scanstatus() to return. |
| 7455 | ** |
| 7456 | ** <dl> |
| 7457 | ** [[SQLITE_SCANSTAT_NLOOP]] <dt>SQLITE_SCANSTAT_NLOOP</dt> |
| 7458 | ** <dd>^The [sqlite3_int64] variable pointed to by the T parameter will be set to the |
| 7459 | ** total number of times that the X-th loop has run.</dd> |
| 7460 | ** |
| 7461 | ** [[SQLITE_SCANSTAT_NVISIT]] <dt>SQLITE_SCANSTAT_NVISIT</dt> |
| 7462 | ** <dd>^The [sqlite3_int64] variable pointed to by the T parameter will be set to the |
| 7463 | ** total number of rows examined by all iterations of the X-th loop.</dd> |
| 7464 | ** |
| 7465 | ** [[SQLITE_SCANSTAT_EST]] <dt>SQLITE_SCANSTAT_EST</dt> |
| 7466 | ** <dd>^The "double" variable pointed to by the T parameter will be set to the |
| 7467 | ** query planner's estimate for the average number of rows output from each |
| 7468 | ** iteration of the X-th loop. If the query planner's estimates was accurate, |
| @@ -7469,18 +7507,18 @@ | |
| 7469 | ** then this value will approximate the quotient NVISIT/NLOOP and the |
| 7470 | ** product of this value for all prior loops with the same SELECTID will |
| 7471 | ** be the NLOOP value for the current loop. |
| 7472 | ** |
| 7473 | ** [[SQLITE_SCANSTAT_NAME]] <dt>SQLITE_SCANSTAT_NAME</dt> |
| 7474 | ** <dd>^The "const char *" variable pointed to by the T parameter will be set to |
| 7475 | ** a zero-terminated UTF-8 string containing the name of the index or table used |
| 7476 | ** for the X-th loop. |
| 7477 | ** |
| 7478 | ** [[SQLITE_SCANSTAT_EXPLAIN]] <dt>SQLITE_SCANSTAT_EXPLAIN</dt> |
| 7479 | ** <dd>^The "const char *" variable pointed to by the T parameter will be set to |
| 7480 | ** a zero-terminated UTF-8 string containing the [EXPLAIN QUERY PLAN] description |
| 7481 | ** for the X-th loop. |
| 7482 | ** |
| 7483 | ** [[SQLITE_SCANSTAT_SELECTID]] <dt>SQLITE_SCANSTAT_SELECT</dt> |
| 7484 | ** <dd>^The "int" variable pointed to by the T parameter will be set to the |
| 7485 | ** "select-id" for the X-th loop. The select-id identifies which query or |
| 7486 | ** subquery the loop is part of. The main query has a select-id of zero. |
| @@ -7499,12 +7537,12 @@ | |
| 7499 | ** CAPI3REF: Prepared Statement Scan Status |
| 7500 | ** |
| 7501 | ** Return status data for a single loop within query pStmt. |
| 7502 | ** |
| 7503 | ** The "iScanStatusOp" parameter determines which status information to return. |
| 7504 | ** The "iScanStatusOp" must be one of the [scanstatus options] or the behavior of |
| 7505 | ** this interface is undefined. |
| 7506 | ** ^The requested measurement is written into a variable pointed to by |
| 7507 | ** the "pOut" parameter. |
| 7508 | ** Parameter "idx" identifies the specific loop to retrieve statistics for. |
| 7509 | ** Loops are numbered starting from zero. ^If idx is out of range - less than |
| 7510 | ** zero or greater than or equal to the total number of loops used to implement |
| 7511 |
| --- src/sqlite3.h | |
| +++ src/sqlite3.h | |
| @@ -107,11 +107,11 @@ | |
| 107 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 108 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 109 | */ |
| 110 | #define SQLITE_VERSION "3.8.8" |
| 111 | #define SQLITE_VERSION_NUMBER 3008008 |
| 112 | #define SQLITE_SOURCE_ID "2015-01-03 18:59:17 23d4c07eb81db5a5c6beb56b5820f0b6501f1fb6" |
| 113 | |
| 114 | /* |
| 115 | ** CAPI3REF: Run-Time Library Version Numbers |
| 116 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 117 | ** |
| @@ -199,11 +199,11 @@ | |
| 199 | ** This interface only reports on the compile-time mutex setting |
| 200 | ** of the [SQLITE_THREADSAFE] flag. If SQLite is compiled with |
| 201 | ** SQLITE_THREADSAFE=1 or =2 then mutexes are enabled by default but |
| 202 | ** can be fully or partially disabled using a call to [sqlite3_config()] |
| 203 | ** with the verbs [SQLITE_CONFIG_SINGLETHREAD], [SQLITE_CONFIG_MULTITHREAD], |
| 204 | ** or [SQLITE_CONFIG_SERIALIZED]. ^(The return value of the |
| 205 | ** sqlite3_threadsafe() function shows only the compile-time setting of |
| 206 | ** thread safety, not any run-time changes to that setting made by |
| 207 | ** sqlite3_config(). In other words, the return value from sqlite3_threadsafe() |
| 208 | ** is unchanged by calls to sqlite3_config().)^ |
| 209 | ** |
| @@ -1219,11 +1219,11 @@ | |
| 1219 | ** <li> SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED |
| 1220 | ** <li> SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE |
| 1221 | ** </ul> |
| 1222 | ** |
| 1223 | ** When unlocking, the same SHARED or EXCLUSIVE flag must be supplied as |
| 1224 | ** was given on the corresponding lock. |
| 1225 | ** |
| 1226 | ** The xShmLock method can transition between unlocked and SHARED or |
| 1227 | ** between unlocked and EXCLUSIVE. It cannot transition between SHARED |
| 1228 | ** and EXCLUSIVE. |
| 1229 | */ |
| @@ -1522,12 +1522,12 @@ | |
| 1522 | ** tracks memory usage, for example. </dd> |
| 1523 | ** |
| 1524 | ** [[SQLITE_CONFIG_MEMSTATUS]] <dt>SQLITE_CONFIG_MEMSTATUS</dt> |
| 1525 | ** <dd> ^The SQLITE_CONFIG_MEMSTATUS option takes single argument of type int, |
| 1526 | ** interpreted as a boolean, which enables or disables the collection of |
| 1527 | ** memory allocation statistics. ^(When memory allocation statistics are |
| 1528 | ** disabled, the following SQLite interfaces become non-operational: |
| 1529 | ** <ul> |
| 1530 | ** <li> [sqlite3_memory_used()] |
| 1531 | ** <li> [sqlite3_memory_highwater()] |
| 1532 | ** <li> [sqlite3_soft_heap_limit64()] |
| 1533 | ** <li> [sqlite3_status()] |
| @@ -1564,14 +1564,15 @@ | |
| 1564 | ** that SQLite can use for the database page cache with the default page |
| 1565 | ** cache implementation. |
| 1566 | ** This configuration should not be used if an application-define page |
| 1567 | ** cache implementation is loaded using the [SQLITE_CONFIG_PCACHE2] |
| 1568 | ** configuration option. |
| 1569 | ** ^There are three arguments to SQLITE_CONFIG_PAGECACHE: A pointer to |
| 1570 | ** 8-byte aligned |
| 1571 | ** memory, the size of each page buffer (sz), and the number of pages (N). |
| 1572 | ** The sz argument should be the size of the largest database page |
| 1573 | ** (a power of two between 512 and 65536) plus some extra bytes for each |
| 1574 | ** page header. ^The number of extra bytes needed by the page header |
| 1575 | ** can be determined using the [SQLITE_CONFIG_PCACHE_HDRSZ] option |
| 1576 | ** to [sqlite3_config()]. |
| 1577 | ** ^It is harmless, apart from the wasted memory, |
| 1578 | ** for the sz parameter to be larger than necessary. The first |
| @@ -1584,11 +1585,12 @@ | |
| 1585 | ** SQLite goes to [sqlite3_malloc()] for the additional storage space.</dd> |
| 1586 | ** |
| 1587 | ** [[SQLITE_CONFIG_HEAP]] <dt>SQLITE_CONFIG_HEAP</dt> |
| 1588 | ** <dd> ^The SQLITE_CONFIG_HEAP option specifies a static memory buffer |
| 1589 | ** that SQLite will use for all of its dynamic memory allocation needs |
| 1590 | ** beyond those provided for by [SQLITE_CONFIG_SCRATCH] and |
| 1591 | ** [SQLITE_CONFIG_PAGECACHE]. |
| 1592 | ** ^The SQLITE_CONFIG_HEAP option is only available if SQLite is compiled |
| 1593 | ** with either [SQLITE_ENABLE_MEMSYS3] or [SQLITE_ENABLE_MEMSYS5] and returns |
| 1594 | ** [SQLITE_ERROR] if invoked otherwise. |
| 1595 | ** ^There are three arguments to SQLITE_CONFIG_HEAP: |
| 1596 | ** An 8-byte aligned pointer to the memory, |
| @@ -1604,13 +1606,13 @@ | |
| 1606 | ** for the minimum allocation size are 2**5 through 2**8.</dd> |
| 1607 | ** |
| 1608 | ** [[SQLITE_CONFIG_MUTEX]] <dt>SQLITE_CONFIG_MUTEX</dt> |
| 1609 | ** <dd> ^(The SQLITE_CONFIG_MUTEX option takes a single argument which is a |
| 1610 | ** pointer to an instance of the [sqlite3_mutex_methods] structure. |
| 1611 | ** The argument specifies alternative low-level mutex routines to be used |
| 1612 | ** in place the mutex routines built into SQLite.)^ ^SQLite makes a copy of |
| 1613 | ** the content of the [sqlite3_mutex_methods] structure before the call to |
| 1614 | ** [sqlite3_config()] returns. ^If SQLite is compiled with |
| 1615 | ** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then |
| 1616 | ** the entire mutexing subsystem is omitted from the build and hence calls to |
| 1617 | ** [sqlite3_config()] with the SQLITE_CONFIG_MUTEX configuration option will |
| 1618 | ** return [SQLITE_ERROR].</dd> |
| @@ -1644,12 +1646,12 @@ | |
| 1646 | ** the interface to a custom page cache implementation.)^ |
| 1647 | ** ^SQLite makes a copy of the [sqlite3_pcache_methods2] object.</dd> |
| 1648 | ** |
| 1649 | ** [[SQLITE_CONFIG_GETPCACHE2]] <dt>SQLITE_CONFIG_GETPCACHE2</dt> |
| 1650 | ** <dd> ^(The SQLITE_CONFIG_GETPCACHE2 option takes a single argument which |
| 1651 | ** is a pointer to an [sqlite3_pcache_methods2] object. SQLite copies of |
| 1652 | ** the current page cache implementation into that object.)^ </dd> |
| 1653 | ** |
| 1654 | ** [[SQLITE_CONFIG_LOG]] <dt>SQLITE_CONFIG_LOG</dt> |
| 1655 | ** <dd> The SQLITE_CONFIG_LOG option is used to configure the SQLite |
| 1656 | ** global [error log]. |
| 1657 | ** (^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a |
| @@ -1670,12 +1672,13 @@ | |
| 1672 | ** function must be threadsafe. </dd> |
| 1673 | ** |
| 1674 | ** [[SQLITE_CONFIG_URI]] <dt>SQLITE_CONFIG_URI |
| 1675 | ** <dd>^(The SQLITE_CONFIG_URI option takes a single argument of type int. |
| 1676 | ** If non-zero, then URI handling is globally enabled. If the parameter is zero, |
| 1677 | ** then URI handling is globally disabled.)^ ^If URI handling is globally |
| 1678 | ** enabled, all filenames passed to [sqlite3_open()], [sqlite3_open_v2()], |
| 1679 | ** [sqlite3_open16()] or |
| 1680 | ** specified as part of [ATTACH] commands are interpreted as URIs, regardless |
| 1681 | ** of whether or not the [SQLITE_OPEN_URI] flag is set when the database |
| 1682 | ** connection is opened. ^If it is globally disabled, filenames are |
| 1683 | ** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the |
| 1684 | ** database connection is opened. ^(By default, URI handling is globally |
| @@ -1733,22 +1736,33 @@ | |
| 1736 | ** changed to its compile-time default. |
| 1737 | ** |
| 1738 | ** [[SQLITE_CONFIG_WIN32_HEAPSIZE]] |
| 1739 | ** <dt>SQLITE_CONFIG_WIN32_HEAPSIZE |
| 1740 | ** <dd>^The SQLITE_CONFIG_WIN32_HEAPSIZE option is only available if SQLite is |
| 1741 | ** compiled for Windows with the [SQLITE_WIN32_MALLOC] pre-processor macro |
| 1742 | ** defined. ^SQLITE_CONFIG_WIN32_HEAPSIZE takes a 32-bit unsigned integer value |
| 1743 | ** that specifies the maximum size of the created heap. |
| 1744 | ** </dl> |
| 1745 | ** |
| 1746 | ** [[SQLITE_CONFIG_PCACHE_HDRSZ]] |
| 1747 | ** <dt>SQLITE_CONFIG_PCACHE_HDRSZ |
| 1748 | ** <dd>^The SQLITE_CONFIG_PCACHE_HDRSZ option takes a single parameter which |
| 1749 | ** is a pointer to an integer and writes into that integer the number of extra |
| 1750 | ** bytes per page required for each page in [SQLITE_CONFIG_PAGECACHE]. |
| 1751 | ** The amount of extra space required can change depending on the compiler, |
| 1752 | ** target platform, and SQLite version. |
| 1753 | ** |
| 1754 | ** [[SQLITE_CONFIG_PMASZ]] |
| 1755 | ** <dt>SQLITE_CONFIG_PMASZ |
| 1756 | ** <dd>^The SQLITE_CONFIG_PMASZ option takes a single parameter which |
| 1757 | ** is an unsigned integer and sets the "Minimum PMA Size" for the multithreaded |
| 1758 | ** sorter to that integer. The default minimum PMA Size is set by the |
| 1759 | ** [SQLITE_SORTER_PMASZ] compile-time option. New threads are launched |
| 1760 | ** to help with sort operations when multithreaded sorting |
| 1761 | ** is enabled (using the [PRAGMA threads] command) and the amount of content |
| 1762 | ** to be sorted exceeds the page size times the minimum of the |
| 1763 | ** [PRAGMA cache_size] setting and this value. |
| 1764 | ** </dl> |
| 1765 | */ |
| 1766 | #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ |
| 1767 | #define SQLITE_CONFIG_MULTITHREAD 2 /* nil */ |
| 1768 | #define SQLITE_CONFIG_SERIALIZED 3 /* nil */ |
| @@ -1771,10 +1785,11 @@ | |
| 1785 | #define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */ |
| 1786 | #define SQLITE_CONFIG_SQLLOG 21 /* xSqllog, void* */ |
| 1787 | #define SQLITE_CONFIG_MMAP_SIZE 22 /* sqlite3_int64, sqlite3_int64 */ |
| 1788 | #define SQLITE_CONFIG_WIN32_HEAPSIZE 23 /* int nByte */ |
| 1789 | #define SQLITE_CONFIG_PCACHE_HDRSZ 24 /* int *psz */ |
| 1790 | #define SQLITE_CONFIG_PMASZ 25 /* unsigned int szPma */ |
| 1791 | |
| 1792 | /* |
| 1793 | ** CAPI3REF: Database Connection Configuration Options |
| 1794 | ** |
| 1795 | ** These constants are the available integer configuration options that |
| @@ -2047,10 +2062,11 @@ | |
| 2062 | SQLITE_API int sqlite3_complete(const char *sql); |
| 2063 | SQLITE_API int sqlite3_complete16(const void *sql); |
| 2064 | |
| 2065 | /* |
| 2066 | ** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors |
| 2067 | ** KEYWORDS: {busy-handler callback} {busy handler} |
| 2068 | ** |
| 2069 | ** ^The sqlite3_busy_handler(D,X,P) routine sets a callback function X |
| 2070 | ** that might be invoked with argument P whenever |
| 2071 | ** an attempt is made to access a database table associated with |
| 2072 | ** [database connection] D when another thread |
| @@ -2063,11 +2079,11 @@ | |
| 2079 | ** is not NULL, then the callback might be invoked with two arguments. |
| 2080 | ** |
| 2081 | ** ^The first argument to the busy handler is a copy of the void* pointer which |
| 2082 | ** is the third argument to sqlite3_busy_handler(). ^The second argument to |
| 2083 | ** the busy handler callback is the number of times that the busy handler has |
| 2084 | ** been invoked previously for the same locking event. ^If the |
| 2085 | ** busy callback returns 0, then no additional attempts are made to |
| 2086 | ** access the database and [SQLITE_BUSY] is returned |
| 2087 | ** to the application. |
| 2088 | ** ^If the callback returns non-zero, then another attempt |
| 2089 | ** is made to access the database and the cycle repeats. |
| @@ -4518,11 +4534,12 @@ | |
| 4534 | ** If these routines are called from within the different thread |
| 4535 | ** than the one containing the application-defined function that received |
| 4536 | ** the [sqlite3_context] pointer, the results are undefined. |
| 4537 | */ |
| 4538 | SQLITE_API void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); |
| 4539 | SQLITE_API void sqlite3_result_blob64(sqlite3_context*,const void*, |
| 4540 | sqlite3_uint64,void(*)(void*)); |
| 4541 | SQLITE_API void sqlite3_result_double(sqlite3_context*, double); |
| 4542 | SQLITE_API void sqlite3_result_error(sqlite3_context*, const char*, int); |
| 4543 | SQLITE_API void sqlite3_result_error16(sqlite3_context*, const void*, int); |
| 4544 | SQLITE_API void sqlite3_result_error_toobig(sqlite3_context*); |
| 4545 | SQLITE_API void sqlite3_result_error_nomem(sqlite3_context*); |
| @@ -5150,24 +5167,31 @@ | |
| 5167 | |
| 5168 | |
| 5169 | /* |
| 5170 | ** CAPI3REF: Extract Metadata About A Column Of A Table |
| 5171 | ** |
| 5172 | ** ^(The sqlite3_table_column_metadata(X,D,T,C,....) routine returns |
| 5173 | ** information about column C of table T in database D |
| 5174 | ** on [database connection] X.)^ ^The sqlite3_table_column_metadata() |
| 5175 | ** interface returns SQLITE_OK and fills in the non-NULL pointers in |
| 5176 | ** the final five arguments with appropriate values if the specified |
| 5177 | ** column exists. ^The sqlite3_table_column_metadata() interface returns |
| 5178 | ** SQLITE_ERROR and if the specified column does not exist. |
| 5179 | ** ^If the column-name parameter to sqlite3_table_column_metadata() is a |
| 5180 | ** NULL pointer, then this routine simply checks for the existance of the |
| 5181 | ** table and returns SQLITE_OK if the table exists and SQLITE_ERROR if it |
| 5182 | ** does not. |
| 5183 | ** |
| 5184 | ** ^The column is identified by the second, third and fourth parameters to |
| 5185 | ** this function. ^(The second parameter is either the name of the database |
| 5186 | ** (i.e. "main", "temp", or an attached database) containing the specified |
| 5187 | ** table or NULL.)^ ^If it is NULL, then all attached databases are searched |
| 5188 | ** for the table using the same algorithm used by the database engine to |
| 5189 | ** resolve unqualified table references. |
| 5190 | ** |
| 5191 | ** ^The third and fourth parameters to this function are the table and column |
| 5192 | ** name of the desired column, respectively. |
| 5193 | ** |
| 5194 | ** ^Metadata is returned by writing to the memory locations passed as the 5th |
| 5195 | ** and subsequent parameters to this function. ^Any of these arguments may be |
| 5196 | ** NULL, in which case the corresponding element of metadata is omitted. |
| 5197 | ** |
| @@ -5182,36 +5206,33 @@ | |
| 5206 | ** <tr><td> 9th <td> int <td> True if column is [AUTOINCREMENT] |
| 5207 | ** </table> |
| 5208 | ** </blockquote>)^ |
| 5209 | ** |
| 5210 | ** ^The memory pointed to by the character pointers returned for the |
| 5211 | ** declaration type and collation sequence is valid until the next |
| 5212 | ** call to any SQLite API function. |
| 5213 | ** |
| 5214 | ** ^If the specified table is actually a view, an [error code] is returned. |
| 5215 | ** |
| 5216 | ** ^If the specified column is "rowid", "oid" or "_rowid_" and the table |
| 5217 | ** is not a [WITHOUT ROWID] table and an |
| 5218 | ** [INTEGER PRIMARY KEY] column has been explicitly declared, then the output |
| 5219 | ** parameters are set for the explicitly declared column. ^(If there is no |
| 5220 | ** [INTEGER PRIMARY KEY] column, then the outputs |
| 5221 | ** for the [rowid] are set as follows: |
| 5222 | ** |
| 5223 | ** <pre> |
| 5224 | ** data type: "INTEGER" |
| 5225 | ** collation sequence: "BINARY" |
| 5226 | ** not null: 0 |
| 5227 | ** primary key: 1 |
| 5228 | ** auto increment: 0 |
| 5229 | ** </pre>)^ |
| 5230 | ** |
| 5231 | ** ^This function causes all database schemas to be read from disk and |
| 5232 | ** parsed, if that has not already been done, and returns an error if |
| 5233 | ** any errors are encountered while loading the schema. |
| 5234 | */ |
| 5235 | SQLITE_API int sqlite3_table_column_metadata( |
| 5236 | sqlite3 *db, /* Connection handle */ |
| 5237 | const char *zDbName, /* Database name or NULL */ |
| 5238 | const char *zTableName, /* Table name */ |
| @@ -7174,16 +7195,14 @@ | |
| 7195 | |
| 7196 | /* |
| 7197 | ** CAPI3REF: Write-Ahead Log Commit Hook |
| 7198 | ** |
| 7199 | ** ^The [sqlite3_wal_hook()] function is used to register a callback that |
| 7200 | ** is invoked each time data is committed to a database in wal mode. |
| 7201 | ** |
| 7202 | ** ^(The callback is invoked by SQLite after the commit has taken place and |
| 7203 | ** the associated write-lock on the database released)^, so the implementation |
| 7204 | ** may read, write or [checkpoint] the database as required. |
| 7205 | ** |
| 7206 | ** ^The first parameter passed to the callback function when it is invoked |
| 7207 | ** is a copy of the third parameter passed to sqlite3_wal_hook() when |
| 7208 | ** registering the callback. ^The second is a copy of the database handle. |
| @@ -7244,101 +7263,118 @@ | |
| 7263 | SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N); |
| 7264 | |
| 7265 | /* |
| 7266 | ** CAPI3REF: Checkpoint a database |
| 7267 | ** |
| 7268 | ** ^(The sqlite3_wal_checkpoint(D,X) is equivalent to |
| 7269 | ** [sqlite3_wal_checkpoint_v2](D,X,[SQLITE_CHECKPOINT_PASSIVE],0,0).)^ |
| 7270 | ** |
| 7271 | ** In brief, sqlite3_wal_checkpoint(D,X) causes the content in the |
| 7272 | ** [write-ahead log] for database X on [database connection] D to be |
| 7273 | ** transferred into the database file and for the write-ahead log to |
| 7274 | ** be reset. See the [checkpointing] documentation for addition |
| 7275 | ** information. |
| 7276 | ** |
| 7277 | ** This interface used to be the only way to cause a checkpoint to |
| 7278 | ** occur. But then the newer and more powerful [sqlite3_wal_checkpoint_v2()] |
| 7279 | ** interface was added. This interface is retained for backwards |
| 7280 | ** compatibility and as a convenience for applications that need to manually |
| 7281 | ** start a callback but which do not need the full power (and corresponding |
| 7282 | ** complication) of [sqlite3_wal_checkpoint_v2()]. |
| 7283 | */ |
| 7284 | SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb); |
| 7285 | |
| 7286 | /* |
| 7287 | ** CAPI3REF: Checkpoint a database |
| 7288 | ** |
| 7289 | ** ^(The sqlite3_wal_checkpoint_v2(D,X,M,L,C) interface runs a checkpoint |
| 7290 | ** operation on database X of [database connection] D in mode M. Status |
| 7291 | ** information is written back into integers pointed to by L and C.)^ |
| 7292 | ** ^(The M parameter must be a valid [checkpoint mode]:)^ |
| 7293 | ** |
| 7294 | ** <dl> |
| 7295 | ** <dt>SQLITE_CHECKPOINT_PASSIVE<dd> |
| 7296 | ** ^Checkpoint as many frames as possible without waiting for any database |
| 7297 | ** readers or writers to finish, then sync the database file if all frames |
| 7298 | ** in the log were checkpointed. ^The [busy-handler callback] |
| 7299 | ** is never invoked in the SQLITE_CHECKPOINT_PASSIVE mode. |
| 7300 | ** ^On the other hand, passive mode might leave the checkpoint unfinished |
| 7301 | ** if there are concurrent readers or writers. |
| 7302 | ** |
| 7303 | ** <dt>SQLITE_CHECKPOINT_FULL<dd> |
| 7304 | ** ^This mode blocks (it invokes the |
| 7305 | ** [sqlite3_busy_handler|busy-handler callback]) until there is no |
| 7306 | ** database writer and all readers are reading from the most recent database |
| 7307 | ** snapshot. ^It then checkpoints all frames in the log file and syncs the |
| 7308 | ** database file. ^This mode blocks new database writers while it is pending, |
| 7309 | ** but new database readers are allowed to continue unimpeded. |
| 7310 | ** |
| 7311 | ** <dt>SQLITE_CHECKPOINT_RESTART<dd> |
| 7312 | ** ^This mode works the same way as SQLITE_CHECKPOINT_FULL with the addition |
| 7313 | ** that after checkpointing the log file it blocks (calls the |
| 7314 | ** [busy-handler callback]) |
| 7315 | ** until all readers are reading from the database file only. ^This ensures |
| 7316 | ** that the next writer will restart the log file from the beginning. |
| 7317 | ** ^Like SQLITE_CHECKPOINT_FULL, this mode blocks new |
| 7318 | ** database writer attempts while it is pending, but does not impede readers. |
| 7319 | ** |
| 7320 | ** <dt>SQLITE_CHECKPOINT_TRUNCATE<dd> |
| 7321 | ** ^This mode works the same way as SQLITE_CHECKPOINT_RESTART with the |
| 7322 | ** addition that it also truncates the log file to zero bytes just prior |
| 7323 | ** to a successful return. |
| 7324 | ** </dl> |
| 7325 | ** |
| 7326 | ** ^If pnLog is not NULL, then *pnLog is set to the total number of frames in |
| 7327 | ** the log file or to -1 if the checkpoint could not run because |
| 7328 | ** of an error or because the database is not in [WAL mode]. ^If pnCkpt is not |
| 7329 | ** NULL,then *pnCkpt is set to the total number of checkpointed frames in the |
| 7330 | ** log file (including any that were already checkpointed before the function |
| 7331 | ** was called) or to -1 if the checkpoint could not run due to an error or |
| 7332 | ** because the database is not in WAL mode. ^Note that upon successful |
| 7333 | ** completion of an SQLITE_CHECKPOINT_TRUNCATE, the log file will have been |
| 7334 | ** truncated to zero bytes and so both *pnLog and *pnCkpt will be set to zero. |
| 7335 | ** |
| 7336 | ** ^All calls obtain an exclusive "checkpoint" lock on the database file. ^If |
| 7337 | ** any other process is running a checkpoint operation at the same time, the |
| 7338 | ** lock cannot be obtained and SQLITE_BUSY is returned. ^Even if there is a |
| 7339 | ** busy-handler configured, it will not be invoked in this case. |
| 7340 | ** |
| 7341 | ** ^The SQLITE_CHECKPOINT_FULL, RESTART and TRUNCATE modes also obtain the |
| 7342 | ** exclusive "writer" lock on the database file. ^If the writer lock cannot be |
| 7343 | ** obtained immediately, and a busy-handler is configured, it is invoked and |
| 7344 | ** the writer lock retried until either the busy-handler returns 0 or the lock |
| 7345 | ** is successfully obtained. ^The busy-handler is also invoked while waiting for |
| 7346 | ** database readers as described above. ^If the busy-handler returns 0 before |
| 7347 | ** the writer lock is obtained or while waiting for database readers, the |
| 7348 | ** checkpoint operation proceeds from that point in the same way as |
| 7349 | ** SQLITE_CHECKPOINT_PASSIVE - checkpointing as many frames as possible |
| 7350 | ** without blocking any further. ^SQLITE_BUSY is returned in this case. |
| 7351 | ** |
| 7352 | ** ^If parameter zDb is NULL or points to a zero length string, then the |
| 7353 | ** specified operation is attempted on all WAL databases [attached] to |
| 7354 | ** [database connection] db. In this case the |
| 7355 | ** values written to output parameters *pnLog and *pnCkpt are undefined. ^If |
| 7356 | ** an SQLITE_BUSY error is encountered when processing one or more of the |
| 7357 | ** attached WAL databases, the operation is still attempted on any remaining |
| 7358 | ** attached databases and SQLITE_BUSY is returned at the end. ^If any other |
| 7359 | ** error occurs while processing an attached database, processing is abandoned |
| 7360 | ** and the error code is returned to the caller immediately. ^If no error |
| 7361 | ** (SQLITE_BUSY or otherwise) is encountered while processing the attached |
| 7362 | ** databases, SQLITE_OK is returned. |
| 7363 | ** |
| 7364 | ** ^If database zDb is the name of an attached database that is not in WAL |
| 7365 | ** mode, SQLITE_OK is returned and both *pnLog and *pnCkpt set to -1. ^If |
| 7366 | ** zDb is not NULL (or a zero length string) and is not the name of any |
| 7367 | ** attached database, SQLITE_ERROR is returned to the caller. |
| 7368 | ** |
| 7369 | ** ^Unless it returns SQLITE_MISUSE, |
| 7370 | ** the sqlite3_wal_checkpoint_v2() interface |
| 7371 | ** sets the error information that is queried by |
| 7372 | ** [sqlite3_errcode()] and [sqlite3_errmsg()]. |
| 7373 | ** |
| 7374 | ** ^The [PRAGMA wal_checkpoint] command can be used to invoke this interface |
| 7375 | ** from SQL. |
| 7376 | */ |
| 7377 | SQLITE_API int sqlite3_wal_checkpoint_v2( |
| 7378 | sqlite3 *db, /* Database handle */ |
| 7379 | const char *zDb, /* Name of attached database (or NULL) */ |
| 7380 | int eMode, /* SQLITE_CHECKPOINT_* value */ |
| @@ -7345,20 +7381,22 @@ | |
| 7381 | int *pnLog, /* OUT: Size of WAL log in frames */ |
| 7382 | int *pnCkpt /* OUT: Total number of frames checkpointed */ |
| 7383 | ); |
| 7384 | |
| 7385 | /* |
| 7386 | ** CAPI3REF: Checkpoint Mode Values |
| 7387 | ** KEYWORDS: {checkpoint mode} |
| 7388 | ** |
| 7389 | ** These constants define all valid values for the "checkpoint mode" passed |
| 7390 | ** as the third parameter to the [sqlite3_wal_checkpoint_v2()] interface. |
| 7391 | ** See the [sqlite3_wal_checkpoint_v2()] documentation for details on the |
| 7392 | ** meaning of each of these checkpoint modes. |
| 7393 | */ |
| 7394 | #define SQLITE_CHECKPOINT_PASSIVE 0 /* Do as much as possible w/o blocking */ |
| 7395 | #define SQLITE_CHECKPOINT_FULL 1 /* Wait for writers, then checkpoint */ |
| 7396 | #define SQLITE_CHECKPOINT_RESTART 2 /* Like FULL but wait for for readers */ |
| 7397 | #define SQLITE_CHECKPOINT_TRUNCATE 3 /* Like RESTART but also truncate WAL */ |
| 7398 | |
| 7399 | /* |
| 7400 | ** CAPI3REF: Virtual Table Interface Configuration |
| 7401 | ** |
| 7402 | ** This function may be called by either the [xConnect] or [xCreate] method |
| @@ -7453,16 +7491,16 @@ | |
| 7491 | ** [sqlite3_stmt_scanstatus(S,X,T,V)] interface. Each constant designates a |
| 7492 | ** different metric for sqlite3_stmt_scanstatus() to return. |
| 7493 | ** |
| 7494 | ** <dl> |
| 7495 | ** [[SQLITE_SCANSTAT_NLOOP]] <dt>SQLITE_SCANSTAT_NLOOP</dt> |
| 7496 | ** <dd>^The [sqlite3_int64] variable pointed to by the T parameter will be |
| 7497 | ** set to the total number of times that the X-th loop has run.</dd> |
| 7498 | ** |
| 7499 | ** [[SQLITE_SCANSTAT_NVISIT]] <dt>SQLITE_SCANSTAT_NVISIT</dt> |
| 7500 | ** <dd>^The [sqlite3_int64] variable pointed to by the T parameter will be set |
| 7501 | ** to the total number of rows examined by all iterations of the X-th loop.</dd> |
| 7502 | ** |
| 7503 | ** [[SQLITE_SCANSTAT_EST]] <dt>SQLITE_SCANSTAT_EST</dt> |
| 7504 | ** <dd>^The "double" variable pointed to by the T parameter will be set to the |
| 7505 | ** query planner's estimate for the average number of rows output from each |
| 7506 | ** iteration of the X-th loop. If the query planner's estimates was accurate, |
| @@ -7469,18 +7507,18 @@ | |
| 7507 | ** then this value will approximate the quotient NVISIT/NLOOP and the |
| 7508 | ** product of this value for all prior loops with the same SELECTID will |
| 7509 | ** be the NLOOP value for the current loop. |
| 7510 | ** |
| 7511 | ** [[SQLITE_SCANSTAT_NAME]] <dt>SQLITE_SCANSTAT_NAME</dt> |
| 7512 | ** <dd>^The "const char *" variable pointed to by the T parameter will be set |
| 7513 | ** to a zero-terminated UTF-8 string containing the name of the index or table |
| 7514 | ** used for the X-th loop. |
| 7515 | ** |
| 7516 | ** [[SQLITE_SCANSTAT_EXPLAIN]] <dt>SQLITE_SCANSTAT_EXPLAIN</dt> |
| 7517 | ** <dd>^The "const char *" variable pointed to by the T parameter will be set |
| 7518 | ** to a zero-terminated UTF-8 string containing the [EXPLAIN QUERY PLAN] |
| 7519 | ** description for the X-th loop. |
| 7520 | ** |
| 7521 | ** [[SQLITE_SCANSTAT_SELECTID]] <dt>SQLITE_SCANSTAT_SELECT</dt> |
| 7522 | ** <dd>^The "int" variable pointed to by the T parameter will be set to the |
| 7523 | ** "select-id" for the X-th loop. The select-id identifies which query or |
| 7524 | ** subquery the loop is part of. The main query has a select-id of zero. |
| @@ -7499,12 +7537,12 @@ | |
| 7537 | ** CAPI3REF: Prepared Statement Scan Status |
| 7538 | ** |
| 7539 | ** Return status data for a single loop within query pStmt. |
| 7540 | ** |
| 7541 | ** The "iScanStatusOp" parameter determines which status information to return. |
| 7542 | ** The "iScanStatusOp" must be one of the [scanstatus options] or the behavior |
| 7543 | ** of this interface is undefined. |
| 7544 | ** ^The requested measurement is written into a variable pointed to by |
| 7545 | ** the "pOut" parameter. |
| 7546 | ** Parameter "idx" identifies the specific loop to retrieve statistics for. |
| 7547 | ** Loops are numbered starting from zero. ^If idx is out of range - less than |
| 7548 | ** zero or greater than or equal to the total number of loops used to implement |
| 7549 |
+3
-3
| --- src/stat.c | ||
| +++ src/stat.c | ||
| @@ -77,11 +77,11 @@ | ||
| 77 | 77 | if( n>0 ){ |
| 78 | 78 | int a, b; |
| 79 | 79 | Stmt q; |
| 80 | 80 | @ <tr><th>Uncompressed Artifact Size:</th><td> |
| 81 | 81 | db_prepare(&q, "SELECT total(size), avg(size), max(size)" |
| 82 | - " FROM blob WHERE size>0"); | |
| 82 | + " FROM blob WHERE size>0 /*scan*/"); | |
| 83 | 83 | db_step(&q); |
| 84 | 84 | t = db_column_int64(&q, 0); |
| 85 | 85 | szAvg = db_column_int(&q, 1); |
| 86 | 86 | szMax = db_column_int(&q, 2); |
| 87 | 87 | db_finalize(&q); |
| @@ -226,19 +226,19 @@ | ||
| 226 | 226 | n = db_int(0, "SELECT count(*) FROM filename /*scan*/"); |
| 227 | 227 | fossil_print("%*s%d across all branches\n", colWidth, "files:", n); |
| 228 | 228 | n = db_int(0, "SELECT count(*) FROM tag /*scan*/" |
| 229 | 229 | " WHERE tagname GLOB 'wiki-*'"); |
| 230 | 230 | m = db_int(0, "SELECT COUNT(*) FROM event WHERE type='w'"); |
| 231 | - fossil_print("%*s%d (%d changes)\n", colWidth, "wikipages:", n, m); | |
| 231 | + fossil_print("%*s%d (%d changes)\n", colWidth, "wiki-pages:", n, m); | |
| 232 | 232 | n = db_int(0, "SELECT count(*) FROM tag /*scan*/" |
| 233 | 233 | " WHERE tagname GLOB 'tkt-*'"); |
| 234 | 234 | m = db_int(0, "SELECT COUNT(*) FROM event WHERE type='t'"); |
| 235 | 235 | fossil_print("%*s%d (%d changes)\n", colWidth, "tickets:", n, m); |
| 236 | 236 | n = db_int(0, "SELECT COUNT(*) FROM event WHERE type='e'"); |
| 237 | 237 | fossil_print("%*s%d\n", colWidth, "events:", n); |
| 238 | 238 | n = db_int(0, "SELECT COUNT(*) FROM event WHERE type='g'"); |
| 239 | - fossil_print("%*s%d\n", colWidth, "tagchanges:", n); | |
| 239 | + fossil_print("%*s%d\n", colWidth, "tag-changes:", n); | |
| 240 | 240 | z = db_text(0, "SELECT datetime(mtime) || ' - about ' ||" |
| 241 | 241 | " CAST(julianday('now') - mtime AS INTEGER)" |
| 242 | 242 | " || ' days ago' FROM event " |
| 243 | 243 | " ORDER BY mtime DESC LIMIT 1"); |
| 244 | 244 | fossil_print("%*s%s\n", colWidth, "latest-change:", z); |
| 245 | 245 |
| --- src/stat.c | |
| +++ src/stat.c | |
| @@ -77,11 +77,11 @@ | |
| 77 | if( n>0 ){ |
| 78 | int a, b; |
| 79 | Stmt q; |
| 80 | @ <tr><th>Uncompressed Artifact Size:</th><td> |
| 81 | db_prepare(&q, "SELECT total(size), avg(size), max(size)" |
| 82 | " FROM blob WHERE size>0"); |
| 83 | db_step(&q); |
| 84 | t = db_column_int64(&q, 0); |
| 85 | szAvg = db_column_int(&q, 1); |
| 86 | szMax = db_column_int(&q, 2); |
| 87 | db_finalize(&q); |
| @@ -226,19 +226,19 @@ | |
| 226 | n = db_int(0, "SELECT count(*) FROM filename /*scan*/"); |
| 227 | fossil_print("%*s%d across all branches\n", colWidth, "files:", n); |
| 228 | n = db_int(0, "SELECT count(*) FROM tag /*scan*/" |
| 229 | " WHERE tagname GLOB 'wiki-*'"); |
| 230 | m = db_int(0, "SELECT COUNT(*) FROM event WHERE type='w'"); |
| 231 | fossil_print("%*s%d (%d changes)\n", colWidth, "wikipages:", n, m); |
| 232 | n = db_int(0, "SELECT count(*) FROM tag /*scan*/" |
| 233 | " WHERE tagname GLOB 'tkt-*'"); |
| 234 | m = db_int(0, "SELECT COUNT(*) FROM event WHERE type='t'"); |
| 235 | fossil_print("%*s%d (%d changes)\n", colWidth, "tickets:", n, m); |
| 236 | n = db_int(0, "SELECT COUNT(*) FROM event WHERE type='e'"); |
| 237 | fossil_print("%*s%d\n", colWidth, "events:", n); |
| 238 | n = db_int(0, "SELECT COUNT(*) FROM event WHERE type='g'"); |
| 239 | fossil_print("%*s%d\n", colWidth, "tagchanges:", n); |
| 240 | z = db_text(0, "SELECT datetime(mtime) || ' - about ' ||" |
| 241 | " CAST(julianday('now') - mtime AS INTEGER)" |
| 242 | " || ' days ago' FROM event " |
| 243 | " ORDER BY mtime DESC LIMIT 1"); |
| 244 | fossil_print("%*s%s\n", colWidth, "latest-change:", z); |
| 245 |
| --- src/stat.c | |
| +++ src/stat.c | |
| @@ -77,11 +77,11 @@ | |
| 77 | if( n>0 ){ |
| 78 | int a, b; |
| 79 | Stmt q; |
| 80 | @ <tr><th>Uncompressed Artifact Size:</th><td> |
| 81 | db_prepare(&q, "SELECT total(size), avg(size), max(size)" |
| 82 | " FROM blob WHERE size>0 /*scan*/"); |
| 83 | db_step(&q); |
| 84 | t = db_column_int64(&q, 0); |
| 85 | szAvg = db_column_int(&q, 1); |
| 86 | szMax = db_column_int(&q, 2); |
| 87 | db_finalize(&q); |
| @@ -226,19 +226,19 @@ | |
| 226 | n = db_int(0, "SELECT count(*) FROM filename /*scan*/"); |
| 227 | fossil_print("%*s%d across all branches\n", colWidth, "files:", n); |
| 228 | n = db_int(0, "SELECT count(*) FROM tag /*scan*/" |
| 229 | " WHERE tagname GLOB 'wiki-*'"); |
| 230 | m = db_int(0, "SELECT COUNT(*) FROM event WHERE type='w'"); |
| 231 | fossil_print("%*s%d (%d changes)\n", colWidth, "wiki-pages:", n, m); |
| 232 | n = db_int(0, "SELECT count(*) FROM tag /*scan*/" |
| 233 | " WHERE tagname GLOB 'tkt-*'"); |
| 234 | m = db_int(0, "SELECT COUNT(*) FROM event WHERE type='t'"); |
| 235 | fossil_print("%*s%d (%d changes)\n", colWidth, "tickets:", n, m); |
| 236 | n = db_int(0, "SELECT COUNT(*) FROM event WHERE type='e'"); |
| 237 | fossil_print("%*s%d\n", colWidth, "events:", n); |
| 238 | n = db_int(0, "SELECT COUNT(*) FROM event WHERE type='g'"); |
| 239 | fossil_print("%*s%d\n", colWidth, "tag-changes:", n); |
| 240 | z = db_text(0, "SELECT datetime(mtime) || ' - about ' ||" |
| 241 | " CAST(julianday('now') - mtime AS INTEGER)" |
| 242 | " || ' days ago' FROM event " |
| 243 | " ORDER BY mtime DESC LIMIT 1"); |
| 244 | fossil_print("%*s%s\n", colWidth, "latest-change:", z); |
| 245 |
+79
-4
| --- src/style.c | ||
| +++ src/style.c | ||
| @@ -783,10 +783,15 @@ | ||
| 783 | 783 | { ".filetree", |
| 784 | 784 | "tree-view file browser", |
| 785 | 785 | @ margin: 1em 0; |
| 786 | 786 | @ line-height: 1.5; |
| 787 | 787 | }, |
| 788 | + { | |
| 789 | + ".filetree > ul", | |
| 790 | + "tree-view top-level list", | |
| 791 | + @ display: inline-block; | |
| 792 | + }, | |
| 788 | 793 | { ".filetree ul", |
| 789 | 794 | "tree-view lists", |
| 790 | 795 | @ margin: 0; |
| 791 | 796 | @ padding: 0; |
| 792 | 797 | @ list-style: none; |
| @@ -832,21 +837,37 @@ | ||
| 832 | 837 | }, |
| 833 | 838 | { ".filetree a", |
| 834 | 839 | "tree-view links", |
| 835 | 840 | @ position: relative; |
| 836 | 841 | @ z-index: 1; |
| 837 | - @ display: inline-block; | |
| 842 | + @ display: table-cell; | |
| 838 | 843 | @ min-height: 16px; |
| 839 | 844 | @ padding-left: 21px; |
| 840 | 845 | @ background-image: url(data:image/gif;base64,R0lGODlhEAAQAJEAAP\/\/\/yEhIf\/\/\/wAAACH5BAEHAAIALAAAAAAQABAAAAIvlIKpxqcfmgOUvoaqDSCxrEEfF14GqFXImJZsu73wepJzVMNxrtNTj3NATMKhpwAAOw==); |
| 841 | 846 | @ background-position: center left; |
| 842 | 847 | @ background-repeat: no-repeat; |
| 843 | 848 | }, |
| 844 | - { ".filetree .dir > a", | |
| 849 | + { "div.filetreeline", | |
| 850 | + "line of a file tree", | |
| 851 | + @ display: table; | |
| 852 | + @ width: 100%; | |
| 853 | + @ white-space: nowrap; | |
| 854 | + }, | |
| 855 | + { ".filetree .dir > div.filetreeline > a", | |
| 845 | 856 | "tree-view directory links", |
| 846 | 857 | @ background-image: url(data:image/gif;base64,R0lGODlhEAAQAJEAAP/WVCIiIv\/\/\/wAAACH5BAEHAAIALAAAAAAQABAAAAInlI9pwa3XYniCgQtkrAFfLXkiFo1jaXpo+jUs6b5Z/K4siDu5RPUFADs=); |
| 847 | 858 | }, |
| 859 | + { "div.filetreeage", | |
| 860 | + "Last change floating display on the right", | |
| 861 | + @ display: table-cell; | |
| 862 | + @ padding-left: 3em; | |
| 863 | + @ text-align: right; | |
| 864 | + }, | |
| 865 | + { "div.filetreeline:hover", | |
| 866 | + "Highlight the line of a file tree", | |
| 867 | + @ background-color: #eee; | |
| 868 | + }, | |
| 848 | 869 | { "table.login_out", |
| 849 | 870 | "table format for login/out label/input table", |
| 850 | 871 | @ text-align: left; |
| 851 | 872 | @ margin-right: 10px; |
| 852 | 873 | @ margin-left: 10px; |
| @@ -1211,17 +1232,71 @@ | ||
| 1211 | 1232 | @ color: black; |
| 1212 | 1233 | @ background-color: white; |
| 1213 | 1234 | }, |
| 1214 | 1235 | { "table.adminLogTable", |
| 1215 | 1236 | "Class for the /admin_log table", |
| 1216 | - @ text-align: left | |
| 1237 | + @ text-align: left; | |
| 1217 | 1238 | }, |
| 1218 | 1239 | { ".adminLogTable .adminTime", |
| 1219 | 1240 | "Class for the /admin_log table", |
| 1220 | - @ text-align: left | |
| 1241 | + @ text-align: left; | |
| 1242 | + @ vertical-align: top; | |
| 1243 | + @ white-space: nowrap; | |
| 1244 | + }, | |
| 1245 | + { ".fileage table", | |
| 1246 | + "The fileage table", | |
| 1247 | + @ border-spacing: 0; | |
| 1248 | + }, | |
| 1249 | + { ".fileage tr:hover", | |
| 1250 | + "Mouse-over effects for the file-age table", | |
| 1251 | + @ background-color: #eee; | |
| 1252 | + }, | |
| 1253 | + { ".fileage td", | |
| 1254 | + "fileage table cells", | |
| 1221 | 1255 | @ vertical-align: top; |
| 1256 | + @ text-align: left; | |
| 1257 | + @ border-top: 1px solid #ddd; | |
| 1258 | + @ padding-top: 3px; | |
| 1259 | + }, | |
| 1260 | + { ".fileage td:first-child", | |
| 1261 | + "fileage first column (the age)", | |
| 1222 | 1262 | @ white-space: nowrap; |
| 1263 | + }, | |
| 1264 | + { ".fileage td:nth-child(2)", | |
| 1265 | + "fileage second column (the filename)", | |
| 1266 | + @ padding-left: 1em; | |
| 1267 | + @ padding-right: 1em; | |
| 1268 | + }, | |
| 1269 | + { ".fileage td:nth-child(3)", | |
| 1270 | + "fileage third column (the check-in comment)", | |
| 1271 | + @ word-break: break-all; | |
| 1272 | + @ word-wrap: break-word; | |
| 1273 | + @ max-width: 50%; | |
| 1274 | + }, | |
| 1275 | + { ".brlist table", "The list of branches", | |
| 1276 | + @ border-spacing: 0; | |
| 1277 | + }, | |
| 1278 | + { ".brlist table th", "Branch list table headers", | |
| 1279 | + @ text-align: left; | |
| 1280 | + @ padding: 0px 1em 0.5ex 0px; | |
| 1281 | + }, | |
| 1282 | + { ".brlist table td", "Branch list table headers", | |
| 1283 | + @ padding: 0px 2em 0px 0px; | |
| 1284 | + }, | |
| 1285 | + { "th.sort:after", | |
| 1286 | + "General styles for sortable column marker", | |
| 1287 | + @ margin-left: .4em; | |
| 1288 | + @ cursor: pointer; | |
| 1289 | + @ text-shadow: 0 0 0 #000; /* Makes arrow darker */ | |
| 1290 | + }, | |
| 1291 | + { "th.sort.asc:after", | |
| 1292 | + "Ascending sort column marker", | |
| 1293 | + @ content: '\2193'; | |
| 1294 | + }, | |
| 1295 | + { "th.sort.desc:after", | |
| 1296 | + "Descending sort column marker", | |
| 1297 | + @ content: '\2191'; | |
| 1223 | 1298 | }, |
| 1224 | 1299 | { 0, |
| 1225 | 1300 | 0, |
| 1226 | 1301 | 0 |
| 1227 | 1302 | } |
| 1228 | 1303 |
| --- src/style.c | |
| +++ src/style.c | |
| @@ -783,10 +783,15 @@ | |
| 783 | { ".filetree", |
| 784 | "tree-view file browser", |
| 785 | @ margin: 1em 0; |
| 786 | @ line-height: 1.5; |
| 787 | }, |
| 788 | { ".filetree ul", |
| 789 | "tree-view lists", |
| 790 | @ margin: 0; |
| 791 | @ padding: 0; |
| 792 | @ list-style: none; |
| @@ -832,21 +837,37 @@ | |
| 832 | }, |
| 833 | { ".filetree a", |
| 834 | "tree-view links", |
| 835 | @ position: relative; |
| 836 | @ z-index: 1; |
| 837 | @ display: inline-block; |
| 838 | @ min-height: 16px; |
| 839 | @ padding-left: 21px; |
| 840 | @ background-image: url(data:image/gif;base64,R0lGODlhEAAQAJEAAP\/\/\/yEhIf\/\/\/wAAACH5BAEHAAIALAAAAAAQABAAAAIvlIKpxqcfmgOUvoaqDSCxrEEfF14GqFXImJZsu73wepJzVMNxrtNTj3NATMKhpwAAOw==); |
| 841 | @ background-position: center left; |
| 842 | @ background-repeat: no-repeat; |
| 843 | }, |
| 844 | { ".filetree .dir > a", |
| 845 | "tree-view directory links", |
| 846 | @ background-image: url(data:image/gif;base64,R0lGODlhEAAQAJEAAP/WVCIiIv\/\/\/wAAACH5BAEHAAIALAAAAAAQABAAAAInlI9pwa3XYniCgQtkrAFfLXkiFo1jaXpo+jUs6b5Z/K4siDu5RPUFADs=); |
| 847 | }, |
| 848 | { "table.login_out", |
| 849 | "table format for login/out label/input table", |
| 850 | @ text-align: left; |
| 851 | @ margin-right: 10px; |
| 852 | @ margin-left: 10px; |
| @@ -1211,17 +1232,71 @@ | |
| 1211 | @ color: black; |
| 1212 | @ background-color: white; |
| 1213 | }, |
| 1214 | { "table.adminLogTable", |
| 1215 | "Class for the /admin_log table", |
| 1216 | @ text-align: left |
| 1217 | }, |
| 1218 | { ".adminLogTable .adminTime", |
| 1219 | "Class for the /admin_log table", |
| 1220 | @ text-align: left |
| 1221 | @ vertical-align: top; |
| 1222 | @ white-space: nowrap; |
| 1223 | }, |
| 1224 | { 0, |
| 1225 | 0, |
| 1226 | 0 |
| 1227 | } |
| 1228 |
| --- src/style.c | |
| +++ src/style.c | |
| @@ -783,10 +783,15 @@ | |
| 783 | { ".filetree", |
| 784 | "tree-view file browser", |
| 785 | @ margin: 1em 0; |
| 786 | @ line-height: 1.5; |
| 787 | }, |
| 788 | { |
| 789 | ".filetree > ul", |
| 790 | "tree-view top-level list", |
| 791 | @ display: inline-block; |
| 792 | }, |
| 793 | { ".filetree ul", |
| 794 | "tree-view lists", |
| 795 | @ margin: 0; |
| 796 | @ padding: 0; |
| 797 | @ list-style: none; |
| @@ -832,21 +837,37 @@ | |
| 837 | }, |
| 838 | { ".filetree a", |
| 839 | "tree-view links", |
| 840 | @ position: relative; |
| 841 | @ z-index: 1; |
| 842 | @ display: table-cell; |
| 843 | @ min-height: 16px; |
| 844 | @ padding-left: 21px; |
| 845 | @ background-image: url(data:image/gif;base64,R0lGODlhEAAQAJEAAP\/\/\/yEhIf\/\/\/wAAACH5BAEHAAIALAAAAAAQABAAAAIvlIKpxqcfmgOUvoaqDSCxrEEfF14GqFXImJZsu73wepJzVMNxrtNTj3NATMKhpwAAOw==); |
| 846 | @ background-position: center left; |
| 847 | @ background-repeat: no-repeat; |
| 848 | }, |
| 849 | { "div.filetreeline", |
| 850 | "line of a file tree", |
| 851 | @ display: table; |
| 852 | @ width: 100%; |
| 853 | @ white-space: nowrap; |
| 854 | }, |
| 855 | { ".filetree .dir > div.filetreeline > a", |
| 856 | "tree-view directory links", |
| 857 | @ background-image: url(data:image/gif;base64,R0lGODlhEAAQAJEAAP/WVCIiIv\/\/\/wAAACH5BAEHAAIALAAAAAAQABAAAAInlI9pwa3XYniCgQtkrAFfLXkiFo1jaXpo+jUs6b5Z/K4siDu5RPUFADs=); |
| 858 | }, |
| 859 | { "div.filetreeage", |
| 860 | "Last change floating display on the right", |
| 861 | @ display: table-cell; |
| 862 | @ padding-left: 3em; |
| 863 | @ text-align: right; |
| 864 | }, |
| 865 | { "div.filetreeline:hover", |
| 866 | "Highlight the line of a file tree", |
| 867 | @ background-color: #eee; |
| 868 | }, |
| 869 | { "table.login_out", |
| 870 | "table format for login/out label/input table", |
| 871 | @ text-align: left; |
| 872 | @ margin-right: 10px; |
| 873 | @ margin-left: 10px; |
| @@ -1211,17 +1232,71 @@ | |
| 1232 | @ color: black; |
| 1233 | @ background-color: white; |
| 1234 | }, |
| 1235 | { "table.adminLogTable", |
| 1236 | "Class for the /admin_log table", |
| 1237 | @ text-align: left; |
| 1238 | }, |
| 1239 | { ".adminLogTable .adminTime", |
| 1240 | "Class for the /admin_log table", |
| 1241 | @ text-align: left; |
| 1242 | @ vertical-align: top; |
| 1243 | @ white-space: nowrap; |
| 1244 | }, |
| 1245 | { ".fileage table", |
| 1246 | "The fileage table", |
| 1247 | @ border-spacing: 0; |
| 1248 | }, |
| 1249 | { ".fileage tr:hover", |
| 1250 | "Mouse-over effects for the file-age table", |
| 1251 | @ background-color: #eee; |
| 1252 | }, |
| 1253 | { ".fileage td", |
| 1254 | "fileage table cells", |
| 1255 | @ vertical-align: top; |
| 1256 | @ text-align: left; |
| 1257 | @ border-top: 1px solid #ddd; |
| 1258 | @ padding-top: 3px; |
| 1259 | }, |
| 1260 | { ".fileage td:first-child", |
| 1261 | "fileage first column (the age)", |
| 1262 | @ white-space: nowrap; |
| 1263 | }, |
| 1264 | { ".fileage td:nth-child(2)", |
| 1265 | "fileage second column (the filename)", |
| 1266 | @ padding-left: 1em; |
| 1267 | @ padding-right: 1em; |
| 1268 | }, |
| 1269 | { ".fileage td:nth-child(3)", |
| 1270 | "fileage third column (the check-in comment)", |
| 1271 | @ word-break: break-all; |
| 1272 | @ word-wrap: break-word; |
| 1273 | @ max-width: 50%; |
| 1274 | }, |
| 1275 | { ".brlist table", "The list of branches", |
| 1276 | @ border-spacing: 0; |
| 1277 | }, |
| 1278 | { ".brlist table th", "Branch list table headers", |
| 1279 | @ text-align: left; |
| 1280 | @ padding: 0px 1em 0.5ex 0px; |
| 1281 | }, |
| 1282 | { ".brlist table td", "Branch list table headers", |
| 1283 | @ padding: 0px 2em 0px 0px; |
| 1284 | }, |
| 1285 | { "th.sort:after", |
| 1286 | "General styles for sortable column marker", |
| 1287 | @ margin-left: .4em; |
| 1288 | @ cursor: pointer; |
| 1289 | @ text-shadow: 0 0 0 #000; /* Makes arrow darker */ |
| 1290 | }, |
| 1291 | { "th.sort.asc:after", |
| 1292 | "Ascending sort column marker", |
| 1293 | @ content: '\2193'; |
| 1294 | }, |
| 1295 | { "th.sort.desc:after", |
| 1296 | "Descending sort column marker", |
| 1297 | @ content: '\2191'; |
| 1298 | }, |
| 1299 | { 0, |
| 1300 | 0, |
| 1301 | 0 |
| 1302 | } |
| 1303 |
+1
-1
| --- src/tag.c | ||
| +++ src/tag.c | ||
| @@ -561,11 +561,11 @@ | ||
| 561 | 561 | ); |
| 562 | 562 | @ <ul> |
| 563 | 563 | while( db_step(&q)==SQLITE_ROW ){ |
| 564 | 564 | const char *zName = db_column_text(&q, 0); |
| 565 | 565 | if( g.perm.Hyperlink ){ |
| 566 | - @ <li>%z(xhref("class='taglink'","%R/timeline?t=%T",zName)) | |
| 566 | + @ <li>%z(xhref("class='taglink'","%R/timeline?t=%T&n=200",zName)) | |
| 567 | 567 | @ %h(zName)</a></li> |
| 568 | 568 | }else{ |
| 569 | 569 | @ <li><span class="tagDsp">%h(zName)</span></li> |
| 570 | 570 | } |
| 571 | 571 | } |
| 572 | 572 |
| --- src/tag.c | |
| +++ src/tag.c | |
| @@ -561,11 +561,11 @@ | |
| 561 | ); |
| 562 | @ <ul> |
| 563 | while( db_step(&q)==SQLITE_ROW ){ |
| 564 | const char *zName = db_column_text(&q, 0); |
| 565 | if( g.perm.Hyperlink ){ |
| 566 | @ <li>%z(xhref("class='taglink'","%R/timeline?t=%T",zName)) |
| 567 | @ %h(zName)</a></li> |
| 568 | }else{ |
| 569 | @ <li><span class="tagDsp">%h(zName)</span></li> |
| 570 | } |
| 571 | } |
| 572 |
| --- src/tag.c | |
| +++ src/tag.c | |
| @@ -561,11 +561,11 @@ | |
| 561 | ); |
| 562 | @ <ul> |
| 563 | while( db_step(&q)==SQLITE_ROW ){ |
| 564 | const char *zName = db_column_text(&q, 0); |
| 565 | if( g.perm.Hyperlink ){ |
| 566 | @ <li>%z(xhref("class='taglink'","%R/timeline?t=%T&n=200",zName)) |
| 567 | @ %h(zName)</a></li> |
| 568 | }else{ |
| 569 | @ <li><span class="tagDsp">%h(zName)</span></li> |
| 570 | } |
| 571 | } |
| 572 |
+64
-27
| --- src/timeline.c | ||
| +++ src/timeline.c | ||
| @@ -20,10 +20,20 @@ | ||
| 20 | 20 | */ |
| 21 | 21 | #include "config.h" |
| 22 | 22 | #include <string.h> |
| 23 | 23 | #include <time.h> |
| 24 | 24 | #include "timeline.h" |
| 25 | + | |
| 26 | +/* | |
| 27 | +** Add an appropriate tag to the output if "rid" is unpublished (private) | |
| 28 | +*/ | |
| 29 | +#define UNPUB_TAG "<em>(unpublished)</em>" | |
| 30 | +void tag_private_status(int rid){ | |
| 31 | + if( content_is_private(rid) ){ | |
| 32 | + cgi_printf("%s", UNPUB_TAG); | |
| 33 | + } | |
| 34 | +} | |
| 25 | 35 | |
| 26 | 36 | /* |
| 27 | 37 | ** Generate a hyperlink to a version. |
| 28 | 38 | */ |
| 29 | 39 | void hyperlink_to_uuid(const char *zUuid){ |
| @@ -77,10 +87,11 @@ | ||
| 77 | 87 | #define TIMELINE_FCHANGES 0x0020 /* Detail file changes */ |
| 78 | 88 | #define TIMELINE_BRCOLOR 0x0040 /* Background color by branch name */ |
| 79 | 89 | #define TIMELINE_UCOLOR 0x0080 /* Background color by user */ |
| 80 | 90 | #define TIMELINE_FRENAMES 0x0100 /* Detail only file name changes */ |
| 81 | 91 | #define TIMELINE_UNHIDE 0x0200 /* Unhide check-ins with "hidden" tag */ |
| 92 | +#define TIMELINE_SHOWRID 0x0400 /* Show RID values in addition to UUIDs */ | |
| 82 | 93 | #endif |
| 83 | 94 | |
| 84 | 95 | /* |
| 85 | 96 | ** Hash a string and use the hash to determine a background color. |
| 86 | 97 | */ |
| @@ -394,10 +405,13 @@ | ||
| 394 | 405 | } |
| 395 | 406 | }else if( zType[0]=='e' && tagid ){ |
| 396 | 407 | hyperlink_to_event_tagid(tagid<0?-tagid:tagid); |
| 397 | 408 | }else if( (tmFlags & TIMELINE_ARTID)!=0 ){ |
| 398 | 409 | hyperlink_to_uuid(zUuid); |
| 410 | + } | |
| 411 | + if( tmFlags & TIMELINE_SHOWRID ){ | |
| 412 | + @ (%d(rid)) | |
| 399 | 413 | } |
| 400 | 414 | db_column_blob(pQuery, commentColumn, &comment); |
| 401 | 415 | if( zType[0]!='c' ){ |
| 402 | 416 | /* Comments for anything other than a check-in are generated by |
| 403 | 417 | ** "fossil rebuild" and expect to be rendered as text/x-fossil-wiki */ |
| @@ -417,11 +431,11 @@ | ||
| 417 | 431 | /* Generate the "user: USERNAME" at the end of the comment, together |
| 418 | 432 | ** with a hyperlink to another timeline for that user. |
| 419 | 433 | */ |
| 420 | 434 | if( zTagList && zTagList[0]==0 ) zTagList = 0; |
| 421 | 435 | if( g.perm.Hyperlink && fossil_strcmp(zDispUser, zThisUser)!=0 ){ |
| 422 | - char *zLink = mprintf("%R/timeline?u=%h&c=%t&nd", zDispUser, zDate); | |
| 436 | + char *zLink = mprintf("%R/timeline?u=%h&c=%t&nd&n=200", zDispUser, zDate); | |
| 423 | 437 | @ (user: %z(href("%z",zLink))%h(zDispUser)</a>%s(zTagList?",":"\051") |
| 424 | 438 | }else{ |
| 425 | 439 | @ (user: %h(zDispUser)%s(zTagList?",":"\051") |
| 426 | 440 | } |
| 427 | 441 | |
| @@ -442,11 +456,11 @@ | ||
| 442 | 456 | while( z && z[0] ){ |
| 443 | 457 | for(i=0; z[i] && (z[i]!=',' || z[i+1]!=' '); i++){} |
| 444 | 458 | if( zThisTag==0 || memcmp(z, zThisTag, i)!=0 || zThisTag[i]!=0 ){ |
| 445 | 459 | blob_appendf(&links, |
| 446 | 460 | "%z%#h</a>%.2s", |
| 447 | - href("%R/timeline?r=%#t&nd&c=%t",i,z,zDate), i,z, &z[i] | |
| 461 | + href("%R/timeline?r=%#t&nd&c=%t&n=200",i,z,zDate), i,z, &z[i] | |
| 448 | 462 | ); |
| 449 | 463 | }else{ |
| 450 | 464 | blob_appendf(&links, "%#h", i+2, z); |
| 451 | 465 | } |
| 452 | 466 | if( z[i]==0 ) break; |
| @@ -456,11 +470,11 @@ | ||
| 456 | 470 | blob_reset(&links); |
| 457 | 471 | }else{ |
| 458 | 472 | @ tags: %h(zTagList)) |
| 459 | 473 | } |
| 460 | 474 | } |
| 461 | - | |
| 475 | + tag_private_status(rid); | |
| 462 | 476 | |
| 463 | 477 | /* Generate extra hyperlinks at the end of the comment */ |
| 464 | 478 | if( xExtra ){ |
| 465 | 479 | xExtra(rid); |
| 466 | 480 | } |
| @@ -471,11 +485,11 @@ | ||
| 471 | 485 | ){ |
| 472 | 486 | int inUl = 0; |
| 473 | 487 | if( !fchngQueryInit ){ |
| 474 | 488 | db_prepare(&fchngQuery, |
| 475 | 489 | "SELECT (pid==0) AS isnew," |
| 476 | - " (fid==0) AS isdel," | |
| 490 | + " fid," | |
| 477 | 491 | " (SELECT name FROM filename WHERE fnid=mlink.fnid) AS name," |
| 478 | 492 | " (SELECT uuid FROM blob WHERE rid=fid)," |
| 479 | 493 | " (SELECT uuid FROM blob WHERE rid=pid)," |
| 480 | 494 | " (SELECT name FROM filename WHERE fnid=mlink.pfnid) AS oldnm" |
| 481 | 495 | " FROM mlink" |
| @@ -488,14 +502,16 @@ | ||
| 488 | 502 | } |
| 489 | 503 | db_bind_int(&fchngQuery, ":mid", rid); |
| 490 | 504 | while( db_step(&fchngQuery)==SQLITE_ROW ){ |
| 491 | 505 | const char *zFilename = db_column_text(&fchngQuery, 2); |
| 492 | 506 | int isNew = db_column_int(&fchngQuery, 0); |
| 493 | - int isDel = db_column_int(&fchngQuery, 1); | |
| 507 | + int fid = db_column_int(&fchngQuery, 1); | |
| 508 | + int isDel = fid==0; | |
| 494 | 509 | const char *zOldName = db_column_text(&fchngQuery, 5); |
| 495 | 510 | const char *zOld = db_column_text(&fchngQuery, 4); |
| 496 | 511 | const char *zNew = db_column_text(&fchngQuery, 3); |
| 512 | + const char *zUnpubTag = ""; | |
| 497 | 513 | if( !inUl ){ |
| 498 | 514 | @ <ul class="filelist"> |
| 499 | 515 | inUl = 1; |
| 500 | 516 | } |
| 501 | 517 | if( (tmFlags & TIMELINE_FRENAMES)!=0 ){ |
| @@ -502,23 +518,26 @@ | ||
| 502 | 518 | if( !isNew && !isDel && zOldName!=0 ){ |
| 503 | 519 | @ <li> %h(zOldName) → %h(zFilename) |
| 504 | 520 | } |
| 505 | 521 | continue; |
| 506 | 522 | } |
| 523 | + if( content_is_private(fid) ){ | |
| 524 | + zUnpubTag = UNPUB_TAG; | |
| 525 | + } | |
| 507 | 526 | if( isNew ){ |
| 508 | - @ <li> %h(zFilename) (new file) | |
| 527 | + @ <li> %h(zFilename) %s(zUnpubTag) (new file) | |
| 509 | 528 | @ %z(href("%R/artifact/%s",zNew))[view]</a></li> |
| 510 | 529 | }else if( isDel ){ |
| 511 | 530 | @ <li> %h(zFilename) (deleted)</li> |
| 512 | 531 | }else if( fossil_strcmp(zOld,zNew)==0 && zOldName!=0 ){ |
| 513 | - @ <li> %h(zOldName) → %h(zFilename) | |
| 532 | + @ <li> %h(zOldName) → %h(zFilename) %s(zUnpubTag) | |
| 514 | 533 | @ %z(href("%R/artifact/%s",zNew))[view]</a></li> |
| 515 | 534 | }else{ |
| 516 | 535 | if( zOldName!=0 ){ |
| 517 | - @ <li> %h(zOldName) → %h(zFilename) | |
| 536 | + @ <li> %h(zOldName) → %h(zFilename) %s(zUnpubTag) | |
| 518 | 537 | }else{ |
| 519 | - @ <li> %h(zFilename) | |
| 538 | + @ <li> %h(zFilename) %s(zUnpubTag) | |
| 520 | 539 | } |
| 521 | 540 | @ %z(href("%R/fdiff?sbs=1&v1=%s&v2=%s",zOld,zNew))[diff]</a></li> |
| 522 | 541 | } |
| 523 | 542 | } |
| 524 | 543 | db_reset(&fchngQuery); |
| @@ -589,12 +608,12 @@ | ||
| 589 | 608 | ** for the upward portion of a merge arrow. The merge arrow goes up |
| 590 | 609 | ** to the row identified by mu:. If this value is zero then |
| 591 | 610 | ** node has no merge children and no merge-out line is drawn. |
| 592 | 611 | ** mu: The id of the row which is the top of the merge-out arrow. |
| 593 | 612 | ** u: Draw a thick child-line out of the top of this node and up to |
| 594 | - ** the node with an id equal to this value. 0 if there is no | |
| 595 | - ** thick-line riser. | |
| 613 | + ** the node with an id equal to this value. 0 if it is straight to | |
| 614 | + ** the top of the page, -1 if there is no thick-line riser. | |
| 596 | 615 | ** f: 0x01: a leaf node. |
| 597 | 616 | ** au: An array of integers that define thick-line risers for branches. |
| 598 | 617 | ** The integers are in pairs. For each pair, the first integer is |
| 599 | 618 | ** is the rail on which the riser should run and the second integer |
| 600 | 619 | ** is the id of the node upto which the riser should run. |
| @@ -1055,11 +1074,11 @@ | ||
| 1055 | 1074 | const char *zYearMonth = P("ym"); /* Show checkins for the given YYYY-MM */ |
| 1056 | 1075 | const char *zYearWeek = P("yw"); /* Show checkins for the given YYYY-WW (week-of-year)*/ |
| 1057 | 1076 | int useDividers = P("nd")==0; /* Show dividers if "nd" is missing */ |
| 1058 | 1077 | int renameOnly = P("namechng")!=0; /* Show only checkins that rename files */ |
| 1059 | 1078 | int tagid; /* Tag ID */ |
| 1060 | - int tmFlags; /* Timeline flags */ | |
| 1079 | + int tmFlags = 0; /* Timeline flags */ | |
| 1061 | 1080 | const char *zThisTag = 0; /* Suppress links to this tag */ |
| 1062 | 1081 | const char *zThisUser = 0; /* Suppress links to this user */ |
| 1063 | 1082 | HQuery url; /* URL for various branch links */ |
| 1064 | 1083 | int from_rid = name_to_typed_rid(P("from"),"ci"); /* from= for paths */ |
| 1065 | 1084 | int to_rid = name_to_typed_rid(P("to"),"ci"); /* to= for path timelines */ |
| @@ -1088,16 +1107,22 @@ | ||
| 1088 | 1107 | tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='sym-%q'",zBrName); |
| 1089 | 1108 | zThisTag = zBrName; |
| 1090 | 1109 | }else{ |
| 1091 | 1110 | tagid = 0; |
| 1092 | 1111 | } |
| 1112 | + if( tagid>0 | |
| 1113 | + && db_int(0,"SELECT count(*) FROM tagxref WHERE tagid=%d",tagid)<=nEntry | |
| 1114 | + ){ | |
| 1115 | + zCirca = zBefore = zAfter = 0; | |
| 1116 | + nEntry = -1; | |
| 1117 | + } | |
| 1093 | 1118 | if( zType[0]=='a' ){ |
| 1094 | - tmFlags = TIMELINE_BRIEF | TIMELINE_GRAPH; | |
| 1119 | + tmFlags |= TIMELINE_BRIEF | TIMELINE_GRAPH; | |
| 1095 | 1120 | }else{ |
| 1096 | - tmFlags = TIMELINE_GRAPH; | |
| 1121 | + tmFlags |= TIMELINE_GRAPH; | |
| 1097 | 1122 | } |
| 1098 | - url_add_parameter(&url, "n", mprintf("%d", nEntry)); | |
| 1123 | + if( nEntry>0 ) url_add_parameter(&url, "n", mprintf("%d", nEntry)); | |
| 1099 | 1124 | if( P("ng")!=0 || zSearch!=0 ){ |
| 1100 | 1125 | tmFlags &= ~TIMELINE_GRAPH; |
| 1101 | 1126 | url_add_parameter(&url, "ng", 0); |
| 1102 | 1127 | } |
| 1103 | 1128 | if( P("brbg")!=0 ){ |
| @@ -1185,10 +1210,11 @@ | ||
| 1185 | 1210 | }else if( (p_rid || d_rid) && g.perm.Read ){ |
| 1186 | 1211 | /* If p= or d= is present, ignore all other parameters other than n= */ |
| 1187 | 1212 | char *zUuid; |
| 1188 | 1213 | int np, nd; |
| 1189 | 1214 | |
| 1215 | + tmFlags |= TIMELINE_DISJOINT; | |
| 1190 | 1216 | if( p_rid && d_rid ){ |
| 1191 | 1217 | if( p_rid!=d_rid ) p_rid = d_rid; |
| 1192 | 1218 | if( P("n")==0 ) nEntry = 10; |
| 1193 | 1219 | } |
| 1194 | 1220 | db_multi_exec( |
| @@ -1229,11 +1255,11 @@ | ||
| 1229 | 1255 | url_add_parameter(&url, "d", zUuid); |
| 1230 | 1256 | } |
| 1231 | 1257 | if( nEntry>20 ){ |
| 1232 | 1258 | timeline_submenu(&url, "20 Entries", "n", "20", 0); |
| 1233 | 1259 | } |
| 1234 | - if( nEntry<200 ){ | |
| 1260 | + if( nEntry<200 && nEntry>0 ){ | |
| 1235 | 1261 | timeline_submenu(&url, "200 Entries", "n", "200", 0); |
| 1236 | 1262 | } |
| 1237 | 1263 | if( tmFlags & TIMELINE_FCHANGES ){ |
| 1238 | 1264 | timeline_submenu(&url, "Hide Files", "v", 0, 0); |
| 1239 | 1265 | }else{ |
| @@ -1373,10 +1399,16 @@ | ||
| 1373 | 1399 | }else if( zType[0]=='g' ){ |
| 1374 | 1400 | zEType = "tag"; |
| 1375 | 1401 | } |
| 1376 | 1402 | } |
| 1377 | 1403 | if( zUser ){ |
| 1404 | + int n = db_int(0,"SELECT count(*) FROM event" | |
| 1405 | + " WHERE user=%Q OR euser=%Q", zUser, zUser); | |
| 1406 | + if( n<=nEntry ){ | |
| 1407 | + zCirca = zBefore = zAfter = 0; | |
| 1408 | + nEntry = -1; | |
| 1409 | + } | |
| 1378 | 1410 | blob_append_sql(&sql, " AND (event.user=%Q OR event.euser=%Q)", |
| 1379 | 1411 | zUser, zUser); |
| 1380 | 1412 | url_add_parameter(&url, "u", zUser); |
| 1381 | 1413 | zThisUser = zUser; |
| 1382 | 1414 | } |
| @@ -1394,11 +1426,11 @@ | ||
| 1394 | 1426 | blob_append_sql(&sql, |
| 1395 | 1427 | " AND event.mtime>=%.17g AND event.mtime<=%.17g" |
| 1396 | 1428 | " ORDER BY event.mtime ASC", rAfter-ONE_SECOND, rBefore+ONE_SECOND); |
| 1397 | 1429 | url_add_parameter(&url, "a", zAfter); |
| 1398 | 1430 | url_add_parameter(&url, "b", zBefore); |
| 1399 | - nEntry = 1000000; | |
| 1431 | + nEntry = -1; | |
| 1400 | 1432 | }else{ |
| 1401 | 1433 | blob_append_sql(&sql, |
| 1402 | 1434 | " AND event.mtime>=%.17g ORDER BY event.mtime ASC", |
| 1403 | 1435 | rAfter-ONE_SECOND); |
| 1404 | 1436 | url_add_parameter(&url, "a", zAfter); |
| @@ -1425,19 +1457,19 @@ | ||
| 1425 | 1457 | if( useDividers ) timeline_add_dividers(rCirca, 0); |
| 1426 | 1458 | url_add_parameter(&url, "c", zCirca); |
| 1427 | 1459 | }else{ |
| 1428 | 1460 | blob_append_sql(&sql, " ORDER BY event.mtime DESC"); |
| 1429 | 1461 | } |
| 1430 | - blob_append_sql(&sql, " LIMIT %d", nEntry); | |
| 1462 | + if( nEntry>0 ) blob_append_sql(&sql, " LIMIT %d", nEntry); | |
| 1431 | 1463 | db_multi_exec("%s", blob_sql_text(&sql)); |
| 1432 | 1464 | |
| 1433 | 1465 | n = db_int(0, "SELECT count(*) FROM timeline WHERE etype!='div' /*scan*/"); |
| 1434 | 1466 | if( zYearMonth ){ |
| 1435 | 1467 | blob_appendf(&desc, "%s events for %h", zEType, zYearMonth); |
| 1436 | 1468 | }else if( zYearWeek ){ |
| 1437 | 1469 | blob_appendf(&desc, "%s events for year/week %h", zEType, zYearWeek); |
| 1438 | - }else if( zAfter==0 && zBefore==0 && zCirca==0 ){ | |
| 1470 | + }else if( zAfter==0 && zBefore==0 && zCirca==0 && n>=nEntry && nEntry>0 ){ | |
| 1439 | 1471 | blob_appendf(&desc, "%d most recent %ss", n, zEType); |
| 1440 | 1472 | }else{ |
| 1441 | 1473 | blob_appendf(&desc, "%d %ss", n, zEType); |
| 1442 | 1474 | } |
| 1443 | 1475 | if( zUses ){ |
| @@ -1484,11 +1516,11 @@ | ||
| 1484 | 1516 | } |
| 1485 | 1517 | if( zBefore || (zAfter && n==nEntry) ){ |
| 1486 | 1518 | zDate = db_text(0, "SELECT max(timestamp) FROM timeline /*scan*/"); |
| 1487 | 1519 | timeline_submenu(&url, "Newer", "a", zDate, "b"); |
| 1488 | 1520 | free(zDate); |
| 1489 | - }else if( tagid==0 ){ | |
| 1521 | + }else if( tagid==0 && zUses==0 ){ | |
| 1490 | 1522 | if( zType[0]!='a' ){ |
| 1491 | 1523 | timeline_submenu(&url, "All Types", "y", "all", 0); |
| 1492 | 1524 | } |
| 1493 | 1525 | if( zType[0]!='w' && g.perm.RdWiki ){ |
| 1494 | 1526 | timeline_submenu(&url, "Wiki Only", "y", "w", 0); |
| @@ -1507,11 +1539,11 @@ | ||
| 1507 | 1539 | } |
| 1508 | 1540 | } |
| 1509 | 1541 | if( nEntry>20 ){ |
| 1510 | 1542 | timeline_submenu(&url, "20 Entries", "n", "20", 0); |
| 1511 | 1543 | } |
| 1512 | - if( nEntry<200 ){ | |
| 1544 | + if( nEntry<200 && nEntry>0 ){ | |
| 1513 | 1545 | timeline_submenu(&url, "200 Entries", "n", "200", 0); |
| 1514 | 1546 | } |
| 1515 | 1547 | if( zType[0]=='a' || zType[0]=='c' ){ |
| 1516 | 1548 | if( tmFlags & TIMELINE_FCHANGES ){ |
| 1517 | 1549 | timeline_submenu(&url, "Hide Files", "v", 0, 0); |
| @@ -1525,10 +1557,11 @@ | ||
| 1525 | 1557 | } |
| 1526 | 1558 | } |
| 1527 | 1559 | if( P("showsql") ){ |
| 1528 | 1560 | @ <blockquote>%h(blob_sql_text(&sql))</blockquote> |
| 1529 | 1561 | } |
| 1562 | + if( P("showrid") ) tmFlags |= TIMELINE_SHOWRID; | |
| 1530 | 1563 | blob_zero(&sql); |
| 1531 | 1564 | db_prepare(&q, "SELECT * FROM timeline ORDER BY sortby DESC /*scan*/"); |
| 1532 | 1565 | @ <h2>%b(&desc)</h2> |
| 1533 | 1566 | blob_reset(&desc); |
| 1534 | 1567 | www_print_timeline(&q, tmFlags, zThisUser, zThisTag, 0); |
| @@ -1617,11 +1650,15 @@ | ||
| 1617 | 1650 | sqlite3_snprintf(sizeof(zPrefix)-n, &zPrefix[n], zBrType); |
| 1618 | 1651 | n = strlen(zPrefix); |
| 1619 | 1652 | } |
| 1620 | 1653 | if( fossil_strcmp(zCurrentUuid,zId)==0 ){ |
| 1621 | 1654 | sqlite3_snprintf(sizeof(zPrefix)-n, &zPrefix[n], "*CURRENT* "); |
| 1622 | - n += strlen(zPrefix); | |
| 1655 | + n += strlen(zPrefix+n); | |
| 1656 | + } | |
| 1657 | + if( content_is_private(rid) ){ | |
| 1658 | + sqlite3_snprintf(sizeof(zPrefix)-n, &zPrefix[n], "*UNPUBLISHED* "); | |
| 1659 | + n += strlen(zPrefix+n); | |
| 1623 | 1660 | } |
| 1624 | 1661 | zFree = mprintf("[%S] %s%s", zId, zPrefix, zCom); |
| 1625 | 1662 | /* record another X lines */ |
| 1626 | 1663 | nLine += comment_print(zFree, zCom, 9, width, g.comFmtFlags); |
| 1627 | 1664 | fossil_free(zFree); |
| @@ -2362,11 +2399,11 @@ | ||
| 2362 | 2399 | @ <br><div>Total events: %d(nEventTotal) |
| 2363 | 2400 | @ <br>Average per active %s(zAvgLabel): %d(nAvg) |
| 2364 | 2401 | @ </div> |
| 2365 | 2402 | } |
| 2366 | 2403 | if( !includeMonth ){ |
| 2367 | - output_table_sorting_javascript("statsTable","tnx"); | |
| 2404 | + output_table_sorting_javascript("statsTable","tnx",-1); | |
| 2368 | 2405 | } |
| 2369 | 2406 | } |
| 2370 | 2407 | |
| 2371 | 2408 | /* |
| 2372 | 2409 | ** Implements the "byuser" view for /reports. |
| @@ -2413,11 +2450,11 @@ | ||
| 2413 | 2450 | rowClass = ++nRowNumber % 2; |
| 2414 | 2451 | nEventTotal += nCount; |
| 2415 | 2452 | @<tr class='row%d(rowClass)'> |
| 2416 | 2453 | @ <td> |
| 2417 | 2454 | @ <a href="?view=bymonth&user=%h(zUser)&type=%c((char)statsReportType)">%h(zUser)</a> |
| 2418 | - @ </td><td>%d(nCount)</td> | |
| 2455 | + @ </td><td data-sortkey='%08x(-nCount)'>%d(nCount)</td> | |
| 2419 | 2456 | @ <td> |
| 2420 | 2457 | @ <div class='statistics-report-graph-line' |
| 2421 | 2458 | @ style='width:%d(nSize)%%;'> </div> |
| 2422 | 2459 | @ </td> |
| 2423 | 2460 | @</tr> |
| @@ -2426,11 +2463,11 @@ | ||
| 2426 | 2463 | use percent-based graph bars. |
| 2427 | 2464 | */ |
| 2428 | 2465 | } |
| 2429 | 2466 | @ </tbody></table> |
| 2430 | 2467 | db_finalize(&query); |
| 2431 | - output_table_sorting_javascript("statsTable","tnx"); | |
| 2468 | + output_table_sorting_javascript("statsTable","tkx",2); | |
| 2432 | 2469 | } |
| 2433 | 2470 | |
| 2434 | 2471 | /* |
| 2435 | 2472 | ** Implements the "byweekday" view for /reports. |
| 2436 | 2473 | */ |
| @@ -2491,11 +2528,11 @@ | ||
| 2491 | 2528 | @ </td> |
| 2492 | 2529 | @</tr> |
| 2493 | 2530 | } |
| 2494 | 2531 | @ </tbody></table> |
| 2495 | 2532 | db_finalize(&query); |
| 2496 | - output_table_sorting_javascript("statsTable","ntnx"); | |
| 2533 | + output_table_sorting_javascript("statsTable","ntnx",1); | |
| 2497 | 2534 | } |
| 2498 | 2535 | |
| 2499 | 2536 | |
| 2500 | 2537 | /* |
| 2501 | 2538 | ** Helper for stats_report_by_month_year(), which generates a list of |
| @@ -2624,11 +2661,11 @@ | ||
| 2624 | 2661 | int nAvg = iterations ? (total/iterations) : 0; |
| 2625 | 2662 | cgi_printf("<br><div>Total events: %d<br>" |
| 2626 | 2663 | "Average per active week: %d</div>", |
| 2627 | 2664 | total, nAvg); |
| 2628 | 2665 | } |
| 2629 | - output_table_sorting_javascript("statsTable","tnx"); | |
| 2666 | + output_table_sorting_javascript("statsTable","tnx",-1); | |
| 2630 | 2667 | } |
| 2631 | 2668 | } |
| 2632 | 2669 | |
| 2633 | 2670 | /* |
| 2634 | 2671 | ** WEBPAGE: reports |
| 2635 | 2672 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -20,10 +20,20 @@ | |
| 20 | */ |
| 21 | #include "config.h" |
| 22 | #include <string.h> |
| 23 | #include <time.h> |
| 24 | #include "timeline.h" |
| 25 | |
| 26 | /* |
| 27 | ** Generate a hyperlink to a version. |
| 28 | */ |
| 29 | void hyperlink_to_uuid(const char *zUuid){ |
| @@ -77,10 +87,11 @@ | |
| 77 | #define TIMELINE_FCHANGES 0x0020 /* Detail file changes */ |
| 78 | #define TIMELINE_BRCOLOR 0x0040 /* Background color by branch name */ |
| 79 | #define TIMELINE_UCOLOR 0x0080 /* Background color by user */ |
| 80 | #define TIMELINE_FRENAMES 0x0100 /* Detail only file name changes */ |
| 81 | #define TIMELINE_UNHIDE 0x0200 /* Unhide check-ins with "hidden" tag */ |
| 82 | #endif |
| 83 | |
| 84 | /* |
| 85 | ** Hash a string and use the hash to determine a background color. |
| 86 | */ |
| @@ -394,10 +405,13 @@ | |
| 394 | } |
| 395 | }else if( zType[0]=='e' && tagid ){ |
| 396 | hyperlink_to_event_tagid(tagid<0?-tagid:tagid); |
| 397 | }else if( (tmFlags & TIMELINE_ARTID)!=0 ){ |
| 398 | hyperlink_to_uuid(zUuid); |
| 399 | } |
| 400 | db_column_blob(pQuery, commentColumn, &comment); |
| 401 | if( zType[0]!='c' ){ |
| 402 | /* Comments for anything other than a check-in are generated by |
| 403 | ** "fossil rebuild" and expect to be rendered as text/x-fossil-wiki */ |
| @@ -417,11 +431,11 @@ | |
| 417 | /* Generate the "user: USERNAME" at the end of the comment, together |
| 418 | ** with a hyperlink to another timeline for that user. |
| 419 | */ |
| 420 | if( zTagList && zTagList[0]==0 ) zTagList = 0; |
| 421 | if( g.perm.Hyperlink && fossil_strcmp(zDispUser, zThisUser)!=0 ){ |
| 422 | char *zLink = mprintf("%R/timeline?u=%h&c=%t&nd", zDispUser, zDate); |
| 423 | @ (user: %z(href("%z",zLink))%h(zDispUser)</a>%s(zTagList?",":"\051") |
| 424 | }else{ |
| 425 | @ (user: %h(zDispUser)%s(zTagList?",":"\051") |
| 426 | } |
| 427 | |
| @@ -442,11 +456,11 @@ | |
| 442 | while( z && z[0] ){ |
| 443 | for(i=0; z[i] && (z[i]!=',' || z[i+1]!=' '); i++){} |
| 444 | if( zThisTag==0 || memcmp(z, zThisTag, i)!=0 || zThisTag[i]!=0 ){ |
| 445 | blob_appendf(&links, |
| 446 | "%z%#h</a>%.2s", |
| 447 | href("%R/timeline?r=%#t&nd&c=%t",i,z,zDate), i,z, &z[i] |
| 448 | ); |
| 449 | }else{ |
| 450 | blob_appendf(&links, "%#h", i+2, z); |
| 451 | } |
| 452 | if( z[i]==0 ) break; |
| @@ -456,11 +470,11 @@ | |
| 456 | blob_reset(&links); |
| 457 | }else{ |
| 458 | @ tags: %h(zTagList)) |
| 459 | } |
| 460 | } |
| 461 | |
| 462 | |
| 463 | /* Generate extra hyperlinks at the end of the comment */ |
| 464 | if( xExtra ){ |
| 465 | xExtra(rid); |
| 466 | } |
| @@ -471,11 +485,11 @@ | |
| 471 | ){ |
| 472 | int inUl = 0; |
| 473 | if( !fchngQueryInit ){ |
| 474 | db_prepare(&fchngQuery, |
| 475 | "SELECT (pid==0) AS isnew," |
| 476 | " (fid==0) AS isdel," |
| 477 | " (SELECT name FROM filename WHERE fnid=mlink.fnid) AS name," |
| 478 | " (SELECT uuid FROM blob WHERE rid=fid)," |
| 479 | " (SELECT uuid FROM blob WHERE rid=pid)," |
| 480 | " (SELECT name FROM filename WHERE fnid=mlink.pfnid) AS oldnm" |
| 481 | " FROM mlink" |
| @@ -488,14 +502,16 @@ | |
| 488 | } |
| 489 | db_bind_int(&fchngQuery, ":mid", rid); |
| 490 | while( db_step(&fchngQuery)==SQLITE_ROW ){ |
| 491 | const char *zFilename = db_column_text(&fchngQuery, 2); |
| 492 | int isNew = db_column_int(&fchngQuery, 0); |
| 493 | int isDel = db_column_int(&fchngQuery, 1); |
| 494 | const char *zOldName = db_column_text(&fchngQuery, 5); |
| 495 | const char *zOld = db_column_text(&fchngQuery, 4); |
| 496 | const char *zNew = db_column_text(&fchngQuery, 3); |
| 497 | if( !inUl ){ |
| 498 | @ <ul class="filelist"> |
| 499 | inUl = 1; |
| 500 | } |
| 501 | if( (tmFlags & TIMELINE_FRENAMES)!=0 ){ |
| @@ -502,23 +518,26 @@ | |
| 502 | if( !isNew && !isDel && zOldName!=0 ){ |
| 503 | @ <li> %h(zOldName) → %h(zFilename) |
| 504 | } |
| 505 | continue; |
| 506 | } |
| 507 | if( isNew ){ |
| 508 | @ <li> %h(zFilename) (new file) |
| 509 | @ %z(href("%R/artifact/%s",zNew))[view]</a></li> |
| 510 | }else if( isDel ){ |
| 511 | @ <li> %h(zFilename) (deleted)</li> |
| 512 | }else if( fossil_strcmp(zOld,zNew)==0 && zOldName!=0 ){ |
| 513 | @ <li> %h(zOldName) → %h(zFilename) |
| 514 | @ %z(href("%R/artifact/%s",zNew))[view]</a></li> |
| 515 | }else{ |
| 516 | if( zOldName!=0 ){ |
| 517 | @ <li> %h(zOldName) → %h(zFilename) |
| 518 | }else{ |
| 519 | @ <li> %h(zFilename) |
| 520 | } |
| 521 | @ %z(href("%R/fdiff?sbs=1&v1=%s&v2=%s",zOld,zNew))[diff]</a></li> |
| 522 | } |
| 523 | } |
| 524 | db_reset(&fchngQuery); |
| @@ -589,12 +608,12 @@ | |
| 589 | ** for the upward portion of a merge arrow. The merge arrow goes up |
| 590 | ** to the row identified by mu:. If this value is zero then |
| 591 | ** node has no merge children and no merge-out line is drawn. |
| 592 | ** mu: The id of the row which is the top of the merge-out arrow. |
| 593 | ** u: Draw a thick child-line out of the top of this node and up to |
| 594 | ** the node with an id equal to this value. 0 if there is no |
| 595 | ** thick-line riser. |
| 596 | ** f: 0x01: a leaf node. |
| 597 | ** au: An array of integers that define thick-line risers for branches. |
| 598 | ** The integers are in pairs. For each pair, the first integer is |
| 599 | ** is the rail on which the riser should run and the second integer |
| 600 | ** is the id of the node upto which the riser should run. |
| @@ -1055,11 +1074,11 @@ | |
| 1055 | const char *zYearMonth = P("ym"); /* Show checkins for the given YYYY-MM */ |
| 1056 | const char *zYearWeek = P("yw"); /* Show checkins for the given YYYY-WW (week-of-year)*/ |
| 1057 | int useDividers = P("nd")==0; /* Show dividers if "nd" is missing */ |
| 1058 | int renameOnly = P("namechng")!=0; /* Show only checkins that rename files */ |
| 1059 | int tagid; /* Tag ID */ |
| 1060 | int tmFlags; /* Timeline flags */ |
| 1061 | const char *zThisTag = 0; /* Suppress links to this tag */ |
| 1062 | const char *zThisUser = 0; /* Suppress links to this user */ |
| 1063 | HQuery url; /* URL for various branch links */ |
| 1064 | int from_rid = name_to_typed_rid(P("from"),"ci"); /* from= for paths */ |
| 1065 | int to_rid = name_to_typed_rid(P("to"),"ci"); /* to= for path timelines */ |
| @@ -1088,16 +1107,22 @@ | |
| 1088 | tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='sym-%q'",zBrName); |
| 1089 | zThisTag = zBrName; |
| 1090 | }else{ |
| 1091 | tagid = 0; |
| 1092 | } |
| 1093 | if( zType[0]=='a' ){ |
| 1094 | tmFlags = TIMELINE_BRIEF | TIMELINE_GRAPH; |
| 1095 | }else{ |
| 1096 | tmFlags = TIMELINE_GRAPH; |
| 1097 | } |
| 1098 | url_add_parameter(&url, "n", mprintf("%d", nEntry)); |
| 1099 | if( P("ng")!=0 || zSearch!=0 ){ |
| 1100 | tmFlags &= ~TIMELINE_GRAPH; |
| 1101 | url_add_parameter(&url, "ng", 0); |
| 1102 | } |
| 1103 | if( P("brbg")!=0 ){ |
| @@ -1185,10 +1210,11 @@ | |
| 1185 | }else if( (p_rid || d_rid) && g.perm.Read ){ |
| 1186 | /* If p= or d= is present, ignore all other parameters other than n= */ |
| 1187 | char *zUuid; |
| 1188 | int np, nd; |
| 1189 | |
| 1190 | if( p_rid && d_rid ){ |
| 1191 | if( p_rid!=d_rid ) p_rid = d_rid; |
| 1192 | if( P("n")==0 ) nEntry = 10; |
| 1193 | } |
| 1194 | db_multi_exec( |
| @@ -1229,11 +1255,11 @@ | |
| 1229 | url_add_parameter(&url, "d", zUuid); |
| 1230 | } |
| 1231 | if( nEntry>20 ){ |
| 1232 | timeline_submenu(&url, "20 Entries", "n", "20", 0); |
| 1233 | } |
| 1234 | if( nEntry<200 ){ |
| 1235 | timeline_submenu(&url, "200 Entries", "n", "200", 0); |
| 1236 | } |
| 1237 | if( tmFlags & TIMELINE_FCHANGES ){ |
| 1238 | timeline_submenu(&url, "Hide Files", "v", 0, 0); |
| 1239 | }else{ |
| @@ -1373,10 +1399,16 @@ | |
| 1373 | }else if( zType[0]=='g' ){ |
| 1374 | zEType = "tag"; |
| 1375 | } |
| 1376 | } |
| 1377 | if( zUser ){ |
| 1378 | blob_append_sql(&sql, " AND (event.user=%Q OR event.euser=%Q)", |
| 1379 | zUser, zUser); |
| 1380 | url_add_parameter(&url, "u", zUser); |
| 1381 | zThisUser = zUser; |
| 1382 | } |
| @@ -1394,11 +1426,11 @@ | |
| 1394 | blob_append_sql(&sql, |
| 1395 | " AND event.mtime>=%.17g AND event.mtime<=%.17g" |
| 1396 | " ORDER BY event.mtime ASC", rAfter-ONE_SECOND, rBefore+ONE_SECOND); |
| 1397 | url_add_parameter(&url, "a", zAfter); |
| 1398 | url_add_parameter(&url, "b", zBefore); |
| 1399 | nEntry = 1000000; |
| 1400 | }else{ |
| 1401 | blob_append_sql(&sql, |
| 1402 | " AND event.mtime>=%.17g ORDER BY event.mtime ASC", |
| 1403 | rAfter-ONE_SECOND); |
| 1404 | url_add_parameter(&url, "a", zAfter); |
| @@ -1425,19 +1457,19 @@ | |
| 1425 | if( useDividers ) timeline_add_dividers(rCirca, 0); |
| 1426 | url_add_parameter(&url, "c", zCirca); |
| 1427 | }else{ |
| 1428 | blob_append_sql(&sql, " ORDER BY event.mtime DESC"); |
| 1429 | } |
| 1430 | blob_append_sql(&sql, " LIMIT %d", nEntry); |
| 1431 | db_multi_exec("%s", blob_sql_text(&sql)); |
| 1432 | |
| 1433 | n = db_int(0, "SELECT count(*) FROM timeline WHERE etype!='div' /*scan*/"); |
| 1434 | if( zYearMonth ){ |
| 1435 | blob_appendf(&desc, "%s events for %h", zEType, zYearMonth); |
| 1436 | }else if( zYearWeek ){ |
| 1437 | blob_appendf(&desc, "%s events for year/week %h", zEType, zYearWeek); |
| 1438 | }else if( zAfter==0 && zBefore==0 && zCirca==0 ){ |
| 1439 | blob_appendf(&desc, "%d most recent %ss", n, zEType); |
| 1440 | }else{ |
| 1441 | blob_appendf(&desc, "%d %ss", n, zEType); |
| 1442 | } |
| 1443 | if( zUses ){ |
| @@ -1484,11 +1516,11 @@ | |
| 1484 | } |
| 1485 | if( zBefore || (zAfter && n==nEntry) ){ |
| 1486 | zDate = db_text(0, "SELECT max(timestamp) FROM timeline /*scan*/"); |
| 1487 | timeline_submenu(&url, "Newer", "a", zDate, "b"); |
| 1488 | free(zDate); |
| 1489 | }else if( tagid==0 ){ |
| 1490 | if( zType[0]!='a' ){ |
| 1491 | timeline_submenu(&url, "All Types", "y", "all", 0); |
| 1492 | } |
| 1493 | if( zType[0]!='w' && g.perm.RdWiki ){ |
| 1494 | timeline_submenu(&url, "Wiki Only", "y", "w", 0); |
| @@ -1507,11 +1539,11 @@ | |
| 1507 | } |
| 1508 | } |
| 1509 | if( nEntry>20 ){ |
| 1510 | timeline_submenu(&url, "20 Entries", "n", "20", 0); |
| 1511 | } |
| 1512 | if( nEntry<200 ){ |
| 1513 | timeline_submenu(&url, "200 Entries", "n", "200", 0); |
| 1514 | } |
| 1515 | if( zType[0]=='a' || zType[0]=='c' ){ |
| 1516 | if( tmFlags & TIMELINE_FCHANGES ){ |
| 1517 | timeline_submenu(&url, "Hide Files", "v", 0, 0); |
| @@ -1525,10 +1557,11 @@ | |
| 1525 | } |
| 1526 | } |
| 1527 | if( P("showsql") ){ |
| 1528 | @ <blockquote>%h(blob_sql_text(&sql))</blockquote> |
| 1529 | } |
| 1530 | blob_zero(&sql); |
| 1531 | db_prepare(&q, "SELECT * FROM timeline ORDER BY sortby DESC /*scan*/"); |
| 1532 | @ <h2>%b(&desc)</h2> |
| 1533 | blob_reset(&desc); |
| 1534 | www_print_timeline(&q, tmFlags, zThisUser, zThisTag, 0); |
| @@ -1617,11 +1650,15 @@ | |
| 1617 | sqlite3_snprintf(sizeof(zPrefix)-n, &zPrefix[n], zBrType); |
| 1618 | n = strlen(zPrefix); |
| 1619 | } |
| 1620 | if( fossil_strcmp(zCurrentUuid,zId)==0 ){ |
| 1621 | sqlite3_snprintf(sizeof(zPrefix)-n, &zPrefix[n], "*CURRENT* "); |
| 1622 | n += strlen(zPrefix); |
| 1623 | } |
| 1624 | zFree = mprintf("[%S] %s%s", zId, zPrefix, zCom); |
| 1625 | /* record another X lines */ |
| 1626 | nLine += comment_print(zFree, zCom, 9, width, g.comFmtFlags); |
| 1627 | fossil_free(zFree); |
| @@ -2362,11 +2399,11 @@ | |
| 2362 | @ <br><div>Total events: %d(nEventTotal) |
| 2363 | @ <br>Average per active %s(zAvgLabel): %d(nAvg) |
| 2364 | @ </div> |
| 2365 | } |
| 2366 | if( !includeMonth ){ |
| 2367 | output_table_sorting_javascript("statsTable","tnx"); |
| 2368 | } |
| 2369 | } |
| 2370 | |
| 2371 | /* |
| 2372 | ** Implements the "byuser" view for /reports. |
| @@ -2413,11 +2450,11 @@ | |
| 2413 | rowClass = ++nRowNumber % 2; |
| 2414 | nEventTotal += nCount; |
| 2415 | @<tr class='row%d(rowClass)'> |
| 2416 | @ <td> |
| 2417 | @ <a href="?view=bymonth&user=%h(zUser)&type=%c((char)statsReportType)">%h(zUser)</a> |
| 2418 | @ </td><td>%d(nCount)</td> |
| 2419 | @ <td> |
| 2420 | @ <div class='statistics-report-graph-line' |
| 2421 | @ style='width:%d(nSize)%%;'> </div> |
| 2422 | @ </td> |
| 2423 | @</tr> |
| @@ -2426,11 +2463,11 @@ | |
| 2426 | use percent-based graph bars. |
| 2427 | */ |
| 2428 | } |
| 2429 | @ </tbody></table> |
| 2430 | db_finalize(&query); |
| 2431 | output_table_sorting_javascript("statsTable","tnx"); |
| 2432 | } |
| 2433 | |
| 2434 | /* |
| 2435 | ** Implements the "byweekday" view for /reports. |
| 2436 | */ |
| @@ -2491,11 +2528,11 @@ | |
| 2491 | @ </td> |
| 2492 | @</tr> |
| 2493 | } |
| 2494 | @ </tbody></table> |
| 2495 | db_finalize(&query); |
| 2496 | output_table_sorting_javascript("statsTable","ntnx"); |
| 2497 | } |
| 2498 | |
| 2499 | |
| 2500 | /* |
| 2501 | ** Helper for stats_report_by_month_year(), which generates a list of |
| @@ -2624,11 +2661,11 @@ | |
| 2624 | int nAvg = iterations ? (total/iterations) : 0; |
| 2625 | cgi_printf("<br><div>Total events: %d<br>" |
| 2626 | "Average per active week: %d</div>", |
| 2627 | total, nAvg); |
| 2628 | } |
| 2629 | output_table_sorting_javascript("statsTable","tnx"); |
| 2630 | } |
| 2631 | } |
| 2632 | |
| 2633 | /* |
| 2634 | ** WEBPAGE: reports |
| 2635 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -20,10 +20,20 @@ | |
| 20 | */ |
| 21 | #include "config.h" |
| 22 | #include <string.h> |
| 23 | #include <time.h> |
| 24 | #include "timeline.h" |
| 25 | |
| 26 | /* |
| 27 | ** Add an appropriate tag to the output if "rid" is unpublished (private) |
| 28 | */ |
| 29 | #define UNPUB_TAG "<em>(unpublished)</em>" |
| 30 | void tag_private_status(int rid){ |
| 31 | if( content_is_private(rid) ){ |
| 32 | cgi_printf("%s", UNPUB_TAG); |
| 33 | } |
| 34 | } |
| 35 | |
| 36 | /* |
| 37 | ** Generate a hyperlink to a version. |
| 38 | */ |
| 39 | void hyperlink_to_uuid(const char *zUuid){ |
| @@ -77,10 +87,11 @@ | |
| 87 | #define TIMELINE_FCHANGES 0x0020 /* Detail file changes */ |
| 88 | #define TIMELINE_BRCOLOR 0x0040 /* Background color by branch name */ |
| 89 | #define TIMELINE_UCOLOR 0x0080 /* Background color by user */ |
| 90 | #define TIMELINE_FRENAMES 0x0100 /* Detail only file name changes */ |
| 91 | #define TIMELINE_UNHIDE 0x0200 /* Unhide check-ins with "hidden" tag */ |
| 92 | #define TIMELINE_SHOWRID 0x0400 /* Show RID values in addition to UUIDs */ |
| 93 | #endif |
| 94 | |
| 95 | /* |
| 96 | ** Hash a string and use the hash to determine a background color. |
| 97 | */ |
| @@ -394,10 +405,13 @@ | |
| 405 | } |
| 406 | }else if( zType[0]=='e' && tagid ){ |
| 407 | hyperlink_to_event_tagid(tagid<0?-tagid:tagid); |
| 408 | }else if( (tmFlags & TIMELINE_ARTID)!=0 ){ |
| 409 | hyperlink_to_uuid(zUuid); |
| 410 | } |
| 411 | if( tmFlags & TIMELINE_SHOWRID ){ |
| 412 | @ (%d(rid)) |
| 413 | } |
| 414 | db_column_blob(pQuery, commentColumn, &comment); |
| 415 | if( zType[0]!='c' ){ |
| 416 | /* Comments for anything other than a check-in are generated by |
| 417 | ** "fossil rebuild" and expect to be rendered as text/x-fossil-wiki */ |
| @@ -417,11 +431,11 @@ | |
| 431 | /* Generate the "user: USERNAME" at the end of the comment, together |
| 432 | ** with a hyperlink to another timeline for that user. |
| 433 | */ |
| 434 | if( zTagList && zTagList[0]==0 ) zTagList = 0; |
| 435 | if( g.perm.Hyperlink && fossil_strcmp(zDispUser, zThisUser)!=0 ){ |
| 436 | char *zLink = mprintf("%R/timeline?u=%h&c=%t&nd&n=200", zDispUser, zDate); |
| 437 | @ (user: %z(href("%z",zLink))%h(zDispUser)</a>%s(zTagList?",":"\051") |
| 438 | }else{ |
| 439 | @ (user: %h(zDispUser)%s(zTagList?",":"\051") |
| 440 | } |
| 441 | |
| @@ -442,11 +456,11 @@ | |
| 456 | while( z && z[0] ){ |
| 457 | for(i=0; z[i] && (z[i]!=',' || z[i+1]!=' '); i++){} |
| 458 | if( zThisTag==0 || memcmp(z, zThisTag, i)!=0 || zThisTag[i]!=0 ){ |
| 459 | blob_appendf(&links, |
| 460 | "%z%#h</a>%.2s", |
| 461 | href("%R/timeline?r=%#t&nd&c=%t&n=200",i,z,zDate), i,z, &z[i] |
| 462 | ); |
| 463 | }else{ |
| 464 | blob_appendf(&links, "%#h", i+2, z); |
| 465 | } |
| 466 | if( z[i]==0 ) break; |
| @@ -456,11 +470,11 @@ | |
| 470 | blob_reset(&links); |
| 471 | }else{ |
| 472 | @ tags: %h(zTagList)) |
| 473 | } |
| 474 | } |
| 475 | tag_private_status(rid); |
| 476 | |
| 477 | /* Generate extra hyperlinks at the end of the comment */ |
| 478 | if( xExtra ){ |
| 479 | xExtra(rid); |
| 480 | } |
| @@ -471,11 +485,11 @@ | |
| 485 | ){ |
| 486 | int inUl = 0; |
| 487 | if( !fchngQueryInit ){ |
| 488 | db_prepare(&fchngQuery, |
| 489 | "SELECT (pid==0) AS isnew," |
| 490 | " fid," |
| 491 | " (SELECT name FROM filename WHERE fnid=mlink.fnid) AS name," |
| 492 | " (SELECT uuid FROM blob WHERE rid=fid)," |
| 493 | " (SELECT uuid FROM blob WHERE rid=pid)," |
| 494 | " (SELECT name FROM filename WHERE fnid=mlink.pfnid) AS oldnm" |
| 495 | " FROM mlink" |
| @@ -488,14 +502,16 @@ | |
| 502 | } |
| 503 | db_bind_int(&fchngQuery, ":mid", rid); |
| 504 | while( db_step(&fchngQuery)==SQLITE_ROW ){ |
| 505 | const char *zFilename = db_column_text(&fchngQuery, 2); |
| 506 | int isNew = db_column_int(&fchngQuery, 0); |
| 507 | int fid = db_column_int(&fchngQuery, 1); |
| 508 | int isDel = fid==0; |
| 509 | const char *zOldName = db_column_text(&fchngQuery, 5); |
| 510 | const char *zOld = db_column_text(&fchngQuery, 4); |
| 511 | const char *zNew = db_column_text(&fchngQuery, 3); |
| 512 | const char *zUnpubTag = ""; |
| 513 | if( !inUl ){ |
| 514 | @ <ul class="filelist"> |
| 515 | inUl = 1; |
| 516 | } |
| 517 | if( (tmFlags & TIMELINE_FRENAMES)!=0 ){ |
| @@ -502,23 +518,26 @@ | |
| 518 | if( !isNew && !isDel && zOldName!=0 ){ |
| 519 | @ <li> %h(zOldName) → %h(zFilename) |
| 520 | } |
| 521 | continue; |
| 522 | } |
| 523 | if( content_is_private(fid) ){ |
| 524 | zUnpubTag = UNPUB_TAG; |
| 525 | } |
| 526 | if( isNew ){ |
| 527 | @ <li> %h(zFilename) %s(zUnpubTag) (new file) |
| 528 | @ %z(href("%R/artifact/%s",zNew))[view]</a></li> |
| 529 | }else if( isDel ){ |
| 530 | @ <li> %h(zFilename) (deleted)</li> |
| 531 | }else if( fossil_strcmp(zOld,zNew)==0 && zOldName!=0 ){ |
| 532 | @ <li> %h(zOldName) → %h(zFilename) %s(zUnpubTag) |
| 533 | @ %z(href("%R/artifact/%s",zNew))[view]</a></li> |
| 534 | }else{ |
| 535 | if( zOldName!=0 ){ |
| 536 | @ <li> %h(zOldName) → %h(zFilename) %s(zUnpubTag) |
| 537 | }else{ |
| 538 | @ <li> %h(zFilename) %s(zUnpubTag) |
| 539 | } |
| 540 | @ %z(href("%R/fdiff?sbs=1&v1=%s&v2=%s",zOld,zNew))[diff]</a></li> |
| 541 | } |
| 542 | } |
| 543 | db_reset(&fchngQuery); |
| @@ -589,12 +608,12 @@ | |
| 608 | ** for the upward portion of a merge arrow. The merge arrow goes up |
| 609 | ** to the row identified by mu:. If this value is zero then |
| 610 | ** node has no merge children and no merge-out line is drawn. |
| 611 | ** mu: The id of the row which is the top of the merge-out arrow. |
| 612 | ** u: Draw a thick child-line out of the top of this node and up to |
| 613 | ** the node with an id equal to this value. 0 if it is straight to |
| 614 | ** the top of the page, -1 if there is no thick-line riser. |
| 615 | ** f: 0x01: a leaf node. |
| 616 | ** au: An array of integers that define thick-line risers for branches. |
| 617 | ** The integers are in pairs. For each pair, the first integer is |
| 618 | ** is the rail on which the riser should run and the second integer |
| 619 | ** is the id of the node upto which the riser should run. |
| @@ -1055,11 +1074,11 @@ | |
| 1074 | const char *zYearMonth = P("ym"); /* Show checkins for the given YYYY-MM */ |
| 1075 | const char *zYearWeek = P("yw"); /* Show checkins for the given YYYY-WW (week-of-year)*/ |
| 1076 | int useDividers = P("nd")==0; /* Show dividers if "nd" is missing */ |
| 1077 | int renameOnly = P("namechng")!=0; /* Show only checkins that rename files */ |
| 1078 | int tagid; /* Tag ID */ |
| 1079 | int tmFlags = 0; /* Timeline flags */ |
| 1080 | const char *zThisTag = 0; /* Suppress links to this tag */ |
| 1081 | const char *zThisUser = 0; /* Suppress links to this user */ |
| 1082 | HQuery url; /* URL for various branch links */ |
| 1083 | int from_rid = name_to_typed_rid(P("from"),"ci"); /* from= for paths */ |
| 1084 | int to_rid = name_to_typed_rid(P("to"),"ci"); /* to= for path timelines */ |
| @@ -1088,16 +1107,22 @@ | |
| 1107 | tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='sym-%q'",zBrName); |
| 1108 | zThisTag = zBrName; |
| 1109 | }else{ |
| 1110 | tagid = 0; |
| 1111 | } |
| 1112 | if( tagid>0 |
| 1113 | && db_int(0,"SELECT count(*) FROM tagxref WHERE tagid=%d",tagid)<=nEntry |
| 1114 | ){ |
| 1115 | zCirca = zBefore = zAfter = 0; |
| 1116 | nEntry = -1; |
| 1117 | } |
| 1118 | if( zType[0]=='a' ){ |
| 1119 | tmFlags |= TIMELINE_BRIEF | TIMELINE_GRAPH; |
| 1120 | }else{ |
| 1121 | tmFlags |= TIMELINE_GRAPH; |
| 1122 | } |
| 1123 | if( nEntry>0 ) url_add_parameter(&url, "n", mprintf("%d", nEntry)); |
| 1124 | if( P("ng")!=0 || zSearch!=0 ){ |
| 1125 | tmFlags &= ~TIMELINE_GRAPH; |
| 1126 | url_add_parameter(&url, "ng", 0); |
| 1127 | } |
| 1128 | if( P("brbg")!=0 ){ |
| @@ -1185,10 +1210,11 @@ | |
| 1210 | }else if( (p_rid || d_rid) && g.perm.Read ){ |
| 1211 | /* If p= or d= is present, ignore all other parameters other than n= */ |
| 1212 | char *zUuid; |
| 1213 | int np, nd; |
| 1214 | |
| 1215 | tmFlags |= TIMELINE_DISJOINT; |
| 1216 | if( p_rid && d_rid ){ |
| 1217 | if( p_rid!=d_rid ) p_rid = d_rid; |
| 1218 | if( P("n")==0 ) nEntry = 10; |
| 1219 | } |
| 1220 | db_multi_exec( |
| @@ -1229,11 +1255,11 @@ | |
| 1255 | url_add_parameter(&url, "d", zUuid); |
| 1256 | } |
| 1257 | if( nEntry>20 ){ |
| 1258 | timeline_submenu(&url, "20 Entries", "n", "20", 0); |
| 1259 | } |
| 1260 | if( nEntry<200 && nEntry>0 ){ |
| 1261 | timeline_submenu(&url, "200 Entries", "n", "200", 0); |
| 1262 | } |
| 1263 | if( tmFlags & TIMELINE_FCHANGES ){ |
| 1264 | timeline_submenu(&url, "Hide Files", "v", 0, 0); |
| 1265 | }else{ |
| @@ -1373,10 +1399,16 @@ | |
| 1399 | }else if( zType[0]=='g' ){ |
| 1400 | zEType = "tag"; |
| 1401 | } |
| 1402 | } |
| 1403 | if( zUser ){ |
| 1404 | int n = db_int(0,"SELECT count(*) FROM event" |
| 1405 | " WHERE user=%Q OR euser=%Q", zUser, zUser); |
| 1406 | if( n<=nEntry ){ |
| 1407 | zCirca = zBefore = zAfter = 0; |
| 1408 | nEntry = -1; |
| 1409 | } |
| 1410 | blob_append_sql(&sql, " AND (event.user=%Q OR event.euser=%Q)", |
| 1411 | zUser, zUser); |
| 1412 | url_add_parameter(&url, "u", zUser); |
| 1413 | zThisUser = zUser; |
| 1414 | } |
| @@ -1394,11 +1426,11 @@ | |
| 1426 | blob_append_sql(&sql, |
| 1427 | " AND event.mtime>=%.17g AND event.mtime<=%.17g" |
| 1428 | " ORDER BY event.mtime ASC", rAfter-ONE_SECOND, rBefore+ONE_SECOND); |
| 1429 | url_add_parameter(&url, "a", zAfter); |
| 1430 | url_add_parameter(&url, "b", zBefore); |
| 1431 | nEntry = -1; |
| 1432 | }else{ |
| 1433 | blob_append_sql(&sql, |
| 1434 | " AND event.mtime>=%.17g ORDER BY event.mtime ASC", |
| 1435 | rAfter-ONE_SECOND); |
| 1436 | url_add_parameter(&url, "a", zAfter); |
| @@ -1425,19 +1457,19 @@ | |
| 1457 | if( useDividers ) timeline_add_dividers(rCirca, 0); |
| 1458 | url_add_parameter(&url, "c", zCirca); |
| 1459 | }else{ |
| 1460 | blob_append_sql(&sql, " ORDER BY event.mtime DESC"); |
| 1461 | } |
| 1462 | if( nEntry>0 ) blob_append_sql(&sql, " LIMIT %d", nEntry); |
| 1463 | db_multi_exec("%s", blob_sql_text(&sql)); |
| 1464 | |
| 1465 | n = db_int(0, "SELECT count(*) FROM timeline WHERE etype!='div' /*scan*/"); |
| 1466 | if( zYearMonth ){ |
| 1467 | blob_appendf(&desc, "%s events for %h", zEType, zYearMonth); |
| 1468 | }else if( zYearWeek ){ |
| 1469 | blob_appendf(&desc, "%s events for year/week %h", zEType, zYearWeek); |
| 1470 | }else if( zAfter==0 && zBefore==0 && zCirca==0 && n>=nEntry && nEntry>0 ){ |
| 1471 | blob_appendf(&desc, "%d most recent %ss", n, zEType); |
| 1472 | }else{ |
| 1473 | blob_appendf(&desc, "%d %ss", n, zEType); |
| 1474 | } |
| 1475 | if( zUses ){ |
| @@ -1484,11 +1516,11 @@ | |
| 1516 | } |
| 1517 | if( zBefore || (zAfter && n==nEntry) ){ |
| 1518 | zDate = db_text(0, "SELECT max(timestamp) FROM timeline /*scan*/"); |
| 1519 | timeline_submenu(&url, "Newer", "a", zDate, "b"); |
| 1520 | free(zDate); |
| 1521 | }else if( tagid==0 && zUses==0 ){ |
| 1522 | if( zType[0]!='a' ){ |
| 1523 | timeline_submenu(&url, "All Types", "y", "all", 0); |
| 1524 | } |
| 1525 | if( zType[0]!='w' && g.perm.RdWiki ){ |
| 1526 | timeline_submenu(&url, "Wiki Only", "y", "w", 0); |
| @@ -1507,11 +1539,11 @@ | |
| 1539 | } |
| 1540 | } |
| 1541 | if( nEntry>20 ){ |
| 1542 | timeline_submenu(&url, "20 Entries", "n", "20", 0); |
| 1543 | } |
| 1544 | if( nEntry<200 && nEntry>0 ){ |
| 1545 | timeline_submenu(&url, "200 Entries", "n", "200", 0); |
| 1546 | } |
| 1547 | if( zType[0]=='a' || zType[0]=='c' ){ |
| 1548 | if( tmFlags & TIMELINE_FCHANGES ){ |
| 1549 | timeline_submenu(&url, "Hide Files", "v", 0, 0); |
| @@ -1525,10 +1557,11 @@ | |
| 1557 | } |
| 1558 | } |
| 1559 | if( P("showsql") ){ |
| 1560 | @ <blockquote>%h(blob_sql_text(&sql))</blockquote> |
| 1561 | } |
| 1562 | if( P("showrid") ) tmFlags |= TIMELINE_SHOWRID; |
| 1563 | blob_zero(&sql); |
| 1564 | db_prepare(&q, "SELECT * FROM timeline ORDER BY sortby DESC /*scan*/"); |
| 1565 | @ <h2>%b(&desc)</h2> |
| 1566 | blob_reset(&desc); |
| 1567 | www_print_timeline(&q, tmFlags, zThisUser, zThisTag, 0); |
| @@ -1617,11 +1650,15 @@ | |
| 1650 | sqlite3_snprintf(sizeof(zPrefix)-n, &zPrefix[n], zBrType); |
| 1651 | n = strlen(zPrefix); |
| 1652 | } |
| 1653 | if( fossil_strcmp(zCurrentUuid,zId)==0 ){ |
| 1654 | sqlite3_snprintf(sizeof(zPrefix)-n, &zPrefix[n], "*CURRENT* "); |
| 1655 | n += strlen(zPrefix+n); |
| 1656 | } |
| 1657 | if( content_is_private(rid) ){ |
| 1658 | sqlite3_snprintf(sizeof(zPrefix)-n, &zPrefix[n], "*UNPUBLISHED* "); |
| 1659 | n += strlen(zPrefix+n); |
| 1660 | } |
| 1661 | zFree = mprintf("[%S] %s%s", zId, zPrefix, zCom); |
| 1662 | /* record another X lines */ |
| 1663 | nLine += comment_print(zFree, zCom, 9, width, g.comFmtFlags); |
| 1664 | fossil_free(zFree); |
| @@ -2362,11 +2399,11 @@ | |
| 2399 | @ <br><div>Total events: %d(nEventTotal) |
| 2400 | @ <br>Average per active %s(zAvgLabel): %d(nAvg) |
| 2401 | @ </div> |
| 2402 | } |
| 2403 | if( !includeMonth ){ |
| 2404 | output_table_sorting_javascript("statsTable","tnx",-1); |
| 2405 | } |
| 2406 | } |
| 2407 | |
| 2408 | /* |
| 2409 | ** Implements the "byuser" view for /reports. |
| @@ -2413,11 +2450,11 @@ | |
| 2450 | rowClass = ++nRowNumber % 2; |
| 2451 | nEventTotal += nCount; |
| 2452 | @<tr class='row%d(rowClass)'> |
| 2453 | @ <td> |
| 2454 | @ <a href="?view=bymonth&user=%h(zUser)&type=%c((char)statsReportType)">%h(zUser)</a> |
| 2455 | @ </td><td data-sortkey='%08x(-nCount)'>%d(nCount)</td> |
| 2456 | @ <td> |
| 2457 | @ <div class='statistics-report-graph-line' |
| 2458 | @ style='width:%d(nSize)%%;'> </div> |
| 2459 | @ </td> |
| 2460 | @</tr> |
| @@ -2426,11 +2463,11 @@ | |
| 2463 | use percent-based graph bars. |
| 2464 | */ |
| 2465 | } |
| 2466 | @ </tbody></table> |
| 2467 | db_finalize(&query); |
| 2468 | output_table_sorting_javascript("statsTable","tkx",2); |
| 2469 | } |
| 2470 | |
| 2471 | /* |
| 2472 | ** Implements the "byweekday" view for /reports. |
| 2473 | */ |
| @@ -2491,11 +2528,11 @@ | |
| 2528 | @ </td> |
| 2529 | @</tr> |
| 2530 | } |
| 2531 | @ </tbody></table> |
| 2532 | db_finalize(&query); |
| 2533 | output_table_sorting_javascript("statsTable","ntnx",1); |
| 2534 | } |
| 2535 | |
| 2536 | |
| 2537 | /* |
| 2538 | ** Helper for stats_report_by_month_year(), which generates a list of |
| @@ -2624,11 +2661,11 @@ | |
| 2661 | int nAvg = iterations ? (total/iterations) : 0; |
| 2662 | cgi_printf("<br><div>Total events: %d<br>" |
| 2663 | "Average per active week: %d</div>", |
| 2664 | total, nAvg); |
| 2665 | } |
| 2666 | output_table_sorting_javascript("statsTable","tnx",-1); |
| 2667 | } |
| 2668 | } |
| 2669 | |
| 2670 | /* |
| 2671 | ** WEBPAGE: reports |
| 2672 |
+1
-3
| --- src/undo.c | ||
| +++ src/undo.c | ||
| @@ -127,11 +127,10 @@ | ||
| 127 | 127 | ** Undo or redo all undoable or redoable changes. |
| 128 | 128 | */ |
| 129 | 129 | static void undo_all(int redoFlag){ |
| 130 | 130 | int ucid; |
| 131 | 131 | int ncid; |
| 132 | - const char *zDb = db_name("localdb"); | |
| 133 | 132 | undo_all_filesystem(redoFlag); |
| 134 | 133 | db_multi_exec( |
| 135 | 134 | "CREATE TEMP TABLE undo_vfile_2 AS SELECT * FROM vfile;" |
| 136 | 135 | "DELETE FROM vfile;" |
| 137 | 136 | "INSERT INTO vfile SELECT * FROM undo_vfile;" |
| @@ -143,12 +142,11 @@ | ||
| 143 | 142 | "INSERT INTO vmerge SELECT * FROM undo_vmerge;" |
| 144 | 143 | "DELETE FROM undo_vmerge;" |
| 145 | 144 | "INSERT INTO undo_vmerge SELECT * FROM undo_vmerge_2;" |
| 146 | 145 | "DROP TABLE undo_vmerge_2;" |
| 147 | 146 | ); |
| 148 | - if(db_exists("SELECT 1 FROM \"%w\".sqlite_master" | |
| 149 | - " WHERE name='undo_stash'", zDb) ){ | |
| 147 | + if( db_table_exists("localdb", "undo_stash") ){ | |
| 150 | 148 | if( redoFlag ){ |
| 151 | 149 | db_multi_exec( |
| 152 | 150 | "DELETE FROM stash WHERE stashid IN (SELECT stashid FROM undo_stash);" |
| 153 | 151 | "DELETE FROM stashfile" |
| 154 | 152 | " WHERE stashid NOT IN (SELECT stashid FROM stash);" |
| 155 | 153 |
| --- src/undo.c | |
| +++ src/undo.c | |
| @@ -127,11 +127,10 @@ | |
| 127 | ** Undo or redo all undoable or redoable changes. |
| 128 | */ |
| 129 | static void undo_all(int redoFlag){ |
| 130 | int ucid; |
| 131 | int ncid; |
| 132 | const char *zDb = db_name("localdb"); |
| 133 | undo_all_filesystem(redoFlag); |
| 134 | db_multi_exec( |
| 135 | "CREATE TEMP TABLE undo_vfile_2 AS SELECT * FROM vfile;" |
| 136 | "DELETE FROM vfile;" |
| 137 | "INSERT INTO vfile SELECT * FROM undo_vfile;" |
| @@ -143,12 +142,11 @@ | |
| 143 | "INSERT INTO vmerge SELECT * FROM undo_vmerge;" |
| 144 | "DELETE FROM undo_vmerge;" |
| 145 | "INSERT INTO undo_vmerge SELECT * FROM undo_vmerge_2;" |
| 146 | "DROP TABLE undo_vmerge_2;" |
| 147 | ); |
| 148 | if(db_exists("SELECT 1 FROM \"%w\".sqlite_master" |
| 149 | " WHERE name='undo_stash'", zDb) ){ |
| 150 | if( redoFlag ){ |
| 151 | db_multi_exec( |
| 152 | "DELETE FROM stash WHERE stashid IN (SELECT stashid FROM undo_stash);" |
| 153 | "DELETE FROM stashfile" |
| 154 | " WHERE stashid NOT IN (SELECT stashid FROM stash);" |
| 155 |
| --- src/undo.c | |
| +++ src/undo.c | |
| @@ -127,11 +127,10 @@ | |
| 127 | ** Undo or redo all undoable or redoable changes. |
| 128 | */ |
| 129 | static void undo_all(int redoFlag){ |
| 130 | int ucid; |
| 131 | int ncid; |
| 132 | undo_all_filesystem(redoFlag); |
| 133 | db_multi_exec( |
| 134 | "CREATE TEMP TABLE undo_vfile_2 AS SELECT * FROM vfile;" |
| 135 | "DELETE FROM vfile;" |
| 136 | "INSERT INTO vfile SELECT * FROM undo_vfile;" |
| @@ -143,12 +142,11 @@ | |
| 142 | "INSERT INTO vmerge SELECT * FROM undo_vmerge;" |
| 143 | "DELETE FROM undo_vmerge;" |
| 144 | "INSERT INTO undo_vmerge SELECT * FROM undo_vmerge_2;" |
| 145 | "DROP TABLE undo_vmerge_2;" |
| 146 | ); |
| 147 | if( db_table_exists("localdb", "undo_stash") ){ |
| 148 | if( redoFlag ){ |
| 149 | db_multi_exec( |
| 150 | "DELETE FROM stash WHERE stashid IN (SELECT stashid FROM undo_stash);" |
| 151 | "DELETE FROM stashfile" |
| 152 | " WHERE stashid NOT IN (SELECT stashid FROM stash);" |
| 153 |
+1
-1
| --- src/xfer.c | ||
| +++ src/xfer.c | ||
| @@ -532,11 +532,11 @@ | ||
| 532 | 532 | ** private artifacts if we are not doing a private transfer. |
| 533 | 533 | */ |
| 534 | 534 | static void request_phantoms(Xfer *pXfer, int maxReq){ |
| 535 | 535 | Stmt q; |
| 536 | 536 | db_prepare(&q, |
| 537 | - "SELECT uuid FROM phantom JOIN blob USING(rid)" | |
| 537 | + "SELECT uuid FROM phantom CROSS JOIN blob USING(rid) /*scan*/" | |
| 538 | 538 | " WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid) %s", |
| 539 | 539 | (pXfer->syncPrivate ? "" : |
| 540 | 540 | " AND NOT EXISTS(SELECT 1 FROM private WHERE rid=blob.rid)") |
| 541 | 541 | ); |
| 542 | 542 | while( db_step(&q)==SQLITE_ROW && maxReq-- > 0 ){ |
| 543 | 543 |
| --- src/xfer.c | |
| +++ src/xfer.c | |
| @@ -532,11 +532,11 @@ | |
| 532 | ** private artifacts if we are not doing a private transfer. |
| 533 | */ |
| 534 | static void request_phantoms(Xfer *pXfer, int maxReq){ |
| 535 | Stmt q; |
| 536 | db_prepare(&q, |
| 537 | "SELECT uuid FROM phantom JOIN blob USING(rid)" |
| 538 | " WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid) %s", |
| 539 | (pXfer->syncPrivate ? "" : |
| 540 | " AND NOT EXISTS(SELECT 1 FROM private WHERE rid=blob.rid)") |
| 541 | ); |
| 542 | while( db_step(&q)==SQLITE_ROW && maxReq-- > 0 ){ |
| 543 |
| --- src/xfer.c | |
| +++ src/xfer.c | |
| @@ -532,11 +532,11 @@ | |
| 532 | ** private artifacts if we are not doing a private transfer. |
| 533 | */ |
| 534 | static void request_phantoms(Xfer *pXfer, int maxReq){ |
| 535 | Stmt q; |
| 536 | db_prepare(&q, |
| 537 | "SELECT uuid FROM phantom CROSS JOIN blob USING(rid) /*scan*/" |
| 538 | " WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid) %s", |
| 539 | (pXfer->syncPrivate ? "" : |
| 540 | " AND NOT EXISTS(SELECT 1 FROM private WHERE rid=blob.rid)") |
| 541 | ); |
| 542 | while( db_step(&q)==SQLITE_ROW && maxReq-- > 0 ){ |
| 543 |
+2
-2
| --- test/valgrind-www.tcl | ||
| +++ test/valgrind-www.tcl | ||
| @@ -1,10 +1,10 @@ | ||
| 1 | 1 | #!/usr/bin/tclsh |
| 2 | 2 | # |
| 3 | -# Run this script in an open Fossil checkout at the top-level with a | |
| 3 | +# Run this script in an open Fossil checkout at the top-level with a | |
| 4 | 4 | # fresh build of Fossil itself. This script will run fossil on hundreds |
| 5 | -# of different web-pages looking for memory allocation problems using | |
| 5 | +# of different web-pages looking for memory allocation problems using | |
| 6 | 6 | # valgrind. Valgrind output appears on stderr. Suggested test scenario: |
| 7 | 7 | # |
| 8 | 8 | # make |
| 9 | 9 | # tclsh valgrind-www.tcl 2>&1 | tee valgrind-out.txt |
| 10 | 10 | # |
| 11 | 11 |
| --- test/valgrind-www.tcl | |
| +++ test/valgrind-www.tcl | |
| @@ -1,10 +1,10 @@ | |
| 1 | #!/usr/bin/tclsh |
| 2 | # |
| 3 | # Run this script in an open Fossil checkout at the top-level with a |
| 4 | # fresh build of Fossil itself. This script will run fossil on hundreds |
| 5 | # of different web-pages looking for memory allocation problems using |
| 6 | # valgrind. Valgrind output appears on stderr. Suggested test scenario: |
| 7 | # |
| 8 | # make |
| 9 | # tclsh valgrind-www.tcl 2>&1 | tee valgrind-out.txt |
| 10 | # |
| 11 |
| --- test/valgrind-www.tcl | |
| +++ test/valgrind-www.tcl | |
| @@ -1,10 +1,10 @@ | |
| 1 | #!/usr/bin/tclsh |
| 2 | # |
| 3 | # Run this script in an open Fossil checkout at the top-level with a |
| 4 | # fresh build of Fossil itself. This script will run fossil on hundreds |
| 5 | # of different web-pages looking for memory allocation problems using |
| 6 | # valgrind. Valgrind output appears on stderr. Suggested test scenario: |
| 7 | # |
| 8 | # make |
| 9 | # tclsh valgrind-www.tcl 2>&1 | tee valgrind-out.txt |
| 10 | # |
| 11 |
+4
-4
| --- tools/fossil_chat.tcl | ||
| +++ tools/fossil_chat.tcl | ||
| @@ -84,11 +84,11 @@ | ||
| 84 | 84 | catch {close $SOCKET} |
| 85 | 85 | if {[catch { |
| 86 | 86 | if {$::PROXYHOST ne {}} { |
| 87 | 87 | set SOCKET [socket $::PROXYHOST $::PROXYPORT] |
| 88 | 88 | puts $SOCKET "CONNECT $::SERVERHOST:$::SERVERPORT HTTP/1.1" |
| 89 | - puts $SOCKET "Host: $::SERVERHOST:$::SERVERPORT" | |
| 89 | + puts $SOCKET "Host: $::SERVERHOST:$::SERVERPORT" | |
| 90 | 90 | puts $SOCKET "" |
| 91 | 91 | } else { |
| 92 | 92 | set SOCKET [socket $::SERVERHOST $::SERVERPORT] |
| 93 | 93 | } |
| 94 | 94 | fconfigure $SOCKET -translation binary -blocking 0 |
| @@ -142,11 +142,11 @@ | ||
| 142 | 142 | # |
| 143 | 143 | proc delete_files {} { |
| 144 | 144 | global FILES |
| 145 | 145 | .mb.files delete 3 end |
| 146 | 146 | array unset FILES |
| 147 | - .mb.files entryconfigure 1 -state disabled | |
| 147 | + .mb.files entryconfigure 1 -state disabled | |
| 148 | 148 | } |
| 149 | 149 | |
| 150 | 150 | # Prompt the user to select a file from the disk. Then send that |
| 151 | 151 | # file to all chat participants. |
| 152 | 152 | # |
| @@ -188,11 +188,11 @@ | ||
| 188 | 188 | if {![info exists prior] || $filename!=$prior} { |
| 189 | 189 | .mb.files add command -label "Save \"$filename\"" \ |
| 190 | 190 | -command [list save_file $filename] |
| 191 | 191 | } |
| 192 | 192 | set FILES($filename) $data |
| 193 | - .mb.files entryconfigure 1 -state active | |
| 193 | + .mb.files entryconfigure 1 -state active | |
| 194 | 194 | set time [clock format [clock seconds] -format {%H:%M} -gmt 1] |
| 195 | 195 | .msg.t insert end "\[$time $from\] " meta "File: \"$filename\"\n" norm |
| 196 | 196 | .msg.t see end |
| 197 | 197 | } |
| 198 | 198 | |
| @@ -232,11 +232,11 @@ | ||
| 232 | 232 | } elseif {$cmd=="file"} { |
| 233 | 233 | if {[info commands handle_file]=="handle_file"} { |
| 234 | 234 | handle_file [lindex $line 1] [lindex $line 2] [lindex $line 3] |
| 235 | 235 | } |
| 236 | 236 | } |
| 237 | -} | |
| 237 | +} | |
| 238 | 238 | |
| 239 | 239 | # Handle a broken socket connection |
| 240 | 240 | # |
| 241 | 241 | proc disconnect {} { |
| 242 | 242 | global SOCKET |
| 243 | 243 |
| --- tools/fossil_chat.tcl | |
| +++ tools/fossil_chat.tcl | |
| @@ -84,11 +84,11 @@ | |
| 84 | catch {close $SOCKET} |
| 85 | if {[catch { |
| 86 | if {$::PROXYHOST ne {}} { |
| 87 | set SOCKET [socket $::PROXYHOST $::PROXYPORT] |
| 88 | puts $SOCKET "CONNECT $::SERVERHOST:$::SERVERPORT HTTP/1.1" |
| 89 | puts $SOCKET "Host: $::SERVERHOST:$::SERVERPORT" |
| 90 | puts $SOCKET "" |
| 91 | } else { |
| 92 | set SOCKET [socket $::SERVERHOST $::SERVERPORT] |
| 93 | } |
| 94 | fconfigure $SOCKET -translation binary -blocking 0 |
| @@ -142,11 +142,11 @@ | |
| 142 | # |
| 143 | proc delete_files {} { |
| 144 | global FILES |
| 145 | .mb.files delete 3 end |
| 146 | array unset FILES |
| 147 | .mb.files entryconfigure 1 -state disabled |
| 148 | } |
| 149 | |
| 150 | # Prompt the user to select a file from the disk. Then send that |
| 151 | # file to all chat participants. |
| 152 | # |
| @@ -188,11 +188,11 @@ | |
| 188 | if {![info exists prior] || $filename!=$prior} { |
| 189 | .mb.files add command -label "Save \"$filename\"" \ |
| 190 | -command [list save_file $filename] |
| 191 | } |
| 192 | set FILES($filename) $data |
| 193 | .mb.files entryconfigure 1 -state active |
| 194 | set time [clock format [clock seconds] -format {%H:%M} -gmt 1] |
| 195 | .msg.t insert end "\[$time $from\] " meta "File: \"$filename\"\n" norm |
| 196 | .msg.t see end |
| 197 | } |
| 198 | |
| @@ -232,11 +232,11 @@ | |
| 232 | } elseif {$cmd=="file"} { |
| 233 | if {[info commands handle_file]=="handle_file"} { |
| 234 | handle_file [lindex $line 1] [lindex $line 2] [lindex $line 3] |
| 235 | } |
| 236 | } |
| 237 | } |
| 238 | |
| 239 | # Handle a broken socket connection |
| 240 | # |
| 241 | proc disconnect {} { |
| 242 | global SOCKET |
| 243 |
| --- tools/fossil_chat.tcl | |
| +++ tools/fossil_chat.tcl | |
| @@ -84,11 +84,11 @@ | |
| 84 | catch {close $SOCKET} |
| 85 | if {[catch { |
| 86 | if {$::PROXYHOST ne {}} { |
| 87 | set SOCKET [socket $::PROXYHOST $::PROXYPORT] |
| 88 | puts $SOCKET "CONNECT $::SERVERHOST:$::SERVERPORT HTTP/1.1" |
| 89 | puts $SOCKET "Host: $::SERVERHOST:$::SERVERPORT" |
| 90 | puts $SOCKET "" |
| 91 | } else { |
| 92 | set SOCKET [socket $::SERVERHOST $::SERVERPORT] |
| 93 | } |
| 94 | fconfigure $SOCKET -translation binary -blocking 0 |
| @@ -142,11 +142,11 @@ | |
| 142 | # |
| 143 | proc delete_files {} { |
| 144 | global FILES |
| 145 | .mb.files delete 3 end |
| 146 | array unset FILES |
| 147 | .mb.files entryconfigure 1 -state disabled |
| 148 | } |
| 149 | |
| 150 | # Prompt the user to select a file from the disk. Then send that |
| 151 | # file to all chat participants. |
| 152 | # |
| @@ -188,11 +188,11 @@ | |
| 188 | if {![info exists prior] || $filename!=$prior} { |
| 189 | .mb.files add command -label "Save \"$filename\"" \ |
| 190 | -command [list save_file $filename] |
| 191 | } |
| 192 | set FILES($filename) $data |
| 193 | .mb.files entryconfigure 1 -state active |
| 194 | set time [clock format [clock seconds] -format {%H:%M} -gmt 1] |
| 195 | .msg.t insert end "\[$time $from\] " meta "File: \"$filename\"\n" norm |
| 196 | .msg.t see end |
| 197 | } |
| 198 | |
| @@ -232,11 +232,11 @@ | |
| 232 | } elseif {$cmd=="file"} { |
| 233 | if {[info commands handle_file]=="handle_file"} { |
| 234 | handle_file [lindex $line 1] [lindex $line 2] [lindex $line 3] |
| 235 | } |
| 236 | } |
| 237 | } |
| 238 | |
| 239 | # Handle a broken socket connection |
| 240 | # |
| 241 | proc disconnect {} { |
| 242 | global SOCKET |
| 243 |
+28
-4
| --- win/Makefile.dmc | ||
| +++ win/Makefile.dmc | ||
| @@ -28,13 +28,13 @@ | ||
| 28 | 28 | |
| 29 | 29 | SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_OMIT_DEPRECATED -DSQLITE_ENABLE_EXPLAIN_COMMENTS |
| 30 | 30 | |
| 31 | 31 | SHELL_OPTIONS = -Dmain=sqlite3_shell -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 | -SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.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 doc_.c encode_.c event_.c export_.c file_.c finfo_.c foci_.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 pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c regexp_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.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 | |
| 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 doc_.c encode_.c event_.c export_.c file_.c finfo_.c foci_.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 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 style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.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 | -OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\builtin$O $(OBJDIR)\cache$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\fusefs$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\loadctrl$O $(OBJDIR)\login$O $(OBJDIR)\lookslike$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winfile$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O | |
| 35 | +OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\builtin$O $(OBJDIR)\bundle$O $(OBJDIR)\cache$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\fusefs$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\loadctrl$O $(OBJDIR)\login$O $(OBJDIR)\lookslike$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\publish$O $(OBJDIR)\purge$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\sitemap$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winfile$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O | |
| 36 | 36 | |
| 37 | 37 | |
| 38 | 38 | RC=$(DMDIR)\bin\rcc |
| 39 | 39 | RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__ |
| 40 | 40 | |
| @@ -49,11 +49,11 @@ | ||
| 49 | 49 | |
| 50 | 50 | $(OBJDIR)\fossil.res: $B\win\fossil.rc |
| 51 | 51 | $(RC) $(RCFLAGS) -o$@ $** |
| 52 | 52 | |
| 53 | 53 | $(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res |
| 54 | - +echo add allrepo attach bag bisect blob branch browse builtin cache captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo foci fusefs glob graph gzip http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_status json_tag json_timeline json_user json_wiki leaf loadctrl login lookslike main manifest markdown markdown_html md5 merge merge3 moderate name path pivot popen pqueue printf rebuild regexp report rss schema search setup sha1 shun skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo unicode update url user utf8 util verify vfile wiki wikiformat winfile winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@ | |
| 54 | + +echo add allrepo attach bag bisect blob branch browse builtin bundle cache captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo foci fusefs glob graph gzip http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_status json_tag json_timeline json_user json_wiki leaf loadctrl login lookslike main manifest markdown markdown_html md5 merge merge3 moderate name path pivot popen pqueue printf publish purge rebuild regexp report rss schema search setup sha1 shun sitemap skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo unicode update url user utf8 util verify vfile wiki wikiformat winfile winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@ | |
| 55 | 55 | +echo fossil >> $@ |
| 56 | 56 | +echo fossil >> $@ |
| 57 | 57 | +echo $(LIBS) >> $@ |
| 58 | 58 | +echo. >> $@ |
| 59 | 59 | +echo fossil >> $@ |
| @@ -176,10 +176,16 @@ | ||
| 176 | 176 | $(OBJDIR)\builtin$O : builtin_.c builtin.h |
| 177 | 177 | $(TCC) -o$@ -c builtin_.c |
| 178 | 178 | |
| 179 | 179 | builtin_.c : $(SRCDIR)\builtin.c |
| 180 | 180 | +translate$E $** > $@ |
| 181 | + | |
| 182 | +$(OBJDIR)\bundle$O : bundle_.c bundle.h | |
| 183 | + $(TCC) -o$@ -c bundle_.c | |
| 184 | + | |
| 185 | +bundle_.c : $(SRCDIR)\bundle.c | |
| 186 | + +translate$E $** > $@ | |
| 181 | 187 | |
| 182 | 188 | $(OBJDIR)\cache$O : cache_.c cache.h |
| 183 | 189 | $(TCC) -o$@ -c cache_.c |
| 184 | 190 | |
| 185 | 191 | cache_.c : $(SRCDIR)\cache.c |
| @@ -572,10 +578,22 @@ | ||
| 572 | 578 | $(OBJDIR)\printf$O : printf_.c printf.h |
| 573 | 579 | $(TCC) -o$@ -c printf_.c |
| 574 | 580 | |
| 575 | 581 | printf_.c : $(SRCDIR)\printf.c |
| 576 | 582 | +translate$E $** > $@ |
| 583 | + | |
| 584 | +$(OBJDIR)\publish$O : publish_.c publish.h | |
| 585 | + $(TCC) -o$@ -c publish_.c | |
| 586 | + | |
| 587 | +publish_.c : $(SRCDIR)\publish.c | |
| 588 | + +translate$E $** > $@ | |
| 589 | + | |
| 590 | +$(OBJDIR)\purge$O : purge_.c purge.h | |
| 591 | + $(TCC) -o$@ -c purge_.c | |
| 592 | + | |
| 593 | +purge_.c : $(SRCDIR)\purge.c | |
| 594 | + +translate$E $** > $@ | |
| 577 | 595 | |
| 578 | 596 | $(OBJDIR)\rebuild$O : rebuild_.c rebuild.h |
| 579 | 597 | $(TCC) -o$@ -c rebuild_.c |
| 580 | 598 | |
| 581 | 599 | rebuild_.c : $(SRCDIR)\rebuild.c |
| @@ -626,10 +644,16 @@ | ||
| 626 | 644 | $(OBJDIR)\shun$O : shun_.c shun.h |
| 627 | 645 | $(TCC) -o$@ -c shun_.c |
| 628 | 646 | |
| 629 | 647 | shun_.c : $(SRCDIR)\shun.c |
| 630 | 648 | +translate$E $** > $@ |
| 649 | + | |
| 650 | +$(OBJDIR)\sitemap$O : sitemap_.c sitemap.h | |
| 651 | + $(TCC) -o$@ -c sitemap_.c | |
| 652 | + | |
| 653 | +sitemap_.c : $(SRCDIR)\sitemap.c | |
| 654 | + +translate$E $** > $@ | |
| 631 | 655 | |
| 632 | 656 | $(OBJDIR)\skins$O : skins_.c skins.h |
| 633 | 657 | $(TCC) -o$@ -c skins_.c |
| 634 | 658 | |
| 635 | 659 | skins_.c : $(SRCDIR)\skins.c |
| @@ -802,7 +826,7 @@ | ||
| 802 | 826 | |
| 803 | 827 | zip_.c : $(SRCDIR)\zip.c |
| 804 | 828 | +translate$E $** > $@ |
| 805 | 829 | |
| 806 | 830 | headers: makeheaders$E page_index.h builtin_data.h VERSION.h |
| 807 | - +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h builtin_.c:builtin.h cache_.c:cache.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h foci_.c:foci.h fusefs_.c:fusefs.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_status_.c:json_status.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h loadctrl_.c:loadctrl.h login_.c:login.h lookslike_.c:lookslike.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h regexp_.c:regexp.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h unicode_.c:unicode.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h util_.c:util.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winfile_.c:winfile.h winhttp_.c:winhttp.h wysiwyg_.c:wysiwyg.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h | |
| 831 | + +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h builtin_.c:builtin.h bundle_.c:bundle.h cache_.c:cache.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h foci_.c:foci.h fusefs_.c:fusefs.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_status_.c:json_status.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h loadctrl_.c:loadctrl.h login_.c:login.h lookslike_.c:lookslike.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h publish_.c:publish.h purge_.c:purge.h rebuild_.c:rebuild.h regexp_.c:regexp.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h sitemap_.c:sitemap.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h unicode_.c:unicode.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h util_.c:util.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winfile_.c:winfile.h winhttp_.c:winhttp.h wysiwyg_.c:wysiwyg.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h | |
| 808 | 832 | @copy /Y nul: headers |
| 809 | 833 |
| --- win/Makefile.dmc | |
| +++ win/Makefile.dmc | |
| @@ -28,13 +28,13 @@ | |
| 28 | |
| 29 | SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_OMIT_DEPRECATED -DSQLITE_ENABLE_EXPLAIN_COMMENTS |
| 30 | |
| 31 | SHELL_OPTIONS = -Dmain=sqlite3_shell -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 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 doc_.c encode_.c event_.c export_.c file_.c finfo_.c foci_.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 pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c regexp_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.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 | OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\builtin$O $(OBJDIR)\cache$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\fusefs$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\loadctrl$O $(OBJDIR)\login$O $(OBJDIR)\lookslike$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winfile$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O |
| 36 | |
| 37 | |
| 38 | RC=$(DMDIR)\bin\rcc |
| 39 | RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__ |
| 40 | |
| @@ -49,11 +49,11 @@ | |
| 49 | |
| 50 | $(OBJDIR)\fossil.res: $B\win\fossil.rc |
| 51 | $(RC) $(RCFLAGS) -o$@ $** |
| 52 | |
| 53 | $(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res |
| 54 | +echo add allrepo attach bag bisect blob branch browse builtin cache captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo foci fusefs glob graph gzip http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_status json_tag json_timeline json_user json_wiki leaf loadctrl login lookslike main manifest markdown markdown_html md5 merge merge3 moderate name path pivot popen pqueue printf rebuild regexp report rss schema search setup sha1 shun skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo unicode update url user utf8 util verify vfile wiki wikiformat winfile winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@ |
| 55 | +echo fossil >> $@ |
| 56 | +echo fossil >> $@ |
| 57 | +echo $(LIBS) >> $@ |
| 58 | +echo. >> $@ |
| 59 | +echo fossil >> $@ |
| @@ -176,10 +176,16 @@ | |
| 176 | $(OBJDIR)\builtin$O : builtin_.c builtin.h |
| 177 | $(TCC) -o$@ -c builtin_.c |
| 178 | |
| 179 | builtin_.c : $(SRCDIR)\builtin.c |
| 180 | +translate$E $** > $@ |
| 181 | |
| 182 | $(OBJDIR)\cache$O : cache_.c cache.h |
| 183 | $(TCC) -o$@ -c cache_.c |
| 184 | |
| 185 | cache_.c : $(SRCDIR)\cache.c |
| @@ -572,10 +578,22 @@ | |
| 572 | $(OBJDIR)\printf$O : printf_.c printf.h |
| 573 | $(TCC) -o$@ -c printf_.c |
| 574 | |
| 575 | printf_.c : $(SRCDIR)\printf.c |
| 576 | +translate$E $** > $@ |
| 577 | |
| 578 | $(OBJDIR)\rebuild$O : rebuild_.c rebuild.h |
| 579 | $(TCC) -o$@ -c rebuild_.c |
| 580 | |
| 581 | rebuild_.c : $(SRCDIR)\rebuild.c |
| @@ -626,10 +644,16 @@ | |
| 626 | $(OBJDIR)\shun$O : shun_.c shun.h |
| 627 | $(TCC) -o$@ -c shun_.c |
| 628 | |
| 629 | shun_.c : $(SRCDIR)\shun.c |
| 630 | +translate$E $** > $@ |
| 631 | |
| 632 | $(OBJDIR)\skins$O : skins_.c skins.h |
| 633 | $(TCC) -o$@ -c skins_.c |
| 634 | |
| 635 | skins_.c : $(SRCDIR)\skins.c |
| @@ -802,7 +826,7 @@ | |
| 802 | |
| 803 | zip_.c : $(SRCDIR)\zip.c |
| 804 | +translate$E $** > $@ |
| 805 | |
| 806 | headers: makeheaders$E page_index.h builtin_data.h VERSION.h |
| 807 | +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h builtin_.c:builtin.h cache_.c:cache.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h foci_.c:foci.h fusefs_.c:fusefs.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_status_.c:json_status.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h loadctrl_.c:loadctrl.h login_.c:login.h lookslike_.c:lookslike.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h regexp_.c:regexp.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h unicode_.c:unicode.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h util_.c:util.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winfile_.c:winfile.h winhttp_.c:winhttp.h wysiwyg_.c:wysiwyg.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h |
| 808 | @copy /Y nul: headers |
| 809 |
| --- win/Makefile.dmc | |
| +++ win/Makefile.dmc | |
| @@ -28,13 +28,13 @@ | |
| 28 | |
| 29 | SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_OMIT_DEPRECATED -DSQLITE_ENABLE_EXPLAIN_COMMENTS |
| 30 | |
| 31 | SHELL_OPTIONS = -Dmain=sqlite3_shell -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 doc_.c encode_.c event_.c export_.c file_.c finfo_.c foci_.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 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 style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.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 | OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\builtin$O $(OBJDIR)\bundle$O $(OBJDIR)\cache$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\fusefs$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\loadctrl$O $(OBJDIR)\login$O $(OBJDIR)\lookslike$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\publish$O $(OBJDIR)\purge$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\sitemap$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winfile$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O |
| 36 | |
| 37 | |
| 38 | RC=$(DMDIR)\bin\rcc |
| 39 | RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__ |
| 40 | |
| @@ -49,11 +49,11 @@ | |
| 49 | |
| 50 | $(OBJDIR)\fossil.res: $B\win\fossil.rc |
| 51 | $(RC) $(RCFLAGS) -o$@ $** |
| 52 | |
| 53 | $(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res |
| 54 | +echo add allrepo attach bag bisect blob branch browse builtin bundle cache captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo foci fusefs glob graph gzip http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_status json_tag json_timeline json_user json_wiki leaf loadctrl login lookslike main manifest markdown markdown_html md5 merge merge3 moderate name path pivot popen pqueue printf publish purge rebuild regexp report rss schema search setup sha1 shun sitemap skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo unicode update url user utf8 util verify vfile wiki wikiformat winfile winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@ |
| 55 | +echo fossil >> $@ |
| 56 | +echo fossil >> $@ |
| 57 | +echo $(LIBS) >> $@ |
| 58 | +echo. >> $@ |
| 59 | +echo fossil >> $@ |
| @@ -176,10 +176,16 @@ | |
| 176 | $(OBJDIR)\builtin$O : builtin_.c builtin.h |
| 177 | $(TCC) -o$@ -c builtin_.c |
| 178 | |
| 179 | builtin_.c : $(SRCDIR)\builtin.c |
| 180 | +translate$E $** > $@ |
| 181 | |
| 182 | $(OBJDIR)\bundle$O : bundle_.c bundle.h |
| 183 | $(TCC) -o$@ -c bundle_.c |
| 184 | |
| 185 | bundle_.c : $(SRCDIR)\bundle.c |
| 186 | +translate$E $** > $@ |
| 187 | |
| 188 | $(OBJDIR)\cache$O : cache_.c cache.h |
| 189 | $(TCC) -o$@ -c cache_.c |
| 190 | |
| 191 | cache_.c : $(SRCDIR)\cache.c |
| @@ -572,10 +578,22 @@ | |
| 578 | $(OBJDIR)\printf$O : printf_.c printf.h |
| 579 | $(TCC) -o$@ -c printf_.c |
| 580 | |
| 581 | printf_.c : $(SRCDIR)\printf.c |
| 582 | +translate$E $** > $@ |
| 583 | |
| 584 | $(OBJDIR)\publish$O : publish_.c publish.h |
| 585 | $(TCC) -o$@ -c publish_.c |
| 586 | |
| 587 | publish_.c : $(SRCDIR)\publish.c |
| 588 | +translate$E $** > $@ |
| 589 | |
| 590 | $(OBJDIR)\purge$O : purge_.c purge.h |
| 591 | $(TCC) -o$@ -c purge_.c |
| 592 | |
| 593 | purge_.c : $(SRCDIR)\purge.c |
| 594 | +translate$E $** > $@ |
| 595 | |
| 596 | $(OBJDIR)\rebuild$O : rebuild_.c rebuild.h |
| 597 | $(TCC) -o$@ -c rebuild_.c |
| 598 | |
| 599 | rebuild_.c : $(SRCDIR)\rebuild.c |
| @@ -626,10 +644,16 @@ | |
| 644 | $(OBJDIR)\shun$O : shun_.c shun.h |
| 645 | $(TCC) -o$@ -c shun_.c |
| 646 | |
| 647 | shun_.c : $(SRCDIR)\shun.c |
| 648 | +translate$E $** > $@ |
| 649 | |
| 650 | $(OBJDIR)\sitemap$O : sitemap_.c sitemap.h |
| 651 | $(TCC) -o$@ -c sitemap_.c |
| 652 | |
| 653 | sitemap_.c : $(SRCDIR)\sitemap.c |
| 654 | +translate$E $** > $@ |
| 655 | |
| 656 | $(OBJDIR)\skins$O : skins_.c skins.h |
| 657 | $(TCC) -o$@ -c skins_.c |
| 658 | |
| 659 | skins_.c : $(SRCDIR)\skins.c |
| @@ -802,7 +826,7 @@ | |
| 826 | |
| 827 | zip_.c : $(SRCDIR)\zip.c |
| 828 | +translate$E $** > $@ |
| 829 | |
| 830 | headers: makeheaders$E page_index.h builtin_data.h VERSION.h |
| 831 | +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h builtin_.c:builtin.h bundle_.c:bundle.h cache_.c:cache.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h foci_.c:foci.h fusefs_.c:fusefs.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_status_.c:json_status.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h loadctrl_.c:loadctrl.h login_.c:login.h lookslike_.c:lookslike.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h publish_.c:publish.h purge_.c:purge.h rebuild_.c:rebuild.h regexp_.c:regexp.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h sitemap_.c:sitemap.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h unicode_.c:unicode.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h util_.c:util.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winfile_.c:winfile.h winhttp_.c:winhttp.h wysiwyg_.c:wysiwyg.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h |
| 832 | @copy /Y nul: headers |
| 833 |
+71
-2
| --- win/Makefile.mingw | ||
| +++ win/Makefile.mingw | ||
| @@ -87,11 +87,12 @@ | ||
| 87 | 87 | # This is useful when Tcl has been compiled statically with MinGW. |
| 88 | 88 | # |
| 89 | 89 | FOSSIL_TCL_SOURCE = 1 |
| 90 | 90 | |
| 91 | 91 | #### Check if the workaround for the MinGW command line handling needs to |
| 92 | -# be enabled by default. | |
| 92 | +# be enabled by default. This check may be somewhat fragile due to the | |
| 93 | +# use of "findstring". | |
| 93 | 94 | # |
| 94 | 95 | ifndef MINGW_IS_32BIT_ONLY |
| 95 | 96 | ifeq (,$(findstring w64-mingw32,$(PREFIX))) |
| 96 | 97 | MINGW_IS_32BIT_ONLY = 1 |
| 97 | 98 | endif |
| @@ -100,26 +101,46 @@ | ||
| 100 | 101 | #### The directories where the zlib include and library files are located. |
| 101 | 102 | # |
| 102 | 103 | ZINCDIR = $(SRCDIR)/../compat/zlib |
| 103 | 104 | ZLIBDIR = $(SRCDIR)/../compat/zlib |
| 104 | 105 | |
| 106 | +#### Make an attempt to detect if Fossil is being built for the x64 processor | |
| 107 | +# architecture. This check may be somewhat fragile due to "findstring". | |
| 108 | +# | |
| 105 | 109 | ifndef X64 |
| 106 | 110 | ifneq (,$(findstring x86_64-w64-mingw32,$(PREFIX))) |
| 107 | 111 | X64 = 1 |
| 108 | 112 | endif |
| 109 | 113 | endif |
| 110 | 114 | |
| 115 | +#### Determine if the optimized assembly routines provided with zlib should be | |
| 116 | +# used, taking into account whether zlib is actually enabled and the target | |
| 117 | +# processor architecture. | |
| 118 | +# | |
| 111 | 119 | ifndef X64 |
| 112 | 120 | SSLCONFIG = mingw |
| 121 | +ifndef FOSSIL_ENABLE_MINIZ | |
| 113 | 122 | ZLIBCONFIG = LOC="-DASMV -DASMINF" OBJA="inffas86.o match.o" |
| 114 | 123 | LIBTARGETS = $(ZLIBDIR)/inffas86.o $(ZLIBDIR)/match.o |
| 124 | +else | |
| 125 | +ZLIBCONFIG = | |
| 126 | +LIBTARGETS = | |
| 127 | +endif | |
| 115 | 128 | else |
| 116 | 129 | SSLCONFIG = mingw64 |
| 117 | -ZLIBCONFIG = | |
| 130 | +ZLIBCONFIG = | |
| 118 | 131 | LIBTARGETS = |
| 119 | 132 | endif |
| 120 | 133 | |
| 134 | +#### Disable creation of the OpenSSL shared libraries. Also, disable support | |
| 135 | +# for both SSLv2 and SSLv3 (i.e. thereby forcing the use of TLS). | |
| 136 | +# | |
| 137 | +SSLCONFIG += no-ssl2 no-ssl3 no-shared | |
| 138 | + | |
| 139 | +#### When using zlib, make sure that OpenSSL is configured to use the zlib | |
| 140 | +# that Fossil knows about (i.e. the one within the source tree). | |
| 141 | +# | |
| 121 | 142 | ifndef FOSSIL_ENABLE_MINIZ |
| 122 | 143 | SSLCONFIG += --with-zlib-lib=$(PWD)/$(ZLIBDIR) --with-zlib-include=$(PWD)/$(ZLIBDIR) zlib |
| 123 | 144 | endif |
| 124 | 145 | |
| 125 | 146 | #### The directories where the OpenSSL include and library files are located. |
| @@ -352,10 +373,11 @@ | ||
| 352 | 373 | $(SRCDIR)/bisect.c \ |
| 353 | 374 | $(SRCDIR)/blob.c \ |
| 354 | 375 | $(SRCDIR)/branch.c \ |
| 355 | 376 | $(SRCDIR)/browse.c \ |
| 356 | 377 | $(SRCDIR)/builtin.c \ |
| 378 | + $(SRCDIR)/bundle.c \ | |
| 357 | 379 | $(SRCDIR)/cache.c \ |
| 358 | 380 | $(SRCDIR)/captcha.c \ |
| 359 | 381 | $(SRCDIR)/cgi.c \ |
| 360 | 382 | $(SRCDIR)/checkin.c \ |
| 361 | 383 | $(SRCDIR)/checkout.c \ |
| @@ -418,19 +440,22 @@ | ||
| 418 | 440 | $(SRCDIR)/path.c \ |
| 419 | 441 | $(SRCDIR)/pivot.c \ |
| 420 | 442 | $(SRCDIR)/popen.c \ |
| 421 | 443 | $(SRCDIR)/pqueue.c \ |
| 422 | 444 | $(SRCDIR)/printf.c \ |
| 445 | + $(SRCDIR)/publish.c \ | |
| 446 | + $(SRCDIR)/purge.c \ | |
| 423 | 447 | $(SRCDIR)/rebuild.c \ |
| 424 | 448 | $(SRCDIR)/regexp.c \ |
| 425 | 449 | $(SRCDIR)/report.c \ |
| 426 | 450 | $(SRCDIR)/rss.c \ |
| 427 | 451 | $(SRCDIR)/schema.c \ |
| 428 | 452 | $(SRCDIR)/search.c \ |
| 429 | 453 | $(SRCDIR)/setup.c \ |
| 430 | 454 | $(SRCDIR)/sha1.c \ |
| 431 | 455 | $(SRCDIR)/shun.c \ |
| 456 | + $(SRCDIR)/sitemap.c \ | |
| 432 | 457 | $(SRCDIR)/skins.c \ |
| 433 | 458 | $(SRCDIR)/sqlcmd.c \ |
| 434 | 459 | $(SRCDIR)/stash.c \ |
| 435 | 460 | $(SRCDIR)/stat.c \ |
| 436 | 461 | $(SRCDIR)/style.c \ |
| @@ -470,10 +495,11 @@ | ||
| 470 | 495 | $(OBJDIR)/bisect_.c \ |
| 471 | 496 | $(OBJDIR)/blob_.c \ |
| 472 | 497 | $(OBJDIR)/branch_.c \ |
| 473 | 498 | $(OBJDIR)/browse_.c \ |
| 474 | 499 | $(OBJDIR)/builtin_.c \ |
| 500 | + $(OBJDIR)/bundle_.c \ | |
| 475 | 501 | $(OBJDIR)/cache_.c \ |
| 476 | 502 | $(OBJDIR)/captcha_.c \ |
| 477 | 503 | $(OBJDIR)/cgi_.c \ |
| 478 | 504 | $(OBJDIR)/checkin_.c \ |
| 479 | 505 | $(OBJDIR)/checkout_.c \ |
| @@ -536,19 +562,22 @@ | ||
| 536 | 562 | $(OBJDIR)/path_.c \ |
| 537 | 563 | $(OBJDIR)/pivot_.c \ |
| 538 | 564 | $(OBJDIR)/popen_.c \ |
| 539 | 565 | $(OBJDIR)/pqueue_.c \ |
| 540 | 566 | $(OBJDIR)/printf_.c \ |
| 567 | + $(OBJDIR)/publish_.c \ | |
| 568 | + $(OBJDIR)/purge_.c \ | |
| 541 | 569 | $(OBJDIR)/rebuild_.c \ |
| 542 | 570 | $(OBJDIR)/regexp_.c \ |
| 543 | 571 | $(OBJDIR)/report_.c \ |
| 544 | 572 | $(OBJDIR)/rss_.c \ |
| 545 | 573 | $(OBJDIR)/schema_.c \ |
| 546 | 574 | $(OBJDIR)/search_.c \ |
| 547 | 575 | $(OBJDIR)/setup_.c \ |
| 548 | 576 | $(OBJDIR)/sha1_.c \ |
| 549 | 577 | $(OBJDIR)/shun_.c \ |
| 578 | + $(OBJDIR)/sitemap_.c \ | |
| 550 | 579 | $(OBJDIR)/skins_.c \ |
| 551 | 580 | $(OBJDIR)/sqlcmd_.c \ |
| 552 | 581 | $(OBJDIR)/stash_.c \ |
| 553 | 582 | $(OBJDIR)/stat_.c \ |
| 554 | 583 | $(OBJDIR)/style_.c \ |
| @@ -585,10 +614,11 @@ | ||
| 585 | 614 | $(OBJDIR)/bisect.o \ |
| 586 | 615 | $(OBJDIR)/blob.o \ |
| 587 | 616 | $(OBJDIR)/branch.o \ |
| 588 | 617 | $(OBJDIR)/browse.o \ |
| 589 | 618 | $(OBJDIR)/builtin.o \ |
| 619 | + $(OBJDIR)/bundle.o \ | |
| 590 | 620 | $(OBJDIR)/cache.o \ |
| 591 | 621 | $(OBJDIR)/captcha.o \ |
| 592 | 622 | $(OBJDIR)/cgi.o \ |
| 593 | 623 | $(OBJDIR)/checkin.o \ |
| 594 | 624 | $(OBJDIR)/checkout.o \ |
| @@ -651,19 +681,22 @@ | ||
| 651 | 681 | $(OBJDIR)/path.o \ |
| 652 | 682 | $(OBJDIR)/pivot.o \ |
| 653 | 683 | $(OBJDIR)/popen.o \ |
| 654 | 684 | $(OBJDIR)/pqueue.o \ |
| 655 | 685 | $(OBJDIR)/printf.o \ |
| 686 | + $(OBJDIR)/publish.o \ | |
| 687 | + $(OBJDIR)/purge.o \ | |
| 656 | 688 | $(OBJDIR)/rebuild.o \ |
| 657 | 689 | $(OBJDIR)/regexp.o \ |
| 658 | 690 | $(OBJDIR)/report.o \ |
| 659 | 691 | $(OBJDIR)/rss.o \ |
| 660 | 692 | $(OBJDIR)/schema.o \ |
| 661 | 693 | $(OBJDIR)/search.o \ |
| 662 | 694 | $(OBJDIR)/setup.o \ |
| 663 | 695 | $(OBJDIR)/sha1.o \ |
| 664 | 696 | $(OBJDIR)/shun.o \ |
| 697 | + $(OBJDIR)/sitemap.o \ | |
| 665 | 698 | $(OBJDIR)/skins.o \ |
| 666 | 699 | $(OBJDIR)/sqlcmd.o \ |
| 667 | 700 | $(OBJDIR)/stash.o \ |
| 668 | 701 | $(OBJDIR)/stat.o \ |
| 669 | 702 | $(OBJDIR)/style.o \ |
| @@ -893,10 +926,11 @@ | ||
| 893 | 926 | $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h \ |
| 894 | 927 | $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h \ |
| 895 | 928 | $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h \ |
| 896 | 929 | $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h \ |
| 897 | 930 | $(OBJDIR)/builtin_.c:$(OBJDIR)/builtin.h \ |
| 931 | + $(OBJDIR)/bundle_.c:$(OBJDIR)/bundle.h \ | |
| 898 | 932 | $(OBJDIR)/cache_.c:$(OBJDIR)/cache.h \ |
| 899 | 933 | $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h \ |
| 900 | 934 | $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h \ |
| 901 | 935 | $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h \ |
| 902 | 936 | $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h \ |
| @@ -959,19 +993,22 @@ | ||
| 959 | 993 | $(OBJDIR)/path_.c:$(OBJDIR)/path.h \ |
| 960 | 994 | $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \ |
| 961 | 995 | $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \ |
| 962 | 996 | $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \ |
| 963 | 997 | $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \ |
| 998 | + $(OBJDIR)/publish_.c:$(OBJDIR)/publish.h \ | |
| 999 | + $(OBJDIR)/purge_.c:$(OBJDIR)/purge.h \ | |
| 964 | 1000 | $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h \ |
| 965 | 1001 | $(OBJDIR)/regexp_.c:$(OBJDIR)/regexp.h \ |
| 966 | 1002 | $(OBJDIR)/report_.c:$(OBJDIR)/report.h \ |
| 967 | 1003 | $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \ |
| 968 | 1004 | $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \ |
| 969 | 1005 | $(OBJDIR)/search_.c:$(OBJDIR)/search.h \ |
| 970 | 1006 | $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \ |
| 971 | 1007 | $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \ |
| 972 | 1008 | $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \ |
| 1009 | + $(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \ | |
| 973 | 1010 | $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \ |
| 974 | 1011 | $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \ |
| 975 | 1012 | $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \ |
| 976 | 1013 | $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h \ |
| 977 | 1014 | $(OBJDIR)/style_.c:$(OBJDIR)/style.h \ |
| @@ -1077,10 +1114,18 @@ | ||
| 1077 | 1114 | |
| 1078 | 1115 | $(OBJDIR)/builtin.o: $(OBJDIR)/builtin_.c $(OBJDIR)/builtin.h $(OBJDIR)/builtin_data.h $(SRCDIR)/config.h |
| 1079 | 1116 | $(XTCC) -o $(OBJDIR)/builtin.o -c $(OBJDIR)/builtin_.c |
| 1080 | 1117 | |
| 1081 | 1118 | $(OBJDIR)/builtin.h: $(OBJDIR)/headers |
| 1119 | + | |
| 1120 | +$(OBJDIR)/bundle_.c: $(SRCDIR)/bundle.c $(TRANSLATE) | |
| 1121 | + $(TRANSLATE) $(SRCDIR)/bundle.c >$@ | |
| 1122 | + | |
| 1123 | +$(OBJDIR)/bundle.o: $(OBJDIR)/bundle_.c $(OBJDIR)/bundle.h $(SRCDIR)/config.h | |
| 1124 | + $(XTCC) -o $(OBJDIR)/bundle.o -c $(OBJDIR)/bundle_.c | |
| 1125 | + | |
| 1126 | +$(OBJDIR)/bundle.h: $(OBJDIR)/headers | |
| 1082 | 1127 | |
| 1083 | 1128 | $(OBJDIR)/cache_.c: $(SRCDIR)/cache.c $(TRANSLATE) |
| 1084 | 1129 | $(TRANSLATE) $(SRCDIR)/cache.c >$@ |
| 1085 | 1130 | |
| 1086 | 1131 | $(OBJDIR)/cache.o: $(OBJDIR)/cache_.c $(OBJDIR)/cache.h $(SRCDIR)/config.h |
| @@ -1605,10 +1650,26 @@ | ||
| 1605 | 1650 | |
| 1606 | 1651 | $(OBJDIR)/printf.o: $(OBJDIR)/printf_.c $(OBJDIR)/printf.h $(SRCDIR)/config.h |
| 1607 | 1652 | $(XTCC) -o $(OBJDIR)/printf.o -c $(OBJDIR)/printf_.c |
| 1608 | 1653 | |
| 1609 | 1654 | $(OBJDIR)/printf.h: $(OBJDIR)/headers |
| 1655 | + | |
| 1656 | +$(OBJDIR)/publish_.c: $(SRCDIR)/publish.c $(TRANSLATE) | |
| 1657 | + $(TRANSLATE) $(SRCDIR)/publish.c >$@ | |
| 1658 | + | |
| 1659 | +$(OBJDIR)/publish.o: $(OBJDIR)/publish_.c $(OBJDIR)/publish.h $(SRCDIR)/config.h | |
| 1660 | + $(XTCC) -o $(OBJDIR)/publish.o -c $(OBJDIR)/publish_.c | |
| 1661 | + | |
| 1662 | +$(OBJDIR)/publish.h: $(OBJDIR)/headers | |
| 1663 | + | |
| 1664 | +$(OBJDIR)/purge_.c: $(SRCDIR)/purge.c $(TRANSLATE) | |
| 1665 | + $(TRANSLATE) $(SRCDIR)/purge.c >$@ | |
| 1666 | + | |
| 1667 | +$(OBJDIR)/purge.o: $(OBJDIR)/purge_.c $(OBJDIR)/purge.h $(SRCDIR)/config.h | |
| 1668 | + $(XTCC) -o $(OBJDIR)/purge.o -c $(OBJDIR)/purge_.c | |
| 1669 | + | |
| 1670 | +$(OBJDIR)/purge.h: $(OBJDIR)/headers | |
| 1610 | 1671 | |
| 1611 | 1672 | $(OBJDIR)/rebuild_.c: $(SRCDIR)/rebuild.c $(TRANSLATE) |
| 1612 | 1673 | $(TRANSLATE) $(SRCDIR)/rebuild.c >$@ |
| 1613 | 1674 | |
| 1614 | 1675 | $(OBJDIR)/rebuild.o: $(OBJDIR)/rebuild_.c $(OBJDIR)/rebuild.h $(SRCDIR)/config.h |
| @@ -1677,10 +1738,18 @@ | ||
| 1677 | 1738 | |
| 1678 | 1739 | $(OBJDIR)/shun.o: $(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h |
| 1679 | 1740 | $(XTCC) -o $(OBJDIR)/shun.o -c $(OBJDIR)/shun_.c |
| 1680 | 1741 | |
| 1681 | 1742 | $(OBJDIR)/shun.h: $(OBJDIR)/headers |
| 1743 | + | |
| 1744 | +$(OBJDIR)/sitemap_.c: $(SRCDIR)/sitemap.c $(TRANSLATE) | |
| 1745 | + $(TRANSLATE) $(SRCDIR)/sitemap.c >$@ | |
| 1746 | + | |
| 1747 | +$(OBJDIR)/sitemap.o: $(OBJDIR)/sitemap_.c $(OBJDIR)/sitemap.h $(SRCDIR)/config.h | |
| 1748 | + $(XTCC) -o $(OBJDIR)/sitemap.o -c $(OBJDIR)/sitemap_.c | |
| 1749 | + | |
| 1750 | +$(OBJDIR)/sitemap.h: $(OBJDIR)/headers | |
| 1682 | 1751 | |
| 1683 | 1752 | $(OBJDIR)/skins_.c: $(SRCDIR)/skins.c $(TRANSLATE) |
| 1684 | 1753 | $(TRANSLATE) $(SRCDIR)/skins.c >$@ |
| 1685 | 1754 | |
| 1686 | 1755 | $(OBJDIR)/skins.o: $(OBJDIR)/skins_.c $(OBJDIR)/skins.h $(SRCDIR)/config.h |
| 1687 | 1756 |
| --- win/Makefile.mingw | |
| +++ win/Makefile.mingw | |
| @@ -87,11 +87,12 @@ | |
| 87 | # This is useful when Tcl has been compiled statically with MinGW. |
| 88 | # |
| 89 | FOSSIL_TCL_SOURCE = 1 |
| 90 | |
| 91 | #### Check if the workaround for the MinGW command line handling needs to |
| 92 | # be enabled by default. |
| 93 | # |
| 94 | ifndef MINGW_IS_32BIT_ONLY |
| 95 | ifeq (,$(findstring w64-mingw32,$(PREFIX))) |
| 96 | MINGW_IS_32BIT_ONLY = 1 |
| 97 | endif |
| @@ -100,26 +101,46 @@ | |
| 100 | #### The directories where the zlib include and library files are located. |
| 101 | # |
| 102 | ZINCDIR = $(SRCDIR)/../compat/zlib |
| 103 | ZLIBDIR = $(SRCDIR)/../compat/zlib |
| 104 | |
| 105 | ifndef X64 |
| 106 | ifneq (,$(findstring x86_64-w64-mingw32,$(PREFIX))) |
| 107 | X64 = 1 |
| 108 | endif |
| 109 | endif |
| 110 | |
| 111 | ifndef X64 |
| 112 | SSLCONFIG = mingw |
| 113 | ZLIBCONFIG = LOC="-DASMV -DASMINF" OBJA="inffas86.o match.o" |
| 114 | LIBTARGETS = $(ZLIBDIR)/inffas86.o $(ZLIBDIR)/match.o |
| 115 | else |
| 116 | SSLCONFIG = mingw64 |
| 117 | ZLIBCONFIG = |
| 118 | LIBTARGETS = |
| 119 | endif |
| 120 | |
| 121 | ifndef FOSSIL_ENABLE_MINIZ |
| 122 | SSLCONFIG += --with-zlib-lib=$(PWD)/$(ZLIBDIR) --with-zlib-include=$(PWD)/$(ZLIBDIR) zlib |
| 123 | endif |
| 124 | |
| 125 | #### The directories where the OpenSSL include and library files are located. |
| @@ -352,10 +373,11 @@ | |
| 352 | $(SRCDIR)/bisect.c \ |
| 353 | $(SRCDIR)/blob.c \ |
| 354 | $(SRCDIR)/branch.c \ |
| 355 | $(SRCDIR)/browse.c \ |
| 356 | $(SRCDIR)/builtin.c \ |
| 357 | $(SRCDIR)/cache.c \ |
| 358 | $(SRCDIR)/captcha.c \ |
| 359 | $(SRCDIR)/cgi.c \ |
| 360 | $(SRCDIR)/checkin.c \ |
| 361 | $(SRCDIR)/checkout.c \ |
| @@ -418,19 +440,22 @@ | |
| 418 | $(SRCDIR)/path.c \ |
| 419 | $(SRCDIR)/pivot.c \ |
| 420 | $(SRCDIR)/popen.c \ |
| 421 | $(SRCDIR)/pqueue.c \ |
| 422 | $(SRCDIR)/printf.c \ |
| 423 | $(SRCDIR)/rebuild.c \ |
| 424 | $(SRCDIR)/regexp.c \ |
| 425 | $(SRCDIR)/report.c \ |
| 426 | $(SRCDIR)/rss.c \ |
| 427 | $(SRCDIR)/schema.c \ |
| 428 | $(SRCDIR)/search.c \ |
| 429 | $(SRCDIR)/setup.c \ |
| 430 | $(SRCDIR)/sha1.c \ |
| 431 | $(SRCDIR)/shun.c \ |
| 432 | $(SRCDIR)/skins.c \ |
| 433 | $(SRCDIR)/sqlcmd.c \ |
| 434 | $(SRCDIR)/stash.c \ |
| 435 | $(SRCDIR)/stat.c \ |
| 436 | $(SRCDIR)/style.c \ |
| @@ -470,10 +495,11 @@ | |
| 470 | $(OBJDIR)/bisect_.c \ |
| 471 | $(OBJDIR)/blob_.c \ |
| 472 | $(OBJDIR)/branch_.c \ |
| 473 | $(OBJDIR)/browse_.c \ |
| 474 | $(OBJDIR)/builtin_.c \ |
| 475 | $(OBJDIR)/cache_.c \ |
| 476 | $(OBJDIR)/captcha_.c \ |
| 477 | $(OBJDIR)/cgi_.c \ |
| 478 | $(OBJDIR)/checkin_.c \ |
| 479 | $(OBJDIR)/checkout_.c \ |
| @@ -536,19 +562,22 @@ | |
| 536 | $(OBJDIR)/path_.c \ |
| 537 | $(OBJDIR)/pivot_.c \ |
| 538 | $(OBJDIR)/popen_.c \ |
| 539 | $(OBJDIR)/pqueue_.c \ |
| 540 | $(OBJDIR)/printf_.c \ |
| 541 | $(OBJDIR)/rebuild_.c \ |
| 542 | $(OBJDIR)/regexp_.c \ |
| 543 | $(OBJDIR)/report_.c \ |
| 544 | $(OBJDIR)/rss_.c \ |
| 545 | $(OBJDIR)/schema_.c \ |
| 546 | $(OBJDIR)/search_.c \ |
| 547 | $(OBJDIR)/setup_.c \ |
| 548 | $(OBJDIR)/sha1_.c \ |
| 549 | $(OBJDIR)/shun_.c \ |
| 550 | $(OBJDIR)/skins_.c \ |
| 551 | $(OBJDIR)/sqlcmd_.c \ |
| 552 | $(OBJDIR)/stash_.c \ |
| 553 | $(OBJDIR)/stat_.c \ |
| 554 | $(OBJDIR)/style_.c \ |
| @@ -585,10 +614,11 @@ | |
| 585 | $(OBJDIR)/bisect.o \ |
| 586 | $(OBJDIR)/blob.o \ |
| 587 | $(OBJDIR)/branch.o \ |
| 588 | $(OBJDIR)/browse.o \ |
| 589 | $(OBJDIR)/builtin.o \ |
| 590 | $(OBJDIR)/cache.o \ |
| 591 | $(OBJDIR)/captcha.o \ |
| 592 | $(OBJDIR)/cgi.o \ |
| 593 | $(OBJDIR)/checkin.o \ |
| 594 | $(OBJDIR)/checkout.o \ |
| @@ -651,19 +681,22 @@ | |
| 651 | $(OBJDIR)/path.o \ |
| 652 | $(OBJDIR)/pivot.o \ |
| 653 | $(OBJDIR)/popen.o \ |
| 654 | $(OBJDIR)/pqueue.o \ |
| 655 | $(OBJDIR)/printf.o \ |
| 656 | $(OBJDIR)/rebuild.o \ |
| 657 | $(OBJDIR)/regexp.o \ |
| 658 | $(OBJDIR)/report.o \ |
| 659 | $(OBJDIR)/rss.o \ |
| 660 | $(OBJDIR)/schema.o \ |
| 661 | $(OBJDIR)/search.o \ |
| 662 | $(OBJDIR)/setup.o \ |
| 663 | $(OBJDIR)/sha1.o \ |
| 664 | $(OBJDIR)/shun.o \ |
| 665 | $(OBJDIR)/skins.o \ |
| 666 | $(OBJDIR)/sqlcmd.o \ |
| 667 | $(OBJDIR)/stash.o \ |
| 668 | $(OBJDIR)/stat.o \ |
| 669 | $(OBJDIR)/style.o \ |
| @@ -893,10 +926,11 @@ | |
| 893 | $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h \ |
| 894 | $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h \ |
| 895 | $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h \ |
| 896 | $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h \ |
| 897 | $(OBJDIR)/builtin_.c:$(OBJDIR)/builtin.h \ |
| 898 | $(OBJDIR)/cache_.c:$(OBJDIR)/cache.h \ |
| 899 | $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h \ |
| 900 | $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h \ |
| 901 | $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h \ |
| 902 | $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h \ |
| @@ -959,19 +993,22 @@ | |
| 959 | $(OBJDIR)/path_.c:$(OBJDIR)/path.h \ |
| 960 | $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \ |
| 961 | $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \ |
| 962 | $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \ |
| 963 | $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \ |
| 964 | $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h \ |
| 965 | $(OBJDIR)/regexp_.c:$(OBJDIR)/regexp.h \ |
| 966 | $(OBJDIR)/report_.c:$(OBJDIR)/report.h \ |
| 967 | $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \ |
| 968 | $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \ |
| 969 | $(OBJDIR)/search_.c:$(OBJDIR)/search.h \ |
| 970 | $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \ |
| 971 | $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \ |
| 972 | $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \ |
| 973 | $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \ |
| 974 | $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \ |
| 975 | $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \ |
| 976 | $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h \ |
| 977 | $(OBJDIR)/style_.c:$(OBJDIR)/style.h \ |
| @@ -1077,10 +1114,18 @@ | |
| 1077 | |
| 1078 | $(OBJDIR)/builtin.o: $(OBJDIR)/builtin_.c $(OBJDIR)/builtin.h $(OBJDIR)/builtin_data.h $(SRCDIR)/config.h |
| 1079 | $(XTCC) -o $(OBJDIR)/builtin.o -c $(OBJDIR)/builtin_.c |
| 1080 | |
| 1081 | $(OBJDIR)/builtin.h: $(OBJDIR)/headers |
| 1082 | |
| 1083 | $(OBJDIR)/cache_.c: $(SRCDIR)/cache.c $(TRANSLATE) |
| 1084 | $(TRANSLATE) $(SRCDIR)/cache.c >$@ |
| 1085 | |
| 1086 | $(OBJDIR)/cache.o: $(OBJDIR)/cache_.c $(OBJDIR)/cache.h $(SRCDIR)/config.h |
| @@ -1605,10 +1650,26 @@ | |
| 1605 | |
| 1606 | $(OBJDIR)/printf.o: $(OBJDIR)/printf_.c $(OBJDIR)/printf.h $(SRCDIR)/config.h |
| 1607 | $(XTCC) -o $(OBJDIR)/printf.o -c $(OBJDIR)/printf_.c |
| 1608 | |
| 1609 | $(OBJDIR)/printf.h: $(OBJDIR)/headers |
| 1610 | |
| 1611 | $(OBJDIR)/rebuild_.c: $(SRCDIR)/rebuild.c $(TRANSLATE) |
| 1612 | $(TRANSLATE) $(SRCDIR)/rebuild.c >$@ |
| 1613 | |
| 1614 | $(OBJDIR)/rebuild.o: $(OBJDIR)/rebuild_.c $(OBJDIR)/rebuild.h $(SRCDIR)/config.h |
| @@ -1677,10 +1738,18 @@ | |
| 1677 | |
| 1678 | $(OBJDIR)/shun.o: $(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h |
| 1679 | $(XTCC) -o $(OBJDIR)/shun.o -c $(OBJDIR)/shun_.c |
| 1680 | |
| 1681 | $(OBJDIR)/shun.h: $(OBJDIR)/headers |
| 1682 | |
| 1683 | $(OBJDIR)/skins_.c: $(SRCDIR)/skins.c $(TRANSLATE) |
| 1684 | $(TRANSLATE) $(SRCDIR)/skins.c >$@ |
| 1685 | |
| 1686 | $(OBJDIR)/skins.o: $(OBJDIR)/skins_.c $(OBJDIR)/skins.h $(SRCDIR)/config.h |
| 1687 |
| --- win/Makefile.mingw | |
| +++ win/Makefile.mingw | |
| @@ -87,11 +87,12 @@ | |
| 87 | # This is useful when Tcl has been compiled statically with MinGW. |
| 88 | # |
| 89 | FOSSIL_TCL_SOURCE = 1 |
| 90 | |
| 91 | #### Check if the workaround for the MinGW command line handling needs to |
| 92 | # be enabled by default. This check may be somewhat fragile due to the |
| 93 | # use of "findstring". |
| 94 | # |
| 95 | ifndef MINGW_IS_32BIT_ONLY |
| 96 | ifeq (,$(findstring w64-mingw32,$(PREFIX))) |
| 97 | MINGW_IS_32BIT_ONLY = 1 |
| 98 | endif |
| @@ -100,26 +101,46 @@ | |
| 101 | #### The directories where the zlib include and library files are located. |
| 102 | # |
| 103 | ZINCDIR = $(SRCDIR)/../compat/zlib |
| 104 | ZLIBDIR = $(SRCDIR)/../compat/zlib |
| 105 | |
| 106 | #### Make an attempt to detect if Fossil is being built for the x64 processor |
| 107 | # architecture. This check may be somewhat fragile due to "findstring". |
| 108 | # |
| 109 | ifndef X64 |
| 110 | ifneq (,$(findstring x86_64-w64-mingw32,$(PREFIX))) |
| 111 | X64 = 1 |
| 112 | endif |
| 113 | endif |
| 114 | |
| 115 | #### Determine if the optimized assembly routines provided with zlib should be |
| 116 | # used, taking into account whether zlib is actually enabled and the target |
| 117 | # processor architecture. |
| 118 | # |
| 119 | ifndef X64 |
| 120 | SSLCONFIG = mingw |
| 121 | ifndef FOSSIL_ENABLE_MINIZ |
| 122 | ZLIBCONFIG = LOC="-DASMV -DASMINF" OBJA="inffas86.o match.o" |
| 123 | LIBTARGETS = $(ZLIBDIR)/inffas86.o $(ZLIBDIR)/match.o |
| 124 | else |
| 125 | ZLIBCONFIG = |
| 126 | LIBTARGETS = |
| 127 | endif |
| 128 | else |
| 129 | SSLCONFIG = mingw64 |
| 130 | ZLIBCONFIG = |
| 131 | LIBTARGETS = |
| 132 | endif |
| 133 | |
| 134 | #### Disable creation of the OpenSSL shared libraries. Also, disable support |
| 135 | # for both SSLv2 and SSLv3 (i.e. thereby forcing the use of TLS). |
| 136 | # |
| 137 | SSLCONFIG += no-ssl2 no-ssl3 no-shared |
| 138 | |
| 139 | #### When using zlib, make sure that OpenSSL is configured to use the zlib |
| 140 | # that Fossil knows about (i.e. the one within the source tree). |
| 141 | # |
| 142 | ifndef FOSSIL_ENABLE_MINIZ |
| 143 | SSLCONFIG += --with-zlib-lib=$(PWD)/$(ZLIBDIR) --with-zlib-include=$(PWD)/$(ZLIBDIR) zlib |
| 144 | endif |
| 145 | |
| 146 | #### The directories where the OpenSSL include and library files are located. |
| @@ -352,10 +373,11 @@ | |
| 373 | $(SRCDIR)/bisect.c \ |
| 374 | $(SRCDIR)/blob.c \ |
| 375 | $(SRCDIR)/branch.c \ |
| 376 | $(SRCDIR)/browse.c \ |
| 377 | $(SRCDIR)/builtin.c \ |
| 378 | $(SRCDIR)/bundle.c \ |
| 379 | $(SRCDIR)/cache.c \ |
| 380 | $(SRCDIR)/captcha.c \ |
| 381 | $(SRCDIR)/cgi.c \ |
| 382 | $(SRCDIR)/checkin.c \ |
| 383 | $(SRCDIR)/checkout.c \ |
| @@ -418,19 +440,22 @@ | |
| 440 | $(SRCDIR)/path.c \ |
| 441 | $(SRCDIR)/pivot.c \ |
| 442 | $(SRCDIR)/popen.c \ |
| 443 | $(SRCDIR)/pqueue.c \ |
| 444 | $(SRCDIR)/printf.c \ |
| 445 | $(SRCDIR)/publish.c \ |
| 446 | $(SRCDIR)/purge.c \ |
| 447 | $(SRCDIR)/rebuild.c \ |
| 448 | $(SRCDIR)/regexp.c \ |
| 449 | $(SRCDIR)/report.c \ |
| 450 | $(SRCDIR)/rss.c \ |
| 451 | $(SRCDIR)/schema.c \ |
| 452 | $(SRCDIR)/search.c \ |
| 453 | $(SRCDIR)/setup.c \ |
| 454 | $(SRCDIR)/sha1.c \ |
| 455 | $(SRCDIR)/shun.c \ |
| 456 | $(SRCDIR)/sitemap.c \ |
| 457 | $(SRCDIR)/skins.c \ |
| 458 | $(SRCDIR)/sqlcmd.c \ |
| 459 | $(SRCDIR)/stash.c \ |
| 460 | $(SRCDIR)/stat.c \ |
| 461 | $(SRCDIR)/style.c \ |
| @@ -470,10 +495,11 @@ | |
| 495 | $(OBJDIR)/bisect_.c \ |
| 496 | $(OBJDIR)/blob_.c \ |
| 497 | $(OBJDIR)/branch_.c \ |
| 498 | $(OBJDIR)/browse_.c \ |
| 499 | $(OBJDIR)/builtin_.c \ |
| 500 | $(OBJDIR)/bundle_.c \ |
| 501 | $(OBJDIR)/cache_.c \ |
| 502 | $(OBJDIR)/captcha_.c \ |
| 503 | $(OBJDIR)/cgi_.c \ |
| 504 | $(OBJDIR)/checkin_.c \ |
| 505 | $(OBJDIR)/checkout_.c \ |
| @@ -536,19 +562,22 @@ | |
| 562 | $(OBJDIR)/path_.c \ |
| 563 | $(OBJDIR)/pivot_.c \ |
| 564 | $(OBJDIR)/popen_.c \ |
| 565 | $(OBJDIR)/pqueue_.c \ |
| 566 | $(OBJDIR)/printf_.c \ |
| 567 | $(OBJDIR)/publish_.c \ |
| 568 | $(OBJDIR)/purge_.c \ |
| 569 | $(OBJDIR)/rebuild_.c \ |
| 570 | $(OBJDIR)/regexp_.c \ |
| 571 | $(OBJDIR)/report_.c \ |
| 572 | $(OBJDIR)/rss_.c \ |
| 573 | $(OBJDIR)/schema_.c \ |
| 574 | $(OBJDIR)/search_.c \ |
| 575 | $(OBJDIR)/setup_.c \ |
| 576 | $(OBJDIR)/sha1_.c \ |
| 577 | $(OBJDIR)/shun_.c \ |
| 578 | $(OBJDIR)/sitemap_.c \ |
| 579 | $(OBJDIR)/skins_.c \ |
| 580 | $(OBJDIR)/sqlcmd_.c \ |
| 581 | $(OBJDIR)/stash_.c \ |
| 582 | $(OBJDIR)/stat_.c \ |
| 583 | $(OBJDIR)/style_.c \ |
| @@ -585,10 +614,11 @@ | |
| 614 | $(OBJDIR)/bisect.o \ |
| 615 | $(OBJDIR)/blob.o \ |
| 616 | $(OBJDIR)/branch.o \ |
| 617 | $(OBJDIR)/browse.o \ |
| 618 | $(OBJDIR)/builtin.o \ |
| 619 | $(OBJDIR)/bundle.o \ |
| 620 | $(OBJDIR)/cache.o \ |
| 621 | $(OBJDIR)/captcha.o \ |
| 622 | $(OBJDIR)/cgi.o \ |
| 623 | $(OBJDIR)/checkin.o \ |
| 624 | $(OBJDIR)/checkout.o \ |
| @@ -651,19 +681,22 @@ | |
| 681 | $(OBJDIR)/path.o \ |
| 682 | $(OBJDIR)/pivot.o \ |
| 683 | $(OBJDIR)/popen.o \ |
| 684 | $(OBJDIR)/pqueue.o \ |
| 685 | $(OBJDIR)/printf.o \ |
| 686 | $(OBJDIR)/publish.o \ |
| 687 | $(OBJDIR)/purge.o \ |
| 688 | $(OBJDIR)/rebuild.o \ |
| 689 | $(OBJDIR)/regexp.o \ |
| 690 | $(OBJDIR)/report.o \ |
| 691 | $(OBJDIR)/rss.o \ |
| 692 | $(OBJDIR)/schema.o \ |
| 693 | $(OBJDIR)/search.o \ |
| 694 | $(OBJDIR)/setup.o \ |
| 695 | $(OBJDIR)/sha1.o \ |
| 696 | $(OBJDIR)/shun.o \ |
| 697 | $(OBJDIR)/sitemap.o \ |
| 698 | $(OBJDIR)/skins.o \ |
| 699 | $(OBJDIR)/sqlcmd.o \ |
| 700 | $(OBJDIR)/stash.o \ |
| 701 | $(OBJDIR)/stat.o \ |
| 702 | $(OBJDIR)/style.o \ |
| @@ -893,10 +926,11 @@ | |
| 926 | $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h \ |
| 927 | $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h \ |
| 928 | $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h \ |
| 929 | $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h \ |
| 930 | $(OBJDIR)/builtin_.c:$(OBJDIR)/builtin.h \ |
| 931 | $(OBJDIR)/bundle_.c:$(OBJDIR)/bundle.h \ |
| 932 | $(OBJDIR)/cache_.c:$(OBJDIR)/cache.h \ |
| 933 | $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h \ |
| 934 | $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h \ |
| 935 | $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h \ |
| 936 | $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h \ |
| @@ -959,19 +993,22 @@ | |
| 993 | $(OBJDIR)/path_.c:$(OBJDIR)/path.h \ |
| 994 | $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \ |
| 995 | $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \ |
| 996 | $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \ |
| 997 | $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \ |
| 998 | $(OBJDIR)/publish_.c:$(OBJDIR)/publish.h \ |
| 999 | $(OBJDIR)/purge_.c:$(OBJDIR)/purge.h \ |
| 1000 | $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h \ |
| 1001 | $(OBJDIR)/regexp_.c:$(OBJDIR)/regexp.h \ |
| 1002 | $(OBJDIR)/report_.c:$(OBJDIR)/report.h \ |
| 1003 | $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \ |
| 1004 | $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \ |
| 1005 | $(OBJDIR)/search_.c:$(OBJDIR)/search.h \ |
| 1006 | $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \ |
| 1007 | $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \ |
| 1008 | $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \ |
| 1009 | $(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \ |
| 1010 | $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \ |
| 1011 | $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \ |
| 1012 | $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \ |
| 1013 | $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h \ |
| 1014 | $(OBJDIR)/style_.c:$(OBJDIR)/style.h \ |
| @@ -1077,10 +1114,18 @@ | |
| 1114 | |
| 1115 | $(OBJDIR)/builtin.o: $(OBJDIR)/builtin_.c $(OBJDIR)/builtin.h $(OBJDIR)/builtin_data.h $(SRCDIR)/config.h |
| 1116 | $(XTCC) -o $(OBJDIR)/builtin.o -c $(OBJDIR)/builtin_.c |
| 1117 | |
| 1118 | $(OBJDIR)/builtin.h: $(OBJDIR)/headers |
| 1119 | |
| 1120 | $(OBJDIR)/bundle_.c: $(SRCDIR)/bundle.c $(TRANSLATE) |
| 1121 | $(TRANSLATE) $(SRCDIR)/bundle.c >$@ |
| 1122 | |
| 1123 | $(OBJDIR)/bundle.o: $(OBJDIR)/bundle_.c $(OBJDIR)/bundle.h $(SRCDIR)/config.h |
| 1124 | $(XTCC) -o $(OBJDIR)/bundle.o -c $(OBJDIR)/bundle_.c |
| 1125 | |
| 1126 | $(OBJDIR)/bundle.h: $(OBJDIR)/headers |
| 1127 | |
| 1128 | $(OBJDIR)/cache_.c: $(SRCDIR)/cache.c $(TRANSLATE) |
| 1129 | $(TRANSLATE) $(SRCDIR)/cache.c >$@ |
| 1130 | |
| 1131 | $(OBJDIR)/cache.o: $(OBJDIR)/cache_.c $(OBJDIR)/cache.h $(SRCDIR)/config.h |
| @@ -1605,10 +1650,26 @@ | |
| 1650 | |
| 1651 | $(OBJDIR)/printf.o: $(OBJDIR)/printf_.c $(OBJDIR)/printf.h $(SRCDIR)/config.h |
| 1652 | $(XTCC) -o $(OBJDIR)/printf.o -c $(OBJDIR)/printf_.c |
| 1653 | |
| 1654 | $(OBJDIR)/printf.h: $(OBJDIR)/headers |
| 1655 | |
| 1656 | $(OBJDIR)/publish_.c: $(SRCDIR)/publish.c $(TRANSLATE) |
| 1657 | $(TRANSLATE) $(SRCDIR)/publish.c >$@ |
| 1658 | |
| 1659 | $(OBJDIR)/publish.o: $(OBJDIR)/publish_.c $(OBJDIR)/publish.h $(SRCDIR)/config.h |
| 1660 | $(XTCC) -o $(OBJDIR)/publish.o -c $(OBJDIR)/publish_.c |
| 1661 | |
| 1662 | $(OBJDIR)/publish.h: $(OBJDIR)/headers |
| 1663 | |
| 1664 | $(OBJDIR)/purge_.c: $(SRCDIR)/purge.c $(TRANSLATE) |
| 1665 | $(TRANSLATE) $(SRCDIR)/purge.c >$@ |
| 1666 | |
| 1667 | $(OBJDIR)/purge.o: $(OBJDIR)/purge_.c $(OBJDIR)/purge.h $(SRCDIR)/config.h |
| 1668 | $(XTCC) -o $(OBJDIR)/purge.o -c $(OBJDIR)/purge_.c |
| 1669 | |
| 1670 | $(OBJDIR)/purge.h: $(OBJDIR)/headers |
| 1671 | |
| 1672 | $(OBJDIR)/rebuild_.c: $(SRCDIR)/rebuild.c $(TRANSLATE) |
| 1673 | $(TRANSLATE) $(SRCDIR)/rebuild.c >$@ |
| 1674 | |
| 1675 | $(OBJDIR)/rebuild.o: $(OBJDIR)/rebuild_.c $(OBJDIR)/rebuild.h $(SRCDIR)/config.h |
| @@ -1677,10 +1738,18 @@ | |
| 1738 | |
| 1739 | $(OBJDIR)/shun.o: $(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h |
| 1740 | $(XTCC) -o $(OBJDIR)/shun.o -c $(OBJDIR)/shun_.c |
| 1741 | |
| 1742 | $(OBJDIR)/shun.h: $(OBJDIR)/headers |
| 1743 | |
| 1744 | $(OBJDIR)/sitemap_.c: $(SRCDIR)/sitemap.c $(TRANSLATE) |
| 1745 | $(TRANSLATE) $(SRCDIR)/sitemap.c >$@ |
| 1746 | |
| 1747 | $(OBJDIR)/sitemap.o: $(OBJDIR)/sitemap_.c $(OBJDIR)/sitemap.h $(SRCDIR)/config.h |
| 1748 | $(XTCC) -o $(OBJDIR)/sitemap.o -c $(OBJDIR)/sitemap_.c |
| 1749 | |
| 1750 | $(OBJDIR)/sitemap.h: $(OBJDIR)/headers |
| 1751 | |
| 1752 | $(OBJDIR)/skins_.c: $(SRCDIR)/skins.c $(TRANSLATE) |
| 1753 | $(TRANSLATE) $(SRCDIR)/skins.c >$@ |
| 1754 | |
| 1755 | $(OBJDIR)/skins.o: $(OBJDIR)/skins_.c $(OBJDIR)/skins.h $(SRCDIR)/config.h |
| 1756 |
+83
-2
| --- win/Makefile.mingw.mistachkin | ||
| +++ win/Makefile.mingw.mistachkin | ||
| @@ -87,11 +87,12 @@ | ||
| 87 | 87 | # This is useful when Tcl has been compiled statically with MinGW. |
| 88 | 88 | # |
| 89 | 89 | FOSSIL_TCL_SOURCE = 1 |
| 90 | 90 | |
| 91 | 91 | #### Check if the workaround for the MinGW command line handling needs to |
| 92 | -# be enabled by default. | |
| 92 | +# be enabled by default. This check may be somewhat fragile due to the | |
| 93 | +# use of "findstring". | |
| 93 | 94 | # |
| 94 | 95 | ifndef MINGW_IS_32BIT_ONLY |
| 95 | 96 | ifeq (,$(findstring w64-mingw32,$(PREFIX))) |
| 96 | 97 | MINGW_IS_32BIT_ONLY = 1 |
| 97 | 98 | endif |
| @@ -100,26 +101,46 @@ | ||
| 100 | 101 | #### The directories where the zlib include and library files are located. |
| 101 | 102 | # |
| 102 | 103 | ZINCDIR = $(SRCDIR)/../compat/zlib |
| 103 | 104 | ZLIBDIR = $(SRCDIR)/../compat/zlib |
| 104 | 105 | |
| 106 | +#### Make an attempt to detect if Fossil is being built for the x64 processor | |
| 107 | +# architecture. This check may be somewhat fragile due to "findstring". | |
| 108 | +# | |
| 105 | 109 | ifndef X64 |
| 106 | 110 | ifneq (,$(findstring x86_64-w64-mingw32,$(PREFIX))) |
| 107 | 111 | X64 = 1 |
| 108 | 112 | endif |
| 109 | 113 | endif |
| 110 | 114 | |
| 115 | +#### Determine if the optimized assembly routines provided with zlib should be | |
| 116 | +# used, taking into account whether zlib is actually enabled and the target | |
| 117 | +# processor architecture. | |
| 118 | +# | |
| 111 | 119 | ifndef X64 |
| 112 | 120 | SSLCONFIG = mingw |
| 121 | +ifndef FOSSIL_ENABLE_MINIZ | |
| 113 | 122 | ZLIBCONFIG = LOC="-DASMV -DASMINF" OBJA="inffas86.o match.o" |
| 114 | 123 | LIBTARGETS = $(ZLIBDIR)/inffas86.o $(ZLIBDIR)/match.o |
| 124 | +else | |
| 125 | +ZLIBCONFIG = | |
| 126 | +LIBTARGETS = | |
| 127 | +endif | |
| 115 | 128 | else |
| 116 | 129 | SSLCONFIG = mingw64 |
| 117 | -ZLIBCONFIG = | |
| 130 | +ZLIBCONFIG = | |
| 118 | 131 | LIBTARGETS = |
| 119 | 132 | endif |
| 120 | 133 | |
| 134 | +#### Disable creation of the OpenSSL shared libraries. Also, disable support | |
| 135 | +# for both SSLv2 and SSLv3 (i.e. thereby forcing the use of TLS). | |
| 136 | +# | |
| 137 | +SSLCONFIG += no-ssl2 no-ssl3 no-shared | |
| 138 | + | |
| 139 | +#### When using zlib, make sure that OpenSSL is configured to use the zlib | |
| 140 | +# that Fossil knows about (i.e. the one within the source tree). | |
| 141 | +# | |
| 121 | 142 | ifndef FOSSIL_ENABLE_MINIZ |
| 122 | 143 | SSLCONFIG += --with-zlib-lib=$(PWD)/$(ZLIBDIR) --with-zlib-include=$(PWD)/$(ZLIBDIR) zlib |
| 123 | 144 | endif |
| 124 | 145 | |
| 125 | 146 | #### The directories where the OpenSSL include and library files are located. |
| @@ -352,10 +373,11 @@ | ||
| 352 | 373 | $(SRCDIR)/bisect.c \ |
| 353 | 374 | $(SRCDIR)/blob.c \ |
| 354 | 375 | $(SRCDIR)/branch.c \ |
| 355 | 376 | $(SRCDIR)/browse.c \ |
| 356 | 377 | $(SRCDIR)/builtin.c \ |
| 378 | + $(SRCDIR)/bundle.c \ | |
| 357 | 379 | $(SRCDIR)/cache.c \ |
| 358 | 380 | $(SRCDIR)/captcha.c \ |
| 359 | 381 | $(SRCDIR)/cgi.c \ |
| 360 | 382 | $(SRCDIR)/checkin.c \ |
| 361 | 383 | $(SRCDIR)/checkout.c \ |
| @@ -374,10 +396,11 @@ | ||
| 374 | 396 | $(SRCDIR)/encode.c \ |
| 375 | 397 | $(SRCDIR)/event.c \ |
| 376 | 398 | $(SRCDIR)/export.c \ |
| 377 | 399 | $(SRCDIR)/file.c \ |
| 378 | 400 | $(SRCDIR)/finfo.c \ |
| 401 | + $(SRCDIR)/foci.c \ | |
| 379 | 402 | $(SRCDIR)/fusefs.c \ |
| 380 | 403 | $(SRCDIR)/glob.c \ |
| 381 | 404 | $(SRCDIR)/graph.c \ |
| 382 | 405 | $(SRCDIR)/gzip.c \ |
| 383 | 406 | $(SRCDIR)/http.c \ |
| @@ -417,19 +440,22 @@ | ||
| 417 | 440 | $(SRCDIR)/path.c \ |
| 418 | 441 | $(SRCDIR)/pivot.c \ |
| 419 | 442 | $(SRCDIR)/popen.c \ |
| 420 | 443 | $(SRCDIR)/pqueue.c \ |
| 421 | 444 | $(SRCDIR)/printf.c \ |
| 445 | + $(SRCDIR)/publish.c \ | |
| 446 | + $(SRCDIR)/purge.c \ | |
| 422 | 447 | $(SRCDIR)/rebuild.c \ |
| 423 | 448 | $(SRCDIR)/regexp.c \ |
| 424 | 449 | $(SRCDIR)/report.c \ |
| 425 | 450 | $(SRCDIR)/rss.c \ |
| 426 | 451 | $(SRCDIR)/schema.c \ |
| 427 | 452 | $(SRCDIR)/search.c \ |
| 428 | 453 | $(SRCDIR)/setup.c \ |
| 429 | 454 | $(SRCDIR)/sha1.c \ |
| 430 | 455 | $(SRCDIR)/shun.c \ |
| 456 | + $(SRCDIR)/sitemap.c \ | |
| 431 | 457 | $(SRCDIR)/skins.c \ |
| 432 | 458 | $(SRCDIR)/sqlcmd.c \ |
| 433 | 459 | $(SRCDIR)/stash.c \ |
| 434 | 460 | $(SRCDIR)/stat.c \ |
| 435 | 461 | $(SRCDIR)/style.c \ |
| @@ -469,10 +495,11 @@ | ||
| 469 | 495 | $(OBJDIR)/bisect_.c \ |
| 470 | 496 | $(OBJDIR)/blob_.c \ |
| 471 | 497 | $(OBJDIR)/branch_.c \ |
| 472 | 498 | $(OBJDIR)/browse_.c \ |
| 473 | 499 | $(OBJDIR)/builtin_.c \ |
| 500 | + $(OBJDIR)/bundle_.c \ | |
| 474 | 501 | $(OBJDIR)/cache_.c \ |
| 475 | 502 | $(OBJDIR)/captcha_.c \ |
| 476 | 503 | $(OBJDIR)/cgi_.c \ |
| 477 | 504 | $(OBJDIR)/checkin_.c \ |
| 478 | 505 | $(OBJDIR)/checkout_.c \ |
| @@ -491,10 +518,11 @@ | ||
| 491 | 518 | $(OBJDIR)/encode_.c \ |
| 492 | 519 | $(OBJDIR)/event_.c \ |
| 493 | 520 | $(OBJDIR)/export_.c \ |
| 494 | 521 | $(OBJDIR)/file_.c \ |
| 495 | 522 | $(OBJDIR)/finfo_.c \ |
| 523 | + $(OBJDIR)/foci_.c \ | |
| 496 | 524 | $(OBJDIR)/fusefs_.c \ |
| 497 | 525 | $(OBJDIR)/glob_.c \ |
| 498 | 526 | $(OBJDIR)/graph_.c \ |
| 499 | 527 | $(OBJDIR)/gzip_.c \ |
| 500 | 528 | $(OBJDIR)/http_.c \ |
| @@ -534,19 +562,22 @@ | ||
| 534 | 562 | $(OBJDIR)/path_.c \ |
| 535 | 563 | $(OBJDIR)/pivot_.c \ |
| 536 | 564 | $(OBJDIR)/popen_.c \ |
| 537 | 565 | $(OBJDIR)/pqueue_.c \ |
| 538 | 566 | $(OBJDIR)/printf_.c \ |
| 567 | + $(OBJDIR)/publish_.c \ | |
| 568 | + $(OBJDIR)/purge_.c \ | |
| 539 | 569 | $(OBJDIR)/rebuild_.c \ |
| 540 | 570 | $(OBJDIR)/regexp_.c \ |
| 541 | 571 | $(OBJDIR)/report_.c \ |
| 542 | 572 | $(OBJDIR)/rss_.c \ |
| 543 | 573 | $(OBJDIR)/schema_.c \ |
| 544 | 574 | $(OBJDIR)/search_.c \ |
| 545 | 575 | $(OBJDIR)/setup_.c \ |
| 546 | 576 | $(OBJDIR)/sha1_.c \ |
| 547 | 577 | $(OBJDIR)/shun_.c \ |
| 578 | + $(OBJDIR)/sitemap_.c \ | |
| 548 | 579 | $(OBJDIR)/skins_.c \ |
| 549 | 580 | $(OBJDIR)/sqlcmd_.c \ |
| 550 | 581 | $(OBJDIR)/stash_.c \ |
| 551 | 582 | $(OBJDIR)/stat_.c \ |
| 552 | 583 | $(OBJDIR)/style_.c \ |
| @@ -583,10 +614,11 @@ | ||
| 583 | 614 | $(OBJDIR)/bisect.o \ |
| 584 | 615 | $(OBJDIR)/blob.o \ |
| 585 | 616 | $(OBJDIR)/branch.o \ |
| 586 | 617 | $(OBJDIR)/browse.o \ |
| 587 | 618 | $(OBJDIR)/builtin.o \ |
| 619 | + $(OBJDIR)/bundle.o \ | |
| 588 | 620 | $(OBJDIR)/cache.o \ |
| 589 | 621 | $(OBJDIR)/captcha.o \ |
| 590 | 622 | $(OBJDIR)/cgi.o \ |
| 591 | 623 | $(OBJDIR)/checkin.o \ |
| 592 | 624 | $(OBJDIR)/checkout.o \ |
| @@ -605,10 +637,11 @@ | ||
| 605 | 637 | $(OBJDIR)/encode.o \ |
| 606 | 638 | $(OBJDIR)/event.o \ |
| 607 | 639 | $(OBJDIR)/export.o \ |
| 608 | 640 | $(OBJDIR)/file.o \ |
| 609 | 641 | $(OBJDIR)/finfo.o \ |
| 642 | + $(OBJDIR)/foci.o \ | |
| 610 | 643 | $(OBJDIR)/fusefs.o \ |
| 611 | 644 | $(OBJDIR)/glob.o \ |
| 612 | 645 | $(OBJDIR)/graph.o \ |
| 613 | 646 | $(OBJDIR)/gzip.o \ |
| 614 | 647 | $(OBJDIR)/http.o \ |
| @@ -648,19 +681,22 @@ | ||
| 648 | 681 | $(OBJDIR)/path.o \ |
| 649 | 682 | $(OBJDIR)/pivot.o \ |
| 650 | 683 | $(OBJDIR)/popen.o \ |
| 651 | 684 | $(OBJDIR)/pqueue.o \ |
| 652 | 685 | $(OBJDIR)/printf.o \ |
| 686 | + $(OBJDIR)/publish.o \ | |
| 687 | + $(OBJDIR)/purge.o \ | |
| 653 | 688 | $(OBJDIR)/rebuild.o \ |
| 654 | 689 | $(OBJDIR)/regexp.o \ |
| 655 | 690 | $(OBJDIR)/report.o \ |
| 656 | 691 | $(OBJDIR)/rss.o \ |
| 657 | 692 | $(OBJDIR)/schema.o \ |
| 658 | 693 | $(OBJDIR)/search.o \ |
| 659 | 694 | $(OBJDIR)/setup.o \ |
| 660 | 695 | $(OBJDIR)/sha1.o \ |
| 661 | 696 | $(OBJDIR)/shun.o \ |
| 697 | + $(OBJDIR)/sitemap.o \ | |
| 662 | 698 | $(OBJDIR)/skins.o \ |
| 663 | 699 | $(OBJDIR)/sqlcmd.o \ |
| 664 | 700 | $(OBJDIR)/stash.o \ |
| 665 | 701 | $(OBJDIR)/stat.o \ |
| 666 | 702 | $(OBJDIR)/style.o \ |
| @@ -890,10 +926,11 @@ | ||
| 890 | 926 | $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h \ |
| 891 | 927 | $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h \ |
| 892 | 928 | $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h \ |
| 893 | 929 | $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h \ |
| 894 | 930 | $(OBJDIR)/builtin_.c:$(OBJDIR)/builtin.h \ |
| 931 | + $(OBJDIR)/bundle_.c:$(OBJDIR)/bundle.h \ | |
| 895 | 932 | $(OBJDIR)/cache_.c:$(OBJDIR)/cache.h \ |
| 896 | 933 | $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h \ |
| 897 | 934 | $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h \ |
| 898 | 935 | $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h \ |
| 899 | 936 | $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h \ |
| @@ -912,10 +949,11 @@ | ||
| 912 | 949 | $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h \ |
| 913 | 950 | $(OBJDIR)/event_.c:$(OBJDIR)/event.h \ |
| 914 | 951 | $(OBJDIR)/export_.c:$(OBJDIR)/export.h \ |
| 915 | 952 | $(OBJDIR)/file_.c:$(OBJDIR)/file.h \ |
| 916 | 953 | $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h \ |
| 954 | + $(OBJDIR)/foci_.c:$(OBJDIR)/foci.h \ | |
| 917 | 955 | $(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \ |
| 918 | 956 | $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h \ |
| 919 | 957 | $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h \ |
| 920 | 958 | $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h \ |
| 921 | 959 | $(OBJDIR)/http_.c:$(OBJDIR)/http.h \ |
| @@ -955,19 +993,22 @@ | ||
| 955 | 993 | $(OBJDIR)/path_.c:$(OBJDIR)/path.h \ |
| 956 | 994 | $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \ |
| 957 | 995 | $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \ |
| 958 | 996 | $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \ |
| 959 | 997 | $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \ |
| 998 | + $(OBJDIR)/publish_.c:$(OBJDIR)/publish.h \ | |
| 999 | + $(OBJDIR)/purge_.c:$(OBJDIR)/purge.h \ | |
| 960 | 1000 | $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h \ |
| 961 | 1001 | $(OBJDIR)/regexp_.c:$(OBJDIR)/regexp.h \ |
| 962 | 1002 | $(OBJDIR)/report_.c:$(OBJDIR)/report.h \ |
| 963 | 1003 | $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \ |
| 964 | 1004 | $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \ |
| 965 | 1005 | $(OBJDIR)/search_.c:$(OBJDIR)/search.h \ |
| 966 | 1006 | $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \ |
| 967 | 1007 | $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \ |
| 968 | 1008 | $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \ |
| 1009 | + $(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \ | |
| 969 | 1010 | $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \ |
| 970 | 1011 | $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \ |
| 971 | 1012 | $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \ |
| 972 | 1013 | $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h \ |
| 973 | 1014 | $(OBJDIR)/style_.c:$(OBJDIR)/style.h \ |
| @@ -1073,10 +1114,18 @@ | ||
| 1073 | 1114 | |
| 1074 | 1115 | $(OBJDIR)/builtin.o: $(OBJDIR)/builtin_.c $(OBJDIR)/builtin.h $(OBJDIR)/builtin_data.h $(SRCDIR)/config.h |
| 1075 | 1116 | $(XTCC) -o $(OBJDIR)/builtin.o -c $(OBJDIR)/builtin_.c |
| 1076 | 1117 | |
| 1077 | 1118 | $(OBJDIR)/builtin.h: $(OBJDIR)/headers |
| 1119 | + | |
| 1120 | +$(OBJDIR)/bundle_.c: $(SRCDIR)/bundle.c $(TRANSLATE) | |
| 1121 | + $(TRANSLATE) $(SRCDIR)/bundle.c >$@ | |
| 1122 | + | |
| 1123 | +$(OBJDIR)/bundle.o: $(OBJDIR)/bundle_.c $(OBJDIR)/bundle.h $(SRCDIR)/config.h | |
| 1124 | + $(XTCC) -o $(OBJDIR)/bundle.o -c $(OBJDIR)/bundle_.c | |
| 1125 | + | |
| 1126 | +$(OBJDIR)/bundle.h: $(OBJDIR)/headers | |
| 1078 | 1127 | |
| 1079 | 1128 | $(OBJDIR)/cache_.c: $(SRCDIR)/cache.c $(TRANSLATE) |
| 1080 | 1129 | $(TRANSLATE) $(SRCDIR)/cache.c >$@ |
| 1081 | 1130 | |
| 1082 | 1131 | $(OBJDIR)/cache.o: $(OBJDIR)/cache_.c $(OBJDIR)/cache.h $(SRCDIR)/config.h |
| @@ -1249,10 +1298,18 @@ | ||
| 1249 | 1298 | |
| 1250 | 1299 | $(OBJDIR)/finfo.o: $(OBJDIR)/finfo_.c $(OBJDIR)/finfo.h $(SRCDIR)/config.h |
| 1251 | 1300 | $(XTCC) -o $(OBJDIR)/finfo.o -c $(OBJDIR)/finfo_.c |
| 1252 | 1301 | |
| 1253 | 1302 | $(OBJDIR)/finfo.h: $(OBJDIR)/headers |
| 1303 | + | |
| 1304 | +$(OBJDIR)/foci_.c: $(SRCDIR)/foci.c $(TRANSLATE) | |
| 1305 | + $(TRANSLATE) $(SRCDIR)/foci.c >$@ | |
| 1306 | + | |
| 1307 | +$(OBJDIR)/foci.o: $(OBJDIR)/foci_.c $(OBJDIR)/foci.h $(SRCDIR)/config.h | |
| 1308 | + $(XTCC) -o $(OBJDIR)/foci.o -c $(OBJDIR)/foci_.c | |
| 1309 | + | |
| 1310 | +$(OBJDIR)/foci.h: $(OBJDIR)/headers | |
| 1254 | 1311 | |
| 1255 | 1312 | $(OBJDIR)/fusefs_.c: $(SRCDIR)/fusefs.c $(TRANSLATE) |
| 1256 | 1313 | $(TRANSLATE) $(SRCDIR)/fusefs.c >$@ |
| 1257 | 1314 | |
| 1258 | 1315 | $(OBJDIR)/fusefs.o: $(OBJDIR)/fusefs_.c $(OBJDIR)/fusefs.h $(SRCDIR)/config.h |
| @@ -1593,10 +1650,26 @@ | ||
| 1593 | 1650 | |
| 1594 | 1651 | $(OBJDIR)/printf.o: $(OBJDIR)/printf_.c $(OBJDIR)/printf.h $(SRCDIR)/config.h |
| 1595 | 1652 | $(XTCC) -o $(OBJDIR)/printf.o -c $(OBJDIR)/printf_.c |
| 1596 | 1653 | |
| 1597 | 1654 | $(OBJDIR)/printf.h: $(OBJDIR)/headers |
| 1655 | + | |
| 1656 | +$(OBJDIR)/publish_.c: $(SRCDIR)/publish.c $(TRANSLATE) | |
| 1657 | + $(TRANSLATE) $(SRCDIR)/publish.c >$@ | |
| 1658 | + | |
| 1659 | +$(OBJDIR)/publish.o: $(OBJDIR)/publish_.c $(OBJDIR)/publish.h $(SRCDIR)/config.h | |
| 1660 | + $(XTCC) -o $(OBJDIR)/publish.o -c $(OBJDIR)/publish_.c | |
| 1661 | + | |
| 1662 | +$(OBJDIR)/publish.h: $(OBJDIR)/headers | |
| 1663 | + | |
| 1664 | +$(OBJDIR)/purge_.c: $(SRCDIR)/purge.c $(TRANSLATE) | |
| 1665 | + $(TRANSLATE) $(SRCDIR)/purge.c >$@ | |
| 1666 | + | |
| 1667 | +$(OBJDIR)/purge.o: $(OBJDIR)/purge_.c $(OBJDIR)/purge.h $(SRCDIR)/config.h | |
| 1668 | + $(XTCC) -o $(OBJDIR)/purge.o -c $(OBJDIR)/purge_.c | |
| 1669 | + | |
| 1670 | +$(OBJDIR)/purge.h: $(OBJDIR)/headers | |
| 1598 | 1671 | |
| 1599 | 1672 | $(OBJDIR)/rebuild_.c: $(SRCDIR)/rebuild.c $(TRANSLATE) |
| 1600 | 1673 | $(TRANSLATE) $(SRCDIR)/rebuild.c >$@ |
| 1601 | 1674 | |
| 1602 | 1675 | $(OBJDIR)/rebuild.o: $(OBJDIR)/rebuild_.c $(OBJDIR)/rebuild.h $(SRCDIR)/config.h |
| @@ -1665,10 +1738,18 @@ | ||
| 1665 | 1738 | |
| 1666 | 1739 | $(OBJDIR)/shun.o: $(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h |
| 1667 | 1740 | $(XTCC) -o $(OBJDIR)/shun.o -c $(OBJDIR)/shun_.c |
| 1668 | 1741 | |
| 1669 | 1742 | $(OBJDIR)/shun.h: $(OBJDIR)/headers |
| 1743 | + | |
| 1744 | +$(OBJDIR)/sitemap_.c: $(SRCDIR)/sitemap.c $(TRANSLATE) | |
| 1745 | + $(TRANSLATE) $(SRCDIR)/sitemap.c >$@ | |
| 1746 | + | |
| 1747 | +$(OBJDIR)/sitemap.o: $(OBJDIR)/sitemap_.c $(OBJDIR)/sitemap.h $(SRCDIR)/config.h | |
| 1748 | + $(XTCC) -o $(OBJDIR)/sitemap.o -c $(OBJDIR)/sitemap_.c | |
| 1749 | + | |
| 1750 | +$(OBJDIR)/sitemap.h: $(OBJDIR)/headers | |
| 1670 | 1751 | |
| 1671 | 1752 | $(OBJDIR)/skins_.c: $(SRCDIR)/skins.c $(TRANSLATE) |
| 1672 | 1753 | $(TRANSLATE) $(SRCDIR)/skins.c >$@ |
| 1673 | 1754 | |
| 1674 | 1755 | $(OBJDIR)/skins.o: $(OBJDIR)/skins_.c $(OBJDIR)/skins.h $(SRCDIR)/config.h |
| 1675 | 1756 |
| --- win/Makefile.mingw.mistachkin | |
| +++ win/Makefile.mingw.mistachkin | |
| @@ -87,11 +87,12 @@ | |
| 87 | # This is useful when Tcl has been compiled statically with MinGW. |
| 88 | # |
| 89 | FOSSIL_TCL_SOURCE = 1 |
| 90 | |
| 91 | #### Check if the workaround for the MinGW command line handling needs to |
| 92 | # be enabled by default. |
| 93 | # |
| 94 | ifndef MINGW_IS_32BIT_ONLY |
| 95 | ifeq (,$(findstring w64-mingw32,$(PREFIX))) |
| 96 | MINGW_IS_32BIT_ONLY = 1 |
| 97 | endif |
| @@ -100,26 +101,46 @@ | |
| 100 | #### The directories where the zlib include and library files are located. |
| 101 | # |
| 102 | ZINCDIR = $(SRCDIR)/../compat/zlib |
| 103 | ZLIBDIR = $(SRCDIR)/../compat/zlib |
| 104 | |
| 105 | ifndef X64 |
| 106 | ifneq (,$(findstring x86_64-w64-mingw32,$(PREFIX))) |
| 107 | X64 = 1 |
| 108 | endif |
| 109 | endif |
| 110 | |
| 111 | ifndef X64 |
| 112 | SSLCONFIG = mingw |
| 113 | ZLIBCONFIG = LOC="-DASMV -DASMINF" OBJA="inffas86.o match.o" |
| 114 | LIBTARGETS = $(ZLIBDIR)/inffas86.o $(ZLIBDIR)/match.o |
| 115 | else |
| 116 | SSLCONFIG = mingw64 |
| 117 | ZLIBCONFIG = |
| 118 | LIBTARGETS = |
| 119 | endif |
| 120 | |
| 121 | ifndef FOSSIL_ENABLE_MINIZ |
| 122 | SSLCONFIG += --with-zlib-lib=$(PWD)/$(ZLIBDIR) --with-zlib-include=$(PWD)/$(ZLIBDIR) zlib |
| 123 | endif |
| 124 | |
| 125 | #### The directories where the OpenSSL include and library files are located. |
| @@ -352,10 +373,11 @@ | |
| 352 | $(SRCDIR)/bisect.c \ |
| 353 | $(SRCDIR)/blob.c \ |
| 354 | $(SRCDIR)/branch.c \ |
| 355 | $(SRCDIR)/browse.c \ |
| 356 | $(SRCDIR)/builtin.c \ |
| 357 | $(SRCDIR)/cache.c \ |
| 358 | $(SRCDIR)/captcha.c \ |
| 359 | $(SRCDIR)/cgi.c \ |
| 360 | $(SRCDIR)/checkin.c \ |
| 361 | $(SRCDIR)/checkout.c \ |
| @@ -374,10 +396,11 @@ | |
| 374 | $(SRCDIR)/encode.c \ |
| 375 | $(SRCDIR)/event.c \ |
| 376 | $(SRCDIR)/export.c \ |
| 377 | $(SRCDIR)/file.c \ |
| 378 | $(SRCDIR)/finfo.c \ |
| 379 | $(SRCDIR)/fusefs.c \ |
| 380 | $(SRCDIR)/glob.c \ |
| 381 | $(SRCDIR)/graph.c \ |
| 382 | $(SRCDIR)/gzip.c \ |
| 383 | $(SRCDIR)/http.c \ |
| @@ -417,19 +440,22 @@ | |
| 417 | $(SRCDIR)/path.c \ |
| 418 | $(SRCDIR)/pivot.c \ |
| 419 | $(SRCDIR)/popen.c \ |
| 420 | $(SRCDIR)/pqueue.c \ |
| 421 | $(SRCDIR)/printf.c \ |
| 422 | $(SRCDIR)/rebuild.c \ |
| 423 | $(SRCDIR)/regexp.c \ |
| 424 | $(SRCDIR)/report.c \ |
| 425 | $(SRCDIR)/rss.c \ |
| 426 | $(SRCDIR)/schema.c \ |
| 427 | $(SRCDIR)/search.c \ |
| 428 | $(SRCDIR)/setup.c \ |
| 429 | $(SRCDIR)/sha1.c \ |
| 430 | $(SRCDIR)/shun.c \ |
| 431 | $(SRCDIR)/skins.c \ |
| 432 | $(SRCDIR)/sqlcmd.c \ |
| 433 | $(SRCDIR)/stash.c \ |
| 434 | $(SRCDIR)/stat.c \ |
| 435 | $(SRCDIR)/style.c \ |
| @@ -469,10 +495,11 @@ | |
| 469 | $(OBJDIR)/bisect_.c \ |
| 470 | $(OBJDIR)/blob_.c \ |
| 471 | $(OBJDIR)/branch_.c \ |
| 472 | $(OBJDIR)/browse_.c \ |
| 473 | $(OBJDIR)/builtin_.c \ |
| 474 | $(OBJDIR)/cache_.c \ |
| 475 | $(OBJDIR)/captcha_.c \ |
| 476 | $(OBJDIR)/cgi_.c \ |
| 477 | $(OBJDIR)/checkin_.c \ |
| 478 | $(OBJDIR)/checkout_.c \ |
| @@ -491,10 +518,11 @@ | |
| 491 | $(OBJDIR)/encode_.c \ |
| 492 | $(OBJDIR)/event_.c \ |
| 493 | $(OBJDIR)/export_.c \ |
| 494 | $(OBJDIR)/file_.c \ |
| 495 | $(OBJDIR)/finfo_.c \ |
| 496 | $(OBJDIR)/fusefs_.c \ |
| 497 | $(OBJDIR)/glob_.c \ |
| 498 | $(OBJDIR)/graph_.c \ |
| 499 | $(OBJDIR)/gzip_.c \ |
| 500 | $(OBJDIR)/http_.c \ |
| @@ -534,19 +562,22 @@ | |
| 534 | $(OBJDIR)/path_.c \ |
| 535 | $(OBJDIR)/pivot_.c \ |
| 536 | $(OBJDIR)/popen_.c \ |
| 537 | $(OBJDIR)/pqueue_.c \ |
| 538 | $(OBJDIR)/printf_.c \ |
| 539 | $(OBJDIR)/rebuild_.c \ |
| 540 | $(OBJDIR)/regexp_.c \ |
| 541 | $(OBJDIR)/report_.c \ |
| 542 | $(OBJDIR)/rss_.c \ |
| 543 | $(OBJDIR)/schema_.c \ |
| 544 | $(OBJDIR)/search_.c \ |
| 545 | $(OBJDIR)/setup_.c \ |
| 546 | $(OBJDIR)/sha1_.c \ |
| 547 | $(OBJDIR)/shun_.c \ |
| 548 | $(OBJDIR)/skins_.c \ |
| 549 | $(OBJDIR)/sqlcmd_.c \ |
| 550 | $(OBJDIR)/stash_.c \ |
| 551 | $(OBJDIR)/stat_.c \ |
| 552 | $(OBJDIR)/style_.c \ |
| @@ -583,10 +614,11 @@ | |
| 583 | $(OBJDIR)/bisect.o \ |
| 584 | $(OBJDIR)/blob.o \ |
| 585 | $(OBJDIR)/branch.o \ |
| 586 | $(OBJDIR)/browse.o \ |
| 587 | $(OBJDIR)/builtin.o \ |
| 588 | $(OBJDIR)/cache.o \ |
| 589 | $(OBJDIR)/captcha.o \ |
| 590 | $(OBJDIR)/cgi.o \ |
| 591 | $(OBJDIR)/checkin.o \ |
| 592 | $(OBJDIR)/checkout.o \ |
| @@ -605,10 +637,11 @@ | |
| 605 | $(OBJDIR)/encode.o \ |
| 606 | $(OBJDIR)/event.o \ |
| 607 | $(OBJDIR)/export.o \ |
| 608 | $(OBJDIR)/file.o \ |
| 609 | $(OBJDIR)/finfo.o \ |
| 610 | $(OBJDIR)/fusefs.o \ |
| 611 | $(OBJDIR)/glob.o \ |
| 612 | $(OBJDIR)/graph.o \ |
| 613 | $(OBJDIR)/gzip.o \ |
| 614 | $(OBJDIR)/http.o \ |
| @@ -648,19 +681,22 @@ | |
| 648 | $(OBJDIR)/path.o \ |
| 649 | $(OBJDIR)/pivot.o \ |
| 650 | $(OBJDIR)/popen.o \ |
| 651 | $(OBJDIR)/pqueue.o \ |
| 652 | $(OBJDIR)/printf.o \ |
| 653 | $(OBJDIR)/rebuild.o \ |
| 654 | $(OBJDIR)/regexp.o \ |
| 655 | $(OBJDIR)/report.o \ |
| 656 | $(OBJDIR)/rss.o \ |
| 657 | $(OBJDIR)/schema.o \ |
| 658 | $(OBJDIR)/search.o \ |
| 659 | $(OBJDIR)/setup.o \ |
| 660 | $(OBJDIR)/sha1.o \ |
| 661 | $(OBJDIR)/shun.o \ |
| 662 | $(OBJDIR)/skins.o \ |
| 663 | $(OBJDIR)/sqlcmd.o \ |
| 664 | $(OBJDIR)/stash.o \ |
| 665 | $(OBJDIR)/stat.o \ |
| 666 | $(OBJDIR)/style.o \ |
| @@ -890,10 +926,11 @@ | |
| 890 | $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h \ |
| 891 | $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h \ |
| 892 | $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h \ |
| 893 | $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h \ |
| 894 | $(OBJDIR)/builtin_.c:$(OBJDIR)/builtin.h \ |
| 895 | $(OBJDIR)/cache_.c:$(OBJDIR)/cache.h \ |
| 896 | $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h \ |
| 897 | $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h \ |
| 898 | $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h \ |
| 899 | $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h \ |
| @@ -912,10 +949,11 @@ | |
| 912 | $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h \ |
| 913 | $(OBJDIR)/event_.c:$(OBJDIR)/event.h \ |
| 914 | $(OBJDIR)/export_.c:$(OBJDIR)/export.h \ |
| 915 | $(OBJDIR)/file_.c:$(OBJDIR)/file.h \ |
| 916 | $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h \ |
| 917 | $(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \ |
| 918 | $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h \ |
| 919 | $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h \ |
| 920 | $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h \ |
| 921 | $(OBJDIR)/http_.c:$(OBJDIR)/http.h \ |
| @@ -955,19 +993,22 @@ | |
| 955 | $(OBJDIR)/path_.c:$(OBJDIR)/path.h \ |
| 956 | $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \ |
| 957 | $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \ |
| 958 | $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \ |
| 959 | $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \ |
| 960 | $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h \ |
| 961 | $(OBJDIR)/regexp_.c:$(OBJDIR)/regexp.h \ |
| 962 | $(OBJDIR)/report_.c:$(OBJDIR)/report.h \ |
| 963 | $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \ |
| 964 | $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \ |
| 965 | $(OBJDIR)/search_.c:$(OBJDIR)/search.h \ |
| 966 | $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \ |
| 967 | $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \ |
| 968 | $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \ |
| 969 | $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \ |
| 970 | $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \ |
| 971 | $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \ |
| 972 | $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h \ |
| 973 | $(OBJDIR)/style_.c:$(OBJDIR)/style.h \ |
| @@ -1073,10 +1114,18 @@ | |
| 1073 | |
| 1074 | $(OBJDIR)/builtin.o: $(OBJDIR)/builtin_.c $(OBJDIR)/builtin.h $(OBJDIR)/builtin_data.h $(SRCDIR)/config.h |
| 1075 | $(XTCC) -o $(OBJDIR)/builtin.o -c $(OBJDIR)/builtin_.c |
| 1076 | |
| 1077 | $(OBJDIR)/builtin.h: $(OBJDIR)/headers |
| 1078 | |
| 1079 | $(OBJDIR)/cache_.c: $(SRCDIR)/cache.c $(TRANSLATE) |
| 1080 | $(TRANSLATE) $(SRCDIR)/cache.c >$@ |
| 1081 | |
| 1082 | $(OBJDIR)/cache.o: $(OBJDIR)/cache_.c $(OBJDIR)/cache.h $(SRCDIR)/config.h |
| @@ -1249,10 +1298,18 @@ | |
| 1249 | |
| 1250 | $(OBJDIR)/finfo.o: $(OBJDIR)/finfo_.c $(OBJDIR)/finfo.h $(SRCDIR)/config.h |
| 1251 | $(XTCC) -o $(OBJDIR)/finfo.o -c $(OBJDIR)/finfo_.c |
| 1252 | |
| 1253 | $(OBJDIR)/finfo.h: $(OBJDIR)/headers |
| 1254 | |
| 1255 | $(OBJDIR)/fusefs_.c: $(SRCDIR)/fusefs.c $(TRANSLATE) |
| 1256 | $(TRANSLATE) $(SRCDIR)/fusefs.c >$@ |
| 1257 | |
| 1258 | $(OBJDIR)/fusefs.o: $(OBJDIR)/fusefs_.c $(OBJDIR)/fusefs.h $(SRCDIR)/config.h |
| @@ -1593,10 +1650,26 @@ | |
| 1593 | |
| 1594 | $(OBJDIR)/printf.o: $(OBJDIR)/printf_.c $(OBJDIR)/printf.h $(SRCDIR)/config.h |
| 1595 | $(XTCC) -o $(OBJDIR)/printf.o -c $(OBJDIR)/printf_.c |
| 1596 | |
| 1597 | $(OBJDIR)/printf.h: $(OBJDIR)/headers |
| 1598 | |
| 1599 | $(OBJDIR)/rebuild_.c: $(SRCDIR)/rebuild.c $(TRANSLATE) |
| 1600 | $(TRANSLATE) $(SRCDIR)/rebuild.c >$@ |
| 1601 | |
| 1602 | $(OBJDIR)/rebuild.o: $(OBJDIR)/rebuild_.c $(OBJDIR)/rebuild.h $(SRCDIR)/config.h |
| @@ -1665,10 +1738,18 @@ | |
| 1665 | |
| 1666 | $(OBJDIR)/shun.o: $(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h |
| 1667 | $(XTCC) -o $(OBJDIR)/shun.o -c $(OBJDIR)/shun_.c |
| 1668 | |
| 1669 | $(OBJDIR)/shun.h: $(OBJDIR)/headers |
| 1670 | |
| 1671 | $(OBJDIR)/skins_.c: $(SRCDIR)/skins.c $(TRANSLATE) |
| 1672 | $(TRANSLATE) $(SRCDIR)/skins.c >$@ |
| 1673 | |
| 1674 | $(OBJDIR)/skins.o: $(OBJDIR)/skins_.c $(OBJDIR)/skins.h $(SRCDIR)/config.h |
| 1675 |
| --- win/Makefile.mingw.mistachkin | |
| +++ win/Makefile.mingw.mistachkin | |
| @@ -87,11 +87,12 @@ | |
| 87 | # This is useful when Tcl has been compiled statically with MinGW. |
| 88 | # |
| 89 | FOSSIL_TCL_SOURCE = 1 |
| 90 | |
| 91 | #### Check if the workaround for the MinGW command line handling needs to |
| 92 | # be enabled by default. This check may be somewhat fragile due to the |
| 93 | # use of "findstring". |
| 94 | # |
| 95 | ifndef MINGW_IS_32BIT_ONLY |
| 96 | ifeq (,$(findstring w64-mingw32,$(PREFIX))) |
| 97 | MINGW_IS_32BIT_ONLY = 1 |
| 98 | endif |
| @@ -100,26 +101,46 @@ | |
| 101 | #### The directories where the zlib include and library files are located. |
| 102 | # |
| 103 | ZINCDIR = $(SRCDIR)/../compat/zlib |
| 104 | ZLIBDIR = $(SRCDIR)/../compat/zlib |
| 105 | |
| 106 | #### Make an attempt to detect if Fossil is being built for the x64 processor |
| 107 | # architecture. This check may be somewhat fragile due to "findstring". |
| 108 | # |
| 109 | ifndef X64 |
| 110 | ifneq (,$(findstring x86_64-w64-mingw32,$(PREFIX))) |
| 111 | X64 = 1 |
| 112 | endif |
| 113 | endif |
| 114 | |
| 115 | #### Determine if the optimized assembly routines provided with zlib should be |
| 116 | # used, taking into account whether zlib is actually enabled and the target |
| 117 | # processor architecture. |
| 118 | # |
| 119 | ifndef X64 |
| 120 | SSLCONFIG = mingw |
| 121 | ifndef FOSSIL_ENABLE_MINIZ |
| 122 | ZLIBCONFIG = LOC="-DASMV -DASMINF" OBJA="inffas86.o match.o" |
| 123 | LIBTARGETS = $(ZLIBDIR)/inffas86.o $(ZLIBDIR)/match.o |
| 124 | else |
| 125 | ZLIBCONFIG = |
| 126 | LIBTARGETS = |
| 127 | endif |
| 128 | else |
| 129 | SSLCONFIG = mingw64 |
| 130 | ZLIBCONFIG = |
| 131 | LIBTARGETS = |
| 132 | endif |
| 133 | |
| 134 | #### Disable creation of the OpenSSL shared libraries. Also, disable support |
| 135 | # for both SSLv2 and SSLv3 (i.e. thereby forcing the use of TLS). |
| 136 | # |
| 137 | SSLCONFIG += no-ssl2 no-ssl3 no-shared |
| 138 | |
| 139 | #### When using zlib, make sure that OpenSSL is configured to use the zlib |
| 140 | # that Fossil knows about (i.e. the one within the source tree). |
| 141 | # |
| 142 | ifndef FOSSIL_ENABLE_MINIZ |
| 143 | SSLCONFIG += --with-zlib-lib=$(PWD)/$(ZLIBDIR) --with-zlib-include=$(PWD)/$(ZLIBDIR) zlib |
| 144 | endif |
| 145 | |
| 146 | #### The directories where the OpenSSL include and library files are located. |
| @@ -352,10 +373,11 @@ | |
| 373 | $(SRCDIR)/bisect.c \ |
| 374 | $(SRCDIR)/blob.c \ |
| 375 | $(SRCDIR)/branch.c \ |
| 376 | $(SRCDIR)/browse.c \ |
| 377 | $(SRCDIR)/builtin.c \ |
| 378 | $(SRCDIR)/bundle.c \ |
| 379 | $(SRCDIR)/cache.c \ |
| 380 | $(SRCDIR)/captcha.c \ |
| 381 | $(SRCDIR)/cgi.c \ |
| 382 | $(SRCDIR)/checkin.c \ |
| 383 | $(SRCDIR)/checkout.c \ |
| @@ -374,10 +396,11 @@ | |
| 396 | $(SRCDIR)/encode.c \ |
| 397 | $(SRCDIR)/event.c \ |
| 398 | $(SRCDIR)/export.c \ |
| 399 | $(SRCDIR)/file.c \ |
| 400 | $(SRCDIR)/finfo.c \ |
| 401 | $(SRCDIR)/foci.c \ |
| 402 | $(SRCDIR)/fusefs.c \ |
| 403 | $(SRCDIR)/glob.c \ |
| 404 | $(SRCDIR)/graph.c \ |
| 405 | $(SRCDIR)/gzip.c \ |
| 406 | $(SRCDIR)/http.c \ |
| @@ -417,19 +440,22 @@ | |
| 440 | $(SRCDIR)/path.c \ |
| 441 | $(SRCDIR)/pivot.c \ |
| 442 | $(SRCDIR)/popen.c \ |
| 443 | $(SRCDIR)/pqueue.c \ |
| 444 | $(SRCDIR)/printf.c \ |
| 445 | $(SRCDIR)/publish.c \ |
| 446 | $(SRCDIR)/purge.c \ |
| 447 | $(SRCDIR)/rebuild.c \ |
| 448 | $(SRCDIR)/regexp.c \ |
| 449 | $(SRCDIR)/report.c \ |
| 450 | $(SRCDIR)/rss.c \ |
| 451 | $(SRCDIR)/schema.c \ |
| 452 | $(SRCDIR)/search.c \ |
| 453 | $(SRCDIR)/setup.c \ |
| 454 | $(SRCDIR)/sha1.c \ |
| 455 | $(SRCDIR)/shun.c \ |
| 456 | $(SRCDIR)/sitemap.c \ |
| 457 | $(SRCDIR)/skins.c \ |
| 458 | $(SRCDIR)/sqlcmd.c \ |
| 459 | $(SRCDIR)/stash.c \ |
| 460 | $(SRCDIR)/stat.c \ |
| 461 | $(SRCDIR)/style.c \ |
| @@ -469,10 +495,11 @@ | |
| 495 | $(OBJDIR)/bisect_.c \ |
| 496 | $(OBJDIR)/blob_.c \ |
| 497 | $(OBJDIR)/branch_.c \ |
| 498 | $(OBJDIR)/browse_.c \ |
| 499 | $(OBJDIR)/builtin_.c \ |
| 500 | $(OBJDIR)/bundle_.c \ |
| 501 | $(OBJDIR)/cache_.c \ |
| 502 | $(OBJDIR)/captcha_.c \ |
| 503 | $(OBJDIR)/cgi_.c \ |
| 504 | $(OBJDIR)/checkin_.c \ |
| 505 | $(OBJDIR)/checkout_.c \ |
| @@ -491,10 +518,11 @@ | |
| 518 | $(OBJDIR)/encode_.c \ |
| 519 | $(OBJDIR)/event_.c \ |
| 520 | $(OBJDIR)/export_.c \ |
| 521 | $(OBJDIR)/file_.c \ |
| 522 | $(OBJDIR)/finfo_.c \ |
| 523 | $(OBJDIR)/foci_.c \ |
| 524 | $(OBJDIR)/fusefs_.c \ |
| 525 | $(OBJDIR)/glob_.c \ |
| 526 | $(OBJDIR)/graph_.c \ |
| 527 | $(OBJDIR)/gzip_.c \ |
| 528 | $(OBJDIR)/http_.c \ |
| @@ -534,19 +562,22 @@ | |
| 562 | $(OBJDIR)/path_.c \ |
| 563 | $(OBJDIR)/pivot_.c \ |
| 564 | $(OBJDIR)/popen_.c \ |
| 565 | $(OBJDIR)/pqueue_.c \ |
| 566 | $(OBJDIR)/printf_.c \ |
| 567 | $(OBJDIR)/publish_.c \ |
| 568 | $(OBJDIR)/purge_.c \ |
| 569 | $(OBJDIR)/rebuild_.c \ |
| 570 | $(OBJDIR)/regexp_.c \ |
| 571 | $(OBJDIR)/report_.c \ |
| 572 | $(OBJDIR)/rss_.c \ |
| 573 | $(OBJDIR)/schema_.c \ |
| 574 | $(OBJDIR)/search_.c \ |
| 575 | $(OBJDIR)/setup_.c \ |
| 576 | $(OBJDIR)/sha1_.c \ |
| 577 | $(OBJDIR)/shun_.c \ |
| 578 | $(OBJDIR)/sitemap_.c \ |
| 579 | $(OBJDIR)/skins_.c \ |
| 580 | $(OBJDIR)/sqlcmd_.c \ |
| 581 | $(OBJDIR)/stash_.c \ |
| 582 | $(OBJDIR)/stat_.c \ |
| 583 | $(OBJDIR)/style_.c \ |
| @@ -583,10 +614,11 @@ | |
| 614 | $(OBJDIR)/bisect.o \ |
| 615 | $(OBJDIR)/blob.o \ |
| 616 | $(OBJDIR)/branch.o \ |
| 617 | $(OBJDIR)/browse.o \ |
| 618 | $(OBJDIR)/builtin.o \ |
| 619 | $(OBJDIR)/bundle.o \ |
| 620 | $(OBJDIR)/cache.o \ |
| 621 | $(OBJDIR)/captcha.o \ |
| 622 | $(OBJDIR)/cgi.o \ |
| 623 | $(OBJDIR)/checkin.o \ |
| 624 | $(OBJDIR)/checkout.o \ |
| @@ -605,10 +637,11 @@ | |
| 637 | $(OBJDIR)/encode.o \ |
| 638 | $(OBJDIR)/event.o \ |
| 639 | $(OBJDIR)/export.o \ |
| 640 | $(OBJDIR)/file.o \ |
| 641 | $(OBJDIR)/finfo.o \ |
| 642 | $(OBJDIR)/foci.o \ |
| 643 | $(OBJDIR)/fusefs.o \ |
| 644 | $(OBJDIR)/glob.o \ |
| 645 | $(OBJDIR)/graph.o \ |
| 646 | $(OBJDIR)/gzip.o \ |
| 647 | $(OBJDIR)/http.o \ |
| @@ -648,19 +681,22 @@ | |
| 681 | $(OBJDIR)/path.o \ |
| 682 | $(OBJDIR)/pivot.o \ |
| 683 | $(OBJDIR)/popen.o \ |
| 684 | $(OBJDIR)/pqueue.o \ |
| 685 | $(OBJDIR)/printf.o \ |
| 686 | $(OBJDIR)/publish.o \ |
| 687 | $(OBJDIR)/purge.o \ |
| 688 | $(OBJDIR)/rebuild.o \ |
| 689 | $(OBJDIR)/regexp.o \ |
| 690 | $(OBJDIR)/report.o \ |
| 691 | $(OBJDIR)/rss.o \ |
| 692 | $(OBJDIR)/schema.o \ |
| 693 | $(OBJDIR)/search.o \ |
| 694 | $(OBJDIR)/setup.o \ |
| 695 | $(OBJDIR)/sha1.o \ |
| 696 | $(OBJDIR)/shun.o \ |
| 697 | $(OBJDIR)/sitemap.o \ |
| 698 | $(OBJDIR)/skins.o \ |
| 699 | $(OBJDIR)/sqlcmd.o \ |
| 700 | $(OBJDIR)/stash.o \ |
| 701 | $(OBJDIR)/stat.o \ |
| 702 | $(OBJDIR)/style.o \ |
| @@ -890,10 +926,11 @@ | |
| 926 | $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h \ |
| 927 | $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h \ |
| 928 | $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h \ |
| 929 | $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h \ |
| 930 | $(OBJDIR)/builtin_.c:$(OBJDIR)/builtin.h \ |
| 931 | $(OBJDIR)/bundle_.c:$(OBJDIR)/bundle.h \ |
| 932 | $(OBJDIR)/cache_.c:$(OBJDIR)/cache.h \ |
| 933 | $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h \ |
| 934 | $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h \ |
| 935 | $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h \ |
| 936 | $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h \ |
| @@ -912,10 +949,11 @@ | |
| 949 | $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h \ |
| 950 | $(OBJDIR)/event_.c:$(OBJDIR)/event.h \ |
| 951 | $(OBJDIR)/export_.c:$(OBJDIR)/export.h \ |
| 952 | $(OBJDIR)/file_.c:$(OBJDIR)/file.h \ |
| 953 | $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h \ |
| 954 | $(OBJDIR)/foci_.c:$(OBJDIR)/foci.h \ |
| 955 | $(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \ |
| 956 | $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h \ |
| 957 | $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h \ |
| 958 | $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h \ |
| 959 | $(OBJDIR)/http_.c:$(OBJDIR)/http.h \ |
| @@ -955,19 +993,22 @@ | |
| 993 | $(OBJDIR)/path_.c:$(OBJDIR)/path.h \ |
| 994 | $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \ |
| 995 | $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \ |
| 996 | $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \ |
| 997 | $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \ |
| 998 | $(OBJDIR)/publish_.c:$(OBJDIR)/publish.h \ |
| 999 | $(OBJDIR)/purge_.c:$(OBJDIR)/purge.h \ |
| 1000 | $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h \ |
| 1001 | $(OBJDIR)/regexp_.c:$(OBJDIR)/regexp.h \ |
| 1002 | $(OBJDIR)/report_.c:$(OBJDIR)/report.h \ |
| 1003 | $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \ |
| 1004 | $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \ |
| 1005 | $(OBJDIR)/search_.c:$(OBJDIR)/search.h \ |
| 1006 | $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \ |
| 1007 | $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \ |
| 1008 | $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \ |
| 1009 | $(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \ |
| 1010 | $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \ |
| 1011 | $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \ |
| 1012 | $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \ |
| 1013 | $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h \ |
| 1014 | $(OBJDIR)/style_.c:$(OBJDIR)/style.h \ |
| @@ -1073,10 +1114,18 @@ | |
| 1114 | |
| 1115 | $(OBJDIR)/builtin.o: $(OBJDIR)/builtin_.c $(OBJDIR)/builtin.h $(OBJDIR)/builtin_data.h $(SRCDIR)/config.h |
| 1116 | $(XTCC) -o $(OBJDIR)/builtin.o -c $(OBJDIR)/builtin_.c |
| 1117 | |
| 1118 | $(OBJDIR)/builtin.h: $(OBJDIR)/headers |
| 1119 | |
| 1120 | $(OBJDIR)/bundle_.c: $(SRCDIR)/bundle.c $(TRANSLATE) |
| 1121 | $(TRANSLATE) $(SRCDIR)/bundle.c >$@ |
| 1122 | |
| 1123 | $(OBJDIR)/bundle.o: $(OBJDIR)/bundle_.c $(OBJDIR)/bundle.h $(SRCDIR)/config.h |
| 1124 | $(XTCC) -o $(OBJDIR)/bundle.o -c $(OBJDIR)/bundle_.c |
| 1125 | |
| 1126 | $(OBJDIR)/bundle.h: $(OBJDIR)/headers |
| 1127 | |
| 1128 | $(OBJDIR)/cache_.c: $(SRCDIR)/cache.c $(TRANSLATE) |
| 1129 | $(TRANSLATE) $(SRCDIR)/cache.c >$@ |
| 1130 | |
| 1131 | $(OBJDIR)/cache.o: $(OBJDIR)/cache_.c $(OBJDIR)/cache.h $(SRCDIR)/config.h |
| @@ -1249,10 +1298,18 @@ | |
| 1298 | |
| 1299 | $(OBJDIR)/finfo.o: $(OBJDIR)/finfo_.c $(OBJDIR)/finfo.h $(SRCDIR)/config.h |
| 1300 | $(XTCC) -o $(OBJDIR)/finfo.o -c $(OBJDIR)/finfo_.c |
| 1301 | |
| 1302 | $(OBJDIR)/finfo.h: $(OBJDIR)/headers |
| 1303 | |
| 1304 | $(OBJDIR)/foci_.c: $(SRCDIR)/foci.c $(TRANSLATE) |
| 1305 | $(TRANSLATE) $(SRCDIR)/foci.c >$@ |
| 1306 | |
| 1307 | $(OBJDIR)/foci.o: $(OBJDIR)/foci_.c $(OBJDIR)/foci.h $(SRCDIR)/config.h |
| 1308 | $(XTCC) -o $(OBJDIR)/foci.o -c $(OBJDIR)/foci_.c |
| 1309 | |
| 1310 | $(OBJDIR)/foci.h: $(OBJDIR)/headers |
| 1311 | |
| 1312 | $(OBJDIR)/fusefs_.c: $(SRCDIR)/fusefs.c $(TRANSLATE) |
| 1313 | $(TRANSLATE) $(SRCDIR)/fusefs.c >$@ |
| 1314 | |
| 1315 | $(OBJDIR)/fusefs.o: $(OBJDIR)/fusefs_.c $(OBJDIR)/fusefs.h $(SRCDIR)/config.h |
| @@ -1593,10 +1650,26 @@ | |
| 1650 | |
| 1651 | $(OBJDIR)/printf.o: $(OBJDIR)/printf_.c $(OBJDIR)/printf.h $(SRCDIR)/config.h |
| 1652 | $(XTCC) -o $(OBJDIR)/printf.o -c $(OBJDIR)/printf_.c |
| 1653 | |
| 1654 | $(OBJDIR)/printf.h: $(OBJDIR)/headers |
| 1655 | |
| 1656 | $(OBJDIR)/publish_.c: $(SRCDIR)/publish.c $(TRANSLATE) |
| 1657 | $(TRANSLATE) $(SRCDIR)/publish.c >$@ |
| 1658 | |
| 1659 | $(OBJDIR)/publish.o: $(OBJDIR)/publish_.c $(OBJDIR)/publish.h $(SRCDIR)/config.h |
| 1660 | $(XTCC) -o $(OBJDIR)/publish.o -c $(OBJDIR)/publish_.c |
| 1661 | |
| 1662 | $(OBJDIR)/publish.h: $(OBJDIR)/headers |
| 1663 | |
| 1664 | $(OBJDIR)/purge_.c: $(SRCDIR)/purge.c $(TRANSLATE) |
| 1665 | $(TRANSLATE) $(SRCDIR)/purge.c >$@ |
| 1666 | |
| 1667 | $(OBJDIR)/purge.o: $(OBJDIR)/purge_.c $(OBJDIR)/purge.h $(SRCDIR)/config.h |
| 1668 | $(XTCC) -o $(OBJDIR)/purge.o -c $(OBJDIR)/purge_.c |
| 1669 | |
| 1670 | $(OBJDIR)/purge.h: $(OBJDIR)/headers |
| 1671 | |
| 1672 | $(OBJDIR)/rebuild_.c: $(SRCDIR)/rebuild.c $(TRANSLATE) |
| 1673 | $(TRANSLATE) $(SRCDIR)/rebuild.c >$@ |
| 1674 | |
| 1675 | $(OBJDIR)/rebuild.o: $(OBJDIR)/rebuild_.c $(OBJDIR)/rebuild.h $(SRCDIR)/config.h |
| @@ -1665,10 +1738,18 @@ | |
| 1738 | |
| 1739 | $(OBJDIR)/shun.o: $(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h |
| 1740 | $(XTCC) -o $(OBJDIR)/shun.o -c $(OBJDIR)/shun_.c |
| 1741 | |
| 1742 | $(OBJDIR)/shun.h: $(OBJDIR)/headers |
| 1743 | |
| 1744 | $(OBJDIR)/sitemap_.c: $(SRCDIR)/sitemap.c $(TRANSLATE) |
| 1745 | $(TRANSLATE) $(SRCDIR)/sitemap.c >$@ |
| 1746 | |
| 1747 | $(OBJDIR)/sitemap.o: $(OBJDIR)/sitemap_.c $(OBJDIR)/sitemap.h $(SRCDIR)/config.h |
| 1748 | $(XTCC) -o $(OBJDIR)/sitemap.o -c $(OBJDIR)/sitemap_.c |
| 1749 | |
| 1750 | $(OBJDIR)/sitemap.h: $(OBJDIR)/headers |
| 1751 | |
| 1752 | $(OBJDIR)/skins_.c: $(SRCDIR)/skins.c $(TRANSLATE) |
| 1753 | $(TRANSLATE) $(SRCDIR)/skins.c >$@ |
| 1754 | |
| 1755 | $(OBJDIR)/skins.o: $(OBJDIR)/skins_.c $(OBJDIR)/skins.h $(SRCDIR)/config.h |
| 1756 |
+54
-5
| --- win/Makefile.msc | ||
| +++ win/Makefile.msc | ||
| @@ -62,23 +62,32 @@ | ||
| 62 | 62 | SSLLIBDIR = $(SSLDIR)\out32 |
| 63 | 63 | SSLLFLAGS = /nologo /opt:ref /debug |
| 64 | 64 | SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib |
| 65 | 65 | !if "$(PLATFORM)"=="amd64" || "$(PLATFORM)"=="x64" |
| 66 | 66 | !message Using 'x64' platform for OpenSSL... |
| 67 | -SSLCONFIG = VC-WIN64A no-asm | |
| 67 | +# BUGBUG (OpenSSL): Apparently, using "no-ssl*" here breaks the build. | |
| 68 | +# SSLCONFIG = VC-WIN64A no-asm no-ssl2 no-ssl3 no-shared | |
| 69 | +SSLCONFIG = VC-WIN64A no-asm no-shared | |
| 68 | 70 | SSLSETUP = ms\do_win64a.bat |
| 69 | 71 | SSLNMAKE = ms\nt.mak all |
| 72 | +SSLCFLAGS = -DOPENSSL_NO_SSL2 -DOPENSSL_NO_SSL3 | |
| 70 | 73 | !elseif "$(PLATFORM)"=="ia64" |
| 71 | 74 | !message Using 'ia64' platform for OpenSSL... |
| 72 | -SSLCONFIG = VC-WIN64I no-asm | |
| 75 | +# BUGBUG (OpenSSL): Apparently, using "no-ssl*" here breaks the build. | |
| 76 | +# SSLCONFIG = VC-WIN64I no-asm no-ssl2 no-ssl3 no-shared | |
| 77 | +SSLCONFIG = VC-WIN64I no-asm no-shared | |
| 73 | 78 | SSLSETUP = ms\do_win64i.bat |
| 74 | 79 | SSLNMAKE = ms\nt.mak all |
| 80 | +SSLCFLAGS = -DOPENSSL_NO_SSL2 -DOPENSSL_NO_SSL3 | |
| 75 | 81 | !else |
| 76 | 82 | !message Assuming 'x86' platform for OpenSSL... |
| 77 | -SSLCONFIG = VC-WIN32 no-asm | |
| 83 | +# BUGBUG (OpenSSL): Apparently, using "no-ssl*" here breaks the build. | |
| 84 | +# SSLCONFIG = VC-WIN32 no-asm no-ssl2 no-ssl3 no-shared | |
| 85 | +SSLCONFIG = VC-WIN32 no-asm no-shared | |
| 78 | 86 | SSLSETUP = ms\do_ms.bat |
| 79 | 87 | SSLNMAKE = ms\nt.mak all |
| 88 | +SSLCFLAGS = -DOPENSSL_NO_SSL2 -DOPENSSL_NO_SSL3 | |
| 80 | 89 | !endif |
| 81 | 90 | !endif |
| 82 | 91 | |
| 83 | 92 | !ifdef FOSSIL_ENABLE_TCL |
| 84 | 93 | TCLDIR = $(B)\compat\tcl-8.6 |
| @@ -204,10 +213,11 @@ | ||
| 204 | 213 | bisect_.c \ |
| 205 | 214 | blob_.c \ |
| 206 | 215 | branch_.c \ |
| 207 | 216 | browse_.c \ |
| 208 | 217 | builtin_.c \ |
| 218 | + bundle_.c \ | |
| 209 | 219 | cache_.c \ |
| 210 | 220 | captcha_.c \ |
| 211 | 221 | cgi_.c \ |
| 212 | 222 | checkin_.c \ |
| 213 | 223 | checkout_.c \ |
| @@ -270,19 +280,22 @@ | ||
| 270 | 280 | path_.c \ |
| 271 | 281 | pivot_.c \ |
| 272 | 282 | popen_.c \ |
| 273 | 283 | pqueue_.c \ |
| 274 | 284 | printf_.c \ |
| 285 | + publish_.c \ | |
| 286 | + purge_.c \ | |
| 275 | 287 | rebuild_.c \ |
| 276 | 288 | regexp_.c \ |
| 277 | 289 | report_.c \ |
| 278 | 290 | rss_.c \ |
| 279 | 291 | schema_.c \ |
| 280 | 292 | search_.c \ |
| 281 | 293 | setup_.c \ |
| 282 | 294 | sha1_.c \ |
| 283 | 295 | shun_.c \ |
| 296 | + sitemap_.c \ | |
| 284 | 297 | skins_.c \ |
| 285 | 298 | sqlcmd_.c \ |
| 286 | 299 | stash_.c \ |
| 287 | 300 | stat_.c \ |
| 288 | 301 | style_.c \ |
| @@ -320,10 +333,11 @@ | ||
| 320 | 333 | $(OX)\bisect$O \ |
| 321 | 334 | $(OX)\blob$O \ |
| 322 | 335 | $(OX)\branch$O \ |
| 323 | 336 | $(OX)\browse$O \ |
| 324 | 337 | $(OX)\builtin$O \ |
| 338 | + $(OX)\bundle$O \ | |
| 325 | 339 | $(OX)\cache$O \ |
| 326 | 340 | $(OX)\captcha$O \ |
| 327 | 341 | $(OX)\cgi$O \ |
| 328 | 342 | $(OX)\checkin$O \ |
| 329 | 343 | $(OX)\checkout$O \ |
| @@ -387,10 +401,12 @@ | ||
| 387 | 401 | $(OX)\path$O \ |
| 388 | 402 | $(OX)\pivot$O \ |
| 389 | 403 | $(OX)\popen$O \ |
| 390 | 404 | $(OX)\pqueue$O \ |
| 391 | 405 | $(OX)\printf$O \ |
| 406 | + $(OX)\publish$O \ | |
| 407 | + $(OX)\purge$O \ | |
| 392 | 408 | $(OX)\rebuild$O \ |
| 393 | 409 | $(OX)\regexp$O \ |
| 394 | 410 | $(OX)\report$O \ |
| 395 | 411 | $(OX)\rss$O \ |
| 396 | 412 | $(OX)\schema$O \ |
| @@ -397,10 +413,11 @@ | ||
| 397 | 413 | $(OX)\search$O \ |
| 398 | 414 | $(OX)\setup$O \ |
| 399 | 415 | $(OX)\sha1$O \ |
| 400 | 416 | $(OX)\shell$O \ |
| 401 | 417 | $(OX)\shun$O \ |
| 418 | + $(OX)\sitemap$O \ | |
| 402 | 419 | $(OX)\skins$O \ |
| 403 | 420 | $(OX)\sqlcmd$O \ |
| 404 | 421 | $(OX)\sqlite3$O \ |
| 405 | 422 | $(OX)\stash$O \ |
| 406 | 423 | $(OX)\stat$O \ |
| @@ -459,13 +476,13 @@ | ||
| 459 | 476 | @set PATH=$(PERLDIR);$(PATH) |
| 460 | 477 | !endif |
| 461 | 478 | @pushd "$(SSLDIR)" && $(PERL) Configure $(SSLCONFIG) && popd |
| 462 | 479 | @pushd "$(SSLDIR)" && call $(SSLSETUP) && popd |
| 463 | 480 | !ifdef FOSSIL_ENABLE_WINXP |
| 464 | - @pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) "CC=cl $(XPCFLAGS)" "LFLAGS=$(SSLLFLAGS) $(XPLDFLAGS)" && popd | |
| 481 | + @pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) "CC=cl $(SSLCFLAGS) $(XPCFLAGS)" "LFLAGS=$(SSLLFLAGS) $(XPLDFLAGS)" && popd | |
| 465 | 482 | !else |
| 466 | - @pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) && popd | |
| 483 | + @pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) "CC=cl $(SSLCFLAGS)" && popd | |
| 467 | 484 | !endif |
| 468 | 485 | !endif |
| 469 | 486 | |
| 470 | 487 | !ifndef FOSSIL_ENABLE_MINIZ |
| 471 | 488 | APPTARGETS = $(APPTARGETS) zlib |
| @@ -490,10 +507,11 @@ | ||
| 490 | 507 | echo $(OX)\bisect.obj >> $@ |
| 491 | 508 | echo $(OX)\blob.obj >> $@ |
| 492 | 509 | echo $(OX)\branch.obj >> $@ |
| 493 | 510 | echo $(OX)\browse.obj >> $@ |
| 494 | 511 | echo $(OX)\builtin.obj >> $@ |
| 512 | + echo $(OX)\bundle.obj >> $@ | |
| 495 | 513 | echo $(OX)\cache.obj >> $@ |
| 496 | 514 | echo $(OX)\captcha.obj >> $@ |
| 497 | 515 | echo $(OX)\cgi.obj >> $@ |
| 498 | 516 | echo $(OX)\checkin.obj >> $@ |
| 499 | 517 | echo $(OX)\checkout.obj >> $@ |
| @@ -557,10 +575,12 @@ | ||
| 557 | 575 | echo $(OX)\path.obj >> $@ |
| 558 | 576 | echo $(OX)\pivot.obj >> $@ |
| 559 | 577 | echo $(OX)\popen.obj >> $@ |
| 560 | 578 | echo $(OX)\pqueue.obj >> $@ |
| 561 | 579 | echo $(OX)\printf.obj >> $@ |
| 580 | + echo $(OX)\publish.obj >> $@ | |
| 581 | + echo $(OX)\purge.obj >> $@ | |
| 562 | 582 | echo $(OX)\rebuild.obj >> $@ |
| 563 | 583 | echo $(OX)\regexp.obj >> $@ |
| 564 | 584 | echo $(OX)\report.obj >> $@ |
| 565 | 585 | echo $(OX)\rss.obj >> $@ |
| 566 | 586 | echo $(OX)\schema.obj >> $@ |
| @@ -567,10 +587,11 @@ | ||
| 567 | 587 | echo $(OX)\search.obj >> $@ |
| 568 | 588 | echo $(OX)\setup.obj >> $@ |
| 569 | 589 | echo $(OX)\sha1.obj >> $@ |
| 570 | 590 | echo $(OX)\shell.obj >> $@ |
| 571 | 591 | echo $(OX)\shun.obj >> $@ |
| 592 | + echo $(OX)\sitemap.obj >> $@ | |
| 572 | 593 | echo $(OX)\skins.obj >> $@ |
| 573 | 594 | echo $(OX)\sqlcmd.obj >> $@ |
| 574 | 595 | echo $(OX)\sqlite3.obj >> $@ |
| 575 | 596 | echo $(OX)\stash.obj >> $@ |
| 576 | 597 | echo $(OX)\stat.obj >> $@ |
| @@ -752,10 +773,16 @@ | ||
| 752 | 773 | $(OX)\builtin$O : builtin_.c builtin.h |
| 753 | 774 | $(TCC) /Fo$@ -c builtin_.c |
| 754 | 775 | |
| 755 | 776 | builtin_.c : $(SRCDIR)\builtin.c |
| 756 | 777 | translate$E $** > $@ |
| 778 | + | |
| 779 | +$(OX)\bundle$O : bundle_.c bundle.h | |
| 780 | + $(TCC) /Fo$@ -c bundle_.c | |
| 781 | + | |
| 782 | +bundle_.c : $(SRCDIR)\bundle.c | |
| 783 | + translate$E $** > $@ | |
| 757 | 784 | |
| 758 | 785 | $(OX)\cache$O : cache_.c cache.h |
| 759 | 786 | $(TCC) /Fo$@ -c cache_.c |
| 760 | 787 | |
| 761 | 788 | cache_.c : $(SRCDIR)\cache.c |
| @@ -1148,10 +1175,22 @@ | ||
| 1148 | 1175 | $(OX)\printf$O : printf_.c printf.h |
| 1149 | 1176 | $(TCC) /Fo$@ -c printf_.c |
| 1150 | 1177 | |
| 1151 | 1178 | printf_.c : $(SRCDIR)\printf.c |
| 1152 | 1179 | translate$E $** > $@ |
| 1180 | + | |
| 1181 | +$(OX)\publish$O : publish_.c publish.h | |
| 1182 | + $(TCC) /Fo$@ -c publish_.c | |
| 1183 | + | |
| 1184 | +publish_.c : $(SRCDIR)\publish.c | |
| 1185 | + translate$E $** > $@ | |
| 1186 | + | |
| 1187 | +$(OX)\purge$O : purge_.c purge.h | |
| 1188 | + $(TCC) /Fo$@ -c purge_.c | |
| 1189 | + | |
| 1190 | +purge_.c : $(SRCDIR)\purge.c | |
| 1191 | + translate$E $** > $@ | |
| 1153 | 1192 | |
| 1154 | 1193 | $(OX)\rebuild$O : rebuild_.c rebuild.h |
| 1155 | 1194 | $(TCC) /Fo$@ -c rebuild_.c |
| 1156 | 1195 | |
| 1157 | 1196 | rebuild_.c : $(SRCDIR)\rebuild.c |
| @@ -1202,10 +1241,16 @@ | ||
| 1202 | 1241 | $(OX)\shun$O : shun_.c shun.h |
| 1203 | 1242 | $(TCC) /Fo$@ -c shun_.c |
| 1204 | 1243 | |
| 1205 | 1244 | shun_.c : $(SRCDIR)\shun.c |
| 1206 | 1245 | translate$E $** > $@ |
| 1246 | + | |
| 1247 | +$(OX)\sitemap$O : sitemap_.c sitemap.h | |
| 1248 | + $(TCC) /Fo$@ -c sitemap_.c | |
| 1249 | + | |
| 1250 | +sitemap_.c : $(SRCDIR)\sitemap.c | |
| 1251 | + translate$E $** > $@ | |
| 1207 | 1252 | |
| 1208 | 1253 | $(OX)\skins$O : skins_.c skins.h |
| 1209 | 1254 | $(TCC) /Fo$@ -c skins_.c |
| 1210 | 1255 | |
| 1211 | 1256 | skins_.c : $(SRCDIR)\skins.c |
| @@ -1390,10 +1435,11 @@ | ||
| 1390 | 1435 | bisect_.c:bisect.h \ |
| 1391 | 1436 | blob_.c:blob.h \ |
| 1392 | 1437 | branch_.c:branch.h \ |
| 1393 | 1438 | browse_.c:browse.h \ |
| 1394 | 1439 | builtin_.c:builtin.h \ |
| 1440 | + bundle_.c:bundle.h \ | |
| 1395 | 1441 | cache_.c:cache.h \ |
| 1396 | 1442 | captcha_.c:captcha.h \ |
| 1397 | 1443 | cgi_.c:cgi.h \ |
| 1398 | 1444 | checkin_.c:checkin.h \ |
| 1399 | 1445 | checkout_.c:checkout.h \ |
| @@ -1456,19 +1502,22 @@ | ||
| 1456 | 1502 | path_.c:path.h \ |
| 1457 | 1503 | pivot_.c:pivot.h \ |
| 1458 | 1504 | popen_.c:popen.h \ |
| 1459 | 1505 | pqueue_.c:pqueue.h \ |
| 1460 | 1506 | printf_.c:printf.h \ |
| 1507 | + publish_.c:publish.h \ | |
| 1508 | + purge_.c:purge.h \ | |
| 1461 | 1509 | rebuild_.c:rebuild.h \ |
| 1462 | 1510 | regexp_.c:regexp.h \ |
| 1463 | 1511 | report_.c:report.h \ |
| 1464 | 1512 | rss_.c:rss.h \ |
| 1465 | 1513 | schema_.c:schema.h \ |
| 1466 | 1514 | search_.c:search.h \ |
| 1467 | 1515 | setup_.c:setup.h \ |
| 1468 | 1516 | sha1_.c:sha1.h \ |
| 1469 | 1517 | shun_.c:shun.h \ |
| 1518 | + sitemap_.c:sitemap.h \ | |
| 1470 | 1519 | skins_.c:skins.h \ |
| 1471 | 1520 | sqlcmd_.c:sqlcmd.h \ |
| 1472 | 1521 | stash_.c:stash.h \ |
| 1473 | 1522 | stat_.c:stat.h \ |
| 1474 | 1523 | style_.c:style.h \ |
| 1475 | 1524 |
| --- win/Makefile.msc | |
| +++ win/Makefile.msc | |
| @@ -62,23 +62,32 @@ | |
| 62 | SSLLIBDIR = $(SSLDIR)\out32 |
| 63 | SSLLFLAGS = /nologo /opt:ref /debug |
| 64 | SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib |
| 65 | !if "$(PLATFORM)"=="amd64" || "$(PLATFORM)"=="x64" |
| 66 | !message Using 'x64' platform for OpenSSL... |
| 67 | SSLCONFIG = VC-WIN64A no-asm |
| 68 | SSLSETUP = ms\do_win64a.bat |
| 69 | SSLNMAKE = ms\nt.mak all |
| 70 | !elseif "$(PLATFORM)"=="ia64" |
| 71 | !message Using 'ia64' platform for OpenSSL... |
| 72 | SSLCONFIG = VC-WIN64I no-asm |
| 73 | SSLSETUP = ms\do_win64i.bat |
| 74 | SSLNMAKE = ms\nt.mak all |
| 75 | !else |
| 76 | !message Assuming 'x86' platform for OpenSSL... |
| 77 | SSLCONFIG = VC-WIN32 no-asm |
| 78 | SSLSETUP = ms\do_ms.bat |
| 79 | SSLNMAKE = ms\nt.mak all |
| 80 | !endif |
| 81 | !endif |
| 82 | |
| 83 | !ifdef FOSSIL_ENABLE_TCL |
| 84 | TCLDIR = $(B)\compat\tcl-8.6 |
| @@ -204,10 +213,11 @@ | |
| 204 | bisect_.c \ |
| 205 | blob_.c \ |
| 206 | branch_.c \ |
| 207 | browse_.c \ |
| 208 | builtin_.c \ |
| 209 | cache_.c \ |
| 210 | captcha_.c \ |
| 211 | cgi_.c \ |
| 212 | checkin_.c \ |
| 213 | checkout_.c \ |
| @@ -270,19 +280,22 @@ | |
| 270 | path_.c \ |
| 271 | pivot_.c \ |
| 272 | popen_.c \ |
| 273 | pqueue_.c \ |
| 274 | printf_.c \ |
| 275 | rebuild_.c \ |
| 276 | regexp_.c \ |
| 277 | report_.c \ |
| 278 | rss_.c \ |
| 279 | schema_.c \ |
| 280 | search_.c \ |
| 281 | setup_.c \ |
| 282 | sha1_.c \ |
| 283 | shun_.c \ |
| 284 | skins_.c \ |
| 285 | sqlcmd_.c \ |
| 286 | stash_.c \ |
| 287 | stat_.c \ |
| 288 | style_.c \ |
| @@ -320,10 +333,11 @@ | |
| 320 | $(OX)\bisect$O \ |
| 321 | $(OX)\blob$O \ |
| 322 | $(OX)\branch$O \ |
| 323 | $(OX)\browse$O \ |
| 324 | $(OX)\builtin$O \ |
| 325 | $(OX)\cache$O \ |
| 326 | $(OX)\captcha$O \ |
| 327 | $(OX)\cgi$O \ |
| 328 | $(OX)\checkin$O \ |
| 329 | $(OX)\checkout$O \ |
| @@ -387,10 +401,12 @@ | |
| 387 | $(OX)\path$O \ |
| 388 | $(OX)\pivot$O \ |
| 389 | $(OX)\popen$O \ |
| 390 | $(OX)\pqueue$O \ |
| 391 | $(OX)\printf$O \ |
| 392 | $(OX)\rebuild$O \ |
| 393 | $(OX)\regexp$O \ |
| 394 | $(OX)\report$O \ |
| 395 | $(OX)\rss$O \ |
| 396 | $(OX)\schema$O \ |
| @@ -397,10 +413,11 @@ | |
| 397 | $(OX)\search$O \ |
| 398 | $(OX)\setup$O \ |
| 399 | $(OX)\sha1$O \ |
| 400 | $(OX)\shell$O \ |
| 401 | $(OX)\shun$O \ |
| 402 | $(OX)\skins$O \ |
| 403 | $(OX)\sqlcmd$O \ |
| 404 | $(OX)\sqlite3$O \ |
| 405 | $(OX)\stash$O \ |
| 406 | $(OX)\stat$O \ |
| @@ -459,13 +476,13 @@ | |
| 459 | @set PATH=$(PERLDIR);$(PATH) |
| 460 | !endif |
| 461 | @pushd "$(SSLDIR)" && $(PERL) Configure $(SSLCONFIG) && popd |
| 462 | @pushd "$(SSLDIR)" && call $(SSLSETUP) && popd |
| 463 | !ifdef FOSSIL_ENABLE_WINXP |
| 464 | @pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) "CC=cl $(XPCFLAGS)" "LFLAGS=$(SSLLFLAGS) $(XPLDFLAGS)" && popd |
| 465 | !else |
| 466 | @pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) && popd |
| 467 | !endif |
| 468 | !endif |
| 469 | |
| 470 | !ifndef FOSSIL_ENABLE_MINIZ |
| 471 | APPTARGETS = $(APPTARGETS) zlib |
| @@ -490,10 +507,11 @@ | |
| 490 | echo $(OX)\bisect.obj >> $@ |
| 491 | echo $(OX)\blob.obj >> $@ |
| 492 | echo $(OX)\branch.obj >> $@ |
| 493 | echo $(OX)\browse.obj >> $@ |
| 494 | echo $(OX)\builtin.obj >> $@ |
| 495 | echo $(OX)\cache.obj >> $@ |
| 496 | echo $(OX)\captcha.obj >> $@ |
| 497 | echo $(OX)\cgi.obj >> $@ |
| 498 | echo $(OX)\checkin.obj >> $@ |
| 499 | echo $(OX)\checkout.obj >> $@ |
| @@ -557,10 +575,12 @@ | |
| 557 | echo $(OX)\path.obj >> $@ |
| 558 | echo $(OX)\pivot.obj >> $@ |
| 559 | echo $(OX)\popen.obj >> $@ |
| 560 | echo $(OX)\pqueue.obj >> $@ |
| 561 | echo $(OX)\printf.obj >> $@ |
| 562 | echo $(OX)\rebuild.obj >> $@ |
| 563 | echo $(OX)\regexp.obj >> $@ |
| 564 | echo $(OX)\report.obj >> $@ |
| 565 | echo $(OX)\rss.obj >> $@ |
| 566 | echo $(OX)\schema.obj >> $@ |
| @@ -567,10 +587,11 @@ | |
| 567 | echo $(OX)\search.obj >> $@ |
| 568 | echo $(OX)\setup.obj >> $@ |
| 569 | echo $(OX)\sha1.obj >> $@ |
| 570 | echo $(OX)\shell.obj >> $@ |
| 571 | echo $(OX)\shun.obj >> $@ |
| 572 | echo $(OX)\skins.obj >> $@ |
| 573 | echo $(OX)\sqlcmd.obj >> $@ |
| 574 | echo $(OX)\sqlite3.obj >> $@ |
| 575 | echo $(OX)\stash.obj >> $@ |
| 576 | echo $(OX)\stat.obj >> $@ |
| @@ -752,10 +773,16 @@ | |
| 752 | $(OX)\builtin$O : builtin_.c builtin.h |
| 753 | $(TCC) /Fo$@ -c builtin_.c |
| 754 | |
| 755 | builtin_.c : $(SRCDIR)\builtin.c |
| 756 | translate$E $** > $@ |
| 757 | |
| 758 | $(OX)\cache$O : cache_.c cache.h |
| 759 | $(TCC) /Fo$@ -c cache_.c |
| 760 | |
| 761 | cache_.c : $(SRCDIR)\cache.c |
| @@ -1148,10 +1175,22 @@ | |
| 1148 | $(OX)\printf$O : printf_.c printf.h |
| 1149 | $(TCC) /Fo$@ -c printf_.c |
| 1150 | |
| 1151 | printf_.c : $(SRCDIR)\printf.c |
| 1152 | translate$E $** > $@ |
| 1153 | |
| 1154 | $(OX)\rebuild$O : rebuild_.c rebuild.h |
| 1155 | $(TCC) /Fo$@ -c rebuild_.c |
| 1156 | |
| 1157 | rebuild_.c : $(SRCDIR)\rebuild.c |
| @@ -1202,10 +1241,16 @@ | |
| 1202 | $(OX)\shun$O : shun_.c shun.h |
| 1203 | $(TCC) /Fo$@ -c shun_.c |
| 1204 | |
| 1205 | shun_.c : $(SRCDIR)\shun.c |
| 1206 | translate$E $** > $@ |
| 1207 | |
| 1208 | $(OX)\skins$O : skins_.c skins.h |
| 1209 | $(TCC) /Fo$@ -c skins_.c |
| 1210 | |
| 1211 | skins_.c : $(SRCDIR)\skins.c |
| @@ -1390,10 +1435,11 @@ | |
| 1390 | bisect_.c:bisect.h \ |
| 1391 | blob_.c:blob.h \ |
| 1392 | branch_.c:branch.h \ |
| 1393 | browse_.c:browse.h \ |
| 1394 | builtin_.c:builtin.h \ |
| 1395 | cache_.c:cache.h \ |
| 1396 | captcha_.c:captcha.h \ |
| 1397 | cgi_.c:cgi.h \ |
| 1398 | checkin_.c:checkin.h \ |
| 1399 | checkout_.c:checkout.h \ |
| @@ -1456,19 +1502,22 @@ | |
| 1456 | path_.c:path.h \ |
| 1457 | pivot_.c:pivot.h \ |
| 1458 | popen_.c:popen.h \ |
| 1459 | pqueue_.c:pqueue.h \ |
| 1460 | printf_.c:printf.h \ |
| 1461 | rebuild_.c:rebuild.h \ |
| 1462 | regexp_.c:regexp.h \ |
| 1463 | report_.c:report.h \ |
| 1464 | rss_.c:rss.h \ |
| 1465 | schema_.c:schema.h \ |
| 1466 | search_.c:search.h \ |
| 1467 | setup_.c:setup.h \ |
| 1468 | sha1_.c:sha1.h \ |
| 1469 | shun_.c:shun.h \ |
| 1470 | skins_.c:skins.h \ |
| 1471 | sqlcmd_.c:sqlcmd.h \ |
| 1472 | stash_.c:stash.h \ |
| 1473 | stat_.c:stat.h \ |
| 1474 | style_.c:style.h \ |
| 1475 |
| --- win/Makefile.msc | |
| +++ win/Makefile.msc | |
| @@ -62,23 +62,32 @@ | |
| 62 | SSLLIBDIR = $(SSLDIR)\out32 |
| 63 | SSLLFLAGS = /nologo /opt:ref /debug |
| 64 | SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib |
| 65 | !if "$(PLATFORM)"=="amd64" || "$(PLATFORM)"=="x64" |
| 66 | !message Using 'x64' platform for OpenSSL... |
| 67 | # BUGBUG (OpenSSL): Apparently, using "no-ssl*" here breaks the build. |
| 68 | # SSLCONFIG = VC-WIN64A no-asm no-ssl2 no-ssl3 no-shared |
| 69 | SSLCONFIG = VC-WIN64A no-asm no-shared |
| 70 | SSLSETUP = ms\do_win64a.bat |
| 71 | SSLNMAKE = ms\nt.mak all |
| 72 | SSLCFLAGS = -DOPENSSL_NO_SSL2 -DOPENSSL_NO_SSL3 |
| 73 | !elseif "$(PLATFORM)"=="ia64" |
| 74 | !message Using 'ia64' platform for OpenSSL... |
| 75 | # BUGBUG (OpenSSL): Apparently, using "no-ssl*" here breaks the build. |
| 76 | # SSLCONFIG = VC-WIN64I no-asm no-ssl2 no-ssl3 no-shared |
| 77 | SSLCONFIG = VC-WIN64I no-asm no-shared |
| 78 | SSLSETUP = ms\do_win64i.bat |
| 79 | SSLNMAKE = ms\nt.mak all |
| 80 | SSLCFLAGS = -DOPENSSL_NO_SSL2 -DOPENSSL_NO_SSL3 |
| 81 | !else |
| 82 | !message Assuming 'x86' platform for OpenSSL... |
| 83 | # BUGBUG (OpenSSL): Apparently, using "no-ssl*" here breaks the build. |
| 84 | # SSLCONFIG = VC-WIN32 no-asm no-ssl2 no-ssl3 no-shared |
| 85 | SSLCONFIG = VC-WIN32 no-asm no-shared |
| 86 | SSLSETUP = ms\do_ms.bat |
| 87 | SSLNMAKE = ms\nt.mak all |
| 88 | SSLCFLAGS = -DOPENSSL_NO_SSL2 -DOPENSSL_NO_SSL3 |
| 89 | !endif |
| 90 | !endif |
| 91 | |
| 92 | !ifdef FOSSIL_ENABLE_TCL |
| 93 | TCLDIR = $(B)\compat\tcl-8.6 |
| @@ -204,10 +213,11 @@ | |
| 213 | bisect_.c \ |
| 214 | blob_.c \ |
| 215 | branch_.c \ |
| 216 | browse_.c \ |
| 217 | builtin_.c \ |
| 218 | bundle_.c \ |
| 219 | cache_.c \ |
| 220 | captcha_.c \ |
| 221 | cgi_.c \ |
| 222 | checkin_.c \ |
| 223 | checkout_.c \ |
| @@ -270,19 +280,22 @@ | |
| 280 | path_.c \ |
| 281 | pivot_.c \ |
| 282 | popen_.c \ |
| 283 | pqueue_.c \ |
| 284 | printf_.c \ |
| 285 | publish_.c \ |
| 286 | purge_.c \ |
| 287 | rebuild_.c \ |
| 288 | regexp_.c \ |
| 289 | report_.c \ |
| 290 | rss_.c \ |
| 291 | schema_.c \ |
| 292 | search_.c \ |
| 293 | setup_.c \ |
| 294 | sha1_.c \ |
| 295 | shun_.c \ |
| 296 | sitemap_.c \ |
| 297 | skins_.c \ |
| 298 | sqlcmd_.c \ |
| 299 | stash_.c \ |
| 300 | stat_.c \ |
| 301 | style_.c \ |
| @@ -320,10 +333,11 @@ | |
| 333 | $(OX)\bisect$O \ |
| 334 | $(OX)\blob$O \ |
| 335 | $(OX)\branch$O \ |
| 336 | $(OX)\browse$O \ |
| 337 | $(OX)\builtin$O \ |
| 338 | $(OX)\bundle$O \ |
| 339 | $(OX)\cache$O \ |
| 340 | $(OX)\captcha$O \ |
| 341 | $(OX)\cgi$O \ |
| 342 | $(OX)\checkin$O \ |
| 343 | $(OX)\checkout$O \ |
| @@ -387,10 +401,12 @@ | |
| 401 | $(OX)\path$O \ |
| 402 | $(OX)\pivot$O \ |
| 403 | $(OX)\popen$O \ |
| 404 | $(OX)\pqueue$O \ |
| 405 | $(OX)\printf$O \ |
| 406 | $(OX)\publish$O \ |
| 407 | $(OX)\purge$O \ |
| 408 | $(OX)\rebuild$O \ |
| 409 | $(OX)\regexp$O \ |
| 410 | $(OX)\report$O \ |
| 411 | $(OX)\rss$O \ |
| 412 | $(OX)\schema$O \ |
| @@ -397,10 +413,11 @@ | |
| 413 | $(OX)\search$O \ |
| 414 | $(OX)\setup$O \ |
| 415 | $(OX)\sha1$O \ |
| 416 | $(OX)\shell$O \ |
| 417 | $(OX)\shun$O \ |
| 418 | $(OX)\sitemap$O \ |
| 419 | $(OX)\skins$O \ |
| 420 | $(OX)\sqlcmd$O \ |
| 421 | $(OX)\sqlite3$O \ |
| 422 | $(OX)\stash$O \ |
| 423 | $(OX)\stat$O \ |
| @@ -459,13 +476,13 @@ | |
| 476 | @set PATH=$(PERLDIR);$(PATH) |
| 477 | !endif |
| 478 | @pushd "$(SSLDIR)" && $(PERL) Configure $(SSLCONFIG) && popd |
| 479 | @pushd "$(SSLDIR)" && call $(SSLSETUP) && popd |
| 480 | !ifdef FOSSIL_ENABLE_WINXP |
| 481 | @pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) "CC=cl $(SSLCFLAGS) $(XPCFLAGS)" "LFLAGS=$(SSLLFLAGS) $(XPLDFLAGS)" && popd |
| 482 | !else |
| 483 | @pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) "CC=cl $(SSLCFLAGS)" && popd |
| 484 | !endif |
| 485 | !endif |
| 486 | |
| 487 | !ifndef FOSSIL_ENABLE_MINIZ |
| 488 | APPTARGETS = $(APPTARGETS) zlib |
| @@ -490,10 +507,11 @@ | |
| 507 | echo $(OX)\bisect.obj >> $@ |
| 508 | echo $(OX)\blob.obj >> $@ |
| 509 | echo $(OX)\branch.obj >> $@ |
| 510 | echo $(OX)\browse.obj >> $@ |
| 511 | echo $(OX)\builtin.obj >> $@ |
| 512 | echo $(OX)\bundle.obj >> $@ |
| 513 | echo $(OX)\cache.obj >> $@ |
| 514 | echo $(OX)\captcha.obj >> $@ |
| 515 | echo $(OX)\cgi.obj >> $@ |
| 516 | echo $(OX)\checkin.obj >> $@ |
| 517 | echo $(OX)\checkout.obj >> $@ |
| @@ -557,10 +575,12 @@ | |
| 575 | echo $(OX)\path.obj >> $@ |
| 576 | echo $(OX)\pivot.obj >> $@ |
| 577 | echo $(OX)\popen.obj >> $@ |
| 578 | echo $(OX)\pqueue.obj >> $@ |
| 579 | echo $(OX)\printf.obj >> $@ |
| 580 | echo $(OX)\publish.obj >> $@ |
| 581 | echo $(OX)\purge.obj >> $@ |
| 582 | echo $(OX)\rebuild.obj >> $@ |
| 583 | echo $(OX)\regexp.obj >> $@ |
| 584 | echo $(OX)\report.obj >> $@ |
| 585 | echo $(OX)\rss.obj >> $@ |
| 586 | echo $(OX)\schema.obj >> $@ |
| @@ -567,10 +587,11 @@ | |
| 587 | echo $(OX)\search.obj >> $@ |
| 588 | echo $(OX)\setup.obj >> $@ |
| 589 | echo $(OX)\sha1.obj >> $@ |
| 590 | echo $(OX)\shell.obj >> $@ |
| 591 | echo $(OX)\shun.obj >> $@ |
| 592 | echo $(OX)\sitemap.obj >> $@ |
| 593 | echo $(OX)\skins.obj >> $@ |
| 594 | echo $(OX)\sqlcmd.obj >> $@ |
| 595 | echo $(OX)\sqlite3.obj >> $@ |
| 596 | echo $(OX)\stash.obj >> $@ |
| 597 | echo $(OX)\stat.obj >> $@ |
| @@ -752,10 +773,16 @@ | |
| 773 | $(OX)\builtin$O : builtin_.c builtin.h |
| 774 | $(TCC) /Fo$@ -c builtin_.c |
| 775 | |
| 776 | builtin_.c : $(SRCDIR)\builtin.c |
| 777 | translate$E $** > $@ |
| 778 | |
| 779 | $(OX)\bundle$O : bundle_.c bundle.h |
| 780 | $(TCC) /Fo$@ -c bundle_.c |
| 781 | |
| 782 | bundle_.c : $(SRCDIR)\bundle.c |
| 783 | translate$E $** > $@ |
| 784 | |
| 785 | $(OX)\cache$O : cache_.c cache.h |
| 786 | $(TCC) /Fo$@ -c cache_.c |
| 787 | |
| 788 | cache_.c : $(SRCDIR)\cache.c |
| @@ -1148,10 +1175,22 @@ | |
| 1175 | $(OX)\printf$O : printf_.c printf.h |
| 1176 | $(TCC) /Fo$@ -c printf_.c |
| 1177 | |
| 1178 | printf_.c : $(SRCDIR)\printf.c |
| 1179 | translate$E $** > $@ |
| 1180 | |
| 1181 | $(OX)\publish$O : publish_.c publish.h |
| 1182 | $(TCC) /Fo$@ -c publish_.c |
| 1183 | |
| 1184 | publish_.c : $(SRCDIR)\publish.c |
| 1185 | translate$E $** > $@ |
| 1186 | |
| 1187 | $(OX)\purge$O : purge_.c purge.h |
| 1188 | $(TCC) /Fo$@ -c purge_.c |
| 1189 | |
| 1190 | purge_.c : $(SRCDIR)\purge.c |
| 1191 | translate$E $** > $@ |
| 1192 | |
| 1193 | $(OX)\rebuild$O : rebuild_.c rebuild.h |
| 1194 | $(TCC) /Fo$@ -c rebuild_.c |
| 1195 | |
| 1196 | rebuild_.c : $(SRCDIR)\rebuild.c |
| @@ -1202,10 +1241,16 @@ | |
| 1241 | $(OX)\shun$O : shun_.c shun.h |
| 1242 | $(TCC) /Fo$@ -c shun_.c |
| 1243 | |
| 1244 | shun_.c : $(SRCDIR)\shun.c |
| 1245 | translate$E $** > $@ |
| 1246 | |
| 1247 | $(OX)\sitemap$O : sitemap_.c sitemap.h |
| 1248 | $(TCC) /Fo$@ -c sitemap_.c |
| 1249 | |
| 1250 | sitemap_.c : $(SRCDIR)\sitemap.c |
| 1251 | translate$E $** > $@ |
| 1252 | |
| 1253 | $(OX)\skins$O : skins_.c skins.h |
| 1254 | $(TCC) /Fo$@ -c skins_.c |
| 1255 | |
| 1256 | skins_.c : $(SRCDIR)\skins.c |
| @@ -1390,10 +1435,11 @@ | |
| 1435 | bisect_.c:bisect.h \ |
| 1436 | blob_.c:blob.h \ |
| 1437 | branch_.c:branch.h \ |
| 1438 | browse_.c:browse.h \ |
| 1439 | builtin_.c:builtin.h \ |
| 1440 | bundle_.c:bundle.h \ |
| 1441 | cache_.c:cache.h \ |
| 1442 | captcha_.c:captcha.h \ |
| 1443 | cgi_.c:cgi.h \ |
| 1444 | checkin_.c:checkin.h \ |
| 1445 | checkout_.c:checkout.h \ |
| @@ -1456,19 +1502,22 @@ | |
| 1502 | path_.c:path.h \ |
| 1503 | pivot_.c:pivot.h \ |
| 1504 | popen_.c:popen.h \ |
| 1505 | pqueue_.c:pqueue.h \ |
| 1506 | printf_.c:printf.h \ |
| 1507 | publish_.c:publish.h \ |
| 1508 | purge_.c:purge.h \ |
| 1509 | rebuild_.c:rebuild.h \ |
| 1510 | regexp_.c:regexp.h \ |
| 1511 | report_.c:report.h \ |
| 1512 | rss_.c:rss.h \ |
| 1513 | schema_.c:schema.h \ |
| 1514 | search_.c:search.h \ |
| 1515 | setup_.c:setup.h \ |
| 1516 | sha1_.c:sha1.h \ |
| 1517 | shun_.c:shun.h \ |
| 1518 | sitemap_.c:sitemap.h \ |
| 1519 | skins_.c:skins.h \ |
| 1520 | sqlcmd_.c:sqlcmd.h \ |
| 1521 | stash_.c:stash.h \ |
| 1522 | stat_.c:stat.h \ |
| 1523 | style_.c:style.h \ |
| 1524 |
+21
| --- www/checkin_names.wiki | ||
| +++ www/checkin_names.wiki | ||
| @@ -115,10 +115,31 @@ | ||
| 115 | 115 | |
| 116 | 116 | The "tag:deed2" name will refer to the most recent check-in |
| 117 | 117 | tagged with "deed2" not to the |
| 118 | 118 | check-in whose canonical name begins with "deed2". |
| 119 | 119 | |
| 120 | +<h2>Whole Branches</h2> | |
| 121 | + | |
| 122 | +Usually whan a branch name is specified, it means the latest checkin on | |
| 123 | +that branch. But for some commands (ex: [/help/purge|purge]) a branch name | |
| 124 | +on the argument means the earliest connected checkin on the branch. This | |
| 125 | +seems confusing when being explained here, but it works out to be intuitive | |
| 126 | +in practice. | |
| 127 | + | |
| 128 | +For example, the command "fossil purge XYZ" means to purge the checkin XYZ | |
| 129 | +and all of its descendents. But when XYZ is in the form of a branch name, one | |
| 130 | +generally wants to purge the entire branch, not just the last checkin on the | |
| 131 | +branch. And so for this reason, commands like purge will interpret a branch | |
| 132 | +name to be the first checkin of the branch rather than the last. If there | |
| 133 | +are two or more branches with the same name, then these commands will select | |
| 134 | +the first check-in of the branch that has the most recent checkin. What | |
| 135 | +happens is that Fossil searches for the most recent checkin with the given | |
| 136 | +tag, just as it always does. But if that tag is a branch name, it then walks | |
| 137 | +back down the branch looking for the first check-in of that branch. | |
| 138 | + | |
| 139 | +Again, this behavior only occurs on a few commands where it make sense. | |
| 140 | + | |
| 120 | 141 | <h2>Timestamps</h2> |
| 121 | 142 | |
| 122 | 143 | A timestamp in one of the formats shown below means the most recent |
| 123 | 144 | check-in that occurs no later than the timestamp given: |
| 124 | 145 | |
| 125 | 146 |
| --- www/checkin_names.wiki | |
| +++ www/checkin_names.wiki | |
| @@ -115,10 +115,31 @@ | |
| 115 | |
| 116 | The "tag:deed2" name will refer to the most recent check-in |
| 117 | tagged with "deed2" not to the |
| 118 | check-in whose canonical name begins with "deed2". |
| 119 | |
| 120 | <h2>Timestamps</h2> |
| 121 | |
| 122 | A timestamp in one of the formats shown below means the most recent |
| 123 | check-in that occurs no later than the timestamp given: |
| 124 | |
| 125 |
| --- www/checkin_names.wiki | |
| +++ www/checkin_names.wiki | |
| @@ -115,10 +115,31 @@ | |
| 115 | |
| 116 | The "tag:deed2" name will refer to the most recent check-in |
| 117 | tagged with "deed2" not to the |
| 118 | check-in whose canonical name begins with "deed2". |
| 119 | |
| 120 | <h2>Whole Branches</h2> |
| 121 | |
| 122 | Usually whan a branch name is specified, it means the latest checkin on |
| 123 | that branch. But for some commands (ex: [/help/purge|purge]) a branch name |
| 124 | on the argument means the earliest connected checkin on the branch. This |
| 125 | seems confusing when being explained here, but it works out to be intuitive |
| 126 | in practice. |
| 127 | |
| 128 | For example, the command "fossil purge XYZ" means to purge the checkin XYZ |
| 129 | and all of its descendents. But when XYZ is in the form of a branch name, one |
| 130 | generally wants to purge the entire branch, not just the last checkin on the |
| 131 | branch. And so for this reason, commands like purge will interpret a branch |
| 132 | name to be the first checkin of the branch rather than the last. If there |
| 133 | are two or more branches with the same name, then these commands will select |
| 134 | the first check-in of the branch that has the most recent checkin. What |
| 135 | happens is that Fossil searches for the most recent checkin with the given |
| 136 | tag, just as it always does. But if that tag is a branch name, it then walks |
| 137 | back down the branch looking for the first check-in of that branch. |
| 138 | |
| 139 | Again, this behavior only occurs on a few commands where it make sense. |
| 140 | |
| 141 | <h2>Timestamps</h2> |
| 142 | |
| 143 | A timestamp in one of the formats shown below means the most recent |
| 144 | check-in that occurs no later than the timestamp given: |
| 145 | |
| 146 |
+1
-1
| --- www/concepts.wiki | ||
| +++ www/concepts.wiki | ||
| @@ -405,11 +405,11 @@ | ||
| 405 | 405 | can do pushes or pulls against your server. Use the <b>--port</b> |
| 406 | 406 | option to the server command to specify a different TCP port. If |
| 407 | 407 | you do not have a local source tree, use the <b>-R</b> command-line |
| 408 | 408 | option to specify the repository file. |
| 409 | 409 | |
| 410 | -A stand-alone server is a great way to set of transient connections | |
| 410 | +The "fossil server" command is a great way to set of transient connections | |
| 411 | 411 | between coworkers for doing quick pushes or pulls. But you can also |
| 412 | 412 | set up a permanent stand-alone server if you prefer. Just make |
| 413 | 413 | arrangements for fossil to be launched with appropriate arguments |
| 414 | 414 | after every reboot. |
| 415 | 415 | |
| 416 | 416 |
| --- www/concepts.wiki | |
| +++ www/concepts.wiki | |
| @@ -405,11 +405,11 @@ | |
| 405 | can do pushes or pulls against your server. Use the <b>--port</b> |
| 406 | option to the server command to specify a different TCP port. If |
| 407 | you do not have a local source tree, use the <b>-R</b> command-line |
| 408 | option to specify the repository file. |
| 409 | |
| 410 | A stand-alone server is a great way to set of transient connections |
| 411 | between coworkers for doing quick pushes or pulls. But you can also |
| 412 | set up a permanent stand-alone server if you prefer. Just make |
| 413 | arrangements for fossil to be launched with appropriate arguments |
| 414 | after every reboot. |
| 415 | |
| 416 |
| --- www/concepts.wiki | |
| +++ www/concepts.wiki | |
| @@ -405,11 +405,11 @@ | |
| 405 | can do pushes or pulls against your server. Use the <b>--port</b> |
| 406 | option to the server command to specify a different TCP port. If |
| 407 | you do not have a local source tree, use the <b>-R</b> command-line |
| 408 | option to specify the repository file. |
| 409 | |
| 410 | The "fossil server" command is a great way to set of transient connections |
| 411 | between coworkers for doing quick pushes or pulls. But you can also |
| 412 | set up a permanent stand-alone server if you prefer. Just make |
| 413 | arrangements for fossil to be launched with appropriate arguments |
| 414 | after every reboot. |
| 415 | |
| 416 |
+8
-8
| --- www/faq.tcl | ||
| +++ www/faq.tcl | ||
| @@ -55,12 +55,12 @@ | ||
| 55 | 55 | If you already have a fork in your check-in tree and you want to convert |
| 56 | 56 | that fork to a branch, you can do this from the web interface. |
| 57 | 57 | First locate the check-in that you want to be |
| 58 | 58 | the initial check-in of your branch on the timeline and click on its |
| 59 | 59 | link so that you are on the <b>ci</b> page. Then find the "<b>edit</b>" |
| 60 | - link (near the "Commands:" label) and click on that. On the | |
| 61 | - "Edit Check-in" page, check the box beside "Branching:" and fill in | |
| 60 | + link (near the "Commands:" label) and click on that. On the | |
| 61 | + "Edit Check-in" page, check the box beside "Branching:" and fill in | |
| 62 | 62 | the name of your new branch to the right and press the "Apply Changes" |
| 63 | 63 | button. |
| 64 | 64 | } |
| 65 | 65 | |
| 66 | 66 | faq { |
| @@ -83,31 +83,31 @@ | ||
| 83 | 83 | |
| 84 | 84 | The CHECK-IN in the previous line can be any |
| 85 | 85 | [./checkin_names.wiki | valid check-in name format]. |
| 86 | 86 | |
| 87 | 87 | You can also add (and remove) tags from a check-in using the |
| 88 | - [./webui.wiki | web interface]. First locate the check-in that you | |
| 88 | + [./webui.wiki | web interface]. First locate the check-in that you | |
| 89 | 89 | what to tag on the tmline, then click on the link to go the detailed |
| 90 | 90 | information page for that check-in. Then find the "<b>edit</b>" |
| 91 | 91 | link (near the "Commands:" label) and click on that. There are |
| 92 | 92 | controls on the edit page that allow new tags to be added and existing |
| 93 | 93 | tags to be removed. |
| 94 | -} | |
| 94 | +} | |
| 95 | 95 | |
| 96 | 96 | faq { |
| 97 | 97 | How do I create a private branch that won't get pushed back to the |
| 98 | 98 | main repository. |
| 99 | 99 | } { |
| 100 | - Use the <b>--private</b> command-line option on the | |
| 100 | + Use the <b>--private</b> command-line option on the | |
| 101 | 101 | <b>commit</b> command. The result will be a check-in which exists on |
| 102 | - your local repository only and is never pushed to other repositories. | |
| 102 | + your local repository only and is never pushed to other repositories. | |
| 103 | 103 | All descendents of a private check-in are also private. |
| 104 | - | |
| 104 | + | |
| 105 | 105 | Unless you specify something different using the <b>--branch</b> and/or |
| 106 | 106 | <b>--bgcolor</b> options, the new private check-in will be put on a branch |
| 107 | 107 | named "private" with an orange background color. |
| 108 | - | |
| 108 | + | |
| 109 | 109 | You can merge from the trunk into your private branch in order to keep |
| 110 | 110 | your private branch in sync with the latest changes on the trunk. Once |
| 111 | 111 | you have everything in your private branch the way you want it, you can |
| 112 | 112 | then merge your private branch back into the trunk and push. Only the |
| 113 | 113 | final merge operation will appear in other repositories. It will seem |
| 114 | 114 |
| --- www/faq.tcl | |
| +++ www/faq.tcl | |
| @@ -55,12 +55,12 @@ | |
| 55 | If you already have a fork in your check-in tree and you want to convert |
| 56 | that fork to a branch, you can do this from the web interface. |
| 57 | First locate the check-in that you want to be |
| 58 | the initial check-in of your branch on the timeline and click on its |
| 59 | link so that you are on the <b>ci</b> page. Then find the "<b>edit</b>" |
| 60 | link (near the "Commands:" label) and click on that. On the |
| 61 | "Edit Check-in" page, check the box beside "Branching:" and fill in |
| 62 | the name of your new branch to the right and press the "Apply Changes" |
| 63 | button. |
| 64 | } |
| 65 | |
| 66 | faq { |
| @@ -83,31 +83,31 @@ | |
| 83 | |
| 84 | The CHECK-IN in the previous line can be any |
| 85 | [./checkin_names.wiki | valid check-in name format]. |
| 86 | |
| 87 | You can also add (and remove) tags from a check-in using the |
| 88 | [./webui.wiki | web interface]. First locate the check-in that you |
| 89 | what to tag on the tmline, then click on the link to go the detailed |
| 90 | information page for that check-in. Then find the "<b>edit</b>" |
| 91 | link (near the "Commands:" label) and click on that. There are |
| 92 | controls on the edit page that allow new tags to be added and existing |
| 93 | tags to be removed. |
| 94 | } |
| 95 | |
| 96 | faq { |
| 97 | How do I create a private branch that won't get pushed back to the |
| 98 | main repository. |
| 99 | } { |
| 100 | Use the <b>--private</b> command-line option on the |
| 101 | <b>commit</b> command. The result will be a check-in which exists on |
| 102 | your local repository only and is never pushed to other repositories. |
| 103 | All descendents of a private check-in are also private. |
| 104 | |
| 105 | Unless you specify something different using the <b>--branch</b> and/or |
| 106 | <b>--bgcolor</b> options, the new private check-in will be put on a branch |
| 107 | named "private" with an orange background color. |
| 108 | |
| 109 | You can merge from the trunk into your private branch in order to keep |
| 110 | your private branch in sync with the latest changes on the trunk. Once |
| 111 | you have everything in your private branch the way you want it, you can |
| 112 | then merge your private branch back into the trunk and push. Only the |
| 113 | final merge operation will appear in other repositories. It will seem |
| 114 |
| --- www/faq.tcl | |
| +++ www/faq.tcl | |
| @@ -55,12 +55,12 @@ | |
| 55 | If you already have a fork in your check-in tree and you want to convert |
| 56 | that fork to a branch, you can do this from the web interface. |
| 57 | First locate the check-in that you want to be |
| 58 | the initial check-in of your branch on the timeline and click on its |
| 59 | link so that you are on the <b>ci</b> page. Then find the "<b>edit</b>" |
| 60 | link (near the "Commands:" label) and click on that. On the |
| 61 | "Edit Check-in" page, check the box beside "Branching:" and fill in |
| 62 | the name of your new branch to the right and press the "Apply Changes" |
| 63 | button. |
| 64 | } |
| 65 | |
| 66 | faq { |
| @@ -83,31 +83,31 @@ | |
| 83 | |
| 84 | The CHECK-IN in the previous line can be any |
| 85 | [./checkin_names.wiki | valid check-in name format]. |
| 86 | |
| 87 | You can also add (and remove) tags from a check-in using the |
| 88 | [./webui.wiki | web interface]. First locate the check-in that you |
| 89 | what to tag on the tmline, then click on the link to go the detailed |
| 90 | information page for that check-in. Then find the "<b>edit</b>" |
| 91 | link (near the "Commands:" label) and click on that. There are |
| 92 | controls on the edit page that allow new tags to be added and existing |
| 93 | tags to be removed. |
| 94 | } |
| 95 | |
| 96 | faq { |
| 97 | How do I create a private branch that won't get pushed back to the |
| 98 | main repository. |
| 99 | } { |
| 100 | Use the <b>--private</b> command-line option on the |
| 101 | <b>commit</b> command. The result will be a check-in which exists on |
| 102 | your local repository only and is never pushed to other repositories. |
| 103 | All descendents of a private check-in are also private. |
| 104 | |
| 105 | Unless you specify something different using the <b>--branch</b> and/or |
| 106 | <b>--bgcolor</b> options, the new private check-in will be put on a branch |
| 107 | named "private" with an orange background color. |
| 108 | |
| 109 | You can merge from the trunk into your private branch in order to keep |
| 110 | your private branch in sync with the latest changes on the trunk. Once |
| 111 | you have everything in your private branch the way you want it, you can |
| 112 | then merge your private branch back into the trunk and push. Only the |
| 113 | final merge operation will appear in other repositories. It will seem |
| 114 |
+5
-5
| --- www/fileformat.wiki | ||
| +++ www/fileformat.wiki | ||
| @@ -49,11 +49,11 @@ | ||
| 49 | 49 | </ul> |
| 50 | 50 | |
| 51 | 51 | These seven artifact types are described in the following sections. |
| 52 | 52 | |
| 53 | 53 | In the current implementation (as of 2009-01-25) the artifacts that |
| 54 | -make up a fossil repository are stored in in as delta- and zlib-compressed | |
| 54 | +make up a fossil repository are stored as delta- and zlib-compressed | |
| 55 | 55 | blobs in an <a href="http://www.sqlite.org/">SQLite</a> database. This |
| 56 | 56 | is an implementation detail and might change in a future release. For |
| 57 | 57 | the purpose of this article "file format" means the format of the artifacts, |
| 58 | 58 | not how the artifacts are stored on disk. It is the artifact format that |
| 59 | 59 | is intended to be enduring. The specifics of how artifacts are stored on |
| @@ -184,11 +184,11 @@ | ||
| 184 | 184 | ancestor, the Q-card is used to identify a single check-in or a small |
| 185 | 185 | range of check-ins which were cherry-picked for inclusion in or |
| 186 | 186 | exclusion from the current manifest. The first argument of |
| 187 | 187 | the Q-card is the artifact ID of another manifest (the "target") |
| 188 | 188 | which has had its changes included or excluded in the current manifest. |
| 189 | -The target is preceeded by "+" or "-" to show inclusion or | |
| 189 | +The target is preceded by "+" or "-" to show inclusion or | |
| 190 | 190 | exclusion, respectively. The optional second argument to the |
| 191 | 191 | Q-card is another manifest artifact ID which is the "baseline" |
| 192 | 192 | for the cherry-pick. If omitted, the baseline is the primary |
| 193 | 193 | parent of the target. The |
| 194 | 194 | changes included or excluded consist of all changes moving from |
| @@ -315,11 +315,11 @@ | ||
| 315 | 315 | is either "+", "-", or "*". The "+" means the tag should be added |
| 316 | 316 | to the artifact. The "-" means the tag should be removed. |
| 317 | 317 | The "*" character means the tag should be added to the artifact |
| 318 | 318 | and all direct descendants (but not descendents through a merge) down |
| 319 | 319 | to but not including the first descendant that contains a |
| 320 | -more recent "-" or "+" tag with the same name. | |
| 320 | +more recent "-", "*", or "+" tag with the same name. | |
| 321 | 321 | The optional third argument is the value of the tag. A tag |
| 322 | 322 | without a value is a boolean. |
| 323 | 323 | |
| 324 | 324 | When two or more tags with the same name are applied to the |
| 325 | 325 | same artifact, the tag with the latest (most recent) date is |
| @@ -362,11 +362,11 @@ | ||
| 362 | 362 | gives the name of the wiki page. The optional N card specifies |
| 363 | 363 | the mimetype of the wiki text. If the N card is omitted, the |
| 364 | 364 | mimetype is assumed to be text/x-fossil-wiki. |
| 365 | 365 | The U card specifies the login |
| 366 | 366 | of the user who made this edit to the wiki page. The Z card is |
| 367 | -the usual checksum over the either artifact and is required. | |
| 367 | +the usual checksum over the entire artifact and is required. | |
| 368 | 368 | |
| 369 | 369 | The W card is used to specify the text of the wiki page. The |
| 370 | 370 | argument to the W card is an integer which is the number of bytes |
| 371 | 371 | of text in the wiki page. That text follows the newline character |
| 372 | 372 | that terminates the W card. The wiki text is always followed by one |
| @@ -453,11 +453,11 @@ | ||
| 453 | 453 | |
| 454 | 454 | There may be zero or one N cards. The N card specifies the mimetype of the |
| 455 | 455 | comment text provided in the C card. If the N card is omitted, the C card |
| 456 | 456 | mimetype is taken to be text/plain. |
| 457 | 457 | |
| 458 | -A single U card gives the name of the user to added the attachment. | |
| 458 | +A single U card gives the name of the user who added the attachment. | |
| 459 | 459 | If an attachment is added anonymously, then the U card may be omitted. |
| 460 | 460 | |
| 461 | 461 | The Z card is the usual checksum over the rest of the attachment artifact. |
| 462 | 462 | The Z card is required. |
| 463 | 463 | |
| 464 | 464 |
| --- www/fileformat.wiki | |
| +++ www/fileformat.wiki | |
| @@ -49,11 +49,11 @@ | |
| 49 | </ul> |
| 50 | |
| 51 | These seven artifact types are described in the following sections. |
| 52 | |
| 53 | In the current implementation (as of 2009-01-25) the artifacts that |
| 54 | make up a fossil repository are stored in in as delta- and zlib-compressed |
| 55 | blobs in an <a href="http://www.sqlite.org/">SQLite</a> database. This |
| 56 | is an implementation detail and might change in a future release. For |
| 57 | the purpose of this article "file format" means the format of the artifacts, |
| 58 | not how the artifacts are stored on disk. It is the artifact format that |
| 59 | is intended to be enduring. The specifics of how artifacts are stored on |
| @@ -184,11 +184,11 @@ | |
| 184 | ancestor, the Q-card is used to identify a single check-in or a small |
| 185 | range of check-ins which were cherry-picked for inclusion in or |
| 186 | exclusion from the current manifest. The first argument of |
| 187 | the Q-card is the artifact ID of another manifest (the "target") |
| 188 | which has had its changes included or excluded in the current manifest. |
| 189 | The target is preceeded by "+" or "-" to show inclusion or |
| 190 | exclusion, respectively. The optional second argument to the |
| 191 | Q-card is another manifest artifact ID which is the "baseline" |
| 192 | for the cherry-pick. If omitted, the baseline is the primary |
| 193 | parent of the target. The |
| 194 | changes included or excluded consist of all changes moving from |
| @@ -315,11 +315,11 @@ | |
| 315 | is either "+", "-", or "*". The "+" means the tag should be added |
| 316 | to the artifact. The "-" means the tag should be removed. |
| 317 | The "*" character means the tag should be added to the artifact |
| 318 | and all direct descendants (but not descendents through a merge) down |
| 319 | to but not including the first descendant that contains a |
| 320 | more recent "-" or "+" tag with the same name. |
| 321 | The optional third argument is the value of the tag. A tag |
| 322 | without a value is a boolean. |
| 323 | |
| 324 | When two or more tags with the same name are applied to the |
| 325 | same artifact, the tag with the latest (most recent) date is |
| @@ -362,11 +362,11 @@ | |
| 362 | gives the name of the wiki page. The optional N card specifies |
| 363 | the mimetype of the wiki text. If the N card is omitted, the |
| 364 | mimetype is assumed to be text/x-fossil-wiki. |
| 365 | The U card specifies the login |
| 366 | of the user who made this edit to the wiki page. The Z card is |
| 367 | the usual checksum over the either artifact and is required. |
| 368 | |
| 369 | The W card is used to specify the text of the wiki page. The |
| 370 | argument to the W card is an integer which is the number of bytes |
| 371 | of text in the wiki page. That text follows the newline character |
| 372 | that terminates the W card. The wiki text is always followed by one |
| @@ -453,11 +453,11 @@ | |
| 453 | |
| 454 | There may be zero or one N cards. The N card specifies the mimetype of the |
| 455 | comment text provided in the C card. If the N card is omitted, the C card |
| 456 | mimetype is taken to be text/plain. |
| 457 | |
| 458 | A single U card gives the name of the user to added the attachment. |
| 459 | If an attachment is added anonymously, then the U card may be omitted. |
| 460 | |
| 461 | The Z card is the usual checksum over the rest of the attachment artifact. |
| 462 | The Z card is required. |
| 463 | |
| 464 |
| --- www/fileformat.wiki | |
| +++ www/fileformat.wiki | |
| @@ -49,11 +49,11 @@ | |
| 49 | </ul> |
| 50 | |
| 51 | These seven artifact types are described in the following sections. |
| 52 | |
| 53 | In the current implementation (as of 2009-01-25) the artifacts that |
| 54 | make up a fossil repository are stored as delta- and zlib-compressed |
| 55 | blobs in an <a href="http://www.sqlite.org/">SQLite</a> database. This |
| 56 | is an implementation detail and might change in a future release. For |
| 57 | the purpose of this article "file format" means the format of the artifacts, |
| 58 | not how the artifacts are stored on disk. It is the artifact format that |
| 59 | is intended to be enduring. The specifics of how artifacts are stored on |
| @@ -184,11 +184,11 @@ | |
| 184 | ancestor, the Q-card is used to identify a single check-in or a small |
| 185 | range of check-ins which were cherry-picked for inclusion in or |
| 186 | exclusion from the current manifest. The first argument of |
| 187 | the Q-card is the artifact ID of another manifest (the "target") |
| 188 | which has had its changes included or excluded in the current manifest. |
| 189 | The target is preceded by "+" or "-" to show inclusion or |
| 190 | exclusion, respectively. The optional second argument to the |
| 191 | Q-card is another manifest artifact ID which is the "baseline" |
| 192 | for the cherry-pick. If omitted, the baseline is the primary |
| 193 | parent of the target. The |
| 194 | changes included or excluded consist of all changes moving from |
| @@ -315,11 +315,11 @@ | |
| 315 | is either "+", "-", or "*". The "+" means the tag should be added |
| 316 | to the artifact. The "-" means the tag should be removed. |
| 317 | The "*" character means the tag should be added to the artifact |
| 318 | and all direct descendants (but not descendents through a merge) down |
| 319 | to but not including the first descendant that contains a |
| 320 | more recent "-", "*", or "+" tag with the same name. |
| 321 | The optional third argument is the value of the tag. A tag |
| 322 | without a value is a boolean. |
| 323 | |
| 324 | When two or more tags with the same name are applied to the |
| 325 | same artifact, the tag with the latest (most recent) date is |
| @@ -362,11 +362,11 @@ | |
| 362 | gives the name of the wiki page. The optional N card specifies |
| 363 | the mimetype of the wiki text. If the N card is omitted, the |
| 364 | mimetype is assumed to be text/x-fossil-wiki. |
| 365 | The U card specifies the login |
| 366 | of the user who made this edit to the wiki page. The Z card is |
| 367 | the usual checksum over the entire artifact and is required. |
| 368 | |
| 369 | The W card is used to specify the text of the wiki page. The |
| 370 | argument to the W card is an integer which is the number of bytes |
| 371 | of text in the wiki page. That text follows the newline character |
| 372 | that terminates the W card. The wiki text is always followed by one |
| @@ -453,11 +453,11 @@ | |
| 453 | |
| 454 | There may be zero or one N cards. The N card specifies the mimetype of the |
| 455 | comment text provided in the C card. If the N card is omitted, the C card |
| 456 | mimetype is taken to be text/plain. |
| 457 | |
| 458 | A single U card gives the name of the user who added the attachment. |
| 459 | If an attachment is added anonymously, then the U card may be omitted. |
| 460 | |
| 461 | The Z card is the usual checksum over the rest of the attachment artifact. |
| 462 | The Z card is required. |
| 463 | |
| 464 |
+1
-1
| --- www/foss-cklist.wiki | ||
| +++ www/foss-cklist.wiki | ||
| @@ -5,11 +5,11 @@ | ||
| 5 | 5 | blog post <a href="http://spot.livejournal.com/308370.html"> |
| 6 | 6 | http://spot.livejournal.com/308370.html</a> (see also |
| 7 | 7 | <a href="http://www.theopensourceway.org/book/The_Open_Source_Way-How_to_tell_if_a_FLOSS_project_is_doomed_to_FAIL.html">[1]</a> and |
| 8 | 8 | <a href="https://www.theopensourceway.org/wiki/How_to_tell_if_a_FLOSS_project_is_doomed_to_FAIL">[2]</a>). |
| 9 | 9 | Tom's original post assigned point scores to the various elements and |
| 10 | -by adding together the individual points, the reader is suppose to be able | |
| 10 | +by adding together the individual points, the reader is supposed to be able | |
| 11 | 11 | to judge the likelihood that the project will fail. |
| 12 | 12 | The point scores, and the items on the list, clearly reflect Tom's |
| 13 | 13 | biases and are not necessarily those of the larger open-source community. |
| 14 | 14 | Nevertheless, the policy of the Fossil shall be to strive for a perfect |
| 15 | 15 | score.</p> |
| 16 | 16 |
| --- www/foss-cklist.wiki | |
| +++ www/foss-cklist.wiki | |
| @@ -5,11 +5,11 @@ | |
| 5 | blog post <a href="http://spot.livejournal.com/308370.html"> |
| 6 | http://spot.livejournal.com/308370.html</a> (see also |
| 7 | <a href="http://www.theopensourceway.org/book/The_Open_Source_Way-How_to_tell_if_a_FLOSS_project_is_doomed_to_FAIL.html">[1]</a> and |
| 8 | <a href="https://www.theopensourceway.org/wiki/How_to_tell_if_a_FLOSS_project_is_doomed_to_FAIL">[2]</a>). |
| 9 | Tom's original post assigned point scores to the various elements and |
| 10 | by adding together the individual points, the reader is suppose to be able |
| 11 | to judge the likelihood that the project will fail. |
| 12 | The point scores, and the items on the list, clearly reflect Tom's |
| 13 | biases and are not necessarily those of the larger open-source community. |
| 14 | Nevertheless, the policy of the Fossil shall be to strive for a perfect |
| 15 | score.</p> |
| 16 |
| --- www/foss-cklist.wiki | |
| +++ www/foss-cklist.wiki | |
| @@ -5,11 +5,11 @@ | |
| 5 | blog post <a href="http://spot.livejournal.com/308370.html"> |
| 6 | http://spot.livejournal.com/308370.html</a> (see also |
| 7 | <a href="http://www.theopensourceway.org/book/The_Open_Source_Way-How_to_tell_if_a_FLOSS_project_is_doomed_to_FAIL.html">[1]</a> and |
| 8 | <a href="https://www.theopensourceway.org/wiki/How_to_tell_if_a_FLOSS_project_is_doomed_to_FAIL">[2]</a>). |
| 9 | Tom's original post assigned point scores to the various elements and |
| 10 | by adding together the individual points, the reader is supposed to be able |
| 11 | to judge the likelihood that the project will fail. |
| 12 | The point scores, and the items on the list, clearly reflect Tom's |
| 13 | biases and are not necessarily those of the larger open-source community. |
| 14 | Nevertheless, the policy of the Fossil shall be to strive for a perfect |
| 15 | score.</p> |
| 16 |
+1
-1
| --- www/fossil-v-git.wiki | ||
| +++ www/fossil-v-git.wiki | ||
| @@ -185,11 +185,11 @@ | ||
| 185 | 185 | between repositories and working checkouts. A power-loss or system crash |
| 186 | 186 | in the middle of Git operation can damage or corrupt the Git repository. |
| 187 | 187 | |
| 188 | 188 | A Fossil repository consists of a single disk file. A single Fossil |
| 189 | 189 | repository can serve multiple simultaneous working checkouts. |
| 190 | -A Fossil repository is an SQLite database, so it highly resistant | |
| 190 | +A Fossil repository is an SQLite database, so it is highly resistant | |
| 191 | 191 | to damage from a power-loss or system crash - incomplete transactions |
| 192 | 192 | are simply rolled back after the system reboots. |
| 193 | 193 | |
| 194 | 194 | <h3>3.8 Audit Trail</h3> |
| 195 | 195 | |
| 196 | 196 |
| --- www/fossil-v-git.wiki | |
| +++ www/fossil-v-git.wiki | |
| @@ -185,11 +185,11 @@ | |
| 185 | between repositories and working checkouts. A power-loss or system crash |
| 186 | in the middle of Git operation can damage or corrupt the Git repository. |
| 187 | |
| 188 | A Fossil repository consists of a single disk file. A single Fossil |
| 189 | repository can serve multiple simultaneous working checkouts. |
| 190 | A Fossil repository is an SQLite database, so it highly resistant |
| 191 | to damage from a power-loss or system crash - incomplete transactions |
| 192 | are simply rolled back after the system reboots. |
| 193 | |
| 194 | <h3>3.8 Audit Trail</h3> |
| 195 | |
| 196 |
| --- www/fossil-v-git.wiki | |
| +++ www/fossil-v-git.wiki | |
| @@ -185,11 +185,11 @@ | |
| 185 | between repositories and working checkouts. A power-loss or system crash |
| 186 | in the middle of Git operation can damage or corrupt the Git repository. |
| 187 | |
| 188 | A Fossil repository consists of a single disk file. A single Fossil |
| 189 | repository can serve multiple simultaneous working checkouts. |
| 190 | A Fossil repository is an SQLite database, so it is highly resistant |
| 191 | to damage from a power-loss or system crash - incomplete transactions |
| 192 | are simply rolled back after the system reboots. |
| 193 | |
| 194 | <h3>3.8 Audit Trail</h3> |
| 195 | |
| 196 |
+4
| --- www/index.wiki | ||
| +++ www/index.wiki | ||
| @@ -110,10 +110,14 @@ | ||
| 110 | 110 | a Fossil repository. |
| 111 | 111 | |
| 112 | 112 | <hr> |
| 113 | 113 | <h3>Links For Fossil Users:</h3> |
| 114 | 114 | |
| 115 | + * "Fuel" is cross-platform GUI front-end for Fossil | |
| 116 | + written in Qt. [http://fuelscm.org/]. | |
| 117 | + Fuel is an independent project run by a different group of | |
| 118 | + developers. | |
| 115 | 119 | * [./reviews.wiki | Testimonials] from satisfied fossil users and |
| 116 | 120 | [./quotes.wiki | Quotes] about Fossil and other DVCSes. |
| 117 | 121 | * [./faq.wiki | FAQ] |
| 118 | 122 | * The [./concepts.wiki | concepts] behind fossil |
| 119 | 123 | * [./quickstart.wiki | Quick Start] guide to using fossil |
| 120 | 124 |
| --- www/index.wiki | |
| +++ www/index.wiki | |
| @@ -110,10 +110,14 @@ | |
| 110 | a Fossil repository. |
| 111 | |
| 112 | <hr> |
| 113 | <h3>Links For Fossil Users:</h3> |
| 114 | |
| 115 | * [./reviews.wiki | Testimonials] from satisfied fossil users and |
| 116 | [./quotes.wiki | Quotes] about Fossil and other DVCSes. |
| 117 | * [./faq.wiki | FAQ] |
| 118 | * The [./concepts.wiki | concepts] behind fossil |
| 119 | * [./quickstart.wiki | Quick Start] guide to using fossil |
| 120 |
| --- www/index.wiki | |
| +++ www/index.wiki | |
| @@ -110,10 +110,14 @@ | |
| 110 | a Fossil repository. |
| 111 | |
| 112 | <hr> |
| 113 | <h3>Links For Fossil Users:</h3> |
| 114 | |
| 115 | * "Fuel" is cross-platform GUI front-end for Fossil |
| 116 | written in Qt. [http://fuelscm.org/]. |
| 117 | Fuel is an independent project run by a different group of |
| 118 | developers. |
| 119 | * [./reviews.wiki | Testimonials] from satisfied fossil users and |
| 120 | [./quotes.wiki | Quotes] about Fossil and other DVCSes. |
| 121 | * [./faq.wiki | FAQ] |
| 122 | * The [./concepts.wiki | concepts] behind fossil |
| 123 | * [./quickstart.wiki | Quick Start] guide to using fossil |
| 124 |
+1
-1
| --- www/mkindex.tcl | ||
| +++ www/mkindex.tcl | ||
| @@ -1,8 +1,8 @@ | ||
| 1 | 1 | #!/bin/sh |
| 2 | 2 | # |
| 3 | -# Run this TCL script to generate a WIKI page that contains a | |
| 3 | +# Run this TCL script to generate a WIKI page that contains a | |
| 4 | 4 | # permuted index of the various documentation files. |
| 5 | 5 | # |
| 6 | 6 | # tclsh mkindex.tcl >permutedindex.wiki |
| 7 | 7 | # |
| 8 | 8 | |
| 9 | 9 |
| --- www/mkindex.tcl | |
| +++ www/mkindex.tcl | |
| @@ -1,8 +1,8 @@ | |
| 1 | #!/bin/sh |
| 2 | # |
| 3 | # Run this TCL script to generate a WIKI page that contains a |
| 4 | # permuted index of the various documentation files. |
| 5 | # |
| 6 | # tclsh mkindex.tcl >permutedindex.wiki |
| 7 | # |
| 8 | |
| 9 |
| --- www/mkindex.tcl | |
| +++ www/mkindex.tcl | |
| @@ -1,8 +1,8 @@ | |
| 1 | #!/bin/sh |
| 2 | # |
| 3 | # Run this TCL script to generate a WIKI page that contains a |
| 4 | # permuted index of the various documentation files. |
| 5 | # |
| 6 | # tclsh mkindex.tcl >permutedindex.wiki |
| 7 | # |
| 8 | |
| 9 |
+1
-1
| --- www/server.wiki | ||
| +++ www/server.wiki | ||
| @@ -70,11 +70,11 @@ | ||
| 70 | 70 | need to modify the pathnames for your particular setup. |
| 71 | 71 | The final argument is either the name of the fossil repository to be served, |
| 72 | 72 | or a directory containing multiple repositories. |
| 73 | 73 | </p> |
| 74 | 74 | <p> |
| 75 | -If you system is running xinetd, then the configuration is likely to be | |
| 75 | +If your system is running xinetd, then the configuration is likely to be | |
| 76 | 76 | in the file "/etc/xinetd.conf" or in a subfile of "/etc/xinetd.d". |
| 77 | 77 | An xinetd configuration file will appear like this:</p> |
| 78 | 78 | <blockquote> |
| 79 | 79 | <pre> |
| 80 | 80 | service http-alt |
| 81 | 81 |
| --- www/server.wiki | |
| +++ www/server.wiki | |
| @@ -70,11 +70,11 @@ | |
| 70 | need to modify the pathnames for your particular setup. |
| 71 | The final argument is either the name of the fossil repository to be served, |
| 72 | or a directory containing multiple repositories. |
| 73 | </p> |
| 74 | <p> |
| 75 | If you system is running xinetd, then the configuration is likely to be |
| 76 | in the file "/etc/xinetd.conf" or in a subfile of "/etc/xinetd.d". |
| 77 | An xinetd configuration file will appear like this:</p> |
| 78 | <blockquote> |
| 79 | <pre> |
| 80 | service http-alt |
| 81 |
| --- www/server.wiki | |
| +++ www/server.wiki | |
| @@ -70,11 +70,11 @@ | |
| 70 | need to modify the pathnames for your particular setup. |
| 71 | The final argument is either the name of the fossil repository to be served, |
| 72 | or a directory containing multiple repositories. |
| 73 | </p> |
| 74 | <p> |
| 75 | If your system is running xinetd, then the configuration is likely to be |
| 76 | in the file "/etc/xinetd.conf" or in a subfile of "/etc/xinetd.d". |
| 77 | An xinetd configuration file will appear like this:</p> |
| 78 | <blockquote> |
| 79 | <pre> |
| 80 | service http-alt |
| 81 |