Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Merge from trunk |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | th1-doc-vars |
Files: | files | file ages | folders |
SHA3-256: |
5b67899db09bdb6ac8cc39713865072c |
User & Date: | george 2021-08-15 23:13:12.993 |
Context
2021-10-09
| ||
19:31 | Merge in trunk (release 2.17) ... (check-in: 56e2d3ad user: george tags: th1-doc-vars) | |
2021-08-15
| ||
23:13 | Merge from trunk ... (check-in: 5b67899d user: george tags: th1-doc-vars) | |
18:38 | Remove a harmless unused variable. ... (check-in: a004b172 user: drh tags: trunk) | |
2021-06-15
| ||
21:27 | Merge from trunk ... (check-in: 1cf5c43e user: george tags: th1-doc-vars) | |
Changes
Changes to VERSION.
|
| | | 1 | 2.17 |
Changes to auto.def.
︙ | ︙ | |||
49 50 51 52 53 54 55 | } # Use pread/pwrite system calls in place of seek + read/write if possible define USE_PREAD [cc-check-functions pread] # If we have cscope here, we'll use it in the "tags" target if {[cc-check-progs cscope]} { | | | 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | } # Use pread/pwrite system calls in place of seek + read/write if possible define USE_PREAD [cc-check-functions pread] # If we have cscope here, we'll use it in the "tags" target if {[cc-check-progs cscope]} { define COLLECT_CSCOPE_DATA "cscope -bR $::autosetup(srcdir)/src/*.\[ch\]" } else { define COLLECT_CSCOPE_DATA "" } # Find tclsh for the test suite. # # We can't use jimsh for this: the test suite uses features of Tcl that |
︙ | ︙ | |||
99 100 101 102 103 104 105 106 107 108 109 110 111 112 | define EXTRA_CFLAGS "-Wall" define EXTRA_LDFLAGS "" define USE_SYSTEM_SQLITE 0 define USE_LINENOISE 0 define FOSSIL_ENABLE_MINIZ 0 define USE_MMAN_H 0 define USE_SEE 0 # This procedure is a customized version of "cc-check-function-in-lib", # that does not modify the LIBS variable. Its use prevents prematurely # pulling in libraries that will be added later anyhow (e.g. "-ldl"). proc check-function-in-lib {function libs {otherlibs {}}} { if {[string length $otherlibs]} { msg-checking "Checking for $function in $libs with $otherlibs..." | > > > > > > > > | 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | define EXTRA_CFLAGS "-Wall" define EXTRA_LDFLAGS "" define USE_SYSTEM_SQLITE 0 define USE_LINENOISE 0 define FOSSIL_ENABLE_MINIZ 0 define USE_MMAN_H 0 define USE_SEE 0 # Maintain the C89/C90-style order of variable declarations before statements. # Check if the compiler supports the respective warning flag. if {[cctest -cflags -Wdeclaration-after-statement]} { define-append EXTRA_CFLAGS -Wdeclaration-after-statement } # This procedure is a customized version of "cc-check-function-in-lib", # that does not modify the LIBS variable. Its use prevents prematurely # pulling in libraries that will be added later anyhow (e.g. "-ldl"). proc check-function-in-lib {function libs {otherlibs {}}} { if {[string length $otherlibs]} { msg-checking "Checking for $function in $libs with $otherlibs..." |
︙ | ︙ |
Changes to fossil.1.
|
| | | 1 2 3 4 5 6 7 8 | .TH FOSSIL "1" "July 2021" "https://fossil-scm.org" "User Commands" .SH NAME fossil \- Distributed Version Control System .SH SYNOPSIS .B fossil \fIhelp\fR .br .B fossil |
︙ | ︙ | |||
92 93 94 95 96 97 98 | .HP 8. .B Free and Open-Source - Uses the 2-clause BSD license. .SH DOCUMENTATION | | | 92 93 94 95 96 97 98 99 100 101 102 | .HP 8. .B Free and Open-Source - Uses the 2-clause BSD license. .SH DOCUMENTATION https://fossil-scm.org/ .br .B fossil \fIui\fR |
Changes to src/add.c.
︙ | ︙ | |||
480 481 482 483 484 485 486 487 488 489 | /** Check for Windows-reserved names and warn or exit, as ** appopriate. Note that the 'add' internal machinery already ** _silently_ skips over any names for which ** file_is_reserved_name() returns true or which is in the ** fossil_reserved_name() list. We do not need to warn for those, ** as they're outright verboten. */ if(db_exists("SELECT 1 FROM sfile WHERE win_reserved(pathname)")){ Stmt q = empty_Stmt; db_prepare(&q,"SELECT pathname FROM sfile " "WHERE win_reserved(pathname)"); | > < | 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 | /** Check for Windows-reserved names and warn or exit, as ** appopriate. Note that the 'add' internal machinery already ** _silently_ skips over any names for which ** file_is_reserved_name() returns true or which is in the ** fossil_reserved_name() list. We do not need to warn for those, ** as they're outright verboten. */ if(db_exists("SELECT 1 FROM sfile WHERE win_reserved(pathname)")){ int reservedCount = 0; Stmt q = empty_Stmt; db_prepare(&q,"SELECT pathname FROM sfile " "WHERE win_reserved(pathname)"); while( db_step(&q)==SQLITE_ROW ){ const char * zName = db_column_text(&q, 0); ++reservedCount; if(allowReservedFlag){ fossil_warning("WARNING: Windows-reserved " "filename: %s", zName); }else{ |
︙ | ︙ |
Changes to src/alerts.c.
︙ | ︙ | |||
395 396 397 398 399 400 401 | x[2] = "0123456789ABCDEF"[c&0xf]; blob_append(pOut, x, 3); iCol += 3; } } } | < < < < < < < | 395 396 397 398 399 400 401 402 403 404 405 406 407 408 | x[2] = "0123456789ABCDEF"[c&0xf]; blob_append(pOut, x, 3); iCol += 3; } } } #if INTERFACE /* ** An instance of the following object is used to send emails. */ struct AlertSender { sqlite3 *db; /* Database emails are sent to */ sqlite3_stmt *pStmt; /* Stmt to insert into the database */ |
︙ | ︙ | |||
1158 1159 1160 1161 1162 1163 1164 | if( g.argc!=3 && g.argc!=5 ) usage("setting [NAME VALUE]"); if( g.argc==5 ){ const char *zLabel = g.argv[3]; if( strncmp(zLabel, "email-", 6)!=0 || (pSetting = db_find_setting(zLabel, 1))==0 ){ fossil_fatal("not a valid email setting: \"%s\"", zLabel); } | | | 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 | if( g.argc!=3 && g.argc!=5 ) usage("setting [NAME VALUE]"); if( g.argc==5 ){ const char *zLabel = g.argv[3]; if( strncmp(zLabel, "email-", 6)!=0 || (pSetting = db_find_setting(zLabel, 1))==0 ){ fossil_fatal("not a valid email setting: \"%s\"", zLabel); } db_set(pSetting->name/*works-like:""*/, g.argv[4], isGlobal); g.argc = 3; } pSetting = setting_info(&nSetting); for(; nSetting>0; nSetting--, pSetting++ ){ if( strncmp(pSetting->name,"email-",6)!=0 ) continue; print_setting(pSetting); } |
︙ | ︙ | |||
3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 | ** capability, that allows one to send announcements to whomever ** has subscribed to receive announcements. The administrator can ** also send a message to an arbitrary email address and/or to all ** subscribers regardless of whether or not they have elected to ** receive announcements. */ void announce_page(void){ login_check_credentials(); if( !g.perm.Announce ){ login_needed(0); return; } style_set_current_feature("alerts"); if( fossil_strcmp(P("name"),"test1")==0 ){ /* Visit the /announce/test1 page to see the CGI variables */ @ <p style='border: 1px solid black; padding: 1ex;'> cgi_print_all(0, 0); @ </p> }else if( P("submit")!=0 && cgi_csrf_safe(1) ){ char *zErr = alert_send_announcement(); style_header("Announcement Sent"); if( zErr ){ | > > > > > > > > | 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 | ** capability, that allows one to send announcements to whomever ** has subscribed to receive announcements. The administrator can ** also send a message to an arbitrary email address and/or to all ** subscribers regardless of whether or not they have elected to ** receive announcements. */ void announce_page(void){ const char *zAction = "announce" /* Maintenance reminder: we need an explicit action=THIS_PAGE on the ** form element to avoid that a URL arg of to=... passed to this ** page ends up overwriting the form-posted "to" value. This ** action value differs for the test1 request path. */; login_check_credentials(); if( !g.perm.Announce ){ login_needed(0); return; } style_set_current_feature("alerts"); if( fossil_strcmp(P("name"),"test1")==0 ){ /* Visit the /announce/test1 page to see the CGI variables */ zAction = "announce/test1"; @ <p style='border: 1px solid black; padding: 1ex;'> cgi_print_all(0, 0); @ </p> }else if( P("submit")!=0 && cgi_csrf_safe(1) ){ char *zErr = alert_send_announcement(); style_header("Announcement Sent"); if( zErr ){ |
︙ | ︙ | |||
3288 3289 3290 3291 3292 3293 3294 | @ <p>Either you have no subscribers yet, or email alerts are not yet @ <a href="https://fossil-scm.org/fossil/doc/trunk/www/alerts.md">set up</a> @ for this repository.</p> return; } style_header("Send Announcement"); | | | 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 | @ <p>Either you have no subscribers yet, or email alerts are not yet @ <a href="https://fossil-scm.org/fossil/doc/trunk/www/alerts.md">set up</a> @ for this repository.</p> return; } style_header("Send Announcement"); @ <form method="POST" action="%R/%s(zAction)"> @ <table class="subscribe"> if( g.perm.Admin ){ int aa = PB("aa"); int all = PB("all"); int aMod = PB("mods"); const char *aack = aa ? "checked" : ""; const char *allck = all ? "checked" : ""; |
︙ | ︙ |
Changes to src/allrepo.c.
︙ | ︙ | |||
108 109 110 111 112 113 114 | ** supported by the rebuild command itself, if any are ** present, are passed along verbatim. The --force and ** --randomize options are not supported. ** ** sync Run a "sync" on all repositories. Only the --verbose ** and --unversioned options are supported. ** | | > > | | > > > > > | 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | ** supported by the rebuild command itself, if any are ** present, are passed along verbatim. The --force and ** --randomize options are not supported. ** ** sync Run a "sync" on all repositories. Only the --verbose ** and --unversioned options are supported. ** ** set Run the "setting" or "set" commands on all ** repositories. These command are particularly useful in ** conjunction with the "max-loadavg" setting which cannot ** otherwise be set globally. ** ** unset Run the "unset" command on all repositories ** ** server Run the "server" commands on all repositories. ** The root URI gives a listing of all repos. ** ** ui Run the "ui" command on all repositories. Like "server" ** but bind to the loopback TCP address only, enable ** the --localauth option and automatically launch a ** web-browser ** ** ** In addition, the following maintenance operations are supported: ** ** add Add all the repositories named to the set of repositories ** tracked by Fossil. Normally Fossil is able to keep up with ** this list by itself, but sometimes it can benefit from this |
︙ | ︙ | |||
245 246 247 248 249 250 251 | if( g.argc<4 ){ usage("git (export|status)"); }else{ int n3 = (int)strlen(g.argv[3]); if( strncmp(g.argv[3], "export", n3)==0 ){ zCmd = "git export --if-mirrored -R"; }else if( strncmp(g.argv[3], "status", n3)==0 ){ | | > | 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 | if( g.argc<4 ){ usage("git (export|status)"); }else{ int n3 = (int)strlen(g.argv[3]); if( strncmp(g.argv[3], "export", n3)==0 ){ zCmd = "git export --if-mirrored -R"; }else if( strncmp(g.argv[3], "status", n3)==0 ){ zCmd = "git status --by-all -q -R"; quiet = 1; }else{ usage("git (export|status)"); } } }else if( strncmp(zCmd, "push", n)==0 ){ zCmd = "push -autourl -R"; collect_argument(&extra, "verbose","v"); |
︙ | ︙ |
Changes to src/attach.c.
︙ | ︙ | |||
776 777 778 779 780 781 782 | goto attachment_cmd_usage; } return; attachment_cmd_usage: usage("add ?PAGENAME? FILENAME [-t|--technote DATETIME ]"); } | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 | goto attachment_cmd_usage; } return; attachment_cmd_usage: usage("add ?PAGENAME? FILENAME [-t|--technote DATETIME ]"); } /* ** COMMAND: test-list-attachments ** ** Usage: %fossil test-list-attachments ?-latest? ?TargetName(s)...? ** ** List attachments for one or more attachment targets. The target ** name arguments are glob prefixes for the attachment.target ** field. If no names are provided then a prefix of [a-zA-Z] is used, ** which will match most wiki page names and some ticket hashes. ** ** Options: ** ** -latest List only the latest version of a given attachment. ** */ void test_list_attachments(void){ Stmt q; int i; const int fLatest = find_option("latest", 0, 0) != 0; db_find_and_open_repository(0, 0); verify_all_options(); db_prepare(&q, "SELECT datetime(mtime,toLocal()), src, target, filename," " comment, user " " FROM attachment" " WHERE target GLOB :tgtname ||'*'" " AND (isLatest OR %d)" " ORDER BY target, isLatest DESC, mtime DESC", !fLatest ); if(g.argc<3){ static char * argv[3] = {0,0,"[a-zA-Z]"}; g.argc = 3; g.argv = argv; } for(i = 2; i < g.argc; ++i){ const char *zPage = g.argv[i]; db_bind_text(&q, ":tgtname", zPage); while(SQLITE_ROW == db_step(&q)){ const char * zTime = db_column_text(&q, 0); const char * zSrc = db_column_text(&q, 1); const char * zTarget = db_column_text(&q, 2); const char * zName = db_column_text(&q, 3); printf("%-20s %s %.12s %s\n", zTarget, zTime, zSrc, zName); } db_reset(&q); } db_finalize(&q); } |
Changes to src/backlink.c.
︙ | ︙ | |||
23 24 25 26 27 28 29 | */ #include "config.h" #include "backlink.h" #include <assert.h> /* | | | 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | */ #include "config.h" #include "backlink.h" #include <assert.h> /* ** Show a graph of all wiki, tickets, and check-ins that refer to object zUuid. ** ** If zLabel is not NULL and the graph is not empty, then output zLabel as ** a prefix to the graph. */ void render_backlink_graph(const char *zUuid, const char *zLabel){ Blob sql; Stmt q; |
︙ | ︙ |
Changes to src/backoffice.c.
︙ | ︙ | |||
482 483 484 485 486 487 488 489 490 491 492 493 494 495 | sqlite3_uint64 tmNow; sqlite3_uint64 idSelf; int lastWarning = 0; int warningDelay = 30; static int once = 0; if( sqlite3_db_readonly(g.db, 0) ) return; backoffice_error_check_one(&once); idSelf = backofficeProcessId(); while(1){ tmNow = time(0); db_begin_write(); backofficeReadLease(&x); if( x.tmNext>=tmNow | > | 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 | sqlite3_uint64 tmNow; sqlite3_uint64 idSelf; int lastWarning = 0; int warningDelay = 30; static int once = 0; if( sqlite3_db_readonly(g.db, 0) ) return; g.zPhase = "backoffice"; backoffice_error_check_one(&once); idSelf = backofficeProcessId(); while(1){ tmNow = time(0); db_begin_write(); backofficeReadLease(&x); if( x.tmNext>=tmNow |
︙ | ︙ | |||
752 753 754 755 756 757 758 | if( iNow && iNow>file_mtime(g.argv[i], ExtFILE) && (nMin<=0 || aLastRun[i]+nMin>iNow) ){ continue; /* Not yet time to run this one */ } blob_init(&cmd, 0, 0); | | | | | 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 | if( iNow && iNow>file_mtime(g.argv[i], ExtFILE) && (nMin<=0 || aLastRun[i]+nMin>iNow) ){ continue; /* Not yet time to run this one */ } blob_init(&cmd, 0, 0); blob_append_escaped_arg(&cmd, g.nameOfExe, 1); blob_append(&cmd, " backoffice --nodelay", -1); if( g.fAnyTrace ){ blob_append(&cmd, " --trace", -1); } if( bDebug ){ blob_append(&cmd, " --debug", -1); } if( nPoll>0 ){ blob_append(&cmd, " --nolease", -1); } if( backofficeLogfile ){ blob_append(&cmd, " --logfile", -1); blob_append_escaped_arg(&cmd, backofficeLogfile, 1); } blob_append_escaped_arg(&cmd, g.argv[i], 1); nCmd++; if( bDebug ){ fossil_print("COMMAND[%u]: %s\n", nCmd, blob_str(&cmd)); } fossil_system(blob_str(&cmd)); aLastRun[i] = iNext; blob_reset(&cmd); |
︙ | ︙ |
Changes to src/bisect.c.
︙ | ︙ | |||
371 372 373 374 375 376 377 | /* ** Reset the bisect subsystem. */ void bisect_reset(void){ db_multi_exec( "DELETE FROM vvar WHERE name IN " | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 | /* ** Reset the bisect subsystem. */ void bisect_reset(void){ db_multi_exec( "DELETE FROM vvar WHERE name IN " " ('bisect-good', 'bisect-bad', 'bisect-log', 'bisect-complete')" ); } /* ** fossil bisect run [OPTIONS] COMMAND ** ** Invoke COMMAND (with arguments) repeatedly to perform the bisect. ** Options: ** ** -i|--interactive Prompt user for decisions rather than ** using the return code from COMMAND */ static void bisect_run(void){ const char *zCmd; int isInteractive = 0; int i; if( g.argc<4 ){ fossil_fatal("Usage: fossil bisect run [OPTIONS] COMMAND\n"); } for(i=3; i<g.argc-1; i++){ const char *zArg = g.argv[i]; if( zArg[0]=='-' && zArg[1]=='-' && zArg[2]!=0 ) zArg++; if( strcmp(zArg, "-i")==0 || strcmp(zArg, "-interactive")==0 ){ isInteractive = 1; continue; } fossil_fatal("unknown command-line option: \"%s\"\n", g.argv[i]); } zCmd = g.argv[i]; if( db_int(0, "SELECT count(*) FROM vvar" " WHERE name IN ('bisect-good','bisect-bad')")!=2 ){ fossil_fatal("need good/bad boundaries to use \"fossil bisect run\""); } while( db_lget_int("bisect-complete",0)==0 ){ int rc; Blob cmd; blob_init(&cmd, 0, 0); blob_append_escaped_arg(&cmd, g.nameOfExe, 1); rc = fossil_unsafe_system(zCmd); if( isInteractive ){ Blob in; fossil_print("test-command result: %d\n", rc); while(1){ int n; char *z; prompt_user("Enter (g)ood, (b)ad, (s)kip, (a)uto, (h)alt: ", &in); n = blob_size(&in); z = blob_str(&in); if( n<1 ) continue; if( sqlite3_strnicmp("good", z, n)==0 ){ rc = 0; break; } if( sqlite3_strnicmp("bad", z, n)==0 ){ rc = 1; break; } if( sqlite3_strnicmp("skip", z, n)==0 ){ rc = 125; break; } if( sqlite3_strnicmp("auto", z, n)==0 ){ isInteractive = 0; break; } if( sqlite3_strnicmp("halt", z, n)==0 ){ return; } blob_reset(&in); } } if( rc==0 ){ blob_append(&cmd, " bisect good", -1); }else if( rc==125 ){ blob_append(&cmd, " bisect skip", -1); }else{ blob_append(&cmd, " bisect bad", -1); } fossil_print("%s\n", blob_str(&cmd)); fossil_system(blob_str(&cmd)); blob_reset(&cmd); } } /* ** COMMAND: bisect ** ** Usage: %fossil bisect SUBCOMMAND ... ** ** Run various subcommands useful for searching back through the change |
︙ | ︙ | |||
415 416 417 418 419 420 421 422 423 424 425 426 427 428 | ** value of a bisect option. ** ** > fossil bisect reset ** ** Reinitialize a bisect session. This cancels prior bisect history ** and allows a bisect session to start over from the beginning. ** ** > fossil bisect skip ?VERSION? ** ** Cause VERSION (or the current checkout if VERSION is omitted) to ** be ignored for the purpose of the current bisect. This might ** be done, for example, because VERSION does not compile correctly ** or is otherwise unsuitable to participate in this bisect. ** | > > > > > > > > > > | 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 | ** value of a bisect option. ** ** > fossil bisect reset ** ** Reinitialize a bisect session. This cancels prior bisect history ** and allows a bisect session to start over from the beginning. ** ** > fossil bisect run [OPTIONS] COMMAND ** ** Invoke COMMAND repeatedly to run the bisect. The exit code for ** COMMAND should be 0 for "good", 125 for "skip", and any other value ** for "bad". Options: ** ** -i|--interactive Prompt the user for the good/bad/skip decision ** after each step, rather than using the exit ** code from COMMAND ** ** > fossil bisect skip ?VERSION? ** ** Cause VERSION (or the current checkout if VERSION is omitted) to ** be ignored for the purpose of the current bisect. This might ** be done, for example, because VERSION does not compile correctly ** or is otherwise unsuitable to participate in this bisect. ** |
︙ | ︙ | |||
538 539 540 541 542 543 544 545 546 547 548 549 550 551 | PathNode *pMid; char *zDisplay = db_lget("bisect-display","chart"); int m = (int)strlen(zDisplay); bisect_path(); pMid = path_midpoint(); if( pMid==0 ){ fossil_print("bisect complete\n"); }else{ int nSpan = path_length_not_hidden(); int nStep = path_search_depth(); g.argv[1] = "update"; g.argv[2] = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", pMid->rid); g.argc = 3; g.fNoSync = 1; | > | 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 | PathNode *pMid; char *zDisplay = db_lget("bisect-display","chart"); int m = (int)strlen(zDisplay); bisect_path(); pMid = path_midpoint(); if( pMid==0 ){ fossil_print("bisect complete\n"); db_lset_int("bisect-complete",1); }else{ int nSpan = path_length_not_hidden(); int nStep = path_search_depth(); g.argv[1] = "update"; g.argv[2] = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", pMid->rid); g.argc = 3; g.fNoSync = 1; |
︙ | ︙ | |||
560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 | }else if( strncmp(zDisplay, "status", m)==0 ){ bisect_list(1); } }else if( strncmp(zCmd, "log", n)==0 ){ bisect_chart(0); }else if( strncmp(zCmd, "chart", n)==0 ){ bisect_chart(1); }else if( strncmp(zCmd, "options", n)==0 ){ if( g.argc==3 ){ unsigned int i; for(i=0; i<count(aBisectOption); i++){ char *z = mprintf("bisect-%s", aBisectOption[i].zName); fossil_print(" %-15s %-6s ", aBisectOption[i].zName, db_lget(z, (char*)aBisectOption[i].zDefault)); fossil_free(z); comment_print(aBisectOption[i].zDesc, 0, 27, -1, get_comment_format()); } }else if( g.argc==4 || g.argc==5 ){ unsigned int i; n = strlen(g.argv[3]); for(i=0; i<count(aBisectOption); i++){ if( strncmp(g.argv[3], aBisectOption[i].zName, n)==0 ){ char *z = mprintf("bisect-%s", aBisectOption[i].zName); if( g.argc==5 ){ | > > | | 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 | }else if( strncmp(zDisplay, "status", m)==0 ){ bisect_list(1); } }else if( strncmp(zCmd, "log", n)==0 ){ bisect_chart(0); }else if( strncmp(zCmd, "chart", n)==0 ){ bisect_chart(1); }else if( strncmp(zCmd, "run", n)==0 ){ bisect_run(); }else if( strncmp(zCmd, "options", n)==0 ){ if( g.argc==3 ){ unsigned int i; for(i=0; i<count(aBisectOption); i++){ char *z = mprintf("bisect-%s", aBisectOption[i].zName); fossil_print(" %-15s %-6s ", aBisectOption[i].zName, db_lget(z, (char*)aBisectOption[i].zDefault)); fossil_free(z); comment_print(aBisectOption[i].zDesc, 0, 27, -1, get_comment_format()); } }else if( g.argc==4 || g.argc==5 ){ unsigned int i; n = strlen(g.argv[3]); for(i=0; i<count(aBisectOption); i++){ if( strncmp(g.argv[3], aBisectOption[i].zName, n)==0 ){ char *z = mprintf("bisect-%s", aBisectOption[i].zName); if( g.argc==5 ){ db_lset(z/*works-like:"bisect-%s"*/, g.argv[4]); } fossil_print("%s\n", db_lget(z, (char*)aBisectOption[i].zDefault)); fossil_free(z); break; } } if( i>=count(aBisectOption) ){ |
︙ | ︙ | |||
610 611 612 613 614 615 616 | || strncmp(zCmd, "ls", n)==0 || strncmp(zCmd, "status", n)==0 ){ int fAll = find_option("all", "a", 0)!=0; bisect_list(!fAll); }else if( !foundCmd ){ usage: | | | 704 705 706 707 708 709 710 711 712 713 | || strncmp(zCmd, "ls", n)==0 || strncmp(zCmd, "status", n)==0 ){ int fAll = find_option("all", "a", 0)!=0; bisect_list(!fAll); }else if( !foundCmd ){ usage: usage("bad|good|log|chart|next|options|reset|run|skip|status|ui|undo"); } } |
Changes to src/blob.c.
︙ | ︙ | |||
458 459 460 461 462 463 464 | /* ** Compare a blob to a string. Return TRUE if they are equal. */ int blob_eq_str(Blob *pBlob, const char *z, int n){ Blob t; blob_is_init(pBlob); | | | | 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 | /* ** Compare a blob to a string. Return TRUE if they are equal. */ int blob_eq_str(Blob *pBlob, const char *z, int n){ Blob t; blob_is_init(pBlob); if( n<=0 ) n = (int)strlen(z); t.aData = (char*)z; t.nUsed = n; t.xRealloc = blobReallocStatic; return blob_compare(pBlob, &t)==0; } /* ** This macro compares a blob against a string constant. We use the sizeof() ** operator on the string constant twice, so it really does need to be a ** string literal or character array - not a character pointer. */ #if INTERFACE # define blob_eq(B,S) \ ((B)->nUsed==sizeof(S"")-1 && memcmp((B)->aData,S,sizeof(S)-1)==0) #endif /* ** Attempt to resize a blob so that its internal buffer is ** nByte in size. The blob is truncated if necessary. */ |
︙ | ︙ | |||
1291 1292 1293 1294 1295 1296 1297 1298 1299 | } }else{ z[--j] = z[i]; } } } /* ** pBlob is a shell command under construction. This routine safely | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > | | | | | | | < < < < < < < < < > > > > | > | < < < < < < < < > > > > > > > > > > > > > > > > > | > | > > > > > > | | | < > | | | > > > > > > > > > > | > > | | | > | > > > > > > > | > | > > > > | > > > > > | < < < < < | < | > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > | > > > | 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 | } }else{ z[--j] = z[i]; } } } /* ** ASCII (for reference): ** x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf ** 0x ^` ^a ^b ^c ^d ^e ^f ^g \b \t \n () \f \r ^n ^o ** 1x ^p ^q ^r ^s ^t ^u ^v ^w ^x ^y ^z ^{ ^| ^} ^~ ^ ** 2x () ! " # $ % & ' ( ) * + , - . / ** 3x 0 1 2 3 4 5 6 7 8 9 : ; < = > ? ** 4x @ A B C D E F G H I J K L M N O ** 5x P Q R S T U V W X Y Z [ \ ] ^ _ ** 6x ` a b c d e f g h i j k l m n o ** 7x p q r s t u v w x y z { | } ~ ^_ */ /* ** Meanings for bytes in a filename: ** ** 0 Ordinary character. No encoding required ** 1 Needs to be escaped ** 2 Illegal character. Do not allow in a filename ** 3 First byte of a 2-byte UTF-8 ** 4 First byte of a 3-byte UTF-8 ** 5 First byte of a 4-byte UTF-8 */ static const char aSafeChar[256] = { #ifdef _WIN32 /* Windows ** Prohibit: all control characters, including tab, \r and \n ** Escape: (space) " # $ % & ' ( ) * ; < > ? [ ] ^ ` { | } */ /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 1x */ 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 2x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, /* 3x */ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, /* 5x */ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /* 7x */ #else /* Unix ** Prohibit: all control characters, including tab, \r and \n ** Escape: (space) ! " # $ % & ' ( ) * ; < > ? [ \ ] ^ ` { | } */ /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 1x */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 2x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, /* 3x */ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, /* 5x */ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /* 7x */ #endif /* all bytes 0x80 through 0xbf are unescaped, being secondary ** bytes to UTF8 characters. Bytes 0xc0 through 0xff are the ** first byte of a UTF8 character and do get escaped */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 8x */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 9x */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* ax */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* bx */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* cx */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* dx */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* ex */ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 /* fx */ }; /* ** pBlob is a shell command under construction. This routine safely ** appends filename argument zIn. ** ** The argument is escaped if it contains white space or other characters ** that need to be escaped for the shell. If zIn contains characters ** that cannot be safely escaped, then throw a fatal error. ** ** If the isFilename argument is true, then the argument is expected ** to be a filename. As shell commands commonly have command-line ** options that begin with "-" and since we do not want an attacker ** to be able to invoke these switches using filenames that begin ** with "-", if zIn begins with "-", prepend an additional "./" ** (or ".\\" on Windows). */ void blob_append_escaped_arg(Blob *pBlob, const char *zIn, int isFilename){ int i; unsigned char c; int needEscape = 0; int n = blob_size(pBlob); char *z = blob_buffer(pBlob); /* Look for illegal byte-sequences and byte-sequences that require ** escaping. No control-characters are allowed. All spaces and ** non-ASCII unicode characters and some punctuation characters require ** escaping. */ for(i=0; (c = (unsigned char)zIn[i])!=0; i++){ if( aSafeChar[c] ){ unsigned char x = aSafeChar[c]; needEscape = 1; if( x==2 ){ Blob bad; blob_token(pBlob, &bad); fossil_fatal("the [%s] argument to the \"%s\" command contains " "a character (ascii 0x%02x) that is not allowed in " "filename arguments", zIn, blob_str(&bad), c); }else if( x>2 ){ if( (zIn[i+1]&0xc0)!=0x80 || (x>=4 && (zIn[i+2]&0xc0)!=0x80) || (x==5 && (zIn[i+3]&0xc0)!=0x80) ){ Blob bad; blob_token(pBlob, &bad); fossil_fatal("the [%s] argument to the \"%s\" command contains " "an illegal UTF-8 character", zIn, blob_str(&bad)); } i += x-2; } } } /* Separate from the previous argument by a space */ if( n>0 && !fossil_isspace(z[n-1]) ){ blob_append_char(pBlob, ' '); } /* Check for characters that need quoting */ if( !needEscape ){ if( isFilename && zIn[0]=='-' ){ blob_append_char(pBlob, '.'); #if defined(_WIN32) blob_append_char(pBlob, '\\'); #else blob_append_char(pBlob, '/'); #endif } blob_append(pBlob, zIn, -1); }else{ #if defined(_WIN32) /* Quoting strategy for windows: ** Put the entire name inside of "...". Any " characters within ** the name get doubled. */ blob_append_char(pBlob, '"'); if( isFilename && zIn[0]=='-' ){ blob_append_char(pBlob, '.'); blob_append_char(pBlob, '\\'); }else if( zIn[0]=='/' ){ blob_append_char(pBlob, '.'); } for(i=0; (c = (unsigned char)zIn[i])!=0; i++){ blob_append_char(pBlob, (char)c); if( c=='"' ) blob_append_char(pBlob, '"'); } blob_append_char(pBlob, '"'); #else /* Quoting strategy for unix: ** If the name does not contain ', then surround the whole thing ** with '...'. If there is one or more ' characters within the ** name, then put \ before each special character. */ if( strchr(zIn,'\'') ){ if( isFilename && zIn[0]=='-' ){ blob_append_char(pBlob, '.'); blob_append_char(pBlob, '/'); } for(i=0; (c = (unsigned char)zIn[i])!=0; i++){ if( aSafeChar[c] && aSafeChar[c]!=2 ) blob_append_char(pBlob, '\\'); blob_append_char(pBlob, (char)c); } }else{ blob_append_char(pBlob, '\''); if( isFilename && zIn[0]=='-' ){ blob_append_char(pBlob, '.'); blob_append_char(pBlob, '/'); } blob_append(pBlob, zIn, -1); blob_append_char(pBlob, '\''); } #endif } } /* ** COMMAND: test-escaped-arg ** ** Usage %fossil ARGS ... ** ** Run each argument through blob_append_escaped_arg() and show the ** result. Append each argument to "fossil test-echo" and run that ** using fossil_system() to verify that it really does get escaped ** correctly. ** ** Other options: ** ** --filename-args BOOL Subsequent arguments are assumed to be ** filenames if BOOL is true, or not if BOOL ** is false. Defaults on. ** ** --hex HEX Skip the --hex flag and instead decode HEX ** into ascii. This provides a way to insert ** unusual characters as an argument for testing. ** ** --compare HEX ASCII Verify that argument ASCII is identical to ** to decoded HEX. ** ** --fuzz N Run N fuzz cases. Each cases is a call ** to "fossil test-escaped-arg --compare HEX ARG" ** where HEX and ARG are the same argument. ** The argument is chosen at random. */ void test_escaped_arg_command(void){ int i; Blob x; const char *zArg; int isFilename = 1; char zBuf[100]; blob_init(&x, 0, 0); for(i=2; i<g.argc; i++){ zArg = g.argv[i]; if( fossil_strcmp(zArg, "--hex")==0 && i+1<g.argc ){ size_t n = strlen(g.argv[++i]); if( n>=(sizeof(zBuf)-1)*2 ){ fossil_fatal("Argument to --hex is too big"); } memset(zBuf, 0, sizeof(zBuf)); decode16((const unsigned char*)g.argv[i], (unsigned char*)zBuf, (int)n); zArg = zBuf; }else if( fossil_strcmp(zArg, "--compare")==0 && i+2<g.argc ){ size_t n = strlen(g.argv[++i]); if( n>=(sizeof(zBuf)-1)*2 ){ fossil_fatal("HEX argument to --compare is too big"); } memset(zBuf, 0, sizeof(zBuf)); if( decode16((const unsigned char*)g.argv[i], (unsigned char*)zBuf, (int)n) ){ fossil_fatal("HEX decode of %s failed", g.argv[i]); } zArg = g.argv[++i]; if( zArg[0]=='-' ){ fossil_fatal("filename argument \"%s\" begins with \"-\"", zArg); } #ifdef _WIN32 if( zBuf[0]=='-' && zArg[0]=='.' && zArg[1]=='\\' ) zArg += 2; #else if( zBuf[0]=='-' && zArg[0]=='.' && zArg[1]=='/' ) zArg += 2; #endif if( strcmp(zBuf, zArg)!=0 ){ fossil_fatal("argument disagree: \"%s\" (%s) versus \"%s\"", zBuf, g.argv[i-1], zArg); } continue; }else if( fossil_strcmp(zArg, "--fuzz")==0 && i+1<g.argc ){ int n = atoi(g.argv[++i]); int j; for(j=0; j<n; j++){ unsigned char m, k; int rc; unsigned char zWord[100]; sqlite3_randomness(sizeof(m), &m); m = (m%40)+5; sqlite3_randomness(m, zWord); /* Between 5 and 45 bytes of randomness */ for(k=0; k<m; k++){ unsigned char cx = zWord[k]; if( cx<0x20 || cx>=0x7f ){ /* Translate illegal bytes into various non-ASCII unicode ** characters in order to exercise those code paths */ unsigned int u; if( cx>=0x7f ){ u = cx; }else if( cx>=0x08 ){ u = 0x800 + cx; }else{ u = 0x10000 + cx; } if( u<0x00080 ){ zWord[k] = u & 0xFF; }else if( u<0x00800 ){ zWord[k++] = 0xC0 + (u8)((u>>6)&0x1F); zWord[k] = 0x80 + (u8)(u & 0x3F); }else if( u<0x10000 ){ zWord[k++] = 0xE0 + (u8)((u>>12)&0x0F); zWord[k++] = 0x80 + (u8)((u>>6) & 0x3F); zWord[k] = 0x80 + (u8)(u & 0x3F); }else{ zWord[k++] = 0xF0 + (u8)((u>>18) & 0x07); zWord[k++] = 0x80 + (u8)((u>>12) & 0x3F); zWord[k++] = 0x80 + (u8)((u>>6) & 0x3F); zWord[k] = 0x80 + (u8)(u & 0x3F); } } } zWord[k] = 0; encode16(zWord, (unsigned char*)zBuf, (int)k); blob_appendf(&x, "%$ test-escaped-arg --compare %s %$", g.nameOfExe, zBuf,zWord); rc = fossil_system(blob_str(&x)); if( rc ) fossil_fatal("failed test (%d): %s\n", rc, blob_str(&x)); blob_reset(&x); } continue; }else if( fossil_strcmp(zArg, "--filename-args")==0 ){ if( i+1<g.argc ){ i++; isFilename = is_truth(g.argv[i]); } continue; } fossil_print("%3d [%s]: ", i, zArg); if( isFilename ){ blob_appendf(&x, "%$ test-echo %$", g.nameOfExe, zArg); }else{ blob_appendf(&x, "%$ test-echo %!$", g.nameOfExe, zArg); } fossil_print("%s\n", blob_str(&x)); fossil_system(blob_str(&x)); blob_reset(&x); } } /* |
︙ | ︙ |
Changes to src/branch.c.
︙ | ︙ | |||
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | const char *zColor; /* Color of the new branch */ Blob branch; /* manifest for the new branch */ Manifest *pParent; /* Parsed parent manifest */ Blob mcksum; /* Self-checksum on the manifest */ const char *zDateOvrd; /* Override date string */ const char *zUserOvrd; /* Override user name */ int isPrivate = 0; /* True if the branch should be private */ noSign = find_option("nosign","",0)!=0; zColor = find_option("bgcolor","c",1); isPrivate = find_option("private",0,0)!=0; zDateOvrd = find_option("date-override",0,1); zUserOvrd = find_option("user-override",0,1); verify_all_options(); if( g.argc<5 ){ usage("new BRANCH-NAME BASIS ?OPTIONS?"); } | > > > > > | 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | const char *zColor; /* Color of the new branch */ Blob branch; /* manifest for the new branch */ Manifest *pParent; /* Parsed parent manifest */ Blob mcksum; /* Self-checksum on the manifest */ const char *zDateOvrd; /* Override date string */ const char *zUserOvrd; /* Override user name */ int isPrivate = 0; /* True if the branch should be private */ int bAutoColor = 0; /* Value of "--bgcolor" is "auto" */ noSign = find_option("nosign","",0)!=0; zColor = find_option("bgcolor","c",1); if( fossil_strncmp(zColor, "auto", 4)==0 ) { bAutoColor = 1; zColor = 0; } isPrivate = find_option("private",0,0)!=0; zDateOvrd = find_option("date-override",0,1); zUserOvrd = find_option("user-override",0,1); verify_all_options(); if( g.argc<5 ){ usage("new BRANCH-NAME BASIS ?OPTIONS?"); } |
︙ | ︙ | |||
149 150 151 152 153 154 155 | blob_appendf(&branch, "R %s\n", pParent->zRepoCksum); } manifest_destroy(pParent); /* Add the symbolic branch name and the "branch" tag to identify ** this as a new branch */ if( content_is_private(rootid) ) isPrivate = 1; | | | 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 | blob_appendf(&branch, "R %s\n", pParent->zRepoCksum); } manifest_destroy(pParent); /* Add the symbolic branch name and the "branch" tag to identify ** this as a new branch */ if( content_is_private(rootid) ) isPrivate = 1; if( isPrivate && zColor==0 && !bAutoColor) zColor = "#fec084"; if( zColor!=0 ){ blob_appendf(&branch, "T *bgcolor * %F\n", zColor); } blob_appendf(&branch, "T *branch * %F\n", zBranch); blob_appendf(&branch, "T *sym-%F *\n", zBranch); if( isPrivate ){ noSign = 1; |
︙ | ︙ | |||
337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 | " WHERE tagid=%d" " AND tagtype=1" " AND ox.rid=ix.rid)", TAG_BRANCH, zBrName, TAG_CLOSED ); } /* ** COMMAND: branch ** ** Usage: %fossil branch SUBCOMMAND ... ?OPTIONS? ** ** Run various subcommands to manage branches of the open repository or ** of the repository identified by the -R or --repository option. ** ** > fossil branch current ** ** Print the name of the branch for the current check-out ** ** > fossil branch info BRANCH-NAME ** ** Print information about a branch ** ** > fossil branch list|ls ?OPTIONS? ?GLOB? ** | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 | " WHERE tagid=%d" " AND tagtype=1" " AND ox.rid=ix.rid)", TAG_BRANCH, zBrName, TAG_CLOSED ); } /* ** Internal helper for branch_cmd_close() and friends. Adds a row to ** the to the brcmdtag TEMP table, initializing that table if needed, ** holding a pending tag for the given blob.rid (which is assumed to ** be valid). zTag must be a fully-formed tag name, including the ** (+,-,*) prefix character. ** */ static void branch_cmd_tag_add(int rid, const char *zTag){ static int once = 0; assert(zTag && ('+'==zTag[0] || '-'==zTag[0] || '*'==zTag[0])); if(0==once++){ db_multi_exec("CREATE TEMP TABLE brcmdtag(" "rid INTEGER UNIQUE ON CONFLICT IGNORE," "tag TEXT NOT NULL" ")"); } db_multi_exec("INSERT INTO brcmdtag(rid,tag) VALUES(%d,%Q)", rid, zTag); } /* ** Internal helper for branch_cmd_close() and friends. Creates and ** saves a control artifact of tag changes stored via ** branch_cmd_tag_add(). Fails fatally on error, returns 0 if it saves ** an artifact, and a negative value if it does not save anything ** because no tags were queued up. A positive return value is reserved ** for potential future semantics. ** ** This function asserts that a transaction is underway and it ends ** the transaction, committing or rolling back, as appropriate. */ static int branch_cmd_tag_finalize(int fDryRun /* roll back if true */, int fVerbose /* output extra info */, const char *zDateOvrd /* --date-override */, const char *zUserOvrd /* --user-override */){ int nTags = 0; Stmt q = empty_Stmt; Blob manifest = empty_blob; int doRollback = fDryRun!=0; assert(db_transaction_nesting_depth() > 0); if(!db_table_exists("temp","brcmdtag")){ fossil_warning("No tags added - nothing to do."); db_end_transaction(1); return -1; } db_prepare(&q, "SELECT b.uuid, t.tag " "FROM blob b, brcmdtag t " "WHERE b.rid=t.rid " "ORDER BY t.tag, b.uuid"); blob_appendf(&manifest, "D %z\n", date_in_standard_format( zDateOvrd ? zDateOvrd : "now")); while(SQLITE_ROW==db_step(&q)){ const char * zHash = db_column_text(&q, 0); const char * zTag = db_column_text(&q, 1); blob_appendf(&manifest, "T %s %s\n", zTag, zHash); ++nTags; } if(!nTags){ fossil_warning("No tags added - nothing to do."); db_end_transaction(1); blob_reset(&manifest); return -1; } user_select(); blob_appendf(&manifest, "U %F\n", zUserOvrd ? zUserOvrd : login_name()); { /* Z-card and save artifact */ int newRid; Blob cksum = empty_blob; md5sum_blob(&manifest, &cksum); blob_appendf(&manifest, "Z %b\n", &cksum); blob_reset(&cksum); if(fDryRun && fVerbose){ fossil_print("Dry-run mode: will roll back new artifact:\n%b", &manifest); /* Run through the saving steps, though, noting that doing so ** will clear out &manifest, which is why we output it here ** instead of after saving. */ } newRid = content_put(&manifest); if(0==newRid){ fossil_fatal("Problem saving new artifact: %s\n%b", g.zErrMsg, &manifest); }else if(manifest_crosslink(newRid, &manifest, 0)==0){ fossil_fatal("Crosslinking error: %s", g.zErrMsg); } fossil_print("Saved new control artifact %z (RID %d).\n", rid_to_uuid(newRid), newRid); db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", newRid); if(fDryRun){ fossil_print("Dry-run mode: rolling back new artifact.\n"); assert(0!=doRollback); } } db_multi_exec("DROP TABLE brcmdtag"); blob_reset(&manifest); db_end_transaction(doRollback); return 0; } /* ** Internal helper for branch_cmd_close() and friends. zName is a ** symbolic checkin name. Returns the blob.rid of the checkin or fails ** fatally if the name does not resolve unambiguously. If zUuid is ** not NULL, *zUuid is set to the resolved blob.uuid and must be freed ** by the caller via fossil_free(). */ static int branch_resolve_name(char const *zName, char **zUuid){ const int rid = name_to_uuid2(zName, "ci", zUuid); if(0==rid){ fossil_fatal("Cannot resolve name: %s", zName); }else if(rid<0){ fossil_fatal("Ambiguous name: %s", zName); } return rid; } /* ** Implementation of (branch hide/unhide) subcommands. nStartAtArg is ** the g.argv index to start reading branch/checkin names. fHide is ** true for hiding, false for unhiding. Fails fatally on error. */ static void branch_cmd_hide(int nStartAtArg, int fHide){ int argPos = nStartAtArg; /* g.argv pos with first branch/ci name */ char * zUuid = 0; /* Resolved branch UUID. */ const int fVerbose = find_option("verbose","v",0)!=0; const int fDryRun = find_option("dry-run","n",0)!=0; const char *zDateOvrd = find_option("date-override",0,1); const char *zUserOvrd = find_option("user-override",0,1); verify_all_options(); db_begin_transaction(); for( ; argPos < g.argc; fossil_free(zUuid), ++argPos ){ const char * zName = g.argv[argPos]; const int rid = branch_resolve_name(zName, &zUuid); const int isHidden = rid_has_tag(rid, TAG_HIDDEN); /* Potential TODO: check for existing 'hidden' flag and skip this ** entry if it already has (if fHide) or does not have (if !fHide) ** that tag. FWIW, /ci_edit does not do so. */ if(fHide && isHidden){ fossil_warning("Skipping hidden checkin %s: %s.", zName, zUuid); continue; }else if(!fHide && !isHidden){ fossil_warning("Skipping non-hidden checkin %s: %s.", zName, zUuid); continue; } branch_cmd_tag_add(rid, fHide ? "*hidden" : "-hidden"); if(fVerbose!=0){ fossil_print("%s checkin [%s] %s\n", fHide ? "Hiding" : "Unhiding", zName, zUuid); } } branch_cmd_tag_finalize(fDryRun, fVerbose, zDateOvrd, zUserOvrd); } /* ** Implementation of (branch close|reopen) subcommands. nStartAtArg is ** the g.argv index to start reading branch/checkin names. The given ** checkins are closed if fClose is true, else their "closed" tag (if ** any) is cancelled. Fails fatally on error. */ static void branch_cmd_close(int nStartAtArg, int fClose){ int argPos = nStartAtArg; /* g.argv pos with first branch name */ char * zUuid = 0; /* Resolved branch UUID. */ const int fVerbose = find_option("verbose","v",0)!=0; const int fDryRun = find_option("dry-run","n",0)!=0; const char *zDateOvrd = find_option("date-override",0,1); const char *zUserOvrd = find_option("user-override",0,1); verify_all_options(); db_begin_transaction(); for( ; argPos < g.argc; fossil_free(zUuid), ++argPos ){ const char * zName = g.argv[argPos]; const int rid = branch_resolve_name(zName, &zUuid); const int isClosed = leaf_is_closed(rid); if(!is_a_leaf(rid)){ /* This behaviour is different from /ci_edit closing, where ** is_a_leaf() adds a "+" tag and !is_a_leaf() adds a "*" ** tag. We might want to change this to match for consistency's ** sake, but it currently seems unnecessary to close/re-open a ** non-leaf. */ fossil_warning("Skipping non-leaf [%s] %s", zName, zUuid); continue; }else if(fClose && isClosed){ fossil_warning("Skipping closed leaf [%s] %s", zName, zUuid); continue; }else if(!fClose && !isClosed){ fossil_warning("Skipping non-closed leaf [%s] %s", zName, zUuid); continue; } branch_cmd_tag_add(rid, fClose ? "+closed" : "-closed"); if(fVerbose!=0){ fossil_print("%s branch [%s] %s\n", fClose ? "Closing" : "Re-opening", zName, zUuid); } } branch_cmd_tag_finalize(fDryRun, fVerbose, zDateOvrd, zUserOvrd); } /* ** COMMAND: branch ** ** Usage: %fossil branch SUBCOMMAND ... ?OPTIONS? ** ** Run various subcommands to manage branches of the open repository or ** of the repository identified by the -R or --repository option. ** ** > fossil branch close|reopen ?OPTIONS? BRANCH-NAME ?...BRANCH-NAMES? ** ** Adds or cancels the "closed" tag to one or more branches. ** It accepts arbitrary unambiguous symbolic names but ** will only resolve checkin names and skips any which resolve ** to non-leaf checkins. Options: ** -n|--dry-run do not commit changes and dump artifact ** to stdout ** -v|--verbose output more information ** --date-override DATE DATE to use instead of 'now' ** --user-override USER USER to use instead of the current default ** ** > fossil branch current ** ** Print the name of the branch for the current check-out ** ** > fossil branch hide|unhide ?OPTIONS? BRANCH-NAME ?...BRANCH-NAMES? ** ** Adds or cancels the "hidden" tag for the specified branches or ** or checkin IDs. Accepts the same options as the close ** subcommand. ** ** > fossil branch info BRANCH-NAME ** ** Print information about a branch ** ** > fossil branch list|ls ?OPTIONS? ?GLOB? ** |
︙ | ︙ | |||
370 371 372 373 374 375 376 | ** ** If GLOB is given, show only branches matching the pattern. ** ** > fossil branch new BRANCH-NAME BASIS ?OPTIONS? ** ** Create a new branch BRANCH-NAME off of check-in BASIS. ** Supported options for this subcommand include: | | | > > | | | | 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 | ** ** If GLOB is given, show only branches matching the pattern. ** ** > fossil branch new BRANCH-NAME BASIS ?OPTIONS? ** ** Create a new branch BRANCH-NAME off of check-in BASIS. ** Supported options for this subcommand include: ** --private branch is private (i.e., remains local) ** --bgcolor COLOR use COLOR instead of automatic background ** ("auto" lets Fossil choose it automatically, ** even for private branches) ** --nosign do not sign contents on this branch ** --date-override DATE DATE to use instead of 'now' ** --user-override USER USER to use instead of the current default ** ** DATE may be "now" or "YYYY-MM-DDTHH:MM:SS.SSS". If in ** year-month-day form, it may be truncated, the "T" may be ** replaced by a space, and it may also name a timezone offset ** from UTC as "-HH:MM" (westward) or "+HH:MM" (eastward). ** Either no timezone suffix or "Z" means UTC. ** |
︙ | ︙ | |||
443 444 445 446 447 448 449 450 451 | const char *zBr = db_column_text(&q, 0); int isCur = zCurrent!=0 && fossil_strcmp(zCurrent,zBr)==0; fossil_print("%s%s\n", (isCur ? "* " : " "), zBr); } db_finalize(&q); }else if( strncmp(zCmd,"new",n)==0 ){ branch_new(); }else{ fossil_fatal("branch subcommand should be one of: " | > > > > > > > > > > > > > > > > > > > > | | 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 | const char *zBr = db_column_text(&q, 0); int isCur = zCurrent!=0 && fossil_strcmp(zCurrent,zBr)==0; fossil_print("%s%s\n", (isCur ? "* " : " "), zBr); } db_finalize(&q); }else if( strncmp(zCmd,"new",n)==0 ){ branch_new(); }else if( strncmp(zCmd,"close",5)==0 ){ if(g.argc<4){ usage("branch close branch-name(s)..."); } branch_cmd_close(3, 1); }else if( strncmp(zCmd,"reopen",6)==0 ){ if(g.argc<4){ usage("branch reopen branch-name(s)..."); } branch_cmd_close(3, 0); }else if( strncmp(zCmd,"hide",4)==0 ){ if(g.argc<4){ usage("branch hide branch-name(s)..."); } branch_cmd_hide(3,1); }else if( strncmp(zCmd,"unhide",6)==0 ){ if(g.argc<4){ usage("branch unhide branch-name(s)..."); } branch_cmd_hide(3,0); }else{ fossil_fatal("branch subcommand should be one of: " "close current hide info list ls new reopen unhide"); } } /* ** This is the new-style branch-list page that shows the branch names ** together with their ages (time of last check-in) and whether or not ** they are closed or merged to another branch. |
︙ | ︙ |
Changes to src/cache.c.
︙ | ︙ | |||
195 196 197 198 199 200 201 202 203 204 205 206 207 208 | cache_write_end: sqlite3_finalize(pStmt); sqlite3_exec(db, rc ? "COMMIT" : "ROLLBACK", 0, 0, 0); sqlite3_close(db); } /* ** Attempt to read content out of the cache with the given zKey. Return ** non-zero on success and zero if unable to locate the content. ** ** Possible reasons for returning zero: ** (1) This server does not implement a cache ** (2) The requested element is not in the cache | > > > > > > > | 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 | cache_write_end: sqlite3_finalize(pStmt); sqlite3_exec(db, rc ? "COMMIT" : "ROLLBACK", 0, 0, 0); sqlite3_close(db); } /* ** SETTING: max-cache-entry width=10 default=10 ** ** This is the maximum number of entries to allow in the web-cache ** for tarballs, ZIP-archives, and SQL-archives. */ /* ** Attempt to read content out of the cache with the given zKey. Return ** non-zero on success and zero if unable to locate the content. ** ** Possible reasons for returning zero: ** (1) This server does not implement a cache ** (2) The requested element is not in the cache |
︙ | ︙ | |||
260 261 262 263 264 265 266 267 268 269 270 271 272 273 | ** clear Remove all entries from the cache. ** ** init Create the cache file if it does not already exist. ** ** list|ls List the keys and content sizes and other stats for ** all entries currently in the cache. ** ** status Show a summary of the cache status. ** ** The cache is stored in a file that is distinct from the repository ** but that is held in the same directory as the repository. The cache ** file can be deleted in order to completely disable the cache. */ void cache_cmd(void){ | > > | 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 | ** clear Remove all entries from the cache. ** ** init Create the cache file if it does not already exist. ** ** list|ls List the keys and content sizes and other stats for ** all entries currently in the cache. ** ** size ?N? Query or set the maximum number of entries in the cache. ** ** status Show a summary of the cache status. ** ** The cache is stored in a file that is distinct from the repository ** but that is held in the same directory as the repository. The cache ** file can be deleted in order to completely disable the cache. */ void cache_cmd(void){ |
︙ | ︙ | |||
301 302 303 304 305 306 307 | if( db ){ sqlite3_exec(db, "DELETE FROM cache; DELETE FROM blob; VACUUM;",0,0,0); sqlite3_close(db); fossil_print("cache cleared\n"); }else{ fossil_print("nothing to clear; cache does not exist\n"); } | | | > > > | | | | | > | > > > > > > > | > | > > > > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > | 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 | if( db ){ sqlite3_exec(db, "DELETE FROM cache; DELETE FROM blob; VACUUM;",0,0,0); sqlite3_close(db); fossil_print("cache cleared\n"); }else{ fossil_print("nothing to clear; cache does not exist\n"); } }else if( strncmp(zCmd, "list", nCmd)==0 || strncmp(zCmd, "ls", nCmd)==0 || strncmp(zCmd, "status", nCmd)==0 ){ db = cacheOpen(0); if( db==0 ){ fossil_print("cache does not exist\n"); }else{ int nEntry = 0; char *zDbName = cacheName(); cache_register_sizename(db); pStmt = cacheStmt(db, "SELECT key, sizename(sz), nRef, datetime(tm,'unixepoch')" " FROM cache" " ORDER BY tm DESC" ); if( pStmt ){ while( sqlite3_step(pStmt)==SQLITE_ROW ){ if( zCmd[0]=='l' ){ fossil_print("%s %4d %8s %s\n", sqlite3_column_text(pStmt, 3), sqlite3_column_int(pStmt, 2), sqlite3_column_text(pStmt, 1), sqlite3_column_text(pStmt, 0)); } nEntry++; } sqlite3_finalize(pStmt); } sqlite3_close(db); fossil_print( "Filename: %s\n" "Entries: %d\n" "max-cache-entry: %d\n" "Cache-file Size: %,lld\n", zDbName, nEntry, db_get_int("max-cache-entry",10), file_size(zDbName, ExtFILE) ); fossil_free(zDbName); } }else if( strncmp(zCmd, "size", nCmd)==0 ){ if( g.argc>=4 ){ int n = atoi(g.argv[3]); if( n>=5 ) db_set_int("max-cache-entry",n,0); } fossil_print("max-cache-entry: %d\n", db_get_int("max-cache-entry",10)); }else{ fossil_fatal("Unknown subcommand \"%s\"." " Should be one of: clear init list size status", zCmd); } } /* ** Given a cache key, find the check-in hash and return it as a separate ** string. The returned string is obtained from fossil_malloc() and must ** be freed by the caller. ** ** Return NULL if not found. ** ** The key is usually in a format like these: ** ** /tarball/HASH/NAME ** /zip/HASH/NAME ** /sqlar/HASH/NAME */ static char *cache_hash_of_key(const char *zKey){ int i; if( zKey==0 ) return 0; if( zKey[0]!='/' ) return 0; zKey++; while( zKey[0] && zKey[0]!='/' ) zKey++; if( zKey[0]==0 ) return 0; zKey++; for(i=0; zKey[i] && zKey[i]!='/'; i++){} if( !validate16(zKey, i) ) return 0; return fossil_strndup(zKey, i); } /* ** WEBPAGE: cachestat ** ** Show information about the webpage cache. Requires Setup privilege. */ void cache_page(void){ |
︙ | ︙ | |||
360 361 362 363 364 365 366 | db = cacheOpen(0); if( db==0 ){ @ The web-page cache is disabled for this repository }else{ char *zDbName = cacheName(); cache_register_sizename(db); pStmt = cacheStmt(db, | | > | | > > > > > > > | | > > > > > > | 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 | db = cacheOpen(0); if( db==0 ){ @ The web-page cache is disabled for this repository }else{ char *zDbName = cacheName(); cache_register_sizename(db); pStmt = cacheStmt(db, "SELECT key, sz, nRef, datetime(tm,'unixepoch')" " FROM cache" " ORDER BY (tm + 3600*min(nRef,48)) DESC" ); if( pStmt ){ @ <ol> while( sqlite3_step(pStmt)==SQLITE_ROW ){ const unsigned char *zName = sqlite3_column_text(pStmt,0); char *zHash = cache_hash_of_key((const char*)zName); @ <li><p>%z(href("%R/cacheget?key=%T",zName))%h(zName)</a><br /> @ size: %,lld(sqlite3_column_int64(pStmt,1)) @ hit-count: %d(sqlite3_column_int(pStmt,2)) @ last-access: %s(sqlite3_column_text(pStmt,3)) \ if( zHash ){ @ %z(href("%R/timeline?c=%S",zHash))check-in</a>\ fossil_free(zHash); } @ </p></li> } sqlite3_finalize(pStmt); @ </ol> } zDbName = cacheName(); bigSizeName(sizeof(zBuf), zBuf, file_size(zDbName, ExtFILE)); @ <p> @ cache-file name: %h(zDbName)<br> @ cache-file size: %s(zBuf)<br> @ max-cache-entry: %d(db_get_int("max-cache-entry",10)) @ </p> @ <p> @ Use the "<a href="%R/help?cmd=cache">fossil cache</a>" command @ on the command-line to create and configure the web-cache. @ </p> fossil_free(zDbName); sqlite3_close(db); } style_finish_page(); } /* |
︙ | ︙ |
Changes to src/cgi.c.
︙ | ︙ | |||
311 312 313 314 315 316 317 | if( etag_mtime()>0 ){ fprintf(g.httpOut, "Last-Modified: %s\r\n", cgi_rfc822_datestamp(etag_mtime())); } }else if( g.isConst ){ /* isConst means that the reply is guaranteed to be invariant, even ** after configuration changes and/or Fossil binary recompiles. */ | | | 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 | if( etag_mtime()>0 ){ fprintf(g.httpOut, "Last-Modified: %s\r\n", cgi_rfc822_datestamp(etag_mtime())); } }else if( g.isConst ){ /* isConst means that the reply is guaranteed to be invariant, even ** after configuration changes and/or Fossil binary recompiles. */ fprintf(g.httpOut, "Cache-Control: max-age=315360000, immutable\r\n"); }else{ fprintf(g.httpOut, "Cache-control: no-cache\r\n"); } if( blob_size(&extraHeader)>0 ){ fprintf(g.httpOut, "%s", blob_buffer(&extraHeader)); } |
︙ | ︙ | |||
1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 | CGIDEBUG(("env-match [%s] = [%s]\n", zName, zValue)); return zValue; } } CGIDEBUG(("no-match [%s]\n", zName)); return zDefault; } /* ** Return the value of a CGI parameter with leading and trailing ** spaces removed and with internal \r\n changed to just \n */ char *cgi_parameter_trimmed(const char *zName, const char *zDefault){ const char *zIn; | > > > > > > > > > > > > > > > > > > > | 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 | CGIDEBUG(("env-match [%s] = [%s]\n", zName, zValue)); return zValue; } } CGIDEBUG(("no-match [%s]\n", zName)); return zDefault; } /* ** Return the value of the first defined query parameter or cookie whose ** name appears in the list of arguments. Or if no parameter is found, ** return NULL. */ const char *cgi_coalesce(const char *zName, ...){ va_list ap; const char *z; const char *zX; if( zName==0 ) return 0; z = cgi_parameter(zName, 0); va_start(ap, zName); while( z==0 && (zX = va_arg(ap,const char*))!=0 ){ z = cgi_parameter(zX, 0); } va_end(ap); return z; } /* ** Return the value of a CGI parameter with leading and trailing ** spaces removed and with internal \r\n changed to just \n */ char *cgi_parameter_trimmed(const char *zName, const char *zDefault){ const char *zIn; |
︙ | ︙ |
Changes to src/checkin.c.
︙ | ︙ | |||
2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 | ** --allow-empty allow a commit with no changes ** --allow-fork allow the commit to fork ** --allow-older allow a commit older than its ancestor ** --baseline use a baseline manifest in the commit process ** --bgcolor COLOR apply COLOR to this one check-in only ** --branch NEW-BRANCH-NAME check in to this new branch ** --branchcolor COLOR apply given COLOR to the branch ** --close close the branch being committed ** --date-override DATETIME DATE to use instead of 'now' ** --delta use a delta manifest in the commit process ** --hash verify file status using hashing rather ** than relying on file mtimes ** --integrate close all merged-in branches ** -m|--comment COMMENT-TEXT use COMMENT-TEXT as commit comment | > > | 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 | ** --allow-empty allow a commit with no changes ** --allow-fork allow the commit to fork ** --allow-older allow a commit older than its ancestor ** --baseline use a baseline manifest in the commit process ** --bgcolor COLOR apply COLOR to this one check-in only ** --branch NEW-BRANCH-NAME check in to this new branch ** --branchcolor COLOR apply given COLOR to the branch ** ("auto" lets Fossil choose it automatically, ** even for private branches) ** --close close the branch being committed ** --date-override DATETIME DATE to use instead of 'now' ** --delta use a delta manifest in the commit process ** --hash verify file status using hashing rather ** than relying on file mtimes ** --integrate close all merged-in branches ** -m|--comment COMMENT-TEXT use COMMENT-TEXT as commit comment |
︙ | ︙ | |||
2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 | int szD; /* Size of the delta manifest */ int szB; /* Size of the baseline manifest */ int nConflict = 0; /* Number of unresolved merge conflicts */ int abortCommit = 0; /* Abort the commit due to text format conversions */ Blob ans; /* Answer to continuation prompts */ char cReply; /* First character of ans */ int bRecheck = 0; /* Repeat fork and closed-branch checks*/ memset(&sCiInfo, 0, sizeof(sCiInfo)); url_proxy_options(); /* --sha1sum is an undocumented alias for --hash for backwards compatiblity */ useHash = find_option("hash",0,0)!=0 || find_option("sha1sum",0,0)!=0; noSign = find_option("nosign",0,0)!=0; privateFlag = find_option("private",0,0)!=0; | > | 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 | int szD; /* Size of the delta manifest */ int szB; /* Size of the baseline manifest */ int nConflict = 0; /* Number of unresolved merge conflicts */ int abortCommit = 0; /* Abort the commit due to text format conversions */ Blob ans; /* Answer to continuation prompts */ char cReply; /* First character of ans */ int bRecheck = 0; /* Repeat fork and closed-branch checks*/ int bAutoBrClr = 0; /* Value of "--branchcolor" is "auto" */ memset(&sCiInfo, 0, sizeof(sCiInfo)); url_proxy_options(); /* --sha1sum is an undocumented alias for --hash for backwards compatiblity */ useHash = find_option("hash",0,0)!=0 || find_option("sha1sum",0,0)!=0; noSign = find_option("nosign",0,0)!=0; privateFlag = find_option("private",0,0)!=0; |
︙ | ︙ | |||
2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 | noPrompt = find_option("no-prompt", 0, 0)!=0; noWarningFlag = find_option("no-warnings", 0, 0)!=0; noVerify = find_option("no-verify",0,0)!=0; bTrace = find_option("trace",0,0)!=0; sCiInfo.zBranch = find_option("branch","b",1); sCiInfo.zColor = find_option("bgcolor",0,1); sCiInfo.zBrClr = find_option("branchcolor",0,1); sCiInfo.closeFlag = find_option("close",0,0)!=0; sCiInfo.integrateFlag = find_option("integrate",0,0)!=0; sCiInfo.zMimetype = find_option("mimetype",0,1); sCiInfo.verboseFlag = find_option("verbose", "v", 0)!=0; while( (zTag = find_option("tag",0,1))!=0 ){ if( zTag[0]==0 ) continue; sCiInfo.azTag = fossil_realloc((void*)sCiInfo.azTag, | > > > > | 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 | noPrompt = find_option("no-prompt", 0, 0)!=0; noWarningFlag = find_option("no-warnings", 0, 0)!=0; noVerify = find_option("no-verify",0,0)!=0; bTrace = find_option("trace",0,0)!=0; sCiInfo.zBranch = find_option("branch","b",1); sCiInfo.zColor = find_option("bgcolor",0,1); sCiInfo.zBrClr = find_option("branchcolor",0,1); if ( fossil_strncmp(sCiInfo.zBrClr, "auto", 4)==0 ) { bAutoBrClr = 1; sCiInfo.zBrClr = 0; } sCiInfo.closeFlag = find_option("close",0,0)!=0; sCiInfo.integrateFlag = find_option("integrate",0,0)!=0; sCiInfo.zMimetype = find_option("mimetype",0,1); sCiInfo.verboseFlag = find_option("verbose", "v", 0)!=0; while( (zTag = find_option("tag",0,1))!=0 ){ if( zTag[0]==0 ) continue; sCiInfo.azTag = fossil_realloc((void*)sCiInfo.azTag, |
︙ | ︙ | |||
2276 2277 2278 2279 2280 2281 2282 | /* Track the "private" status */ g.markPrivate = privateFlag || privateParent; if( privateFlag && !privateParent ){ /* Apply default branch name ("private") and color ("orange") if not ** specified otherwise on the command-line, and if the parent is not ** already private. */ if( sCiInfo.zBranch==0 ) sCiInfo.zBranch = "private"; | | > > | 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 | /* Track the "private" status */ g.markPrivate = privateFlag || privateParent; if( privateFlag && !privateParent ){ /* Apply default branch name ("private") and color ("orange") if not ** specified otherwise on the command-line, and if the parent is not ** already private. */ if( sCiInfo.zBranch==0 ) sCiInfo.zBranch = "private"; if( sCiInfo.zBrClr==0 && sCiInfo.zColor==0 && !bAutoBrClr) { sCiInfo.zBrClr = "#fec084"; } } /* Do not allow the creation of a new branch using an existing open ** branch name unless the --force flag is used */ if( sCiInfo.zBranch!=0 && !forceFlag && fossil_strcmp(sCiInfo.zBranch,"private")!=0 |
︙ | ︙ |
Changes to src/checkout.c.
︙ | ︙ | |||
416 417 418 419 420 421 422 | if( !forceFlag && db_table_exists("localdb","stash") && db_exists("SELECT 1 FROM localdb.stash") ){ fossil_fatal("closing the checkout will delete your stash"); } if( db_is_writeable("repository") ){ | | < < | 416 417 418 419 420 421 422 423 424 425 426 427 428 | if( !forceFlag && db_table_exists("localdb","stash") && db_exists("SELECT 1 FROM localdb.stash") ){ fossil_fatal("closing the checkout will delete your stash"); } if( db_is_writeable("repository") ){ db_unset_mprintf(1, "ckout:%q", g.zLocalRoot); } unlink_local_database(1); db_close(1); unlink_local_database(0); } |
Changes to src/clone.c.
︙ | ︙ | |||
288 289 290 291 292 293 294 | zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin); fossil_print("admin-user: %s (password is \"%s\")\n", g.zLogin, zPassword); if( zWorkDir!=0 && zWorkDir[0]!=0 && !noOpen ){ Blob cmd; fossil_print("opening the new %s repository in directory %s...\n", zRepo, zWorkDir); blob_init(&cmd, 0, 0); | | | | < | < | < < | 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 | zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin); fossil_print("admin-user: %s (password is \"%s\")\n", g.zLogin, zPassword); if( zWorkDir!=0 && zWorkDir[0]!=0 && !noOpen ){ Blob cmd; fossil_print("opening the new %s repository in directory %s...\n", zRepo, zWorkDir); blob_init(&cmd, 0, 0); blob_append_escaped_arg(&cmd, g.nameOfExe, 1); blob_append(&cmd, " open ", -1); blob_append_escaped_arg(&cmd, zRepo, 1); blob_append(&cmd, " --workdir ", -1); blob_append_escaped_arg(&cmd, zWorkDir, 1); if( allowNested ){ blob_append(&cmd, " --nested", -1); } fossil_system(blob_str(&cmd)); blob_reset(&cmd); } } /* ** If user chooses to use HTTP Authentication over unencrypted HTTP, ** remember decision. Otherwise, if the URL is being changed and no ** preference has been indicated, err on the safe side and revert the ** decision. Set the global preference if the URL is not being changed. */ void remember_or_get_http_auth( const char *zHttpAuth, /* Credentials in the form "user:password" */ int fRemember, /* True to remember credentials for later reuse */ const char *zUrl /* URL for which these credentials apply */ ){ if( zHttpAuth && zHttpAuth[0] ){ g.zHttpAuth = mprintf("%s", zHttpAuth); } if( fRemember ){ if( g.zHttpAuth && g.zHttpAuth[0] ){ set_httpauth(g.zHttpAuth); }else if( zUrl && zUrl[0] ){ db_unset_mprintf(0, "http-auth:%s", g.url.canonical); }else{ g.zHttpAuth = get_httpauth(); } }else if( g.zHttpAuth==0 && zUrl==0 ){ g.zHttpAuth = get_httpauth(); } } /* ** Get the HTTP Authorization preference from db. */ char *get_httpauth(void){ char *zKey = mprintf("http-auth:%s", g.url.canonical); char * rc = unobscure(db_get(zKey, 0)); free(zKey); return rc; } /* ** Set the HTTP Authorization preference in db. */ void set_httpauth(const char *zHttpAuth){ db_set_mprintf(obscure(zHttpAuth), 0, "http-auth:%s", g.url.canonical); } /* ** Look for SSH clone command line options and setup in globals. */ void clone_ssh_find_options(void){ const char *zSshCmd; /* SSH command string */ |
︙ | ︙ |
Changes to src/codecheck1.c.
︙ | ︙ | |||
345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 | /* ** Processing flags */ #define FMT_SQL 0x00001 /* Generator for SQL text */ #define FMT_HTML 0x00002 /* Generator for HTML text */ #define FMT_URL 0x00004 /* Generator for URLs */ #define FMT_SAFE 0x00008 /* Generator for human-readable text */ /* ** A list of internal Fossil interfaces that take a printf-style format ** string. */ struct FmtFunc { const char *zFName; /* Name of the function */ int iFmtArg; /* Index of format argument. Leftmost is 1. */ unsigned fmtFlags; /* Processing flags */ } aFmtFunc[] = { | > > | | | | | | | | | | | | | | | | | | | | > > | | | | > > | | | > | | > | | | | | | | | | | | | | | | > > | | | | | | | | | > > | > | | 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 | /* ** Processing flags */ #define FMT_SQL 0x00001 /* Generator for SQL text */ #define FMT_HTML 0x00002 /* Generator for HTML text */ #define FMT_URL 0x00004 /* Generator for URLs */ #define FMT_SAFE 0x00008 /* Generator for human-readable text */ #define FMT_LIT 0x00010 /* Just verify that a string literal */ #define FMT_PX 0x00020 /* Must have a literal prefix in format string */ /* ** A list of internal Fossil interfaces that take a printf-style format ** string. */ struct FmtFunc { const char *zFName; /* Name of the function */ int iFmtArg; /* Index of format argument. Leftmost is 1. */ unsigned fmtFlags; /* Processing flags */ } aFmtFunc[] = { { "admin_log", 1, FMT_SAFE }, { "audit_append", 3, FMT_SAFE }, { "backofficeTrace", 1, FMT_SAFE }, { "blob_append_sql", 2, FMT_SQL }, { "blob_appendf", 2, FMT_SAFE }, { "cgi_debug", 1, FMT_SAFE }, { "cgi_panic", 1, FMT_SAFE }, { "cgi_printf", 1, FMT_HTML }, { "cgi_printf_header", 1, FMT_HTML }, { "cgi_redirectf", 1, FMT_URL }, { "chref", 2, FMT_URL }, { "CX", 1, FMT_HTML }, { "db_blob", 2, FMT_SQL }, { "db_debug", 1, FMT_SQL }, { "db_double", 2, FMT_SQL }, { "db_err", 1, FMT_SAFE }, { "db_exists", 1, FMT_SQL }, { "db_get_mprintf", 2, FMT_SAFE }, { "db_int", 2, FMT_SQL }, { "db_int64", 2, FMT_SQL }, { "db_lset", 1, FMT_LIT }, { "db_lset_int", 1, FMT_LIT }, { "db_multi_exec", 1, FMT_SQL }, { "db_optional_sql", 2, FMT_SQL }, { "db_prepare", 2, FMT_SQL }, { "db_prepare_ignore_error", 2, FMT_SQL }, { "db_set", 1, FMT_LIT }, { "db_set_int", 1, FMT_LIT }, { "db_set_mprintf", 3, FMT_PX }, { "db_static_prepare", 2, FMT_SQL }, { "db_text", 2, FMT_SQL }, { "db_unset", 1, FMT_LIT }, { "db_unset_mprintf", 2, FMT_PX }, { "emailerError", 2, FMT_SAFE }, { "entry_attribute", 4, FMT_LIT }, { "fileedit_ajax_error", 2, FMT_SAFE }, { "form_begin", 2, FMT_URL }, { "fossil_error", 2, FMT_SAFE }, { "fossil_errorlog", 1, FMT_SAFE }, { "fossil_fatal", 1, FMT_SAFE }, { "fossil_fatal_recursive", 1, FMT_SAFE }, { "fossil_panic", 1, FMT_SAFE }, { "fossil_print", 1, FMT_SAFE }, { "fossil_trace", 1, FMT_SAFE }, { "fossil_warning", 1, FMT_SAFE }, { "href", 1, FMT_URL }, { "json_new_string_f", 1, FMT_SAFE }, { "json_set_err", 2, FMT_SAFE }, { "json_warn", 2, FMT_SAFE }, { "mprintf", 1, FMT_SAFE }, { "multiple_choice_attribute", 3, FMT_LIT }, { "onoff_attribute", 3, FMT_LIT }, { "pop3_print", 2, FMT_SAFE }, { "smtp_send_line", 2, FMT_SAFE }, { "smtp_server_send", 2, FMT_SAFE }, { "socket_set_errmsg", 1, FMT_SAFE }, { "ssl_set_errmsg", 1, FMT_SAFE }, { "style_header", 1, FMT_HTML }, { "style_set_current_page", 1, FMT_URL }, { "style_submenu_element", 2, FMT_URL }, { "style_submenu_sql", 3, FMT_SQL }, { "textarea_attribute", 5, FMT_LIT }, { "tktsetup_generic", 1, FMT_LIT }, { "webpage_error", 1, FMT_SAFE }, { "xfersetup_generic", 1, FMT_LIT }, { "xhref", 2, FMT_URL }, }; /* ** Comparison function for two FmtFunc entries */ static int fmtfunc_cmp(const void *pAA, const void *pBB){ const struct FmtFunc *pA = (const struct FmtFunc*)pAA; |
︙ | ︙ | |||
457 458 459 460 461 462 463 464 | /* ** Return the expected number of arguments for the format string. ** Return -1 if the value cannot be computed. ** ** For each argument less than nType, store the conversion character ** for that argument in cType[i]. */ | > > > | > > > | 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 | /* ** Return the expected number of arguments for the format string. ** Return -1 if the value cannot be computed. ** ** For each argument less than nType, store the conversion character ** for that argument in cType[i]. ** ** Store the number of initial literal characters of the format string ** in *pInit. */ static int formatArgCount(const char *z, int nType, char *cType, int *pInit){ int nArg = 0; int i, k; int len; int eType; int ln = 0; *pInit = 0; while( z[0] ){ len = token_length(z, &eType, &ln); if( eType==TK_STR ){ for(i=1; i<len-1 && isalpha(z[i]); i++){} *pInit = i-1; for(i=1; i<len-1; i++){ if( z[i]!='%' ) continue; if( z[i+1]=='%' ){ i++; continue; } for(k=i+1; k<len && !isalpha(z[k]); k++){ if( z[k]=='*' || z[k]=='#' ){ if( nArg<nType ) cType[nArg] = z[k]; nArg++; |
︙ | ︙ | |||
513 514 515 516 517 518 519 520 521 522 523 524 525 526 | char *z; char *zCopy; int nArg = 0; const char **azArg = 0; int i, k; int nErr = 0; char *acType; szFName = token_length(zFCall, &eToken, &ln); zStart = next_non_whitespace(zFCall+szFName, &len, &eToken); assert( zStart[0]=='(' && len==1 ); len = distance_to(zStart+1, ')'); zCopy = safe_malloc( len + 1 ); memcpy(zCopy, zStart+1, len); | > | 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 | char *z; char *zCopy; int nArg = 0; const char **azArg = 0; int i, k; int nErr = 0; char *acType; int nInit = 0; szFName = token_length(zFCall, &eToken, &ln); zStart = next_non_whitespace(zFCall+szFName, &len, &eToken); assert( zStart[0]=='(' && len==1 ); len = distance_to(zStart+1, ')'); zCopy = safe_malloc( len + 1 ); memcpy(zCopy, zStart+1, len); |
︙ | ︙ | |||
543 544 545 546 547 548 549 | printf("%s:%d: too few arguments to %.*s()\n", zFilename, lnFCall, szFName, zFCall); nErr++; }else{ const char *zFmt = azArg[fmtArg-1]; const char *zOverride = strstr(zFmt, "/*works-like:"); if( zOverride ) zFmt = zOverride + sizeof("/*works-like:")-1; | > | > > > > > | > > > > > > > | 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 | printf("%s:%d: too few arguments to %.*s()\n", zFilename, lnFCall, szFName, zFCall); nErr++; }else{ const char *zFmt = azArg[fmtArg-1]; const char *zOverride = strstr(zFmt, "/*works-like:"); if( zOverride ) zFmt = zOverride + sizeof("/*works-like:")-1; if( fmtFlags & FMT_LIT ){ if( !is_string_lit(zFmt) ){ printf("%s:%d: argument %d to %.*s() should be a string literal\n", zFilename, lnFCall, fmtArg, szFName, zFCall); nErr++; } }else if( !is_string_lit(zFmt) ){ printf("%s:%d: %.*s() has non-constant format on arg[%d]\n", zFilename, lnFCall, szFName, zFCall, fmtArg-1); nErr++; }else if( (k = formatArgCount(zFmt, nArg, acType, &nInit))>=0 && nArg!=fmtArg+k ){ printf("%s:%d: too %s arguments to %.*s() " "- got %d and expected %d\n", zFilename, lnFCall, (nArg<fmtArg+k ? "few" : "many"), szFName, zFCall, nArg, fmtArg+k); nErr++; }else if( (fmtFlags & FMT_PX)!=0 ){ if( nInit==0 ){ printf("%s:%d: format string on %.*s() should have" " an ASCII character prefix\n", zFilename, lnFCall, szFName, zFCall); nErr++; } }else if( (fmtFlags & FMT_SAFE)==0 ){ for(i=0; i<nArg && i<k; i++){ if( (acType[i]=='s' || acType[i]=='z' || acType[i]=='b') ){ const char *zExpr = azArg[fmtArg+i]; if( never_safe(zExpr) ){ printf("%s:%d: Argument %d to %.*s() is not safe for" " a query parameter\n", |
︙ | ︙ |
Changes to src/config.h.
︙ | ︙ | |||
64 65 66 67 68 69 70 71 72 73 74 75 76 77 | #if defined( __MINGW32__) || defined(__DMC__) || defined(_MSC_VER) || defined(__POCC__) # if defined(__DMC__) || defined(_MSC_VER) || defined(__POCC__) typedef int socklen_t; # endif # ifndef _WIN32 # define _WIN32 # endif #else # include <sys/types.h> # include <signal.h> # include <pwd.h> #endif /* | > > > > > > | 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | #if defined( __MINGW32__) || defined(__DMC__) || defined(_MSC_VER) || defined(__POCC__) # if defined(__DMC__) || defined(_MSC_VER) || defined(__POCC__) typedef int socklen_t; # endif # ifndef _WIN32 # define _WIN32 # endif # include <io.h> # include <fcntl.h> # undef popen # define popen _popen # undef pclose # define pclose _pclose #else # include <sys/types.h> # include <signal.h> # include <pwd.h> #endif /* |
︙ | ︙ |
Changes to src/db.c.
︙ | ︙ | |||
3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 | return db_int(dflt, "SELECT value FROM vvar WHERE name=%Q", zName); } void db_lset_int(const char *zName, int value){ db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%d)", zName, value); } /* Va-args versions of db_get(), db_set(), and db_unset() */ char *db_get_mprintf(const char *zDefault, const char *zFormat, ...){ va_list ap; char *zName; char *zResult; va_start(ap, zFormat); zName = vmprintf(zFormat, ap); va_end(ap); zResult = db_get(zName, zDefault); fossil_free(zName); return zResult; } void db_set_mprintf(const char *zNew, int iGlobal, const char *zFormat, ...){ va_list ap; char *zName; va_start(ap, zFormat); zName = vmprintf(zFormat, ap); va_end(ap); | > > > > > | | | 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 | return db_int(dflt, "SELECT value FROM vvar WHERE name=%Q", zName); } void db_lset_int(const char *zName, int value){ db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%d)", zName, value); } /* Va-args versions of db_get(), db_set(), and db_unset() ** ** codecheck1.c verifies that the format string for db_set_mprintf() ** and db_unset_mprintf() begins with an ASCII character prefix. We ** don't want that format string to begin with %s or %d as that might ** allow an injection attack to set or overwrite arbitrary settings. */ char *db_get_mprintf(const char *zDefault, const char *zFormat, ...){ va_list ap; char *zName; char *zResult; va_start(ap, zFormat); zName = vmprintf(zFormat, ap); va_end(ap); zResult = db_get(zName, zDefault); fossil_free(zName); return zResult; } void db_set_mprintf(const char *zNew, int iGlobal, const char *zFormat, ...){ va_list ap; char *zName; va_start(ap, zFormat); zName = vmprintf(zFormat, ap); va_end(ap); db_set(zName/*works-like:"x"*/, zNew, iGlobal); fossil_free(zName); } void db_unset_mprintf(int iGlobal, const char *zFormat, ...){ va_list ap; char *zName; va_start(ap, zFormat); zName = vmprintf(zFormat, ap); va_end(ap); db_unset(zName/*works-like:"x"*/, iGlobal); fossil_free(zName); } #if INTERFACE /* Manifest generation flags */ |
︙ | ︙ | |||
3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 | ** with the local repository. If you commit this checkout, ** it will become a new "initial" commit in the repository. ** -f|--force Continue with the open even if the working directory is ** not empty. ** --force-missing Force opening a repository with missing content ** --keep Only modify the manifest and manifest.uuid files ** --nested Allow opening a repository inside an opened checkout ** --repodir DIR If REPOSITORY is a URI that will be cloned, store ** the clone in DIR rather than in "." ** --setmtime Set timestamps of all files to match their SCM-side ** times (the timestamp of the last checkin which modified ** them). ** --workdir DIR Use DIR as the working directory instead of ".". The DIR ** directory is created if it does not exist. | > | 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 | ** with the local repository. If you commit this checkout, ** it will become a new "initial" commit in the repository. ** -f|--force Continue with the open even if the working directory is ** not empty. ** --force-missing Force opening a repository with missing content ** --keep Only modify the manifest and manifest.uuid files ** --nested Allow opening a repository inside an opened checkout ** --nosync Do not auto-sync the repository prior to opening ** --repodir DIR If REPOSITORY is a URI that will be cloned, store ** the clone in DIR rather than in "." ** --setmtime Set timestamps of all files to match their SCM-side ** times (the timestamp of the last checkin which modified ** them). ** --workdir DIR Use DIR as the working directory instead of ".". The DIR ** directory is created if it does not exist. |
︙ | ︙ | |||
3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 | static char *azNewArgv[] = { 0, "checkout", "--prompt", 0, 0, 0, 0 }; const char *zWorkDir; /* --workdir value */ const char *zRepo = 0; /* Name of the repository file */ const char *zRepoDir = 0; /* --repodir value */ char *zPwd; /* Initial working directory */ int isUri = 0; /* True if REPOSITORY is a URI */ int nLocal; /* Number of preexisting files in cwd */ url_proxy_options(); emptyFlag = find_option("empty",0,0)!=0; keepFlag = find_option("keep",0,0)!=0; forceMissingFlag = find_option("force-missing",0,0)!=0; allowNested = find_option("nested",0,0)!=0; setmtimeFlag = find_option("setmtime",0,0)!=0; zWorkDir = find_option("workdir",0,1); zRepoDir = find_option("repodir",0,1); bForce = find_option("force","f",0)!=0; zPwd = file_getcwd(0,0); /* We should be done with options.. */ verify_all_options(); if( g.argc!=3 && g.argc!=4 ){ | > > | 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 | static char *azNewArgv[] = { 0, "checkout", "--prompt", 0, 0, 0, 0 }; const char *zWorkDir; /* --workdir value */ const char *zRepo = 0; /* Name of the repository file */ const char *zRepoDir = 0; /* --repodir value */ char *zPwd; /* Initial working directory */ int isUri = 0; /* True if REPOSITORY is a URI */ int nLocal; /* Number of preexisting files in cwd */ int bNosync = 0; /* --nosync. Omit auto-sync */ url_proxy_options(); emptyFlag = find_option("empty",0,0)!=0; keepFlag = find_option("keep",0,0)!=0; forceMissingFlag = find_option("force-missing",0,0)!=0; allowNested = find_option("nested",0,0)!=0; setmtimeFlag = find_option("setmtime",0,0)!=0; zWorkDir = find_option("workdir",0,1); zRepoDir = find_option("repodir",0,1); bForce = find_option("force","f",0)!=0; bNosync = find_option("nosync",0,0)!=0; zPwd = file_getcwd(0,0); /* We should be done with options.. */ verify_all_options(); if( g.argc!=3 && g.argc!=4 ){ |
︙ | ︙ | |||
3597 3598 3599 3600 3601 3602 3603 | fossil_fatal("unable to deduce a repository name from the url \"%s\"", zUri); } if( zRepoDir==0 ) zRepoDir = zPwd; zRepo = mprintf("%s/%s.fossil", zRepoDir, zNewBase); fossil_free(zNewBase); blob_init(&cmd, 0, 0); | | | | | 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 | fossil_fatal("unable to deduce a repository name from the url \"%s\"", zUri); } if( zRepoDir==0 ) zRepoDir = zPwd; zRepo = mprintf("%s/%s.fossil", zRepoDir, zNewBase); fossil_free(zNewBase); blob_init(&cmd, 0, 0); blob_append_escaped_arg(&cmd, g.nameOfExe, 1); blob_append(&cmd, " clone", -1); blob_append_escaped_arg(&cmd, zUri, 1); blob_append_escaped_arg(&cmd, zRepo, 1); zCmd = blob_str(&cmd); fossil_print("%s\n", zCmd); if( zWorkDir ) file_chdir(zPwd, 0); rc = fossil_system(zCmd); if( rc ){ fossil_fatal("clone of %s failed", zUri); } |
︙ | ︙ | |||
3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 | /* Figure out which revision to open. */ if( !emptyFlag ){ if( g.argc==4 ){ g.zOpenRevision = g.argv[3]; }else if( db_exists("SELECT 1 FROM event WHERE type='ci'") ){ g.zOpenRevision = db_get("main-branch", 0); } } #if defined(_WIN32) || defined(__CYGWIN__) # define LOCALDB_NAME "./_FOSSIL_" #else # define LOCALDB_NAME "./.fslckout" | > > > > > > | 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 | /* Figure out which revision to open. */ if( !emptyFlag ){ if( g.argc==4 ){ g.zOpenRevision = g.argv[3]; }else if( db_exists("SELECT 1 FROM event WHERE type='ci'") ){ g.zOpenRevision = db_get("main-branch", 0); } if( !bNosync && autosync_loop(SYNC_PULL, db_get_int("autosync-tries", 1), 1) && !bForce ){ fossil_fatal("unable to auto-sync the repository"); } } #if defined(_WIN32) || defined(__CYGWIN__) # define LOCALDB_NAME "./_FOSSIL_" #else # define LOCALDB_NAME "./.fslckout" |
︙ | ︙ | |||
3982 3983 3984 3985 3986 3987 3988 | /* ** SETTING: gmerge-command width=40 sensitive ** The value is a graphical merge conflict resolver command operating ** on four files. Examples: ** ** kdiff3 "%baseline" "%original" "%merge" -o "%output" ** xxdiff "%original" "%baseline" "%merge" -M "%output" | | | 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 | /* ** SETTING: gmerge-command width=40 sensitive ** The value is a graphical merge conflict resolver command operating ** on four files. Examples: ** ** kdiff3 "%baseline" "%original" "%merge" -o "%output" ** xxdiff "%original" "%baseline" "%merge" -M "%output" ** meld "%baseline" "%original" "%merge" --output "%output" */ /* ** SETTING: hash-digits width=5 default=10 ** The number of hexadecimal digits of the SHA3 hash to display. */ /* ** SETTING: http-port width=16 default=8080 |
︙ | ︙ | |||
4058 4059 4060 4061 4062 4063 4064 | ** This value should be set on the server to which users auto-sync ** their work. This setting has no effect on client repositories. The ** check-in lock mechanism is only effective if all users are auto-syncing ** to the same server. ** ** Check-in locks are an advisory mechanism designed to help prevent ** accidental forks due to a check-in race in installations where many | | | 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 | ** This value should be set on the server to which users auto-sync ** their work. This setting has no effect on client repositories. The ** check-in lock mechanism is only effective if all users are auto-syncing ** to the same server. ** ** Check-in locks are an advisory mechanism designed to help prevent ** accidental forks due to a check-in race in installations where many ** users are committing to the same branch and auto-sync is enabled. ** As forks are harmless, there is no danger in disabling this mechanism. ** However, keeping check-in locks turned on can help prevent unnecessary ** confusion. */ /* ** SETTING: main-branch width=40 default=trunk ** The value is the primary branch for the project. |
︙ | ︙ | |||
4411 4412 4413 4414 4415 4416 4417 | fossil_fatal("ambiguous setting \"%s\" - might be:%s", zName, blob_str(&x)); } if( globalFlag && isManifest ){ fossil_fatal("cannot set 'manifest' globally"); } if( unsetFlag ){ | | | | 4425 4426 4427 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 | fossil_fatal("ambiguous setting \"%s\" - might be:%s", zName, blob_str(&x)); } if( globalFlag && isManifest ){ fossil_fatal("cannot set 'manifest' globally"); } if( unsetFlag ){ db_unset(pSetting->name/*works-like:"x"*/, globalFlag); }else{ db_protect_only(PROTECT_NONE); db_set(pSetting->name/*works-like:"x"*/, g.argv[3], globalFlag); db_protect_pop(); } if( isManifest && g.localOpen ){ manifest_to_disk(db_lget_int("checkout", 0)); } }else{ while( pSetting->name ){ |
︙ | ︙ |
Changes to src/default.css.
︙ | ︙ | |||
1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 | } body.branch .submenu > a.timeline-link { display: none; } body.branch .submenu > a.timeline-link.selected { display: inline; } /* Objects in the "desktoponly" class are invisible on mobile */ @media screen and (max-width: 600px) { .desktoponly { display: none; } } | > > > > | 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 | } body.branch .submenu > a.timeline-link { display: none; } body.branch .submenu > a.timeline-link.selected { display: inline; } .monospace { font-family: monospace; } /* Objects in the "desktoponly" class are invisible on mobile */ @media screen and (max-width: 600px) { .desktoponly { display: none; } } |
︙ | ︙ |
Changes to src/diffcmd.c.
︙ | ︙ | |||
269 270 271 272 273 274 275 | file_tempname(&nameFile1, zFile2, "orig"); blob_write_to_file(pFile1, blob_str(&nameFile1)); /* Construct the external diff command */ blob_zero(&cmd); blob_append(&cmd, zDiffCmd, -1); if( fSwapDiff ){ | | | | | | 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 | file_tempname(&nameFile1, zFile2, "orig"); blob_write_to_file(pFile1, blob_str(&nameFile1)); /* Construct the external diff command */ blob_zero(&cmd); blob_append(&cmd, zDiffCmd, -1); if( fSwapDiff ){ blob_append_escaped_arg(&cmd, zFile2, 1); blob_append_escaped_arg(&cmd, blob_str(&nameFile1), 1); }else{ blob_append_escaped_arg(&cmd, blob_str(&nameFile1), 1); blob_append_escaped_arg(&cmd, zFile2, 1); } /* Run the external diff command */ fossil_system(blob_str(&cmd)); /* Delete the temporary file and clean up memory used */ file_delete(blob_str(&nameFile1)); |
︙ | ︙ | |||
355 356 357 358 359 360 361 | file_tempname(&temp2, zName, "after"); blob_write_to_file(pFile1, blob_str(&temp1)); blob_write_to_file(pFile2, blob_str(&temp2)); /* Construct the external diff command */ blob_zero(&cmd); blob_append(&cmd, zDiffCmd, -1); | | | | 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 | file_tempname(&temp2, zName, "after"); blob_write_to_file(pFile1, blob_str(&temp1)); blob_write_to_file(pFile2, blob_str(&temp2)); /* Construct the external diff command */ blob_zero(&cmd); blob_append(&cmd, zDiffCmd, -1); blob_append_escaped_arg(&cmd, blob_str(&temp1), 1); blob_append_escaped_arg(&cmd, blob_str(&temp2), 1); /* Run the external diff command */ fossil_system(blob_str(&cmd)); /* Delete the temporary file and clean up memory used */ file_delete(blob_str(&temp1)); file_delete(blob_str(&temp2)); |
︙ | ︙ |
Changes to src/dispatch.c.
︙ | ︙ | |||
563 564 565 566 567 568 569 | }else if( rawOut ){ fossil_print("# %s\n", aCommand[i].zName); fossil_print("%s\n\n", aCommand[i].zHelp); }else{ Blob txt; blob_init(&txt, 0, 0); help_to_text(aCommand[i].zHelp, &txt); | | > > | 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 | }else if( rawOut ){ fossil_print("# %s\n", aCommand[i].zName); fossil_print("%s\n\n", aCommand[i].zHelp); }else{ Blob txt; blob_init(&txt, 0, 0); help_to_text(aCommand[i].zHelp, &txt); fossil_print("# %s%s\n", aCommand[i].zName, (aCommand[i].eCmdFlags & CMDFLAG_VERSIONABLE)!=0 ? " (versionable)" : ""); fossil_print("%s\n\n", blob_str(&txt)); blob_reset(&txt); } } if( useHtml ){ fossil_print("<!-- end_all_help -->\n"); }else{ |
︙ | ︙ | |||
973 974 975 976 977 978 979 | multi_column_list(aCmd, nCmd); } /* ** List of commands starting with zPrefix, or all commands if zPrefix is NULL. */ | | > > > | < | | < | < | | | > | 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 | multi_column_list(aCmd, nCmd); } /* ** List of commands starting with zPrefix, or all commands if zPrefix is NULL. */ static void command_list(int cmdMask, int verboseFlag, int useHtml){ if( verboseFlag ){ display_all_help(cmdMask, useHtml, 0); }else{ int i, nCmd; const char *aCmd[MX_COMMAND]; for(i=nCmd=0; i<MX_COMMAND; i++){ if( (aCommand[i].eCmdFlags & cmdMask)==0 ) continue; aCmd[nCmd++] = aCommand[i].zName; } multi_column_list(aCmd, nCmd); } } /* ** Documentation on universal command-line options. */ /* @-comment: # */ static const char zOptions[] = |
︙ | ︙ | |||
1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 | ** ** The following options can be used when TOPIC is omitted: ** ** -a|--all List both common and auxiliary commands ** -o|--options List command-line options common to all commands ** -s|--setting List setting names ** -t|--test List unsupported "test" commands ** -x|--aux List only auxiliary commands ** -w|--www List all web pages ** -f|--full List full set of commands (including auxiliary ** and unsupported "test" commands), options, ** settings, and web pages ** -e|--everything List all help on all topics ** ** These options can be used when TOPIC is present: ** ** -h|--html Format output as HTML rather than plain text ** -c|--commands Restrict TOPIC search to commands */ void help_cmd(void){ int rc; int mask = CMDFLAG_ANY; int isPage = 0; const char *z; const char *zCmdOrPage; const CmdOrPage *pCmd = 0; int useHtml = 0; Blob txt; if( g.argc<3 ){ z = g.argv[0]; fossil_print( "Usage: %s help TOPIC\n" "Try \"%s help help\" or \"%s help -a\" for more options\n" "Frequently used commands:\n", z, z, z); | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | | | 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 | ** ** The following options can be used when TOPIC is omitted: ** ** -a|--all List both common and auxiliary commands ** -o|--options List command-line options common to all commands ** -s|--setting List setting names ** -t|--test List unsupported "test" commands ** -v|--verbose List both names and help text ** -x|--aux List only auxiliary commands ** -w|--www List all web pages ** -f|--full List full set of commands (including auxiliary ** and unsupported "test" commands), options, ** settings, and web pages ** -e|--everything List all help on all topics ** ** These options can be used when TOPIC is present: ** ** -h|--html Format output as HTML rather than plain text ** -c|--commands Restrict TOPIC search to commands */ void help_cmd(void){ int rc; int mask = CMDFLAG_ANY; int isPage = 0; int verboseFlag = 0; int commandsFlag = 0; const char *z; const char *zCmdOrPage; const CmdOrPage *pCmd = 0; int useHtml = 0; const char *zTopic; Blob txt; verboseFlag = find_option("verbose","v",0)!=0; commandsFlag = find_option("commands","c",0)!=0; useHtml = find_option("html","h",0)!=0; if( find_option("options","o",0) ){ fossil_print("%s", zOptions); return; } else if( find_option("all","a",0) ){ command_list(CMDFLAG_1ST_TIER | CMDFLAG_2ND_TIER, verboseFlag, useHtml); return; } else if( find_option("www","w",0) ){ command_list(CMDFLAG_WEBPAGE, verboseFlag, useHtml); return; } else if( find_option("aux","x",0) ){ command_list(CMDFLAG_2ND_TIER, verboseFlag, useHtml); return; } else if( find_option("test","t",0) ){ command_list(CMDFLAG_TEST, verboseFlag, useHtml); return; } else if( find_option("setting","s",0) ){ command_list(CMDFLAG_SETTING, verboseFlag, useHtml); return; } else if( find_option("full","f",0) ){ fossil_print("fossil commands:\n\n"); command_list(CMDFLAG_1ST_TIER, verboseFlag, useHtml); fossil_print("\nfossil auxiliary commands:\n\n"); command_list(CMDFLAG_2ND_TIER, verboseFlag, useHtml); fossil_print("\n%s", zOptions); fossil_print("\nfossil settings:\n\n"); command_list(CMDFLAG_SETTING, verboseFlag, useHtml); fossil_print("\nfossil web pages:\n\n"); command_list(CMDFLAG_WEBPAGE, verboseFlag, useHtml); fossil_print("\nfossil test commands (unsupported):\n\n"); command_list(CMDFLAG_TEST, verboseFlag, useHtml); fossil_print("\n"); version_cmd(); return; } else if( find_option("everything","e",0) ){ display_all_help(CMDFLAG_1ST_TIER | CMDFLAG_2ND_TIER | CMDFLAG_WEBPAGE | CMDFLAG_SETTING | CMDFLAG_TEST, useHtml, 0); return; } verify_all_options(); if( g.argc<3 ){ z = g.argv[0]; fossil_print( "Usage: %s help TOPIC\n" "Try \"%s help help\" or \"%s help -a\" for more options\n" "Frequently used commands:\n", z, z, z); command_list(CMDFLAG_1ST_TIER,verboseFlag,useHtml); if( !verboseFlag ) version_cmd(); return; } zTopic = g.argv[2]; isPage = ('/' == zTopic[0]) ? 1 : 0; if(isPage){ zCmdOrPage = "page"; }else if( commandsFlag ){ mask = CMDFLAG_COMMAND; zCmdOrPage = "command"; }else{ zCmdOrPage = "command or setting"; } rc = dispatch_name_search(g.argv[2], mask|CMDFLAG_PREFIX, &pCmd); if( rc ){ |
︙ | ︙ |
Changes to src/doc.c.
︙ | ︙ | |||
1245 1246 1247 1248 1249 1250 1251 1252 | ** is prompted to enter a search string. ** ** Query parameters: ** ** s=PATTERN Search for PATTERN */ void doc_search_page(void){ login_check_credentials(); | > | | 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 | ** is prompted to enter a search string. ** ** Query parameters: ** ** s=PATTERN Search for PATTERN */ void doc_search_page(void){ const int isSearch = P("s")!=0; login_check_credentials(); style_header("Document Search%s", isSearch ? " Results" : ""); search_screen(SRCH_DOC, 0); style_finish_page(); } |
Changes to src/etag.c.
︙ | ︙ | |||
171 172 173 174 175 176 177 178 179 180 181 182 183 184 | ** not changed and we can do a 304 reply */ cgi_reset_content(); cgi_set_status(304, "Not Modified"); cgi_reply(); db_close(0); fossil_exit(0); } /* ** Accept a new Last-Modified time. This routine should be called by ** page generators that know a valid last-modified time. This routine ** might generate a 304 Not Modified reply and exit(), never returning. ** Or, if not, it will cause a Last-Modified: header to be included in the ** reply. | > > > > > > > > > > > > > > > > | 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 | ** not changed and we can do a 304 reply */ cgi_reset_content(); cgi_set_status(304, "Not Modified"); cgi_reply(); db_close(0); fossil_exit(0); } /* ** If the output is determined purely by hash parameter and the hash ** is long enough to be invariant, then set the g.isConst flag, indicating ** that the output will never change. */ void etag_check_for_invariant_name(const char *zHash){ size_t nHash = strlen(zHash); if( nHash<HNAME_MIN ){ return; /* Name is too short */ } if( !validate16(zHash, (int)nHash) ){ return; /* Name is not pure hex */ } g.isConst = 1; /* A long hex identifier must be a unique hash */ } /* ** Accept a new Last-Modified time. This routine should be called by ** page generators that know a valid last-modified time. This routine ** might generate a 304 Not Modified reply and exit(), never returning. ** Or, if not, it will cause a Last-Modified: header to be included in the ** reply. |
︙ | ︙ | |||
210 211 212 213 214 215 216 | db_close(0); fossil_exit(0); } /* Return the ETag, if there is one. */ const char *etag_tag(void){ | | | 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 | db_close(0); fossil_exit(0); } /* Return the ETag, if there is one. */ const char *etag_tag(void){ return g.isConst ? "" : zETag; } /* Return the recommended max-age */ int etag_maxage(void){ return iMaxAge; } |
︙ | ︙ |
Changes to src/export.c.
︙ | ︙ | |||
36 37 38 39 40 41 42 | struct mark_t { char *name; /* Name of the mark. Also starts with ":" */ int rid; /* Corresponding object in the BLOB table */ char uuid[65]; /* The GIT hash name for this object */ }; #endif | < < < < < < < | 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | struct mark_t { char *name; /* Name of the mark. Also starts with ":" */ int rid; /* Corresponding object in the BLOB table */ char uuid[65]; /* The GIT hash name for this object */ }; #endif /* ** Output a "committer" record for the given user. ** NOTE: the given user name may be an email itself. */ static void print_person(const char *zUser){ static Stmt q; const char *zContact; |
︙ | ︙ | |||
1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 | } gitmirror_message(VERB_NORMAL, "%s\n", zPushCmd); fossil_free(zPushCmd); zPushCmd = mprintf("git push --mirror %$", zPushUrl); rc = fossil_system(zPushCmd); if( rc ){ fossil_fatal("cannot push content using: %s", zPushCmd); } fossil_free(zPushCmd); } } /* ** Implementation of the "fossil git status" command. ** ** Show the status of a "git export". */ void gitmirror_status_command(void){ char *zMirror; char *z; int n, k; db_find_and_open_repository(0, 0); verify_all_options(); zMirror = db_get("last-git-export-repo", 0); if( zMirror==0 ){ fossil_print("Git mirror: none\n"); return; } | > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > | | 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 | } gitmirror_message(VERB_NORMAL, "%s\n", zPushCmd); fossil_free(zPushCmd); zPushCmd = mprintf("git push --mirror %$", zPushUrl); rc = fossil_system(zPushCmd); if( rc ){ fossil_fatal("cannot push content using: %s", zPushCmd); }else if( db_is_writeable("repository") ){ db_unprotect(PROTECT_CONFIG); db_multi_exec("REPLACE INTO config(name,value,mtime)" "VALUES('gitpush:%q',1,now())", zPushUrl); db_protect_pop(); } fossil_free(zPushCmd); } } /* ** Implementation of the "fossil git status" command. ** ** Show the status of a "git export". */ void gitmirror_status_command(void){ char *zMirror; char *z; int n, k; int rc; char *zSql; int bQuiet = 0; int bByAll = 0; /* Undocumented option meaning this command was invoked ** from "fossil all" and should modify output accordingly */ db_find_and_open_repository(0, 0); bQuiet = find_option("quiet","q",0)!=0; bByAll = find_option("by-all",0,0)!=0; verify_all_options(); zMirror = db_get("last-git-export-repo", 0); if( zMirror==0 ){ if( bQuiet ) return; if( bByAll ) return; fossil_print("Git mirror: none\n"); return; } zSql = sqlite3_mprintf("ATTACH '%q/.mirror_state/db' AS mirror", zMirror); if( zSql==0 ) fossil_fatal("out of memory"); g.dbIgnoreErrors++; rc = sqlite3_exec(g.db, zSql, 0, 0, 0); g.dbIgnoreErrors--; sqlite3_free(zSql); if( rc ){ if( bQuiet ) return; if( bByAll ) return; fossil_print("Git mirror: %s (Inactive)\n", zMirror); return; } if( bByAll ){ size_t len = strlen(g.zRepositoryName); int n; if( len>60 ) len = 60; n = (int)(65 - len); fossil_print("%.12c %s %.*c\n", '*', g.zRepositoryName, n, '*'); } fossil_print("Git mirror: %s\n", zMirror); z = db_text(0, "SELECT datetime(value) FROM mconfig WHERE key='start'"); if( z ){ double rAge = db_double(0.0, "SELECT julianday('now') - value" " FROM mconfig WHERE key='start'"); if( rAge>1.0/86400.0 ){ fossil_print("Last export: %s (%z ago)\n", z, human_readable_age(rAge)); }else{ |
︙ | ︙ | |||
1776 1777 1778 1779 1780 1781 1782 | if( n==0 ){ fossil_print("Status: up-to-date\n"); }else{ fossil_print("Status: %d check-in%s awaiting export\n", n, n==1 ? "" : "s"); } n = db_int(0, "SELECT count(*) FROM mmark WHERE isfile"); | | | 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 | if( n==0 ){ fossil_print("Status: up-to-date\n"); }else{ fossil_print("Status: %d check-in%s awaiting export\n", n, n==1 ? "" : "s"); } n = db_int(0, "SELECT count(*) FROM mmark WHERE isfile"); k = db_int(0, "SELECT count(*) FROM mmark WHERE NOT isfile"); fossil_print("Exported: %d check-ins and %d file blobs\n", k, n); } /* ** COMMAND: git* ** ** Usage: %fossil git SUBCOMMAND |
︙ | ︙ | |||
1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 | ** > fossil git import MIRROR ** ** TBD... ** ** > fossil git status ** ** Show the status of the current Git mirror, if there is one. */ void gitmirror_command(void){ char *zCmd; int nCmd; if( g.argc<3 ){ usage("export ARGS..."); } | > > | 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 | ** > fossil git import MIRROR ** ** TBD... ** ** > fossil git status ** ** Show the status of the current Git mirror, if there is one. ** ** -q|--quiet No output if there is nothing to report */ void gitmirror_command(void){ char *zCmd; int nCmd; if( g.argc<3 ){ usage("export ARGS..."); } |
︙ | ︙ |
Changes to src/extcgi.c.
︙ | ︙ | |||
28 29 30 31 32 33 34 | ** same login system as the main repository, and appear to be ** an integrated part of the repository. */ #include "config.h" #include "extcgi.h" #include <assert.h> | < < < < < < < | 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | ** same login system as the main repository, and appear to be ** an integrated part of the repository. */ #include "config.h" #include "extcgi.h" #include <assert.h> /* ** These are the environment variables that should be set for CGI ** extension programs: */ static const char *azCgiEnv[] = { "AUTH_TYPE", "AUTH_CONTENT", |
︙ | ︙ |
Changes to src/file.c.
︙ | ︙ | |||
907 908 909 910 911 912 913 914 915 916 917 918 919 920 | if( zName==0 ){ rc = 1; }else{ rc = file_rmdir(zName); } sqlite3_result_int(context, rc); } /* ** Return true if the filename given is a valid filename for ** a file in a repository. Valid filenames follow all of the ** following rules: ** ** * Does not begin with "/" | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 | if( zName==0 ){ rc = 1; }else{ rc = file_rmdir(zName); } sqlite3_result_int(context, rc); } /* ** Check the input argument to see if it looks like it has an prefix that ** indicates a remote file. If so, return the tail of the specification, ** which is the name of the file on the remote system. ** ** If the input argument does not have a prefix that makes it look like ** a remote file reference, then return NULL. ** ** Remote files look like: "HOST:PATH" or "USER@HOST:PATH". Host must ** be a valid hostname, meaning it must follow these rules: ** ** * Only characters [-.a-zA-Z0-9]. No spaces or other punctuation ** * Does not begin or end with - ** * Name is two or more characters long (otherwise it might be ** confused with a drive-letter on Windows). ** ** The USER section, if it exists, must not contain the '@' character. */ const char *file_skip_userhost(const char *zIn){ const char *zTail; int n, i; if( zIn[0]==':' ) return 0; zTail = strchr(zIn, ':'); if( zTail==0 ) return 0; if( zTail - zIn > 10000 ) return 0; n = (int)(zTail - zIn); if( n<2 ) return 0; if( zIn[n-1]=='-' || zIn[n-1]=='.' ) return 0; for(i=n-1; i>0 && zIn[i-1]!='@'; i--){ if( !fossil_isalnum(zIn[i]) && zIn[i]!='-' && zIn[i]!='.' ) return 0; } if( zIn[i]=='-' || zIn[i]=='.' || i==1 ) return 0; if( i>1 ){ i -= 2; while( i>=0 ){ if( zIn[i]=='@' ) return 0; i--; } } return zTail+1; } /* ** Return true if the filename given is a valid filename for ** a file in a repository. Valid filenames follow all of the ** following rules: ** ** * Does not begin with "/" |
︙ | ︙ | |||
1111 1112 1113 1114 1115 1116 1117 | } /* ** COMMAND: test-simplify-name ** ** Usage: %fossil test-simplify-name FILENAME... ** | | > > > > > > > > > > > | > | 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 | } /* ** COMMAND: test-simplify-name ** ** Usage: %fossil test-simplify-name FILENAME... ** ** Print the simplified versions of each FILENAME. This is used to test ** the file_simplify_name() routine. ** ** If FILENAME is of the form "HOST:PATH" or "USER@HOST:PATH", then remove ** and print the remote host prefix first. This is used to test the ** file_skip_userhost() interface. */ void cmd_test_simplify_name(void){ int i; char *z; const char *zTail; for(i=2; i<g.argc; i++){ zTail = file_skip_userhost(g.argv[i]); if( zTail ){ fossil_print("... ON REMOTE: %.*s\n", (int)(zTail-g.argv[i]), g.argv[i]); z = mprintf("%s", zTail); }else{ z = mprintf("%s", g.argv[i]); } fossil_print("[%s] -> ", z); file_simplify_name(z, -1, 0); fossil_print("[%s]\n", z); fossil_free(z); } } |
︙ | ︙ | |||
1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 | ** and should be freed by the caller. ** ** This routine only works on unix. On Windows, simply return ** a copy of the input. */ char *file_fullexename(const char *zCmd){ #ifdef _WIN32 return fossil_strdup(zCmd); #else char *zPath; char *z; if( zCmd[0]=='/' ){ return fossil_strdup(zCmd); } | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 | ** and should be freed by the caller. ** ** This routine only works on unix. On Windows, simply return ** a copy of the input. */ char *file_fullexename(const char *zCmd){ #ifdef _WIN32 char *zPath; char *z = 0; const char *zExe = ""; if( sqlite3_strlike("%.exe",zCmd,0)!=0 ) zExe = ".exe"; if( file_is_absolute_path(zCmd) ){ return mprintf("%s%s", zCmd, zExe); } if( strchr(zCmd,'\\')!=0 && strchr(zCmd,'/')!=0 ){ int i; Blob out = BLOB_INITIALIZER; file_canonical_name(zCmd, &out, 0); blob_append(&out, zExe, -1); z = fossil_strdup(blob_str(&out)); blob_reset(&out); for(i=0; z[i]; i++){ if( z[i]=='/' ) z[i] = '\\'; } return z; } z = mprintf(".\\%s%s", zCmd, zExe); if( file_isfile(z, ExtFILE) ){ int i; Blob out = BLOB_INITIALIZER; file_canonical_name(zCmd, &out, 0); blob_append(&out, zExe, -1); z = fossil_strdup(blob_str(&out)); blob_reset(&out); for(i=0; z[i]; i++){ if( z[i]=='/' ) z[i] = '\\'; } return z; } fossil_free(z); zPath = fossil_getenv("PATH"); while( zPath && zPath[0] ){ int n; char *zColon; zColon = strchr(zPath, ';'); n = zColon ? (int)(zColon-zPath) : (int)strlen(zPath); while( n>0 && zPath[n-1]=='\\' ){ n--; } z = mprintf("%.*s\\%s%s", n, zPath, zCmd, zExe); if( file_isfile(z, ExtFILE) ){ return z; } fossil_free(z); if( zColon==0 ) break; zPath = zColon+1; } return fossil_strdup(zCmd); #else char *zPath; char *z; if( zCmd[0]=='/' ){ return fossil_strdup(zCmd); } |
︙ | ︙ | |||
1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 | ** the temporary file is derived from zBasis. The suffix on the temp ** file is the same as the suffix on zBasis, and the temp file has ** the root of zBasis in its name. ** ** If zTag is not NULL, then try to create the temp-file using zTag ** as a differentiator. If that fails, or if zTag is NULL, then use ** a bunch of random characters as the tag. */ void file_tempname(Blob *pBuf, const char *zBasis, const char *zTag){ #if defined(_WIN32) const char *azDirs[] = { 0, /* GetTempPath */ 0, /* TEMP */ 0, /* TMP */ ".", }; | > > < > | 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 | ** the temporary file is derived from zBasis. The suffix on the temp ** file is the same as the suffix on zBasis, and the temp file has ** the root of zBasis in its name. ** ** If zTag is not NULL, then try to create the temp-file using zTag ** as a differentiator. If that fails, or if zTag is NULL, then use ** a bunch of random characters as the tag. ** ** Dangerous characters in zBasis are changed. */ void file_tempname(Blob *pBuf, const char *zBasis, const char *zTag){ #if defined(_WIN32) const char *azDirs[] = { 0, /* GetTempPath */ 0, /* TEMP */ 0, /* TMP */ ".", }; #else static const char *azDirs[] = { 0, /* TMPDIR */ "/var/tmp", "/usr/tmp", "/tmp", "/temp", ".", }; #endif static const unsigned char zChars[] = "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789"; unsigned int i; const char *zDir = "."; int cnt = 0; char zRand[16]; int nBasis; const char *zSuffix; char *z; #if defined(_WIN32) wchar_t zTmpPath[MAX_PATH]; if( GetTempPathW(MAX_PATH, zTmpPath) ){ azDirs[0] = fossil_path_to_utf8(zTmpPath); /* Removing trailing \ from the temp path */ |
︙ | ︙ | |||
1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 | zRand[i] = (char)zChars[ ((unsigned char)zRand[i])%(sizeof(zChars)-1) ]; } zRand[15] = 0; zTag = zRand; } blob_appendf(pBuf, "%s/%.*s~%s%s", zDir, nBasis, zBasis, zTag, zSuffix); zTag = 0; }while( file_size(blob_str(pBuf), ExtFILE)>=0 ); #if defined(_WIN32) fossil_path_free((char *)azDirs[0]); fossil_path_free((char *)azDirs[1]); fossil_path_free((char *)azDirs[2]); /* Change all \ characters in the windows path into / so that they can | > > > | 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 | zRand[i] = (char)zChars[ ((unsigned char)zRand[i])%(sizeof(zChars)-1) ]; } zRand[15] = 0; zTag = zRand; } blob_appendf(pBuf, "%s/%.*s~%s%s", zDir, nBasis, zBasis, zTag, zSuffix); zTag = 0; for(z=blob_str(pBuf); z!=0 && (z=strpbrk(z,"'\"`;|$&"))!=0; z++){ z[0] = '_'; } }while( file_size(blob_str(pBuf), ExtFILE)>=0 ); #if defined(_WIN32) fossil_path_free((char *)azDirs[0]); fossil_path_free((char *)azDirs[1]); fossil_path_free((char *)azDirs[2]); /* Change all \ characters in the windows path into / so that they can |
︙ | ︙ | |||
2618 2619 2620 2621 2622 2623 2624 | usage("FILENAME_1 [...FILENAME_N]"); } for( i = 2; i < g.argc; ++i ){ const int check = file_is_reserved_name(g.argv[i], -1); fossil_print("%d %s\n", check, g.argv[i]); } } | > > > > > > > > > > > > > > > > > > > > > | 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 | usage("FILENAME_1 [...FILENAME_N]"); } for( i = 2; i < g.argc; ++i ){ const int check = file_is_reserved_name(g.argv[i], -1); fossil_print("%d %s\n", check, g.argv[i]); } } /* ** Returns 1 if the given directory contains a file named .fslckout, 2 ** if it contains a file named _FOSSIL_, else returns 0. */ int dir_has_ckout_db(const char *zDir){ int rc = 0; char * zCkoutDb = mprintf("%//.fslckout", zDir); if(file_isfile(zCkoutDb, ExtFILE)){ rc = 1; }else{ fossil_free(zCkoutDb); zCkoutDb = mprintf("%//_FOSSIL_", zDir); if(file_isfile(zCkoutDb, ExtFILE)){ rc = 2; } } fossil_free(zCkoutDb); return rc; } |
Changes to src/finfo.c.
︙ | ︙ | |||
139 140 141 142 143 144 145 146 147 148 149 150 151 152 | content_get(rid, &record); } blob_write_to_file(&record, "-"); blob_reset(&record); blob_reset(&fname); }else if( find_option("id","i",0) ){ Blob fname; const char *zRevision = find_option("revision", "r", 1); verify_all_options(); if( zRevision==0 ) usage("-i|--id also requires -r|--revision"); if( g.argc!=3 ) usage("-r|--revision REVISION FILENAME"); file_tree_name(g.argv[2], &fname, 0, 1); | > | | | | | 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 | content_get(rid, &record); } blob_write_to_file(&record, "-"); blob_reset(&record); blob_reset(&fname); }else if( find_option("id","i",0) ){ Blob fname; int rid; const char *zRevision = find_option("revision", "r", 1); verify_all_options(); if( zRevision==0 ) usage("-i|--id also requires -r|--revision"); if( g.argc!=3 ) usage("-r|--revision REVISION FILENAME"); file_tree_name(g.argv[2], &fname, 0, 1); rid = db_int(0, "SELECT rid FROM blob WHERE uuid =" " (SELECT uuid FROM files_of_checkin(%Q)" " WHERE filename=%B %s)", zRevision, &fname, filename_collation()); if( rid==0 ) { fossil_fatal("file not found for revision %s: %s", zRevision, blob_str(&fname)); } whatis_rid(rid,0); blob_reset(&fname); }else{ |
︙ | ︙ | |||
898 899 900 901 902 903 904 | /* 5 */ " (SELECT uuid FROM blob WHERE rid=mlink.pmid)," /* 6 */ " mperm," /* 7 */ " isaux" " FROM mlink WHERE mid=%d ORDER BY 1", mid ); @ <h1>MLINK table for check-in %h(zCI)</h1> | | | 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 | /* 5 */ " (SELECT uuid FROM blob WHERE rid=mlink.pmid)," /* 6 */ " mperm," /* 7 */ " isaux" " FROM mlink WHERE mid=%d ORDER BY 1", mid ); @ <h1>MLINK table for check-in %h(zCI)</h1> render_checkin_context(mid, 0, 1, 0); style_table_sorter(); @ <hr /> @ <div class='brlist'> @ <table class='sortable' data-column-types='ttxtttt' data-init-sort='1'> @ <thead><tr> @ <th>File</th> @ <th>Parent<br>Check-in</th> |
︙ | ︙ |
Changes to src/forum.c.
︙ | ︙ | |||
1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 | ** threads. Also show a search box at the top if search is enabled, ** and a button for creating a new thread, if enabled. ** ** Query parameters: ** ** n=N The number of threads to show on each page ** x=X Skip the first X threads */ void forum_main_page(void){ Stmt q; int iLimit, iOfst, iCnt; int srchFlags; login_check_credentials(); srchFlags = search_restrict(SRCH_FORUM); if( !g.perm.RdForum ){ login_needed(g.anon.RdForum); return; } style_set_current_feature("forum"); | > > | | 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 | ** threads. Also show a search box at the top if search is enabled, ** and a button for creating a new thread, if enabled. ** ** Query parameters: ** ** n=N The number of threads to show on each page ** x=X Skip the first X threads ** s=Y Search for term Y. */ void forum_main_page(void){ Stmt q; int iLimit, iOfst, iCnt; int srchFlags; const int isSearch = P("s")!=0; login_check_credentials(); srchFlags = search_restrict(SRCH_FORUM); if( !g.perm.RdForum ){ login_needed(g.anon.RdForum); return; } style_set_current_feature("forum"); style_header( "%s", isSearch ? "Forum Search Results" : "Forum" ); if( g.perm.WrForum ){ style_submenu_element("New Thread","%R/forumnew"); }else{ /* Can't combine this with previous case using the ternary operator * because that causes an error yelling about "non-constant format" * with some compilers. I can't see it, since both expressions have * the same format, but I'm no C spec lawyer. */ |
︙ | ︙ |
Changes to src/fossil.copybutton.js.
︙ | ︙ | |||
19 20 21 22 23 24 25 | .copyFromId: DOM element ID One of copyFromElement or copyFromId must be provided, but copyFromId may optionally be provided via e.dataset.copyFromId. .extractText: optional callback which is triggered when the copy | | | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | .copyFromId: DOM element ID One of copyFromElement or copyFromId must be provided, but copyFromId may optionally be provided via e.dataset.copyFromId. .extractText: optional callback which is triggered when the copy button is clicked. It must return the text to copy to the clipboard. The default is to extract it from the copy-from element, using its [value] member, if it has one, else its [innerText]. A client-provided callback may use any data source it likes, so long as it's synchronous. If this function returns a falsy value then the clipboard is not modified. This function is called with the fully expanded/resolved options object as its "this" (that's a different instance than the one passed to this |
︙ | ︙ | |||
79 80 81 82 83 84 85 | fossil.dom.flashOnce(ev.target); console.debug("Copied text:",ev.detail.text); }); */ F.copyButton = function f(e, opt){ if('string'===typeof e){ e = document.querySelector(e); | | | 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | fossil.dom.flashOnce(ev.target); console.debug("Copied text:",ev.detail.text); }); */ F.copyButton = function f(e, opt){ if('string'===typeof e){ e = document.querySelector(e); } opt = F.mergeLastWins(f.defaultOptions, opt); if(opt.cssClass){ D.addClass(e, opt.cssClass); } var srcId, srcElem; if(opt.copyFromElement){ srcElem = opt.copyFromElement; |
︙ | ︙ |
Changes to src/fossil.page.wikiedit.js.
︙ | ︙ | |||
180 181 182 183 184 185 186 187 188 189 190 191 192 193 | }); record.mimetype = winfo.mimetype; record.type = winfo.type; record.parent = winfo.parent; record.version = winfo.version; record.stashTime = new Date().getTime(); record.isEmpty = !!winfo.isEmpty; this.storeIndex(); if(arguments.length>1){ if(content) delete record.isEmpty; F.storage.set(this.contentKey(key), content); } this._fireStashEvent(); return this; | > | 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 | }); record.mimetype = winfo.mimetype; record.type = winfo.type; record.parent = winfo.parent; record.version = winfo.version; record.stashTime = new Date().getTime(); record.isEmpty = !!winfo.isEmpty; record.attachments = winfo.attachments; this.storeIndex(); if(arguments.length>1){ if(content) delete record.isEmpty; F.storage.set(this.contentKey(key), content); } this._fireStashEvent(); return this; |
︙ | ︙ | |||
524 525 526 527 528 529 530 | var wtype = 'normal'; if(0===name.indexOf('checkin/')) wtype = 'checkin'; else if(0===name.indexOf('branch/')) wtype = 'branch'; else if(0===name.indexOf('tag/')) wtype = 'tag'; /* ^^^ note that we're not validating that, e.g., checkin/XYZ has a full artifact ID after "checkin/". */ const winfo = { | | | 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 | var wtype = 'normal'; if(0===name.indexOf('checkin/')) wtype = 'checkin'; else if(0===name.indexOf('branch/')) wtype = 'branch'; else if(0===name.indexOf('tag/')) wtype = 'tag'; /* ^^^ note that we're not validating that, e.g., checkin/XYZ has a full artifact ID after "checkin/". */ const winfo = { name: name, type: wtype, mimetype: 'text/x-markdown', version: null, parent: null }; this.cache.pageList.push( winfo/*keeps entry from getting lost from the list on save*/ ); $stash.updateWinfo(winfo, ''); this._rebuildList(); |
︙ | ︙ | |||
816 817 818 819 820 821 822 | }; F.fetch.beforesend = function f(){ if(!ajaxState.toDisable){ ajaxState.toDisable = document.querySelectorAll( ['button:not([disabled])', 'input:not([disabled])', 'select:not([disabled])', | | > | 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 | }; F.fetch.beforesend = function f(){ if(!ajaxState.toDisable){ ajaxState.toDisable = document.querySelectorAll( ['button:not([disabled])', 'input:not([disabled])', 'select:not([disabled])', 'textarea:not([disabled])', 'fieldset:not([disabled])' ].join(',') ); } if(1===++ajaxState.count){ D.addClass(document.body, 'waiting'); D.disable(ajaxState.toDisable); } |
︙ | ︙ | |||
851 852 853 854 855 856 857 858 859 860 861 862 863 864 | selectFontSizeWrap: E('#select-font-size'), // selectDiffWS: E('select[name=diff_ws]'), cbAutoPreview: E('#cb-preview-autorefresh'), previewTarget: E('#wikiedit-tab-preview-wrapper'), diffTarget: E('#wikiedit-tab-diff-wrapper'), editStatus: E('#wikiedit-edit-status'), tabContainer: E('#wikiedit-tabs'), tabs:{ pageList: E('#wikiedit-tab-pages'), content: E('#wikiedit-tab-content'), preview: E('#wikiedit-tab-preview'), diff: E('#wikiedit-tab-diff'), misc: E('#wikiedit-tab-misc') //commit: E('#wikiedit-tab-commit') | > | 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 | selectFontSizeWrap: E('#select-font-size'), // selectDiffWS: E('select[name=diff_ws]'), cbAutoPreview: E('#cb-preview-autorefresh'), previewTarget: E('#wikiedit-tab-preview-wrapper'), diffTarget: E('#wikiedit-tab-diff-wrapper'), editStatus: E('#wikiedit-edit-status'), tabContainer: E('#wikiedit-tabs'), attachmentContainer: E("#attachment-wrapper"), tabs:{ pageList: E('#wikiedit-tab-pages'), content: E('#wikiedit-tab-content'), preview: E('#wikiedit-tab-preview'), diff: E('#wikiedit-tab-diff'), misc: E('#wikiedit-tab-misc') //commit: E('#wikiedit-tab-commit') |
︙ | ︙ | |||
1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 | If passed a truthy value any error message about not having a wiki page loaded is suppressed. */ const affirmPageLoaded = function(quiet){ if(!P.winfo && !quiet) F.error("No wiki page is loaded."); return !!P.winfo; }; /** Updates the in-tab title/edit status information */ P.updateEditStatus = function f(){ if(!f.eLinks){ f.eName = P.e.editStatus.querySelector('span.name'); f.eLinks = P.e.editStatus.querySelector('span.links'); } const wi = this.winfo; D.clearElement(f.eName, f.eLinks); if(!wi){ D.append(f.eName, '(no page loaded)'); | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | < | > | | | | | | | | | < > | 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 | If passed a truthy value any error message about not having a wiki page loaded is suppressed. */ const affirmPageLoaded = function(quiet){ if(!P.winfo && !quiet) F.error("No wiki page is loaded."); return !!P.winfo; }; /** Updates the attachments list from this.winfo. */ P.updateAttachmentsView = function f(){ if(!f.eAttach){ f.eAttach = P.e.attachmentContainer.querySelector('div'); } D.clearElement(f.eAttach); const wi = this.winfo; if(!wi){ D.append(f.eAttach,"No page loaded."); return this; } else if(!wi.version){ D.append(f.eAttach, "Page ["+wi.name+"] cannot have ", "attachments until it is saved once."); return this; } const btnReload = D.button("Reload list"); const self = this; btnReload.addEventListener('click', function(){ const isStashed = $stash.hasStashedContent(wi); F.fetch('wikiajax/attachments',{ responseType: 'json', urlParams: {page: wi.name}, onload: function(r){ wi.attachments = r; if(isStashed) self.stashContentChange(true); F.message("Reloaded attachment list for ["+wi.name+"]."); self.updateAttachmentsView(); } }); }); if(!wi.attachments || !wi.attachments.length){ D.append(f.eAttach, btnReload, " No attachments found for page ["+wi.name+"]. ", D.a(F.repoUrl('attachadd',{ page: wi.name, from: F.repoUrl('wikiedit',{name: wi.name})}), "Add attachments..." ) ); return this; } D.append( f.eAttach, D.append(D.p(), btnReload," ", D.a(F.repoUrl('attachlist',{page:wi.name}), "Attachments for page ["+wi.name+"]."), " ", D.a(F.repoUrl('attachadd',{ page:wi.name, from: F.repoUrl('wikiedit',{name: wi.name})}), "Add attachments..." ) ) ); wi.attachments.forEach(function(a){ const wrap = D.div(); D.append(f.eAttach, wrap); D.append(wrap, D.append(D.div(), "Attachment ", D.addClass( D.a(F.repoUrl('ainfo',{name:a.uuid}), F.hashDigits(a.uuid,true)), 'monospace'), " ", a.filename, (a.isLatest ? " (latest)" : "") ) ); //D.append(wrap,D.append(D.div(), "URLs:")); const ul = D.ul(); D.append(wrap, ul); [ // List download URL variants for each attachment: [ "attachdownload?page=", encodeURIComponent(wi.name), "&file=", encodeURIComponent(a.filename) ].join(''), "raw/"+a.src ].forEach(function(url){ const imgUrl = D.append(D.addClass(D.span(), 'monospace'), url); const urlCopy = D.span(); const li = D.li(ul); D.append(li, urlCopy, " ", imgUrl); F.copyButton(urlCopy, {copyFromElement: imgUrl}); }); }); return this; }; /** Updates the in-tab title/edit status information */ P.updateEditStatus = function f(){ if(!f.eLinks){ f.eName = P.e.editStatus.querySelector('span.name'); f.eLinks = P.e.editStatus.querySelector('span.links'); } const wi = this.winfo; D.clearElement(f.eName, f.eLinks); if(!wi){ D.append(f.eName, '(no page loaded)'); this.updateAttachmentsView(); return this; } D.append(f.eName,getEditMarker(wi, false),wi.name); this.updateAttachmentsView(); if(!wi.version) return this; D.append( f.eLinks, D.a(F.repoUrl('wiki',{name:wi.name}),"viewer"), D.a(F.repoUrl('whistory',{name:wi.name}),'history'), D.a(F.repoUrl('attachlist',{page:wi.name}),"attachments"), D.a(F.repoUrl('attachadd',{page:wi.name,from: F.repoUrl('wikiedit',{name: wi.name})}), "attach"), D.a(F.repoUrl('wikiedit',{name:wi.name}),"editor permalink") ); return this; }; /** Update the page title and header based on the state of this.winfo. A no-op if this.winfo is not set. Returns this. */ P.updatePageTitle = function f(){ |
︙ | ︙ | |||
1311 1312 1313 1314 1315 1316 1317 | onload({ name: stashWinfo.name, mimetype: stashWinfo.mimetype, type: stashWinfo.type, version: stashWinfo.version, parent: stashWinfo.parent, isEmpty: !!stashWinfo.isEmpty, | | > | 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 | onload({ name: stashWinfo.name, mimetype: stashWinfo.mimetype, type: stashWinfo.type, version: stashWinfo.version, parent: stashWinfo.parent, isEmpty: !!stashWinfo.isEmpty, content: $stash.stashedContent(stashWinfo), attachments: stashWinfo.attachments }); this._isDirty = true/*b/c loading normally clears that flag*/; return this; } F.message( "Loading content..." ).fetch('wikiajax/fetch',{ |
︙ | ︙ |
Changes to src/http_ssl.c.
︙ | ︙ | |||
435 436 437 438 439 440 441 | ** Remember that the cert with the given hash is a acceptable for ** use with pUrlData->name. */ LOCAL void ssl_remember_certificate_exception( UrlData *pUrlData, const char *zHash ){ | | < < | 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 | ** Remember that the cert with the given hash is a acceptable for ** use with pUrlData->name. */ LOCAL void ssl_remember_certificate_exception( UrlData *pUrlData, const char *zHash ){ db_set_mprintf(zHash, 1, "cert:%s", pUrlData->name); } /* ** Return true if the there exists a certificate exception for ** pUrlData->name that matches the hash. */ LOCAL int ssl_certificate_exception_exists( |
︙ | ︙ |
Changes to src/http_transport.c.
︙ | ︙ | |||
90 91 92 93 94 95 96 | } return 0; } /* ** Default SSH command */ | | | | > > > > > > > > > < < | < < < < > | | | | | 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 | } return 0; } /* ** Default SSH command */ #if 0 /* was: defined(_WIN32). Windows generally has ssh now. */ static const char zDefaultSshCmd[] = "plink -ssh"; #else static const char zDefaultSshCmd[] = "ssh -e none"; #endif /* ** Initialize a Blob to the name of the configured SSH command. */ void transport_ssh_command(Blob *p){ char *zSsh; /* The base SSH command */ zSsh = db_get("ssh-command", zDefaultSshCmd); blob_init(p, zSsh, -1); } /* ** SSH initialization of the transport layer */ int transport_ssh_open(UrlData *pUrlData){ /* For SSH we need to create and run SSH fossil http ** to talk to the remote machine. */ Blob zCmd; /* The SSH command */ char *zHost; /* The host name to contact */ socket_ssh_resolve_addr(pUrlData); transport_ssh_command(&zCmd); if( pUrlData->port!=pUrlData->dfltPort && pUrlData->port ){ blob_appendf(&zCmd, " -p %d", pUrlData->port); } blob_appendf(&zCmd, " -T --"); /* End of switches */ if( pUrlData->user && pUrlData->user[0] ){ zHost = mprintf("%s@%s", pUrlData->user, pUrlData->name); blob_append_escaped_arg(&zCmd, zHost, 0); fossil_free(zHost); }else{ blob_append_escaped_arg(&zCmd, pUrlData->name, 0); } if( !is_safe_fossil_command(pUrlData->fossil) ){ fossil_fatal("the ssh:// URL is asking to run an unsafe command [%s] on " "the server.", pUrlData->fossil); } blob_append_escaped_arg(&zCmd, pUrlData->fossil, 1); blob_append(&zCmd, " test-http", 10); if( pUrlData->path && pUrlData->path[0] ){ blob_append_escaped_arg(&zCmd, pUrlData->path, 1); }else{ fossil_fatal("ssh:// URI does not specify a path to the repository"); } if( g.fSshTrace ){ fossil_print("%s\n", blob_str(&zCmd)); /* Show the whole SSH command */ } popen2(blob_str(&zCmd), &sshIn, &sshOut, &sshPid, 0); |
︙ | ︙ |
Changes to src/info.c.
︙ | ︙ | |||
268 269 270 271 272 273 274 | } show_common_info(rid, "hash:", 1, 1); } } /* ** Show the context graph (immediate parents and children) for | | | | 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 | } show_common_info(rid, "hash:", 1, 1); } } /* ** Show the context graph (immediate parents and children) for ** check-in rid and rid2 */ void render_checkin_context(int rid, int rid2, int parentsOnly, int mFlags){ Blob sql; Stmt q; int rx[2]; int i, n; rx[0] = rid; rx[1] = rid2; n = rid2 ? 2 : 1; |
︙ | ︙ | |||
311 312 313 314 315 316 317 | ); } } } blob_append_sql(&sql, " AND event.objid IN ok ORDER BY mtime DESC"); db_prepare(&q, "%s", blob_sql_text(&sql)); www_print_timeline(&q, | > | | 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 | ); } } } blob_append_sql(&sql, " AND event.objid IN ok ORDER BY mtime DESC"); db_prepare(&q, "%s", blob_sql_text(&sql)); www_print_timeline(&q, mFlags |TIMELINE_GRAPH |TIMELINE_FILLGAPS |TIMELINE_NOSCROLL |TIMELINE_XMERGE |TIMELINE_CHPICK, 0, 0, 0, rid, rid2, 0); db_finalize(&q); } |
︙ | ︙ | |||
878 879 880 881 882 883 884 | } db_finalize(&q1); if( !PB("nowiki") ){ wiki_render_associated("checkin", zUuid, 0); } render_backlink_graph(zUuid, "<div class=\"section\">References</div>\n"); @ <div class="section">Context</div> | | | 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 | } db_finalize(&q1); if( !PB("nowiki") ){ wiki_render_associated("checkin", zUuid, 0); } render_backlink_graph(zUuid, "<div class=\"section\">References</div>\n"); @ <div class="section">Context</div> render_checkin_context(rid, 0, 0, 0); @ <div class="section">Changes</div> @ <div class="sectionmenu"> diffFlags = construct_diff_flags(diffType); zW = (diffFlags&DIFF_IGNORE_ALLWS)?"&w":""; if( diffType!=0 ){ @ %z(chref("button","%R/%s/%T?diff=0",zPageHide,zName))\ @ Hide Diffs</a> |
︙ | ︙ | |||
1162 1163 1164 1165 1166 1167 1168 | ** to=TAG Right side of the comparison ** branch=TAG Show all changes on a particular branch ** diff=INTEGER 0: none, 1: unified, 2: side-by-side ** glob=STRING only diff files matching this glob ** dc=N show N lines of context around each diff ** w=BOOLEAN ignore whitespace when computing diffs ** nohdr omit the description at the top of the page | | > < < > > > > > | > > > | > > > > > > > > > > | | > > | > > > > > | > > | < < | < < < | < < < | < < | < | > | 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 | ** to=TAG Right side of the comparison ** branch=TAG Show all changes on a particular branch ** diff=INTEGER 0: none, 1: unified, 2: side-by-side ** glob=STRING only diff files matching this glob ** dc=N show N lines of context around each diff ** w=BOOLEAN ignore whitespace when computing diffs ** nohdr omit the description at the top of the page ** nc omit branch coloration from the header graph ** inv "Invert". Exchange the roles of from= and to= ** ** Show all differences between two check-ins. */ void vdiff_page(void){ int ridFrom, ridTo; int diffType = 0; /* 0: none, 1: unified, 2: side-by-side */ u64 diffFlags = 0; Manifest *pFrom, *pTo; ManifestFile *pFileFrom, *pFileTo; const char *zBranch; const char *zFrom; const char *zTo; const char *zRe; const char *zGlob; char *zMergeOrigin = 0; ReCompiled *pRe = 0; int graphFlags = 0; Blob qp; int bInvert = PB("inv"); login_check_credentials(); if( !g.perm.Read ){ login_needed(g.anon.Read); return; } login_anonymous_available(); load_control(); blob_init(&qp, 0, 0); diffType = preferred_diff_type(); zRe = P("regex"); if( zRe ) re_compile(&pRe, zRe, 0); zBranch = P("branch"); if( zBranch && zBranch[0]==0 ) zBranch = 0; if( zBranch ){ blob_appendf(&qp, "branch=%T", zBranch); zMergeOrigin = mprintf("merge-in:%s", zBranch); cgi_replace_parameter("from", zMergeOrigin); cgi_replace_parameter("to", zBranch); }else{ if( bInvert ){ blob_appendf(&qp, "to=%T&from=%T",PD("from",""),PD("to","")); }else{ blob_appendf(&qp, "from=%T&to=%T",PD("from",""),PD("to","")); } } pTo = vdiff_parse_manifest("to", &ridTo); if( pTo==0 ) return; pFrom = vdiff_parse_manifest("from", &ridFrom); if( pFrom==0 ) return; zGlob = P("glob"); zFrom = P("from"); zTo = P("to"); if( bInvert ){ Manifest *pTemp = pTo; const char *zTemp = zTo; pTo = pFrom; pFrom = pTemp; zTo = zFrom; zFrom = zTemp; } if( zGlob ){ if( !*zGlob ){ zGlob = NULL; }else{ blob_appendf(&qp, "&glob=%T", zGlob); } } if( PB("nc") ){ graphFlags |= TIMELINE_NOCOLOR; blob_appendf(&qp, "&nc"); } diffFlags = construct_diff_flags(diffType); if( diffFlags & DIFF_IGNORE_ALLWS ){ blob_appendf(&qp, "&w"); } style_set_current_feature("vdiff"); if( zBranch==0 ){ style_submenu_element("Path", "%R/timeline?me=%T&you=%T", zFrom, zTo); } if( diffType!=0 ){ style_submenu_element("Hide Diff", "%R/vdiff?diff=0&%b", &qp); } if( diffType!=2 ){ style_submenu_element("Side-by-Side Diff", "%R/vdiff?diff=2&%b", &qp); } if( diffType!=1 ) { style_submenu_element("Unified Diff", "%R/vdiff?diff=1&%b", &qp); } if( zBranch==0 ){ style_submenu_element("Invert","%R/vdiff?diff=%d&inv&%b", diffType, &qp); } if( zGlob ){ style_submenu_element("Clear glob", "%R/vdiff?diff=%d&%b", diffType, &qp); }else{ style_submenu_element("Patch", "%R/vpatch?from=%T&to=%T%s", zFrom, zTo, (diffFlags & DIFF_IGNORE_ALLWS)?"&w":""); } if( diffType!=0 ){ style_submenu_checkbox("w", "Ignore Whitespace", 0, 0); } if( zBranch ){ style_header("Changes On Branch %h", zBranch); }else{ |
︙ | ︙ | |||
1272 1273 1274 1275 1276 1277 1278 | @ %z(href("%R/info/%!S",zToUuid))%S(zToUuid)</a></span></p> }else{ @ <h2>Difference From <span class='timelineSelected'>\ @ %z(href("%R/info/%h",zFrom))%h(zFrom)</a></span> @ To <span class='timelineSelected timelineSecondary'>\ @ %z(href("%R/info/%h",zTo))%h(zTo)</a></span></h2> } | | | | 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 | @ %z(href("%R/info/%!S",zToUuid))%S(zToUuid)</a></span></p> }else{ @ <h2>Difference From <span class='timelineSelected'>\ @ %z(href("%R/info/%h",zFrom))%h(zFrom)</a></span> @ To <span class='timelineSelected timelineSecondary'>\ @ %z(href("%R/info/%h",zTo))%h(zTo)</a></span></h2> } render_checkin_context(ridFrom, ridTo, 0, graphFlags); if( pRe ){ @ <p><b>Only differences that match regular expression "%h(zRe)" @ are shown.</b></p> } if( zGlob ){ @ <p><b>Only files matching the glob "%h(zGlob)" are shown.</b></p> } @<hr /><p> } blob_reset(&qp); manifest_file_rewind(pFrom); pFileFrom = manifest_file_next(pFrom, 0); manifest_file_rewind(pTo); pFileTo = manifest_file_next(pTo, 0); while( pFileFrom || pFileTo ){ int cmp; |
︙ | ︙ | |||
2337 2338 2339 2340 2341 2342 2343 | @ The name= query parameter is missing style_finish_page(); return; } url_initialize(&url, g.zPath); url_add_parameter(&url, "name", zName); | | | 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 | @ The name= query parameter is missing style_finish_page(); return; } url_initialize(&url, g.zPath); url_add_parameter(&url, "name", zName); url_add_parameter(&url, "ci", zCI); /* no-op if zCI is NULL */ if( zCI==0 && !isFile ){ /* If there is no ci= query parameter, then prefer to interpret ** name= as a hash for /artifact and /whatis. But for not for /file. ** For /file, a name= without a ci= while prefer to use the default ** "tip" value for ci=. */ rid = name_to_rid(zName); |
︙ | ︙ | |||
2379 2380 2381 2382 2383 2384 2385 | " AND event.objid=mlink.mid" " AND blob.rid=mlink.mid" " ORDER BY event.mtime DESC", zName ); if( db_step(&q)==SQLITE_ROW ){ rid = db_column_int(&q, 0); | | > | 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 | " AND event.objid=mlink.mid" " AND blob.rid=mlink.mid" " ORDER BY event.mtime DESC", zName ); if( db_step(&q)==SQLITE_ROW ){ rid = db_column_int(&q, 0); zCI = fossil_strdup(db_column_text(&q, 1)); zCIUuid = fossil_strdup(zCI); url_add_parameter(&url, "ci", zCI); } db_finalize(&q); if( rid==0 ){ style_header("No such file"); @ File '%h(zName)' does not exist in this repository. } |
︙ | ︙ |
Changes to src/json_branch.c.
︙ | ︙ | |||
152 153 154 155 156 157 158 | /* ** Parameters for the create-branch operation. */ typedef struct BranchCreateOptions{ char const * zName; char const * zBasis; char const * zColor; | | | 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 | /* ** Parameters for the create-branch operation. */ typedef struct BranchCreateOptions{ char const * zName; char const * zBasis; char const * zColor; int isPrivate; /** Might be set to an error string by json_branch_new(). */ char const * rcErrMsg; } BranchCreateOptions; |
︙ | ︙ | |||
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 | char *zUuid; /* Artifact ID of origin */ Stmt q; /* Generic query */ char *zDate; /* Date that branch was created */ char *zComment; /* Check-in comment for the new branch */ Blob branch; /* manifest for the new branch */ Manifest *pParent; /* Parsed parent manifest */ Blob mcksum; /* Self-checksum on the manifest */ /* fossil branch new name */ if( zBranch==0 || zBranch[0]==0 ){ zOpt->rcErrMsg = "Branch name may not be null/empty."; return FSL_JSON_E_INVALID_ARGS; } if( db_exists( "SELECT 1 FROM tagxref" | > > > > > | 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 | char *zUuid; /* Artifact ID of origin */ Stmt q; /* Generic query */ char *zDate; /* Date that branch was created */ char *zComment; /* Check-in comment for the new branch */ Blob branch; /* manifest for the new branch */ Manifest *pParent; /* Parsed parent manifest */ Blob mcksum; /* Self-checksum on the manifest */ int bAutoColor = 0; /* Value of "--bgcolor" is "auto" */ if( fossil_strncmp(zColor, "auto", 4)==0 ) { bAutoColor = 1; zColor = 0; } /* fossil branch new name */ if( zBranch==0 || zBranch[0]==0 ){ zOpt->rcErrMsg = "Branch name may not be null/empty."; return FSL_JSON_E_INVALID_ARGS; } if( db_exists( "SELECT 1 FROM tagxref" |
︙ | ︙ | |||
258 259 260 261 262 263 264 | blob_appendf(&branch, "R %s\n", pParent->zRepoCksum); } manifest_destroy(pParent); /* Add the symbolic branch name and the "branch" tag to identify ** this as a new branch */ if( content_is_private(rootid) ) zOpt->isPrivate = 1; | | | 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 | blob_appendf(&branch, "R %s\n", pParent->zRepoCksum); } manifest_destroy(pParent); /* Add the symbolic branch name and the "branch" tag to identify ** this as a new branch */ if( content_is_private(rootid) ) zOpt->isPrivate = 1; if( zOpt->isPrivate && zColor==0 && !bAutoColor) zColor = "#fec084"; if( zColor!=0 ){ blob_appendf(&branch, "T *bgcolor * %F\n", zColor); } blob_appendf(&branch, "T *branch * %F\n", zBranch); blob_appendf(&branch, "T *sym-%F *\n", zBranch); /* Cancel all other symbolic tags */ |
︙ | ︙ |
Changes to src/linenoise.c.
︙ | ︙ | |||
1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 | * to its standard input. In this case, we want to be able to return the * line regardless of its length (by default we are limited to 4k). */ static char *linenoiseNoTTY(void) { char *line = NULL; size_t len = 0, maxlen = 0; while(1) { if (len == maxlen) { if (maxlen == 0) maxlen = 16; maxlen *= 2; | > > < | | 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 | * to its standard input. In this case, we want to be able to return the * line regardless of its length (by default we are limited to 4k). */ static char *linenoiseNoTTY(void) { char *line = NULL; size_t len = 0, maxlen = 0; while(1) { int c; if (len == maxlen) { char *oldval = line; if (maxlen == 0) maxlen = 16; maxlen *= 2; line = realloc(line,maxlen); if (line == NULL) { if (oldval) free(oldval); return NULL; } } c = fgetc(stdin); if (c == EOF || c == '\n') { if (c == EOF && len == 0) { free(line); return NULL; } else { line[len] = '\0'; return line; |
︙ | ︙ |
Changes to src/login.c.
︙ | ︙ | |||
1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 | uSeed = captcha_seed(); } zDecoded = captcha_decode(uSeed); zCaptcha = captcha_render(zDecoded); style_header("Register"); /* Print out the registration form. */ form_begin(0, "%R/register"); if( P("g") ){ @ <input type="hidden" name="g" value="%h(P("g"))" /> } @ <p><input type="hidden" name="captchaseed" value="%u(uSeed)" /> @ <table class="login_out"> @ <tr> | > | 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 | uSeed = captcha_seed(); } zDecoded = captcha_decode(uSeed); zCaptcha = captcha_render(zDecoded); style_header("Register"); /* Print out the registration form. */ g.perm.Hyperlink = 1; /* Artificially enable hyperlinks */ form_begin(0, "%R/register"); if( P("g") ){ @ <input type="hidden" name="g" value="%h(P("g"))" /> } @ <p><input type="hidden" name="captchaseed" value="%u(uSeed)" /> @ <table class="login_out"> @ <tr> |
︙ | ︙ |
Changes to src/main.c.
︙ | ︙ | |||
141 142 143 144 145 146 147 148 149 150 151 152 153 154 | }; #endif struct Global { int argc; char **argv; /* Command-line arguments to the program */ char *nameOfExe; /* Full path of executable. */ const char *zErrlog; /* Log errors to this file, if not NULL */ int isConst; /* True if the output is unchanging & cacheable */ const char *zVfsName; /* The VFS to use for database connections */ sqlite3 *db; /* The connection to the databases */ sqlite3 *dbConfig; /* Separate connection for global_config table */ char *zAuxSchema; /* Main repository aux-schema */ int dbIgnoreErrors; /* Ignore database errors if true */ char *zConfigDbName; /* Path of the config database. NULL if not open */ | > | 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | }; #endif struct Global { int argc; char **argv; /* Command-line arguments to the program */ char *nameOfExe; /* Full path of executable. */ const char *zErrlog; /* Log errors to this file, if not NULL */ const char *zPhase; /* Phase of operation, for use by the error log */ int isConst; /* True if the output is unchanging & cacheable */ const char *zVfsName; /* The VFS to use for database connections */ sqlite3 *db; /* The connection to the databases */ sqlite3 *dbConfig; /* Separate connection for global_config table */ char *zAuxSchema; /* Main repository aux-schema */ int dbIgnoreErrors; /* Ignore database errors if true */ char *zConfigDbName; /* Path of the config database. NULL if not open */ |
︙ | ︙ | |||
471 472 473 474 475 476 477 | for(k=0, nLine=1; z[k]; k++) if( z[k]=='\n' ) nLine++; if( nLine>100000000 ) fossil_fatal("too many command-line arguments"); nArg = g.argc + nLine*2; newArgv = fossil_malloc( sizeof(char*)*nArg ); for(j=0; j<i; j++) newArgv[j] = g.argv[j]; blob_rewind(&file); | | > > > > > > | 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 | for(k=0, nLine=1; z[k]; k++) if( z[k]=='\n' ) nLine++; if( nLine>100000000 ) fossil_fatal("too many command-line arguments"); nArg = g.argc + nLine*2; newArgv = fossil_malloc( sizeof(char*)*nArg ); for(j=0; j<i; j++) newArgv[j] = g.argv[j]; blob_rewind(&file); while( nLine-->0 && (n = blob_line(&file, &line))>0 ){ /* Reminder: ^^^ nLine check avoids that embedded NUL bytes in the ** --args file causes nLine to be less than blob_line() will end ** up reporting, as such a miscount leads to an illegal memory ** write. See forum post ** https://fossil-scm.org/forum/forumpost/7b34eecc1b8c for ** details */ if( n<1 ){ /* Reminder: corner-case: a line with 1 byte and no newline. */ continue; } z = blob_buffer(&line); if('\n'==z[n-1]){ z[n-1] = 0; |
︙ | ︙ | |||
665 666 667 668 669 670 671 672 673 674 675 676 677 678 | ** being called by separate invocations of fossil_main(). */ int fossil_main(int argc, char **argv){ const char *zCmdName = "unknown"; const CmdOrPage *pCmd = 0; int rc; #if !defined(_WIN32_WCE) if( fossil_getenv("FOSSIL_BREAK") ){ if( isatty(0) && isatty(2) ){ fprintf(stderr, "attach debugger to process %d and press any key to continue.\n", GETPID()); fgetc(stdin); | > | 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 | ** being called by separate invocations of fossil_main(). */ int fossil_main(int argc, char **argv){ const char *zCmdName = "unknown"; const CmdOrPage *pCmd = 0; int rc; g.zPhase = "init"; #if !defined(_WIN32_WCE) if( fossil_getenv("FOSSIL_BREAK") ){ if( isatty(0) && isatty(2) ){ fprintf(stderr, "attach debugger to process %d and press any key to continue.\n", GETPID()); fgetc(stdin); |
︙ | ︙ | |||
949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 | rc = Th_CommandHook(pCmd->zName, pCmd->eCmdFlags); }else{ rc = TH_OK; } if( rc==TH_OK || rc==TH_RETURN || rc==TH_CONTINUE ){ if( rc==TH_OK || rc==TH_RETURN ){ #endif pCmd->xFunc(); #ifdef FOSSIL_ENABLE_TH1_HOOKS } if( !g.isHTTP && !g.fNoThHook && (rc==TH_OK || rc==TH_CONTINUE) ){ Th_CommandNotify(pCmd->zName, pCmd->eCmdFlags); } } #endif | > > | 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 | rc = Th_CommandHook(pCmd->zName, pCmd->eCmdFlags); }else{ rc = TH_OK; } if( rc==TH_OK || rc==TH_RETURN || rc==TH_CONTINUE ){ if( rc==TH_OK || rc==TH_RETURN ){ #endif g.zPhase = pCmd->zName; pCmd->xFunc(); g.zPhase = "shutdown"; #ifdef FOSSIL_ENABLE_TH1_HOOKS } if( !g.isHTTP && !g.fNoThHook && (rc==TH_OK || rc==TH_CONTINUE) ){ Th_CommandNotify(pCmd->zName, pCmd->eCmdFlags); } } #endif |
︙ | ︙ | |||
1401 1402 1403 1404 1405 1406 1407 | }else{ g.zBaseURL = mprintf("http://%s%.*s", z, i, zCur); g.zTop = &g.zBaseURL[7+strlen(z)]; g.zHttpsURL = mprintf("https://%s%.*s", z, i, zCur); } fossil_free(z); } | > > > > > > > > > > > > > | | 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 | }else{ g.zBaseURL = mprintf("http://%s%.*s", z, i, zCur); g.zTop = &g.zBaseURL[7+strlen(z)]; g.zHttpsURL = mprintf("https://%s%.*s", z, i, zCur); } fossil_free(z); } /* Try to record the base URL as a CONFIG table entry with a name ** of the form: "baseurl:BASE". This keeps a record of how the ** the repository is used as a server, to help in answering questions ** like "where is the CGI script that references this repository?" ** ** This is just a logging hint. So don't worry if it cannot be done. ** Don't try this if the repository database is not writable, for ** example. ** ** If g.useLocalauth is set, that (probably) means that we are running ** "fossil ui" and there is no point in logging those cases either. */ if( db_is_writeable("repository") && !g.useLocalauth ){ int nBase = (int)strlen(g.zBaseURL); char *zBase = g.zBaseURL; if( g.nExtraURL>0 && g.nExtraURL<nBase-6 ){ zBase = fossil_strndup(g.zBaseURL, nBase - g.nExtraURL); } db_unprotect(PROTECT_CONFIG); if( !db_exists("SELECT 1 FROM config WHERE name='baseurl:%q'", zBase)){ |
︙ | ︙ | |||
1506 1507 1508 1509 1510 1511 1512 | size_t size; char **strings; size_t i; Blob out; size = backtrace(array, sizeof(array)/sizeof(array[0])); strings = backtrace_symbols(array, size); blob_init(&out, 0, 0); | | | > | 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 | size_t size; char **strings; size_t i; Blob out; size = backtrace(array, sizeof(array)/sizeof(array[0])); strings = backtrace_symbols(array, size); blob_init(&out, 0, 0); blob_appendf(&out, "Segfault during %s", g.zPhase); for(i=0; i<size; i++){ blob_appendf(&out, "\n(%d) %s", i, strings[i]); } fossil_panic("%s", blob_str(&out)); #else fossil_panic("Segfault during %s", g.zPhase); #endif exit(1); } /* ** Called if a server gets a SIGPIPE. This often happens when a client ** webbrowser opens a connection but never sends the HTTP request */ void sigpipe_handler(int x){ #ifndef _WIN32 if( g.fAnyTrace ){ fprintf(stderr,"/***** sigpipe received by subprocess %d ****\n", getpid()); } #endif g.zPhase = "sigpipe shutdown"; db_panic_close(); exit(1); } /* ** Return true if it is appropriate to redirect requests to HTTPS. ** |
︙ | ︙ | |||
1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 | ){ const char *zPathInfo = PD("PATH_INFO", ""); char *zPath = NULL; int i; const CmdOrPage *pCmd = 0; const char *zBase = g.zRepositoryName; #if !defined(_WIN32) signal(SIGSEGV, sigsegv_handler); #endif /* Handle universal query parameters */ if( PB("utc") ){ g.fTimeFormat = 1; | > | 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 | ){ const char *zPathInfo = PD("PATH_INFO", ""); char *zPath = NULL; int i; const CmdOrPage *pCmd = 0; const char *zBase = g.zRepositoryName; g.zPhase = "process_one_web_page"; #if !defined(_WIN32) signal(SIGSEGV, sigsegv_handler); #endif /* Handle universal query parameters */ if( PB("utc") ){ g.fTimeFormat = 1; |
︙ | ︙ | |||
1822 1823 1824 1825 1826 1827 1828 | /* At this point, the appropriate repository database file will have ** been opened. */ /* | | | | < | < < < < < | 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 | /* At this point, the appropriate repository database file will have ** been opened. */ /* ** Check to see if the first term of PATH_INFO specifies an ** alternative skin. This will be the case if the first term of ** PATH_INFO begins with "draftN/" where N is an integer between 1 ** and 9. If so, activate the skin associated with that draft. */ if( zPathInfo && strncmp(zPathInfo,"/draft",6)==0 && zPathInfo[6]>='1' && zPathInfo[6]<='9' && (zPathInfo[7]=='/' || zPathInfo[7]==0) ){ int iSkin = zPathInfo[6] - '0'; char *zNewScript; |
︙ | ︙ | |||
2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 | rc = Th_WebpageHook(pCmd->zName+1, pCmd->eCmdFlags); }else{ rc = TH_OK; } if( rc==TH_OK || rc==TH_RETURN || rc==TH_CONTINUE ){ if( rc==TH_OK || rc==TH_RETURN ){ #endif pCmd->xFunc(); #ifdef FOSSIL_ENABLE_TH1_HOOKS } if( !g.fNoThHook && (rc==TH_OK || rc==TH_CONTINUE) ){ Th_WebpageNotify(pCmd->zName+1, pCmd->eCmdFlags); } } } #endif } /* Return the result. */ cgi_reply(); } /* If the CGI program contains one or more lines of the form ** ** redirect: repository-filename http://hostname/path/%s ** | > > | 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 | rc = Th_WebpageHook(pCmd->zName+1, pCmd->eCmdFlags); }else{ rc = TH_OK; } if( rc==TH_OK || rc==TH_RETURN || rc==TH_CONTINUE ){ if( rc==TH_OK || rc==TH_RETURN ){ #endif g.zPhase = pCmd->zName; pCmd->xFunc(); #ifdef FOSSIL_ENABLE_TH1_HOOKS } if( !g.fNoThHook && (rc==TH_OK || rc==TH_CONTINUE) ){ Th_WebpageNotify(pCmd->zName+1, pCmd->eCmdFlags); } } } #endif } /* Return the result. */ g.zPhase = "web-page reply"; cgi_reply(); } /* If the CGI program contains one or more lines of the form ** ** redirect: repository-filename http://hostname/path/%s ** |
︙ | ︙ | |||
2726 2727 2728 2729 2730 2731 2732 | ** ** COMMAND: test-http ** ** Works like the [[http]] command but gives setup permission to all users. ** ** Options: ** --th-trace Trace TH1 execution (for debugging purposes) | | | | 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 | ** ** COMMAND: test-http ** ** Works like the [[http]] command but gives setup permission to all users. ** ** Options: ** --th-trace Trace TH1 execution (for debugging purposes) ** --usercap CAP User capability string (Default: "sxy") ** */ void cmd_test_http(void){ const char *zIpAddr; /* IP address of remote client */ const char *zUserCap; Th_InitTraceLog(); zUserCap = find_option("usercap",0,1); if( zUserCap==0 ){ g.useLocalauth = 1; zUserCap = "sxy"; } login_set_capabilities(zUserCap, 0); g.httpIn = stdin; g.httpOut = stdout; fossil_binary_mode(g.httpOut); fossil_binary_mode(g.httpIn); g.zExtRoot = find_option("extroot",0,1); |
︙ | ︙ | |||
2766 2767 2768 2769 2770 2771 2772 2773 | } /* ** Respond to a SIGALRM by writing a message to the error log (if there ** is one) and exiting. */ #ifndef _WIN32 static void sigalrm_handler(int x){ | > > > | > > > | | | > > > > > > > > > > > | | > > > > | 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 | } /* ** Respond to a SIGALRM by writing a message to the error log (if there ** is one) and exiting. */ #ifndef _WIN32 static int nAlarmSeconds = 0; static void sigalrm_handler(int x){ sqlite3_uint64 tmUser = 0, tmKernel = 0; fossil_cpu_times(&tmUser, &tmKernel); fossil_panic("Timeout after %d seconds during %s" " - user %,llu µs, sys %,llu µs", nAlarmSeconds, g.zPhase, tmUser, tmKernel); } #endif /* ** Arrange to timeout using SIGALRM after N seconds. Or if N==0, cancel ** any pending timeout. ** ** Bugs: ** (1) This only works on unix systems. ** (2) Any call to sleep() or sqlite3_sleep() will cancel the alarm. */ void fossil_set_timeout(int N){ #ifndef _WIN32 signal(SIGALRM, sigalrm_handler); alarm(N); nAlarmSeconds = N; #endif } /* ** COMMAND: server* ** COMMAND: ui ** ** Usage: %fossil server ?OPTIONS? ?REPOSITORY? ** or: %fossil ui ?OPTIONS? ?REPOSITORY? ** ** Open a socket and begin listening and responding to HTTP requests on ** TCP port 8080, or on any other TCP port defined by the -P or ** --port option. The optional REPOSITORY argument is the name of the ** Fossil repository to be served. The REPOSITORY argument may be omitted ** if the working directory is within an open checkout, in which case the ** repository associated with that checkout is used. ** ** The "ui" command automatically starts a web browser after initializing ** the web server. The "ui" command also binds to 127.0.0.1 and so will ** only process HTTP traffic from the local machine. ** ** If REPOSITORY is a directory name which is the root of a ** checkout, then use the repository associated with that checkout. ** This only works for the "fossil ui" command, not the "fossil server" ** command. ** ** If REPOSITORY begins with a "HOST:" or "USER@HOST:" prefix, then ** the command is run on the remote host specified and the results are ** tunneled back to the local machine via SSH. This feature only works for ** the "fossil ui" command, not the "fossil server" command. ** ** REPOSITORY may also be a directory (aka folder) that contains one or ** more repositories with names ending in ".fossil". In this case, a ** prefix of the URL pathname is used to search the directory for an ** appropriate repository. To thwart mischief, the pathname in the URL must ** contain only alphanumerics, "_", "/", "-", and ".", and no "-" may ** occur after "/", and every "." must be surrounded on both sides by ** alphanumerics. Any pathname that does not satisfy these constraints ** results in a 404 error. Files in REPOSITORY that match the comma-separated ** list of glob patterns given by --files and that have known suffixes ** such as ".txt" or ".html" or ".jpeg" and do not match the pattern ** "*.fossil*" will be served as static content. With the "ui" command, ** the REPOSITORY can only be a directory if the --notfound option is ** also present. ** ** For the special case REPOSITORY name of "/", the global configuration ** database is consulted for a list of all known repositories. The --repolist ** option is implied by this special case. See also the "fossil all ui" ** command. ** ** By default, the "ui" command provides full administrative access without ** having to log in. This can be disabled by turning off the "localauth" ** setting. Automatic login for the "server" command is available if the ** --localauth option is present and the "localauth" setting is off and the ** connection is from localhost. The "ui" command also enables --repolist ** by default. ** ** Options: ** --baseurl URL Use URL as the base (useful for reverse proxies) ** --ckout-alias NAME Treat URIs of the form /doc/NAME/... as if they were ** /doc/ckout/... ** --create Create a new REPOSITORY if it does not already exist ** --extroot DIR Document root for the /ext extension mechanism ** --files GLOBLIST Comma-separated list of glob patterns for static files ** --fossilcmd PATH Full pathname of the "fossil" executable on the remote ** system when REPOSITORY is remote. Default: "fossil" ** --localauth enable automatic login for requests from localhost ** --localhost listen on 127.0.0.1 only (always true for "ui") ** --https Indicates that the input is coming through a reverse ** proxy that has already translated HTTPS into HTTP. ** --jsmode MODE Determine how JavaScript is delivered with pages. ** Mode can be one of: ** inline All JavaScript is inserted inline at ** the end of the HTML file. ** separate Separate HTTP requests are made for ** each JavaScript file. ** bundled One single separate HTTP fetches all ** JavaScript concatenated together. ** Depending on the needs of any given page, inline ** and bundled modes might result in a single ** amalgamated script or several, but both approaches ** result in fewer HTTP requests than the separate mode. ** --max-latency N Do not let any single HTTP request run for more than N ** seconds (only works on unix) ** --nobrowser Do not automatically launch a web-browser for the ** "fossil ui" command. ** --nocompress Do not compress HTTP replies ** --nojail Drop root privileges but do not enter the chroot jail ** --nossl signal that no SSL connections are available (Always ** set by default for the "ui" command) ** --notfound URL Redirect ** --page PAGE Start "ui" on PAGE. ex: --page "timeline?y=ci" ** -P|--port TCPPORT listen to request on port TCPPORT |
︙ | ︙ | |||
2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 | const char *zTimeout = 0; /* Max runtime of any single HTTP request */ #endif int allowRepoList; /* List repositories on URL "/" */ const char *zAltBase; /* Argument to the --baseurl option */ const char *zFileGlob; /* Static content must match this */ char *zIpAddr = 0; /* Bind to this IP address */ int fCreate = 0; /* The --create flag */ const char *zInitPage = 0; /* Start on this page. --page option */ #if defined(_WIN32) const char *zStopperFile; /* Name of file used to terminate server */ zStopperFile = find_option("stopper", 0, 1); #endif if( g.zErrlog==0 ){ g.zErrlog = "-"; } g.zExtRoot = find_option("extroot",0,1); | > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > | 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 | const char *zTimeout = 0; /* Max runtime of any single HTTP request */ #endif int allowRepoList; /* List repositories on URL "/" */ const char *zAltBase; /* Argument to the --baseurl option */ const char *zFileGlob; /* Static content must match this */ char *zIpAddr = 0; /* Bind to this IP address */ int fCreate = 0; /* The --create flag */ int fNoBrowser = 0; /* Do not auto-launch web-browser */ const char *zInitPage = 0; /* Start on this page. --page option */ int findServerArg = 2; /* argv index for find_server_repository() */ char *zRemote = 0; /* Remote host on which to run "fossil ui" */ const char *zJsMode; /* The --jsmode parameter */ const char *zFossilCmd =0; /* Name of "fossil" binary on remote system */ #if defined(_WIN32) const char *zStopperFile; /* Name of file used to terminate server */ zStopperFile = find_option("stopper", 0, 1); #endif if( g.zErrlog==0 ){ g.zErrlog = "-"; } g.zExtRoot = find_option("extroot",0,1); zJsMode = find_option("jsmode",0,1); builtin_set_js_delivery_mode(zJsMode,0); zFileGlob = find_option("files-urlenc",0,1); if( zFileGlob ){ char *z = mprintf("%s", zFileGlob); dehttpize(z); zFileGlob = z; }else{ zFileGlob = find_option("files",0,1); } skin_override(); #if !defined(_WIN32) noJail = find_option("nojail",0,0)!=0; zTimeout = find_option("max-latency",0,1); #endif g.useLocalauth = find_option("localauth", 0, 0)!=0; Th_InitTraceLog(); zPort = find_option("port", "P", 1); isUiCmd = g.argv[1][0]=='u'; if( isUiCmd ){ zInitPage = find_option("page", 0, 1); if( zInitPage && zInitPage[0]=='/' ) zInitPage++; zFossilCmd = find_option("fossilcmd", 0, 1); } zNotFound = find_option("notfound", 0, 1); allowRepoList = find_option("repolist",0,0)!=0; if( find_option("nocompress",0,0)!=0 ) g.fNoHttpCompress = 1; zAltBase = find_option("baseurl", 0, 1); fCreate = find_option("create",0,0)!=0; if( find_option("scgi", 0, 0)!=0 ) flags |= HTTP_SERVER_SCGI; if( zAltBase ){ set_base_url(zAltBase); } g.sslNotAvailable = find_option("nossl", 0, 0)!=0 || isUiCmd; fNoBrowser = find_option("nobrowser", 0, 0)!=0; if( find_option("https",0,0)!=0 ){ cgi_replace_parameter("HTTPS","on"); } if( find_option("localhost", 0, 0)!=0 ){ flags |= HTTP_SERVER_LOCALHOST; } g.zCkoutAlias = find_option("ckout-alias",0,1); g.zMainMenuFile = find_option("mainmenu",0,1); if( g.zMainMenuFile!=0 && file_size(g.zMainMenuFile,ExtFILE)<0 ){ fossil_fatal("Cannot read --mainmenu file %s", g.zMainMenuFile); } /* We should be done with options.. */ verify_all_options(); if( g.argc!=2 && g.argc!=3 ) usage("?REPOSITORY?"); if( isUiCmd && 3==g.argc && file_isdir(g.argv[2], ExtFILE)>0 ){ /* If REPOSITORY arg is the root of a checkout, ** chdir to that checkout so that the current version ** gets highlighted in the timeline by default. */ const char * zDir = g.argv[2]; if(dir_has_ckout_db(zDir)){ if(0!=file_chdir(zDir, 0)){ fossil_fatal("Cannot chdir to %s", zDir); } findServerArg = 99; fCreate = 0; g.argv[2] = 0; --g.argc; } } if( isUiCmd && 3==g.argc && (zRemote = (char*)file_skip_userhost(g.argv[2]))!=0 ){ /* The REPOSITORY argument has a USER@HOST: or HOST: prefix */ const char *zRepoTail = file_skip_userhost(g.argv[2]); unsigned x; int n; sqlite3_randomness(2,&x); zPort = mprintf("%d", 8100+(x%32000)); n = (int)(zRepoTail - g.argv[2]) - 1; zRemote = mprintf("%.*s", n, g.argv[2]); g.argv[2] = (char*)zRepoTail; } if( isUiCmd ){ flags |= HTTP_SERVER_LOCALHOST|HTTP_SERVER_REPOLIST; g.useLocalauth = 1; allowRepoList = 1; } if( !zRemote ){ find_server_repository(findServerArg, fCreate); } if( zInitPage==0 ){ if( isUiCmd && g.localOpen ){ zInitPage = "timeline?c=current"; }else{ zInitPage = ""; } } |
︙ | ︙ | |||
2977 2978 2979 2980 2981 2982 2983 | } } iPort = mxPort = atoi(zPort); }else{ iPort = db_get_int("http-port", 8080); mxPort = iPort+100; } | < < | > > | < | > | > > > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | > > > > > > | 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 | } } iPort = mxPort = atoi(zPort); }else{ iPort = db_get_int("http-port", 8080); mxPort = iPort+100; } if( isUiCmd && !fNoBrowser ){ char *zBrowserArg; if( zRemote ) db_open_config(0,0); zBrowser = fossil_web_browser(); if( zIpAddr==0 ){ zBrowserArg = mprintf("http://localhost:%%d/%s", zInitPage); }else if( strchr(zIpAddr,':') ){ zBrowserArg = mprintf("http://[%s]:%%d/%s", zIpAddr, zInitPage); }else{ zBrowserArg = mprintf("http://%s:%%d/%s", zIpAddr, zInitPage); } #ifdef _WIN32 zBrowserCmd = mprintf("%s %s &", zBrowser, zBrowserArg); #else zBrowserCmd = mprintf("%s %!$ &", zBrowser, zBrowserArg); #endif fossil_free(zBrowserArg); } if( zRemote ){ /* If a USER@HOST:REPO argument is supplied, then use SSH to run ** "fossil ui --nobrowser" on the remote system and to set up a ** tunnel from the local machine to the remote. */ FILE *sshIn; Blob ssh; char zLine[1000]; blob_init(&ssh, 0, 0); transport_ssh_command(&ssh); db_close_config(); if( zFossilCmd==0 ) zFossilCmd = "fossil"; blob_appendf(&ssh, " -t -L 127.0.0.1:%d:127.0.0.1:%d %!$" " %$ ui --nobrowser --localauth --port %d", iPort, iPort, zRemote, zFossilCmd, iPort); if( zNotFound ) blob_appendf(&ssh, " --notfound %!$", zNotFound); if( zFileGlob ) blob_appendf(&ssh, " --files-urlenc %T", zFileGlob); if( g.zCkoutAlias ) blob_appendf(&ssh, " --ckout-alias %!$",g.zCkoutAlias); if( g.zExtRoot ) blob_appendf(&ssh, " --extroot %$", g.zExtRoot); if( skin_in_use() ) blob_appendf(&ssh, " --skin %s", skin_in_use()); if( zJsMode ) blob_appendf(&ssh, " --jsmode %s", zJsMode); if( fCreate ) blob_appendf(&ssh, " --create"); blob_appendf(&ssh, " %$", g.argv[2]); fossil_print("%s\n", blob_str(&ssh)); sshIn = popen(blob_str(&ssh), "r"); if( sshIn==0 ){ fossil_fatal("unable to %s", blob_str(&ssh)); } while( fgets(zLine, sizeof(zLine), sshIn) ){ fputs(zLine, stdout); fflush(stdout); if( zBrowserCmd && sqlite3_strglob("*Listening for HTTP*",zLine)==0 ){ char *zCmd = mprintf(zBrowserCmd/*works-like:"%d"*/,iPort); fossil_system(zCmd); fossil_free(zCmd); fossil_free(zBrowserCmd); zBrowserCmd = 0; } } pclose(sshIn); fossil_free(zBrowserCmd); return; } #if !defined(_WIN32) /* Unix implementation */ if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY; if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT; db_close(1); if( cgi_http_server(iPort, mxPort, zBrowserCmd, zIpAddr, flags) ){ fossil_fatal("unable to listen on TCP socket %d", iPort); } /* For the parent process, the cgi_http_server() command above never |
︙ | ︙ | |||
3042 3043 3044 3045 3046 3047 3048 | process_one_web_page(zNotFound, glob_create(zFileGlob), allowRepoList); if( g.fAnyTrace ){ fprintf(stderr, "/***** Webpage finished in subprocess %d *****/\n", getpid()); } #else /* Win32 implementation */ | < < < < < < < < < < < < < | 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 | process_one_web_page(zNotFound, glob_create(zFileGlob), allowRepoList); if( g.fAnyTrace ){ fprintf(stderr, "/***** Webpage finished in subprocess %d *****/\n", getpid()); } #else /* Win32 implementation */ if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY; if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT; db_close(1); if( allowRepoList ){ flags |= HTTP_SERVER_REPOLIST; } if( win32_http_service(iPort, zAltBase, zNotFound, zFileGlob, flags) ){ |
︙ | ︙ | |||
3130 3131 3132 3133 3134 3135 3136 | style_submenu_element("Error Log","%R/errorlog"); if( iCase<1 || iCase>4 ){ @ <p>Generate a message to the <a href="%R/errorlog">error log</a> @ by clicking on one of the following cases: }else{ @ <p>This is the test page for case=%d(iCase). All possible cases: } | | | 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 | style_submenu_element("Error Log","%R/errorlog"); if( iCase<1 || iCase>4 ){ @ <p>Generate a message to the <a href="%R/errorlog">error log</a> @ by clicking on one of the following cases: }else{ @ <p>This is the test page for case=%d(iCase). All possible cases: } for(i=1; i<=8; i++){ @ <a href='./test-warning?case=%d(i)'>[%d(i)]</a> } @ </p> @ <p><ol> @ <li value='1'> Call fossil_warning() if( iCase==1 ){ fossil_warning("Test warning message from /test-warning"); |
︙ | ︙ | |||
3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 | if( iCase==6 ){ webpage_assert( 5==7 ); } @ <li value='7'> call webpage_error()" if( iCase==7 ){ cgi_reset_content(); webpage_error("Case 7 from /test-warning"); } @ </ol> @ <p>End of test</p> style_finish_page(); } | > > > > > > | 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 | if( iCase==6 ){ webpage_assert( 5==7 ); } @ <li value='7'> call webpage_error()" if( iCase==7 ){ cgi_reset_content(); webpage_error("Case 7 from /test-warning"); } @ <li value='8'> simulated timeout" if( iCase==8 ){ fossil_set_timeout(1); cgi_reset_content(); sqlite3_sleep(1100); } @ </ol> @ <p>End of test</p> style_finish_page(); } |
Changes to src/main.mk.
︙ | ︙ | |||
102 103 104 105 106 107 108 109 110 111 112 113 114 115 | $(SRCDIR)/markdown.c \ $(SRCDIR)/markdown_html.c \ $(SRCDIR)/md5.c \ $(SRCDIR)/merge.c \ $(SRCDIR)/merge3.c \ $(SRCDIR)/moderate.c \ $(SRCDIR)/name.c \ $(SRCDIR)/path.c \ $(SRCDIR)/piechart.c \ $(SRCDIR)/pikchr.c \ $(SRCDIR)/pikchrshow.c \ $(SRCDIR)/pivot.c \ $(SRCDIR)/popen.c \ $(SRCDIR)/pqueue.c \ | > | 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | $(SRCDIR)/markdown.c \ $(SRCDIR)/markdown_html.c \ $(SRCDIR)/md5.c \ $(SRCDIR)/merge.c \ $(SRCDIR)/merge3.c \ $(SRCDIR)/moderate.c \ $(SRCDIR)/name.c \ $(SRCDIR)/patch.c \ $(SRCDIR)/path.c \ $(SRCDIR)/piechart.c \ $(SRCDIR)/pikchr.c \ $(SRCDIR)/pikchrshow.c \ $(SRCDIR)/pivot.c \ $(SRCDIR)/popen.c \ $(SRCDIR)/pqueue.c \ |
︙ | ︙ | |||
359 360 361 362 363 364 365 366 367 368 369 370 371 372 | $(OBJDIR)/markdown_.c \ $(OBJDIR)/markdown_html_.c \ $(OBJDIR)/md5_.c \ $(OBJDIR)/merge_.c \ $(OBJDIR)/merge3_.c \ $(OBJDIR)/moderate_.c \ $(OBJDIR)/name_.c \ $(OBJDIR)/path_.c \ $(OBJDIR)/piechart_.c \ $(OBJDIR)/pikchr_.c \ $(OBJDIR)/pikchrshow_.c \ $(OBJDIR)/pivot_.c \ $(OBJDIR)/popen_.c \ $(OBJDIR)/pqueue_.c \ | > | 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 | $(OBJDIR)/markdown_.c \ $(OBJDIR)/markdown_html_.c \ $(OBJDIR)/md5_.c \ $(OBJDIR)/merge_.c \ $(OBJDIR)/merge3_.c \ $(OBJDIR)/moderate_.c \ $(OBJDIR)/name_.c \ $(OBJDIR)/patch_.c \ $(OBJDIR)/path_.c \ $(OBJDIR)/piechart_.c \ $(OBJDIR)/pikchr_.c \ $(OBJDIR)/pikchrshow_.c \ $(OBJDIR)/pivot_.c \ $(OBJDIR)/popen_.c \ $(OBJDIR)/pqueue_.c \ |
︙ | ︙ | |||
508 509 510 511 512 513 514 515 516 517 518 519 520 521 | $(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)/piechart.o \ $(OBJDIR)/pikchr.o \ $(OBJDIR)/pikchrshow.o \ $(OBJDIR)/pivot.o \ $(OBJDIR)/popen.o \ $(OBJDIR)/pqueue.o \ | > | 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 | $(OBJDIR)/markdown.o \ $(OBJDIR)/markdown_html.o \ $(OBJDIR)/md5.o \ $(OBJDIR)/merge.o \ $(OBJDIR)/merge3.o \ $(OBJDIR)/moderate.o \ $(OBJDIR)/name.o \ $(OBJDIR)/patch.o \ $(OBJDIR)/path.o \ $(OBJDIR)/piechart.o \ $(OBJDIR)/pikchr.o \ $(OBJDIR)/pikchrshow.o \ $(OBJDIR)/pivot.o \ $(OBJDIR)/popen.o \ $(OBJDIR)/pqueue.o \ |
︙ | ︙ | |||
847 848 849 850 851 852 853 854 855 856 857 858 859 860 | $(OBJDIR)/markdown_.c:$(OBJDIR)/markdown.h \ $(OBJDIR)/markdown_html_.c:$(OBJDIR)/markdown_html.h \ $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h \ $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h \ $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h \ $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h \ $(OBJDIR)/name_.c:$(OBJDIR)/name.h \ $(OBJDIR)/path_.c:$(OBJDIR)/path.h \ $(OBJDIR)/piechart_.c:$(OBJDIR)/piechart.h \ $(OBJDIR)/pikchr_.c:$(OBJDIR)/pikchr.h \ $(OBJDIR)/pikchrshow_.c:$(OBJDIR)/pikchrshow.h \ $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \ $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \ $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \ | > | 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 | $(OBJDIR)/markdown_.c:$(OBJDIR)/markdown.h \ $(OBJDIR)/markdown_html_.c:$(OBJDIR)/markdown_html.h \ $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h \ $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h \ $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h \ $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h \ $(OBJDIR)/name_.c:$(OBJDIR)/name.h \ $(OBJDIR)/patch_.c:$(OBJDIR)/patch.h \ $(OBJDIR)/path_.c:$(OBJDIR)/path.h \ $(OBJDIR)/piechart_.c:$(OBJDIR)/piechart.h \ $(OBJDIR)/pikchr_.c:$(OBJDIR)/pikchr.h \ $(OBJDIR)/pikchrshow_.c:$(OBJDIR)/pikchrshow.h \ $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \ $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \ $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \ |
︙ | ︙ | |||
1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 | $(OBJDIR)/name_.c: $(SRCDIR)/name.c $(OBJDIR)/translate $(OBJDIR)/translate $(SRCDIR)/name.c >$@ $(OBJDIR)/name.o: $(OBJDIR)/name_.c $(OBJDIR)/name.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/name.o -c $(OBJDIR)/name_.c $(OBJDIR)/name.h: $(OBJDIR)/headers $(OBJDIR)/path_.c: $(SRCDIR)/path.c $(OBJDIR)/translate $(OBJDIR)/translate $(SRCDIR)/path.c >$@ $(OBJDIR)/path.o: $(OBJDIR)/path_.c $(OBJDIR)/path.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/path.o -c $(OBJDIR)/path_.c | > > > > > > > > | 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 | $(OBJDIR)/name_.c: $(SRCDIR)/name.c $(OBJDIR)/translate $(OBJDIR)/translate $(SRCDIR)/name.c >$@ $(OBJDIR)/name.o: $(OBJDIR)/name_.c $(OBJDIR)/name.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/name.o -c $(OBJDIR)/name_.c $(OBJDIR)/name.h: $(OBJDIR)/headers $(OBJDIR)/patch_.c: $(SRCDIR)/patch.c $(OBJDIR)/translate $(OBJDIR)/translate $(SRCDIR)/patch.c >$@ $(OBJDIR)/patch.o: $(OBJDIR)/patch_.c $(OBJDIR)/patch.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/patch.o -c $(OBJDIR)/patch_.c $(OBJDIR)/patch.h: $(OBJDIR)/headers $(OBJDIR)/path_.c: $(SRCDIR)/path.c $(OBJDIR)/translate $(OBJDIR)/translate $(SRCDIR)/path.c >$@ $(OBJDIR)/path.o: $(OBJDIR)/path_.c $(OBJDIR)/path.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/path.o -c $(OBJDIR)/path_.c |
︙ | ︙ |
Changes to src/makemake.tcl.
︙ | ︙ | |||
123 124 125 126 127 128 129 130 131 132 133 134 135 136 | markdown markdown_html md5 merge merge3 moderate name path piechart pikchr pikchrshow pivot popen pqueue | > | 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | markdown markdown_html md5 merge merge3 moderate name patch path piechart pikchr pikchrshow pivot popen pqueue |
︙ | ︙ |
Changes to src/markdown.c.
︙ | ︙ | |||
169 170 171 172 173 174 175 | /******************** * GLOBAL VARIABLES * ********************/ | | > > > > > < | < < < < < < < < < < < < < < < < < < < < < < | 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 | /******************** * GLOBAL VARIABLES * ********************/ /* block_tags -- recognised block tags, sorted by cmp_html_tag. ** ** When these HTML tags are separated from other text by newlines ** then they are rendered verbatim. Their content is not interpreted ** in any way. */ static const struct html_tag block_tags[] = { { "html", 4 }, { "pre", 3 }, { "script", 6 }, }; /*************************** * STATIC HELPER FUNCTIONS * ***************************/ /* build_ref_id -- collapse whitespace from input text to make it a ref id */ |
︙ | ︙ | |||
268 269 270 271 272 273 274 | } /* cmp_html_tag -- comparison function for bsearch() (stolen from discount) */ static int cmp_html_tag(const void *a, const void *b){ const struct html_tag *hta = a; const struct html_tag *htb = b; | | > > | > > | 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 | } /* cmp_html_tag -- comparison function for bsearch() (stolen from discount) */ static int cmp_html_tag(const void *a, const void *b){ const struct html_tag *hta = a; const struct html_tag *htb = b; int sz = hta->size; int c; if( htb->size<sz ) sz = htb->size; c = fossil_strnicmp(hta->text, htb->text, sz); if( c==0 ) c = hta->size - htb->size; return c; } /* find_block_tag -- returns the current block tag */ static const struct html_tag *find_block_tag(const char *data, size_t size){ size_t i = 0; struct html_tag key; |
︙ | ︙ | |||
1709 1710 1711 1712 1713 1714 1715 | size_t size ){ size_t i, w; /* assuming data[0]=='<' && data[1]=='/' already tested */ /* checking tag is a match */ | | | 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 | size_t size ){ size_t i, w; /* assuming data[0]=='<' && data[1]=='/' already tested */ /* checking tag is a match */ if( (tag->size+3)>size || fossil_strnicmp(data+2, tag->text, tag->size) || data[tag->size+2]!='>' ){ return 0; } /* checking white lines */ |
︙ | ︙ | |||
1795 1796 1797 1798 1799 1800 1801 | } } /* no special case recognised */ return 0; } | | | < | < < | < < < < < < < < < < < < < < < < < < < > > > > > > | > | 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 | } } /* no special case recognised */ return 0; } /* looking for an matching closing tag */ /* followed by a blank line */ i = 1; found = 0; while( i<size ){ i++; while( i<size && !(data[i-1]=='<' && data[i]=='/') ){ i++; } if( (i+2+curtag->size)>size ) break; j = htmlblock_end(curtag, data+i-1, size-i+1); if (j) { i += j-1; found = 1; break; } } if( !found ) return 0; /* the end of the block has been found */ if( strcmp(curtag->text,"html")==0 ){ /* Omit <html> tags */ enum mkd_autolink dummy; int k = tag_length(data, size, &dummy); blob_init(&work, data+k, i-(j+k)); }else{ blob_init(&work, data, i); } if( rndr->make.blockhtml ){ rndr->make.blockhtml(ob, &work, rndr->make.opaque); } return i; } |
︙ | ︙ |
Changes to src/markdown.md.
︙ | ︙ | |||
171 172 173 174 175 176 177 | > * For documents that begin with a top-level heading (ex: **# heading #**), > the heading is omitted from the body of the document and becomes the > document title displayed at the top of the Fossil page. [daringfireball.net]: http://daringfireball.net/projects/markdown/syntax <a name="intermap"></a> | | | 171 172 173 174 175 176 177 178 | > * For documents that begin with a top-level heading (ex: **# heading #**), > the heading is omitted from the body of the document and becomes the > document title displayed at the top of the Fossil page. [daringfireball.net]: http://daringfireball.net/projects/markdown/syntax <a name="intermap"></a> ## Interwiki Tag [Map](/intermap) |
Added src/patch.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 | /* ** Copyright (c) 2021 D. Richard Hipp ** ** This program is free software; you can redistribute it and/or ** modify it under the terms of the Simplified BSD License (also ** known as the "2-Clause License" or "FreeBSD License".) ** ** This program is distributed in the hope that it will be useful, ** but without any warranty; without even the implied warranty of ** merchantability or fitness for a particular purpose. ** ** Author contact information: ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ******************************************************************************* ** ** This file contains code used to implement the "diff" command */ #include "config.h" #include "patch.h" #include <assert.h> /* ** Try to compute the name of the computer on which this process ** is running. */ char *fossil_hostname(void){ FILE *in; char zBuf[200]; in = popen("hostname","r"); if( in ){ size_t n = fread(zBuf, 1, sizeof(zBuf)-1, in); while( n>0 && fossil_isspace(zBuf[n-1]) ){ n--; } if( n<0 ) n = 0; zBuf[n] = 0; pclose(in); return fossil_strdup(zBuf); } return 0; } /* ** Flags passed from the main patch_cmd() routine into subfunctions used ** to implement the various subcommands. */ #define PATCH_DRYRUN 0x0001 #define PATCH_VERBOSE 0x0002 #define PATCH_FORCE 0x0004 /* ** Implementation of the "readfile(X)" SQL function. The entire content ** of the checkout file named X is read and returned as a BLOB. */ static void readfileFunc( sqlite3_context *context, int argc, sqlite3_value **argv ){ const char *zName; Blob x; sqlite3_int64 sz; (void)(argc); /* Unused parameter */ zName = (const char*)sqlite3_value_text(argv[0]); if( zName==0 || (zName[0]=='-' && zName[1]==0) ) return; sz = blob_read_from_file(&x, zName, RepoFILE); sqlite3_result_blob64(context, x.aData, sz, SQLITE_TRANSIENT); blob_reset(&x); } /* ** mkdelta(X,Y) ** ** X is an numeric artifact id. Y is a filename. ** ** Compute a compressed delta that carries X into Y. Or return ** and zero-length blob if X is equal to Y. */ static void mkdeltaFunc( sqlite3_context *context, int argc, sqlite3_value **argv ){ const char *zFile; Blob x, y; int rid; char *aOut; int nOut; sqlite3_int64 sz; rid = sqlite3_value_int(argv[0]); if( !content_get(rid, &x) ){ sqlite3_result_error(context, "mkdelta(X,Y): no content for X", -1); return; } zFile = (const char*)sqlite3_value_text(argv[1]); if( zFile==0 ){ sqlite3_result_error(context, "mkdelta(X,Y): NULL Y argument", -1); blob_reset(&x); return; } sz = blob_read_from_file(&y, zFile, RepoFILE); if( sz<0 ){ sqlite3_result_error(context, "mkdelta(X,Y): cannot read file Y", -1); blob_reset(&x); return; } aOut = sqlite3_malloc64(sz+70); if( aOut==0 ){ sqlite3_result_error_nomem(context); blob_reset(&y); blob_reset(&x); return; } if( blob_size(&x)==blob_size(&y) && memcmp(blob_buffer(&x), blob_buffer(&y), blob_size(&x))==0 ){ blob_reset(&y); blob_reset(&x); sqlite3_result_blob64(context, "", 0, SQLITE_STATIC); return; } nOut = delta_create(blob_buffer(&x),blob_size(&x), blob_buffer(&y),blob_size(&y), aOut); blob_reset(&x); blob_reset(&y); blob_init(&x, aOut, nOut); blob_compress(&x, &x); sqlite3_result_blob64(context, blob_buffer(&x), blob_size(&x), SQLITE_TRANSIENT); blob_reset(&x); } /* ** Generate a binary patch file and store it into the file ** named zOut. */ void patch_create(unsigned mFlags, const char *zOut, FILE *out){ int vid; char *z; if( zOut && file_isdir(zOut, ExtFILE)!=0 ){ if( mFlags & PATCH_FORCE ){ file_delete(zOut); } if( file_isdir(zOut, ExtFILE)!=0 ){ fossil_fatal("patch file already exists: %s", zOut); } } add_content_sql_commands(g.db); deltafunc_init(g.db); sqlite3_create_function(g.db, "read_co_file", 1, SQLITE_UTF8, 0, readfileFunc, 0, 0); sqlite3_create_function(g.db, "mkdelta", 2, SQLITE_UTF8, 0, mkdeltaFunc, 0, 0); db_multi_exec("ATTACH %Q AS patch;", zOut ? zOut : ":memory:"); db_multi_exec( "PRAGMA patch.journal_mode=OFF;\n" "PRAGMA patch.page_size=512;\n" "CREATE TABLE patch.chng(\n" " pathname TEXT,\n" /* Filename */ " origname TEXT,\n" /* Name before rename. NULL if not renamed */ " hash TEXT,\n" /* Baseline hash. NULL for new files. */ " isexe BOOL,\n" /* True if executable */ " islink BOOL,\n" /* True if is a symbolic link */ " delta BLOB\n" /* compressed delta. NULL if deleted. ** length 0 if unchanged */ ");" "CREATE TABLE patch.cfg(\n" " key TEXT,\n" " value ANY\n" ");" ); vid = db_lget_int("checkout", 0); vfile_check_signature(vid, CKSIG_ENOTFILE); user_select(); db_multi_exec( "INSERT INTO patch.cfg(key,value)" "SELECT 'baseline',uuid FROM blob WHERE rid=%d " "UNION ALL" " SELECT 'ckout',rtrim(%Q,'/')" "UNION ALL" " SELECT 'repo',%Q " "UNION ALL" " SELECT 'user',%Q " "UNION ALL" " SELECT 'date',julianday('now')" "UNION ALL" " SELECT name,value FROM repository.config" " WHERE name IN ('project-code','project-name') " "UNION ALL" " SELECT 'fossil-date',julianday('" MANIFEST_DATE "')" ";", vid, g.zLocalRoot, g.zRepositoryName, g.zLogin); z = fossil_hostname(); if( z ){ db_multi_exec( "INSERT INTO patch.cfg(key,value)VALUES('hostname',%Q)", z); fossil_free(z); } /* New files */ db_multi_exec( "INSERT INTO patch.chng(pathname,hash,isexe,islink,delta)" " SELECT pathname, NULL, isexe, islink," " compress(read_co_file(%Q||pathname))" " FROM vfile WHERE rid==0;", g.zLocalRoot ); /* Deleted files */ db_multi_exec( "INSERT INTO patch.chng(pathname,hash,isexe,islink,delta)" " SELECT pathname, NULL, 0, 0, NULL" " FROM vfile WHERE deleted;" ); /* Changed files */ db_multi_exec( "INSERT INTO patch.chng(pathname,origname,hash,isexe,islink,delta)" " SELECT pathname, nullif(origname,pathname), blob.uuid, isexe, islink," " mkdelta(blob.rid, %Q||pathname)" " FROM vfile, blob" " WHERE blob.rid=vfile.rid" " AND NOT deleted AND (chnged OR origname<>pathname);", g.zLocalRoot ); /* Merges */ if( db_exists("SELECT 1 FROM localdb.vmerge WHERE id<=0") ){ db_multi_exec( "CREATE TABLE patch.patchmerge(type TEXT,mhash TEXT);\n" "WITH tmap(id,type) AS (VALUES(0,'merge'),(-1,'cherrypick')," "(-2,'backout'),(-4,'integrate'))" "INSERT INTO patch.patchmerge(type,mhash)" " SELECT tmap.type,vmerge.mhash FROM vmerge, tmap" " WHERE tmap.id=vmerge.id;" ); } /* Write the database to standard output if zOut==0 */ if( zOut==0 ){ sqlite3_int64 sz; unsigned char *pData; pData = sqlite3_serialize(g.db, "patch", &sz, 0); if( pData==0 ){ fossil_fatal("out of memory"); } #ifdef _WIN32 fflush(out); _setmode(_fileno(out), _O_BINARY); #endif fwrite(pData, sz, 1, out); sqlite3_free(pData); fflush(out); } } /* ** Attempt to load and validate a patchfile identified by the first ** argument. */ void patch_attach(const char *zIn, FILE *in){ Stmt q; if( g.db==0 ){ sqlite3_open(":memory:", &g.db); } if( zIn==0 ){ Blob buf; int rc; int sz; unsigned char *pData; blob_init(&buf, 0, 0); #ifdef _WIN32 _setmode(_fileno(in), _O_BINARY); #endif sz = blob_read_from_channel(&buf, in, -1); pData = (unsigned char*)blob_buffer(&buf); db_multi_exec("ATTACH ':memory:' AS patch"); if( g.fSqlTrace ){ fossil_trace("-- deserialize(\"patch\", pData, %lld);\n", sz); } rc = sqlite3_deserialize(g.db, "patch", pData, sz, sz, 0); if( rc ){ fossil_fatal("cannot open patch database: %s", sqlite3_errmsg(g.db)); } }else if( !file_isfile(zIn, ExtFILE) ){ fossil_fatal("no such file: %s", zIn); }else{ db_multi_exec("ATTACH %Q AS patch", zIn); } db_prepare(&q, "PRAGMA patch.quick_check"); while( db_step(&q)==SQLITE_ROW ){ if( fossil_strcmp(db_column_text(&q,0),"ok")!=0 ){ fossil_fatal("file %s is not a well-formed Fossil patchfile", zIn); } } db_finalize(&q); } /* ** Show a summary of the content of a patch on standard output */ void patch_view(unsigned mFlags){ Stmt q; db_prepare(&q, "WITH nmap(nkey,nm) AS (VALUES" "('baseline','BASELINE')," "('project-name','PROJECT-NAME'))" "SELECT nm, value FROM nmap, patch.cfg WHERE nkey=key;" ); while( db_step(&q)==SQLITE_ROW ){ fossil_print("%-12s %s\n", db_column_text(&q,0), db_column_text(&q,1)); } db_finalize(&q); if( mFlags & PATCH_VERBOSE ){ db_prepare(&q, "WITH nmap(nkey,nm,isDate) AS (VALUES" "('project-code','PROJECT-CODE',0)," "('date','TIMESTAMP',1)," "('user','USER',0)," "('hostname','HOSTNAME',0)," "('ckout','CHECKOUT',0)," "('repo','REPOSITORY',0))" "SELECT nm, CASE WHEN isDate THEN datetime(value) ELSE value END" " FROM nmap, patch.cfg WHERE nkey=key;" ); while( db_step(&q)==SQLITE_ROW ){ fossil_print("%-12s %s\n", db_column_text(&q,0), db_column_text(&q,1)); } db_finalize(&q); } if( db_table_exists("patch","patchmerge") ){ db_prepare(&q, "SELECT upper(type),mhash FROM patchmerge"); while( db_step(&q)==SQLITE_ROW ){ fossil_print("%-12s %s\n", db_column_text(&q,0), db_column_text(&q,1)); } db_finalize(&q); } db_prepare(&q, "SELECT pathname," /* 0: new name */ " hash IS NULL AND delta IS NOT NULL," /* 1: isNew */ " delta IS NULL," /* 2: isDeleted */ " origname" /* 3: old name or NULL */ " FROM patch.chng ORDER BY 1"); while( db_step(&q)==SQLITE_ROW ){ const char *zClass = "EDIT"; const char *zName = db_column_text(&q,0); const char *zOrigName = db_column_text(&q, 3); if( db_column_int(&q, 1) && zOrigName==0 ){ zClass = "NEW"; }else if( db_column_int(&q, 2) ){ zClass = zOrigName==0 ? "DELETE" : 0; } if( zOrigName!=0 && zOrigName[0]!=0 ){ fossil_print("%-12s %s -> %s\n", "RENAME",zOrigName,zName); } if( zClass ){ fossil_print("%-12s %s\n", zClass, zName); } } db_finalize(&q); } /* ** Apply the patch currently attached as database "patch". ** ** First update the check-out to be at "baseline". Then loop through ** and update all files. */ void patch_apply(unsigned mFlags){ Stmt q; Blob cmd; if( (mFlags & PATCH_FORCE)==0 && unsaved_changes(0) ){ fossil_fatal("there are unsaved changes in the current checkout"); } blob_init(&cmd, 0, 0); file_chdir(g.zLocalRoot, 0); db_prepare(&q, "SELECT patch.cfg.value" " FROM patch.cfg, localdb.vvar" " WHERE patch.cfg.key='baseline'" " AND localdb.vvar.name='checkout-hash'" " AND patch.cfg.key<>localdb.vvar.name" ); if( db_step(&q)==SQLITE_ROW ){ blob_append_escaped_arg(&cmd, g.nameOfExe, 1); blob_appendf(&cmd, " update %s", db_column_text(&q, 0)); if( mFlags & PATCH_VERBOSE ){ fossil_print("%-10s %s\n", "BASELINE", db_column_text(&q,0)); } } db_finalize(&q); if( blob_size(&cmd)>0 ){ if( mFlags & PATCH_DRYRUN ){ fossil_print("%s\n", blob_str(&cmd)); }else{ int rc = fossil_system(blob_str(&cmd)); if( rc ){ fossil_fatal("unable to update to the baseline check-out: %s", blob_str(&cmd)); } } } blob_reset(&cmd); if( db_table_exists("patch","patchmerge") ){ db_prepare(&q, "SELECT type, mhash, upper(type) FROM patch.patchmerge" " WHERE type IN ('merge','cherrypick','backout','integrate')" " AND mhash NOT GLOB '*[^a-fA-F0-9]*';" ); while( db_step(&q)==SQLITE_ROW ){ const char *zType = db_column_text(&q,0); blob_append_escaped_arg(&cmd, g.nameOfExe, 1); if( strcmp(zType,"merge")==0 ){ blob_appendf(&cmd, " merge %s\n", db_column_text(&q,1)); }else{ blob_appendf(&cmd, " merge --%s %s\n", zType, db_column_text(&q,1)); } if( mFlags & PATCH_VERBOSE ){ fossil_print("%-10s %s\n", db_column_text(&q,2), db_column_text(&q,0)); } } db_finalize(&q); if( mFlags & PATCH_DRYRUN ){ fossil_print("%s", blob_str(&cmd)); }else{ int rc = fossil_unsafe_system(blob_str(&cmd)); if( rc ){ fossil_fatal("unable to do merges:\n%s", blob_str(&cmd)); } } blob_reset(&cmd); } /* Deletions */ db_prepare(&q, "SELECT pathname FROM patch.chng" " WHERE origname IS NULL AND delta IS NULL"); while( db_step(&q)==SQLITE_ROW ){ blob_append_escaped_arg(&cmd, g.nameOfExe, 1); blob_appendf(&cmd, " rm --hard %$\n", db_column_text(&q,0)); if( mFlags & PATCH_VERBOSE ){ fossil_print("%-10s %s\n", "DELETE", db_column_text(&q,0)); } } db_finalize(&q); if( blob_size(&cmd)>0 ){ if( mFlags & PATCH_DRYRUN ){ fossil_print("%s", blob_str(&cmd)); }else{ int rc = fossil_unsafe_system(blob_str(&cmd)); if( rc ){ fossil_fatal("unable to do merges:\n%s", blob_str(&cmd)); } } blob_reset(&cmd); } /* Renames */ db_prepare(&q, "SELECT origname, pathname FROM patch.chng" " WHERE origname IS NOT NULL" " AND origname<>pathname" ); while( db_step(&q)==SQLITE_ROW ){ blob_append_escaped_arg(&cmd, g.nameOfExe, 1); blob_appendf(&cmd, " mv --hard %$ %$\n", db_column_text(&q,0), db_column_text(&q,1)); if( mFlags & PATCH_VERBOSE ){ fossil_print("%-10s %s -> %s\n", "RENAME", db_column_text(&q,0), db_column_text(&q,1)); } } db_finalize(&q); if( blob_size(&cmd)>0 ){ if( mFlags & PATCH_DRYRUN ){ fossil_print("%s", blob_str(&cmd)); }else{ int rc = fossil_unsafe_system(blob_str(&cmd)); if( rc ){ fossil_fatal("unable to rename files:\n%s", blob_str(&cmd)); } } blob_reset(&cmd); } /* Edits and new files */ db_prepare(&q, "SELECT pathname, hash, isexe, islink, delta FROM patch.chng" " WHERE delta IS NOT NULL" ); while( db_step(&q)==SQLITE_ROW ){ const char *zPathname = db_column_text(&q,0); const char *zHash = db_column_text(&q,1); int isExe = db_column_int(&q,2); int isLink = db_column_int(&q,3); Blob data; blob_init(&data, 0, 0); db_ephemeral_blob(&q, 4, &data); if( blob_size(&data) ){ blob_uncompress(&data, &data); } if( blob_size(&data)==0 ){ /* No changes to the file */ }else if( zHash ){ Blob basis; int rid = fast_uuid_to_rid(zHash); int outSize, sz; char *aOut; if( rid==0 ){ fossil_fatal("cannot locate basis artifact %s for %s", zHash, zPathname); } if( !content_get(rid, &basis) ){ fossil_fatal("cannot load basis artifact %d for %s", rid, zPathname); } outSize = delta_output_size(blob_buffer(&data),blob_size(&data)); if( outSize<=0 ){ fossil_fatal("malformed delta for %s", zPathname); } aOut = sqlite3_malloc64( outSize+1 ); if( aOut==0 ){ fossil_fatal("out of memory"); } sz = delta_apply(blob_buffer(&basis), blob_size(&basis), blob_buffer(&data), blob_size(&data), aOut); if( sz<0 ){ fossil_fatal("malformed delta for %s", zPathname); } blob_reset(&basis); blob_reset(&data); blob_append(&data, aOut, sz); sqlite3_free(aOut); if( mFlags & PATCH_VERBOSE ){ fossil_print("%-10s %s\n", "EDIT", zPathname); } }else{ blob_append_escaped_arg(&cmd, g.nameOfExe, 1); blob_appendf(&cmd, " add %$\n", zPathname); if( mFlags & PATCH_VERBOSE ){ fossil_print("%-10s %s\n", "NEW", zPathname); } } if( (mFlags & PATCH_DRYRUN)==0 ){ if( isLink ){ symlink_create(blob_str(&data), zPathname); }else{ blob_write_to_file(&data, zPathname); } file_setexe(zPathname, isExe); blob_reset(&data); } } db_finalize(&q); if( blob_size(&cmd)>0 ){ if( mFlags & PATCH_DRYRUN ){ fossil_print("%s", blob_str(&cmd)); }else{ int rc = fossil_system(blob_str(&cmd)); if( rc ){ fossil_fatal("unable to add new files:\n%s", blob_str(&cmd)); } } blob_reset(&cmd); } } /* ** This routine processes the ** ** ... [--dir64 DIR64] [DIRECTORY] FILENAME ** ** part of various "fossil patch" subcommands. ** ** Find and return the filename of the patch file to be used by ** "fossil patch apply" or "fossil patch create". Space to hold ** the returned name is obtained from fossil_malloc() and should ** be freed by the caller. ** ** If the name is "-" return NULL. The caller will interpret this ** to mean the patch is coming in over stdin or going out over ** stdout. ** ** If there is a prior DIRECTORY argument, or if ** the --dir64 option is present, first chdir to the specified ** directory, and adjust the path of FILENAME as appropriate so ** that it still points to the same file. ** ** The --dir64 option is undocumented. The argument to --dir64 ** is a base64-encoded directory name. The --dir64 option is used ** to transmit the directory as part of the command argument to ** a "ssh" command without having to worry about quoting ** any special characters in the filename. ** ** The returned name is obtained from fossil_malloc() and should ** be freed by the caller. */ static char *patch_find_patch_filename(const char *zCmdName){ const char *zDir64 = find_option("dir64",0,1); const char *zDir = 0; const char *zBaseName; char *zToFree = 0; char *zPatchFile = 0; if( zDir64 ){ int n = 0; zToFree = decode64(zDir64, &n); zDir = zToFree; } verify_all_options(); if( g.argc!=4 && g.argc!=5 ){ usage(mprintf("%s [DIRECTORY] FILENAME", zCmdName)); } if( g.argc==5 ){ zDir = g.argv[3]; zBaseName = g.argv[4]; }else{ zBaseName = g.argv[3]; } if( fossil_strcmp(zBaseName, "-")==0 ){ zPatchFile = 0; }else if( zDir ){ zPatchFile = file_canonical_name_dup(g.argv[4]); }else{ zPatchFile = fossil_strdup(g.argv[3]); } if( zDir && file_chdir(zDir,0) ){ fossil_fatal("cannot change to directory \"%s\"", zDir); } fossil_free(zToFree); return zPatchFile; } /* ** Create a FILE* that will execute the remote side of a push or pull ** using ssh (probably) or fossil for local pushes and pulls. Return ** a FILE* obtained from popen() into which we write the patch, or from ** which we read the patch, depending on whether this is a push or pull. */ static FILE *patch_remote_command( unsigned mFlags, /* flags */ const char *zThisCmd, /* "push" or "pull" */ const char *zRemoteCmd, /* "apply" or "create" */ const char *zRW /* "w" or "r" */ ){ char *zRemote; char *zDir; Blob cmd; FILE *f; const char *zForce = (mFlags & PATCH_FORCE)!=0 ? " -f" : ""; if( g.argc!=4 ){ usage(mprintf("%s [USER@]HOST:DIRECTORY", zThisCmd)); } zRemote = fossil_strdup(g.argv[3]); zDir = (char*)file_skip_userhost(zRemote); if( zDir==0 ){ zDir = zRemote; blob_init(&cmd, 0, 0); blob_append_escaped_arg(&cmd, g.nameOfExe, 1); blob_appendf(&cmd, " patch %s%s %$ -", zRemoteCmd, zForce, zDir); }else{ Blob remote; *(char*)(zDir-1) = 0; transport_ssh_command(&cmd); blob_appendf(&cmd, " -T"); blob_append_escaped_arg(&cmd, zRemote, 0); blob_init(&remote, 0, 0); blob_appendf(&remote, "fossil patch %s%s --dir64 %z -", zRemoteCmd, zForce, encode64(zDir, -1)); blob_append_escaped_arg(&cmd, blob_str(&remote), 0); blob_reset(&remote); } if( mFlags & PATCH_VERBOSE ){ fossil_print("# %s\n", blob_str(&cmd)); fflush(stdout); } f = popen(blob_str(&cmd), zRW); if( f==0 ){ fossil_fatal("cannot run command: %s", blob_str(&cmd)); } blob_reset(&cmd); return f; } /* ** Show a diff for the patch currently loaded into database "patch". */ static void patch_diff( unsigned mFlags, /* Patch flags. only -f is allowed */ const char *zDiffCmd, /* Command used for diffing */ const char *zBinGlob, /* GLOB pattern to determine binary files */ int fIncludeBinary, /* Do diffs against binary files */ u64 diffFlags /* Other diff flags */ ){ int nErr = 0; Stmt q; Blob empty; blob_zero(&empty); if( (mFlags & PATCH_FORCE)==0 ){ /* Check to ensure that the patch is against the repository that ** we have opened. ** ** To do: If there is a mismatch, should we scan all of the repositories ** listed in the global_config table looking for a match? */ if( db_exists( "SELECT 1 FROM patch.cfg" " WHERE cfg.key='baseline'" " AND NOT EXISTS(SELECT 1 FROM blob WHERE uuid=cfg.value)" )){ char *zBaseline; db_prepare(&q, "SELECT config.value, cfg.value FROM config, cfg" " WHERE config.name='project-name'" " AND cfg.key='project-name'" " AND config.value<>cfg.value" ); if( db_step(&q)==SQLITE_ROW ){ char *zRepo = fossil_strdup(db_column_text(&q,0)); char *zPatch = fossil_strdup(db_column_text(&q,1)); db_finalize(&q); fossil_fatal("the patch is against project \"%z\" but you are using " "project \"%z\"", zPatch, zRepo); } db_finalize(&q); zBaseline = db_text(0, "SELECT value FROM patch.cfg" " WHERE key='baseline'"); if( zBaseline ){ fossil_fatal("the baseline of the patch (check-in %S) is not found " "in the %s repository", zBaseline, g.zRepositoryName); } } } db_prepare(&q, "SELECT" " (SELECT blob.rid FROM blob WHERE blob.uuid=chng.hash)," " pathname," /* 1: new pathname */ " origname," /* 2: original pathname. Null if not renamed */ " delta," /* 3: delta. NULL if deleted. empty is no change */ " hash" /* 4: baseline hash */ " FROM patch.chng" " ORDER BY pathname" ); while( db_step(&q)==SQLITE_ROW ){ int rid; const char *zName; int isBin1, isBin2; Blob a, b; if( db_column_type(&q,0)!=SQLITE_INTEGER && db_column_type(&q,4)==SQLITE_TEXT ){ char *zUuid = fossil_strdup(db_column_text(&q,4)); char *zName = fossil_strdup(db_column_text(&q,1)); if( mFlags & PATCH_FORCE ){ fossil_print("ERROR cannot find base artifact %S for file \"%s\"\n", zUuid, zName); nErr++; fossil_free(zUuid); fossil_free(zName); continue; }else{ db_finalize(&q); fossil_fatal("base artifact %S for file \"%s\" not found", zUuid, zName); } } zName = db_column_text(&q, 1); rid = db_column_int(&q, 0); if( db_column_type(&q,3)==SQLITE_NULL ){ fossil_print("DELETE %s\n", zName); diff_print_index(zName, diffFlags, 0); isBin2 = 0; content_get(rid, &a); isBin1 = fIncludeBinary ? 0 : looks_like_binary(&a); diff_file_mem(&a, &empty, isBin1, isBin2, zName, zDiffCmd, zBinGlob, fIncludeBinary, diffFlags); }else if( rid==0 ){ db_ephemeral_blob(&q, 3, &a); blob_uncompress(&a, &a); fossil_print("ADDED %s\n", zName); diff_print_index(zName, diffFlags, 0); isBin1 = 0; isBin2 = fIncludeBinary ? 0 : looks_like_binary(&a); diff_file_mem(&empty, &a, isBin1, isBin2, zName, zDiffCmd, zBinGlob, fIncludeBinary, diffFlags); blob_reset(&a); }else if( db_column_bytes(&q, 3)>0 ){ Blob delta; db_ephemeral_blob(&q, 3, &delta); blob_uncompress(&delta, &delta); content_get(rid, &a); blob_delta_apply(&a, &delta, &b); isBin1 = fIncludeBinary ? 0 : looks_like_binary(&a); isBin2 = fIncludeBinary ? 0 : looks_like_binary(&b); diff_file_mem(&a, &b, isBin1, isBin2, zName, zDiffCmd, zBinGlob, fIncludeBinary, diffFlags); blob_reset(&a); blob_reset(&b); blob_reset(&delta); } } db_finalize(&q); if( nErr ) fossil_fatal("abort due to prior errors"); } /* ** COMMAND: patch ** ** Usage: %fossil patch SUBCOMMAND ?ARGS ..? ** ** This command is used to create, view, and apply Fossil binary patches. ** A Fossil binary patch is a single (binary) file that captures all of the ** uncommitted changes of a check-out. Use Fossil binary patches to transfer ** proposed or incomplete changes between machines for testing or analysis. ** ** > fossil patch create [DIRECTORY] FILENAME ** ** Create a new binary patch in FILENAME that captures all uncommitted ** changes in the check-out at DIRECTORY, or the current directory if ** DIRECTORY is omitted. If FILENAME is "-" then the binary patch ** is written to standard output. ** ** -f|--force Overwrite an existing patch with the same name. ** ** > fossil patch apply [DIRECTORY] FILENAME ** ** Apply the changes in FILENAME to the check-out at DIRECTORY, or ** in the current directory if DIRECTORY is omitted. Options: ** ** -f|--force Apply the patch even though there are unsaved ** changes in the current check-out. ** -n|--dryrun Do nothing, but print what would have happened. ** -v|--verbose Extra output explaining what happens. ** ** > fossil patch diff [DIRECTORY] FILENAME ** ** Show a human-readable diff for the patch. All the usual ** diff flags described at "fossil help diff" apply. In addition: ** ** -f|--force Continue trying to perform the diff even if ** baseline information is missing from the current ** repository ** ** > fossil patch push REMOTE-CHECKOUT ** ** Create a patch for the current check-out, transfer that patch to ** a remote machine (using ssh) and apply the patch there. The ** REMOTE-CHECKOUT is in one of the following formats: ** ** * DIRECTORY ** * HOST:DIRECTORY ** * USER@HOST:DIRECTORY ** ** This command will only work if "fossil" is on the default PATH ** of the remote machine. ** ** > fossil patch pull REMOTE-CHECKOUT ** ** Create a patch on a remote check-out, transfer that patch to the ** local machine (using ssh) and apply the patch in the local checkout. ** ** -f|--force Apply the patch even though there are unsaved ** changes in the current check-out. ** -n|--dryrun Do nothing, but print what would have happened. ** -v|--verbose Extra output explaining what happens. ** ** > fossil patch view FILENAME ** ** View a summary of the changes in the binary patch FILENAME. ** Use "fossil patch diff" for detailed patch content. ** ** -v|--verbose Show extra detail about the patch. ** */ void patch_cmd(void){ const char *zCmd; size_t n; if( g.argc<3 ){ patch_usage: usage("apply|create|diff|pull|push|view"); } zCmd = g.argv[2]; n = strlen(zCmd); if( strncmp(zCmd, "apply", n)==0 ){ char *zIn; unsigned flags = 0; if( find_option("dryrun","n",0) ) flags |= PATCH_DRYRUN; if( find_option("verbose","v",0) ) flags |= PATCH_VERBOSE; if( find_option("force","f",0) ) flags |= PATCH_FORCE; zIn = patch_find_patch_filename("apply"); db_must_be_within_tree(); patch_attach(zIn, stdin); patch_apply(flags); fossil_free(zIn); }else if( strncmp(zCmd, "create", n)==0 ){ char *zOut; unsigned flags = 0; if( find_option("force","f",0) ) flags |= PATCH_FORCE; zOut = patch_find_patch_filename("create"); verify_all_options(); db_must_be_within_tree(); patch_create(flags, zOut, stdout); fossil_free(zOut); }else if( strncmp(zCmd, "diff", n)==0 ){ const char *zDiffCmd = 0; const char *zBinGlob = 0; int fIncludeBinary = 0; u64 diffFlags; char *zIn; unsigned flags = 0; if( find_option("tk",0,0)!=0 ){ db_close(0); diff_tk("patch diff", 3); return; } if( find_option("internal","i",0)==0 ){ zDiffCmd = diff_command_external(zCmd[0]=='g'); } diffFlags = diff_options(); if( find_option("verbose","v",0)!=0 ) diffFlags |= DIFF_VERBOSE; if( zDiffCmd ){ zBinGlob = diff_get_binary_glob(); fIncludeBinary = diff_include_binary_files(); } db_find_and_open_repository(0, 0); if( find_option("force","f",0) ) flags |= PATCH_FORCE; verify_all_options(); zIn = patch_find_patch_filename("apply"); patch_attach(zIn, stdin); patch_diff(flags, zDiffCmd, zBinGlob, fIncludeBinary, diffFlags); fossil_free(zIn); }else if( strncmp(zCmd, "pull", n)==0 ){ FILE *pIn = 0; unsigned flags = 0; if( find_option("dryrun","n",0) ) flags |= PATCH_DRYRUN; if( find_option("verbose","v",0) ) flags |= PATCH_VERBOSE; if( find_option("force","f",0) ) flags |= PATCH_FORCE; db_must_be_within_tree(); verify_all_options(); pIn = patch_remote_command(flags & (~PATCH_FORCE), "pull", "create", "r"); if( pIn ){ patch_attach(0, pIn); pclose(pIn); patch_apply(flags); } }else if( strncmp(zCmd, "push", n)==0 ){ FILE *pOut = 0; unsigned flags = 0; if( find_option("dryrun","n",0) ) flags |= PATCH_DRYRUN; if( find_option("verbose","v",0) ) flags |= PATCH_VERBOSE; if( find_option("force","f",0) ) flags |= PATCH_FORCE; db_must_be_within_tree(); verify_all_options(); pOut = patch_remote_command(flags, "push", "apply", "w"); if( pOut ){ patch_create(0, 0, pOut); pclose(pOut); } }else if( strncmp(zCmd, "view", n)==0 ){ const char *zIn; unsigned int flags = 0; if( find_option("verbose","v",0) ) flags |= PATCH_VERBOSE; verify_all_options(); if( g.argc!=4 ){ usage("view FILENAME"); } zIn = g.argv[3]; if( fossil_strcmp(zIn, "-")==0 ) zIn = 0; patch_attach(zIn, stdin); patch_view(flags); }else { goto patch_usage; } } |
Changes to src/pikchr.c.
︙ | ︙ | |||
315 316 317 318 319 320 321 322 323 324 325 326 327 328 | unsigned mProp; /* Masks of properties set so far */ unsigned mCalc; /* Values computed from other constraints */ PToken aTxt[5]; /* Text with .eCode holding TP flags */ int iLayer; /* Rendering order */ int inDir, outDir; /* Entry and exit directions */ int nPath; /* Number of path points */ PPoint *aPath; /* Array of path points */ PBox bbox; /* Bounding box */ }; /* A list of graphics objects */ struct PList { int n; /* Number of statements in the list */ int nAlloc; /* Allocated slots in a[] */ | > | 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 | unsigned mProp; /* Masks of properties set so far */ unsigned mCalc; /* Values computed from other constraints */ PToken aTxt[5]; /* Text with .eCode holding TP flags */ int iLayer; /* Rendering order */ int inDir, outDir; /* Entry and exit directions */ int nPath; /* Number of path points */ PPoint *aPath; /* Array of path points */ PObj *pFrom, *pTo; /* End-point objects of a path */ PBox bbox; /* Bounding box */ }; /* A list of graphics objects */ struct PList { int n; /* Number of statements in the list */ int nAlloc; /* Allocated slots in a[] */ |
︙ | ︙ | |||
345 346 347 348 349 350 351 352 353 354 355 356 357 358 | PToken sIn; /* Input Pikchr-language text */ char *zOut; /* Result accumulates here */ unsigned int nOut; /* Bytes written to zOut[] so far */ unsigned int nOutAlloc; /* Space allocated to zOut[] */ unsigned char eDir; /* Current direction */ unsigned int mFlags; /* Flags passed to pikchr() */ PObj *cur; /* Object under construction */ PList *list; /* Object list under construction */ PMacro *pMacros; /* List of all defined macros */ PVar *pVar; /* Application-defined variables */ PBox bbox; /* Bounding box around all statements */ /* Cache of layout values. <=0.0 for unknown... */ PNum rScale; /* Multiply to convert inches to pixels */ PNum fontScale; /* Scale fonts by this percent */ | > | 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 | PToken sIn; /* Input Pikchr-language text */ char *zOut; /* Result accumulates here */ unsigned int nOut; /* Bytes written to zOut[] so far */ unsigned int nOutAlloc; /* Space allocated to zOut[] */ unsigned char eDir; /* Current direction */ unsigned int mFlags; /* Flags passed to pikchr() */ PObj *cur; /* Object under construction */ PObj *lastRef; /* Last object references by name */ PList *list; /* Object list under construction */ PMacro *pMacros; /* List of all defined macros */ PVar *pVar; /* Application-defined variables */ PBox bbox; /* Bounding box around all statements */ /* Cache of layout values. <=0.0 for unknown... */ PNum rScale; /* Multiply to convert inches to pixels */ PNum fontScale; /* Scale fonts by this percent */ |
︙ | ︙ | |||
424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 | static void pik_elist_free(Pik*,PList*); static void pik_elem_free(Pik*,PObj*); static void pik_render(Pik*,PList*); static PList *pik_elist_append(Pik*,PList*,PObj*); static PObj *pik_elem_new(Pik*,PToken*,PToken*,PList*); static void pik_set_direction(Pik*,int); static void pik_elem_setname(Pik*,PObj*,PToken*); static void pik_set_var(Pik*,PToken*,PNum,PToken*); static PNum pik_value(Pik*,const char*,int,int*); static PNum pik_lookup_color(Pik*,PToken*); static PNum pik_get_var(Pik*,PToken*); static PNum pik_atof(PToken*); static void pik_after_adding_attributes(Pik*,PObj*); static void pik_elem_move(PObj*,PNum dx, PNum dy); static void pik_elist_move(PList*,PNum dx, PNum dy); static void pik_set_numprop(Pik*,PToken*,PRel*); | > > | 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 | static void pik_elist_free(Pik*,PList*); static void pik_elem_free(Pik*,PObj*); static void pik_render(Pik*,PList*); static PList *pik_elist_append(Pik*,PList*,PObj*); static PObj *pik_elem_new(Pik*,PToken*,PToken*,PList*); static void pik_set_direction(Pik*,int); static void pik_elem_setname(Pik*,PObj*,PToken*); static int pik_round(PNum); static void pik_set_var(Pik*,PToken*,PNum,PToken*); static PNum pik_value(Pik*,const char*,int,int*); static int pik_value_int(Pik*,const char*,int,int*); static PNum pik_lookup_color(Pik*,PToken*); static PNum pik_get_var(Pik*,PToken*); static PNum pik_atof(PToken*); static void pik_after_adding_attributes(Pik*,PObj*); static void pik_elem_move(PObj*,PNum dx, PNum dy); static void pik_elist_move(PList*,PNum dx, PNum dy); static void pik_set_numprop(Pik*,PToken*,PRel*); |
︙ | ︙ | |||
448 449 450 451 452 453 454 455 456 457 458 459 460 461 | static void pik_close_path(Pik*,PToken*); static void pik_set_at(Pik*,PToken*,PPoint*,PToken*); static short int pik_nth_value(Pik*,PToken*); static PObj *pik_find_nth(Pik*,PObj*,PToken*); static PObj *pik_find_byname(Pik*,PObj*,PToken*); static PPoint pik_place_of_elem(Pik*,PObj*,PToken*); static int pik_bbox_isempty(PBox*); static void pik_bbox_init(PBox*); static void pik_bbox_addbox(PBox*,PBox*); static void pik_bbox_add_xy(PBox*,PNum,PNum); static void pik_bbox_addellipse(PBox*,PNum x,PNum y,PNum rx,PNum ry); static void pik_add_txt(Pik*,PToken*,int); static int pik_text_length(const PToken *pToken); static void pik_size_to_fit(Pik*,PToken*,int); | > | 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 | static void pik_close_path(Pik*,PToken*); static void pik_set_at(Pik*,PToken*,PPoint*,PToken*); static short int pik_nth_value(Pik*,PToken*); static PObj *pik_find_nth(Pik*,PObj*,PToken*); static PObj *pik_find_byname(Pik*,PObj*,PToken*); static PPoint pik_place_of_elem(Pik*,PObj*,PToken*); static int pik_bbox_isempty(PBox*); static int pik_bbox_contains_point(PBox*,PPoint*); static void pik_bbox_init(PBox*); static void pik_bbox_addbox(PBox*,PBox*); static void pik_bbox_add_xy(PBox*,PNum,PNum); static void pik_bbox_addellipse(PBox*,PNum x,PNum y,PNum rx,PNum ry); static void pik_add_txt(Pik*,PToken*,int); static int pik_text_length(const PToken *pToken); static void pik_size_to_fit(Pik*,PToken*,int); |
︙ | ︙ | |||
472 473 474 475 476 477 478 | static void pik_behind(Pik*,PObj*); static PObj *pik_assert(Pik*,PNum,PToken*,PNum); static PObj *pik_position_assert(Pik*,PPoint*,PToken*,PPoint*); static PNum pik_dist(PPoint*,PPoint*); static void pik_add_macro(Pik*,PToken *pId,PToken *pCode); | | | 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 | static void pik_behind(Pik*,PObj*); static PObj *pik_assert(Pik*,PNum,PToken*,PNum); static PObj *pik_position_assert(Pik*,PPoint*,PToken*,PPoint*); static PNum pik_dist(PPoint*,PPoint*); static void pik_add_macro(Pik*,PToken *pId,PToken *pCode); #line 510 "pikchr.c" /**************** End of %include directives **********************************/ /* These constants specify the various numeric values for terminal symbols. ***************** Begin token definitions *************************************/ #ifndef T_ID #define T_ID 1 #define T_EDGEPT 2 #define T_OF 3 |
︙ | ︙ | |||
1701 1702 1703 1704 1705 1706 1707 | ** Note: during a reduce, the only symbols destroyed are those ** which appear on the RHS of the rule, but which are *not* used ** inside the C code. */ /********* Begin destructor definitions ***************************************/ case 99: /* statement_list */ { | | | | | | 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 | ** Note: during a reduce, the only symbols destroyed are those ** which appear on the RHS of the rule, but which are *not* used ** inside the C code. */ /********* Begin destructor definitions ***************************************/ case 99: /* statement_list */ { #line 499 "pikchr.y" pik_elist_free(p,(yypminor->yy227)); #line 1740 "pikchr.c" } break; case 100: /* statement */ case 101: /* unnamed_statement */ case 102: /* basetype */ { #line 501 "pikchr.y" pik_elem_free(p,(yypminor->yy36)); #line 1749 "pikchr.c" } break; /********* End destructor definitions *****************************************/ default: break; /* If no destructor action specified: do nothing */ } } |
︙ | ︙ | |||
1930 1931 1932 1933 1934 1935 1936 | fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt); } #endif while( yypParser->yytos>yypParser->yystack ) yy_pop_parser_stack(yypParser); /* Here code is inserted which will execute if the parser ** stack every overflows */ /******** Begin %stack_overflow code ******************************************/ | | | | 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 | fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt); } #endif while( yypParser->yytos>yypParser->yystack ) yy_pop_parser_stack(yypParser); /* Here code is inserted which will execute if the parser ** stack every overflows */ /******** Begin %stack_overflow code ******************************************/ #line 533 "pikchr.y" pik_error(p, 0, "parser stack overflow"); #line 1970 "pikchr.c" /******** End %stack_overflow code ********************************************/ pik_parserARG_STORE /* Suppress warning about unused %extra_argument var */ pik_parserCTX_STORE } /* ** Print tracing information for a SHIFT action |
︙ | ︙ | |||
2413 2414 2415 2416 2417 2418 2419 | ** { ... } // User supplied code ** #line <lineno> <thisfile> ** break; */ /********** Begin reduce actions **********************************************/ YYMINORTYPE yylhsminor; case 0: /* document ::= statement_list */ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 | ** { ... } // User supplied code ** #line <lineno> <thisfile> ** break; */ /********** Begin reduce actions **********************************************/ YYMINORTYPE yylhsminor; case 0: /* document ::= statement_list */ #line 537 "pikchr.y" {pik_render(p,yymsp[0].minor.yy227);} #line 2452 "pikchr.c" break; case 1: /* statement_list ::= statement */ #line 540 "pikchr.y" { yylhsminor.yy227 = pik_elist_append(p,0,yymsp[0].minor.yy36); } #line 2457 "pikchr.c" yymsp[0].minor.yy227 = yylhsminor.yy227; break; case 2: /* statement_list ::= statement_list EOL statement */ #line 542 "pikchr.y" { yylhsminor.yy227 = pik_elist_append(p,yymsp[-2].minor.yy227,yymsp[0].minor.yy36); } #line 2463 "pikchr.c" yymsp[-2].minor.yy227 = yylhsminor.yy227; break; case 3: /* statement ::= */ #line 545 "pikchr.y" { yymsp[1].minor.yy36 = 0; } #line 2469 "pikchr.c" break; case 4: /* statement ::= direction */ #line 546 "pikchr.y" { pik_set_direction(p,yymsp[0].minor.yy0.eCode); yylhsminor.yy36=0; } #line 2474 "pikchr.c" yymsp[0].minor.yy36 = yylhsminor.yy36; break; case 5: /* statement ::= lvalue ASSIGN rvalue */ #line 547 "pikchr.y" {pik_set_var(p,&yymsp[-2].minor.yy0,yymsp[0].minor.yy153,&yymsp[-1].minor.yy0); yylhsminor.yy36=0;} #line 2480 "pikchr.c" yymsp[-2].minor.yy36 = yylhsminor.yy36; break; case 6: /* statement ::= PLACENAME COLON unnamed_statement */ #line 549 "pikchr.y" { yylhsminor.yy36 = yymsp[0].minor.yy36; pik_elem_setname(p,yymsp[0].minor.yy36,&yymsp[-2].minor.yy0); } #line 2486 "pikchr.c" yymsp[-2].minor.yy36 = yylhsminor.yy36; break; case 7: /* statement ::= PLACENAME COLON position */ #line 551 "pikchr.y" { yylhsminor.yy36 = pik_elem_new(p,0,0,0); if(yylhsminor.yy36){ yylhsminor.yy36->ptAt = yymsp[0].minor.yy79; pik_elem_setname(p,yylhsminor.yy36,&yymsp[-2].minor.yy0); }} #line 2493 "pikchr.c" yymsp[-2].minor.yy36 = yylhsminor.yy36; break; case 8: /* statement ::= unnamed_statement */ #line 553 "pikchr.y" {yylhsminor.yy36 = yymsp[0].minor.yy36;} #line 2499 "pikchr.c" yymsp[0].minor.yy36 = yylhsminor.yy36; break; case 9: /* statement ::= print prlist */ #line 554 "pikchr.y" {pik_append(p,"<br>\n",5); yymsp[-1].minor.yy36=0;} #line 2505 "pikchr.c" break; case 10: /* statement ::= ASSERT LP expr EQ expr RP */ #line 559 "pikchr.y" {yymsp[-5].minor.yy36=pik_assert(p,yymsp[-3].minor.yy153,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy153);} #line 2510 "pikchr.c" break; case 11: /* statement ::= ASSERT LP position EQ position RP */ #line 561 "pikchr.y" {yymsp[-5].minor.yy36=pik_position_assert(p,&yymsp[-3].minor.yy79,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy79);} #line 2515 "pikchr.c" break; case 12: /* statement ::= DEFINE ID CODEBLOCK */ #line 562 "pikchr.y" {yymsp[-2].minor.yy36=0; pik_add_macro(p,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);} #line 2520 "pikchr.c" break; case 13: /* rvalue ::= PLACENAME */ #line 573 "pikchr.y" {yylhsminor.yy153 = pik_lookup_color(p,&yymsp[0].minor.yy0);} #line 2525 "pikchr.c" yymsp[0].minor.yy153 = yylhsminor.yy153; break; case 14: /* pritem ::= FILL */ case 15: /* pritem ::= COLOR */ yytestcase(yyruleno==15); case 16: /* pritem ::= THICKNESS */ yytestcase(yyruleno==16); #line 578 "pikchr.y" {pik_append_num(p,"",pik_value(p,yymsp[0].minor.yy0.z,yymsp[0].minor.yy0.n,0));} #line 2533 "pikchr.c" break; case 17: /* pritem ::= rvalue */ #line 581 "pikchr.y" {pik_append_num(p,"",yymsp[0].minor.yy153);} #line 2538 "pikchr.c" break; case 18: /* pritem ::= STRING */ #line 582 "pikchr.y" {pik_append_text(p,yymsp[0].minor.yy0.z+1,yymsp[0].minor.yy0.n-2,0);} #line 2543 "pikchr.c" break; case 19: /* prsep ::= COMMA */ #line 583 "pikchr.y" {pik_append(p, " ", 1);} #line 2548 "pikchr.c" break; case 20: /* unnamed_statement ::= basetype attribute_list */ #line 586 "pikchr.y" {yylhsminor.yy36 = yymsp[-1].minor.yy36; pik_after_adding_attributes(p,yylhsminor.yy36);} #line 2553 "pikchr.c" yymsp[-1].minor.yy36 = yylhsminor.yy36; break; case 21: /* basetype ::= CLASSNAME */ #line 588 "pikchr.y" {yylhsminor.yy36 = pik_elem_new(p,&yymsp[0].minor.yy0,0,0); } #line 2559 "pikchr.c" yymsp[0].minor.yy36 = yylhsminor.yy36; break; case 22: /* basetype ::= STRING textposition */ #line 590 "pikchr.y" {yymsp[-1].minor.yy0.eCode = yymsp[0].minor.yy164; yylhsminor.yy36 = pik_elem_new(p,0,&yymsp[-1].minor.yy0,0); } #line 2565 "pikchr.c" yymsp[-1].minor.yy36 = yylhsminor.yy36; break; case 23: /* basetype ::= LB savelist statement_list RB */ #line 592 "pikchr.y" { p->list = yymsp[-2].minor.yy227; yymsp[-3].minor.yy36 = pik_elem_new(p,0,0,yymsp[-1].minor.yy227); if(yymsp[-3].minor.yy36) yymsp[-3].minor.yy36->errTok = yymsp[0].minor.yy0; } #line 2571 "pikchr.c" break; case 24: /* savelist ::= */ #line 597 "pikchr.y" {yymsp[1].minor.yy227 = p->list; p->list = 0;} #line 2576 "pikchr.c" break; case 25: /* relexpr ::= expr */ #line 604 "pikchr.y" {yylhsminor.yy10.rAbs = yymsp[0].minor.yy153; yylhsminor.yy10.rRel = 0;} #line 2581 "pikchr.c" yymsp[0].minor.yy10 = yylhsminor.yy10; break; case 26: /* relexpr ::= expr PERCENT */ #line 605 "pikchr.y" {yylhsminor.yy10.rAbs = 0; yylhsminor.yy10.rRel = yymsp[-1].minor.yy153/100;} #line 2587 "pikchr.c" yymsp[-1].minor.yy10 = yylhsminor.yy10; break; case 27: /* optrelexpr ::= */ #line 607 "pikchr.y" {yymsp[1].minor.yy10.rAbs = 0; yymsp[1].minor.yy10.rRel = 1.0;} #line 2593 "pikchr.c" break; case 28: /* attribute_list ::= relexpr alist */ #line 609 "pikchr.y" {pik_add_direction(p,0,&yymsp[-1].minor.yy10);} #line 2598 "pikchr.c" break; case 29: /* attribute ::= numproperty relexpr */ #line 613 "pikchr.y" { pik_set_numprop(p,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy10); } #line 2603 "pikchr.c" break; case 30: /* attribute ::= dashproperty expr */ #line 614 "pikchr.y" { pik_set_dashed(p,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy153); } #line 2608 "pikchr.c" break; case 31: /* attribute ::= dashproperty */ #line 615 "pikchr.y" { pik_set_dashed(p,&yymsp[0].minor.yy0,0); } #line 2613 "pikchr.c" break; case 32: /* attribute ::= colorproperty rvalue */ #line 616 "pikchr.y" { pik_set_clrprop(p,&yymsp[-1].minor.yy0,yymsp[0].minor.yy153); } #line 2618 "pikchr.c" break; case 33: /* attribute ::= go direction optrelexpr */ #line 617 "pikchr.y" { pik_add_direction(p,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy10);} #line 2623 "pikchr.c" break; case 34: /* attribute ::= go direction even position */ #line 618 "pikchr.y" {pik_evenwith(p,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy79);} #line 2628 "pikchr.c" break; case 35: /* attribute ::= CLOSE */ #line 619 "pikchr.y" { pik_close_path(p,&yymsp[0].minor.yy0); } #line 2633 "pikchr.c" break; case 36: /* attribute ::= CHOP */ #line 620 "pikchr.y" { p->cur->bChop = 1; } #line 2638 "pikchr.c" break; case 37: /* attribute ::= FROM position */ #line 621 "pikchr.y" { pik_set_from(p,p->cur,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy79); } #line 2643 "pikchr.c" break; case 38: /* attribute ::= TO position */ #line 622 "pikchr.y" { pik_add_to(p,p->cur,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy79); } #line 2648 "pikchr.c" break; case 39: /* attribute ::= THEN */ #line 623 "pikchr.y" { pik_then(p, &yymsp[0].minor.yy0, p->cur); } #line 2653 "pikchr.c" break; case 40: /* attribute ::= THEN optrelexpr HEADING expr */ case 42: /* attribute ::= GO optrelexpr HEADING expr */ yytestcase(yyruleno==42); #line 625 "pikchr.y" {pik_move_hdg(p,&yymsp[-2].minor.yy10,&yymsp[-1].minor.yy0,yymsp[0].minor.yy153,0,&yymsp[-3].minor.yy0);} #line 2659 "pikchr.c" break; case 41: /* attribute ::= THEN optrelexpr EDGEPT */ case 43: /* attribute ::= GO optrelexpr EDGEPT */ yytestcase(yyruleno==43); #line 626 "pikchr.y" {pik_move_hdg(p,&yymsp[-1].minor.yy10,0,0,&yymsp[0].minor.yy0,&yymsp[-2].minor.yy0);} #line 2665 "pikchr.c" break; case 44: /* attribute ::= AT position */ #line 631 "pikchr.y" { pik_set_at(p,0,&yymsp[0].minor.yy79,&yymsp[-1].minor.yy0); } #line 2670 "pikchr.c" break; case 45: /* attribute ::= SAME */ #line 633 "pikchr.y" {pik_same(p,0,&yymsp[0].minor.yy0);} #line 2675 "pikchr.c" break; case 46: /* attribute ::= SAME AS object */ #line 634 "pikchr.y" {pik_same(p,yymsp[0].minor.yy36,&yymsp[-2].minor.yy0);} #line 2680 "pikchr.c" break; case 47: /* attribute ::= STRING textposition */ #line 635 "pikchr.y" {pik_add_txt(p,&yymsp[-1].minor.yy0,yymsp[0].minor.yy164);} #line 2685 "pikchr.c" break; case 48: /* attribute ::= FIT */ #line 636 "pikchr.y" {pik_size_to_fit(p,&yymsp[0].minor.yy0,3); } #line 2690 "pikchr.c" break; case 49: /* attribute ::= BEHIND object */ #line 637 "pikchr.y" {pik_behind(p,yymsp[0].minor.yy36);} #line 2695 "pikchr.c" break; case 50: /* withclause ::= DOT_E edge AT position */ case 51: /* withclause ::= edge AT position */ yytestcase(yyruleno==51); #line 645 "pikchr.y" { pik_set_at(p,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy79,&yymsp[-1].minor.yy0); } #line 2701 "pikchr.c" break; case 52: /* numproperty ::= HEIGHT|WIDTH|RADIUS|DIAMETER|THICKNESS */ #line 649 "pikchr.y" {yylhsminor.yy0 = yymsp[0].minor.yy0;} #line 2706 "pikchr.c" yymsp[0].minor.yy0 = yylhsminor.yy0; break; case 53: /* boolproperty ::= CW */ #line 660 "pikchr.y" {p->cur->cw = 1;} #line 2712 "pikchr.c" break; case 54: /* boolproperty ::= CCW */ #line 661 "pikchr.y" {p->cur->cw = 0;} #line 2717 "pikchr.c" break; case 55: /* boolproperty ::= LARROW */ #line 662 "pikchr.y" {p->cur->larrow=1; p->cur->rarrow=0; } #line 2722 "pikchr.c" break; case 56: /* boolproperty ::= RARROW */ #line 663 "pikchr.y" {p->cur->larrow=0; p->cur->rarrow=1; } #line 2727 "pikchr.c" break; case 57: /* boolproperty ::= LRARROW */ #line 664 "pikchr.y" {p->cur->larrow=1; p->cur->rarrow=1; } #line 2732 "pikchr.c" break; case 58: /* boolproperty ::= INVIS */ #line 665 "pikchr.y" {p->cur->sw = 0.0;} #line 2737 "pikchr.c" break; case 59: /* boolproperty ::= THICK */ #line 666 "pikchr.y" {p->cur->sw *= 1.5;} #line 2742 "pikchr.c" break; case 60: /* boolproperty ::= THIN */ #line 667 "pikchr.y" {p->cur->sw *= 0.67;} #line 2747 "pikchr.c" break; case 61: /* boolproperty ::= SOLID */ #line 668 "pikchr.y" {p->cur->sw = pik_value(p,"thickness",9,0); p->cur->dotted = p->cur->dashed = 0.0;} #line 2753 "pikchr.c" break; case 62: /* textposition ::= */ #line 671 "pikchr.y" {yymsp[1].minor.yy164 = 0;} #line 2758 "pikchr.c" break; case 63: /* textposition ::= textposition CENTER|LJUST|RJUST|ABOVE|BELOW|ITALIC|BOLD|ALIGNED|BIG|SMALL */ #line 674 "pikchr.y" {yylhsminor.yy164 = (short int)pik_text_position(yymsp[-1].minor.yy164,&yymsp[0].minor.yy0);} #line 2763 "pikchr.c" yymsp[-1].minor.yy164 = yylhsminor.yy164; break; case 64: /* position ::= expr COMMA expr */ #line 677 "pikchr.y" {yylhsminor.yy79.x=yymsp[-2].minor.yy153; yylhsminor.yy79.y=yymsp[0].minor.yy153;} #line 2769 "pikchr.c" yymsp[-2].minor.yy79 = yylhsminor.yy79; break; case 65: /* position ::= place PLUS expr COMMA expr */ #line 679 "pikchr.y" {yylhsminor.yy79.x=yymsp[-4].minor.yy79.x+yymsp[-2].minor.yy153; yylhsminor.yy79.y=yymsp[-4].minor.yy79.y+yymsp[0].minor.yy153;} #line 2775 "pikchr.c" yymsp[-4].minor.yy79 = yylhsminor.yy79; break; case 66: /* position ::= place MINUS expr COMMA expr */ #line 680 "pikchr.y" {yylhsminor.yy79.x=yymsp[-4].minor.yy79.x-yymsp[-2].minor.yy153; yylhsminor.yy79.y=yymsp[-4].minor.yy79.y-yymsp[0].minor.yy153;} #line 2781 "pikchr.c" yymsp[-4].minor.yy79 = yylhsminor.yy79; break; case 67: /* position ::= place PLUS LP expr COMMA expr RP */ #line 682 "pikchr.y" {yylhsminor.yy79.x=yymsp[-6].minor.yy79.x+yymsp[-3].minor.yy153; yylhsminor.yy79.y=yymsp[-6].minor.yy79.y+yymsp[-1].minor.yy153;} #line 2787 "pikchr.c" yymsp[-6].minor.yy79 = yylhsminor.yy79; break; case 68: /* position ::= place MINUS LP expr COMMA expr RP */ #line 684 "pikchr.y" {yylhsminor.yy79.x=yymsp[-6].minor.yy79.x-yymsp[-3].minor.yy153; yylhsminor.yy79.y=yymsp[-6].minor.yy79.y-yymsp[-1].minor.yy153;} #line 2793 "pikchr.c" yymsp[-6].minor.yy79 = yylhsminor.yy79; break; case 69: /* position ::= LP position COMMA position RP */ #line 685 "pikchr.y" {yymsp[-4].minor.yy79.x=yymsp[-3].minor.yy79.x; yymsp[-4].minor.yy79.y=yymsp[-1].minor.yy79.y;} #line 2799 "pikchr.c" break; case 70: /* position ::= LP position RP */ #line 686 "pikchr.y" {yymsp[-2].minor.yy79=yymsp[-1].minor.yy79;} #line 2804 "pikchr.c" break; case 71: /* position ::= expr between position AND position */ #line 688 "pikchr.y" {yylhsminor.yy79 = pik_position_between(yymsp[-4].minor.yy153,yymsp[-2].minor.yy79,yymsp[0].minor.yy79);} #line 2809 "pikchr.c" yymsp[-4].minor.yy79 = yylhsminor.yy79; break; case 72: /* position ::= expr LT position COMMA position GT */ #line 690 "pikchr.y" {yylhsminor.yy79 = pik_position_between(yymsp[-5].minor.yy153,yymsp[-3].minor.yy79,yymsp[-1].minor.yy79);} #line 2815 "pikchr.c" yymsp[-5].minor.yy79 = yylhsminor.yy79; break; case 73: /* position ::= expr ABOVE position */ #line 691 "pikchr.y" {yylhsminor.yy79=yymsp[0].minor.yy79; yylhsminor.yy79.y += yymsp[-2].minor.yy153;} #line 2821 "pikchr.c" yymsp[-2].minor.yy79 = yylhsminor.yy79; break; case 74: /* position ::= expr BELOW position */ #line 692 "pikchr.y" {yylhsminor.yy79=yymsp[0].minor.yy79; yylhsminor.yy79.y -= yymsp[-2].minor.yy153;} #line 2827 "pikchr.c" yymsp[-2].minor.yy79 = yylhsminor.yy79; break; case 75: /* position ::= expr LEFT OF position */ #line 693 "pikchr.y" {yylhsminor.yy79=yymsp[0].minor.yy79; yylhsminor.yy79.x -= yymsp[-3].minor.yy153;} #line 2833 "pikchr.c" yymsp[-3].minor.yy79 = yylhsminor.yy79; break; case 76: /* position ::= expr RIGHT OF position */ #line 694 "pikchr.y" {yylhsminor.yy79=yymsp[0].minor.yy79; yylhsminor.yy79.x += yymsp[-3].minor.yy153;} #line 2839 "pikchr.c" yymsp[-3].minor.yy79 = yylhsminor.yy79; break; case 77: /* position ::= expr ON HEADING EDGEPT OF position */ #line 696 "pikchr.y" {yylhsminor.yy79 = pik_position_at_hdg(yymsp[-5].minor.yy153,&yymsp[-2].minor.yy0,yymsp[0].minor.yy79);} #line 2845 "pikchr.c" yymsp[-5].minor.yy79 = yylhsminor.yy79; break; case 78: /* position ::= expr HEADING EDGEPT OF position */ #line 698 "pikchr.y" {yylhsminor.yy79 = pik_position_at_hdg(yymsp[-4].minor.yy153,&yymsp[-2].minor.yy0,yymsp[0].minor.yy79);} #line 2851 "pikchr.c" yymsp[-4].minor.yy79 = yylhsminor.yy79; break; case 79: /* position ::= expr EDGEPT OF position */ #line 700 "pikchr.y" {yylhsminor.yy79 = pik_position_at_hdg(yymsp[-3].minor.yy153,&yymsp[-2].minor.yy0,yymsp[0].minor.yy79);} #line 2857 "pikchr.c" yymsp[-3].minor.yy79 = yylhsminor.yy79; break; case 80: /* position ::= expr ON HEADING expr FROM position */ #line 702 "pikchr.y" {yylhsminor.yy79 = pik_position_at_angle(yymsp[-5].minor.yy153,yymsp[-2].minor.yy153,yymsp[0].minor.yy79);} #line 2863 "pikchr.c" yymsp[-5].minor.yy79 = yylhsminor.yy79; break; case 81: /* position ::= expr HEADING expr FROM position */ #line 704 "pikchr.y" {yylhsminor.yy79 = pik_position_at_angle(yymsp[-4].minor.yy153,yymsp[-2].minor.yy153,yymsp[0].minor.yy79);} #line 2869 "pikchr.c" yymsp[-4].minor.yy79 = yylhsminor.yy79; break; case 82: /* place ::= edge OF object */ #line 716 "pikchr.y" {yylhsminor.yy79 = pik_place_of_elem(p,yymsp[0].minor.yy36,&yymsp[-2].minor.yy0);} #line 2875 "pikchr.c" yymsp[-2].minor.yy79 = yylhsminor.yy79; break; case 83: /* place2 ::= object */ #line 717 "pikchr.y" {yylhsminor.yy79 = pik_place_of_elem(p,yymsp[0].minor.yy36,0);} #line 2881 "pikchr.c" yymsp[0].minor.yy79 = yylhsminor.yy79; break; case 84: /* place2 ::= object DOT_E edge */ #line 718 "pikchr.y" {yylhsminor.yy79 = pik_place_of_elem(p,yymsp[-2].minor.yy36,&yymsp[0].minor.yy0);} #line 2887 "pikchr.c" yymsp[-2].minor.yy79 = yylhsminor.yy79; break; case 85: /* place2 ::= NTH VERTEX OF object */ #line 719 "pikchr.y" {yylhsminor.yy79 = pik_nth_vertex(p,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,yymsp[0].minor.yy36);} #line 2893 "pikchr.c" yymsp[-3].minor.yy79 = yylhsminor.yy79; break; case 86: /* object ::= nth */ #line 731 "pikchr.y" {yylhsminor.yy36 = pik_find_nth(p,0,&yymsp[0].minor.yy0);} #line 2899 "pikchr.c" yymsp[0].minor.yy36 = yylhsminor.yy36; break; case 87: /* object ::= nth OF|IN object */ #line 732 "pikchr.y" {yylhsminor.yy36 = pik_find_nth(p,yymsp[0].minor.yy36,&yymsp[-2].minor.yy0);} #line 2905 "pikchr.c" yymsp[-2].minor.yy36 = yylhsminor.yy36; break; case 88: /* objectname ::= THIS */ #line 734 "pikchr.y" {yymsp[0].minor.yy36 = p->cur;} #line 2911 "pikchr.c" break; case 89: /* objectname ::= PLACENAME */ #line 735 "pikchr.y" {yylhsminor.yy36 = pik_find_byname(p,0,&yymsp[0].minor.yy0);} #line 2916 "pikchr.c" yymsp[0].minor.yy36 = yylhsminor.yy36; break; case 90: /* objectname ::= objectname DOT_U PLACENAME */ #line 737 "pikchr.y" {yylhsminor.yy36 = pik_find_byname(p,yymsp[-2].minor.yy36,&yymsp[0].minor.yy0);} #line 2922 "pikchr.c" yymsp[-2].minor.yy36 = yylhsminor.yy36; break; case 91: /* nth ::= NTH CLASSNAME */ #line 739 "pikchr.y" {yylhsminor.yy0=yymsp[0].minor.yy0; yylhsminor.yy0.eCode = pik_nth_value(p,&yymsp[-1].minor.yy0); } #line 2928 "pikchr.c" yymsp[-1].minor.yy0 = yylhsminor.yy0; break; case 92: /* nth ::= NTH LAST CLASSNAME */ #line 740 "pikchr.y" {yylhsminor.yy0=yymsp[0].minor.yy0; yylhsminor.yy0.eCode = -pik_nth_value(p,&yymsp[-2].minor.yy0); } #line 2934 "pikchr.c" yymsp[-2].minor.yy0 = yylhsminor.yy0; break; case 93: /* nth ::= LAST CLASSNAME */ #line 741 "pikchr.y" {yymsp[-1].minor.yy0=yymsp[0].minor.yy0; yymsp[-1].minor.yy0.eCode = -1;} #line 2940 "pikchr.c" break; case 94: /* nth ::= LAST */ #line 742 "pikchr.y" {yylhsminor.yy0=yymsp[0].minor.yy0; yylhsminor.yy0.eCode = -1;} #line 2945 "pikchr.c" yymsp[0].minor.yy0 = yylhsminor.yy0; break; case 95: /* nth ::= NTH LB RB */ #line 743 "pikchr.y" {yylhsminor.yy0=yymsp[-1].minor.yy0; yylhsminor.yy0.eCode = pik_nth_value(p,&yymsp[-2].minor.yy0);} #line 2951 "pikchr.c" yymsp[-2].minor.yy0 = yylhsminor.yy0; break; case 96: /* nth ::= NTH LAST LB RB */ #line 744 "pikchr.y" {yylhsminor.yy0=yymsp[-1].minor.yy0; yylhsminor.yy0.eCode = -pik_nth_value(p,&yymsp[-3].minor.yy0);} #line 2957 "pikchr.c" yymsp[-3].minor.yy0 = yylhsminor.yy0; break; case 97: /* nth ::= LAST LB RB */ #line 745 "pikchr.y" {yymsp[-2].minor.yy0=yymsp[-1].minor.yy0; yymsp[-2].minor.yy0.eCode = -1; } #line 2963 "pikchr.c" break; case 98: /* expr ::= expr PLUS expr */ #line 747 "pikchr.y" {yylhsminor.yy153=yymsp[-2].minor.yy153+yymsp[0].minor.yy153;} #line 2968 "pikchr.c" yymsp[-2].minor.yy153 = yylhsminor.yy153; break; case 99: /* expr ::= expr MINUS expr */ #line 748 "pikchr.y" {yylhsminor.yy153=yymsp[-2].minor.yy153-yymsp[0].minor.yy153;} #line 2974 "pikchr.c" yymsp[-2].minor.yy153 = yylhsminor.yy153; break; case 100: /* expr ::= expr STAR expr */ #line 749 "pikchr.y" {yylhsminor.yy153=yymsp[-2].minor.yy153*yymsp[0].minor.yy153;} #line 2980 "pikchr.c" yymsp[-2].minor.yy153 = yylhsminor.yy153; break; case 101: /* expr ::= expr SLASH expr */ #line 750 "pikchr.y" { if( yymsp[0].minor.yy153==0.0 ){ pik_error(p, &yymsp[-1].minor.yy0, "division by zero"); yylhsminor.yy153 = 0.0; } else{ yylhsminor.yy153 = yymsp[-2].minor.yy153/yymsp[0].minor.yy153; } } #line 2989 "pikchr.c" yymsp[-2].minor.yy153 = yylhsminor.yy153; break; case 102: /* expr ::= MINUS expr */ #line 754 "pikchr.y" {yymsp[-1].minor.yy153=-yymsp[0].minor.yy153;} #line 2995 "pikchr.c" break; case 103: /* expr ::= PLUS expr */ #line 755 "pikchr.y" {yymsp[-1].minor.yy153=yymsp[0].minor.yy153;} #line 3000 "pikchr.c" break; case 104: /* expr ::= LP expr RP */ #line 756 "pikchr.y" {yymsp[-2].minor.yy153=yymsp[-1].minor.yy153;} #line 3005 "pikchr.c" break; case 105: /* expr ::= LP FILL|COLOR|THICKNESS RP */ #line 757 "pikchr.y" {yymsp[-2].minor.yy153=pik_get_var(p,&yymsp[-1].minor.yy0);} #line 3010 "pikchr.c" break; case 106: /* expr ::= NUMBER */ #line 758 "pikchr.y" {yylhsminor.yy153=pik_atof(&yymsp[0].minor.yy0);} #line 3015 "pikchr.c" yymsp[0].minor.yy153 = yylhsminor.yy153; break; case 107: /* expr ::= ID */ #line 759 "pikchr.y" {yylhsminor.yy153=pik_get_var(p,&yymsp[0].minor.yy0);} #line 3021 "pikchr.c" yymsp[0].minor.yy153 = yylhsminor.yy153; break; case 108: /* expr ::= FUNC1 LP expr RP */ #line 760 "pikchr.y" {yylhsminor.yy153 = pik_func(p,&yymsp[-3].minor.yy0,yymsp[-1].minor.yy153,0.0);} #line 3027 "pikchr.c" yymsp[-3].minor.yy153 = yylhsminor.yy153; break; case 109: /* expr ::= FUNC2 LP expr COMMA expr RP */ #line 761 "pikchr.y" {yylhsminor.yy153 = pik_func(p,&yymsp[-5].minor.yy0,yymsp[-3].minor.yy153,yymsp[-1].minor.yy153);} #line 3033 "pikchr.c" yymsp[-5].minor.yy153 = yylhsminor.yy153; break; case 110: /* expr ::= DIST LP position COMMA position RP */ #line 762 "pikchr.y" {yymsp[-5].minor.yy153 = pik_dist(&yymsp[-3].minor.yy79,&yymsp[-1].minor.yy79);} #line 3039 "pikchr.c" break; case 111: /* expr ::= place2 DOT_XY X */ #line 763 "pikchr.y" {yylhsminor.yy153 = yymsp[-2].minor.yy79.x;} #line 3044 "pikchr.c" yymsp[-2].minor.yy153 = yylhsminor.yy153; break; case 112: /* expr ::= place2 DOT_XY Y */ #line 764 "pikchr.y" {yylhsminor.yy153 = yymsp[-2].minor.yy79.y;} #line 3050 "pikchr.c" yymsp[-2].minor.yy153 = yylhsminor.yy153; break; case 113: /* expr ::= object DOT_L numproperty */ case 114: /* expr ::= object DOT_L dashproperty */ yytestcase(yyruleno==114); case 115: /* expr ::= object DOT_L colorproperty */ yytestcase(yyruleno==115); #line 765 "pikchr.y" {yylhsminor.yy153=pik_property_of(yymsp[-2].minor.yy36,&yymsp[0].minor.yy0);} #line 3058 "pikchr.c" yymsp[-2].minor.yy153 = yylhsminor.yy153; break; default: /* (116) lvalue ::= ID */ yytestcase(yyruleno==116); /* (117) lvalue ::= FILL */ yytestcase(yyruleno==117); /* (118) lvalue ::= COLOR */ yytestcase(yyruleno==118); /* (119) lvalue ::= THICKNESS */ yytestcase(yyruleno==119); |
︙ | ︙ | |||
3124 3125 3126 3127 3128 3129 3130 | int yymajor, /* The major type of the error token */ pik_parserTOKENTYPE yyminor /* The minor type of the error token */ ){ pik_parserARG_FETCH pik_parserCTX_FETCH #define TOKEN yyminor /************ Begin %syntax_error code ****************************************/ | | | | 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 | int yymajor, /* The major type of the error token */ pik_parserTOKENTYPE yyminor /* The minor type of the error token */ ){ pik_parserARG_FETCH pik_parserCTX_FETCH #define TOKEN yyminor /************ Begin %syntax_error code ****************************************/ #line 525 "pikchr.y" if( TOKEN.z && TOKEN.z[0] ){ pik_error(p, &TOKEN, "syntax error"); }else{ pik_error(p, 0, "syntax error"); } UNUSED_PARAMETER(yymajor); #line 3169 "pikchr.c" /************ End %syntax_error code ******************************************/ pik_parserARG_STORE /* Suppress warning about unused %extra_argument variable */ pik_parserCTX_STORE } /* ** The following is executed when the parser accepts |
︙ | ︙ | |||
3365 3366 3367 3368 3369 3370 3371 | assert( iToken<(int)(sizeof(yyFallback)/sizeof(yyFallback[0])) ); return yyFallback[iToken]; #else (void)iToken; return 0; #endif } | | | 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 | assert( iToken<(int)(sizeof(yyFallback)/sizeof(yyFallback[0])) ); return yyFallback[iToken]; #else (void)iToken; return 0; #endif } #line 770 "pikchr.y" /* Chart of the 148 official CSS color names with their ** corresponding RGB values thru Color Module Level 4: ** https://developer.mozilla.org/en-US/docs/Web/CSS/color_value ** |
︙ | ︙ | |||
3809 3810 3811 3812 3813 3814 3815 | UNUSED_PARAMETER(p); } static PPoint circleChop(Pik *p, PObj *pObj, PPoint *pPt){ PPoint chop; PNum dx = pPt->x - pObj->ptAt.x; PNum dy = pPt->y - pObj->ptAt.y; PNum dist = hypot(dx,dy); | | | 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 | UNUSED_PARAMETER(p); } static PPoint circleChop(Pik *p, PObj *pObj, PPoint *pPt){ PPoint chop; PNum dx = pPt->x - pObj->ptAt.x; PNum dy = pPt->y - pObj->ptAt.y; PNum dist = hypot(dx,dy); if( dist<pObj->rad || dist<=0 ) return pObj->ptAt; chop.x = pObj->ptAt.x + dx*pObj->rad/dist; chop.y = pObj->ptAt.y + dy*pObj->rad/dist; UNUSED_PARAMETER(p); return chop; } static void circleFit(Pik *p, PObj *pObj, PNum w, PNum h){ PNum mx = 0.0; |
︙ | ︙ | |||
4508 4509 4510 4511 4512 4513 4514 | int nNew = (p->nOut+n)*2 + 1; char *z = realloc(p->zOut, nNew); if( z==0 ){ pik_error(p, 0, 0); return; } p->zOut = z; | | | 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 | int nNew = (p->nOut+n)*2 + 1; char *z = realloc(p->zOut, nNew); if( z==0 ){ pik_error(p, 0, 0); return; } p->zOut = z; p->nOutAlloc = nNew; } memcpy(p->zOut+p->nOut, zText, n); p->nOut += n; p->zOut[p->nOut] = 0; } /* |
︙ | ︙ | |||
4634 4635 4636 4637 4638 4639 4640 | /* Append a PNum value surrounded by text. Do coordinate transformations ** on the value. */ static void pik_append_x(Pik *p, const char *z1, PNum v, const char *z2){ char buf[200]; v -= p->bbox.sw.x; | | | | | | 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 | /* Append a PNum value surrounded by text. Do coordinate transformations ** on the value. */ static void pik_append_x(Pik *p, const char *z1, PNum v, const char *z2){ char buf[200]; v -= p->bbox.sw.x; snprintf(buf, sizeof(buf)-1, "%s%d%s", z1, pik_round(p->rScale*v), z2); buf[sizeof(buf)-1] = 0; pik_append(p, buf, -1); } static void pik_append_y(Pik *p, const char *z1, PNum v, const char *z2){ char buf[200]; v = p->bbox.ne.y - v; snprintf(buf, sizeof(buf)-1, "%s%d%s", z1, pik_round(p->rScale*v), z2); buf[sizeof(buf)-1] = 0; pik_append(p, buf, -1); } static void pik_append_xy(Pik *p, const char *z1, PNum x, PNum y){ char buf[200]; x = x - p->bbox.sw.x; y = p->bbox.ne.y - y; snprintf(buf, sizeof(buf)-1, "%s%d,%d", z1, pik_round(p->rScale*x), pik_round(p->rScale*y)); buf[sizeof(buf)-1] = 0; pik_append(p, buf, -1); } static void pik_append_dis(Pik *p, const char *z1, PNum v, const char *z2){ char buf[200]; snprintf(buf, sizeof(buf)-1, "%s%g%s", z1, p->rScale*v, z2); buf[sizeof(buf)-1] = 0; pik_append(p, buf, -1); } /* Append a color specification to the output. ** ** In PIKCHR_DARK_MODE, the color is inverted. The "bg" flags indicates that ** the color is intended for use as a background color if true, or as a ** foreground color if false. The distinction only matters for color ** inversions in PIKCHR_DARK_MODE. */ static void pik_append_clr(Pik *p,const char *z1,PNum v,const char *z2,int bg){ char buf[200]; int x = pik_round(v); int r, g, b; if( x==0 && p->fgcolor>0 && !bg ){ x = p->fgcolor; }else if( bg && x>=0xffffff && p->bgcolor>0 ){ x = p->bgcolor; }else if( p->mFlags & PIKCHR_DARK_MODE ){ x = pik_color_to_dark_mode(x,bg); |
︙ | ︙ | |||
4696 4697 4698 4699 4700 4701 4702 | ** A r1 r2 0 0 0 x y */ static void pik_append_arc(Pik *p, PNum r1, PNum r2, PNum x, PNum y){ char buf[200]; x = x - p->bbox.sw.x; y = p->bbox.ne.y - y; snprintf(buf, sizeof(buf)-1, "A%d %d 0 0 0 %d %d", | | | | 4701 4702 4703 4704 4705 4706 4707 4708 4709 4710 4711 4712 4713 4714 4715 4716 | ** A r1 r2 0 0 0 x y */ static void pik_append_arc(Pik *p, PNum r1, PNum r2, PNum x, PNum y){ char buf[200]; x = x - p->bbox.sw.x; y = p->bbox.ne.y - y; snprintf(buf, sizeof(buf)-1, "A%d %d 0 0 0 %d %d", pik_round(p->rScale*r1), pik_round(p->rScale*r2), pik_round(p->rScale*x), pik_round(p->rScale*y)); buf[sizeof(buf)-1] = 0; pik_append(p, buf, -1); } /* Append a style="..." text. But, leave the quote unterminated, in case ** the caller wants to add some more. ** |
︙ | ︙ | |||
5239 5240 5241 5242 5243 5244 5245 5246 5247 5248 5249 5250 5251 5252 | } /* Return true if a bounding box is empty. */ static int pik_bbox_isempty(PBox *p){ return p->sw.x>p->ne.x; } /* Initialize a bounding box to an empty container */ static void pik_bbox_init(PBox *p){ p->sw.x = 1.0; p->sw.y = 1.0; p->ne.x = 0.0; | > > > > > > > > > > > | 5244 5245 5246 5247 5248 5249 5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 5264 5265 5266 5267 5268 | } /* Return true if a bounding box is empty. */ static int pik_bbox_isempty(PBox *p){ return p->sw.x>p->ne.x; } /* Return true if point pPt is contained within the bounding box pBox */ static int pik_bbox_contains_point(PBox *pBox, PPoint *pPt){ if( pik_bbox_isempty(pBox) ) return 0; if( pPt->x < pBox->sw.x ) return 0; if( pPt->x > pBox->ne.x ) return 0; if( pPt->y < pBox->sw.y ) return 0; if( pPt->y > pBox->ne.y ) return 0; return 1; } /* Initialize a bounding box to an empty container */ static void pik_bbox_init(PBox *p){ p->sw.x = 1.0; p->sw.y = 1.0; p->ne.x = 0.0; |
︙ | ︙ | |||
5389 5390 5391 5392 5393 5394 5395 | case DIR_UP: pNew->eWith = CP_S; break; case DIR_DOWN: pNew->eWith = CP_N; break; } } p->aTPath[0] = pNew->ptAt; pNew->with = pNew->ptAt; pNew->outDir = pNew->inDir = p->eDir; | | | 5405 5406 5407 5408 5409 5410 5411 5412 5413 5414 5415 5416 5417 5418 5419 | case DIR_UP: pNew->eWith = CP_S; break; case DIR_DOWN: pNew->eWith = CP_N; break; } } p->aTPath[0] = pNew->ptAt; pNew->with = pNew->ptAt; pNew->outDir = pNew->inDir = p->eDir; pNew->iLayer = pik_value_int(p, "layer", 5, &miss); if( miss ) pNew->iLayer = 1000; if( pNew->iLayer<0 ) pNew->iLayer = 0; if( pSublist ){ pNew->type = &sublistClass; pNew->pSublist = pSublist; sublistClass.xInit(p,pNew); return pNew; |
︙ | ︙ | |||
5835 5836 5837 5838 5839 5840 5841 5842 5843 5844 5845 5846 5847 5848 | if( p->mTPath & 1 ) n = pik_next_rpath(p, pDir); p->aTPath[n].x = pPlace->x; p->mTPath |= 1; break; } pObj->outDir = pDir->eCode; } /* Set the "from" of an object */ static void pik_set_from(Pik *p, PObj *pObj, PToken *pTk, PPoint *pPt){ if( !pObj->type->isLine ){ pik_error(p, pTk, "use \"at\" to position this object"); return; | > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 5851 5852 5853 5854 5855 5856 5857 5858 5859 5860 5861 5862 5863 5864 5865 5866 5867 5868 5869 5870 5871 5872 5873 5874 5875 5876 5877 5878 5879 5880 5881 5882 5883 5884 5885 5886 5887 5888 5889 5890 5891 5892 | if( p->mTPath & 1 ) n = pik_next_rpath(p, pDir); p->aTPath[n].x = pPlace->x; p->mTPath |= 1; break; } pObj->outDir = pDir->eCode; } /* If the last referenced object is centered at point pPt then return ** a pointer to that object. If there is no prior object reference, ** or if the points are not the same, return NULL. ** ** This is a side-channel hack used to find the objects at which a ** line begins and ends. For example, in ** ** arrow from OBJ1 to OBJ2 chop ** ** The arrow object is normally just handed the coordinates of the ** centers for OBJ1 and OBJ2. But we also want to know the specific ** object named in case there are multiple objects centered at the ** same point. ** ** See forum post 1d46e3a0bc */ static PObj *pik_last_ref_object(Pik *p, PPoint *pPt){ PObj *pRes = 0; if( p->lastRef==0 ) return 0; if( p->lastRef->ptAt.x==pPt->x && p->lastRef->ptAt.y==pPt->y ){ pRes = p->lastRef; } p->lastRef = 0; return pRes; } /* Set the "from" of an object */ static void pik_set_from(Pik *p, PObj *pObj, PToken *pTk, PPoint *pPt){ if( !pObj->type->isLine ){ pik_error(p, pTk, "use \"at\" to position this object"); return; |
︙ | ︙ | |||
5863 5864 5865 5866 5867 5868 5869 5870 5871 5872 5873 5874 5875 5876 5877 5878 5879 5880 5881 5882 5883 5884 5885 5886 5887 5888 5889 5890 5891 5892 5893 5894 5895 5896 | p->aTPath[i].x += dx; p->aTPath[i].y += dy; } } p->aTPath[0] = *pPt; p->mTPath = 3; pObj->mProp |= A_FROM; } /* Set the "to" of an object */ static void pik_add_to(Pik *p, PObj *pObj, PToken *pTk, PPoint *pPt){ int n = p->nTPath-1; if( !pObj->type->isLine ){ pik_error(p, pTk, "use \"at\" to position this object"); return; } if( pObj->bClose ){ pik_error(p, pTk, "polygon is closed"); return; } pik_reset_samepath(p); if( n==0 || p->mTPath==3 || p->thenFlag ){ n = pik_next_rpath(p, pTk); } p->aTPath[n] = *pPt; p->mTPath = 3; } static void pik_close_path(Pik *p, PToken *pErr){ PObj *pObj = p->cur; if( p->nTPath<3 ){ pik_error(p, pErr, "need at least 3 vertexes in order to close the polygon"); | > > | 5907 5908 5909 5910 5911 5912 5913 5914 5915 5916 5917 5918 5919 5920 5921 5922 5923 5924 5925 5926 5927 5928 5929 5930 5931 5932 5933 5934 5935 5936 5937 5938 5939 5940 5941 5942 | p->aTPath[i].x += dx; p->aTPath[i].y += dy; } } p->aTPath[0] = *pPt; p->mTPath = 3; pObj->mProp |= A_FROM; pObj->pFrom = pik_last_ref_object(p, pPt); } /* Set the "to" of an object */ static void pik_add_to(Pik *p, PObj *pObj, PToken *pTk, PPoint *pPt){ int n = p->nTPath-1; if( !pObj->type->isLine ){ pik_error(p, pTk, "use \"at\" to position this object"); return; } if( pObj->bClose ){ pik_error(p, pTk, "polygon is closed"); return; } pik_reset_samepath(p); if( n==0 || p->mTPath==3 || p->thenFlag ){ n = pik_next_rpath(p, pTk); } p->aTPath[n] = *pPt; p->mTPath = 3; pObj->pTo = pik_last_ref_object(p, pPt); } static void pik_close_path(Pik *p, PToken *pErr){ PObj *pObj = p->cur; if( p->nTPath<3 ){ pik_error(p, pErr, "need at least 3 vertexes in order to close the polygon"); |
︙ | ︙ | |||
6218 6219 6220 6221 6222 6223 6224 6225 6226 6227 6228 6229 6230 6231 | pVar->val /= val; } break; default: pVar->val = val; break; } p->bLayoutVars = 0; /* Clear the layout setting cache */ } /* ** Search for the variable named z[0..n-1] in: ** ** * Application defined variables ** * Built-in variables ** | > > > > > > > > > > | 6264 6265 6266 6267 6268 6269 6270 6271 6272 6273 6274 6275 6276 6277 6278 6279 6280 6281 6282 6283 6284 6285 6286 6287 | pVar->val /= val; } break; default: pVar->val = val; break; } p->bLayoutVars = 0; /* Clear the layout setting cache */ } /* ** Round a PNum into the nearest integer */ static int pik_round(PNum v){ if( isnan(v) ) return 0; if( v < -2147483647 ) return -2147483648; if( v >= 2147483647 ) return 2147483647; return (int)v; } /* ** Search for the variable named z[0..n-1] in: ** ** * Application defined variables ** * Built-in variables ** |
︙ | ︙ | |||
6256 6257 6258 6259 6260 6261 6262 6263 6264 6265 6266 6267 6268 6269 | first = mid+1; }else{ last = mid-1; } } if( pMiss ) *pMiss = 1; return 0.0; } /* ** Look up a color-name. Unlike other names in this program, the ** color-names are not case sensitive. So "DarkBlue" and "darkblue" ** and "DARKBLUE" all find the same value (139). ** | > > > | 6312 6313 6314 6315 6316 6317 6318 6319 6320 6321 6322 6323 6324 6325 6326 6327 6328 | first = mid+1; }else{ last = mid-1; } } if( pMiss ) *pMiss = 1; return 0.0; } static int pik_value_int(Pik *p, const char *z, int n, int *pMiss){ return pik_round(pik_value(p,z,n,pMiss)); } /* ** Look up a color-name. Unlike other names in this program, the ** color-names are not case sensitive. So "DarkBlue" and "darkblue" ** and "DARKBLUE" all find the same value (139). ** |
︙ | ︙ | |||
6411 6412 6413 6414 6415 6416 6417 6418 6419 6420 6421 6422 6423 6424 6425 6426 6427 6428 6429 6430 6431 6432 6433 6434 | pik_error(p, pName, "no such object"); return 0; } /* First look explicitly tagged objects */ for(i=pList->n-1; i>=0; i--){ PObj *pObj = pList->a[i]; if( pObj->zName && pik_token_eq(pName,pObj->zName)==0 ){ return pObj; } } /* If not found, do a second pass looking for any object containing ** text which exactly matches pName */ for(i=pList->n-1; i>=0; i--){ PObj *pObj = pList->a[i]; for(j=0; j<pObj->nTxt; j++){ if( pObj->aTxt[j].n==pName->n+2 && memcmp(pObj->aTxt[j].z+1,pName->z,pName->n)==0 ){ return pObj; } } } pik_error(p, pName, "no such object"); return 0; } | > > | 6470 6471 6472 6473 6474 6475 6476 6477 6478 6479 6480 6481 6482 6483 6484 6485 6486 6487 6488 6489 6490 6491 6492 6493 6494 6495 | pik_error(p, pName, "no such object"); return 0; } /* First look explicitly tagged objects */ for(i=pList->n-1; i>=0; i--){ PObj *pObj = pList->a[i]; if( pObj->zName && pik_token_eq(pName,pObj->zName)==0 ){ p->lastRef = pObj; return pObj; } } /* If not found, do a second pass looking for any object containing ** text which exactly matches pName */ for(i=pList->n-1; i>=0; i--){ PObj *pObj = pList->a[i]; for(j=0; j<pObj->nTxt; j++){ if( pObj->aTxt[j].n==pName->n+2 && memcmp(pObj->aTxt[j].z+1,pName->z,pName->n)==0 ){ p->lastRef = pObj; return pObj; } } } pik_error(p, pName, "no such object"); return 0; } |
︙ | ︙ | |||
6555 6556 6557 6558 6559 6560 6561 | return pObj->aPath[n-1]; } /* Return the value of a property of an object. */ static PNum pik_property_of(PObj *pObj, PToken *pProp){ PNum v = 0.0; | > | | | | | | | | | | | | | | | | > | 6616 6617 6618 6619 6620 6621 6622 6623 6624 6625 6626 6627 6628 6629 6630 6631 6632 6633 6634 6635 6636 6637 6638 6639 6640 6641 6642 6643 6644 6645 6646 6647 | return pObj->aPath[n-1]; } /* Return the value of a property of an object. */ static PNum pik_property_of(PObj *pObj, PToken *pProp){ PNum v = 0.0; if( pObj ){ switch( pProp->eType ){ case T_HEIGHT: v = pObj->h; break; case T_WIDTH: v = pObj->w; break; case T_RADIUS: v = pObj->rad; break; case T_DIAMETER: v = pObj->rad*2.0; break; case T_THICKNESS: v = pObj->sw; break; case T_DASHED: v = pObj->dashed; break; case T_DOTTED: v = pObj->dotted; break; case T_FILL: v = pObj->fill; break; case T_COLOR: v = pObj->color; break; case T_X: v = pObj->ptAt.x; break; case T_Y: v = pObj->ptAt.y; break; case T_TOP: v = pObj->bbox.ne.y; break; case T_BOTTOM: v = pObj->bbox.sw.y; break; case T_LEFT: v = pObj->bbox.sw.x; break; case T_RIGHT: v = pObj->bbox.ne.x; break; } } return v; } /* Compute one of the built-in functions */ static PNum pik_func(Pik *p, PToken *pFunc, PNum x, PNum y){ |
︙ | ︙ | |||
6616 6617 6618 6619 6620 6621 6622 | memcpy(pObj->zName,pName->z,pName->n); pObj->zName[pName->n] = 0; } return; } /* | | > > | > | | | | > > > > | > | > | 6679 6680 6681 6682 6683 6684 6685 6686 6687 6688 6689 6690 6691 6692 6693 6694 6695 6696 6697 6698 6699 6700 6701 6702 6703 6704 6705 6706 6707 6708 6709 6710 6711 6712 6713 6714 6715 6716 6717 6718 6719 6720 6721 6722 6723 6724 6725 6726 6727 6728 6729 6730 6731 | memcpy(pObj->zName,pName->z,pName->n); pObj->zName[pName->n] = 0; } return; } /* ** Search for object located at *pCenter that has an xChop method and ** that does not enclose point pOther. ** ** Return a pointer to the object, or NULL if not found. */ static PObj *pik_find_chopper(PList *pList, PPoint *pCenter, PPoint *pOther){ int i; if( pList==0 ) return 0; for(i=pList->n-1; i>=0; i--){ PObj *pObj = pList->a[i]; if( pObj->type->xChop!=0 && pObj->ptAt.x==pCenter->x && pObj->ptAt.y==pCenter->y && !pik_bbox_contains_point(&pObj->bbox, pOther) ){ return pObj; }else if( pObj->pSublist ){ pObj = pik_find_chopper(pObj->pSublist,pCenter,pOther); if( pObj ) return pObj; } } return 0; } /* ** There is a line traveling from pFrom to pTo. ** ** If pObj is not null and is a choppable object, then chop at ** the boundary of pObj - where the line crosses the boundary ** of pObj. ** ** If pObj is NULL or has no xChop method, then search for some ** other object centered at pTo that is choppable and use it ** instead. */ static void pik_autochop(Pik *p, PPoint *pFrom, PPoint *pTo, PObj *pObj){ if( pObj==0 || pObj->type->xChop==0 ){ pObj = pik_find_chopper(p->list, pTo, pFrom); } if( pObj ){ *pTo = pObj->type->xChop(p, pObj, pFrom); } } /* This routine runs after all attributes have been received ** on an object. |
︙ | ︙ | |||
6744 6745 6746 6747 6748 6749 6750 | /* "chop" processing: ** If the line goes to the center of an object with an ** xChop method, then use the xChop method to trim the line. */ if( pObj->bChop && pObj->nPath>=2 ){ int n = pObj->nPath; | | | | 6816 6817 6818 6819 6820 6821 6822 6823 6824 6825 6826 6827 6828 6829 6830 6831 | /* "chop" processing: ** If the line goes to the center of an object with an ** xChop method, then use the xChop method to trim the line. */ if( pObj->bChop && pObj->nPath>=2 ){ int n = pObj->nPath; pik_autochop(p, &pObj->aPath[n-2], &pObj->aPath[n-1], pObj->pTo); pik_autochop(p, &pObj->aPath[1], &pObj->aPath[0], pObj->pFrom); } pObj->ptEnter = pObj->aPath[0]; pObj->ptExit = pObj->aPath[pObj->nPath-1]; /* Compute the center of the line based on the bounding box over ** the vertexes. This is a difference from PIC. In Pikchr, the |
︙ | ︙ | |||
6840 6841 6842 6843 6844 6845 6846 | */ void pik_elist_render(Pik *p, PList *pList){ int i; int iNextLayer = 0; int iThisLayer; int bMoreToDo; int miss = 0; | | | 6912 6913 6914 6915 6916 6917 6918 6919 6920 6921 6922 6923 6924 6925 6926 | */ void pik_elist_render(Pik *p, PList *pList){ int i; int iNextLayer = 0; int iThisLayer; int bMoreToDo; int miss = 0; int mDebug = pik_value_int(p, "debug", 5, 0); PNum colorLabel; do{ bMoreToDo = 0; iThisLayer = iNextLayer; iNextLayer = 0x7fffffff; for(i=0; i<pList->n; i++){ PObj *pObj = pList->a[i]; |
︙ | ︙ | |||
6958 6959 6960 6961 6962 6963 6964 | pik_compute_layout_settings(p); thickness = pik_value(p,"thickness",9,0); if( thickness<=0.01 ) thickness = 0.01; margin = pik_value(p,"margin",6,0); margin += thickness; wArrow = p->wArrow*thickness; miss = 0; | | | | | | 7030 7031 7032 7033 7034 7035 7036 7037 7038 7039 7040 7041 7042 7043 7044 7045 7046 7047 7048 7049 7050 7051 7052 7053 7054 7055 7056 7057 | pik_compute_layout_settings(p); thickness = pik_value(p,"thickness",9,0); if( thickness<=0.01 ) thickness = 0.01; margin = pik_value(p,"margin",6,0); margin += thickness; wArrow = p->wArrow*thickness; miss = 0; p->fgcolor = pik_value_int(p,"fgcolor",7,&miss); if( miss ){ PToken t; t.z = "fgcolor"; t.n = 7; p->fgcolor = pik_round(pik_lookup_color(0, &t)); } miss = 0; p->bgcolor = pik_value_int(p,"bgcolor",7,&miss); if( miss ){ PToken t; t.z = "bgcolor"; t.n = 7; p->bgcolor = pik_round(pik_lookup_color(0, &t)); } /* Compute a bounding box over all objects so that we can know ** how big to declare the SVG canvas */ pik_bbox_init(&p->bbox); pik_bbox_add_elist(p, pList, wArrow); |
︙ | ︙ | |||
6995 6996 6997 6998 6999 7000 7001 | if( p->zClass ){ pik_append(p, " class=\"", -1); pik_append(p, p->zClass, -1); pik_append(p, "\"", 1); } w = p->bbox.ne.x - p->bbox.sw.x; h = p->bbox.ne.y - p->bbox.sw.y; | | | | | | 7067 7068 7069 7070 7071 7072 7073 7074 7075 7076 7077 7078 7079 7080 7081 7082 7083 7084 7085 7086 7087 7088 | if( p->zClass ){ pik_append(p, " class=\"", -1); pik_append(p, p->zClass, -1); pik_append(p, "\"", 1); } w = p->bbox.ne.x - p->bbox.sw.x; h = p->bbox.ne.y - p->bbox.sw.y; p->wSVG = pik_round(p->rScale*w); p->hSVG = pik_round(p->rScale*h); pikScale = pik_value(p,"scale",5,0); if( pikScale>=0.001 && pikScale<=1000.0 && (pikScale<0.99 || pikScale>1.01) ){ p->wSVG = pik_round(p->wSVG*pikScale); p->hSVG = pik_round(p->hSVG*pikScale); pik_append_num(p, " width=\"", p->wSVG); pik_append_num(p, "\" height=\"", p->hSVG); pik_append(p, "\"", 1); } pik_append_dis(p, " viewBox=\"0 0 ",w,""); pik_append_dis(p, " ",h,"\">\n"); pik_elist_render(p, pList); |
︙ | ︙ | |||
7747 7748 7749 7750 7751 7752 7753 7754 7755 7756 7757 | } #if defined(PIKCHR_FUZZ) #include <stdint.h> int LLVMFuzzerTestOneInput(const uint8_t *aData, size_t nByte){ int w,h; char *zIn, *zOut; zIn = malloc( nByte + 1 ); if( zIn==0 ) return 0; memcpy(zIn, aData, nByte); zIn[nByte] = 0; | > | | 7819 7820 7821 7822 7823 7824 7825 7826 7827 7828 7829 7830 7831 7832 7833 7834 7835 7836 7837 7838 | } #if defined(PIKCHR_FUZZ) #include <stdint.h> int LLVMFuzzerTestOneInput(const uint8_t *aData, size_t nByte){ int w,h; char *zIn, *zOut; unsigned int mFlags = nByte & 3; zIn = malloc( nByte + 1 ); if( zIn==0 ) return 0; memcpy(zIn, aData, nByte); zIn[nByte] = 0; zOut = pikchr(zIn, "pikchr", mFlags, &w, &h); free(zIn); free(zOut); return 0; } #endif /* PIKCHR_FUZZ */ #if defined(PIKCHR_SHELL) |
︙ | ︙ | |||
7986 7987 7988 7989 7990 7991 7992 7993 7994 7995 7996 7997 | Tcl_ListObjAppendElement(0, pRes, Tcl_NewStringObj(zOut, -1)); free(zOut); Tcl_ListObjAppendElement(0, pRes, Tcl_NewIntObj(w)); Tcl_ListObjAppendElement(0, pRes, Tcl_NewIntObj(h)); Tcl_SetObjResult(interp, pRes); return TCL_OK; } /* Invoke this routine to register the "pikchr" command with the interpreter ** given in the argument */ int Pikchr_Init(Tcl_Interp *interp){ Tcl_CreateObjCommand(interp, "pikchr", pik_tcl_command, 0, 0); | > > > > > > > | | | 8059 8060 8061 8062 8063 8064 8065 8066 8067 8068 8069 8070 8071 8072 8073 8074 8075 8076 8077 8078 8079 8080 8081 8082 8083 8084 8085 8086 | Tcl_ListObjAppendElement(0, pRes, Tcl_NewStringObj(zOut, -1)); free(zOut); Tcl_ListObjAppendElement(0, pRes, Tcl_NewIntObj(w)); Tcl_ListObjAppendElement(0, pRes, Tcl_NewIntObj(h)); Tcl_SetObjResult(interp, pRes); return TCL_OK; } #ifndef PACKAGE_NAME # define PACKAGE_NAME "pikchr" #endif #ifndef PACKAGE_VERSION # define PACKAGE_VERSION "1.0" #endif /* Invoke this routine to register the "pikchr" command with the interpreter ** given in the argument */ int Pikchr_Init(Tcl_Interp *interp){ Tcl_CreateObjCommand(interp, "pikchr", pik_tcl_command, 0, 0); Tcl_PkgProvide(interp, PACKAGE_NAME, PACKAGE_VERSION); return TCL_OK; } #endif /* PIKCHR_TCL */ #line 8111 "pikchr.c" |
Changes to src/printf.c.
︙ | ︙ | |||
100 101 102 103 104 105 106 | #define etPATH 21 /* Path type */ #define etWIKISTR 22 /* Timeline comment text rendered from a char*: %W */ #define etSTRINGID 23 /* String with length limit for a hash prefix: %S */ #define etROOT 24 /* String value of g.zTop: %R */ #define etJSONSTR 25 /* String encoded as a JSON string literal: %j Use %!j to include double-quotes around it. */ #define etSHELLESC 26 /* Escape a filename for use in a shell command: %$ | | > > | 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | #define etPATH 21 /* Path type */ #define etWIKISTR 22 /* Timeline comment text rendered from a char*: %W */ #define etSTRINGID 23 /* String with length limit for a hash prefix: %S */ #define etROOT 24 /* String value of g.zTop: %R */ #define etJSONSTR 25 /* String encoded as a JSON string literal: %j Use %!j to include double-quotes around it. */ #define etSHELLESC 26 /* Escape a filename for use in a shell command: %$ See blob_append_escaped_arg() for details "%$" -> adds "./" prefix if necessary. "%!$" -> omits the "./" prefix. */ /* ** An "etByte" is an 8-bit unsigned value. */ typedef unsigned char etByte; |
︙ | ︙ | |||
836 837 838 839 840 841 842 | wiki_convert(&wiki, pBlob, wiki_convert_flags(flag_altform2)); blob_reset(&wiki); length = width = 0; break; } case etSHELLESC: { char *zArg = va_arg(ap, char*); | | | 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 | wiki_convert(&wiki, pBlob, wiki_convert_flags(flag_altform2)); blob_reset(&wiki); length = width = 0; break; } case etSHELLESC: { char *zArg = va_arg(ap, char*); blob_append_escaped_arg(pBlob, zArg, !flag_altform2); length = width = 0; break; } case etERROR: buf[0] = '%'; buf[1] = c; errorflag = 0; |
︙ | ︙ |
Changes to src/report.c.
︙ | ︙ | |||
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | /* Forward references to static routines */ static void report_format_hints(void); #ifndef SQLITE_RECURSIVE # define SQLITE_RECURSIVE 33 #endif /* ** WEBPAGE: reportlist ** ** Main menu for Tickets. */ void view_list(void){ const char *zScript; Blob ril; /* Report Item List */ Stmt q; int rn = 0; int cnt = 0; login_check_credentials(); if( !g.perm.RdTkt && !g.perm.NewTkt ){ login_needed(g.anon.RdTkt || g.anon.NewTkt); return; } style_header("Ticket Main Menu"); | > > > > > > > > > | 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | /* Forward references to static routines */ static void report_format_hints(void); #ifndef SQLITE_RECURSIVE # define SQLITE_RECURSIVE 33 #endif /* Settings that can be used to control ticket reports */ /* ** SETTING: ticket-default-report width=80 ** If this setting has a string value, then when the ticket ** search page query is blank, the report with this title is shown. ** If the setting is blank (default), then no report is shown. */ /* ** WEBPAGE: reportlist ** ** Main menu for Tickets. */ void view_list(void){ const char *zScript; Blob ril; /* Report Item List */ Stmt q; int rn = 0; int cnt = 0; char *defaultReport = db_get("ticket-default-report", 0); login_check_credentials(); if( !g.perm.RdTkt && !g.perm.NewTkt ){ login_needed(g.anon.RdTkt || g.anon.NewTkt); return; } style_header("Ticket Main Menu"); |
︙ | ︙ | |||
83 84 85 86 87 88 89 90 91 92 93 94 95 96 | ){ blob_appendf(&ril, "[%zedit</a>]", href("%R/rptedit?rn=%d", rn)); } if( g.perm.TktFmt ){ blob_appendf(&ril, "[%zsql</a>]", href("%R/rptsql?rn=%d", rn)); } blob_appendf(&ril, "</li>\n"); } db_finalize(&q); Th_Store("report_items", blob_str(&ril)); | > > > | 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | ){ blob_appendf(&ril, "[%zedit</a>]", href("%R/rptedit?rn=%d", rn)); } if( g.perm.TktFmt ){ blob_appendf(&ril, "[%zsql</a>]", href("%R/rptsql?rn=%d", rn)); } if( fossil_strcmp(zTitle, defaultReport)==0 ){ blob_appendf(&ril, " ← default"); } blob_appendf(&ril, "</li>\n"); } db_finalize(&q); Th_Store("report_items", blob_str(&ril)); |
︙ | ︙ | |||
350 351 352 353 354 355 356 | @ <table cellpadding=0 cellspacing=0 border=0> @ <tr><td valign="top" align="right">Title:</td><td width=15></td> @ <td colspan="3">%h(zTitle)</td></tr> @ <tr><td valign="top" align="right">Owner:</td><td></td> @ <td colspan="3">%h(zOwner)</td></tr> @ <tr><td valign="top" align="right">SQL:</td><td></td> @ <td valign="top"><pre> | | | 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 | @ <table cellpadding=0 cellspacing=0 border=0> @ <tr><td valign="top" align="right">Title:</td><td width=15></td> @ <td colspan="3">%h(zTitle)</td></tr> @ <tr><td valign="top" align="right">Owner:</td><td></td> @ <td colspan="3">%h(zOwner)</td></tr> @ <tr><td valign="top" align="right">SQL:</td><td></td> @ <td valign="top"><pre> @ <code class="language-sql">%h(zSQL)</code> @ </pre></td> @ <td width=15></td><td valign="top"> output_color_key(zClrKey, 0, "border=0 cellspacing=0 cellpadding=3"); @ </td> @ </tr></table> report_format_hints(); style_finish_page(); |
︙ | ︙ | |||
382 383 384 385 386 387 388 389 390 391 392 393 394 395 | int rn; const char *zTitle; const char *z; const char *zOwner; const char *zClrKey; char *zSQL; char *zErr = 0; login_check_credentials(); if( !g.perm.TktFmt ){ login_needed(g.anon.TktFmt); return; } style_set_current_feature("report"); | > | 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 | int rn; const char *zTitle; const char *z; const char *zOwner; const char *zClrKey; char *zSQL; char *zErr = 0; int dflt = P("dflt") ? 1 : 0; login_check_credentials(); if( !g.perm.TktFmt ){ login_needed(g.anon.TktFmt); return; } style_set_current_feature("report"); |
︙ | ︙ | |||
450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 | " owner=%Q, cols=%Q, mtime=now() WHERE rn=%d", zTitle, zSQL, zOwner, zClrKey, rn); }else{ db_multi_exec("INSERT INTO reportfmt(title,sqlcode,owner,cols,mtime) " "VALUES(%Q,%Q,%Q,%Q,now())", zTitle, zSQL, zOwner, zClrKey); rn = db_last_insert_rowid(); } cgi_redirect(mprintf("rptview?rn=%d", rn)); return; } }else if( rn==0 ){ zTitle = ""; zSQL = ticket_report_template(); zClrKey = ticket_key_template(); }else{ Stmt q; db_prepare(&q, "SELECT title, sqlcode, owner, cols " "FROM reportfmt WHERE rn=%d",rn); if( db_step(&q)==SQLITE_ROW ){ zTitle = db_column_malloc(&q, 0); zSQL = db_column_malloc(&q, 1); zOwner = db_column_malloc(&q, 2); zClrKey = db_column_malloc(&q, 3); } db_finalize(&q); if( P("copy") ){ rn = 0; zTitle = mprintf("Copy Of %s", zTitle); zOwner = g.zLogin; } | > > > > > > > > > > | 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 | " owner=%Q, cols=%Q, mtime=now() WHERE rn=%d", zTitle, zSQL, zOwner, zClrKey, rn); }else{ db_multi_exec("INSERT INTO reportfmt(title,sqlcode,owner,cols,mtime) " "VALUES(%Q,%Q,%Q,%Q,now())", zTitle, zSQL, zOwner, zClrKey); rn = db_last_insert_rowid(); } if( dflt ){ db_set("ticket-default-report", zTitle, 0); }else{ char *defaultReport = db_get("ticket-default-report", 0); if( fossil_strcmp(zTitle, defaultReport)==0 ){ db_set("ticket-default-report", "", 0); } } cgi_redirect(mprintf("rptview?rn=%d", rn)); return; } }else if( rn==0 ){ zTitle = ""; zSQL = ticket_report_template(); zClrKey = ticket_key_template(); }else{ Stmt q; db_prepare(&q, "SELECT title, sqlcode, owner, cols " "FROM reportfmt WHERE rn=%d",rn); if( db_step(&q)==SQLITE_ROW ){ char *defaultReport = db_get("ticket-default-report", 0); zTitle = db_column_malloc(&q, 0); zSQL = db_column_malloc(&q, 1); zOwner = db_column_malloc(&q, 2); zClrKey = db_column_malloc(&q, 3); dflt = fossil_strcmp(zTitle, defaultReport)==0; } db_finalize(&q); if( P("copy") ){ rn = 0; zTitle = mprintf("Copy Of %s", zTitle); zOwner = g.zLogin; } |
︙ | ︙ | |||
505 506 507 508 509 510 511 512 513 514 515 516 517 518 | } @ <p>Enter an optional color key in the following box. (If blank, no @ color key is displayed.) Each line contains the text for a single @ entry in the key. The first token of each line is the background @ color for that line.<br /> @ <textarea name="k" rows="8" cols="50">%h(zClrKey)</textarea> @ </p> if( !g.perm.Admin && fossil_strcmp(zOwner,g.zLogin)!=0 ){ @ <p>This report format is owned by %h(zOwner). You are not allowed @ to change it.</p> @ </form> report_format_hints(); style_finish_page(); return; | > > | 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 | } @ <p>Enter an optional color key in the following box. (If blank, no @ color key is displayed.) Each line contains the text for a single @ entry in the key. The first token of each line is the background @ color for that line.<br /> @ <textarea name="k" rows="8" cols="50">%h(zClrKey)</textarea> @ </p> @ <p><label><input type="checkbox" name="dflt" %s(dflt?"checked":"")> \ @ Make this the default report</label></p> if( !g.perm.Admin && fossil_strcmp(zOwner,g.zLogin)!=0 ){ @ <p>This report format is owned by %h(zOwner). You are not allowed @ to change it.</p> @ </form> report_format_hints(); style_finish_page(); return; |
︙ | ︙ | |||
535 536 537 538 539 540 541 | zSchema = db_text(0,"SELECT sql FROM sqlite_schema WHERE name='ticket'"); if( zSchema==0 ){ zSchema = db_text(0,"SELECT sql FROM repository.sqlite_schema" " WHERE name='ticket'"); } @ <hr /><h3>TICKET Schema</h3> @ <blockquote><pre> | | | 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 | zSchema = db_text(0,"SELECT sql FROM sqlite_schema WHERE name='ticket'"); if( zSchema==0 ){ zSchema = db_text(0,"SELECT sql FROM repository.sqlite_schema" " WHERE name='ticket'"); } @ <hr /><h3>TICKET Schema</h3> @ <blockquote><pre> @ <code class="language-sql">%h(zSchema)</code> @ </pre></blockquote> @ <h3>Notes</h3> @ <ul> @ <li><p>The SQL must consist of a single SELECT statement</p></li> @ @ <li><p>If a column of the result set is named "#" then that column @ is assumed to hold a ticket number. A hyperlink will be created from |
︙ | ︙ | |||
980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 | ** ** Generate a report. The rn query parameter is the report number ** corresponding to REPORTFMT.RN. If the tablist query parameter exists, ** then the output consists of lines of tab-separated fields instead of ** an HTML table. */ void rptview_page(void){ int count = 0; int rn, rc; char *zSql; char *zTitle; char *zOwner; char *zClrKey; int tabs; Stmt q; char *zErr1 = 0; char *zErr2 = 0; login_check_credentials(); if( !g.perm.RdTkt ){ login_needed(g.anon.RdTkt); return; } tabs = P("tablist")!=0; db_prepare(&q, "SELECT title, sqlcode, owner, cols, rn FROM reportfmt WHERE rn=%d", atoi(PD("rn","0"))); rc = db_step(&q); if( rc!=SQLITE_ROW ){ db_finalize(&q); db_prepare(&q, "SELECT title, sqlcode, owner, cols, rn FROM reportfmt WHERE title GLOB %Q", | > > > > > > > > > > > > > > > | > | > | 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 | ** ** Generate a report. The rn query parameter is the report number ** corresponding to REPORTFMT.RN. If the tablist query parameter exists, ** then the output consists of lines of tab-separated fields instead of ** an HTML table. */ void rptview_page(void){ rptview_page_content(0, 1, 1); } /* ** Render a report. */ void rptview_page_content( const char *defaultTitleSearch, /* If rn and title query parameters are blank, search reports by this title. */ int pageWrap, /* If true, render full page; otherwise, just the report */ int redirectMissing /* If true and report not found, go to reportlist */ ){ int count = 0; int rn, rc; char *zSql; char *zTitle; char *zOwner; char *zClrKey; int tabs; Stmt q; char *zErr1 = 0; char *zErr2 = 0; login_check_credentials(); if( !g.perm.RdTkt ){ login_needed(g.anon.RdTkt); return; } tabs = P("tablist")!=0; db_prepare(&q, "SELECT title, sqlcode, owner, cols, rn FROM reportfmt WHERE rn=%d", atoi(PD("rn","0"))); rc = db_step(&q); if( rc!=SQLITE_ROW ){ const char *titleSearch = defaultTitleSearch==0 || trim_string(defaultTitleSearch)[0]==0 ? P("title") : defaultTitleSearch; db_finalize(&q); db_prepare(&q, "SELECT title, sqlcode, owner, cols, rn FROM reportfmt WHERE title GLOB %Q", titleSearch); rc = db_step(&q); } if( rc!=SQLITE_ROW ){ db_finalize(&q); if( redirectMissing ) { cgi_redirect("reportlist"); } return; } zTitle = db_column_malloc(&q, 0); zSql = db_column_malloc(&q, 1); zOwner = db_column_malloc(&q, 2); zClrKey = db_column_malloc(&q, 3); rn = db_column_int(&q,4); |
︙ | ︙ | |||
1039 1040 1041 1042 1043 1044 1045 | count = 0; if( !tabs ){ struct GenerateHTML sState = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; const char *zQS = PD("QUERY_STRING",""); db_multi_exec("PRAGMA empty_result_callbacks=ON"); style_set_current_feature("report"); | > | | | | | | | | | | | | | | | | | | | > > | > | 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 | count = 0; if( !tabs ){ struct GenerateHTML sState = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; const char *zQS = PD("QUERY_STRING",""); db_multi_exec("PRAGMA empty_result_callbacks=ON"); style_set_current_feature("report"); if( pageWrap ) { /* style_finish_page() should provide escaping via %h formatting */ if( zQS[0] ){ style_submenu_element("Raw","%R/%s?tablist=1&%s",g.zPath,zQS); style_submenu_element("Reports","%R/reportlist?%s",zQS); } else { style_submenu_element("Raw","%R/%s?tablist=1",g.zPath); style_submenu_element("Reports","%R/reportlist"); } if( g.perm.Admin || (g.perm.TktFmt && g.zLogin && fossil_strcmp(g.zLogin,zOwner)==0) ){ style_submenu_element("Edit", "rptedit?rn=%d", rn); } if( g.perm.TktFmt ){ style_submenu_element("SQL", "rptsql?rn=%d",rn); } if( g.perm.NewTkt ){ style_submenu_element("New Ticket", "%R/tktnew"); } style_header("%s", zTitle); } output_color_key(zClrKey, 1, "border=\"0\" cellpadding=\"3\" cellspacing=\"0\" class=\"report\""); @ <table border="1" cellpadding="2" cellspacing="0" class="report sortable" @ data-column-types='' data-init-sort='0'> sState.rn = rn; sState.nCount = 0; report_restrict_sql(&zErr1); db_exec_readonly(g.db, zSql, generate_html, &sState, &zErr2); report_unrestrict_sql(); @ </tbody></table> if( zErr1 ){ @ <p class="reportError">Error: %h(zErr1)</p> }else if( zErr2 ){ @ <p class="reportError">Error: %h(zErr2)</p> } style_table_sorter(); if( pageWrap ) { style_finish_page(); } }else{ report_restrict_sql(&zErr1); db_exec_readonly(g.db, zSql, output_tab_separated, &count, &zErr2); report_unrestrict_sql(); cgi_set_content_type("text/plain"); } } |
︙ | ︙ |
Changes to src/search.c.
︙ | ︙ | |||
1207 1208 1209 1210 1211 1212 1213 1214 | ** t -> tickets ** w -> wiki ** e -> tech notes ** f -> forum ** all -> everything */ void search_page(void){ login_check_credentials(); | > | | 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 | ** t -> tickets ** w -> wiki ** e -> tech notes ** f -> forum ** all -> everything */ void search_page(void){ const int isSearch = P("s")!=0; login_check_credentials(); style_header("Search%s", isSearch ? " Results" : ""); search_screen(SRCH_ALL, 1); style_finish_page(); } /* ** This is a helper function for search_stext(). Writing into pOut |
︙ | ︙ | |||
1928 1929 1930 1931 1932 1933 1934 | /* Adjust search settings */ if( iCmd==3 || iCmd==4 ){ const char *zCtrl; if( g.argc<4 ) usage(mprintf("%s STRING",zSubCmd)); zCtrl = g.argv[3]; for(j=0; j<count(aSetng); j++){ if( strchr(zCtrl, aSetng[j].zSw[0])!=0 ){ | | | 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 | /* Adjust search settings */ if( iCmd==3 || iCmd==4 ){ const char *zCtrl; if( g.argc<4 ) usage(mprintf("%s STRING",zSubCmd)); zCtrl = g.argv[3]; for(j=0; j<count(aSetng); j++){ if( strchr(zCtrl, aSetng[j].zSw[0])!=0 ){ db_set_int(aSetng[j].zSetting/*works-like:"x"*/, iCmd-3, 0); } } } if( iCmd==5 ){ if( g.argc<4 ) usage("porter ON/OFF"); db_set_int("search-stemmer", is_truth(g.argv[3]), 0); } |
︙ | ︙ |
Changes to src/setup.c.
︙ | ︙ | |||
184 185 186 187 188 189 190 | } /* ** Generate a checkbox for an attribute. */ void onoff_attribute( const char *zLabel, /* The text label on the checkbox */ | | | | | 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 | } /* ** Generate a checkbox for an attribute. */ void onoff_attribute( const char *zLabel, /* The text label on the checkbox */ const char *zVar, /* The corresponding row in the CONFIG table */ const char *zQParm, /* The query parameter */ int dfltVal, /* Default value if CONFIG table entry does not exist */ int disabled /* 1 if disabled */ ){ const char *zQ = P(zQParm); int iVal = db_get_boolean(zVar, dfltVal); if( zQ==0 && !disabled && P("submit") ){ zQ = "off"; } if( zQ ){ int iQ = fossil_strcmp(zQ,"on")==0 || atoi(zQ); if( iQ!=iVal ){ login_verify_csrf_secret(); db_protect_only(PROTECT_NONE); db_set(zVar/*works-like:"x"*/, iQ ? "1" : "0", 0); db_protect_pop(); setup_incr_cfgcnt(); admin_log("Set option [%q] to [%q].", zVar, iQ ? "on" : "off"); iVal = iQ; } } |
︙ | ︙ | |||
224 225 226 227 228 229 230 | /* ** Generate an entry box for an attribute. */ void entry_attribute( const char *zLabel, /* The text label on the entry box */ int width, /* Width of the entry box */ | | | | | | | | 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 | /* ** Generate an entry box for an attribute. */ void entry_attribute( const char *zLabel, /* The text label on the entry box */ int width, /* Width of the entry box */ const char *zVar, /* The corresponding row in the CONFIG table */ const char *zQParm, /* The query parameter */ const char *zDflt, /* Default value if CONFIG table entry does not exist */ int disabled /* 1 if disabled */ ){ const char *zVal = db_get(zVar, zDflt); const char *zQ = P(zQParm); if( zQ && fossil_strcmp(zQ,zVal)!=0 ){ const int nZQ = (int)strlen(zQ); login_verify_csrf_secret(); setup_incr_cfgcnt(); db_protect_only(PROTECT_NONE); db_set(zVar/*works-like:"x"*/, zQ, 0); db_protect_pop(); admin_log("Set entry_attribute %Q to: %.*s%s", zVar, 20, zQ, (nZQ>20 ? "..." : "")); zVal = zQ; } @ <input aria-label="%h(zLabel[0]?zLabel:zQParm)" type="text" \ @ id="%s(zQParm)" name="%s(zQParm)" value="%h(zVal)" size="%d(width)" \ if( disabled ){ @ disabled="disabled" \ } @ /> <b>%s(zLabel)</b> } /* ** Generate a text box for an attribute. */ const char *textarea_attribute( const char *zLabel, /* The text label on the textarea */ int rows, /* Rows in the textarea */ int cols, /* Columns in the textarea */ const char *zVar, /* The corresponding row in the CONFIG table */ const char *zQP, /* The query parameter */ const char *zDflt, /* Default value if CONFIG table entry does not exist */ int disabled /* 1 if the textarea should not be editable */ ){ const char *z = db_get(zVar, zDflt); const char *zQ = P(zQP); if( zQ && !disabled && fossil_strcmp(zQ,z)!=0){ const int nZQ = (int)strlen(zQ); login_verify_csrf_secret(); db_protect_only(PROTECT_NONE); db_set(zVar/*works-like:"x"*/, zQ, 0); db_protect_pop(); setup_incr_cfgcnt(); admin_log("Set textarea_attribute %Q to: %.*s%s", zVar, 20, zQ, (nZQ>20 ? "..." : "")); z = zQ; } if( rows>0 && cols>0 ){ |
︙ | ︙ | |||
294 295 296 297 298 299 300 | } /* ** Generate a text box for an attribute. */ void multiple_choice_attribute( const char *zLabel, /* The text label on the menu */ | | | | | 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 | } /* ** Generate a text box for an attribute. */ void multiple_choice_attribute( const char *zLabel, /* The text label on the menu */ const char *zVar, /* The corresponding row in the CONFIG table */ const char *zQP, /* The query parameter */ const char *zDflt, /* Default value if CONFIG table entry does not exist */ int nChoice, /* Number of choices */ const char *const *azChoice /* Choices in pairs (VAR value, Display) */ ){ const char *z = db_get(zVar, zDflt); const char *zQ = P(zQP); int i; if( zQ && fossil_strcmp(zQ,z)!=0){ const int nZQ = (int)strlen(zQ); login_verify_csrf_secret(); db_unprotect(PROTECT_ALL); db_set(zVar/*works-like:"x"*/, zQ, 0); setup_incr_cfgcnt(); db_protect_pop(); admin_log("Set multiple_choice_attribute %Q to: %.*s%s", zVar, 20, zQ, (nZQ>20 ? "..." : "")); z = zQ; } @ <select aria-label="%h(zLabel)" size="1" name="%s(zQP)" id="id%s(zQP)"> |
︙ | ︙ | |||
897 898 899 900 901 902 903 | @ <table border="0"><tr><td valign="top"> login_insert_csrf_secret(); for(i=0, pSet=aSetting; i<nSetting; i++, pSet++){ if( pSet->width==0 ){ int hasVersionableValue = pSet->versionable && (db_get_versioned(pSet->name, NULL)!=0); onoff_attribute("", pSet->name, | | | 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 | @ <table border="0"><tr><td valign="top"> login_insert_csrf_secret(); for(i=0, pSet=aSetting; i<nSetting; i++, pSet++){ if( pSet->width==0 ){ int hasVersionableValue = pSet->versionable && (db_get_versioned(pSet->name, NULL)!=0); onoff_attribute("", pSet->name, pSet->var!=0 ? pSet->var : pSet->name /*works-like:"x"*/, is_truth(pSet->def), hasVersionableValue); @ <a href='%R/help?cmd=%s(pSet->name)'>%h(pSet->name)</a> if( pSet->versionable ){ @ (v)<br /> } else { @ <br /> } |
︙ | ︙ | |||
923 924 925 926 927 928 929 | if( pSet->versionable ){ @ (v) } else { @ } @</td><td> entry_attribute("", /*pSet->width*/ 25, pSet->name, | | | | 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 | if( pSet->versionable ){ @ (v) } else { @ } @</td><td> entry_attribute("", /*pSet->width*/ 25, pSet->name, pSet->var!=0 ? pSet->var : pSet->name /*works-like:"x"*/, (char*)pSet->def, hasVersionableValue); @</td></tr> } } @</table> @ </td><td style="width:50px;"></td><td valign="top"> for(i=0, pSet=aSetting; i<nSetting; i++, pSet++){ if( pSet->width>0 && pSet->forceTextArea ){ int hasVersionableValue = db_get_versioned(pSet->name, NULL)!=0; @ <a href='%R/help?cmd=%s(pSet->name)'>%s(pSet->name)</a> if( pSet->versionable ){ @ (v)<br /> } else { @ <br /> } textarea_attribute("", /*rows*/ 2, /*cols*/ 35, pSet->name, pSet->var!=0 ? pSet->var : pSet->name /*works-like:"x"*/, (char*)pSet->def, hasVersionableValue); @<br /> } } @ </td></tr></table> @ </div></form> db_end_transaction(0); |
︙ | ︙ |
Changes to src/shell.c.
︙ | ︙ | |||
31 32 33 34 35 36 37 38 39 40 41 42 43 44 | ** utility for accessing SQLite databases. */ #if (defined(_WIN32) || defined(WIN32)) && !defined(_CRT_SECURE_NO_WARNINGS) /* This needs to come before any includes for MSVC compiler */ #define _CRT_SECURE_NO_WARNINGS #endif /* ** Determine if we are dealing with WinRT, which provides only a subset of ** the full Win32 API. */ #if !defined(SQLITE_OS_WINRT) # define SQLITE_OS_WINRT 0 #endif | > > > > > > > > > > > > | 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | ** utility for accessing SQLite databases. */ #if (defined(_WIN32) || defined(WIN32)) && !defined(_CRT_SECURE_NO_WARNINGS) /* This needs to come before any includes for MSVC compiler */ #define _CRT_SECURE_NO_WARNINGS #endif /* ** Optionally #include a user-defined header, whereby compilation options ** may be set prior to where they take effect, but after platform setup. ** If SQLITE_CUSTOM_INCLUDE=? is defined, its value names the #include ** file. Note that this macro has a like effect on sqlite3.c compilation. */ #ifdef SQLITE_CUSTOM_INCLUDE # define INC_STRINGIFY_(f) #f # define INC_STRINGIFY(f) INC_STRINGIFY_(f) # include INC_STRINGIFY(SQLITE_CUSTOM_INCLUDE) #endif /* ** Determine if we are dealing with WinRT, which provides only a subset of ** the full Win32 API. */ #if !defined(SQLITE_OS_WINRT) # define SQLITE_OS_WINRT 0 #endif |
︙ | ︙ | |||
240 241 242 243 244 245 246 247 248 249 250 251 252 253 | static int enableTimer = 0; /* Return the current wall-clock time */ static sqlite3_int64 timeOfDay(void){ static sqlite3_vfs *clockVfs = 0; sqlite3_int64 t; if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0); if( clockVfs->iVersion>=2 && clockVfs->xCurrentTimeInt64!=0 ){ clockVfs->xCurrentTimeInt64(clockVfs, &t); }else{ double r; clockVfs->xCurrentTime(clockVfs, &r); t = (sqlite3_int64)(r*86400000.0); } | > | 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 | static int enableTimer = 0; /* Return the current wall-clock time */ static sqlite3_int64 timeOfDay(void){ static sqlite3_vfs *clockVfs = 0; sqlite3_int64 t; if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0); if( clockVfs==0 ) return 0; /* Never actually happens */ if( clockVfs->iVersion>=2 && clockVfs->xCurrentTimeInt64!=0 ){ clockVfs->xCurrentTimeInt64(clockVfs, &t); }else{ double r; clockVfs->xCurrentTime(clockVfs, &r); t = (sqlite3_int64)(r*86400000.0); } |
︙ | ︙ | |||
984 985 986 987 988 989 990 | int i = 0; const char *zIn = (const char*)sqlite3_value_text(apVal[0]); const char *zSchema = (const char*)sqlite3_value_text(apVal[1]); const char *zName = (const char*)sqlite3_value_text(apVal[2]); sqlite3 *db = sqlite3_context_db_handle(pCtx); UNUSED_PARAMETER(nVal); if( zIn!=0 && strncmp(zIn, "CREATE ", 7)==0 ){ | | | 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 | int i = 0; const char *zIn = (const char*)sqlite3_value_text(apVal[0]); const char *zSchema = (const char*)sqlite3_value_text(apVal[1]); const char *zName = (const char*)sqlite3_value_text(apVal[2]); sqlite3 *db = sqlite3_context_db_handle(pCtx); UNUSED_PARAMETER(nVal); if( zIn!=0 && strncmp(zIn, "CREATE ", 7)==0 ){ for(i=0; i<ArraySize(aPrefix); i++){ int n = strlen30(aPrefix[i]); if( strncmp(zIn+7, aPrefix[i], n)==0 && zIn[n+7]==' ' ){ char *z = 0; char *zFake = 0; if( zSchema ){ char cQuote = quoteChar(zSchema); if( cQuote && sqlite3_stricmp(zSchema,"temp")!=0 ){ |
︙ | ︙ | |||
4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 | ){ int rc = SQLITE_OK; sqlite3_vfs *pOrig; SQLITE_EXTENSION_INIT2(pApi); (void)pzErrMsg; (void)db; pOrig = sqlite3_vfs_find(0); apnd_vfs.iVersion = pOrig->iVersion; apnd_vfs.pAppData = pOrig; apnd_vfs.szOsFile = pOrig->szOsFile + sizeof(ApndFile); rc = sqlite3_vfs_register(&apnd_vfs, 0); #ifdef APPENDVFS_TEST if( rc==SQLITE_OK ){ rc = sqlite3_auto_extension((void(*)(void))apndvfsRegister); | > | 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 | ){ int rc = SQLITE_OK; sqlite3_vfs *pOrig; SQLITE_EXTENSION_INIT2(pApi); (void)pzErrMsg; (void)db; pOrig = sqlite3_vfs_find(0); if( pOrig==0 ) return SQLITE_ERROR; apnd_vfs.iVersion = pOrig->iVersion; apnd_vfs.pAppData = pOrig; apnd_vfs.szOsFile = pOrig->szOsFile + sizeof(ApndFile); rc = sqlite3_vfs_register(&apnd_vfs, 0); #ifdef APPENDVFS_TEST if( rc==SQLITE_OK ){ rc = sqlite3_auto_extension((void(*)(void))apndvfsRegister); |
︙ | ︙ | |||
5755 5756 5757 5758 5759 5760 5761 | ** ** (1) start = $value -- constraint exists ** (2) stop = $value -- constraint exists ** (4) step = $value -- constraint exists ** (8) output in descending order */ static int seriesBestIndex( | | > | > > > > > > > > > > > > > | 5769 5770 5771 5772 5773 5774 5775 5776 5777 5778 5779 5780 5781 5782 5783 5784 5785 5786 5787 5788 5789 5790 5791 5792 5793 5794 5795 5796 5797 5798 5799 5800 5801 5802 5803 5804 5805 5806 5807 5808 5809 5810 5811 5812 5813 5814 5815 5816 5817 5818 5819 5820 5821 5822 5823 5824 5825 5826 5827 5828 5829 5830 5831 5832 5833 5834 | ** ** (1) start = $value -- constraint exists ** (2) stop = $value -- constraint exists ** (4) step = $value -- constraint exists ** (8) output in descending order */ static int seriesBestIndex( sqlite3_vtab *pVTab, sqlite3_index_info *pIdxInfo ){ int i, j; /* Loop over constraints */ int idxNum = 0; /* The query plan bitmask */ int bStartSeen = 0; /* EQ constraint seen on the START column */ int unusableMask = 0; /* Mask of unusable constraints */ int nArg = 0; /* Number of arguments that seriesFilter() expects */ int aIdx[3]; /* Constraints on start, stop, and step */ const struct sqlite3_index_constraint *pConstraint; /* This implementation assumes that the start, stop, and step columns ** are the last three columns in the virtual table. */ assert( SERIES_COLUMN_STOP == SERIES_COLUMN_START+1 ); assert( SERIES_COLUMN_STEP == SERIES_COLUMN_START+2 ); aIdx[0] = aIdx[1] = aIdx[2] = -1; pConstraint = pIdxInfo->aConstraint; for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){ int iCol; /* 0 for start, 1 for stop, 2 for step */ int iMask; /* bitmask for those column */ if( pConstraint->iColumn<SERIES_COLUMN_START ) continue; iCol = pConstraint->iColumn - SERIES_COLUMN_START; assert( iCol>=0 && iCol<=2 ); iMask = 1 << iCol; if( iCol==0 ) bStartSeen = 1; if( pConstraint->usable==0 ){ unusableMask |= iMask; continue; }else if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){ idxNum |= iMask; aIdx[iCol] = i; } } for(i=0; i<3; i++){ if( (j = aIdx[i])>=0 ){ pIdxInfo->aConstraintUsage[j].argvIndex = ++nArg; pIdxInfo->aConstraintUsage[j].omit = !SQLITE_SERIES_CONSTRAINT_VERIFY; } } /* The current generate_column() implementation requires at least one ** argument (the START value). Legacy versions assumed START=0 if the ** first argument was omitted. Compile with -DZERO_ARGUMENT_GENERATE_SERIES ** to obtain the legacy behavior */ #ifndef ZERO_ARGUMENT_GENERATE_SERIES if( !bStartSeen ){ sqlite3_free(pVTab->zErrMsg); pVTab->zErrMsg = sqlite3_mprintf( "first argument to \"generate_series()\" missing or unusable"); return SQLITE_ERROR; } #endif if( (unusableMask & ~idxNum)!=0 ){ /* The start, stop, and step columns are inputs. Therefore if there ** are unusable constraints on any of start, stop, or step then ** this plan is unusable */ return SQLITE_CONSTRAINT; } if( (idxNum & 3)==3 ){ |
︙ | ︙ | |||
8141 8142 8143 8144 8145 8146 8147 8148 8149 8150 8151 8152 8153 8154 | /* ** Return the current time as a 32-bit timestamp in UNIX epoch format (like ** time(2)). */ static u32 zipfileTime(void){ sqlite3_vfs *pVfs = sqlite3_vfs_find(0); u32 ret; if( pVfs->iVersion>=2 && pVfs->xCurrentTimeInt64 ){ i64 ms; pVfs->xCurrentTimeInt64(pVfs, &ms); ret = (u32)((ms/1000) - ((i64)24405875 * 8640)); }else{ double day; pVfs->xCurrentTime(pVfs, &day); | > | 8169 8170 8171 8172 8173 8174 8175 8176 8177 8178 8179 8180 8181 8182 8183 | /* ** Return the current time as a 32-bit timestamp in UNIX epoch format (like ** time(2)). */ static u32 zipfileTime(void){ sqlite3_vfs *pVfs = sqlite3_vfs_find(0); u32 ret; if( pVfs==0 ) return 0; if( pVfs->iVersion>=2 && pVfs->xCurrentTimeInt64 ){ i64 ms; pVfs->xCurrentTimeInt64(pVfs, &ms); ret = (u32)((ms/1000) - ((i64)24405875 * 8640)); }else{ double day; pVfs->xCurrentTime(pVfs, &day); |
︙ | ︙ | |||
9845 9846 9847 9848 9849 9850 9851 9852 9853 | int rc, rc2; char *pCsr = 0; int nPk = 0; rc = idxPrintfPrepareStmt(db, &p1, pzErrmsg, "PRAGMA table_xinfo=%Q", zTab); while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){ const char *zCol = (const char*)sqlite3_column_text(p1, 1); nByte += 1 + STRLEN(zCol); rc = sqlite3_table_column_metadata( | > | > | > | > | | | 9874 9875 9876 9877 9878 9879 9880 9881 9882 9883 9884 9885 9886 9887 9888 9889 9890 9891 9892 9893 9894 9895 9896 9897 9898 9899 9900 9901 9902 9903 9904 9905 9906 9907 9908 9909 9910 9911 9912 9913 9914 9915 9916 9917 9918 9919 9920 9921 9922 9923 9924 9925 9926 9927 9928 | int rc, rc2; char *pCsr = 0; int nPk = 0; rc = idxPrintfPrepareStmt(db, &p1, pzErrmsg, "PRAGMA table_xinfo=%Q", zTab); while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){ const char *zCol = (const char*)sqlite3_column_text(p1, 1); const char *zColSeq = 0; nByte += 1 + STRLEN(zCol); rc = sqlite3_table_column_metadata( db, "main", zTab, zCol, 0, &zColSeq, 0, 0, 0 ); if( zColSeq==0 ) zColSeq = "binary"; nByte += 1 + STRLEN(zColSeq); nCol++; nPk += (sqlite3_column_int(p1, 5)>0); } rc2 = sqlite3_reset(p1); if( rc==SQLITE_OK ) rc = rc2; nByte += sizeof(IdxColumn) * nCol; if( rc==SQLITE_OK ){ pNew = idxMalloc(&rc, nByte); } if( rc==SQLITE_OK ){ pNew->aCol = (IdxColumn*)&pNew[1]; pNew->nCol = nCol; pCsr = (char*)&pNew->aCol[nCol]; } nCol = 0; while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){ const char *zCol = (const char*)sqlite3_column_text(p1, 1); const char *zColSeq = 0; int nCopy = STRLEN(zCol) + 1; pNew->aCol[nCol].zName = pCsr; pNew->aCol[nCol].iPk = (sqlite3_column_int(p1, 5)==1 && nPk==1); memcpy(pCsr, zCol, nCopy); pCsr += nCopy; rc = sqlite3_table_column_metadata( db, "main", zTab, zCol, 0, &zColSeq, 0, 0, 0 ); if( rc==SQLITE_OK ){ if( zColSeq==0 ) zColSeq = "binary"; nCopy = STRLEN(zColSeq) + 1; pNew->aCol[nCol].zColl = pCsr; memcpy(pCsr, zColSeq, nCopy); pCsr += nCopy; } nCol++; } idxFinalize(&rc, p1); |
︙ | ︙ | |||
12063 12064 12065 12066 12067 12068 12069 | char rowSepPrior[20]; /* Saved row separator */ int *colWidth; /* Requested width of each column in columnar modes */ int *actualWidth; /* Actual width of each column */ int nWidth; /* Number of slots in colWidth[] and actualWidth[] */ char nullValue[20]; /* The text to print when a NULL comes back from ** the database */ char outfile[FILENAME_MAX]; /* Filename for *out */ | < < < > > > > > > > > > > < < < < | 12096 12097 12098 12099 12100 12101 12102 12103 12104 12105 12106 12107 12108 12109 12110 12111 12112 12113 12114 12115 12116 12117 12118 12119 12120 12121 12122 12123 12124 12125 | char rowSepPrior[20]; /* Saved row separator */ int *colWidth; /* Requested width of each column in columnar modes */ int *actualWidth; /* Actual width of each column */ int nWidth; /* Number of slots in colWidth[] and actualWidth[] */ char nullValue[20]; /* The text to print when a NULL comes back from ** the database */ char outfile[FILENAME_MAX]; /* Filename for *out */ sqlite3_stmt *pStmt; /* Current statement if any. */ FILE *pLog; /* Write log output here */ struct AuxDb { /* Storage space for auxiliary database connections */ sqlite3 *db; /* Connection pointer */ const char *zDbFilename; /* Filename used to open the connection */ char *zFreeOnClose; /* Free this memory allocation on close */ #if defined(SQLITE_ENABLE_SESSION) int nSession; /* Number of active sessions */ OpenSession aSession[4]; /* Array of sessions. [0] is in focus. */ #endif } aAuxDb[5], /* Array of all database connections */ *pAuxDb; /* Currently active database connection */ int *aiIndent; /* Array of indents used in MODE_Explain */ int nIndent; /* Size of array aiIndent[] */ int iIndent; /* Index of current op in aiIndent[] */ EQPGraph sGraph; /* Information for the graphical EXPLAIN QUERY PLAN */ ExpertInfo expert; /* Valid if previous command was ".expert OPT..." */ }; /* Allowed values for ShellState.autoEQP */ #define AUTOEQP_off 0 /* Automatic EXPLAIN QUERY PLAN is off */ |
︙ | ︙ | |||
14827 14828 14829 14830 14831 14832 14833 14834 14835 14836 14837 14838 14839 14840 | " --async Write to FILE without journal and fsync()", ".bail on|off Stop after hitting an error. Default OFF", ".binary on|off Turn binary output on or off. Default OFF", ".cd DIRECTORY Change the working directory to DIRECTORY", ".changes on|off Show number of rows changed by SQL", ".check GLOB Fail if output since .testcase does not match", ".clone NEWDB Clone data into NEWDB from the existing database", ".databases List names and files of attached databases", ".dbconfig ?op? ?val? List or change sqlite3_db_config() options", ".dbinfo ?DB? Show status information about the database", ".dump ?OBJECTS? Render database content as SQL", " Options:", " --data-only Output only INSERT statements", " --newlines Allow unescaped newline characters in output", | > | 14863 14864 14865 14866 14867 14868 14869 14870 14871 14872 14873 14874 14875 14876 14877 | " --async Write to FILE without journal and fsync()", ".bail on|off Stop after hitting an error. Default OFF", ".binary on|off Turn binary output on or off. Default OFF", ".cd DIRECTORY Change the working directory to DIRECTORY", ".changes on|off Show number of rows changed by SQL", ".check GLOB Fail if output since .testcase does not match", ".clone NEWDB Clone data into NEWDB from the existing database", ".connection [close] [#] Open or close an auxiliary database connection", ".databases List names and files of attached databases", ".dbconfig ?op? ?val? List or change sqlite3_db_config() options", ".dbinfo ?DB? Show status information about the database", ".dump ?OBJECTS? Render database content as SQL", " Options:", " --data-only Output only INSERT statements", " --newlines Allow unescaped newline characters in output", |
︙ | ︙ | |||
15167 15168 15169 15170 15171 15172 15173 | } #endif /* ** Close all OpenSession objects and release all associated resources. */ #if defined(SQLITE_ENABLE_SESSION) | | | > | | | | | 15204 15205 15206 15207 15208 15209 15210 15211 15212 15213 15214 15215 15216 15217 15218 15219 15220 15221 15222 15223 15224 15225 15226 15227 | } #endif /* ** Close all OpenSession objects and release all associated resources. */ #if defined(SQLITE_ENABLE_SESSION) static void session_close_all(ShellState *p, int i){ int j; struct AuxDb *pAuxDb = i<0 ? p->pAuxDb : &p->aAuxDb[i]; for(j=0; j<pAuxDb->nSession; j++){ session_close(&pAuxDb->aSession[j]); } pAuxDb->nSession = 0; } #else # define session_close_all(X,Y) #endif /* ** Implementation of the xFilter function for an open session. Omit ** any tables named by ".session filter" but let all other table through. */ #if defined(SQLITE_ENABLE_SESSION) |
︙ | ︙ | |||
15240 15241 15242 15243 15244 15245 15246 | fclose(f); return rc; } #ifndef SQLITE_OMIT_DESERIALIZE /* ** Reconstruct an in-memory database using the output from the "dbtotxt" | | | > | | | | 15278 15279 15280 15281 15282 15283 15284 15285 15286 15287 15288 15289 15290 15291 15292 15293 15294 15295 15296 15297 15298 15299 15300 15301 15302 15303 15304 15305 15306 15307 15308 15309 15310 | fclose(f); return rc; } #ifndef SQLITE_OMIT_DESERIALIZE /* ** Reconstruct an in-memory database using the output from the "dbtotxt" ** program. Read content from the file in p->aAuxDb[].zDbFilename. ** If p->aAuxDb[].zDbFilename is 0, then read from standard input. */ static unsigned char *readHexDb(ShellState *p, int *pnData){ unsigned char *a = 0; int nLine; int n = 0; int pgsz = 0; int iOffset = 0; int j, k; int rc; FILE *in; const char *zDbFilename = p->pAuxDb->zDbFilename; unsigned int x[16]; char zLine[1000]; if( zDbFilename ){ in = fopen(zDbFilename, "r"); if( in==0 ){ utf8_printf(stderr, "cannot open \"%s\" for reading\n", zDbFilename); return 0; } nLine = 0; }else{ in = p->in; nLine = p->lineno; if( in==0 ) in = stdin; |
︙ | ︙ | |||
15499 15500 15501 15502 15503 15504 15505 15506 | /* ** Make sure the database is open. If it is not, then open it. If ** the database fails to open, print an error message and exit. */ static void open_db(ShellState *p, int openFlags){ if( p->db==0 ){ if( p->openMode==SHELL_OPEN_UNSPEC ){ | > | | | | | | | 15538 15539 15540 15541 15542 15543 15544 15545 15546 15547 15548 15549 15550 15551 15552 15553 15554 15555 15556 15557 15558 15559 15560 15561 15562 15563 15564 15565 15566 15567 15568 15569 15570 15571 15572 15573 15574 15575 15576 15577 15578 15579 15580 15581 15582 15583 15584 15585 15586 15587 15588 15589 15590 15591 | /* ** Make sure the database is open. If it is not, then open it. If ** the database fails to open, print an error message and exit. */ static void open_db(ShellState *p, int openFlags){ if( p->db==0 ){ const char *zDbFilename = p->pAuxDb->zDbFilename; if( p->openMode==SHELL_OPEN_UNSPEC ){ if( zDbFilename==0 || zDbFilename[0]==0 ){ p->openMode = SHELL_OPEN_NORMAL; }else{ p->openMode = (u8)deduceDatabaseType(zDbFilename, (openFlags & OPEN_DB_ZIPFILE)!=0); } } switch( p->openMode ){ case SHELL_OPEN_APPENDVFS: { sqlite3_open_v2(zDbFilename, &p->db, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|p->openFlags, "apndvfs"); break; } case SHELL_OPEN_HEXDB: case SHELL_OPEN_DESERIALIZE: { sqlite3_open(0, &p->db); break; } case SHELL_OPEN_ZIPFILE: { sqlite3_open(":memory:", &p->db); break; } case SHELL_OPEN_READONLY: { sqlite3_open_v2(zDbFilename, &p->db, SQLITE_OPEN_READONLY|p->openFlags, 0); break; } case SHELL_OPEN_UNSPEC: case SHELL_OPEN_NORMAL: { sqlite3_open_v2(zDbFilename, &p->db, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|p->openFlags, 0); break; } } globalDb = p->db; if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){ utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n", zDbFilename, sqlite3_errmsg(p->db)); if( openFlags & OPEN_DB_KEEPALIVE ){ sqlite3_open(":memory:", &p->db); return; } exit(1); } #ifndef SQLITE_OMIT_LOAD_EXTENSION |
︙ | ︙ | |||
15584 15585 15586 15587 15588 15589 15590 | sqlite3_create_function(p->db, "edit", 1, SQLITE_UTF8, 0, editFunc, 0, 0); sqlite3_create_function(p->db, "edit", 2, SQLITE_UTF8, 0, editFunc, 0, 0); #endif if( p->openMode==SHELL_OPEN_ZIPFILE ){ char *zSql = sqlite3_mprintf( | | | | 15624 15625 15626 15627 15628 15629 15630 15631 15632 15633 15634 15635 15636 15637 15638 15639 15640 15641 15642 15643 15644 15645 15646 15647 15648 15649 | sqlite3_create_function(p->db, "edit", 1, SQLITE_UTF8, 0, editFunc, 0, 0); sqlite3_create_function(p->db, "edit", 2, SQLITE_UTF8, 0, editFunc, 0, 0); #endif if( p->openMode==SHELL_OPEN_ZIPFILE ){ char *zSql = sqlite3_mprintf( "CREATE VIRTUAL TABLE zip USING zipfile(%Q);", zDbFilename); sqlite3_exec(p->db, zSql, 0, 0, 0); sqlite3_free(zSql); } #ifndef SQLITE_OMIT_DESERIALIZE else if( p->openMode==SHELL_OPEN_DESERIALIZE || p->openMode==SHELL_OPEN_HEXDB ){ int rc; int nData = 0; unsigned char *aData; if( p->openMode==SHELL_OPEN_DESERIALIZE ){ aData = (unsigned char*)readFile(zDbFilename, &nData); }else{ aData = readHexDb(p, &nData); if( aData==0 ){ return; } } rc = sqlite3_deserialize(p->db, "main", aData, nData, nData, |
︙ | ︙ | |||
18316 18317 18318 18319 18320 18321 18322 | raw_printf(pState->out, "COMMIT;\n"); } sqlite3_exec(pState->db, "DETACH recovery", 0, 0, 0); return rc; } #endif /* !(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) */ | < | 18356 18357 18358 18359 18360 18361 18362 18363 18364 18365 18366 18367 18368 18369 | raw_printf(pState->out, "COMMIT;\n"); } sqlite3_exec(pState->db, "DETACH recovery", 0, 0, 0); return rc; } #endif /* !(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) */ /* ** If an input line begins with "." then invoke this routine to ** process that line. ** ** Return 1 on error, 2 to exit, and 0 otherwise. */ static int do_meta_command(char *zLine, ShellState *p){ |
︙ | ︙ | |||
18480 18481 18482 18483 18484 18485 18486 18487 18488 18489 18490 18491 18492 18493 18494 18495 18496 18497 18498 18499 18500 18501 18502 18503 18504 18505 18506 | setTextMode(p->out, 1); } }else{ raw_printf(stderr, "Usage: .binary on|off\n"); rc = 1; } }else if( c=='c' && strcmp(azArg[0],"cd")==0 ){ if( nArg==2 ){ #if defined(_WIN32) || defined(WIN32) wchar_t *z = sqlite3_win32_utf8_to_unicode(azArg[1]); rc = !SetCurrentDirectoryW(z); sqlite3_free(z); #else rc = chdir(azArg[1]); #endif if( rc ){ utf8_printf(stderr, "Cannot change to directory \"%s\"\n", azArg[1]); rc = 1; } }else{ raw_printf(stderr, "Usage: .cd DIRECTORY\n"); rc = 1; } }else | > > > > > > > < < < < < < < | 18519 18520 18521 18522 18523 18524 18525 18526 18527 18528 18529 18530 18531 18532 18533 18534 18535 18536 18537 18538 18539 18540 18541 18542 18543 18544 18545 18546 18547 18548 18549 18550 18551 18552 18553 18554 18555 18556 18557 18558 18559 | setTextMode(p->out, 1); } }else{ raw_printf(stderr, "Usage: .binary on|off\n"); rc = 1; } }else /* The undocumented ".breakpoint" command causes a call to the no-op ** routine named test_breakpoint(). */ if( c=='b' && n>=3 && strncmp(azArg[0], "breakpoint", n)==0 ){ test_breakpoint(); }else if( c=='c' && strcmp(azArg[0],"cd")==0 ){ if( nArg==2 ){ #if defined(_WIN32) || defined(WIN32) wchar_t *z = sqlite3_win32_utf8_to_unicode(azArg[1]); rc = !SetCurrentDirectoryW(z); sqlite3_free(z); #else rc = chdir(azArg[1]); #endif if( rc ){ utf8_printf(stderr, "Cannot change to directory \"%s\"\n", azArg[1]); rc = 1; } }else{ raw_printf(stderr, "Usage: .cd DIRECTORY\n"); rc = 1; } }else if( c=='c' && n>=3 && strncmp(azArg[0], "changes", n)==0 ){ if( nArg==2 ){ setOrClearFlag(p, SHFLG_CountChanges, azArg[1]); }else{ raw_printf(stderr, "Usage: .changes on|off\n"); rc = 1; } |
︙ | ︙ | |||
18549 18550 18551 18552 18553 18554 18555 18556 18557 18558 18559 18560 18561 18562 | if( nArg==2 ){ tryToClone(p, azArg[1]); }else{ raw_printf(stderr, "Usage: .clone FILENAME\n"); rc = 1; } }else if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){ char **azName = 0; int nName = 0; sqlite3_stmt *pStmt; int i; open_db(p, 0); | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 18588 18589 18590 18591 18592 18593 18594 18595 18596 18597 18598 18599 18600 18601 18602 18603 18604 18605 18606 18607 18608 18609 18610 18611 18612 18613 18614 18615 18616 18617 18618 18619 18620 18621 18622 18623 18624 18625 18626 18627 18628 18629 18630 18631 18632 18633 18634 18635 18636 18637 18638 18639 18640 18641 18642 18643 18644 18645 18646 18647 | if( nArg==2 ){ tryToClone(p, azArg[1]); }else{ raw_printf(stderr, "Usage: .clone FILENAME\n"); rc = 1; } }else if( c=='c' && strncmp(azArg[0], "connection", n)==0 ){ if( nArg==1 ){ /* List available connections */ int i; for(i=0; i<ArraySize(p->aAuxDb); i++){ const char *zFile = p->aAuxDb[i].zDbFilename; if( p->aAuxDb[i].db==0 && p->pAuxDb!=&p->aAuxDb[i] ){ zFile = "(not open)"; }else if( zFile==0 ){ zFile = "(memory)"; }else if( zFile[0]==0 ){ zFile = "(temporary-file)"; } if( p->pAuxDb == &p->aAuxDb[i] ){ utf8_printf(stdout, "ACTIVE %d: %s\n", i, zFile); }else if( p->aAuxDb[i].db!=0 ){ utf8_printf(stdout, " %d: %s\n", i, zFile); } } }else if( nArg==2 && IsDigit(azArg[1][0]) && azArg[1][1]==0 ){ int i = azArg[1][0] - '0'; if( p->pAuxDb != &p->aAuxDb[i] && i>=0 && i<ArraySize(p->aAuxDb) ){ p->pAuxDb->db = p->db; p->pAuxDb = &p->aAuxDb[i]; globalDb = p->db = p->pAuxDb->db; p->pAuxDb->db = 0; } }else if( nArg==3 && strcmp(azArg[1], "close")==0 && IsDigit(azArg[2][0]) && azArg[2][1]==0 ){ int i = azArg[2][0] - '0'; if( i<0 || i>=ArraySize(p->aAuxDb) ){ /* No-op */ }else if( p->pAuxDb == &p->aAuxDb[i] ){ raw_printf(stderr, "cannot close the active database connection\n"); rc = 1; }else if( p->aAuxDb[i].db ){ session_close_all(p, i); close_db(p->aAuxDb[i].db); p->aAuxDb[i].db = 0; } }else{ raw_printf(stderr, "Usage: .connection [close] [CONNECTION-NUMBER]\n"); rc = 1; } }else if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){ char **azName = 0; int nName = 0; sqlite3_stmt *pStmt; int i; open_db(p, 0); |
︙ | ︙ | |||
18995 18996 18997 18998 18999 19000 19001 | open_db(p, 0); rc = sqlite3_exec(p->db, "SELECT sql FROM" " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x" " FROM sqlite_schema UNION ALL" " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_schema) " "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' " | | < < | 19080 19081 19082 19083 19084 19085 19086 19087 19088 19089 19090 19091 19092 19093 19094 19095 19096 19097 19098 19099 19100 19101 19102 19103 19104 19105 19106 19107 19108 19109 | open_db(p, 0); rc = sqlite3_exec(p->db, "SELECT sql FROM" " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x" " FROM sqlite_schema UNION ALL" " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_schema) " "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' " "ORDER BY x", callback, &data, 0 ); if( rc==SQLITE_OK ){ sqlite3_stmt *pStmt; rc = sqlite3_prepare_v2(p->db, "SELECT rowid FROM sqlite_schema" " WHERE name GLOB 'sqlite_stat[134]'", -1, &pStmt, 0); doStats = sqlite3_step(pStmt)==SQLITE_ROW; sqlite3_finalize(pStmt); } if( doStats==0 ){ raw_printf(p->out, "/* No STAT tables available */\n"); }else{ raw_printf(p->out, "ANALYZE sqlite_schema;\n"); data.cMode = data.mode = MODE_Insert; data.zDestTable = "sqlite_stat1"; shell_exec(&data, "SELECT * FROM sqlite_stat1", 0); data.zDestTable = "sqlite_stat4"; shell_exec(&data, "SELECT * FROM sqlite_stat4", 0); raw_printf(p->out, "ANALYZE sqlite_schema;\n"); } |
︙ | ︙ | |||
19641 19642 19643 19644 19645 19646 19647 | #endif /* SQLITE_DEBUG */ if( c=='o' && strncmp(azArg[0], "open", n)==0 && n>=2 ){ char *zNewFilename = 0; /* Name of the database file to open */ int iName = 1; /* Index in azArg[] of the filename */ int newFlag = 0; /* True to delete file before opening */ /* Close the existing database */ | | | | | > > | 19724 19725 19726 19727 19728 19729 19730 19731 19732 19733 19734 19735 19736 19737 19738 19739 19740 19741 19742 19743 19744 19745 19746 19747 19748 19749 19750 19751 19752 19753 19754 19755 19756 19757 19758 19759 19760 19761 19762 19763 | #endif /* SQLITE_DEBUG */ if( c=='o' && strncmp(azArg[0], "open", n)==0 && n>=2 ){ char *zNewFilename = 0; /* Name of the database file to open */ int iName = 1; /* Index in azArg[] of the filename */ int newFlag = 0; /* True to delete file before opening */ /* Close the existing database */ session_close_all(p, -1); close_db(p->db); p->db = 0; p->pAuxDb->zDbFilename = 0; sqlite3_free(p->pAuxDb->zFreeOnClose); p->pAuxDb->zFreeOnClose = 0; p->openMode = SHELL_OPEN_UNSPEC; p->openFlags = 0; p->szMax = 0; /* Check for command-line arguments */ for(iName=1; iName<nArg; iName++){ const char *z = azArg[iName]; if( optionMatch(z,"new") ){ newFlag = 1; #ifdef SQLITE_HAVE_ZLIB }else if( optionMatch(z, "zip") ){ p->openMode = SHELL_OPEN_ZIPFILE; #endif }else if( optionMatch(z, "append") ){ p->openMode = SHELL_OPEN_APPENDVFS; }else if( optionMatch(z, "readonly") ){ p->openMode = SHELL_OPEN_READONLY; }else if( optionMatch(z, "nofollow") ){ p->openFlags |= SQLITE_OPEN_NOFOLLOW; }else if( optionMatch(z, "excl") ){ p->openFlags |= SQLITE_OPEN_EXCLUSIVE; #ifndef SQLITE_OMIT_DESERIALIZE }else if( optionMatch(z, "deserialize") ){ p->openMode = SHELL_OPEN_DESERIALIZE; }else if( optionMatch(z, "hexdb") ){ p->openMode = SHELL_OPEN_HEXDB; }else if( optionMatch(z, "maxsize") && iName+1<nArg ){ p->szMax = integerValue(azArg[++iName]); |
︙ | ︙ | |||
19688 19689 19690 19691 19692 19693 19694 | }else{ zNewFilename = sqlite3_mprintf("%s", z); } } /* If a filename is specified, try to open it first */ if( zNewFilename || p->openMode==SHELL_OPEN_HEXDB ){ if( newFlag ) shellDeleteFile(zNewFilename); | | | | | 19773 19774 19775 19776 19777 19778 19779 19780 19781 19782 19783 19784 19785 19786 19787 19788 19789 19790 19791 19792 19793 19794 19795 19796 19797 19798 | }else{ zNewFilename = sqlite3_mprintf("%s", z); } } /* If a filename is specified, try to open it first */ if( zNewFilename || p->openMode==SHELL_OPEN_HEXDB ){ if( newFlag ) shellDeleteFile(zNewFilename); p->pAuxDb->zDbFilename = zNewFilename; open_db(p, OPEN_DB_KEEPALIVE); if( p->db==0 ){ utf8_printf(stderr, "Error: cannot open '%s'\n", zNewFilename); sqlite3_free(zNewFilename); }else{ p->pAuxDb->zFreeOnClose = zNewFilename; } } if( p->db==0 ){ /* As a fall-back open a TEMP database */ p->pAuxDb->zDbFilename = 0; open_db(p, 0); } }else if( (c=='o' && (strncmp(azArg[0], "output", n)==0||strncmp(azArg[0], "once", n)==0)) || (c=='e' && n==5 && strcmp(azArg[0],"excel")==0) |
︙ | ︙ | |||
20228 20229 20230 20231 20232 20233 20234 | if( c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0 ){ unsigned int x = nArg>=2 ? (unsigned int)integerValue(azArg[1]) : 0xffffffff; sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &x); }else #if defined(SQLITE_ENABLE_SESSION) if( c=='s' && strncmp(azArg[0],"session",n)==0 && n>=3 ){ | > | | | | | | | 20313 20314 20315 20316 20317 20318 20319 20320 20321 20322 20323 20324 20325 20326 20327 20328 20329 20330 20331 20332 20333 20334 20335 20336 20337 20338 20339 20340 20341 20342 20343 20344 | if( c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0 ){ unsigned int x = nArg>=2 ? (unsigned int)integerValue(azArg[1]) : 0xffffffff; sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &x); }else #if defined(SQLITE_ENABLE_SESSION) if( c=='s' && strncmp(azArg[0],"session",n)==0 && n>=3 ){ struct AuxDb *pAuxDb = p->pAuxDb; OpenSession *pSession = &pAuxDb->aSession[0]; char **azCmd = &azArg[1]; int iSes = 0; int nCmd = nArg - 1; int i; if( nArg<=1 ) goto session_syntax_error; open_db(p, 0); if( nArg>=3 ){ for(iSes=0; iSes<pAuxDb->nSession; iSes++){ if( strcmp(pAuxDb->aSession[iSes].zName, azArg[1])==0 ) break; } if( iSes<pAuxDb->nSession ){ pSession = &pAuxDb->aSession[iSes]; azCmd++; nCmd--; }else{ pSession = &pAuxDb->aSession[0]; iSes = 0; } } /* .session attach TABLE ** Invoke the sqlite3session_attach() interface to attach a particular ** table so that it is never filtered. |
︙ | ︙ | |||
20306 20307 20308 20309 20310 20311 20312 | }else /* .session close ** Close the identified session */ if( strcmp(azCmd[0], "close")==0 ){ if( nCmd!=1 ) goto session_syntax_error; | | | | | | 20392 20393 20394 20395 20396 20397 20398 20399 20400 20401 20402 20403 20404 20405 20406 20407 20408 20409 20410 20411 20412 20413 20414 20415 20416 20417 20418 20419 20420 20421 20422 20423 20424 20425 20426 20427 20428 20429 20430 20431 20432 | }else /* .session close ** Close the identified session */ if( strcmp(azCmd[0], "close")==0 ){ if( nCmd!=1 ) goto session_syntax_error; if( pAuxDb->nSession ){ session_close(pSession); pAuxDb->aSession[iSes] = pAuxDb->aSession[--pAuxDb->nSession]; } }else /* .session enable ?BOOLEAN? ** Query or set the enable flag */ if( strcmp(azCmd[0], "enable")==0 ){ int ii; if( nCmd>2 ) goto session_syntax_error; ii = nCmd==1 ? -1 : booleanValue(azCmd[1]); if( pAuxDb->nSession ){ ii = sqlite3session_enable(pSession->p, ii); utf8_printf(p->out, "session %s enable flag = %d\n", pSession->zName, ii); } }else /* .session filter GLOB .... ** Set a list of GLOB patterns of table names to be excluded. */ if( strcmp(azCmd[0], "filter")==0 ){ int ii, nByte; if( nCmd<2 ) goto session_syntax_error; if( pAuxDb->nSession ){ for(ii=0; ii<pSession->nFilter; ii++){ sqlite3_free(pSession->azFilter[ii]); } sqlite3_free(pSession->azFilter); nByte = sizeof(pSession->azFilter[0])*(nCmd-1); pSession->azFilter = sqlite3_malloc( nByte ); if( pSession->azFilter==0 ){ |
︙ | ︙ | |||
20357 20358 20359 20360 20361 20362 20363 | /* .session indirect ?BOOLEAN? ** Query or set the indirect flag */ if( strcmp(azCmd[0], "indirect")==0 ){ int ii; if( nCmd>2 ) goto session_syntax_error; ii = nCmd==1 ? -1 : booleanValue(azCmd[1]); | | | | | | | | | | | | 20443 20444 20445 20446 20447 20448 20449 20450 20451 20452 20453 20454 20455 20456 20457 20458 20459 20460 20461 20462 20463 20464 20465 20466 20467 20468 20469 20470 20471 20472 20473 20474 20475 20476 20477 20478 20479 20480 20481 20482 20483 20484 20485 20486 20487 20488 20489 20490 20491 20492 20493 20494 20495 20496 20497 20498 20499 20500 20501 20502 20503 20504 20505 20506 20507 20508 20509 20510 20511 20512 20513 20514 | /* .session indirect ?BOOLEAN? ** Query or set the indirect flag */ if( strcmp(azCmd[0], "indirect")==0 ){ int ii; if( nCmd>2 ) goto session_syntax_error; ii = nCmd==1 ? -1 : booleanValue(azCmd[1]); if( pAuxDb->nSession ){ ii = sqlite3session_indirect(pSession->p, ii); utf8_printf(p->out, "session %s indirect flag = %d\n", pSession->zName, ii); } }else /* .session isempty ** Determine if the session is empty */ if( strcmp(azCmd[0], "isempty")==0 ){ int ii; if( nCmd!=1 ) goto session_syntax_error; if( pAuxDb->nSession ){ ii = sqlite3session_isempty(pSession->p); utf8_printf(p->out, "session %s isempty flag = %d\n", pSession->zName, ii); } }else /* .session list ** List all currently open sessions */ if( strcmp(azCmd[0],"list")==0 ){ for(i=0; i<pAuxDb->nSession; i++){ utf8_printf(p->out, "%d %s\n", i, pAuxDb->aSession[i].zName); } }else /* .session open DB NAME ** Open a new session called NAME on the attached database DB. ** DB is normally "main". */ if( strcmp(azCmd[0],"open")==0 ){ char *zName; if( nCmd!=3 ) goto session_syntax_error; zName = azCmd[2]; if( zName[0]==0 ) goto session_syntax_error; for(i=0; i<pAuxDb->nSession; i++){ if( strcmp(pAuxDb->aSession[i].zName,zName)==0 ){ utf8_printf(stderr, "Session \"%s\" already exists\n", zName); goto meta_command_exit; } } if( pAuxDb->nSession>=ArraySize(pAuxDb->aSession) ){ raw_printf(stderr, "Maximum of %d sessions\n", ArraySize(pAuxDb->aSession)); goto meta_command_exit; } pSession = &pAuxDb->aSession[pAuxDb->nSession]; rc = sqlite3session_create(p->db, azCmd[1], &pSession->p); if( rc ){ raw_printf(stderr, "Cannot open session: error code=%d\n", rc); rc = 0; goto meta_command_exit; } pSession->nFilter = 0; sqlite3session_table_filter(pSession->p, session_filter, pSession); pAuxDb->nSession++; pSession->zName = sqlite3_mprintf("%s", zName); }else /* If no command name matches, show a syntax error */ session_syntax_error: showHelp(p->out, "session"); }else #endif |
︙ | ︙ | |||
20743 20744 20745 20746 20747 20748 20749 | utf8_printf(p->out, "%12.12s: %s\n","stats", zOut); utf8_printf(p->out, "%12.12s: ", "width"); for (i=0;i<p->nWidth;i++) { raw_printf(p->out, "%d ", p->colWidth[i]); } raw_printf(p->out, "\n"); utf8_printf(p->out, "%12.12s: %s\n", "filename", | | | 20829 20830 20831 20832 20833 20834 20835 20836 20837 20838 20839 20840 20841 20842 20843 | utf8_printf(p->out, "%12.12s: %s\n","stats", zOut); utf8_printf(p->out, "%12.12s: ", "width"); for (i=0;i<p->nWidth;i++) { raw_printf(p->out, "%d ", p->colWidth[i]); } raw_printf(p->out, "\n"); utf8_printf(p->out, "%12.12s: %s\n", "filename", p->pAuxDb->zDbFilename ? p->pAuxDb->zDbFilename : ""); }else if( c=='s' && strncmp(azArg[0], "stats", n)==0 ){ if( nArg==2 ){ if( strcmp(azArg[1],"stmt")==0 ){ p->statsOn = 2; }else if( strcmp(azArg[1],"vmstep")==0 ){ |
︙ | ︙ | |||
20910 20911 20912 20913 20914 20915 20916 20917 20918 20919 20920 20921 20922 20923 | { "parser_coverage", SQLITE_TESTCTRL_PARSER_COVERAGE, "" }, #endif { "pending_byte", SQLITE_TESTCTRL_PENDING_BYTE, "OFFSET " }, { "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE, "" }, { "prng_save", SQLITE_TESTCTRL_PRNG_SAVE, "" }, { "prng_seed", SQLITE_TESTCTRL_PRNG_SEED, "SEED ?db?" }, { "seek_count", SQLITE_TESTCTRL_SEEK_COUNT, "" }, { "tune", SQLITE_TESTCTRL_TUNE, "ID VALUE" }, }; int testctrl = -1; int iCtrl = -1; int rc2 = 0; /* 0: usage. 1: %d 2: %x 3: no-output */ int isOk = 0; int i, n2; | > | 20996 20997 20998 20999 21000 21001 21002 21003 21004 21005 21006 21007 21008 21009 21010 | { "parser_coverage", SQLITE_TESTCTRL_PARSER_COVERAGE, "" }, #endif { "pending_byte", SQLITE_TESTCTRL_PENDING_BYTE, "OFFSET " }, { "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE, "" }, { "prng_save", SQLITE_TESTCTRL_PRNG_SAVE, "" }, { "prng_seed", SQLITE_TESTCTRL_PRNG_SEED, "SEED ?db?" }, { "seek_count", SQLITE_TESTCTRL_SEEK_COUNT, "" }, { "sorter_mmap", SQLITE_TESTCTRL_SORTER_MMAP, "NMAX" }, { "tune", SQLITE_TESTCTRL_TUNE, "ID VALUE" }, }; int testctrl = -1; int iCtrl = -1; int rc2 = 0; /* 0: usage. 1: %d 2: %x 3: no-output */ int isOk = 0; int i, n2; |
︙ | ︙ | |||
21090 21091 21092 21093 21094 21095 21096 21097 21098 21099 21100 21101 21102 21103 | } if( id>1 ) utf8_printf(p->out, "\n"); isOk = 3; } break; } #endif } } if( isOk==0 && iCtrl>=0 ){ utf8_printf(p->out, "Usage: .testctrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage); rc = 1; }else if( isOk==1 ){ raw_printf(p->out, "%d\n", rc2); | > > > > > > > | 21177 21178 21179 21180 21181 21182 21183 21184 21185 21186 21187 21188 21189 21190 21191 21192 21193 21194 21195 21196 21197 | } if( id>1 ) utf8_printf(p->out, "\n"); isOk = 3; } break; } #endif case SQLITE_TESTCTRL_SORTER_MMAP: if( nArg==3 ){ int opt = (unsigned int)integerValue(azArg[2]); rc2 = sqlite3_test_control(testctrl, p->db, opt); isOk = 3; } break; } } if( isOk==0 && iCtrl>=0 ){ utf8_printf(p->out, "Usage: .testctrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage); rc = 1; }else if( isOk==1 ){ raw_printf(p->out, "%d\n", rc2); |
︙ | ︙ | |||
21458 21459 21460 21461 21462 21463 21464 | sqlite3_free(zErrMsg); zErrMsg = 0; }else{ utf8_printf(stderr, "%s %s\n", zPrefix, sqlite3_errmsg(p->db)); } return 1; }else if( ShellHasFlag(p, SHFLG_CountChanges) ){ | | | | 21552 21553 21554 21555 21556 21557 21558 21559 21560 21561 21562 21563 21564 21565 21566 21567 | sqlite3_free(zErrMsg); zErrMsg = 0; }else{ utf8_printf(stderr, "%s %s\n", zPrefix, sqlite3_errmsg(p->db)); } return 1; }else if( ShellHasFlag(p, SHFLG_CountChanges) ){ raw_printf(p->out, "changes: %3lld total_changes: %lld\n", sqlite3_changes64(p->db), sqlite3_total_changes64(p->db)); } return 0; } /* ** Read input from *in and process it. If *in==0 then input |
︙ | ︙ | |||
21764 21765 21766 21767 21768 21769 21770 21771 21772 21773 21774 21775 21776 21777 | /* ** Initialize the state information in data */ static void main_init(ShellState *data) { memset(data, 0, sizeof(*data)); data->normalMode = data->cMode = data->mode = MODE_List; data->autoExplain = 1; memcpy(data->colSeparator,SEP_Column, 2); memcpy(data->rowSeparator,SEP_Row, 2); data->showHeader = 0; data->shellFlgs = SHFLG_Lookaside; verify_uninitialized(); sqlite3_config(SQLITE_CONFIG_URI, 1); sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data); | > | 21858 21859 21860 21861 21862 21863 21864 21865 21866 21867 21868 21869 21870 21871 21872 | /* ** Initialize the state information in data */ static void main_init(ShellState *data) { memset(data, 0, sizeof(*data)); data->normalMode = data->cMode = data->mode = MODE_List; data->autoExplain = 1; data->pAuxDb = &data->aAuxDb[0]; memcpy(data->colSeparator,SEP_Column, 2); memcpy(data->rowSeparator,SEP_Row, 2); data->showHeader = 0; data->shellFlgs = SHFLG_Lookaside; verify_uninitialized(); sqlite3_config(SQLITE_CONFIG_URI, 1); sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data); |
︙ | ︙ | |||
21927 21928 21929 21930 21931 21932 21933 | #ifdef SQLITE_SHELL_DBNAME_PROC { /* If the SQLITE_SHELL_DBNAME_PROC macro is defined, then it is the name ** of a C-function that will provide the name of the database file. Use ** this compile-time option to embed this shell program in larger ** applications. */ extern void SQLITE_SHELL_DBNAME_PROC(const char**); | | | | | 22022 22023 22024 22025 22026 22027 22028 22029 22030 22031 22032 22033 22034 22035 22036 22037 22038 22039 22040 22041 22042 22043 22044 22045 22046 22047 22048 22049 22050 22051 22052 | #ifdef SQLITE_SHELL_DBNAME_PROC { /* If the SQLITE_SHELL_DBNAME_PROC macro is defined, then it is the name ** of a C-function that will provide the name of the database file. Use ** this compile-time option to embed this shell program in larger ** applications. */ extern void SQLITE_SHELL_DBNAME_PROC(const char**); SQLITE_SHELL_DBNAME_PROC(&data.pAuxDb->zDbFilename); warnInmemoryDb = 0; } #endif /* Do an initial pass through the command-line argument to locate ** the name of the database file, the name of the initialization file, ** the size of the alternative malloc heap, ** and the first command to execute. */ verify_uninitialized(); for(i=1; i<argc; i++){ char *z; z = argv[i]; if( z[0]!='-' ){ if( data.aAuxDb->zDbFilename==0 ){ data.aAuxDb->zDbFilename = z; }else{ /* Excesss arguments are interpreted as SQL (or dot-commands) and ** mean that nothing is read from stdin */ readStdin = 0; nCmd++; azCmd = realloc(azCmd, sizeof(azCmd[0])*nCmd); if( azCmd==0 ) shell_out_of_memory(); |
︙ | ︙ | |||
22083 22084 22085 22086 22087 22088 22089 | sqlite3_vfs_register(pVfs, 1); }else{ utf8_printf(stderr, "no such VFS: \"%s\"\n", argv[i]); exit(1); } } | | | | | 22178 22179 22180 22181 22182 22183 22184 22185 22186 22187 22188 22189 22190 22191 22192 22193 22194 22195 22196 22197 22198 22199 22200 22201 22202 22203 22204 22205 22206 22207 22208 22209 | sqlite3_vfs_register(pVfs, 1); }else{ utf8_printf(stderr, "no such VFS: \"%s\"\n", argv[i]); exit(1); } } if( data.pAuxDb->zDbFilename==0 ){ #ifndef SQLITE_OMIT_MEMORYDB data.pAuxDb->zDbFilename = ":memory:"; warnInmemoryDb = argc==1; #else utf8_printf(stderr,"%s: Error: no database filename specified\n", Argv0); return 1; #endif } data.out = stdout; sqlite3_appendvfs_init(0,0,0); /* Go ahead and open the database file if it already exists. If the ** file does not exist, delay opening it. This prevents empty database ** files from being created if a user mistypes the database name argument ** to the sqlite command-line tool. */ if( access(data.pAuxDb->zDbFilename, 0)==0 ){ open_db(&data, 0); } /* Process the initialization file if there is one. If no -init option ** is given on the command line, look for a file named ~/.sqliterc and ** try to process it. */ |
︙ | ︙ | |||
22354 22355 22356 22357 22358 22359 22360 | data.in = stdin; rc = process_input(&data); } } free(azCmd); set_table_name(&data, 0); if( data.db ){ | | > | > > > > > | 22449 22450 22451 22452 22453 22454 22455 22456 22457 22458 22459 22460 22461 22462 22463 22464 22465 22466 22467 22468 22469 22470 22471 22472 | data.in = stdin; rc = process_input(&data); } } free(azCmd); set_table_name(&data, 0); if( data.db ){ session_close_all(&data, -1); close_db(data.db); } for(i=0; i<ArraySize(data.aAuxDb); i++){ sqlite3_free(data.aAuxDb[i].zFreeOnClose); if( data.aAuxDb[i].db ){ session_close_all(&data, i); close_db(data.aAuxDb[i].db); } } find_home_dir(1); output_reset(&data); data.doXdgOpen = 0; clearTempFile(&data); #if !SQLITE_SHELL_IS_UTF8 for(i=0; i<argcToFree; i++) free(argvToFree[i]); free(argvToFree); |
︙ | ︙ |
Changes to src/skins.c.
︙ | ︙ | |||
787 788 789 790 791 792 793 | /* 4 */ { "js", "JavaScript", "Script", }, }; const char *zBasis; /* The baseline file */ const char *zOrig; /* Original content prior to editing */ const char *zContent; /* Content after editing */ const char *zDflt; /* Default content */ char *zDraft; /* Which draft: "draft%d" */ | < | 787 788 789 790 791 792 793 794 795 796 797 798 799 800 | /* 4 */ { "js", "JavaScript", "Script", }, }; const char *zBasis; /* The baseline file */ const char *zOrig; /* Original content prior to editing */ const char *zContent; /* Content after editing */ const char *zDflt; /* Default content */ char *zDraft; /* Which draft: "draft%d" */ char *zTitle; /* Title of this page */ const char *zFile; /* One of "css", "footer", "header", "details" */ int iSkin; /* draft number. 1..9 */ int ii; /* Index in aSkinAttr[] of this file */ int j; /* Loop counter */ int isRevert = 0; /* True if Revert-to-Baseline was pressed */ |
︙ | ︙ | |||
825 826 827 828 829 830 831 | } /* figure out which file is to be edited */ ii = atoi(PD("w","0")); if( ii<0 || ii>count(aSkinAttr) ) ii = 0; zFile = aSkinAttr[ii].zFile; zDraft = mprintf("draft%d", iSkin); | < | | | 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 | } /* figure out which file is to be edited */ ii = atoi(PD("w","0")); if( ii<0 || ii>count(aSkinAttr) ) ii = 0; zFile = aSkinAttr[ii].zFile; zDraft = mprintf("draft%d", iSkin); zTitle = mprintf("%s for Draft%d", aSkinAttr[ii].zTitle, iSkin); zBasis = PD("basis","current"); zDflt = skin_file_content(zBasis, zFile); zOrig = db_get_mprintf(zDflt, "draft%d-%s",iSkin,zFile); zContent = PD(zFile,zOrig); if( P("revert")!=0 && cgi_csrf_safe(0) ){ zContent = zDflt; isRevert = 1; } db_begin_transaction(); style_set_current_feature("skins"); style_header("%s", zTitle); for(j=0; j<count(aSkinAttr); j++){ style_submenu_element(aSkinAttr[j].zSubmenu, "%R/setup_skinedit?w=%d&basis=%h&sk=%d",j,zBasis,iSkin); } @ <form action="%R/setup_skinedit" method="post"><div> login_insert_csrf_secret(); @ <input type='hidden' name='w' value='%d(ii)'> @ <input type='hidden' name='sk' value='%d(iSkin)'> @ <h2>Edit %s(zTitle):</h2> if( P("submit") && cgi_csrf_safe(0) && strcmp(zOrig,zContent)!=0 ){ db_set_mprintf(zContent, 0, "draft%d-%s",iSkin,zFile); } @ <textarea name="%s(zFile)" rows="10" cols="80">\ @ %h(zContent)</textarea> @ <br /> @ <input type="submit" name="submit" value="Apply Changes" /> if( isRevert ){ @ ← Press to complete reversion to "%s(zBasis)" |
︙ | ︙ | |||
940 941 942 943 944 945 946 | ); db_protect_pop(); } /* Publish draft iSkin */ for(i=0; i<count(azSkinFile); i++){ char *zNew = db_get_mprintf("", "draft%d-%s", iSkin, azSkinFile[i]); | | | 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 | ); db_protect_pop(); } /* Publish draft iSkin */ for(i=0; i<count(azSkinFile); i++){ char *zNew = db_get_mprintf("", "draft%d-%s", iSkin, azSkinFile[i]); db_set(azSkinFile[i]/*works-like:"x"*/, zNew, 0); } } /* ** WEBPAGE: setup_skin ** ** Generate a page showing the steps needed to customize a skin. |
︙ | ︙ |
Changes to src/sqlite3.c.
1 2 | /****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite | | | 1 2 3 4 5 6 7 8 9 10 | /****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite ** version 3.37.0. By combining all the individual C code files into this ** single large file, the entire code can be compiled as a single translation ** unit. This allows many compilers to do optimizations that would not be ** possible if the files were compiled separately. Performance improvements ** of 5% or more are commonly seen when SQLite is compiled as a single ** translation unit. ** ** This file is all you need to compile SQLite. To use SQLite in other |
︙ | ︙ | |||
18 19 20 21 22 23 24 | ** separate file. This file contains only code for the core SQLite library. */ #define SQLITE_CORE 1 #define SQLITE_AMALGAMATION 1 #ifndef SQLITE_PRIVATE # define SQLITE_PRIVATE static #endif | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | ** separate file. This file contains only code for the core SQLite library. */ #define SQLITE_CORE 1 #define SQLITE_AMALGAMATION 1 #ifndef SQLITE_PRIVATE # define SQLITE_PRIVATE static #endif /************** Begin file sqliteInt.h ***************************************/ /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** |
︙ | ︙ | |||
1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 | */ #if !defined(_USE_32BIT_TIME_T) && !defined(_USE_64BIT_TIME_T) && \ defined(_WIN32) && !defined(_WIN64) && \ defined(__MINGW_MAJOR_VERSION) && __MINGW_MAJOR_VERSION >= 4 && \ defined(__MSVCRT__) # define _USE_32BIT_TIME_T #endif /* The public SQLite interface. The _FILE_OFFSET_BITS macro must appear ** first in QNX. Also, the _USE_32BIT_TIME_T macro must appear first for ** MinGW. */ /************** Include sqlite3.h in the middle of sqliteInt.h ***************/ /************** Begin file sqlite3.h *****************************************/ | > > > > > > > > > > > | 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 | */ #if !defined(_USE_32BIT_TIME_T) && !defined(_USE_64BIT_TIME_T) && \ defined(_WIN32) && !defined(_WIN64) && \ defined(__MINGW_MAJOR_VERSION) && __MINGW_MAJOR_VERSION >= 4 && \ defined(__MSVCRT__) # define _USE_32BIT_TIME_T #endif /* Optionally #include a user-defined header, whereby compilation options ** may be set prior to where they take effect, but after platform setup. ** If SQLITE_CUSTOM_INCLUDE=? is defined, its value names the #include ** file. */ #ifdef SQLITE_CUSTOM_INCLUDE # define INC_STRINGIFY_(f) #f # define INC_STRINGIFY(f) INC_STRINGIFY_(f) # include INC_STRINGIFY(SQLITE_CUSTOM_INCLUDE) #endif /* The public SQLite interface. The _FILE_OFFSET_BITS macro must appear ** first in QNX. Also, the _USE_32BIT_TIME_T macro must appear first for ** MinGW. */ /************** Include sqlite3.h in the middle of sqliteInt.h ***************/ /************** Begin file sqlite3.h *****************************************/ |
︙ | ︙ | |||
1121 1122 1123 1124 1125 1126 1127 | */ #if 0 extern "C" { #endif /* | | > > > > > > > > > > > > > > > > > > > > > > > | 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 | */ #if 0 extern "C" { #endif /* ** Facilitate override of interface linkage and calling conventions. ** Be aware that these macros may not be used within this particular ** translation of the amalgamation and its associated header file. ** ** The SQLITE_EXTERN and SQLITE_API macros are used to instruct the ** compiler that the target identifier should have external linkage. ** ** The SQLITE_CDECL macro is used to set the calling convention for ** public functions that accept a variable number of arguments. ** ** The SQLITE_APICALL macro is used to set the calling convention for ** public functions that accept a fixed number of arguments. ** ** The SQLITE_STDCALL macro is no longer used and is now deprecated. ** ** The SQLITE_CALLBACK macro is used to set the calling convention for ** function pointers. ** ** The SQLITE_SYSAPI macro is used to set the calling convention for ** functions provided by the operating system. ** ** Currently, the SQLITE_CDECL, SQLITE_APICALL, SQLITE_CALLBACK, and ** SQLITE_SYSAPI macros are used only when building for environments ** that require non-default calling conventions. */ #ifndef SQLITE_EXTERN # define SQLITE_EXTERN extern #endif #ifndef SQLITE_API # define SQLITE_API #endif |
︙ | ︙ | |||
1201 1202 1203 1204 1205 1206 1207 | ** been edited in any way since it was last checked in, then the last ** four hexadecimal digits of the hash may be modified. ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ | | | | | 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 | ** been edited in any way since it was last checked in, then the last ** four hexadecimal digits of the hash may be modified. ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.37.0" #define SQLITE_VERSION_NUMBER 3037000 #define SQLITE_SOURCE_ID "2021-08-06 20:17:39 087b8b41c6ed76b55c11315e7e95679d67590be20ae21108b593d00bb7d1c57a" /* ** CAPI3REF: Run-Time Library Version Numbers ** KEYWORDS: sqlite3_version sqlite3_sourceid ** ** These interfaces provide the same information as the [SQLITE_VERSION], ** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros |
︙ | ︙ | |||
1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 | #define SQLITE_BUSY_TIMEOUT (SQLITE_BUSY | (3<<8)) #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8)) #define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8)) #define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8)) #define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8)) #define SQLITE_CANTOPEN_DIRTYWAL (SQLITE_CANTOPEN | (5<<8)) /* Not Used */ #define SQLITE_CANTOPEN_SYMLINK (SQLITE_CANTOPEN | (6<<8)) #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8)) #define SQLITE_CORRUPT_SEQUENCE (SQLITE_CORRUPT | (2<<8)) #define SQLITE_CORRUPT_INDEX (SQLITE_CORRUPT | (3<<8)) #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8)) #define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8)) #define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8)) #define SQLITE_READONLY_DBMOVED (SQLITE_READONLY | (4<<8)) | > | 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 | #define SQLITE_BUSY_TIMEOUT (SQLITE_BUSY | (3<<8)) #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8)) #define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8)) #define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8)) #define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8)) #define SQLITE_CANTOPEN_DIRTYWAL (SQLITE_CANTOPEN | (5<<8)) /* Not Used */ #define SQLITE_CANTOPEN_SYMLINK (SQLITE_CANTOPEN | (6<<8)) #define SQLITE_CANTOPEN_EXISTS (SQLITE_CANTOPEN | (7<<8)) #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8)) #define SQLITE_CORRUPT_SEQUENCE (SQLITE_CORRUPT | (2<<8)) #define SQLITE_CORRUPT_INDEX (SQLITE_CORRUPT | (3<<8)) #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8)) #define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8)) #define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8)) #define SQLITE_READONLY_DBMOVED (SQLITE_READONLY | (4<<8)) |
︙ | ︙ | |||
3542 3543 3544 3545 3546 3547 3548 | */ SQLITE_API void sqlite3_set_last_insert_rowid(sqlite3*,sqlite3_int64); /* ** CAPI3REF: Count The Number Of Rows Modified ** METHOD: sqlite3 ** | | > > > > | < | 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 | */ SQLITE_API void sqlite3_set_last_insert_rowid(sqlite3*,sqlite3_int64); /* ** CAPI3REF: Count The Number Of Rows Modified ** METHOD: sqlite3 ** ** ^These functions return the number of rows modified, inserted or ** deleted by the most recently completed INSERT, UPDATE or DELETE ** statement on the database connection specified by the only parameter. ** The two functions are identical except for the type of the return value ** and that if the number of rows modified by the most recent INSERT, UPDATE ** or DELETE is greater than the maximum value supported by type "int", then ** the return value of sqlite3_changes() is undefined. ^Executing any other ** type of SQL statement does not modify the value returned by these functions. ** ** ^Only changes made directly by the INSERT, UPDATE or DELETE statement are ** considered - auxiliary changes caused by [CREATE TRIGGER | triggers], ** [foreign key actions] or [REPLACE] constraint resolution are not counted. ** ** Changes to a view that are intercepted by ** [INSTEAD OF trigger | INSTEAD OF triggers] are not counted. ^The value |
︙ | ︙ | |||
3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 | ** <li> the [sqlite3_total_changes()] interface ** <li> the [count_changes pragma] ** <li> the [changes() SQL function] ** <li> the [data_version pragma] ** </ul> */ SQLITE_API int sqlite3_changes(sqlite3*); /* ** CAPI3REF: Total Number Of Rows Modified ** METHOD: sqlite3 ** | > | > > > > | | | 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 | ** <li> the [sqlite3_total_changes()] interface ** <li> the [count_changes pragma] ** <li> the [changes() SQL function] ** <li> the [data_version pragma] ** </ul> */ SQLITE_API int sqlite3_changes(sqlite3*); SQLITE_API sqlite3_int64 sqlite3_changes64(sqlite3*); /* ** CAPI3REF: Total Number Of Rows Modified ** METHOD: sqlite3 ** ** ^These functions return the total number of rows inserted, modified or ** deleted by all [INSERT], [UPDATE] or [DELETE] statements completed ** since the database connection was opened, including those executed as ** part of trigger programs. The two functions are identical except for the ** type of the return value and that if the number of rows modified by the ** connection exceeds the maximum value supported by type "int", then ** the return value of sqlite3_total_changes() is undefined. ^Executing ** any other type of SQL statement does not affect the value returned by ** sqlite3_total_changes(). ** ** ^Changes made as part of [foreign key actions] are included in the ** count, but those made as part of REPLACE constraint resolution are ** not. ^Changes to a view that are intercepted by INSTEAD OF triggers ** are not counted. ** ** The [sqlite3_total_changes(D)] interface only reports the number |
︙ | ︙ | |||
3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 | ** <li> the [count_changes pragma] ** <li> the [changes() SQL function] ** <li> the [data_version pragma] ** <li> the [SQLITE_FCNTL_DATA_VERSION] [file control] ** </ul> */ SQLITE_API int sqlite3_total_changes(sqlite3*); /* ** CAPI3REF: Interrupt A Long-Running Query ** METHOD: sqlite3 ** ** ^This function causes any pending database operation to abort and ** return at its earliest opportunity. This routine is typically | > | 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 | ** <li> the [count_changes pragma] ** <li> the [changes() SQL function] ** <li> the [data_version pragma] ** <li> the [SQLITE_FCNTL_DATA_VERSION] [file control] ** </ul> */ SQLITE_API int sqlite3_total_changes(sqlite3*); SQLITE_API sqlite3_int64 sqlite3_total_changes64(sqlite3*); /* ** CAPI3REF: Interrupt A Long-Running Query ** METHOD: sqlite3 ** ** ^This function causes any pending database operation to abort and ** return at its earliest opportunity. This routine is typically |
︙ | ︙ | |||
4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 4475 4476 | ** ^(<dt>[SQLITE_OPEN_PRIVATECACHE]</dt> ** <dd>The database is opened [shared cache] disabled, overriding ** the default shared cache setting provided by ** [sqlite3_enable_shared_cache()].)^ ** ** [[OPEN_NOFOLLOW]] ^(<dt>[SQLITE_OPEN_NOFOLLOW]</dt> ** <dd>The database filename is not allowed to be a symbolic link</dd> ** </dl>)^ ** ** If the 3rd parameter to sqlite3_open_v2() is not one of the ** required combinations shown above optionally combined with other ** [SQLITE_OPEN_READONLY | SQLITE_OPEN_* bits] ** then the behavior is undefined. ** | > > > > > > | 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 | ** ^(<dt>[SQLITE_OPEN_PRIVATECACHE]</dt> ** <dd>The database is opened [shared cache] disabled, overriding ** the default shared cache setting provided by ** [sqlite3_enable_shared_cache()].)^ ** ** [[OPEN_NOFOLLOW]] ^(<dt>[SQLITE_OPEN_NOFOLLOW]</dt> ** <dd>The database filename is not allowed to be a symbolic link</dd> ** ** [[OPEN_EXCLUSIVE]] ^(<dt>[SQLITE_OPEN_EXCLUSIVE]</dt> ** <dd>This flag causes the open to fail if the database file already ** exists. The open will only be success if this flag is used in combination ** with the SQLITE_OPEN_CREATE and SQLITE_OPEN_READWRITE flags and if ** the file does not previously exist.</dd> ** </dl>)^ ** ** If the 3rd parameter to sqlite3_open_v2() is not one of the ** required combinations shown above optionally combined with other ** [SQLITE_OPEN_READONLY | SQLITE_OPEN_* bits] ** then the behavior is undefined. ** |
︙ | ︙ | |||
5236 5237 5238 5239 5240 5241 5242 | ** bound parameter expansions. ^The [SQLITE_OMIT_TRACE] compile-time ** option causes sqlite3_expanded_sql() to always return NULL. ** ** ^The strings returned by sqlite3_sql(P) and sqlite3_normalized_sql(P) ** are managed by SQLite and are automatically freed when the prepared ** statement is finalized. ** ^The string returned by sqlite3_expanded_sql(P), on the other hand, | | > > > > > | 4499 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 | ** bound parameter expansions. ^The [SQLITE_OMIT_TRACE] compile-time ** option causes sqlite3_expanded_sql() to always return NULL. ** ** ^The strings returned by sqlite3_sql(P) and sqlite3_normalized_sql(P) ** are managed by SQLite and are automatically freed when the prepared ** statement is finalized. ** ^The string returned by sqlite3_expanded_sql(P), on the other hand, ** is obtained from [sqlite3_malloc()] and must be freed by the application ** by passing it to [sqlite3_free()]. ** ** ^The sqlite3_normalized_sql() interface is only available if ** the [SQLITE_ENABLE_NORMALIZE] compile-time option is defined. */ SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt); SQLITE_API char *sqlite3_expanded_sql(sqlite3_stmt *pStmt); #ifdef SQLITE_ENABLE_NORMALIZE SQLITE_API const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt); #endif /* ** CAPI3REF: Determine If An SQL Statement Writes The Database ** METHOD: sqlite3_stmt ** ** ^The sqlite3_stmt_readonly(X) interface returns true (non-zero) if ** and only if the [prepared statement] X makes no direct changes to |
︙ | ︙ | |||
5456 5457 5458 5459 5460 5461 5462 | ** terminated. If any NUL characters occurs at byte offsets less than ** the value of the fourth parameter then the resulting string value will ** contain embedded NULs. The result of expressions involving strings ** with embedded NULs is undefined. ** ** ^The fifth argument to the BLOB and string binding interfaces controls ** or indicates the lifetime of the object referenced by the third parameter. | | | | | | 4724 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746 4747 4748 | ** terminated. If any NUL characters occurs at byte offsets less than ** the value of the fourth parameter then the resulting string value will ** contain embedded NULs. The result of expressions involving strings ** with embedded NULs is undefined. ** ** ^The fifth argument to the BLOB and string binding interfaces controls ** or indicates the lifetime of the object referenced by the third parameter. ** These three options exist: ** ^ (1) A destructor to dispose of the BLOB or string after SQLite has finished ** with it may be passed. ^It is called to dispose of the BLOB or string even ** if the call to the bind API fails, except the destructor is not called if ** the third parameter is a NULL pointer or the fourth parameter is negative. ** ^ (2) The special constant, [SQLITE_STATIC], may be passsed to indicate that ** the application remains responsible for disposing of the object. ^In this ** case, the object and the provided pointer to it must remain valid until ** either the prepared statement is finalized or the same SQL parameter is ** bound to something else, whichever occurs sooner. ** ^ (3) The constant, [SQLITE_TRANSIENT], may be passed to indicate that the ** object is to be copied prior to the return from sqlite3_bind_*(). ^The ** object and pointer to it must remain valid until then. ^SQLite will then ** manage the lifetime of its private copy. ** ** ^The sixth argument to sqlite3_bind_text64() must be one of ** [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE] ** to specify the encoding of the text in the third parameter. If |
︙ | ︙ | |||
10088 10089 10090 10091 10092 10093 10094 | ** to report an error, though the commit will have still occurred. If the ** callback returns [SQLITE_ROW] or [SQLITE_DONE], or if it returns a value ** that does not correspond to any valid SQLite error code, the results ** are undefined. ** ** A single database handle may have at most a single write-ahead log callback ** registered at one time. ^Calling [sqlite3_wal_hook()] replaces any | | > | | 9356 9357 9358 9359 9360 9361 9362 9363 9364 9365 9366 9367 9368 9369 9370 9371 9372 | ** to report an error, though the commit will have still occurred. If the ** callback returns [SQLITE_ROW] or [SQLITE_DONE], or if it returns a value ** that does not correspond to any valid SQLite error code, the results ** are undefined. ** ** A single database handle may have at most a single write-ahead log callback ** registered at one time. ^Calling [sqlite3_wal_hook()] replaces any ** previously registered write-ahead log callback. ^The return value is ** a copy of the third parameter from the previous call, if any, or 0. ** ^Note that the [sqlite3_wal_autocheckpoint()] interface and the ** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and will ** overwrite any prior [sqlite3_wal_hook()] settings. */ SQLITE_API void *sqlite3_wal_hook( sqlite3*, int(*)(void *,sqlite3*,const char*,int), void* |
︙ | ︙ | |||
10955 10956 10957 10958 10959 10960 10961 10962 10963 10964 10965 10966 10967 10968 | ** connection closes. If the SQLITE_DESERIALIZE_RESIZEABLE bit is set, then ** SQLite will try to increase the buffer size using sqlite3_realloc64() ** if writes on the database cause it to grow larger than M bytes. ** ** The sqlite3_deserialize() interface will fail with SQLITE_BUSY if the ** database is currently in a read transaction or is involved in a backup ** operation. ** ** If sqlite3_deserialize(D,S,P,N,M,F) fails for any reason and if the ** SQLITE_DESERIALIZE_FREEONCLOSE bit is set in argument F, then ** [sqlite3_free()] is invoked on argument P prior to returning. ** ** This interface is omitted if SQLite is compiled with the ** [SQLITE_OMIT_DESERIALIZE] option. | > > > > | 10224 10225 10226 10227 10228 10229 10230 10231 10232 10233 10234 10235 10236 10237 10238 10239 10240 10241 | ** connection closes. If the SQLITE_DESERIALIZE_RESIZEABLE bit is set, then ** SQLite will try to increase the buffer size using sqlite3_realloc64() ** if writes on the database cause it to grow larger than M bytes. ** ** The sqlite3_deserialize() interface will fail with SQLITE_BUSY if the ** database is currently in a read transaction or is involved in a backup ** operation. ** ** It is not possible to deserialized into the TEMP database. If the ** S argument to sqlite3_deserialize(D,S,P,N,M,F) is "temp" then the ** function returns SQLITE_ERROR. ** ** If sqlite3_deserialize(D,S,P,N,M,F) fails for any reason and if the ** SQLITE_DESERIALIZE_FREEONCLOSE bit is set in argument F, then ** [sqlite3_free()] is invoked on argument P prior to returning. ** ** This interface is omitted if SQLite is compiled with the ** [SQLITE_OMIT_DESERIALIZE] option. |
︙ | ︙ | |||
13438 13439 13440 13441 13442 13443 13444 | /************** Continuing where we left off in sqliteInt.h ******************/ /* ** Include the configuration header output by 'configure' if we're using the ** autoconf-based build */ #if defined(_HAVE_SQLITE_CONFIG_H) && !defined(SQLITECONFIG_H) | | | 12711 12712 12713 12714 12715 12716 12717 12718 12719 12720 12721 12722 12723 12724 12725 | /************** Continuing where we left off in sqliteInt.h ******************/ /* ** Include the configuration header output by 'configure' if we're using the ** autoconf-based build */ #if defined(_HAVE_SQLITE_CONFIG_H) && !defined(SQLITECONFIG_H) #include "config.h" #define SQLITECONFIG_H 1 #endif /************** Include sqliteLimit.h in the middle of sqliteInt.h ***********/ /************** Begin file sqliteLimit.h *************************************/ /* ** 2007 May 7 |
︙ | ︙ | |||
13674 13675 13676 13677 13678 13679 13680 | /* ** WAL mode depends on atomic aligned 32-bit loads and stores in a few ** places. The following macros try to make this explicit. */ #ifndef __has_extension # define __has_extension(x) 0 /* compatibility with non-clang compilers */ #endif | | | > | 12947 12948 12949 12950 12951 12952 12953 12954 12955 12956 12957 12958 12959 12960 12961 12962 12963 12964 12965 12966 | /* ** WAL mode depends on atomic aligned 32-bit loads and stores in a few ** places. The following macros try to make this explicit. */ #ifndef __has_extension # define __has_extension(x) 0 /* compatibility with non-clang compilers */ #endif #if GCC_VERSION>=4007000 || __has_extension(c_atomic) # define SQLITE_ATOMIC_INTRINSICS 1 # define AtomicLoad(PTR) __atomic_load_n((PTR),__ATOMIC_RELAXED) # define AtomicStore(PTR,VAL) __atomic_store_n((PTR),(VAL),__ATOMIC_RELAXED) #else # define SQLITE_ATOMIC_INTRINSICS 0 # define AtomicLoad(PTR) (*(PTR)) # define AtomicStore(PTR,VAL) (*(PTR) = (VAL)) #endif /* ** Include standard header files as necessary */ |
︙ | ︙ | |||
14596 14597 14598 14599 14600 14601 14602 14603 14604 14605 14606 14607 14608 14609 | ** Set the SQLITE_PTRSIZE macro to the number of bytes in a pointer */ #ifndef SQLITE_PTRSIZE # if defined(__SIZEOF_POINTER__) # define SQLITE_PTRSIZE __SIZEOF_POINTER__ # elif defined(i386) || defined(__i386__) || defined(_M_IX86) || \ defined(_M_ARM) || defined(__arm__) || defined(__x86) || \ (defined(__TOS_AIX__) && !defined(__64BIT__)) # define SQLITE_PTRSIZE 4 # else # define SQLITE_PTRSIZE 8 # endif #endif | > | 13870 13871 13872 13873 13874 13875 13876 13877 13878 13879 13880 13881 13882 13883 13884 | ** Set the SQLITE_PTRSIZE macro to the number of bytes in a pointer */ #ifndef SQLITE_PTRSIZE # if defined(__SIZEOF_POINTER__) # define SQLITE_PTRSIZE __SIZEOF_POINTER__ # elif defined(i386) || defined(__i386__) || defined(_M_IX86) || \ defined(_M_ARM) || defined(__arm__) || defined(__x86) || \ (defined(__APPLE__) && defined(__POWERPC__)) || \ (defined(__TOS_AIX__) && !defined(__64BIT__)) # define SQLITE_PTRSIZE 4 # else # define SQLITE_PTRSIZE 8 # endif #endif |
︙ | ︙ | |||
15347 15348 15349 15350 15351 15352 15353 | ** anywhere - the key is the content. (BTREE_BLOBKEY is used for SQL ** indices.) */ #define BTREE_INTKEY 1 /* Table has only 64-bit signed integer keys */ #define BTREE_BLOBKEY 2 /* Table has keys only - no data */ SQLITE_PRIVATE int sqlite3BtreeDropTable(Btree*, int, int*); | | | 14622 14623 14624 14625 14626 14627 14628 14629 14630 14631 14632 14633 14634 14635 14636 | ** anywhere - the key is the content. (BTREE_BLOBKEY is used for SQL ** indices.) */ #define BTREE_INTKEY 1 /* Table has only 64-bit signed integer keys */ #define BTREE_BLOBKEY 2 /* Table has keys only - no data */ SQLITE_PRIVATE int sqlite3BtreeDropTable(Btree*, int, int*); SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree*, int, i64*); SQLITE_PRIVATE int sqlite3BtreeClearTableOfCursor(BtCursor*); SQLITE_PRIVATE int sqlite3BtreeTripAllCursors(Btree*, int, int); SQLITE_PRIVATE void sqlite3BtreeGetMeta(Btree *pBtree, int idx, u32 *pValue); SQLITE_PRIVATE int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value); SQLITE_PRIVATE int sqlite3BtreeNewDb(Btree *p); |
︙ | ︙ | |||
15471 15472 15473 15474 15475 15476 15477 | SQLITE_PRIVATE void sqlite3BtreeCursorZero(BtCursor*); SQLITE_PRIVATE void sqlite3BtreeCursorHintFlags(BtCursor*, unsigned); #ifdef SQLITE_ENABLE_CURSOR_HINTS SQLITE_PRIVATE void sqlite3BtreeCursorHint(BtCursor*, int, ...); #endif SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor*); | | < > > > > > | 14746 14747 14748 14749 14750 14751 14752 14753 14754 14755 14756 14757 14758 14759 14760 14761 14762 14763 14764 14765 14766 14767 14768 14769 | SQLITE_PRIVATE void sqlite3BtreeCursorZero(BtCursor*); SQLITE_PRIVATE void sqlite3BtreeCursorHintFlags(BtCursor*, unsigned); #ifdef SQLITE_ENABLE_CURSOR_HINTS SQLITE_PRIVATE void sqlite3BtreeCursorHint(BtCursor*, int, ...); #endif SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor*); SQLITE_PRIVATE int sqlite3BtreeTableMoveto( BtCursor*, i64 intKey, int bias, int *pRes ); SQLITE_PRIVATE int sqlite3BtreeIndexMoveto( BtCursor*, UnpackedRecord *pUnKey, int *pRes ); SQLITE_PRIVATE int sqlite3BtreeCursorHasMoved(BtCursor*); SQLITE_PRIVATE int sqlite3BtreeCursorRestore(BtCursor*, int*); SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor*, u8 flags); /* Allowed flags for sqlite3BtreeDelete() and sqlite3BtreeInsert() */ #define BTREE_SAVEPOSITION 0x02 /* Leave cursor pointing at NEXT or PREV */ |
︙ | ︙ | |||
17108 17109 17110 17111 17112 17113 17114 | u8 vtabOnConflict; /* Value to return for s3_vtab_on_conflict() */ u8 isTransactionSavepoint; /* True if the outermost savepoint is a TS */ u8 mTrace; /* zero or more SQLITE_TRACE flags */ u8 noSharedCache; /* True if no shared-cache backends */ u8 nSqlExec; /* Number of pending OP_SqlExec opcodes */ int nextPagesize; /* Pagesize after VACUUM if >0 */ u32 magic; /* Magic number for detect library misuse */ | | | | 16387 16388 16389 16390 16391 16392 16393 16394 16395 16396 16397 16398 16399 16400 16401 16402 | u8 vtabOnConflict; /* Value to return for s3_vtab_on_conflict() */ u8 isTransactionSavepoint; /* True if the outermost savepoint is a TS */ u8 mTrace; /* zero or more SQLITE_TRACE flags */ u8 noSharedCache; /* True if no shared-cache backends */ u8 nSqlExec; /* Number of pending OP_SqlExec opcodes */ int nextPagesize; /* Pagesize after VACUUM if >0 */ u32 magic; /* Magic number for detect library misuse */ i64 nChange; /* Value returned by sqlite3_changes() */ i64 nTotalChange; /* Value returned by sqlite3_total_changes() */ int aLimit[SQLITE_N_LIMIT]; /* Limits */ int nMaxSorterMmap; /* Maximum size of regions mapped by sorter */ struct sqlite3InitInfo { /* Information used during initialization */ Pgno newTnum; /* Rootpage of table being initialized */ u8 iDb; /* Which db file is being initialized */ u8 busy; /* TRUE if currently initializing */ unsigned orphanTrigger : 1; /* Last statement is orphaned TEMP trigger */ |
︙ | ︙ | |||
17318 17319 17320 17321 17322 17323 17324 17325 17326 17327 17328 17329 17330 17331 | /* TH3 expects this value ^^^^^^^^^^ to be 0x0000800. Don't change it */ #define SQLITE_PushDown 0x00001000 /* The push-down optimization */ #define SQLITE_SimplifyJoin 0x00002000 /* Convert LEFT JOIN to JOIN */ #define SQLITE_SkipScan 0x00004000 /* Skip-scans */ #define SQLITE_PropagateConst 0x00008000 /* The constant propagation opt */ #define SQLITE_MinMaxOpt 0x00010000 /* The min/max optimization */ #define SQLITE_SeekScan 0x00020000 /* The OP_SeekScan optimization */ #define SQLITE_AllOpts 0xffffffff /* All optimizations */ /* ** Macros for testing whether or not optimizations are enabled or disabled. */ #define OptimizationDisabled(db, mask) (((db)->dbOptFlags&(mask))!=0) #define OptimizationEnabled(db, mask) (((db)->dbOptFlags&(mask))==0) | > > | 16597 16598 16599 16600 16601 16602 16603 16604 16605 16606 16607 16608 16609 16610 16611 16612 | /* TH3 expects this value ^^^^^^^^^^ to be 0x0000800. Don't change it */ #define SQLITE_PushDown 0x00001000 /* The push-down optimization */ #define SQLITE_SimplifyJoin 0x00002000 /* Convert LEFT JOIN to JOIN */ #define SQLITE_SkipScan 0x00004000 /* Skip-scans */ #define SQLITE_PropagateConst 0x00008000 /* The constant propagation opt */ #define SQLITE_MinMaxOpt 0x00010000 /* The min/max optimization */ #define SQLITE_SeekScan 0x00020000 /* The OP_SeekScan optimization */ #define SQLITE_OmitOrderBy 0x00040000 /* Omit pointless ORDER BY */ /* TH3 expects this value ^^^^^^^^^^ to be 0x40000. Coordinate any change */ #define SQLITE_AllOpts 0xffffffff /* All optimizations */ /* ** Macros for testing whether or not optimizations are enabled or disabled. */ #define OptimizationDisabled(db, mask) (((db)->dbOptFlags&(mask))!=0) #define OptimizationEnabled(db, mask) (((db)->dbOptFlags&(mask))==0) |
︙ | ︙ | |||
17397 17398 17399 17400 17401 17402 17403 | /* ** Possible values for FuncDef.flags. Note that the _LENGTH and _TYPEOF ** values must correspond to OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG. And ** SQLITE_FUNC_CONSTANT must be the same as SQLITE_DETERMINISTIC. There ** are assert() statements in the code to verify this. ** ** Value constraints (enforced via assert()): | | > | | | | | | 16678 16679 16680 16681 16682 16683 16684 16685 16686 16687 16688 16689 16690 16691 16692 16693 16694 16695 16696 16697 16698 | /* ** Possible values for FuncDef.flags. Note that the _LENGTH and _TYPEOF ** values must correspond to OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG. And ** SQLITE_FUNC_CONSTANT must be the same as SQLITE_DETERMINISTIC. There ** are assert() statements in the code to verify this. ** ** Value constraints (enforced via assert()): ** SQLITE_FUNC_MINMAX == NC_MinMaxAgg == SF_MinMaxAgg ** SQLITE_FUNC_ANYORDER == NC_OrderAgg == SF_OrderByReqd ** SQLITE_FUNC_LENGTH == OPFLAG_LENGTHARG ** SQLITE_FUNC_TYPEOF == OPFLAG_TYPEOFARG ** SQLITE_FUNC_CONSTANT == SQLITE_DETERMINISTIC from the API ** SQLITE_FUNC_DIRECT == SQLITE_DIRECTONLY from the API ** SQLITE_FUNC_UNSAFE == SQLITE_INNOCUOUS ** SQLITE_FUNC_ENCMASK depends on SQLITE_UTF* macros in the API */ #define SQLITE_FUNC_ENCMASK 0x0003 /* SQLITE_UTF8, SQLITE_UTF16BE or UTF16LE */ #define SQLITE_FUNC_LIKE 0x0004 /* Candidate for the LIKE optimization */ #define SQLITE_FUNC_CASE 0x0008 /* Case-sensitive LIKE-type function */ #define SQLITE_FUNC_EPHEM 0x0010 /* Ephemeral. Delete with VDBE */ #define SQLITE_FUNC_NEEDCOLL 0x0020 /* sqlite3GetFuncCollSeq() might be called*/ |
︙ | ︙ | |||
17427 17428 17429 17430 17431 17432 17433 17434 17435 17436 17437 17438 17439 17440 | #define SQLITE_FUNC_OFFSET 0x8000 /* Built-in sqlite_offset() function */ #define SQLITE_FUNC_WINDOW 0x00010000 /* Built-in window-only function */ #define SQLITE_FUNC_INTERNAL 0x00040000 /* For use by NestedParse() only */ #define SQLITE_FUNC_DIRECT 0x00080000 /* Not for use in TRIGGERs or VIEWs */ #define SQLITE_FUNC_SUBTYPE 0x00100000 /* Result likely to have sub-type */ #define SQLITE_FUNC_UNSAFE 0x00200000 /* Function has side effects */ #define SQLITE_FUNC_INLINE 0x00400000 /* Functions implemented in-line */ /* Identifier numbers for each in-line function */ #define INLINEFUNC_coalesce 0 #define INLINEFUNC_implies_nonnull_row 1 #define INLINEFUNC_expr_implies_expr 2 #define INLINEFUNC_expr_compare 3 #define INLINEFUNC_affinity 4 | > | 16709 16710 16711 16712 16713 16714 16715 16716 16717 16718 16719 16720 16721 16722 16723 | #define SQLITE_FUNC_OFFSET 0x8000 /* Built-in sqlite_offset() function */ #define SQLITE_FUNC_WINDOW 0x00010000 /* Built-in window-only function */ #define SQLITE_FUNC_INTERNAL 0x00040000 /* For use by NestedParse() only */ #define SQLITE_FUNC_DIRECT 0x00080000 /* Not for use in TRIGGERs or VIEWs */ #define SQLITE_FUNC_SUBTYPE 0x00100000 /* Result likely to have sub-type */ #define SQLITE_FUNC_UNSAFE 0x00200000 /* Function has side effects */ #define SQLITE_FUNC_INLINE 0x00400000 /* Functions implemented in-line */ #define SQLITE_FUNC_ANYORDER 0x08000000 /* count/min/max aggregate */ /* Identifier numbers for each in-line function */ #define INLINEFUNC_coalesce 0 #define INLINEFUNC_implies_nonnull_row 1 #define INLINEFUNC_expr_implies_expr 2 #define INLINEFUNC_expr_compare 3 #define INLINEFUNC_affinity 4 |
︙ | ︙ | |||
17597 17598 17599 17600 17601 17602 17603 17604 17605 | ** ** "storage column index" This is the index of the column in the ** record BLOB generated by the OP_MakeRecord ** opcode. The storage column index is less than ** or equal to the table column index. It is ** equal if and only if there are no VIRTUAL ** columns to the left. */ struct Column { | > > > > > > > > | < < | > | | | > | > > > > > > > > > > > > > > > > | 16880 16881 16882 16883 16884 16885 16886 16887 16888 16889 16890 16891 16892 16893 16894 16895 16896 16897 16898 16899 16900 16901 16902 16903 16904 16905 16906 16907 16908 16909 16910 16911 16912 16913 16914 16915 16916 16917 16918 16919 16920 16921 16922 16923 16924 16925 16926 16927 16928 16929 16930 16931 16932 16933 16934 16935 16936 16937 16938 16939 16940 16941 16942 16943 16944 16945 | ** ** "storage column index" This is the index of the column in the ** record BLOB generated by the OP_MakeRecord ** opcode. The storage column index is less than ** or equal to the table column index. It is ** equal if and only if there are no VIRTUAL ** columns to the left. ** ** Notes on zCnName: ** The zCnName field stores the name of the column, the datatype of the ** column, and the collating sequence for the column, in that order, all in ** a single allocation. Each string is 0x00 terminated. The datatype ** is only included if the COLFLAG_HASTYPE bit of colFlags is set and the ** collating sequence name is only included if the COLFLAG_HASCOLL bit is ** set. */ struct Column { char *zCnName; /* Name of this column */ unsigned notNull :4; /* An OE_ code for handling a NOT NULL constraint */ unsigned eType :4; /* One of the standard types */ char affinity; /* One of the SQLITE_AFF_... values */ u8 szEst; /* Est size of value in this column. sizeof(INT)==1 */ u8 hName; /* Column name hash for faster lookup */ u16 iDflt; /* 1-based index of DEFAULT. 0 means "none" */ u16 colFlags; /* Boolean properties. See COLFLAG_ defines below */ }; /* Allowed values for Column.eType. ** ** Values must match entries in the global constant arrays ** sqlite3StdTypeLen[] and sqlite3StdType[]. Each value is one more ** than the offset into these arrays for the corresponding name. ** Adjust the SQLITE_N_STDTYPE value if adding or removing entries. */ #define COLTYPE_CUSTOM 0 /* Type appended to zName */ #define COLTYPE_BLOB 1 #define COLTYPE_INT 2 #define COLTYPE_INTEGER 3 #define COLTYPE_REAL 4 #define COLTYPE_TEXT 5 #define SQLITE_N_STDTYPE 5 /* Number of standard types */ /* Allowed values for Column.colFlags. ** ** Constraints: ** TF_HasVirtual == COLFLAG_VIRTUAL ** TF_HasStored == COLFLAG_STORED ** TF_HasHidden == COLFLAG_HIDDEN */ #define COLFLAG_PRIMKEY 0x0001 /* Column is part of the primary key */ #define COLFLAG_HIDDEN 0x0002 /* A hidden column in a virtual table */ #define COLFLAG_HASTYPE 0x0004 /* Type name follows column name */ #define COLFLAG_UNIQUE 0x0008 /* Column def contains "UNIQUE" or "PK" */ #define COLFLAG_SORTERREF 0x0010 /* Use sorter-refs with this column */ #define COLFLAG_VIRTUAL 0x0020 /* GENERATED ALWAYS AS ... VIRTUAL */ #define COLFLAG_STORED 0x0040 /* GENERATED ALWAYS AS ... STORED */ #define COLFLAG_NOTAVAIL 0x0080 /* STORED column not yet calculated */ #define COLFLAG_BUSY 0x0100 /* Blocks recursion on GENERATED columns */ #define COLFLAG_HASCOLL 0x0200 /* Has collating sequence name in zCnName */ #define COLFLAG_GENERATED 0x0060 /* Combo: _STORED, _VIRTUAL */ #define COLFLAG_NOINSERT 0x0062 /* Combo: _HIDDEN, _STORED, _VIRTUAL */ /* ** A "Collating Sequence" is defined by an instance of the following ** structure. Conceptually, a collating sequence consists of a name and ** a comparison routine that defines the order of that sequence. |
︙ | ︙ | |||
17754 17755 17756 17757 17758 17759 17760 | /* Allowed values for VTable.eVtabRisk */ #define SQLITE_VTABRISK_Low 0 #define SQLITE_VTABRISK_Normal 1 #define SQLITE_VTABRISK_High 2 /* | | | < < | > > | > > > > > > | < > | | | < > > | | | | | | | | | | | | | | | | | | > > > > > > > > > > | | | 17061 17062 17063 17064 17065 17066 17067 17068 17069 17070 17071 17072 17073 17074 17075 17076 17077 17078 17079 17080 17081 17082 17083 17084 17085 17086 17087 17088 17089 17090 17091 17092 17093 17094 17095 17096 17097 17098 17099 17100 17101 17102 17103 17104 17105 17106 17107 17108 17109 17110 17111 17112 17113 17114 17115 17116 17117 17118 17119 17120 17121 17122 17123 17124 17125 17126 17127 17128 17129 17130 17131 17132 17133 17134 17135 17136 17137 17138 17139 17140 17141 17142 17143 17144 17145 17146 17147 17148 17149 17150 17151 17152 17153 17154 17155 17156 17157 17158 17159 17160 17161 17162 17163 17164 17165 17166 17167 17168 17169 17170 | /* Allowed values for VTable.eVtabRisk */ #define SQLITE_VTABRISK_Low 0 #define SQLITE_VTABRISK_Normal 1 #define SQLITE_VTABRISK_High 2 /* ** The schema for each SQL table, virtual table, and view is represented ** in memory by an instance of the following structure. */ struct Table { char *zName; /* Name of the table or view */ Column *aCol; /* Information about each column */ Index *pIndex; /* List of SQL indexes on this table. */ char *zColAff; /* String defining the affinity of each column */ ExprList *pCheck; /* All CHECK constraints */ /* ... also used as column name list in a VIEW */ Pgno tnum; /* Root BTree page for this table */ u32 nTabRef; /* Number of pointers to this Table */ u32 tabFlags; /* Mask of TF_* values */ i16 iPKey; /* If not negative, use aCol[iPKey] as the rowid */ i16 nCol; /* Number of columns in this table */ i16 nNVCol; /* Number of columns that are not VIRTUAL */ LogEst nRowLogEst; /* Estimated rows in table - from sqlite_stat1 table */ LogEst szTabRow; /* Estimated size of each table row in bytes */ #ifdef SQLITE_ENABLE_COSTMULT LogEst costMult; /* Cost multiplier for using this table */ #endif u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */ u8 eTabType; /* 0: normal, 1: virtual, 2: view */ union { struct { /* Used by ordinary tables: */ int addColOffset; /* Offset in CREATE TABLE stmt to add a new column */ FKey *pFKey; /* Linked list of all foreign keys in this table */ ExprList *pDfltList; /* DEFAULT clauses on various columns. ** Or the AS clause for generated columns. */ } tab; struct { /* Used by views: */ Select *pSelect; /* View definition */ } view; struct { /* Used by virtual tables only: */ int nArg; /* Number of arguments to the module */ char **azArg; /* 0: module 1: schema 2: vtab name 3...: args */ VTable *p; /* List of VTable objects. */ } vtab; } u; Trigger *pTrigger; /* List of triggers on this object */ Schema *pSchema; /* Schema that contains this table */ }; /* ** Allowed values for Table.tabFlags. ** ** TF_OOOHidden applies to tables or view that have hidden columns that are ** followed by non-hidden columns. Example: "CREATE VIRTUAL TABLE x USING ** vtab1(a HIDDEN, b);". Since "b" is a non-hidden column but "a" is hidden, ** the TF_OOOHidden attribute would apply in this case. Such tables require ** special handling during INSERT processing. The "OOO" means "Out Of Order". ** ** Constraints: ** ** TF_HasVirtual == COLFLAG_VIRTUAL ** TF_HasStored == COLFLAG_STORED ** TF_HasHidden == COLFLAG_HIDDEN */ #define TF_Readonly 0x00000001 /* Read-only system table */ #define TF_HasHidden 0x00000002 /* Has one or more hidden columns */ #define TF_HasPrimaryKey 0x00000004 /* Table has a primary key */ #define TF_Autoincrement 0x00000008 /* Integer primary key is autoincrement */ #define TF_HasStat1 0x00000010 /* nRowLogEst set from sqlite_stat1 */ #define TF_HasVirtual 0x00000020 /* Has one or more VIRTUAL columns */ #define TF_HasStored 0x00000040 /* Has one or more STORED columns */ #define TF_HasGenerated 0x00000060 /* Combo: HasVirtual + HasStored */ #define TF_WithoutRowid 0x00000080 /* No rowid. PRIMARY KEY is the key */ #define TF_StatsUsed 0x00000100 /* Query planner decisions affected by ** Index.aiRowLogEst[] values */ #define TF_NoVisibleRowid 0x00000200 /* No user-visible "rowid" column */ #define TF_OOOHidden 0x00000400 /* Out-of-Order hidden columns */ #define TF_HasNotNull 0x00000800 /* Contains NOT NULL constraints */ #define TF_Shadow 0x00001000 /* True for a shadow table */ #define TF_HasStat4 0x00002000 /* STAT4 info available for this table */ #define TF_Ephemeral 0x00004000 /* An ephemeral table */ #define TF_Eponymous 0x00008000 /* An eponymous virtual table */ /* ** Allowed values for Table.eTabType */ #define TABTYP_NORM 0 /* Ordinary table */ #define TABTYP_VTAB 1 /* Virtual table */ #define TABTYP_VIEW 2 /* A view */ #define IsView(X) ((X)->eTabType==TABTYP_VIEW) #define IsOrdinaryTable(X) ((X)->eTabType==TABTYP_NORM) /* ** Test to see whether or not a table is a virtual table. This is ** done as a macro so that it will be optimized out when virtual ** table support is omitted from the build. */ #ifndef SQLITE_OMIT_VIRTUALTABLE # define IsVirtual(X) ((X)->eTabType==TABTYP_VTAB) # define ExprIsVtab(X) \ ((X)->op==TK_COLUMN && (X)->y.pTab!=0 && (X)->y.pTab->eTabType==TABTYP_VTAB) #else # define IsVirtual(X) 0 # define ExprIsVtab(X) 0 #endif /* ** Macros to determine if a column is hidden. IsOrdinaryHiddenColumn() |
︙ | ︙ | |||
18662 18663 18664 18665 18666 18667 18668 | Select *pWinSelect; /* SELECT statement for any window functions */ }; /* ** Allowed values for the NameContext, ncFlags field. ** ** Value constraints (all checked via assert()): | | | > | | | | | | | | | | | | | | | | | | | | > | 17986 17987 17988 17989 17990 17991 17992 17993 17994 17995 17996 17997 17998 17999 18000 18001 18002 18003 18004 18005 18006 18007 18008 18009 18010 18011 18012 18013 18014 18015 18016 18017 18018 18019 18020 18021 18022 18023 18024 18025 18026 | Select *pWinSelect; /* SELECT statement for any window functions */ }; /* ** Allowed values for the NameContext, ncFlags field. ** ** Value constraints (all checked via assert()): ** NC_HasAgg == SF_HasAgg == EP_Agg ** NC_MinMaxAgg == SF_MinMaxAgg == SQLITE_FUNC_MINMAX ** NC_OrderAgg == SF_OrderByReqd == SQLITE_FUNC_ANYORDER ** NC_HasWin == EP_Win ** */ #define NC_AllowAgg 0x000001 /* Aggregate functions are allowed here */ #define NC_PartIdx 0x000002 /* True if resolving a partial index WHERE */ #define NC_IsCheck 0x000004 /* True if resolving a CHECK constraint */ #define NC_GenCol 0x000008 /* True for a GENERATED ALWAYS AS clause */ #define NC_HasAgg 0x000010 /* One or more aggregate functions seen */ #define NC_IdxExpr 0x000020 /* True if resolving columns of CREATE INDEX */ #define NC_SelfRef 0x00002e /* Combo: PartIdx, isCheck, GenCol, and IdxExpr */ #define NC_VarSelect 0x000040 /* A correlated subquery has been seen */ #define NC_UEList 0x000080 /* True if uNC.pEList is used */ #define NC_UAggInfo 0x000100 /* True if uNC.pAggInfo is used */ #define NC_UUpsert 0x000200 /* True if uNC.pUpsert is used */ #define NC_UBaseReg 0x000400 /* True if uNC.iBaseReg is used */ #define NC_MinMaxAgg 0x001000 /* min/max aggregates seen. See note above */ #define NC_Complex 0x002000 /* True if a function or subquery seen */ #define NC_AllowWin 0x004000 /* Window functions are allowed here */ #define NC_HasWin 0x008000 /* One or more window functions seen */ #define NC_IsDDL 0x010000 /* Resolving names in a CREATE statement */ #define NC_InAggFunc 0x020000 /* True if analyzing arguments to an agg func */ #define NC_FromDDL 0x040000 /* SQL text comes from sqlite_schema */ #define NC_NoSelect 0x080000 /* Do not descend into sub-selects */ #define NC_OrderAgg 0x8000000 /* Has an aggregate other than count/min/max */ /* ** An instance of the following object describes a single ON CONFLICT ** clause in an upsert. ** ** The pUpsertTarget field is only set if the ON CONFLICT clause includes ** conflict-target clause. (In "ON CONFLICT(a,b)" the "(a,b)" is the |
︙ | ︙ | |||
18769 18770 18771 18772 18773 18774 18775 | }; /* ** Allowed values for Select.selFlags. The "SF" prefix stands for ** "Select Flag". ** ** Value constraints (all checked via assert()) | | | > | | 18095 18096 18097 18098 18099 18100 18101 18102 18103 18104 18105 18106 18107 18108 18109 18110 18111 18112 | }; /* ** Allowed values for Select.selFlags. The "SF" prefix stands for ** "Select Flag". ** ** Value constraints (all checked via assert()) ** SF_HasAgg == NC_HasAgg ** SF_MinMaxAgg == NC_MinMaxAgg == SQLITE_FUNC_MINMAX ** SF_OrderByReqd == NC_OrderAgg == SQLITE_FUNC_ANYORDER ** SF_FixedLimit == WHERE_USE_LIMIT */ #define SF_Distinct 0x0000001 /* Output should be DISTINCT */ #define SF_All 0x0000002 /* Includes the ALL keyword */ #define SF_Resolved 0x0000004 /* Identifiers have been resolved */ #define SF_Aggregate 0x0000008 /* Contains agg functions or a GROUP BY */ #define SF_HasAgg 0x0000010 /* Contains aggregate functions */ #define SF_UsesEphemeral 0x0000020 /* Uses the OpenEphemeral opcode */ |
︙ | ︙ | |||
18796 18797 18798 18799 18800 18801 18802 | #define SF_Converted 0x0010000 /* By convertCompoundSelectToSubquery() */ #define SF_IncludeHidden 0x0020000 /* Include hidden columns in output */ #define SF_ComplexResult 0x0040000 /* Result contains subquery or function */ #define SF_WhereBegin 0x0080000 /* Really a WhereBegin() call. Debug Only */ #define SF_WinRewrite 0x0100000 /* Window function rewrite accomplished */ #define SF_View 0x0200000 /* SELECT statement is a view */ #define SF_NoopOrderBy 0x0400000 /* ORDER BY is ignored for this query */ | | > | 18123 18124 18125 18126 18127 18128 18129 18130 18131 18132 18133 18134 18135 18136 18137 18138 18139 18140 18141 | #define SF_Converted 0x0010000 /* By convertCompoundSelectToSubquery() */ #define SF_IncludeHidden 0x0020000 /* Include hidden columns in output */ #define SF_ComplexResult 0x0040000 /* Result contains subquery or function */ #define SF_WhereBegin 0x0080000 /* Really a WhereBegin() call. Debug Only */ #define SF_WinRewrite 0x0100000 /* Window function rewrite accomplished */ #define SF_View 0x0200000 /* SELECT statement is a view */ #define SF_NoopOrderBy 0x0400000 /* ORDER BY is ignored for this query */ #define SF_UFSrcCheck 0x0800000 /* Check pSrc as required by UPDATE...FROM */ #define SF_PushDown 0x1000000 /* SELECT has be modified by push-down opt */ #define SF_MultiPart 0x2000000 /* Has multiple incompatible PARTITIONs */ #define SF_CopyCte 0x4000000 /* SELECT statement is a copy of a CTE */ #define SF_OrderByReqd 0x8000000 /* The ORDER BY clause may not be omitted */ /* ** The results of a SELECT can be distributed in several ways, as defined ** by one of the following macros. The "SRT" prefix means "SELECT Result ** Type". ** ** SRT_Union Store results as a key in a temporary index |
︙ | ︙ | |||
19882 19883 19884 19885 19886 19887 19888 19889 19890 19891 19892 19893 19894 19895 | SQLITE_PRIVATE void sqlite3SetString(char **, sqlite3*, const char*); SQLITE_PRIVATE void sqlite3ErrorMsg(Parse*, const char*, ...); SQLITE_PRIVATE int sqlite3ErrorToParser(sqlite3*,int); SQLITE_PRIVATE void sqlite3Dequote(char*); SQLITE_PRIVATE void sqlite3DequoteExpr(Expr*); SQLITE_PRIVATE void sqlite3TokenInit(Token*,char*); SQLITE_PRIVATE int sqlite3KeywordCode(const unsigned char*, int); SQLITE_PRIVATE int sqlite3RunParser(Parse*, const char*, char **); SQLITE_PRIVATE void sqlite3FinishCoding(Parse*); SQLITE_PRIVATE int sqlite3GetTempReg(Parse*); SQLITE_PRIVATE void sqlite3ReleaseTempReg(Parse*,int); SQLITE_PRIVATE int sqlite3GetTempRange(Parse*,int); | > | 19210 19211 19212 19213 19214 19215 19216 19217 19218 19219 19220 19221 19222 19223 19224 | SQLITE_PRIVATE void sqlite3SetString(char **, sqlite3*, const char*); SQLITE_PRIVATE void sqlite3ErrorMsg(Parse*, const char*, ...); SQLITE_PRIVATE int sqlite3ErrorToParser(sqlite3*,int); SQLITE_PRIVATE void sqlite3Dequote(char*); SQLITE_PRIVATE void sqlite3DequoteExpr(Expr*); SQLITE_PRIVATE void sqlite3DequoteToken(Token*); SQLITE_PRIVATE void sqlite3TokenInit(Token*,char*); SQLITE_PRIVATE int sqlite3KeywordCode(const unsigned char*, int); SQLITE_PRIVATE int sqlite3RunParser(Parse*, const char*, char **); SQLITE_PRIVATE void sqlite3FinishCoding(Parse*); SQLITE_PRIVATE int sqlite3GetTempReg(Parse*); SQLITE_PRIVATE void sqlite3ReleaseTempReg(Parse*,int); SQLITE_PRIVATE int sqlite3GetTempRange(Parse*,int); |
︙ | ︙ | |||
19909 19910 19911 19912 19913 19914 19915 19916 19917 19918 19919 19920 19921 19922 19923 19924 19925 19926 19927 19928 19929 19930 19931 19932 19933 19934 19935 19936 19937 19938 19939 | SQLITE_PRIVATE void sqlite3ExprFunctionUsable(Parse*,Expr*,FuncDef*); SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse*, Expr*, u32); SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3*, Expr*); SQLITE_PRIVATE void sqlite3ExprDeferredDelete(Parse*, Expr*); SQLITE_PRIVATE void sqlite3ExprUnmapAndDelete(Parse*, Expr*); SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*); SQLITE_PRIVATE ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*); SQLITE_PRIVATE void sqlite3ExprListSetSortOrder(ExprList*,int,int); SQLITE_PRIVATE void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int); SQLITE_PRIVATE void sqlite3ExprListSetSpan(Parse*,ExprList*,const char*,const char*); SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3*, ExprList*); SQLITE_PRIVATE u32 sqlite3ExprListFlags(const ExprList*); SQLITE_PRIVATE int sqlite3IndexHasDuplicateRootPage(Index*); SQLITE_PRIVATE int sqlite3Init(sqlite3*, char**); SQLITE_PRIVATE int sqlite3InitCallback(void*, int, char**, char**); SQLITE_PRIVATE int sqlite3InitOne(sqlite3*, int, char**, u32); SQLITE_PRIVATE void sqlite3Pragma(Parse*,Token*,Token*,Token*,int); #ifndef SQLITE_OMIT_VIRTUALTABLE SQLITE_PRIVATE Module *sqlite3PragmaVtabRegister(sqlite3*,const char *zName); #endif SQLITE_PRIVATE void sqlite3ResetAllSchemasOfConnection(sqlite3*); SQLITE_PRIVATE void sqlite3ResetOneSchema(sqlite3*,int); SQLITE_PRIVATE void sqlite3CollapseDatabaseArray(sqlite3*); SQLITE_PRIVATE void sqlite3CommitInternalChanges(sqlite3*); SQLITE_PRIVATE void sqlite3DeleteColumnNames(sqlite3*,Table*); SQLITE_PRIVATE void sqlite3GenerateColumnNames(Parse *pParse, Select *pSelect); SQLITE_PRIVATE int sqlite3ColumnsFromExprList(Parse*,ExprList*,i16*,Column**); SQLITE_PRIVATE void sqlite3SelectAddColumnTypeAndCollation(Parse*,Table*,Select*,char); SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse*,Select*,char); SQLITE_PRIVATE void sqlite3OpenSchemaTable(Parse *, int); SQLITE_PRIVATE Index *sqlite3PrimaryKeyIndex(Table*); | > > > > > | 19238 19239 19240 19241 19242 19243 19244 19245 19246 19247 19248 19249 19250 19251 19252 19253 19254 19255 19256 19257 19258 19259 19260 19261 19262 19263 19264 19265 19266 19267 19268 19269 19270 19271 19272 19273 | SQLITE_PRIVATE void sqlite3ExprFunctionUsable(Parse*,Expr*,FuncDef*); SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse*, Expr*, u32); SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3*, Expr*); SQLITE_PRIVATE void sqlite3ExprDeferredDelete(Parse*, Expr*); SQLITE_PRIVATE void sqlite3ExprUnmapAndDelete(Parse*, Expr*); SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*); SQLITE_PRIVATE ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*); SQLITE_PRIVATE Select *sqlite3ExprListToValues(Parse*, int, ExprList*); SQLITE_PRIVATE void sqlite3ExprListSetSortOrder(ExprList*,int,int); SQLITE_PRIVATE void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int); SQLITE_PRIVATE void sqlite3ExprListSetSpan(Parse*,ExprList*,const char*,const char*); SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3*, ExprList*); SQLITE_PRIVATE u32 sqlite3ExprListFlags(const ExprList*); SQLITE_PRIVATE int sqlite3IndexHasDuplicateRootPage(Index*); SQLITE_PRIVATE int sqlite3Init(sqlite3*, char**); SQLITE_PRIVATE int sqlite3InitCallback(void*, int, char**, char**); SQLITE_PRIVATE int sqlite3InitOne(sqlite3*, int, char**, u32); SQLITE_PRIVATE void sqlite3Pragma(Parse*,Token*,Token*,Token*,int); #ifndef SQLITE_OMIT_VIRTUALTABLE SQLITE_PRIVATE Module *sqlite3PragmaVtabRegister(sqlite3*,const char *zName); #endif SQLITE_PRIVATE void sqlite3ResetAllSchemasOfConnection(sqlite3*); SQLITE_PRIVATE void sqlite3ResetOneSchema(sqlite3*,int); SQLITE_PRIVATE void sqlite3CollapseDatabaseArray(sqlite3*); SQLITE_PRIVATE void sqlite3CommitInternalChanges(sqlite3*); SQLITE_PRIVATE void sqlite3ColumnSetExpr(Parse*,Table*,Column*,Expr*); SQLITE_PRIVATE Expr *sqlite3ColumnExpr(Table*,Column*); SQLITE_PRIVATE void sqlite3ColumnSetColl(sqlite3*,Column*,const char*zColl); SQLITE_PRIVATE const char *sqlite3ColumnColl(Column*); SQLITE_PRIVATE void sqlite3DeleteColumnNames(sqlite3*,Table*); SQLITE_PRIVATE void sqlite3GenerateColumnNames(Parse *pParse, Select *pSelect); SQLITE_PRIVATE int sqlite3ColumnsFromExprList(Parse*,ExprList*,i16*,Column**); SQLITE_PRIVATE void sqlite3SelectAddColumnTypeAndCollation(Parse*,Table*,Select*,char); SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse*,Select*,char); SQLITE_PRIVATE void sqlite3OpenSchemaTable(Parse *, int); SQLITE_PRIVATE Index *sqlite3PrimaryKeyIndex(Table*); |
︙ | ︙ | |||
19947 19948 19949 19950 19951 19952 19953 | #endif SQLITE_PRIVATE void sqlite3StartTable(Parse*,Token*,Token*,int,int,int,int); #if SQLITE_ENABLE_HIDDEN_COLUMNS SQLITE_PRIVATE void sqlite3ColumnPropertiesFromName(Table*, Column*); #else # define sqlite3ColumnPropertiesFromName(T,C) /* no-op */ #endif | | | 19281 19282 19283 19284 19285 19286 19287 19288 19289 19290 19291 19292 19293 19294 19295 | #endif SQLITE_PRIVATE void sqlite3StartTable(Parse*,Token*,Token*,int,int,int,int); #if SQLITE_ENABLE_HIDDEN_COLUMNS SQLITE_PRIVATE void sqlite3ColumnPropertiesFromName(Table*, Column*); #else # define sqlite3ColumnPropertiesFromName(T,C) /* no-op */ #endif SQLITE_PRIVATE void sqlite3AddColumn(Parse*,Token,Token); SQLITE_PRIVATE void sqlite3AddNotNull(Parse*, int); SQLITE_PRIVATE void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int, int); SQLITE_PRIVATE void sqlite3AddCheckConstraint(Parse*, Expr*, const char*, const char*); SQLITE_PRIVATE void sqlite3AddDefaultValue(Parse*,Expr*,const char*,const char*); SQLITE_PRIVATE void sqlite3AddCollateType(Parse*, Token*); SQLITE_PRIVATE void sqlite3AddGenerated(Parse*,Expr*,Token*); SQLITE_PRIVATE void sqlite3EndTable(Parse*,Token*,Token*,u8,Select*); |
︙ | ︙ | |||
20064 20065 20066 20067 20068 20069 20070 | SQLITE_PRIVATE int sqlite3WhereUsesDeferredSeek(WhereInfo*); SQLITE_PRIVATE void sqlite3ExprCodeLoadIndexColumn(Parse*, Index*, int, int, int); SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8); SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int); SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse*, int, int, int); SQLITE_PRIVATE void sqlite3ExprCode(Parse*, Expr*, int); #ifndef SQLITE_OMIT_GENERATED_COLUMNS | | | 19398 19399 19400 19401 19402 19403 19404 19405 19406 19407 19408 19409 19410 19411 19412 | SQLITE_PRIVATE int sqlite3WhereUsesDeferredSeek(WhereInfo*); SQLITE_PRIVATE void sqlite3ExprCodeLoadIndexColumn(Parse*, Index*, int, int, int); SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8); SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int); SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse*, int, int, int); SQLITE_PRIVATE void sqlite3ExprCode(Parse*, Expr*, int); #ifndef SQLITE_OMIT_GENERATED_COLUMNS SQLITE_PRIVATE void sqlite3ExprCodeGeneratedColumn(Parse*, Table*, Column*, int); #endif SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse*, Expr*, int); SQLITE_PRIVATE void sqlite3ExprCodeFactorable(Parse*, Expr*, int); SQLITE_PRIVATE int sqlite3ExprCodeRunJustOnce(Parse*, Expr*, int); SQLITE_PRIVATE int sqlite3ExprCodeTemp(Parse*, Expr*, int*); SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse*, Expr*, int); SQLITE_PRIVATE int sqlite3ExprCodeExprList(Parse*, ExprList*, int, int, u8); |
︙ | ︙ | |||
20327 20328 20329 20330 20331 20332 20333 | SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, const Token*, int); SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*); SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr*); SQLITE_PRIVATE Expr *sqlite3ExprSkipCollateAndLikely(Expr*); SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *, CollSeq *); SQLITE_PRIVATE int sqlite3WritableSchema(sqlite3*); SQLITE_PRIVATE int sqlite3CheckObjectName(Parse*, const char*,const char*,const char*); | | | 19661 19662 19663 19664 19665 19666 19667 19668 19669 19670 19671 19672 19673 19674 19675 | SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, const Token*, int); SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*); SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr*); SQLITE_PRIVATE Expr *sqlite3ExprSkipCollateAndLikely(Expr*); SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *, CollSeq *); SQLITE_PRIVATE int sqlite3WritableSchema(sqlite3*); SQLITE_PRIVATE int sqlite3CheckObjectName(Parse*, const char*,const char*,const char*); SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *, i64); SQLITE_PRIVATE int sqlite3AddInt64(i64*,i64); SQLITE_PRIVATE int sqlite3SubInt64(i64*,i64); SQLITE_PRIVATE int sqlite3MulInt64(i64*,i64); SQLITE_PRIVATE int sqlite3AbsInt32(int); #ifdef SQLITE_ENABLE_8_3_NAMES SQLITE_PRIVATE void sqlite3FileSuffix3(const char*, char*); #else |
︙ | ︙ | |||
20357 20358 20359 20360 20361 20362 20363 20364 20365 20366 20367 20368 20369 20370 | SQLITE_PRIVATE char *sqlite3Utf16to8(sqlite3 *, const void*, int, u8); #endif SQLITE_PRIVATE int sqlite3ValueFromExpr(sqlite3 *, Expr *, u8, u8, sqlite3_value **); SQLITE_PRIVATE void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8); #ifndef SQLITE_AMALGAMATION SQLITE_PRIVATE const unsigned char sqlite3OpcodeProperty[]; SQLITE_PRIVATE const char sqlite3StrBINARY[]; SQLITE_PRIVATE const unsigned char sqlite3UpperToLower[]; SQLITE_PRIVATE const unsigned char *sqlite3aLTb; SQLITE_PRIVATE const unsigned char *sqlite3aEQb; SQLITE_PRIVATE const unsigned char *sqlite3aGTb; SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[]; SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config; SQLITE_PRIVATE FuncDefHash sqlite3BuiltinFunctions; | > > > | 19691 19692 19693 19694 19695 19696 19697 19698 19699 19700 19701 19702 19703 19704 19705 19706 19707 | SQLITE_PRIVATE char *sqlite3Utf16to8(sqlite3 *, const void*, int, u8); #endif SQLITE_PRIVATE int sqlite3ValueFromExpr(sqlite3 *, Expr *, u8, u8, sqlite3_value **); SQLITE_PRIVATE void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8); #ifndef SQLITE_AMALGAMATION SQLITE_PRIVATE const unsigned char sqlite3OpcodeProperty[]; SQLITE_PRIVATE const char sqlite3StrBINARY[]; SQLITE_PRIVATE const unsigned char sqlite3StdTypeLen[]; SQLITE_PRIVATE const char sqlite3StdTypeAffinity[]; SQLITE_PRIVATE const char *sqlite3StdType[]; SQLITE_PRIVATE const unsigned char sqlite3UpperToLower[]; SQLITE_PRIVATE const unsigned char *sqlite3aLTb; SQLITE_PRIVATE const unsigned char *sqlite3aEQb; SQLITE_PRIVATE const unsigned char *sqlite3aGTb; SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[]; SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config; SQLITE_PRIVATE FuncDefHash sqlite3BuiltinFunctions; |
︙ | ︙ | |||
20777 20778 20779 20780 20781 20782 20783 | #if defined(SQLITE_ENABLE_DBSTAT_VTAB) || defined(SQLITE_TEST) SQLITE_PRIVATE int sqlite3DbstatRegister(sqlite3*); #endif SQLITE_PRIVATE int sqlite3ExprVectorSize(Expr *pExpr); SQLITE_PRIVATE int sqlite3ExprIsVector(Expr *pExpr); SQLITE_PRIVATE Expr *sqlite3VectorFieldSubexpr(Expr*, int); | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 20114 20115 20116 20117 20118 20119 20120 20121 20122 20123 20124 20125 20126 20127 20128 20129 20130 20131 20132 20133 20134 20135 20136 20137 20138 20139 20140 20141 20142 20143 20144 20145 20146 20147 20148 20149 20150 20151 20152 20153 20154 20155 20156 20157 20158 20159 20160 20161 20162 20163 20164 20165 20166 20167 20168 20169 20170 20171 20172 20173 20174 20175 20176 20177 20178 20179 20180 20181 20182 20183 20184 20185 20186 20187 20188 20189 20190 20191 20192 20193 20194 20195 20196 20197 20198 20199 20200 20201 20202 20203 20204 20205 20206 20207 20208 20209 20210 20211 20212 20213 20214 20215 20216 20217 20218 20219 20220 20221 20222 20223 20224 20225 20226 20227 20228 20229 20230 20231 20232 20233 20234 20235 20236 20237 20238 20239 20240 20241 20242 20243 20244 20245 20246 20247 20248 20249 20250 20251 20252 20253 20254 20255 20256 20257 20258 20259 20260 20261 20262 20263 20264 20265 20266 20267 20268 20269 20270 20271 20272 20273 20274 20275 20276 20277 20278 20279 20280 20281 20282 20283 20284 20285 20286 20287 20288 20289 20290 20291 20292 20293 20294 20295 20296 20297 20298 20299 20300 20301 20302 20303 20304 20305 20306 20307 20308 20309 20310 20311 20312 20313 20314 20315 20316 20317 20318 20319 20320 20321 20322 20323 20324 20325 20326 20327 20328 20329 20330 20331 20332 20333 20334 20335 20336 20337 20338 20339 20340 20341 20342 20343 20344 20345 20346 20347 20348 20349 20350 20351 20352 20353 20354 20355 20356 20357 20358 20359 20360 20361 20362 20363 20364 20365 20366 20367 20368 20369 20370 20371 20372 20373 20374 20375 20376 20377 20378 20379 20380 20381 20382 20383 20384 20385 20386 20387 20388 20389 20390 20391 20392 20393 20394 20395 20396 20397 20398 20399 20400 20401 20402 20403 20404 20405 20406 20407 20408 20409 20410 20411 20412 20413 20414 20415 20416 20417 20418 20419 20420 20421 20422 20423 20424 20425 20426 20427 20428 20429 20430 20431 20432 20433 20434 20435 20436 20437 20438 20439 20440 20441 20442 20443 20444 20445 20446 20447 20448 20449 20450 20451 20452 20453 20454 20455 20456 20457 20458 20459 20460 20461 20462 20463 20464 20465 20466 20467 20468 20469 20470 20471 20472 20473 20474 20475 20476 20477 20478 20479 20480 20481 20482 20483 20484 20485 20486 20487 20488 20489 20490 20491 20492 20493 20494 20495 20496 20497 20498 20499 20500 20501 20502 20503 20504 20505 20506 20507 20508 20509 20510 20511 20512 20513 20514 20515 20516 20517 20518 20519 20520 20521 20522 20523 20524 20525 20526 20527 20528 20529 20530 20531 20532 20533 20534 20535 20536 20537 20538 20539 20540 20541 20542 20543 20544 20545 20546 20547 20548 20549 20550 20551 20552 20553 20554 20555 20556 20557 20558 20559 20560 20561 20562 20563 20564 20565 20566 20567 20568 20569 20570 20571 20572 20573 20574 20575 20576 20577 20578 20579 20580 20581 20582 20583 20584 20585 20586 20587 20588 20589 20590 20591 20592 20593 20594 20595 20596 20597 20598 20599 20600 20601 20602 20603 20604 20605 20606 20607 20608 20609 20610 20611 20612 20613 20614 20615 20616 20617 20618 20619 20620 20621 20622 20623 20624 20625 20626 20627 20628 20629 20630 20631 20632 20633 20634 20635 20636 20637 20638 20639 20640 20641 20642 20643 20644 20645 20646 20647 20648 20649 20650 20651 20652 20653 20654 20655 20656 20657 20658 20659 20660 20661 20662 20663 20664 20665 20666 20667 20668 20669 20670 20671 20672 20673 20674 20675 20676 20677 20678 20679 20680 20681 20682 20683 20684 20685 20686 20687 20688 20689 20690 20691 20692 20693 20694 20695 20696 20697 20698 20699 20700 20701 20702 20703 20704 20705 20706 20707 20708 20709 20710 20711 20712 20713 20714 20715 20716 20717 20718 20719 20720 20721 20722 20723 20724 20725 20726 20727 20728 20729 20730 20731 20732 20733 20734 20735 20736 20737 20738 20739 20740 20741 20742 20743 20744 20745 20746 20747 20748 20749 20750 20751 20752 20753 20754 20755 20756 20757 20758 20759 20760 20761 20762 20763 20764 20765 20766 20767 20768 20769 20770 20771 20772 20773 20774 20775 20776 20777 20778 20779 20780 20781 20782 20783 20784 20785 20786 20787 20788 20789 20790 20791 20792 20793 20794 20795 20796 20797 20798 20799 20800 20801 20802 20803 20804 20805 20806 20807 20808 20809 20810 20811 20812 20813 20814 20815 20816 20817 20818 20819 20820 20821 20822 20823 20824 20825 20826 20827 20828 20829 20830 20831 20832 20833 20834 20835 20836 20837 20838 20839 20840 20841 20842 20843 20844 20845 20846 20847 20848 20849 20850 20851 20852 20853 20854 20855 20856 20857 20858 20859 20860 20861 20862 20863 20864 20865 20866 20867 20868 20869 20870 20871 20872 20873 20874 20875 20876 20877 20878 20879 20880 20881 20882 20883 20884 20885 20886 20887 20888 20889 20890 20891 20892 20893 20894 20895 20896 20897 20898 20899 20900 20901 20902 20903 20904 20905 20906 20907 20908 20909 20910 20911 20912 20913 20914 20915 20916 20917 20918 20919 20920 20921 20922 20923 20924 20925 20926 20927 20928 20929 20930 20931 20932 20933 20934 20935 20936 20937 20938 20939 20940 20941 20942 20943 20944 20945 20946 20947 20948 20949 20950 20951 20952 20953 20954 20955 20956 20957 20958 20959 20960 20961 20962 20963 20964 20965 20966 20967 20968 20969 20970 20971 20972 20973 20974 20975 20976 20977 20978 20979 20980 20981 20982 20983 20984 20985 20986 20987 20988 20989 20990 20991 20992 20993 20994 20995 20996 20997 20998 20999 21000 21001 21002 21003 21004 21005 21006 21007 21008 21009 21010 21011 21012 21013 21014 21015 21016 21017 21018 21019 21020 21021 21022 21023 21024 21025 21026 21027 21028 21029 21030 21031 21032 21033 21034 21035 21036 21037 21038 21039 21040 21041 21042 21043 21044 21045 21046 21047 21048 21049 21050 21051 21052 21053 21054 21055 21056 21057 21058 21059 21060 21061 21062 21063 21064 21065 21066 21067 21068 21069 21070 21071 21072 21073 21074 21075 21076 21077 21078 21079 21080 21081 21082 21083 21084 21085 21086 21087 21088 21089 21090 21091 21092 21093 21094 21095 21096 21097 21098 21099 21100 21101 21102 21103 21104 21105 21106 21107 21108 21109 21110 21111 21112 21113 21114 21115 21116 21117 21118 21119 21120 21121 | #if defined(SQLITE_ENABLE_DBSTAT_VTAB) || defined(SQLITE_TEST) SQLITE_PRIVATE int sqlite3DbstatRegister(sqlite3*); #endif SQLITE_PRIVATE int sqlite3ExprVectorSize(Expr *pExpr); SQLITE_PRIVATE int sqlite3ExprIsVector(Expr *pExpr); SQLITE_PRIVATE Expr *sqlite3VectorFieldSubexpr(Expr*, int); SQLITE_PRIVATE Expr *sqlite3ExprForVectorField(Parse*,Expr*,int,int); SQLITE_PRIVATE void sqlite3VectorErrorMsg(Parse*, Expr*); #ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS SQLITE_PRIVATE const char **sqlite3CompileOptions(int *pnOpt); #endif #endif /* SQLITEINT_H */ /************** End of sqliteInt.h *******************************************/ /************** Begin file os_common.h ***************************************/ /* ** 2004 May 22 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ****************************************************************************** ** ** This file contains macros and a little bit of code that is common to ** all of the platform-specific files (os_*.c) and is #included into those ** files. ** ** This file should be #included by the os_*.c files only. It is not a ** general purpose header file. */ #ifndef _OS_COMMON_H_ #define _OS_COMMON_H_ /* ** At least two bugs have slipped in because we changed the MEMORY_DEBUG ** macro to SQLITE_DEBUG and some older makefiles have not yet made the ** switch. The following code should catch this problem at compile-time. */ #ifdef MEMORY_DEBUG # error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead." #endif /* ** Macros for performance tracing. Normally turned off. Only works ** on i486 hardware. */ #ifdef SQLITE_PERFORMANCE_TRACE /* ** hwtime.h contains inline assembler code for implementing ** high-performance timing routines. */ /************** Include hwtime.h in the middle of os_common.h ****************/ /************** Begin file hwtime.h ******************************************/ /* ** 2008 May 27 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ****************************************************************************** ** ** This file contains inline asm code for retrieving "high-performance" ** counters for x86 and x86_64 class CPUs. */ #ifndef SQLITE_HWTIME_H #define SQLITE_HWTIME_H /* ** The following routine only works on pentium-class (or newer) processors. ** It uses the RDTSC opcode to read the cycle count value out of the ** processor and returns that value. This can be used for high-res ** profiling. */ #if !defined(__STRICT_ANSI__) && \ (defined(__GNUC__) || defined(_MSC_VER)) && \ (defined(i386) || defined(__i386__) || defined(_M_IX86)) #if defined(__GNUC__) __inline__ sqlite_uint64 sqlite3Hwtime(void){ unsigned int lo, hi; __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi)); return (sqlite_uint64)hi << 32 | lo; } #elif defined(_MSC_VER) __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){ __asm { rdtsc ret ; return value at EDX:EAX } } #endif #elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__x86_64__)) __inline__ sqlite_uint64 sqlite3Hwtime(void){ unsigned long val; __asm__ __volatile__ ("rdtsc" : "=A" (val)); return val; } #elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__ppc__)) __inline__ sqlite_uint64 sqlite3Hwtime(void){ unsigned long long retval; unsigned long junk; __asm__ __volatile__ ("\n\ 1: mftbu %1\n\ mftb %L0\n\ mftbu %0\n\ cmpw %0,%1\n\ bne 1b" : "=r" (retval), "=r" (junk)); return retval; } #else /* ** asm() is needed for hardware timing support. Without asm(), ** disable the sqlite3Hwtime() routine. ** ** sqlite3Hwtime() is only used for some obscure debugging ** and analysis configurations, not in any deliverable, so this ** should not be a great loss. */ SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); } #endif #endif /* !defined(SQLITE_HWTIME_H) */ /************** End of hwtime.h **********************************************/ /************** Continuing where we left off in os_common.h ******************/ static sqlite_uint64 g_start; static sqlite_uint64 g_elapsed; #define TIMER_START g_start=sqlite3Hwtime() #define TIMER_END g_elapsed=sqlite3Hwtime()-g_start #define TIMER_ELAPSED g_elapsed #else #define TIMER_START #define TIMER_END #define TIMER_ELAPSED ((sqlite_uint64)0) #endif /* ** If we compile with the SQLITE_TEST macro set, then the following block ** of code will give us the ability to simulate a disk I/O error. This ** is used for testing the I/O recovery logic. */ #if defined(SQLITE_TEST) SQLITE_API extern int sqlite3_io_error_hit; SQLITE_API extern int sqlite3_io_error_hardhit; SQLITE_API extern int sqlite3_io_error_pending; SQLITE_API extern int sqlite3_io_error_persist; SQLITE_API extern int sqlite3_io_error_benign; SQLITE_API extern int sqlite3_diskfull_pending; SQLITE_API extern int sqlite3_diskfull; #define SimulateIOErrorBenign(X) sqlite3_io_error_benign=(X) #define SimulateIOError(CODE) \ if( (sqlite3_io_error_persist && sqlite3_io_error_hit) \ || sqlite3_io_error_pending-- == 1 ) \ { local_ioerr(); CODE; } static void local_ioerr(){ IOTRACE(("IOERR\n")); sqlite3_io_error_hit++; if( !sqlite3_io_error_benign ) sqlite3_io_error_hardhit++; } #define SimulateDiskfullError(CODE) \ if( sqlite3_diskfull_pending ){ \ if( sqlite3_diskfull_pending == 1 ){ \ local_ioerr(); \ sqlite3_diskfull = 1; \ sqlite3_io_error_hit = 1; \ CODE; \ }else{ \ sqlite3_diskfull_pending--; \ } \ } #else #define SimulateIOErrorBenign(X) #define SimulateIOError(A) #define SimulateDiskfullError(A) #endif /* defined(SQLITE_TEST) */ /* ** When testing, keep a count of the number of open files. */ #if defined(SQLITE_TEST) SQLITE_API extern int sqlite3_open_file_count; #define OpenCounter(X) sqlite3_open_file_count+=(X) #else #define OpenCounter(X) #endif /* defined(SQLITE_TEST) */ #endif /* !defined(_OS_COMMON_H_) */ /************** End of os_common.h *******************************************/ /************** Begin file ctime.c *******************************************/ /* ** 2010 February 23 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** ** This file implements routines used to report what compile-time options ** SQLite was built with. */ #ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS /* IMP: R-16824-07538 */ /* ** Include the configuration header output by 'configure' if we're using the ** autoconf-based build */ #if defined(_HAVE_SQLITE_CONFIG_H) && !defined(SQLITECONFIG_H) /* #include "config.h" */ #define SQLITECONFIG_H 1 #endif /* These macros are provided to "stringify" the value of the define ** for those options in which the value is meaningful. */ #define CTIMEOPT_VAL_(opt) #opt #define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt) /* Like CTIMEOPT_VAL, but especially for SQLITE_DEFAULT_LOOKASIDE. This ** option requires a separate macro because legal values contain a single ** comma. e.g. (-DSQLITE_DEFAULT_LOOKASIDE="100,100") */ #define CTIMEOPT_VAL2_(opt1,opt2) #opt1 "," #opt2 #define CTIMEOPT_VAL2(opt) CTIMEOPT_VAL2_(opt) /* #include "sqliteInt.h" */ /* ** An array of names of all compile-time options. This array should ** be sorted A-Z. ** ** This array looks large, but in a typical installation actually uses ** only a handful of compile-time options, so most times this array is usually ** rather short and uses little memory space. */ static const char * const sqlite3azCompileOpt[] = { /* ** BEGIN CODE GENERATED BY tool/mkctime.tcl */ #ifdef SQLITE_32BIT_ROWID "32BIT_ROWID", #endif #ifdef SQLITE_4_BYTE_ALIGNED_MALLOC "4_BYTE_ALIGNED_MALLOC", #endif #ifdef SQLITE_64BIT_STATS "64BIT_STATS", #endif #ifdef SQLITE_ALLOW_COVERING_INDEX_SCAN # if SQLITE_ALLOW_COVERING_INDEX_SCAN != 1 "ALLOW_COVERING_INDEX_SCAN=" CTIMEOPT_VAL(SQLITE_ALLOW_COVERING_INDEX_SCAN), # endif #endif #ifdef SQLITE_ALLOW_URI_AUTHORITY "ALLOW_URI_AUTHORITY", #endif #ifdef SQLITE_ATOMIC_INTRINSICS "ATOMIC_INTRINSICS=" CTIMEOPT_VAL(SQLITE_ATOMIC_INTRINSICS), #endif #ifdef SQLITE_BITMASK_TYPE "BITMASK_TYPE=" CTIMEOPT_VAL(SQLITE_BITMASK_TYPE), #endif #ifdef SQLITE_BUG_COMPATIBLE_20160819 "BUG_COMPATIBLE_20160819", #endif #ifdef SQLITE_CASE_SENSITIVE_LIKE "CASE_SENSITIVE_LIKE", #endif #ifdef SQLITE_CHECK_PAGES "CHECK_PAGES", #endif #if defined(__clang__) && defined(__clang_major__) "COMPILER=clang-" CTIMEOPT_VAL(__clang_major__) "." CTIMEOPT_VAL(__clang_minor__) "." CTIMEOPT_VAL(__clang_patchlevel__), #elif defined(_MSC_VER) "COMPILER=msvc-" CTIMEOPT_VAL(_MSC_VER), #elif defined(__GNUC__) && defined(__VERSION__) "COMPILER=gcc-" __VERSION__, #endif #ifdef SQLITE_COVERAGE_TEST "COVERAGE_TEST", #endif #ifdef SQLITE_DEBUG "DEBUG", #endif #ifdef SQLITE_DEFAULT_AUTOMATIC_INDEX "DEFAULT_AUTOMATIC_INDEX", #endif #ifdef SQLITE_DEFAULT_AUTOVACUUM "DEFAULT_AUTOVACUUM", #endif #ifdef SQLITE_DEFAULT_CACHE_SIZE "DEFAULT_CACHE_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_CACHE_SIZE), #endif #ifdef SQLITE_DEFAULT_CKPTFULLFSYNC "DEFAULT_CKPTFULLFSYNC", #endif #ifdef SQLITE_DEFAULT_FILE_FORMAT "DEFAULT_FILE_FORMAT=" CTIMEOPT_VAL(SQLITE_DEFAULT_FILE_FORMAT), #endif #ifdef SQLITE_DEFAULT_FILE_PERMISSIONS "DEFAULT_FILE_PERMISSIONS=" CTIMEOPT_VAL(SQLITE_DEFAULT_FILE_PERMISSIONS), #endif #ifdef SQLITE_DEFAULT_FOREIGN_KEYS "DEFAULT_FOREIGN_KEYS", #endif #ifdef SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT "DEFAULT_JOURNAL_SIZE_LIMIT=" CTIMEOPT_VAL(SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT), #endif #ifdef SQLITE_DEFAULT_LOCKING_MODE "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE), #endif #ifdef SQLITE_DEFAULT_LOOKASIDE "DEFAULT_LOOKASIDE=" CTIMEOPT_VAL2(SQLITE_DEFAULT_LOOKASIDE), #endif #ifdef SQLITE_DEFAULT_MEMSTATUS # if SQLITE_DEFAULT_MEMSTATUS != 1 "DEFAULT_MEMSTATUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_MEMSTATUS), # endif #endif #ifdef SQLITE_DEFAULT_MMAP_SIZE "DEFAULT_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_MMAP_SIZE), #endif #ifdef SQLITE_DEFAULT_PAGE_SIZE "DEFAULT_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_PAGE_SIZE), #endif #ifdef SQLITE_DEFAULT_PCACHE_INITSZ "DEFAULT_PCACHE_INITSZ=" CTIMEOPT_VAL(SQLITE_DEFAULT_PCACHE_INITSZ), #endif #ifdef SQLITE_DEFAULT_PROXYDIR_PERMISSIONS "DEFAULT_PROXYDIR_PERMISSIONS=" CTIMEOPT_VAL(SQLITE_DEFAULT_PROXYDIR_PERMISSIONS), #endif #ifdef SQLITE_DEFAULT_RECURSIVE_TRIGGERS "DEFAULT_RECURSIVE_TRIGGERS", #endif #ifdef SQLITE_DEFAULT_ROWEST "DEFAULT_ROWEST=" CTIMEOPT_VAL(SQLITE_DEFAULT_ROWEST), #endif #ifdef SQLITE_DEFAULT_SECTOR_SIZE "DEFAULT_SECTOR_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_SECTOR_SIZE), #endif #ifdef SQLITE_DEFAULT_SYNCHRONOUS "DEFAULT_SYNCHRONOUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_SYNCHRONOUS), #endif #ifdef SQLITE_DEFAULT_WAL_AUTOCHECKPOINT "DEFAULT_WAL_AUTOCHECKPOINT=" CTIMEOPT_VAL(SQLITE_DEFAULT_WAL_AUTOCHECKPOINT), #endif #ifdef SQLITE_DEFAULT_WAL_SYNCHRONOUS "DEFAULT_WAL_SYNCHRONOUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_WAL_SYNCHRONOUS), #endif #ifdef SQLITE_DEFAULT_WORKER_THREADS "DEFAULT_WORKER_THREADS=" CTIMEOPT_VAL(SQLITE_DEFAULT_WORKER_THREADS), #endif #ifdef SQLITE_DIRECT_OVERFLOW_READ "DIRECT_OVERFLOW_READ", #endif #ifdef SQLITE_DISABLE_DIRSYNC "DISABLE_DIRSYNC", #endif #ifdef SQLITE_DISABLE_FTS3_UNICODE "DISABLE_FTS3_UNICODE", #endif #ifdef SQLITE_DISABLE_FTS4_DEFERRED "DISABLE_FTS4_DEFERRED", #endif #ifdef SQLITE_DISABLE_INTRINSIC "DISABLE_INTRINSIC", #endif #ifdef SQLITE_DISABLE_LFS "DISABLE_LFS", #endif #ifdef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS "DISABLE_PAGECACHE_OVERFLOW_STATS", #endif #ifdef SQLITE_DISABLE_SKIPAHEAD_DISTINCT "DISABLE_SKIPAHEAD_DISTINCT", #endif #ifdef SQLITE_ENABLE_8_3_NAMES "ENABLE_8_3_NAMES=" CTIMEOPT_VAL(SQLITE_ENABLE_8_3_NAMES), #endif #ifdef SQLITE_ENABLE_API_ARMOR "ENABLE_API_ARMOR", #endif #ifdef SQLITE_ENABLE_ATOMIC_WRITE "ENABLE_ATOMIC_WRITE", #endif #ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE "ENABLE_BATCH_ATOMIC_WRITE", #endif #ifdef SQLITE_ENABLE_BYTECODE_VTAB "ENABLE_BYTECODE_VTAB", #endif #ifdef SQLITE_ENABLE_CEROD "ENABLE_CEROD=" CTIMEOPT_VAL(SQLITE_ENABLE_CEROD), #endif #ifdef SQLITE_ENABLE_COLUMN_METADATA "ENABLE_COLUMN_METADATA", #endif #ifdef SQLITE_ENABLE_COLUMN_USED_MASK "ENABLE_COLUMN_USED_MASK", #endif #ifdef SQLITE_ENABLE_COSTMULT "ENABLE_COSTMULT", #endif #ifdef SQLITE_ENABLE_CURSOR_HINTS "ENABLE_CURSOR_HINTS", #endif #ifdef SQLITE_ENABLE_DBPAGE_VTAB "ENABLE_DBPAGE_VTAB", #endif #ifdef SQLITE_ENABLE_DBSTAT_VTAB "ENABLE_DBSTAT_VTAB", #endif #ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT "ENABLE_EXPENSIVE_ASSERT", #endif #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS "ENABLE_EXPLAIN_COMMENTS", #endif #ifdef SQLITE_ENABLE_FTS3 "ENABLE_FTS3", #endif #ifdef SQLITE_ENABLE_FTS3_PARENTHESIS "ENABLE_FTS3_PARENTHESIS", #endif #ifdef SQLITE_ENABLE_FTS3_TOKENIZER "ENABLE_FTS3_TOKENIZER", #endif #ifdef SQLITE_ENABLE_FTS4 "ENABLE_FTS4", #endif #ifdef SQLITE_ENABLE_FTS5 "ENABLE_FTS5", #endif #ifdef SQLITE_ENABLE_GEOPOLY "ENABLE_GEOPOLY", #endif #ifdef SQLITE_ENABLE_HIDDEN_COLUMNS "ENABLE_HIDDEN_COLUMNS", #endif #ifdef SQLITE_ENABLE_ICU "ENABLE_ICU", #endif #ifdef SQLITE_ENABLE_IOTRACE "ENABLE_IOTRACE", #endif #ifdef SQLITE_ENABLE_JSON1 "ENABLE_JSON1", #endif #ifdef SQLITE_ENABLE_LOAD_EXTENSION "ENABLE_LOAD_EXTENSION", #endif #ifdef SQLITE_ENABLE_LOCKING_STYLE "ENABLE_LOCKING_STYLE=" CTIMEOPT_VAL(SQLITE_ENABLE_LOCKING_STYLE), #endif #ifdef SQLITE_ENABLE_MATH_FUNCTIONS "ENABLE_MATH_FUNCTIONS", #endif #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT "ENABLE_MEMORY_MANAGEMENT", #endif #ifdef SQLITE_ENABLE_MEMSYS3 "ENABLE_MEMSYS3", #endif #ifdef SQLITE_ENABLE_MEMSYS5 "ENABLE_MEMSYS5", #endif #ifdef SQLITE_ENABLE_MULTIPLEX "ENABLE_MULTIPLEX", #endif #ifdef SQLITE_ENABLE_NORMALIZE "ENABLE_NORMALIZE", #endif #ifdef SQLITE_ENABLE_NULL_TRIM "ENABLE_NULL_TRIM", #endif #ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC "ENABLE_OFFSET_SQL_FUNC", #endif #ifdef SQLITE_ENABLE_OVERSIZE_CELL_CHECK "ENABLE_OVERSIZE_CELL_CHECK", #endif #ifdef SQLITE_ENABLE_PREUPDATE_HOOK "ENABLE_PREUPDATE_HOOK", #endif #ifdef SQLITE_ENABLE_QPSG "ENABLE_QPSG", #endif #ifdef SQLITE_ENABLE_RBU "ENABLE_RBU", #endif #ifdef SQLITE_ENABLE_RTREE "ENABLE_RTREE", #endif #ifdef SQLITE_ENABLE_SELECTTRACE "ENABLE_SELECTTRACE", #endif #ifdef SQLITE_ENABLE_SESSION "ENABLE_SESSION", #endif #ifdef SQLITE_ENABLE_SNAPSHOT "ENABLE_SNAPSHOT", #endif #ifdef SQLITE_ENABLE_SORTER_REFERENCES "ENABLE_SORTER_REFERENCES", #endif #ifdef SQLITE_ENABLE_SQLLOG "ENABLE_SQLLOG", #endif #ifdef SQLITE_ENABLE_STAT4 "ENABLE_STAT4", #endif #ifdef SQLITE_ENABLE_STMTVTAB "ENABLE_STMTVTAB", #endif #ifdef SQLITE_ENABLE_STMT_SCANSTATUS "ENABLE_STMT_SCANSTATUS", #endif #ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION "ENABLE_UNKNOWN_SQL_FUNCTION", #endif #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY "ENABLE_UNLOCK_NOTIFY", #endif #ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT "ENABLE_UPDATE_DELETE_LIMIT", #endif #ifdef SQLITE_ENABLE_URI_00_ERROR "ENABLE_URI_00_ERROR", #endif #ifdef SQLITE_ENABLE_VFSTRACE "ENABLE_VFSTRACE", #endif #ifdef SQLITE_ENABLE_WHERETRACE "ENABLE_WHERETRACE", #endif #ifdef SQLITE_ENABLE_ZIPVFS "ENABLE_ZIPVFS", #endif #ifdef SQLITE_EXPLAIN_ESTIMATED_ROWS "EXPLAIN_ESTIMATED_ROWS", #endif #ifdef SQLITE_EXTRA_IFNULLROW "EXTRA_IFNULLROW", #endif #ifdef SQLITE_EXTRA_INIT "EXTRA_INIT=" CTIMEOPT_VAL(SQLITE_EXTRA_INIT), #endif #ifdef SQLITE_EXTRA_SHUTDOWN "EXTRA_SHUTDOWN=" CTIMEOPT_VAL(SQLITE_EXTRA_SHUTDOWN), #endif #ifdef SQLITE_FTS3_MAX_EXPR_DEPTH "FTS3_MAX_EXPR_DEPTH=" CTIMEOPT_VAL(SQLITE_FTS3_MAX_EXPR_DEPTH), #endif #ifdef SQLITE_FTS5_ENABLE_TEST_MI "FTS5_ENABLE_TEST_MI", #endif #ifdef SQLITE_FTS5_NO_WITHOUT_ROWID "FTS5_NO_WITHOUT_ROWID", #endif #if HAVE_ISNAN || SQLITE_HAVE_ISNAN "HAVE_ISNAN", #endif #ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX # if SQLITE_HOMEGROWN_RECURSIVE_MUTEX != 1 "HOMEGROWN_RECURSIVE_MUTEX=" CTIMEOPT_VAL(SQLITE_HOMEGROWN_RECURSIVE_MUTEX), # endif #endif #ifdef SQLITE_IGNORE_AFP_LOCK_ERRORS "IGNORE_AFP_LOCK_ERRORS", #endif #ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS "IGNORE_FLOCK_LOCK_ERRORS", #endif #ifdef SQLITE_INLINE_MEMCPY "INLINE_MEMCPY", #endif #ifdef SQLITE_INT64_TYPE "INT64_TYPE", #endif #ifdef SQLITE_INTEGRITY_CHECK_ERROR_MAX "INTEGRITY_CHECK_ERROR_MAX=" CTIMEOPT_VAL(SQLITE_INTEGRITY_CHECK_ERROR_MAX), #endif #ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS "LIKE_DOESNT_MATCH_BLOBS", #endif #ifdef SQLITE_LOCK_TRACE "LOCK_TRACE", #endif #ifdef SQLITE_LOG_CACHE_SPILL "LOG_CACHE_SPILL", #endif #ifdef SQLITE_MALLOC_SOFT_LIMIT "MALLOC_SOFT_LIMIT=" CTIMEOPT_VAL(SQLITE_MALLOC_SOFT_LIMIT), #endif #ifdef SQLITE_MAX_ATTACHED "MAX_ATTACHED=" CTIMEOPT_VAL(SQLITE_MAX_ATTACHED), #endif #ifdef SQLITE_MAX_COLUMN "MAX_COLUMN=" CTIMEOPT_VAL(SQLITE_MAX_COLUMN), #endif #ifdef SQLITE_MAX_COMPOUND_SELECT "MAX_COMPOUND_SELECT=" CTIMEOPT_VAL(SQLITE_MAX_COMPOUND_SELECT), #endif #ifdef SQLITE_MAX_DEFAULT_PAGE_SIZE "MAX_DEFAULT_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_DEFAULT_PAGE_SIZE), #endif #ifdef SQLITE_MAX_EXPR_DEPTH "MAX_EXPR_DEPTH=" CTIMEOPT_VAL(SQLITE_MAX_EXPR_DEPTH), #endif #ifdef SQLITE_MAX_FUNCTION_ARG "MAX_FUNCTION_ARG=" CTIMEOPT_VAL(SQLITE_MAX_FUNCTION_ARG), #endif #ifdef SQLITE_MAX_LENGTH "MAX_LENGTH=" CTIMEOPT_VAL(SQLITE_MAX_LENGTH), #endif #ifdef SQLITE_MAX_LIKE_PATTERN_LENGTH "MAX_LIKE_PATTERN_LENGTH=" CTIMEOPT_VAL(SQLITE_MAX_LIKE_PATTERN_LENGTH), #endif #ifdef SQLITE_MAX_MEMORY "MAX_MEMORY=" CTIMEOPT_VAL(SQLITE_MAX_MEMORY), #endif #ifdef SQLITE_MAX_MMAP_SIZE "MAX_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_MMAP_SIZE), #endif #ifdef SQLITE_MAX_MMAP_SIZE_ "MAX_MMAP_SIZE_=" CTIMEOPT_VAL(SQLITE_MAX_MMAP_SIZE_), #endif #ifdef SQLITE_MAX_PAGE_COUNT "MAX_PAGE_COUNT=" CTIMEOPT_VAL(SQLITE_MAX_PAGE_COUNT), #endif #ifdef SQLITE_MAX_PAGE_SIZE "MAX_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_PAGE_SIZE), #endif #ifdef SQLITE_MAX_SCHEMA_RETRY "MAX_SCHEMA_RETRY=" CTIMEOPT_VAL(SQLITE_MAX_SCHEMA_RETRY), #endif #ifdef SQLITE_MAX_SQL_LENGTH "MAX_SQL_LENGTH=" CTIMEOPT_VAL(SQLITE_MAX_SQL_LENGTH), #endif #ifdef SQLITE_MAX_TRIGGER_DEPTH "MAX_TRIGGER_DEPTH=" CTIMEOPT_VAL(SQLITE_MAX_TRIGGER_DEPTH), #endif #ifdef SQLITE_MAX_VARIABLE_NUMBER "MAX_VARIABLE_NUMBER=" CTIMEOPT_VAL(SQLITE_MAX_VARIABLE_NUMBER), #endif #ifdef SQLITE_MAX_VDBE_OP "MAX_VDBE_OP=" CTIMEOPT_VAL(SQLITE_MAX_VDBE_OP), #endif #ifdef SQLITE_MAX_WORKER_THREADS "MAX_WORKER_THREADS=" CTIMEOPT_VAL(SQLITE_MAX_WORKER_THREADS), #endif #ifdef SQLITE_MEMDEBUG "MEMDEBUG", #endif #ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT "MIXED_ENDIAN_64BIT_FLOAT", #endif #ifdef SQLITE_MMAP_READWRITE "MMAP_READWRITE", #endif #ifdef SQLITE_MUTEX_NOOP "MUTEX_NOOP", #endif #ifdef SQLITE_MUTEX_OMIT "MUTEX_OMIT", #endif #ifdef SQLITE_MUTEX_PTHREADS "MUTEX_PTHREADS", #endif #ifdef SQLITE_MUTEX_W32 "MUTEX_W32", #endif #ifdef SQLITE_NEED_ERR_NAME "NEED_ERR_NAME", #endif #ifdef SQLITE_NO_SYNC "NO_SYNC", #endif #ifdef SQLITE_OMIT_ALTERTABLE "OMIT_ALTERTABLE", #endif #ifdef SQLITE_OMIT_ANALYZE "OMIT_ANALYZE", #endif #ifdef SQLITE_OMIT_ATTACH "OMIT_ATTACH", #endif #ifdef SQLITE_OMIT_AUTHORIZATION "OMIT_AUTHORIZATION", #endif #ifdef SQLITE_OMIT_AUTOINCREMENT "OMIT_AUTOINCREMENT", #endif #ifdef SQLITE_OMIT_AUTOINIT "OMIT_AUTOINIT", #endif #ifdef SQLITE_OMIT_AUTOMATIC_INDEX "OMIT_AUTOMATIC_INDEX", #endif #ifdef SQLITE_OMIT_AUTORESET "OMIT_AUTORESET", #endif #ifdef SQLITE_OMIT_AUTOVACUUM "OMIT_AUTOVACUUM", #endif #ifdef SQLITE_OMIT_BETWEEN_OPTIMIZATION "OMIT_BETWEEN_OPTIMIZATION", #endif #ifdef SQLITE_OMIT_BLOB_LITERAL "OMIT_BLOB_LITERAL", #endif #ifdef SQLITE_OMIT_CAST "OMIT_CAST", #endif #ifdef SQLITE_OMIT_CHECK "OMIT_CHECK", #endif #ifdef SQLITE_OMIT_COMPLETE "OMIT_COMPLETE", #endif #ifdef SQLITE_OMIT_COMPOUND_SELECT "OMIT_COMPOUND_SELECT", #endif #ifdef SQLITE_OMIT_CONFLICT_CLAUSE "OMIT_CONFLICT_CLAUSE", #endif #ifdef SQLITE_OMIT_CTE "OMIT_CTE", #endif #if defined(SQLITE_OMIT_DATETIME_FUNCS) || defined(SQLITE_OMIT_FLOATING_POINT) "OMIT_DATETIME_FUNCS", #endif #ifdef SQLITE_OMIT_DECLTYPE "OMIT_DECLTYPE", #endif #ifdef SQLITE_OMIT_DEPRECATED "OMIT_DEPRECATED", #endif #ifdef SQLITE_OMIT_DESERIALIZE "OMIT_DESERIALIZE", #endif #ifdef SQLITE_OMIT_DISKIO "OMIT_DISKIO", #endif #ifdef SQLITE_OMIT_EXPLAIN "OMIT_EXPLAIN", #endif #ifdef SQLITE_OMIT_FLAG_PRAGMAS "OMIT_FLAG_PRAGMAS", #endif #ifdef SQLITE_OMIT_FLOATING_POINT "OMIT_FLOATING_POINT", #endif #ifdef SQLITE_OMIT_FOREIGN_KEY "OMIT_FOREIGN_KEY", #endif #ifdef SQLITE_OMIT_GET_TABLE "OMIT_GET_TABLE", #endif #ifdef SQLITE_OMIT_HEX_INTEGER "OMIT_HEX_INTEGER", #endif #ifdef SQLITE_OMIT_INCRBLOB "OMIT_INCRBLOB", #endif #ifdef SQLITE_OMIT_INTEGRITY_CHECK "OMIT_INTEGRITY_CHECK", #endif #ifdef SQLITE_OMIT_INTROSPECTION_PRAGMAS "OMIT_INTROSPECTION_PRAGMAS", #endif #ifdef SQLITE_OMIT_LIKE_OPTIMIZATION "OMIT_LIKE_OPTIMIZATION", #endif #ifdef SQLITE_OMIT_LOAD_EXTENSION "OMIT_LOAD_EXTENSION", #endif #ifdef SQLITE_OMIT_LOCALTIME "OMIT_LOCALTIME", #endif #ifdef SQLITE_OMIT_LOOKASIDE "OMIT_LOOKASIDE", #endif #ifdef SQLITE_OMIT_MEMORYDB "OMIT_MEMORYDB", #endif #ifdef SQLITE_OMIT_OR_OPTIMIZATION "OMIT_OR_OPTIMIZATION", #endif #ifdef SQLITE_OMIT_PAGER_PRAGMAS "OMIT_PAGER_PRAGMAS", #endif #ifdef SQLITE_OMIT_PARSER_TRACE "OMIT_PARSER_TRACE", #endif #ifdef SQLITE_OMIT_POPEN "OMIT_POPEN", #endif #ifdef SQLITE_OMIT_PRAGMA "OMIT_PRAGMA", #endif #ifdef SQLITE_OMIT_PROGRESS_CALLBACK "OMIT_PROGRESS_CALLBACK", #endif #ifdef SQLITE_OMIT_QUICKBALANCE "OMIT_QUICKBALANCE", #endif #ifdef SQLITE_OMIT_REINDEX "OMIT_REINDEX", #endif #ifdef SQLITE_OMIT_SCHEMA_PRAGMAS "OMIT_SCHEMA_PRAGMAS", #endif #ifdef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS "OMIT_SCHEMA_VERSION_PRAGMAS", #endif #ifdef SQLITE_OMIT_SHARED_CACHE "OMIT_SHARED_CACHE", #endif #ifdef SQLITE_OMIT_SHUTDOWN_DIRECTORIES "OMIT_SHUTDOWN_DIRECTORIES", #endif #ifdef SQLITE_OMIT_SUBQUERY "OMIT_SUBQUERY", #endif #ifdef SQLITE_OMIT_TCL_VARIABLE "OMIT_TCL_VARIABLE", #endif #ifdef SQLITE_OMIT_TEMPDB "OMIT_TEMPDB", #endif #ifdef SQLITE_OMIT_TEST_CONTROL "OMIT_TEST_CONTROL", #endif #ifdef SQLITE_OMIT_TRACE # if SQLITE_OMIT_TRACE != 1 "OMIT_TRACE=" CTIMEOPT_VAL(SQLITE_OMIT_TRACE), # endif #endif #ifdef SQLITE_OMIT_TRIGGER "OMIT_TRIGGER", #endif #ifdef SQLITE_OMIT_TRUNCATE_OPTIMIZATION "OMIT_TRUNCATE_OPTIMIZATION", #endif #ifdef SQLITE_OMIT_UTF16 "OMIT_UTF16", #endif #ifdef SQLITE_OMIT_VACUUM "OMIT_VACUUM", #endif #ifdef SQLITE_OMIT_VIEW "OMIT_VIEW", #endif #ifdef SQLITE_OMIT_VIRTUALTABLE "OMIT_VIRTUALTABLE", #endif #ifdef SQLITE_OMIT_WAL "OMIT_WAL", #endif #ifdef SQLITE_OMIT_WSD "OMIT_WSD", #endif #ifdef SQLITE_OMIT_XFER_OPT "OMIT_XFER_OPT", #endif #ifdef SQLITE_PCACHE_SEPARATE_HEADER "PCACHE_SEPARATE_HEADER", #endif #ifdef SQLITE_PERFORMANCE_TRACE "PERFORMANCE_TRACE", #endif #ifdef SQLITE_POWERSAFE_OVERWRITE # if SQLITE_POWERSAFE_OVERWRITE != 1 "POWERSAFE_OVERWRITE=" CTIMEOPT_VAL(SQLITE_POWERSAFE_OVERWRITE), # endif #endif #ifdef SQLITE_PREFER_PROXY_LOCKING "PREFER_PROXY_LOCKING", #endif #ifdef SQLITE_PROXY_DEBUG "PROXY_DEBUG", #endif #ifdef SQLITE_REVERSE_UNORDERED_SELECTS "REVERSE_UNORDERED_SELECTS", #endif #ifdef SQLITE_RTREE_INT_ONLY "RTREE_INT_ONLY", #endif #ifdef SQLITE_SECURE_DELETE "SECURE_DELETE", #endif #ifdef SQLITE_SMALL_STACK "SMALL_STACK", #endif #ifdef SQLITE_SORTER_PMASZ "SORTER_PMASZ=" CTIMEOPT_VAL(SQLITE_SORTER_PMASZ), #endif #ifdef SQLITE_SOUNDEX "SOUNDEX", #endif #ifdef SQLITE_STAT4_SAMPLES "STAT4_SAMPLES=" CTIMEOPT_VAL(SQLITE_STAT4_SAMPLES), #endif #ifdef SQLITE_STMTJRNL_SPILL "STMTJRNL_SPILL=" CTIMEOPT_VAL(SQLITE_STMTJRNL_SPILL), #endif #ifdef SQLITE_SUBSTR_COMPATIBILITY "SUBSTR_COMPATIBILITY", #endif #if (!defined(SQLITE_WIN32_MALLOC) \ && !defined(SQLITE_ZERO_MALLOC) \ && !defined(SQLITE_MEMDEBUG) \ ) || defined(SQLITE_SYSTEM_MALLOC) "SYSTEM_MALLOC", #endif #ifdef SQLITE_TCL "TCL", #endif #ifdef SQLITE_TEMP_STORE "TEMP_STORE=" CTIMEOPT_VAL(SQLITE_TEMP_STORE), #endif #ifdef SQLITE_TEST "TEST", #endif #if defined(SQLITE_THREADSAFE) "THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE), #elif defined(THREADSAFE) "THREADSAFE=" CTIMEOPT_VAL(THREADSAFE), #else "THREADSAFE=1", #endif #ifdef SQLITE_UNLINK_AFTER_CLOSE "UNLINK_AFTER_CLOSE", #endif #ifdef SQLITE_UNTESTABLE "UNTESTABLE", #endif #ifdef SQLITE_USER_AUTHENTICATION "USER_AUTHENTICATION", #endif #ifdef SQLITE_USE_ALLOCA "USE_ALLOCA", #endif #ifdef SQLITE_USE_FCNTL_TRACE "USE_FCNTL_TRACE", #endif #ifdef SQLITE_USE_URI "USE_URI", #endif #ifdef SQLITE_VDBE_COVERAGE "VDBE_COVERAGE", #endif #ifdef SQLITE_WIN32_MALLOC "WIN32_MALLOC", #endif #ifdef SQLITE_ZERO_MALLOC "ZERO_MALLOC", #endif /* ** END CODE GENERATED BY tool/mkctime.tcl */ }; SQLITE_PRIVATE const char **sqlite3CompileOptions(int *pnOpt){ *pnOpt = sizeof(sqlite3azCompileOpt) / sizeof(sqlite3azCompileOpt[0]); return (const char**)sqlite3azCompileOpt; } #endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ /************** End of ctime.c ***********************************************/ /************** Begin file global.c ******************************************/ /* ** 2008 June 13 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** |
︙ | ︙ | |||
21137 21138 21139 21140 21141 21142 21143 21144 21145 21146 21147 21148 21149 21150 | */ SQLITE_PRIVATE const unsigned char sqlite3OpcodeProperty[] = OPFLG_INITIALIZER; /* ** Name of the default collating sequence */ SQLITE_PRIVATE const char sqlite3StrBINARY[] = "BINARY"; /************** End of global.c **********************************************/ /************** Begin file status.c ******************************************/ /* ** 2008 June 18 ** ** The author disclaims copyright to this source code. In place of | > > > > > > > > > > > > > > > > > > > > | 21458 21459 21460 21461 21462 21463 21464 21465 21466 21467 21468 21469 21470 21471 21472 21473 21474 21475 21476 21477 21478 21479 21480 21481 21482 21483 21484 21485 21486 21487 21488 21489 21490 21491 | */ SQLITE_PRIVATE const unsigned char sqlite3OpcodeProperty[] = OPFLG_INITIALIZER; /* ** Name of the default collating sequence */ SQLITE_PRIVATE const char sqlite3StrBINARY[] = "BINARY"; /* ** Standard typenames. These names must match the COLTYPE_* definitions. ** Adjust the SQLITE_N_STDTYPE value if adding or removing entries. */ SQLITE_PRIVATE const unsigned char sqlite3StdTypeLen[] = { 4, 3, 7, 4, 4 }; SQLITE_PRIVATE const char sqlite3StdTypeAffinity[] = { SQLITE_AFF_BLOB, SQLITE_AFF_INTEGER, SQLITE_AFF_INTEGER, SQLITE_AFF_REAL, SQLITE_AFF_TEXT }; SQLITE_PRIVATE const char *sqlite3StdType[] = { "BLOB", "INT", "INTEGER", "REAL", "TEXT" }; /************** End of global.c **********************************************/ /************** Begin file status.c ******************************************/ /* ** 2008 June 18 ** ** The author disclaims copyright to this source code. In place of |
︙ | ︙ | |||
21340 21341 21342 21343 21344 21345 21346 | #endif int nCursor; /* Number of entries in apCsr */ int pc; /* Program Counter in parent (calling) frame */ int nOp; /* Size of aOp array */ int nMem; /* Number of entries in aMem */ int nChildMem; /* Number of memory cells for child frame */ int nChildCsr; /* Number of cursors for child frame */ | | | | 21681 21682 21683 21684 21685 21686 21687 21688 21689 21690 21691 21692 21693 21694 21695 21696 | #endif int nCursor; /* Number of entries in apCsr */ int pc; /* Program Counter in parent (calling) frame */ int nOp; /* Size of aOp array */ int nMem; /* Number of entries in aMem */ int nChildMem; /* Number of memory cells for child frame */ int nChildCsr; /* Number of cursors for child frame */ i64 nChange; /* Statement changes (Vdbe.nChange) */ i64 nDbChange; /* Value of db->nChange */ }; /* Magic number for sanity checking on VdbeFrame objects */ #define SQLITE_FRAME_MAGIC 0x879fb71e /* ** Return a pointer to the array of registers allocated for use |
︙ | ︙ | |||
21548 21549 21550 21551 21552 21553 21554 | ynVar nVar; /* Number of entries in aVar[] */ u32 iVdbeMagic; /* Magic number defining state of the SQL statement */ int nMem; /* Number of memory locations currently allocated */ int nCursor; /* Number of slots in apCsr[] */ u32 cacheCtr; /* VdbeCursor row cache generation counter */ int pc; /* The program counter */ int rc; /* Value to return */ | | | 21889 21890 21891 21892 21893 21894 21895 21896 21897 21898 21899 21900 21901 21902 21903 | ynVar nVar; /* Number of entries in aVar[] */ u32 iVdbeMagic; /* Magic number defining state of the SQL statement */ int nMem; /* Number of memory locations currently allocated */ int nCursor; /* Number of slots in apCsr[] */ u32 cacheCtr; /* VdbeCursor row cache generation counter */ int pc; /* The program counter */ int rc; /* Value to return */ i64 nChange; /* Number of db changes made since last reset */ int iStatement; /* Statement number (or 0 if has no opened stmt) */ i64 iCurrentTime; /* Value of julianday('now') for this statement */ i64 nFkConstraint; /* Number of imm. FK constraints this VM */ i64 nStmtDefCons; /* Number of def. constraints when stmt started */ i64 nStmtDefImmCons; /* Number of def. imm constraints when stmt started */ Mem *aMem; /* The memory locations */ Mem **apArg; /* Arguments to currently executing user function */ |
︙ | ︙ | |||
21693 21694 21695 21696 21697 21698 21699 21700 21701 21702 21703 21704 21705 21706 | SQLITE_PRIVATE void sqlite3VdbeMemSetZeroBlob(Mem*,int); #ifdef SQLITE_DEBUG SQLITE_PRIVATE int sqlite3VdbeMemIsRowSet(const Mem*); #endif SQLITE_PRIVATE int sqlite3VdbeMemSetRowSet(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem*, u8, u8); SQLITE_PRIVATE i64 sqlite3VdbeIntValue(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemIntegerify(Mem*); SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem*); SQLITE_PRIVATE int sqlite3VdbeBooleanValue(Mem*, int ifNull); SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem*); | > | 22034 22035 22036 22037 22038 22039 22040 22041 22042 22043 22044 22045 22046 22047 22048 | SQLITE_PRIVATE void sqlite3VdbeMemSetZeroBlob(Mem*,int); #ifdef SQLITE_DEBUG SQLITE_PRIVATE int sqlite3VdbeMemIsRowSet(const Mem*); #endif SQLITE_PRIVATE int sqlite3VdbeMemSetRowSet(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem*, u8, u8); SQLITE_PRIVATE int sqlite3IntFloatCompare(i64,double); SQLITE_PRIVATE i64 sqlite3VdbeIntValue(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemIntegerify(Mem*); SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem*); SQLITE_PRIVATE int sqlite3VdbeBooleanValue(Mem*, int ifNull); SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem*); |
︙ | ︙ | |||
27106 27107 27108 27109 27110 27111 27112 | */ /* #include "sqliteInt.h" */ #if SQLITE_OS_WIN /* ** Include code that is common to all os_*.c files */ | < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 27448 27449 27450 27451 27452 27453 27454 27455 27456 27457 27458 27459 27460 27461 27462 | */ /* #include "sqliteInt.h" */ #if SQLITE_OS_WIN /* ** Include code that is common to all os_*.c files */ /* #include "os_common.h" */ /* ** Include the header file for the Windows VFS. */ /************** Include os_win.h in the middle of mutex_w32.c ****************/ /************** Begin file os_win.h ******************************************/ /* |
︙ | ︙ | |||
30075 30076 30077 30078 30079 30080 30081 30082 30083 30084 30085 30086 30087 30088 | sqlite3_str_appendf(&x, "{%d:*} %!S", pItem->iCursor, pItem); if( pItem->pTab ){ sqlite3_str_appendf(&x, " tab=%Q nCol=%d ptr=%p used=%llx", pItem->pTab->zName, pItem->pTab->nCol, pItem->pTab, pItem->colUsed); } if( pItem->fg.jointype & JT_LEFT ){ sqlite3_str_appendf(&x, " LEFT-JOIN"); } if( pItem->fg.fromDDL ){ sqlite3_str_appendf(&x, " DDL"); } if( pItem->fg.isCte ){ sqlite3_str_appendf(&x, " CteUse=0x%p", pItem->u2.pCteUse); } | > > | 30219 30220 30221 30222 30223 30224 30225 30226 30227 30228 30229 30230 30231 30232 30233 30234 | sqlite3_str_appendf(&x, "{%d:*} %!S", pItem->iCursor, pItem); if( pItem->pTab ){ sqlite3_str_appendf(&x, " tab=%Q nCol=%d ptr=%p used=%llx", pItem->pTab->zName, pItem->pTab->nCol, pItem->pTab, pItem->colUsed); } if( pItem->fg.jointype & JT_LEFT ){ sqlite3_str_appendf(&x, " LEFT-JOIN"); }else if( pItem->fg.jointype & JT_CROSS ){ sqlite3_str_appendf(&x, " CROSS-JOIN"); } if( pItem->fg.fromDDL ){ sqlite3_str_appendf(&x, " DDL"); } if( pItem->fg.isCte ){ sqlite3_str_appendf(&x, " CteUse=0x%p", pItem->u2.pCteUse); } |
︙ | ︙ | |||
30405 30406 30407 30408 30409 30410 30411 | break; } case TK_NULL: { sqlite3TreeViewLine(pView,"NULL"); break; } case TK_TRUEFALSE: { | | | | 30551 30552 30553 30554 30555 30556 30557 30558 30559 30560 30561 30562 30563 30564 30565 30566 | break; } case TK_NULL: { sqlite3TreeViewLine(pView,"NULL"); break; } case TK_TRUEFALSE: { sqlite3TreeViewLine(pView,"%s%s", sqlite3ExprTruthValue(pExpr) ? "TRUE" : "FALSE", zFlgs); break; } #ifndef SQLITE_OMIT_BLOB_LITERAL case TK_BLOB: { sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken); break; } |
︙ | ︙ | |||
30630 30631 30632 30633 30634 30635 30636 | case TK_VECTOR: { char *z = sqlite3_mprintf("VECTOR%s",zFlgs); sqlite3TreeViewBareExprList(pView, pExpr->x.pList, z); sqlite3_free(z); break; } case TK_SELECT_COLUMN: { | | > > > > > > > > > > > | 30776 30777 30778 30779 30780 30781 30782 30783 30784 30785 30786 30787 30788 30789 30790 30791 30792 30793 30794 30795 30796 30797 30798 30799 30800 30801 30802 30803 30804 30805 30806 30807 30808 30809 30810 30811 30812 30813 30814 30815 30816 | case TK_VECTOR: { char *z = sqlite3_mprintf("VECTOR%s",zFlgs); sqlite3TreeViewBareExprList(pView, pExpr->x.pList, z); sqlite3_free(z); break; } case TK_SELECT_COLUMN: { sqlite3TreeViewLine(pView, "SELECT-COLUMN %d of [0..%d]%s", pExpr->iColumn, pExpr->iTable-1, pExpr->pRight==pExpr->pLeft ? " (SELECT-owner)" : ""); sqlite3TreeViewSelect(pView, pExpr->pLeft->x.pSelect, 0); break; } case TK_IF_NULL_ROW: { sqlite3TreeViewLine(pView, "IF-NULL-ROW %d", pExpr->iTable); sqlite3TreeViewExpr(pView, pExpr->pLeft, 0); break; } case TK_ERROR: { Expr tmp; sqlite3TreeViewLine(pView, "ERROR"); tmp = *pExpr; tmp.op = pExpr->op2; sqlite3TreeViewExpr(pView, &tmp, 0); break; } case TK_ROW: { if( pExpr->iColumn<=0 ){ sqlite3TreeViewLine(pView, "First FROM table rowid"); }else{ sqlite3TreeViewLine(pView, "First FROM table column %d", pExpr->iColumn-1); } break; } default: { sqlite3TreeViewLine(pView, "op=%d", pExpr->op); break; } } if( zBinOp ){ |
︙ | ︙ | |||
30796 30797 30798 30799 30800 30801 30802 30803 30804 30805 30806 | ** trying to do secure encryption or anything like that... ** ** Nothing in this file or anywhere else in SQLite does any kind of ** encryption. The RC4 algorithm is being used as a PRNG (pseudo-random ** number generator) not as an encryption device. */ if( !wsdPrng.isInit ){ int i; char k[256]; wsdPrng.j = 0; wsdPrng.i = 0; | > > > > | > | 30953 30954 30955 30956 30957 30958 30959 30960 30961 30962 30963 30964 30965 30966 30967 30968 30969 30970 30971 30972 30973 30974 30975 30976 | ** trying to do secure encryption or anything like that... ** ** Nothing in this file or anywhere else in SQLite does any kind of ** encryption. The RC4 algorithm is being used as a PRNG (pseudo-random ** number generator) not as an encryption device. */ if( !wsdPrng.isInit ){ sqlite3_vfs *pVfs = sqlite3_vfs_find(0); int i; char k[256]; wsdPrng.j = 0; wsdPrng.i = 0; if( NEVER(pVfs==0) ){ memset(k, 0, sizeof(k)); }else{ sqlite3OsRandomness(pVfs, 256, k); } for(i=0; i<256; i++){ wsdPrng.s[i] = (u8)i; } for(i=0; i<256; i++){ wsdPrng.j += wsdPrng.s[i] + k[i]; t = wsdPrng.s[wsdPrng.j]; wsdPrng.s[wsdPrng.j] = wsdPrng.s[i]; |
︙ | ︙ | |||
31761 31762 31763 31764 31765 31766 31767 | ** Return the declared type of a column. Or return zDflt if the column ** has no declared type. ** ** The column type is an extra string stored after the zero-terminator on ** the column name if and only if the COLFLAG_HASTYPE flag is set. */ SQLITE_PRIVATE char *sqlite3ColumnType(Column *pCol, char *zDflt){ | | | > > > > > > | 31923 31924 31925 31926 31927 31928 31929 31930 31931 31932 31933 31934 31935 31936 31937 31938 31939 31940 31941 31942 31943 31944 | ** Return the declared type of a column. Or return zDflt if the column ** has no declared type. ** ** The column type is an extra string stored after the zero-terminator on ** the column name if and only if the COLFLAG_HASTYPE flag is set. */ SQLITE_PRIVATE char *sqlite3ColumnType(Column *pCol, char *zDflt){ if( pCol->colFlags & COLFLAG_HASTYPE ){ return pCol->zCnName + strlen(pCol->zCnName) + 1; }else if( pCol->eType ){ assert( pCol->eType<=SQLITE_N_STDTYPE ); return (char*)sqlite3StdType[pCol->eType-1]; }else{ return zDflt; } } /* ** Helper function for sqlite3Error() - called rarely. Broken out into ** a separate routine to avoid unnecessary register saves on entry to ** sqlite3Error(). */ |
︙ | ︙ | |||
31937 31938 31939 31940 31941 31942 31943 31944 31945 31946 31947 31948 31949 31950 | z[j] = 0; } SQLITE_PRIVATE void sqlite3DequoteExpr(Expr *p){ assert( sqlite3Isquote(p->u.zToken[0]) ); p->flags |= p->u.zToken[0]=='"' ? EP_Quoted|EP_DblQuoted : EP_Quoted; sqlite3Dequote(p->u.zToken); } /* ** Generate a Token object from a string */ SQLITE_PRIVATE void sqlite3TokenInit(Token *p, char *z){ p->z = z; p->n = sqlite3Strlen30(z); | > > > > > > > > > > > > > > > > > > > > > > | 32105 32106 32107 32108 32109 32110 32111 32112 32113 32114 32115 32116 32117 32118 32119 32120 32121 32122 32123 32124 32125 32126 32127 32128 32129 32130 32131 32132 32133 32134 32135 32136 32137 32138 32139 32140 | z[j] = 0; } SQLITE_PRIVATE void sqlite3DequoteExpr(Expr *p){ assert( sqlite3Isquote(p->u.zToken[0]) ); p->flags |= p->u.zToken[0]=='"' ? EP_Quoted|EP_DblQuoted : EP_Quoted; sqlite3Dequote(p->u.zToken); } /* ** If the input token p is quoted, try to adjust the token to remove ** the quotes. This is not always possible: ** ** "abc" -> abc ** "ab""cd" -> (not possible because of the interior "") ** ** Remove the quotes if possible. This is a optimization. The overall ** system should still return the correct answer even if this routine ** is always a no-op. */ SQLITE_PRIVATE void sqlite3DequoteToken(Token *p){ unsigned int i; if( p->n<2 ) return; if( !sqlite3Isquote(p->z[0]) ) return; for(i=1; i<p->n-1; i++){ if( sqlite3Isquote(p->z[i]) ) return; } p->n -= 2; p->z++; } /* ** Generate a Token object from a string */ SQLITE_PRIVATE void sqlite3TokenInit(Token *p, char *z){ p->z = z; p->n = sqlite3Strlen30(z); |
︙ | ︙ | |||
34148 34149 34150 34151 34152 34153 34154 | #define UNIXFILE_DELETE 0x20 /* Delete on close */ #define UNIXFILE_URI 0x40 /* Filename might have query parameters */ #define UNIXFILE_NOLOCK 0x80 /* Do no file locking */ /* ** Include code that is common to all os_*.c files */ | < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 34338 34339 34340 34341 34342 34343 34344 34345 34346 34347 34348 34349 34350 34351 34352 | #define UNIXFILE_DELETE 0x20 /* Delete on close */ #define UNIXFILE_URI 0x40 /* Filename might have query parameters */ #define UNIXFILE_NOLOCK 0x80 /* Do no file locking */ /* ** Include code that is common to all os_*.c files */ /* #include "os_common.h" */ /* ** Define various macros that are missing from some systems. */ #ifndef O_LARGEFILE # define O_LARGEFILE 0 #endif |
︙ | ︙ | |||
40234 40235 40236 40237 40238 40239 40240 40241 40242 40243 40244 40245 40246 40247 | OSTRACE(("OPENX %-3d %s 0%o\n", fd, zName, openFlags)); assert( !isExclusive || (openFlags & O_CREAT)!=0 ); if( fd<0 ){ if( isNewJrnl && errno==EACCES && osAccess(zName, F_OK) ){ /* If unable to create a journal because the directory is not ** writable, change the error code to indicate that. */ rc = SQLITE_READONLY_DIRECTORY; }else if( errno!=EISDIR && isReadWrite ){ /* Failed to open the file for read/write access. Try read-only. */ flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE); openFlags &= ~(O_RDWR|O_CREAT); flags |= SQLITE_OPEN_READONLY; openFlags |= O_RDONLY; isReadonly = 1; | > > | 40226 40227 40228 40229 40230 40231 40232 40233 40234 40235 40236 40237 40238 40239 40240 40241 | OSTRACE(("OPENX %-3d %s 0%o\n", fd, zName, openFlags)); assert( !isExclusive || (openFlags & O_CREAT)!=0 ); if( fd<0 ){ if( isNewJrnl && errno==EACCES && osAccess(zName, F_OK) ){ /* If unable to create a journal because the directory is not ** writable, change the error code to indicate that. */ rc = SQLITE_READONLY_DIRECTORY; }else if( errno==EEXIST ){ rc = SQLITE_CANTOPEN_EXISTS; }else if( errno!=EISDIR && isReadWrite ){ /* Failed to open the file for read/write access. Try read-only. */ flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE); openFlags &= ~(O_RDWR|O_CREAT); flags |= SQLITE_OPEN_READONLY; openFlags |= O_RDONLY; isReadonly = 1; |
︙ | ︙ | |||
42117 42118 42119 42120 42121 42122 42123 42124 42125 42126 42127 42128 42129 42130 42131 42132 42133 42134 42135 42136 42137 42138 42139 42140 42141 42142 42143 42144 42145 | /* Register all VFSes defined in the aVfs[] array */ for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){ sqlite3_vfs_register(&aVfs[i], i==0); } unixBigLock = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1); /* Validate lock assumptions */ assert( SQLITE_SHM_NLOCK==8 ); /* Number of available locks */ assert( UNIX_SHM_BASE==120 ); /* Start of locking area */ /* Locks: ** WRITE UNIX_SHM_BASE 120 ** CKPT UNIX_SHM_BASE+1 121 ** RECOVER UNIX_SHM_BASE+2 122 ** READ-0 UNIX_SHM_BASE+3 123 ** READ-1 UNIX_SHM_BASE+4 124 ** READ-2 UNIX_SHM_BASE+5 125 ** READ-3 UNIX_SHM_BASE+6 126 ** READ-4 UNIX_SHM_BASE+7 127 ** DMS UNIX_SHM_BASE+8 128 */ assert( UNIX_SHM_DMS==128 ); /* Byte offset of the deadman-switch */ return SQLITE_OK; } /* ** Shutdown the operating system interface. ** ** Some operating systems might need to do some cleanup in this routine, | > > > | 42111 42112 42113 42114 42115 42116 42117 42118 42119 42120 42121 42122 42123 42124 42125 42126 42127 42128 42129 42130 42131 42132 42133 42134 42135 42136 42137 42138 42139 42140 42141 42142 | /* Register all VFSes defined in the aVfs[] array */ for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){ sqlite3_vfs_register(&aVfs[i], i==0); } unixBigLock = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1); #ifndef SQLITE_OMIT_WAL /* Validate lock assumptions */ assert( SQLITE_SHM_NLOCK==8 ); /* Number of available locks */ assert( UNIX_SHM_BASE==120 ); /* Start of locking area */ /* Locks: ** WRITE UNIX_SHM_BASE 120 ** CKPT UNIX_SHM_BASE+1 121 ** RECOVER UNIX_SHM_BASE+2 122 ** READ-0 UNIX_SHM_BASE+3 123 ** READ-1 UNIX_SHM_BASE+4 124 ** READ-2 UNIX_SHM_BASE+5 125 ** READ-3 UNIX_SHM_BASE+6 126 ** READ-4 UNIX_SHM_BASE+7 127 ** DMS UNIX_SHM_BASE+8 128 */ assert( UNIX_SHM_DMS==128 ); /* Byte offset of the deadman-switch */ #endif return SQLITE_OK; } /* ** Shutdown the operating system interface. ** ** Some operating systems might need to do some cleanup in this routine, |
︙ | ︙ | |||
42171 42172 42173 42174 42175 42176 42177 | */ /* #include "sqliteInt.h" */ #if SQLITE_OS_WIN /* This file is used for Windows only */ /* ** Include code that is common to all os_*.c files */ | < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 42168 42169 42170 42171 42172 42173 42174 42175 42176 42177 42178 42179 42180 42181 42182 | */ /* #include "sqliteInt.h" */ #if SQLITE_OS_WIN /* This file is used for Windows only */ /* ** Include code that is common to all os_*.c files */ /* #include "os_common.h" */ /* ** Include the header file for the Windows VFS. */ /* #include "os_win.h" */ /* |
︙ | ︙ | |||
49317 49318 49319 49320 49321 49322 49323 | if( szDb<0 ) return SQLITE_MISUSE_BKPT; if( szBuf<0 ) return SQLITE_MISUSE_BKPT; #endif sqlite3_mutex_enter(db->mutex); if( zSchema==0 ) zSchema = db->aDb[0].zDbSName; iDb = sqlite3FindDbName(db, zSchema); | > | | 49116 49117 49118 49119 49120 49121 49122 49123 49124 49125 49126 49127 49128 49129 49130 49131 | if( szDb<0 ) return SQLITE_MISUSE_BKPT; if( szBuf<0 ) return SQLITE_MISUSE_BKPT; #endif sqlite3_mutex_enter(db->mutex); if( zSchema==0 ) zSchema = db->aDb[0].zDbSName; iDb = sqlite3FindDbName(db, zSchema); testcase( iDb==1 ); if( iDb<2 && iDb!=0 ){ rc = SQLITE_ERROR; goto end_deserialize; } zSql = sqlite3_mprintf("ATTACH x AS %Q", zSchema); if( zSql==0 ){ rc = SQLITE_NOMEM; }else{ |
︙ | ︙ | |||
49369 49370 49371 49372 49373 49374 49375 | /* ** This routine is called when the extension is loaded. ** Register the new VFS. */ SQLITE_PRIVATE int sqlite3MemdbInit(void){ sqlite3_vfs *pLower = sqlite3_vfs_find(0); | | > > | 49169 49170 49171 49172 49173 49174 49175 49176 49177 49178 49179 49180 49181 49182 49183 49184 49185 | /* ** This routine is called when the extension is loaded. ** Register the new VFS. */ SQLITE_PRIVATE int sqlite3MemdbInit(void){ sqlite3_vfs *pLower = sqlite3_vfs_find(0); unsigned int sz; if( NEVER(pLower==0) ) return SQLITE_ERROR; sz = pLower->szOsFile; memdb_vfs.pAppData = pLower; /* The following conditional can only be true when compiled for ** Windows x86 and SQLITE_MAX_MMAP_SIZE=0. We always leave ** it in, to be safe, but it is marked as NO_TEST since there ** is no way to reach it under most builds. */ if( sz<sizeof(MemFile) ) sz = sizeof(MemFile); /*NO_TEST*/ memdb_vfs.szOsFile = sz; |
︙ | ︙ | |||
60502 60503 60504 60505 60506 60507 60508 | ** in the mxFrame field. ** ** Each index block except for the first contains information on ** HASHTABLE_NPAGE frames. The first index block contains information on ** HASHTABLE_NPAGE_ONE frames. The values of HASHTABLE_NPAGE_ONE and ** HASHTABLE_NPAGE are selected so that together the wal-index header and ** first index block are the same size as all other index blocks in the | | > > > | 60304 60305 60306 60307 60308 60309 60310 60311 60312 60313 60314 60315 60316 60317 60318 60319 60320 60321 | ** in the mxFrame field. ** ** Each index block except for the first contains information on ** HASHTABLE_NPAGE frames. The first index block contains information on ** HASHTABLE_NPAGE_ONE frames. The values of HASHTABLE_NPAGE_ONE and ** HASHTABLE_NPAGE are selected so that together the wal-index header and ** first index block are the same size as all other index blocks in the ** wal-index. The values are: ** ** HASHTABLE_NPAGE 4096 ** HASHTABLE_NPAGE_ONE 4062 ** ** Each index block contains two sections, a page-mapping that contains the ** database page number associated with each wal frame, and a hash-table ** that allows readers to query an index block for a specific page number. ** The page-mapping is an array of HASHTABLE_NPAGE (or HASHTABLE_NPAGE_ONE ** for the first index block) 32-bit page numbers. The first entry in the ** first index-block contains the database page number corresponding to the |
︙ | ︙ | |||
60738 60739 60740 60741 60742 60743 60744 60745 60746 60747 60748 60749 60750 60751 | u32 aReadMark[WAL_NREADER]; /* Reader marks */ u8 aLock[SQLITE_SHM_NLOCK]; /* Reserved space for locks */ u32 nBackfillAttempted; /* WAL frames perhaps written, or maybe not */ u32 notUsed0; /* Available for future enhancements */ }; #define READMARK_NOT_USED 0xffffffff /* A block of WALINDEX_LOCK_RESERVED bytes beginning at ** WALINDEX_LOCK_OFFSET is reserved for locks. Since some systems ** only support mandatory file-locks, we do not read or write data ** from the region of the file on which locks are applied. */ #define WALINDEX_LOCK_OFFSET (sizeof(WalIndexHdr)*2+offsetof(WalCkptInfo,aLock)) | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 60543 60544 60545 60546 60547 60548 60549 60550 60551 60552 60553 60554 60555 60556 60557 60558 60559 60560 60561 60562 60563 60564 60565 60566 60567 60568 60569 60570 60571 60572 60573 60574 60575 60576 60577 60578 60579 60580 60581 60582 60583 60584 60585 60586 60587 60588 60589 60590 60591 60592 60593 60594 60595 60596 60597 60598 60599 60600 60601 60602 60603 60604 60605 60606 60607 60608 60609 60610 60611 60612 60613 60614 60615 60616 60617 60618 60619 60620 | u32 aReadMark[WAL_NREADER]; /* Reader marks */ u8 aLock[SQLITE_SHM_NLOCK]; /* Reserved space for locks */ u32 nBackfillAttempted; /* WAL frames perhaps written, or maybe not */ u32 notUsed0; /* Available for future enhancements */ }; #define READMARK_NOT_USED 0xffffffff /* ** This is a schematic view of the complete 136-byte header of the ** wal-index file (also known as the -shm file): ** ** +-----------------------------+ ** 0: | iVersion | \ ** +-----------------------------+ | ** 4: | (unused padding) | | ** +-----------------------------+ | ** 8: | iChange | | ** +-------+-------+-------------+ | ** 12: | bInit | bBig | szPage | | ** +-------+-------+-------------+ | ** 16: | mxFrame | | First copy of the ** +-----------------------------+ | WalIndexHdr object ** 20: | nPage | | ** +-----------------------------+ | ** 24: | aFrameCksum | | ** | | | ** +-----------------------------+ | ** 32: | aSalt | | ** | | | ** +-----------------------------+ | ** 40: | aCksum | | ** | | / ** +-----------------------------+ ** 48: | iVersion | \ ** +-----------------------------+ | ** 52: | (unused padding) | | ** +-----------------------------+ | ** 56: | iChange | | ** +-------+-------+-------------+ | ** 60: | bInit | bBig | szPage | | ** +-------+-------+-------------+ | Second copy of the ** 64: | mxFrame | | WalIndexHdr ** +-----------------------------+ | ** 68: | nPage | | ** +-----------------------------+ | ** 72: | aFrameCksum | | ** | | | ** +-----------------------------+ | ** 80: | aSalt | | ** | | | ** +-----------------------------+ | ** 88: | aCksum | | ** | | / ** +-----------------------------+ ** 96: | nBackfill | ** +-----------------------------+ ** 100: | 5 read marks | ** | | ** | | ** | | ** | | ** +-------+-------+------+------+ ** 120: | Write | Ckpt | Rcvr | Rd0 | \ ** +-------+-------+------+------+ ) 8 lock bytes ** | Read1 | Read2 | Rd3 | Rd4 | / ** +-------+-------+------+------+ ** 128: | nBackfillAttempted | ** +-----------------------------+ ** 132: | (unused padding) | ** +-----------------------------+ */ /* A block of WALINDEX_LOCK_RESERVED bytes beginning at ** WALINDEX_LOCK_OFFSET is reserved for locks. Since some systems ** only support mandatory file-locks, we do not read or write data ** from the region of the file on which locks are applied. */ #define WALINDEX_LOCK_OFFSET (sizeof(WalIndexHdr)*2+offsetof(WalCkptInfo,aLock)) |
︙ | ︙ | |||
61750 61751 61752 61753 61754 61755 61756 61757 61758 61759 61760 61761 61762 61763 | ){ int rc; /* Return Code */ Wal *pRet; /* Object to allocate and return */ int flags; /* Flags passed to OsOpen() */ assert( zWalName && zWalName[0] ); assert( pDbFd ); /* In the amalgamation, the os_unix.c and os_win.c source files come before ** this source file. Verify that the #defines of the locking byte offsets ** in os_unix.c and os_win.c agree with the WALINDEX_LOCK_OFFSET value. ** For that matter, if the lock offset ever changes from its initial design ** value of 120, we need to know that so there is an assert() to check it. */ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < < | 61619 61620 61621 61622 61623 61624 61625 61626 61627 61628 61629 61630 61631 61632 61633 61634 61635 61636 61637 61638 61639 61640 61641 61642 61643 61644 61645 61646 61647 61648 61649 61650 61651 61652 61653 61654 61655 61656 61657 61658 61659 61660 61661 61662 61663 61664 61665 61666 61667 61668 61669 61670 | ){ int rc; /* Return Code */ Wal *pRet; /* Object to allocate and return */ int flags; /* Flags passed to OsOpen() */ assert( zWalName && zWalName[0] ); assert( pDbFd ); /* Verify the values of various constants. Any changes to the values ** of these constants would result in an incompatible on-disk format ** for the -shm file. Any change that causes one of these asserts to ** fail is a backward compatibility problem, even if the change otherwise ** works. ** ** This table also serves as a helpful cross-reference when trying to ** interpret hex dumps of the -shm file. */ assert( 48 == sizeof(WalIndexHdr) ); assert( 40 == sizeof(WalCkptInfo) ); assert( 120 == WALINDEX_LOCK_OFFSET ); assert( 136 == WALINDEX_HDR_SIZE ); assert( 4096 == HASHTABLE_NPAGE ); assert( 4062 == HASHTABLE_NPAGE_ONE ); assert( 8192 == HASHTABLE_NSLOT ); assert( 383 == HASHTABLE_HASH_1 ); assert( 32768 == WALINDEX_PGSZ ); assert( 8 == SQLITE_SHM_NLOCK ); assert( 5 == WAL_NREADER ); assert( 24 == WAL_FRAME_HDRSIZE ); assert( 32 == WAL_HDRSIZE ); assert( 120 == WALINDEX_LOCK_OFFSET + WAL_WRITE_LOCK ); assert( 121 == WALINDEX_LOCK_OFFSET + WAL_CKPT_LOCK ); assert( 122 == WALINDEX_LOCK_OFFSET + WAL_RECOVER_LOCK ); assert( 123 == WALINDEX_LOCK_OFFSET + WAL_READ_LOCK(0) ); assert( 124 == WALINDEX_LOCK_OFFSET + WAL_READ_LOCK(1) ); assert( 125 == WALINDEX_LOCK_OFFSET + WAL_READ_LOCK(2) ); assert( 126 == WALINDEX_LOCK_OFFSET + WAL_READ_LOCK(3) ); assert( 127 == WALINDEX_LOCK_OFFSET + WAL_READ_LOCK(4) ); /* In the amalgamation, the os_unix.c and os_win.c source files come before ** this source file. Verify that the #defines of the locking byte offsets ** in os_unix.c and os_win.c agree with the WALINDEX_LOCK_OFFSET value. ** For that matter, if the lock offset ever changes from its initial design ** value of 120, we need to know that so there is an assert() to check it. */ #ifdef WIN_SHM_BASE assert( WIN_SHM_BASE==WALINDEX_LOCK_OFFSET ); #endif #ifdef UNIX_SHM_BASE assert( UNIX_SHM_BASE==WALINDEX_LOCK_OFFSET ); #endif |
︙ | ︙ | |||
66265 66266 66267 66268 66269 66270 66271 | KeyInfo *pKeyInfo = pCur->pKeyInfo; assert( nKey==(i64)(int)nKey ); pIdxKey = sqlite3VdbeAllocUnpackedRecord(pKeyInfo); if( pIdxKey==0 ) return SQLITE_NOMEM_BKPT; sqlite3VdbeRecordUnpack(pKeyInfo, (int)nKey, pKey, pIdxKey); if( pIdxKey->nField==0 || pIdxKey->nField>pKeyInfo->nAllField ){ rc = SQLITE_CORRUPT_BKPT; | > | > < | < < < | 66163 66164 66165 66166 66167 66168 66169 66170 66171 66172 66173 66174 66175 66176 66177 66178 66179 66180 66181 66182 66183 | KeyInfo *pKeyInfo = pCur->pKeyInfo; assert( nKey==(i64)(int)nKey ); pIdxKey = sqlite3VdbeAllocUnpackedRecord(pKeyInfo); if( pIdxKey==0 ) return SQLITE_NOMEM_BKPT; sqlite3VdbeRecordUnpack(pKeyInfo, (int)nKey, pKey, pIdxKey); if( pIdxKey->nField==0 || pIdxKey->nField>pKeyInfo->nAllField ){ rc = SQLITE_CORRUPT_BKPT; }else{ rc = sqlite3BtreeIndexMoveto(pCur, pIdxKey, pRes); } sqlite3DbFree(pCur->pKeyInfo->db, pIdxKey); }else{ pIdxKey = 0; rc = sqlite3BtreeTableMoveto(pCur, nKey, bias, pRes); } return rc; } /* ** Restore the cursor to the position it was in (or as close to as possible) ** when saveCursorPosition() was called. Note that this call deletes the |
︙ | ︙ | |||
67122 67123 67124 67125 67126 67127 67128 | testcase( gap==top ); if( (data[hdr+2] || data[hdr+1]) && gap+2<=top ){ u8 *pSpace = pageFindSlot(pPage, nByte, &rc); if( pSpace ){ int g2; assert( pSpace+nByte<=data+pPage->pBt->usableSize ); *pIdx = g2 = (int)(pSpace-data); | | | 67018 67019 67020 67021 67022 67023 67024 67025 67026 67027 67028 67029 67030 67031 67032 | testcase( gap==top ); if( (data[hdr+2] || data[hdr+1]) && gap+2<=top ){ u8 *pSpace = pageFindSlot(pPage, nByte, &rc); if( pSpace ){ int g2; assert( pSpace+nByte<=data+pPage->pBt->usableSize ); *pIdx = g2 = (int)(pSpace-data); if( g2<=gap ){ return SQLITE_CORRUPT_PAGE(pPage); }else{ return SQLITE_OK; } }else if( rc ){ return rc; } |
︙ | ︙ | |||
70859 70860 70861 70862 70863 70864 70865 | assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 ); *pRes = 1; rc = SQLITE_OK; } return rc; } | | | < < < < | | | < < < | < < | | < | < | 70755 70756 70757 70758 70759 70760 70761 70762 70763 70764 70765 70766 70767 70768 70769 70770 70771 70772 70773 70774 70775 70776 70777 70778 70779 70780 70781 70782 70783 70784 70785 70786 70787 70788 70789 70790 70791 70792 70793 70794 70795 70796 70797 70798 70799 70800 70801 70802 70803 70804 70805 70806 70807 70808 | assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 ); *pRes = 1; rc = SQLITE_OK; } return rc; } /* Move the cursor so that it points to an entry in a table (a.k.a INTKEY) ** table near the key intKey. Return a success code. ** ** If an exact match is not found, then the cursor is always ** left pointing at a leaf page which would hold the entry if it ** were present. The cursor might point to an entry that comes ** before or after the key. ** ** An integer is written into *pRes which is the result of ** comparing the key with the entry to which the cursor is ** pointing. The meaning of the integer written into ** *pRes is as follows: ** ** *pRes<0 The cursor is left pointing at an entry that ** is smaller than intKey or if the table is empty ** and the cursor is therefore left point to nothing. ** ** *pRes==0 The cursor is left pointing at an entry that ** exactly matches intKey. ** ** *pRes>0 The cursor is left pointing at an entry that ** is larger than intKey. */ SQLITE_PRIVATE int sqlite3BtreeTableMoveto( BtCursor *pCur, /* The cursor to be moved */ i64 intKey, /* The table key */ int biasRight, /* If true, bias the search to the high end */ int *pRes /* Write search results here */ ){ int rc; assert( cursorOwnsBtShared(pCur) ); assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); assert( pRes ); assert( pCur->pKeyInfo==0 ); assert( pCur->eState!=CURSOR_VALID || pCur->curIntKey!=0 ); /* If the cursor is already positioned at the point we are trying ** to move to, then just return without doing any work */ if( pCur->eState==CURSOR_VALID && (pCur->curFlags & BTCF_ValidNKey)!=0 ){ if( pCur->info.nKey==intKey ){ *pRes = 0; return SQLITE_OK; } if( pCur->info.nKey<intKey ){ if( (pCur->curFlags & BTCF_AtLast)!=0 ){ *pRes = -1; |
︙ | ︙ | |||
70944 70945 70946 70947 70948 70949 70950 | } } #ifdef SQLITE_DEBUG pCur->pBtree->nSeek++; /* Performance measurement during testing */ #endif | > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | | | | < < < | 70829 70830 70831 70832 70833 70834 70835 70836 70837 70838 70839 70840 70841 70842 70843 70844 70845 70846 70847 70848 70849 70850 70851 70852 70853 70854 70855 70856 70857 70858 70859 70860 70861 70862 70863 70864 70865 70866 70867 70868 70869 70870 70871 70872 70873 70874 70875 70876 70877 70878 70879 70880 70881 70882 70883 70884 70885 70886 70887 70888 70889 70890 70891 70892 70893 70894 70895 70896 70897 70898 70899 70900 70901 70902 70903 70904 70905 70906 70907 70908 70909 70910 70911 70912 70913 70914 70915 70916 70917 70918 70919 70920 70921 70922 70923 70924 70925 70926 70927 70928 70929 70930 70931 70932 70933 70934 70935 70936 70937 70938 70939 70940 70941 70942 70943 70944 70945 70946 70947 70948 70949 70950 70951 70952 70953 70954 70955 70956 70957 70958 70959 70960 70961 70962 70963 70964 70965 70966 70967 70968 70969 70970 70971 70972 70973 70974 70975 70976 70977 70978 70979 70980 70981 70982 70983 70984 70985 | } } #ifdef SQLITE_DEBUG pCur->pBtree->nSeek++; /* Performance measurement during testing */ #endif rc = moveToRoot(pCur); if( rc ){ if( rc==SQLITE_EMPTY ){ assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 ); *pRes = -1; return SQLITE_OK; } return rc; } assert( pCur->pPage ); assert( pCur->pPage->isInit ); assert( pCur->eState==CURSOR_VALID ); assert( pCur->pPage->nCell > 0 ); assert( pCur->iPage==0 || pCur->apPage[0]->intKey==pCur->curIntKey ); assert( pCur->curIntKey ); for(;;){ int lwr, upr, idx, c; Pgno chldPg; MemPage *pPage = pCur->pPage; u8 *pCell; /* Pointer to current cell in pPage */ /* pPage->nCell must be greater than zero. If this is the root-page ** the cursor would have been INVALID above and this for(;;) loop ** not run. If this is not the root-page, then the moveToChild() routine ** would have already detected db corruption. Similarly, pPage must ** be the right kind (index or table) of b-tree page. Otherwise ** a moveToChild() or moveToRoot() call would have detected corruption. */ assert( pPage->nCell>0 ); assert( pPage->intKey ); lwr = 0; upr = pPage->nCell-1; assert( biasRight==0 || biasRight==1 ); idx = upr>>(1-biasRight); /* idx = biasRight ? upr : (lwr+upr)/2; */ pCur->ix = (u16)idx; for(;;){ i64 nCellKey; pCell = findCellPastPtr(pPage, idx); if( pPage->intKeyLeaf ){ while( 0x80 <= *(pCell++) ){ if( pCell>=pPage->aDataEnd ){ return SQLITE_CORRUPT_PAGE(pPage); } } } getVarint(pCell, (u64*)&nCellKey); if( nCellKey<intKey ){ lwr = idx+1; if( lwr>upr ){ c = -1; break; } }else if( nCellKey>intKey ){ upr = idx-1; if( lwr>upr ){ c = +1; break; } }else{ assert( nCellKey==intKey ); pCur->ix = (u16)idx; if( !pPage->leaf ){ lwr = idx; goto moveto_table_next_layer; }else{ pCur->curFlags |= BTCF_ValidNKey; pCur->info.nKey = nCellKey; pCur->info.nSize = 0; *pRes = 0; return SQLITE_OK; } } assert( lwr+upr>=0 ); idx = (lwr+upr)>>1; /* idx = (lwr+upr)/2; */ } assert( lwr==upr+1 || !pPage->leaf ); assert( pPage->isInit ); if( pPage->leaf ){ assert( pCur->ix<pCur->pPage->nCell ); pCur->ix = (u16)idx; *pRes = c; rc = SQLITE_OK; goto moveto_table_finish; } moveto_table_next_layer: if( lwr>=pPage->nCell ){ chldPg = get4byte(&pPage->aData[pPage->hdrOffset+8]); }else{ chldPg = get4byte(findCell(pPage, lwr)); } pCur->ix = (u16)lwr; rc = moveToChild(pCur, chldPg); if( rc ) break; } moveto_table_finish: pCur->info.nSize = 0; assert( (pCur->curFlags & BTCF_ValidOvfl)==0 ); return rc; } /* Move the cursor so that it points to an entry in an index table ** near the key pIdxKey. Return a success code. ** ** If an exact match is not found, then the cursor is always ** left pointing at a leaf page which would hold the entry if it ** were present. The cursor might point to an entry that comes ** before or after the key. ** ** An integer is written into *pRes which is the result of ** comparing the key with the entry to which the cursor is ** pointing. The meaning of the integer written into ** *pRes is as follows: ** ** *pRes<0 The cursor is left pointing at an entry that ** is smaller than pIdxKey or if the table is empty ** and the cursor is therefore left point to nothing. ** ** *pRes==0 The cursor is left pointing at an entry that ** exactly matches pIdxKey. ** ** *pRes>0 The cursor is left pointing at an entry that ** is larger than pIdxKey. ** ** The pIdxKey->eqSeen field is set to 1 if there ** exists an entry in the table that exactly matches pIdxKey. */ SQLITE_PRIVATE int sqlite3BtreeIndexMoveto( BtCursor *pCur, /* The cursor to be moved */ UnpackedRecord *pIdxKey, /* Unpacked index key */ int *pRes /* Write search results here */ ){ int rc; RecordCompare xRecordCompare; assert( cursorOwnsBtShared(pCur) ); assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); assert( pRes ); assert( pCur->pKeyInfo!=0 ); #ifdef SQLITE_DEBUG pCur->pBtree->nSeek++; /* Performance measurement during testing */ #endif xRecordCompare = sqlite3VdbeFindCompare(pIdxKey); pIdxKey->errCode = 0; assert( pIdxKey->default_rc==1 || pIdxKey->default_rc==0 || pIdxKey->default_rc==-1 ); rc = moveToRoot(pCur); if( rc ){ if( rc==SQLITE_EMPTY ){ assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 ); *pRes = -1; return SQLITE_OK; |
︙ | ︙ | |||
70986 70987 70988 70989 70990 70991 70992 | ** would have already detected db corruption. Similarly, pPage must ** be the right kind (index or table) of b-tree page. Otherwise ** a moveToChild() or moveToRoot() call would have detected corruption. */ assert( pPage->nCell>0 ); assert( pPage->intKey==(pIdxKey==0) ); lwr = 0; upr = pPage->nCell-1; | < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < | < | | 71004 71005 71006 71007 71008 71009 71010 71011 71012 71013 71014 71015 71016 71017 71018 71019 71020 71021 71022 71023 71024 71025 71026 71027 71028 71029 71030 71031 71032 71033 71034 71035 71036 71037 71038 71039 71040 71041 71042 71043 71044 71045 71046 71047 71048 71049 71050 71051 71052 71053 71054 71055 71056 71057 71058 71059 71060 71061 71062 71063 71064 71065 71066 71067 71068 71069 71070 71071 71072 71073 71074 71075 71076 71077 71078 71079 71080 71081 71082 71083 71084 71085 71086 71087 71088 71089 71090 71091 71092 71093 71094 71095 71096 71097 71098 71099 71100 71101 71102 71103 71104 71105 71106 71107 71108 71109 71110 71111 71112 71113 71114 71115 71116 71117 71118 71119 71120 71121 71122 71123 | ** would have already detected db corruption. Similarly, pPage must ** be the right kind (index or table) of b-tree page. Otherwise ** a moveToChild() or moveToRoot() call would have detected corruption. */ assert( pPage->nCell>0 ); assert( pPage->intKey==(pIdxKey==0) ); lwr = 0; upr = pPage->nCell-1; idx = upr>>1; /* idx = (lwr+upr)/2; */ pCur->ix = (u16)idx; for(;;){ int nCell; /* Size of the pCell cell in bytes */ pCell = findCellPastPtr(pPage, idx); /* The maximum supported page-size is 65536 bytes. This means that ** the maximum number of record bytes stored on an index B-Tree ** page is less than 16384 bytes and may be stored as a 2-byte ** varint. This information is used to attempt to avoid parsing ** the entire cell by checking for the cases where the record is ** stored entirely within the b-tree page by inspecting the first ** 2 bytes of the cell. */ nCell = pCell[0]; if( nCell<=pPage->max1bytePayload ){ /* This branch runs if the record-size field of the cell is a ** single byte varint and the record fits entirely on the main ** b-tree page. */ testcase( pCell+nCell+1==pPage->aDataEnd ); c = xRecordCompare(nCell, (void*)&pCell[1], pIdxKey); }else if( !(pCell[1] & 0x80) && (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal ){ /* The record-size field is a 2 byte varint and the record ** fits entirely on the main b-tree page. */ testcase( pCell+nCell+2==pPage->aDataEnd ); c = xRecordCompare(nCell, (void*)&pCell[2], pIdxKey); }else{ /* The record flows over onto one or more overflow pages. In ** this case the whole cell needs to be parsed, a buffer allocated ** and accessPayload() used to retrieve the record into the ** buffer before VdbeRecordCompare() can be called. ** ** If the record is corrupt, the xRecordCompare routine may read ** up to two varints past the end of the buffer. An extra 18 ** bytes of padding is allocated at the end of the buffer in ** case this happens. */ void *pCellKey; u8 * const pCellBody = pCell - pPage->childPtrSize; const int nOverrun = 18; /* Size of the overrun padding */ pPage->xParseCell(pPage, pCellBody, &pCur->info); nCell = (int)pCur->info.nKey; testcase( nCell<0 ); /* True if key size is 2^32 or more */ testcase( nCell==0 ); /* Invalid key size: 0x80 0x80 0x00 */ testcase( nCell==1 ); /* Invalid key size: 0x80 0x80 0x01 */ testcase( nCell==2 ); /* Minimum legal index key size */ if( nCell<2 || nCell/pCur->pBt->usableSize>pCur->pBt->nPage ){ rc = SQLITE_CORRUPT_PAGE(pPage); goto moveto_index_finish; } pCellKey = sqlite3Malloc( nCell+nOverrun ); if( pCellKey==0 ){ rc = SQLITE_NOMEM_BKPT; goto moveto_index_finish; } pCur->ix = (u16)idx; rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 0); memset(((u8*)pCellKey)+nCell,0,nOverrun); /* Fix uninit warnings */ pCur->curFlags &= ~BTCF_ValidOvfl; if( rc ){ sqlite3_free(pCellKey); goto moveto_index_finish; } c = sqlite3VdbeRecordCompare(nCell, pCellKey, pIdxKey); sqlite3_free(pCellKey); } assert( (pIdxKey->errCode!=SQLITE_CORRUPT || c==0) && (pIdxKey->errCode!=SQLITE_NOMEM || pCur->pBtree->db->mallocFailed) ); if( c<0 ){ lwr = idx+1; }else if( c>0 ){ upr = idx-1; }else{ assert( c==0 ); *pRes = 0; rc = SQLITE_OK; pCur->ix = (u16)idx; if( pIdxKey->errCode ) rc = SQLITE_CORRUPT_BKPT; goto moveto_index_finish; } if( lwr>upr ) break; assert( lwr+upr>=0 ); idx = (lwr+upr)>>1; /* idx = (lwr+upr)/2 */ } assert( lwr==upr+1 || (pPage->intKey && !pPage->leaf) ); assert( pPage->isInit ); if( pPage->leaf ){ assert( pCur->ix<pCur->pPage->nCell ); pCur->ix = (u16)idx; *pRes = c; rc = SQLITE_OK; goto moveto_index_finish; } if( lwr>=pPage->nCell ){ chldPg = get4byte(&pPage->aData[pPage->hdrOffset+8]); }else{ chldPg = get4byte(findCell(pPage, lwr)); } pCur->ix = (u16)lwr; rc = moveToChild(pCur, chldPg); if( rc ) break; } moveto_index_finish: pCur->info.nSize = 0; assert( (pCur->curFlags & BTCF_ValidOvfl)==0 ); return rc; } /* |
︙ | ︙ | |||
73114 73115 73116 73117 73118 73119 73120 73121 73122 73123 73124 73125 73126 73127 | if( apOld[i]->nFree<0 ){ rc = btreeComputeFreeSpace(apOld[i]); if( rc ){ memset(apOld, 0, (i)*sizeof(MemPage*)); goto balance_cleanup; } } if( (i--)==0 ) break; if( pParent->nOverflow && i+nxDiv==pParent->aiOvfl[0] ){ apDiv[i] = pParent->apOvfl[0]; pgno = get4byte(apDiv[i]); szNew[i] = pParent->xCellSize(pParent, apDiv[i]); pParent->nOverflow = 0; | > | 73093 73094 73095 73096 73097 73098 73099 73100 73101 73102 73103 73104 73105 73106 73107 | if( apOld[i]->nFree<0 ){ rc = btreeComputeFreeSpace(apOld[i]); if( rc ){ memset(apOld, 0, (i)*sizeof(MemPage*)); goto balance_cleanup; } } nMaxCells += apOld[i]->nCell + ArraySize(pParent->apOvfl); if( (i--)==0 ) break; if( pParent->nOverflow && i+nxDiv==pParent->aiOvfl[0] ){ apDiv[i] = pParent->apOvfl[0]; pgno = get4byte(apDiv[i]); szNew[i] = pParent->xCellSize(pParent, apDiv[i]); pParent->nOverflow = 0; |
︙ | ︙ | |||
73155 73156 73157 73158 73159 73160 73161 | } dropCell(pParent, i+nxDiv-pParent->nOverflow, szNew[i], &rc); } } /* Make nMaxCells a multiple of 4 in order to preserve 8-byte ** alignment */ | < | 73135 73136 73137 73138 73139 73140 73141 73142 73143 73144 73145 73146 73147 73148 | } dropCell(pParent, i+nxDiv-pParent->nOverflow, szNew[i], &rc); } } /* Make nMaxCells a multiple of 4 in order to preserve 8-byte ** alignment */ nMaxCells = (nMaxCells + 3)&~3; /* ** Allocate space for memory structures */ szScratch = nMaxCells*sizeof(u8*) /* b.apCell */ |
︙ | ︙ | |||
73438 73439 73440 73441 73442 73443 73444 | for(i=0; i<k; i++){ MemPage *pNew; if( i<nOld ){ pNew = apNew[i] = apOld[i]; apOld[i] = 0; rc = sqlite3PagerWrite(pNew->pDbPage); nNew++; | | > > | 73417 73418 73419 73420 73421 73422 73423 73424 73425 73426 73427 73428 73429 73430 73431 73432 73433 | for(i=0; i<k; i++){ MemPage *pNew; if( i<nOld ){ pNew = apNew[i] = apOld[i]; apOld[i] = 0; rc = sqlite3PagerWrite(pNew->pDbPage); nNew++; if( sqlite3PagerPageRefcount(pNew->pDbPage)!=1+(i==(iParentIdx-nxDiv)) && rc==SQLITE_OK ){ rc = SQLITE_CORRUPT_BKPT; } if( rc ) goto balance_cleanup; }else{ assert( i>0 ); rc = allocateBtreePage(pBt, &pNew, &pgno, (bBulk ? 1 : pgno), 0); if( rc ) goto balance_cleanup; |
︙ | ︙ | |||
74236 74237 74238 74239 74240 74241 74242 | } assert( loc==0 ); }else if( loc==0 ){ /* The cursor is *not* pointing to the cell to be overwritten, nor ** to an adjacent cell. Move the cursor so that it is pointing either ** to the cell to be overwritten or an adjacent cell. */ | | > | 74217 74218 74219 74220 74221 74222 74223 74224 74225 74226 74227 74228 74229 74230 74231 74232 | } assert( loc==0 ); }else if( loc==0 ){ /* The cursor is *not* pointing to the cell to be overwritten, nor ** to an adjacent cell. Move the cursor so that it is pointing either ** to the cell to be overwritten or an adjacent cell. */ rc = sqlite3BtreeTableMoveto(pCur, pX->nKey, (flags & BTREE_APPEND)!=0, &loc); if( rc ) return rc; } }else{ /* This is an index or a WITHOUT ROWID table */ /* If BTREE_SAVEPOSITION is set, the cursor must already be pointing ** to a row with the same key as the new entry being inserted. |
︙ | ︙ | |||
74259 74260 74261 74262 74263 74264 74265 | if( loc==0 && (flags & BTREE_SAVEPOSITION)==0 ){ if( pX->nMem ){ UnpackedRecord r; r.pKeyInfo = pCur->pKeyInfo; r.aMem = pX->aMem; r.nField = pX->nMem; r.default_rc = 0; | < < < | | > | 74241 74242 74243 74244 74245 74246 74247 74248 74249 74250 74251 74252 74253 74254 74255 74256 74257 74258 74259 | if( loc==0 && (flags & BTREE_SAVEPOSITION)==0 ){ if( pX->nMem ){ UnpackedRecord r; r.pKeyInfo = pCur->pKeyInfo; r.aMem = pX->aMem; r.nField = pX->nMem; r.default_rc = 0; r.eqSeen = 0; rc = sqlite3BtreeIndexMoveto(pCur, &r, &loc); }else{ rc = btreeMoveto(pCur, pX->pKey, pX->nKey, (flags & BTREE_APPEND)!=0, &loc); } if( rc ) return rc; } /* If the cursor is currently pointing to an entry to be overwritten ** and the new content is the same as as the old, then use the ** overwrite optimization. |
︙ | ︙ | |||
74899 74900 74901 74902 74903 74904 74905 | ** Erase the given database page and all its children. Return ** the page to the freelist. */ static int clearDatabasePage( BtShared *pBt, /* The BTree that contains the table */ Pgno pgno, /* Page number to clear */ int freePageFlag, /* Deallocate page if true */ | | | 74879 74880 74881 74882 74883 74884 74885 74886 74887 74888 74889 74890 74891 74892 74893 | ** Erase the given database page and all its children. Return ** the page to the freelist. */ static int clearDatabasePage( BtShared *pBt, /* The BTree that contains the table */ Pgno pgno, /* Page number to clear */ int freePageFlag, /* Deallocate page if true */ i64 *pnChange /* Add number of Cells freed to this counter */ ){ MemPage *pPage; int rc; unsigned char *pCell; int i; int hdr; CellInfo info; |
︙ | ︙ | |||
74932 74933 74934 74935 74936 74937 74938 74939 74940 74941 74942 74943 74944 74945 | } BTREE_CLEAR_CELL(rc, pPage, pCell, info); if( rc ) goto cleardatabasepage_out; } if( !pPage->leaf ){ rc = clearDatabasePage(pBt, get4byte(&pPage->aData[hdr+8]), 1, pnChange); if( rc ) goto cleardatabasepage_out; } if( pnChange ){ testcase( !pPage->intKey ); *pnChange += pPage->nCell; } if( freePageFlag ){ freePage(pPage, &rc); | > | 74912 74913 74914 74915 74916 74917 74918 74919 74920 74921 74922 74923 74924 74925 74926 | } BTREE_CLEAR_CELL(rc, pPage, pCell, info); if( rc ) goto cleardatabasepage_out; } if( !pPage->leaf ){ rc = clearDatabasePage(pBt, get4byte(&pPage->aData[hdr+8]), 1, pnChange); if( rc ) goto cleardatabasepage_out; if( pPage->intKey ) pnChange = 0; } if( pnChange ){ testcase( !pPage->intKey ); *pnChange += pPage->nCell; } if( freePageFlag ){ freePage(pPage, &rc); |
︙ | ︙ | |||
74961 74962 74963 74964 74965 74966 74967 | ** This routine will fail with SQLITE_LOCKED if there are any open ** read cursors on the table. Open write cursors are moved to the ** root of the table. ** ** If pnChange is not NULL, then the integer value pointed to by pnChange ** is incremented by the number of entries in the table. */ | | | 74942 74943 74944 74945 74946 74947 74948 74949 74950 74951 74952 74953 74954 74955 74956 | ** This routine will fail with SQLITE_LOCKED if there are any open ** read cursors on the table. Open write cursors are moved to the ** root of the table. ** ** If pnChange is not NULL, then the integer value pointed to by pnChange ** is incremented by the number of entries in the table. */ SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree *p, int iTable, i64 *pnChange){ int rc; BtShared *pBt = p->pBt; sqlite3BtreeEnter(p); assert( p->inTrans==TRANS_WRITE ); rc = saveAllCursors(pBt, (Pgno)iTable, 0); |
︙ | ︙ | |||
80555 80556 80557 80558 80559 80560 80561 | displayP4Expr(&x, pOp->p4.pExpr); break; } #endif case P4_COLLSEQ: { static const char *const encnames[] = {"?", "8", "16LE", "16BE"}; CollSeq *pColl = pOp->p4.pColl; | | | 80536 80537 80538 80539 80540 80541 80542 80543 80544 80545 80546 80547 80548 80549 80550 | displayP4Expr(&x, pOp->p4.pExpr); break; } #endif case P4_COLLSEQ: { static const char *const encnames[] = {"?", "8", "16LE", "16BE"}; CollSeq *pColl = pOp->p4.pColl; assert( pColl->enc<4 ); sqlite3_str_appendf(&x, "%.18s-%s", pColl->zName, encnames[pColl->enc]); break; } case P4_FUNCDEF: { FuncDef *pDef = pOp->p4.pFunc; sqlite3_str_appendf(&x, "%s(%d)", pDef->zName, pDef->nArg); |
︙ | ︙ | |||
82396 82397 82398 82399 82400 82401 82402 | int res, rc; #ifdef SQLITE_TEST extern int sqlite3_search_count; #endif assert( p->deferredMoveto ); assert( p->isTable ); assert( p->eCurType==CURTYPE_BTREE ); | | | 82377 82378 82379 82380 82381 82382 82383 82384 82385 82386 82387 82388 82389 82390 82391 | int res, rc; #ifdef SQLITE_TEST extern int sqlite3_search_count; #endif assert( p->deferredMoveto ); assert( p->isTable ); assert( p->eCurType==CURTYPE_BTREE ); rc = sqlite3BtreeTableMoveto(p->uc.pCursor, p->movetoTarget, 0, &res); if( rc ) return rc; if( res!=0 ) return SQLITE_CORRUPT_BKPT; #ifdef SQLITE_TEST sqlite3_search_count++; #endif p->deferredMoveto = 0; p->cacheStatus = CACHE_STALE; |
︙ | ︙ | |||
83180 83181 83182 83183 83184 83185 83186 | } /* ** Do a comparison between a 64-bit signed integer and a 64-bit floating-point ** number. Return negative, zero, or positive if the first (i64) is less than, ** equal to, or greater than the second (double). */ | | | 83161 83162 83163 83164 83165 83166 83167 83168 83169 83170 83171 83172 83173 83174 83175 | } /* ** Do a comparison between a 64-bit signed integer and a 64-bit floating-point ** number. Return negative, zero, or positive if the first (i64) is less than, ** equal to, or greater than the second (double). */ SQLITE_PRIVATE int sqlite3IntFloatCompare(i64 i, double r){ if( sizeof(LONGDOUBLE_TYPE)>8 ){ LONGDOUBLE_TYPE x = (LONGDOUBLE_TYPE)i; testcase( x<r ); testcase( x>r ); testcase( x==r ); if( x<r ) return -1; if( x>r ) return +1; /*NO_TEST*/ /* work around bugs in gcov */ |
︙ | ︙ | |||
83904 83905 83906 83907 83908 83909 83910 | return SQLITE_OK; } /* ** This routine sets the value to be returned by subsequent calls to ** sqlite3_changes() on the database handle 'db'. */ | | | 83885 83886 83887 83888 83889 83890 83891 83892 83893 83894 83895 83896 83897 83898 83899 | return SQLITE_OK; } /* ** This routine sets the value to be returned by subsequent calls to ** sqlite3_changes() on the database handle 'db'. */ SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *db, i64 nChange){ assert( sqlite3_mutex_held(db->mutex) ); db->nChange = nChange; db->nTotalChange += nChange; } /* ** Set a flag in the vdbe to update the change counter when it is finalised |
︙ | ︙ | |||
87021 87022 87023 87024 87025 87026 87027 | #ifdef VDBE_PROFILE /* ** hwtime.h contains inline assembler code for implementing ** high-performance timing routines. */ | < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 87002 87003 87004 87005 87006 87007 87008 87009 87010 87011 87012 87013 87014 87015 87016 | #ifdef VDBE_PROFILE /* ** hwtime.h contains inline assembler code for implementing ** high-performance timing routines. */ /* #include "hwtime.h" */ #endif #ifndef NDEBUG /* ** This function is only called from within an assert() expression. It ** checks that the sqlite3.nTransaction variable is correctly set to |
︙ | ︙ | |||
90272 90273 90274 90275 90276 90277 90278 90279 90280 90281 90282 90283 90284 90285 | Db *pDb; assert( pOp->p5==0 || pOp->p5==OPFLAG_SEEKEQ ); assert( pOp->p4type==P4_KEYINFO ); pCur = p->apCsr[pOp->p1]; if( pCur && pCur->pgnoRoot==(u32)pOp->p2 ){ assert( pCur->iDb==pOp->p3 ); /* Guaranteed by the code generator */ goto open_cursor_set_hints; } /* If the cursor is not currently open or is open on a different ** index, then fall through into OP_OpenRead to force a reopen */ case OP_OpenRead: case OP_OpenWrite: | > > | 90164 90165 90166 90167 90168 90169 90170 90171 90172 90173 90174 90175 90176 90177 90178 90179 | Db *pDb; assert( pOp->p5==0 || pOp->p5==OPFLAG_SEEKEQ ); assert( pOp->p4type==P4_KEYINFO ); pCur = p->apCsr[pOp->p1]; if( pCur && pCur->pgnoRoot==(u32)pOp->p2 ){ assert( pCur->iDb==pOp->p3 ); /* Guaranteed by the code generator */ assert( pCur->eCurType==CURTYPE_BTREE ); sqlite3BtreeClearCursor(pCur->uc.pCursor); goto open_cursor_set_hints; } /* If the cursor is not currently open or is open on a different ** index, then fall through into OP_OpenRead to force a reopen */ case OP_OpenRead: case OP_OpenWrite: |
︙ | ︙ | |||
90759 90760 90761 90762 90763 90764 90765 90766 90767 90768 90769 90770 90771 90772 90773 90774 | iKey = sqlite3VdbeIntValue(pIn3); /* Get the integer key value */ newType = pIn3->flags; /* Record the type after applying numeric affinity */ pIn3->flags = flags3; /* But convert the type back to its original */ /* If the P3 value could not be converted into an integer without ** loss of information, then special processing is required... */ if( (newType & (MEM_Int|MEM_IntReal))==0 ){ if( (newType & MEM_Real)==0 ){ if( (newType & MEM_Null) || oc>=OP_SeekGE ){ VdbeBranchTaken(1,2); goto jump_to_p2; }else{ rc = sqlite3BtreeLast(pC->uc.pCursor, &res); if( rc!=SQLITE_OK ) goto abort_due_to_error; goto seek_not_found; } | > < > > | | | | 90653 90654 90655 90656 90657 90658 90659 90660 90661 90662 90663 90664 90665 90666 90667 90668 90669 90670 90671 90672 90673 90674 90675 90676 90677 90678 90679 90680 90681 90682 90683 90684 90685 90686 90687 90688 90689 90690 90691 90692 90693 90694 90695 90696 90697 90698 90699 90700 90701 90702 90703 | iKey = sqlite3VdbeIntValue(pIn3); /* Get the integer key value */ newType = pIn3->flags; /* Record the type after applying numeric affinity */ pIn3->flags = flags3; /* But convert the type back to its original */ /* If the P3 value could not be converted into an integer without ** loss of information, then special processing is required... */ if( (newType & (MEM_Int|MEM_IntReal))==0 ){ int c; if( (newType & MEM_Real)==0 ){ if( (newType & MEM_Null) || oc>=OP_SeekGE ){ VdbeBranchTaken(1,2); goto jump_to_p2; }else{ rc = sqlite3BtreeLast(pC->uc.pCursor, &res); if( rc!=SQLITE_OK ) goto abort_due_to_error; goto seek_not_found; } } c = sqlite3IntFloatCompare(iKey, pIn3->u.r); /* If the approximation iKey is larger than the actual real search ** term, substitute >= for > and < for <=. e.g. if the search term ** is 4.9 and the integer approximation 5: ** ** (x > 4.9) -> (x >= 5) ** (x <= 4.9) -> (x < 5) */ if( c>0 ){ assert( OP_SeekGE==(OP_SeekGT-1) ); assert( OP_SeekLT==(OP_SeekLE-1) ); assert( (OP_SeekLE & 0x0001)==(OP_SeekGT & 0x0001) ); if( (oc & 0x0001)==(OP_SeekGT & 0x0001) ) oc--; } /* If the approximation iKey is smaller than the actual real search ** term, substitute <= for < and > for >=. */ else if( c<0 ){ assert( OP_SeekLE==(OP_SeekLT+1) ); assert( OP_SeekGT==(OP_SeekGE+1) ); assert( (OP_SeekLT & 0x0001)==(OP_SeekGE & 0x0001) ); if( (oc & 0x0001)==(OP_SeekLT & 0x0001) ) oc++; } } rc = sqlite3BtreeTableMoveto(pC->uc.pCursor, (u64)iKey, 0, &res); pC->movetoTarget = iKey; /* Used by OP_Delete */ if( rc!=SQLITE_OK ){ goto abort_due_to_error; } }else{ /* For a cursor with the OPFLAG_SEEKEQ/BTREE_SEEK_EQ hint, only the ** OP_SeekGE and OP_SeekLE opcodes are allowed, and these must be |
︙ | ︙ | |||
90840 90841 90842 90843 90844 90845 90846 | assert( oc!=OP_SeekLT || r.default_rc==+1 ); r.aMem = &aMem[pOp->p3]; #ifdef SQLITE_DEBUG { int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); } #endif r.eqSeen = 0; | | | 90736 90737 90738 90739 90740 90741 90742 90743 90744 90745 90746 90747 90748 90749 90750 | assert( oc!=OP_SeekLT || r.default_rc==+1 ); r.aMem = &aMem[pOp->p3]; #ifdef SQLITE_DEBUG { int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); } #endif r.eqSeen = 0; rc = sqlite3BtreeIndexMoveto(pC->uc.pCursor, &r, &res); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } if( eqOnly && r.eqSeen==0 ){ assert( res!=0 ); goto seek_not_found; } |
︙ | ︙ | |||
91259 91260 91261 91262 91263 91264 91265 | for(ii=0; ii<pIdxKey->nField; ii++){ if( pIdxKey->aMem[ii].flags & MEM_Null ){ takeJump = 1; break; } } } | | | 91155 91156 91157 91158 91159 91160 91161 91162 91163 91164 91165 91166 91167 91168 91169 | for(ii=0; ii<pIdxKey->nField; ii++){ if( pIdxKey->aMem[ii].flags & MEM_Null ){ takeJump = 1; break; } } } rc = sqlite3BtreeIndexMoveto(pC->uc.pCursor, pIdxKey, &res); if( pFree ) sqlite3DbFreeNN(db, pFree); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } pC->seekResult = res; alreadyExists = (res==0); pC->nullRow = 1-alreadyExists; |
︙ | ︙ | |||
91368 91369 91370 91371 91372 91373 91374 | if( pOp->opcode==OP_SeekRowid ) pC->seekOp = OP_SeekRowid; #endif assert( pC->isTable ); assert( pC->eCurType==CURTYPE_BTREE ); pCrsr = pC->uc.pCursor; assert( pCrsr!=0 ); res = 0; | | | 91264 91265 91266 91267 91268 91269 91270 91271 91272 91273 91274 91275 91276 91277 91278 | if( pOp->opcode==OP_SeekRowid ) pC->seekOp = OP_SeekRowid; #endif assert( pC->isTable ); assert( pC->eCurType==CURTYPE_BTREE ); pCrsr = pC->uc.pCursor; assert( pCrsr!=0 ); res = 0; rc = sqlite3BtreeTableMoveto(pCrsr, iKey, 0, &res); assert( rc==SQLITE_OK || res==0 ); pC->movetoTarget = iKey; /* Used by OP_Delete */ pC->nullRow = 0; pC->cacheStatus = CACHE_STALE; pC->deferredMoveto = 0; VdbeBranchTaken(res!=0,2); pC->seekResult = res; |
︙ | ︙ | |||
91525 91526 91527 91528 91529 91530 91531 | ** it finds one that is not previously used. */ assert( pOp->p3==0 ); /* We cannot be in random rowid mode if this is ** an AUTOINCREMENT table. */ cnt = 0; do{ sqlite3_randomness(sizeof(v), &v); v &= (MAX_ROWID>>1); v++; /* Ensure that v is greater than zero */ | | | 91421 91422 91423 91424 91425 91426 91427 91428 91429 91430 91431 91432 91433 91434 91435 | ** it finds one that is not previously used. */ assert( pOp->p3==0 ); /* We cannot be in random rowid mode if this is ** an AUTOINCREMENT table. */ cnt = 0; do{ sqlite3_randomness(sizeof(v), &v); v &= (MAX_ROWID>>1); v++; /* Ensure that v is greater than zero */ }while( ((rc = sqlite3BtreeTableMoveto(pC->uc.pCursor, (u64)v, 0, &res))==SQLITE_OK) && (res==0) && (++cnt<100)); if( rc ) goto abort_due_to_error; if( res==0 ){ rc = SQLITE_FULL; /* IMP: R-38219-53002 */ goto abort_due_to_error; |
︙ | ︙ | |||
92423 92424 92425 92426 92427 92428 92429 | sqlite3VdbeIncrWriteCounter(p, pC); pCrsr = pC->uc.pCursor; assert( pCrsr!=0 ); r.pKeyInfo = pC->pKeyInfo; r.nField = (u16)pOp->p3; r.default_rc = 0; r.aMem = &aMem[pOp->p2]; | | | 92319 92320 92321 92322 92323 92324 92325 92326 92327 92328 92329 92330 92331 92332 92333 | sqlite3VdbeIncrWriteCounter(p, pC); pCrsr = pC->uc.pCursor; assert( pCrsr!=0 ); r.pKeyInfo = pC->pKeyInfo; r.nField = (u16)pOp->p3; r.default_rc = 0; r.aMem = &aMem[pOp->p2]; rc = sqlite3BtreeIndexMoveto(pCrsr, &r, &res); if( rc ) goto abort_due_to_error; if( res==0 ){ rc = sqlite3BtreeDelete(pCrsr, BTREE_AUXDELETE); if( rc ) goto abort_due_to_error; }else if( pOp->p5 ){ rc = sqlite3ReportError(SQLITE_CORRUPT_INDEX, __LINE__, "index corruption"); goto abort_due_to_error; |
︙ | ︙ | |||
92736 92737 92738 92739 92740 92741 92742 | ** by the number of rows in the table being cleared. If P3 is greater ** than zero, then the value stored in register P3 is also incremented ** by the number of rows in the table being cleared. ** ** See also: Destroy */ case OP_Clear: { | | | 92632 92633 92634 92635 92636 92637 92638 92639 92640 92641 92642 92643 92644 92645 92646 | ** by the number of rows in the table being cleared. If P3 is greater ** than zero, then the value stored in register P3 is also incremented ** by the number of rows in the table being cleared. ** ** See also: Destroy */ case OP_Clear: { i64 nChange; sqlite3VdbeIncrWriteCounter(p, 0); nChange = 0; assert( p->readOnly==0 ); assert( DbMaskTest(p->btreeMask, pOp->p2) ); rc = sqlite3BtreeClearTable(db->aDb[pOp->p2].pBt, (u32)pOp->p1, &nChange); if( pOp->p3 ){ |
︙ | ︙ | |||
94958 94959 94960 94961 94962 94963 94964 | sqlite3ErrorMsg(&sParse, "cannot open virtual table: %s", zTable); } if( pTab && !HasRowid(pTab) ){ pTab = 0; sqlite3ErrorMsg(&sParse, "cannot open table without rowid: %s", zTable); } #ifndef SQLITE_OMIT_VIEW | | | | 94854 94855 94856 94857 94858 94859 94860 94861 94862 94863 94864 94865 94866 94867 94868 94869 94870 94871 94872 94873 94874 94875 94876 94877 94878 94879 94880 94881 94882 94883 94884 94885 94886 94887 94888 | sqlite3ErrorMsg(&sParse, "cannot open virtual table: %s", zTable); } if( pTab && !HasRowid(pTab) ){ pTab = 0; sqlite3ErrorMsg(&sParse, "cannot open table without rowid: %s", zTable); } #ifndef SQLITE_OMIT_VIEW if( pTab && IsView(pTab) ){ pTab = 0; sqlite3ErrorMsg(&sParse, "cannot open view: %s", zTable); } #endif if( !pTab ){ if( sParse.zErrMsg ){ sqlite3DbFree(db, zErr); zErr = sParse.zErrMsg; sParse.zErrMsg = 0; } rc = SQLITE_ERROR; sqlite3BtreeLeaveAll(db); goto blob_open_out; } pBlob->pTab = pTab; pBlob->zDb = db->aDb[sqlite3SchemaToIndex(db, pTab->pSchema)].zDbSName; /* Now search pTab for the exact column. */ for(iCol=0; iCol<pTab->nCol; iCol++) { if( sqlite3StrICmp(pTab->aCol[iCol].zCnName, zColumn)==0 ){ break; } } if( iCol==pTab->nCol ){ sqlite3DbFree(db, zErr); zErr = sqlite3MPrintf(db, "no such column: \"%s\"", zColumn); rc = SQLITE_ERROR; |
︙ | ︙ | |||
95003 95004 95005 95006 95007 95008 95009 | #ifndef SQLITE_OMIT_FOREIGN_KEY if( db->flags&SQLITE_ForeignKeys ){ /* Check that the column is not part of an FK child key definition. It ** is not necessary to check if it is part of a parent key, as parent ** key columns must be indexed. The check below will pick up this ** case. */ FKey *pFKey; | > | | 94899 94900 94901 94902 94903 94904 94905 94906 94907 94908 94909 94910 94911 94912 94913 94914 | #ifndef SQLITE_OMIT_FOREIGN_KEY if( db->flags&SQLITE_ForeignKeys ){ /* Check that the column is not part of an FK child key definition. It ** is not necessary to check if it is part of a parent key, as parent ** key columns must be indexed. The check below will pick up this ** case. */ FKey *pFKey; assert( !IsVirtual(pTab) ); for(pFKey=pTab->u.tab.pFKey; pFKey; pFKey=pFKey->pNextFrom){ int j; for(j=0; j<pFKey->nCol; j++){ if( pFKey->aCol[j].iFrom==iCol ){ zFault = "foreign key"; } } } |
︙ | ︙ | |||
96376 96377 96378 96379 96380 96381 96382 | static void vdbeSorterWorkDebug(SortSubtask *pTask, const char *zEvent){ i64 t; int iTask = (pTask - pTask->pSorter->aTask); sqlite3OsCurrentTimeInt64(pTask->pSorter->db->pVfs, &t); fprintf(stderr, "%lld:%d %s\n", t, iTask, zEvent); } static void vdbeSorterRewindDebug(const char *zEvent){ | | > | | 96273 96274 96275 96276 96277 96278 96279 96280 96281 96282 96283 96284 96285 96286 96287 96288 96289 | static void vdbeSorterWorkDebug(SortSubtask *pTask, const char *zEvent){ i64 t; int iTask = (pTask - pTask->pSorter->aTask); sqlite3OsCurrentTimeInt64(pTask->pSorter->db->pVfs, &t); fprintf(stderr, "%lld:%d %s\n", t, iTask, zEvent); } static void vdbeSorterRewindDebug(const char *zEvent){ i64 t = 0; sqlite3_vfs *pVfs = sqlite3_vfs_find(0); if( ALWAYS(pVfs) ) sqlite3OsCurrentTimeInt64(pVfs, &t); fprintf(stderr, "%lld:X %s\n", t, zEvent); } static void vdbeSorterPopulateDebug( SortSubtask *pTask, const char *zEvent ){ i64 t; |
︙ | ︙ | |||
99498 99499 99500 99501 99502 99503 99504 | SrcList *pSrcList = pNC->pSrcList; if( pSrcList ){ for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){ u8 hCol; pTab = pItem->pTab; assert( pTab!=0 && pTab->zName!=0 ); | | | 99396 99397 99398 99399 99400 99401 99402 99403 99404 99405 99406 99407 99408 99409 99410 | SrcList *pSrcList = pNC->pSrcList; if( pSrcList ){ for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){ u8 hCol; pTab = pItem->pTab; assert( pTab!=0 && pTab->zName!=0 ); assert( pTab->nCol>0 || pParse->nErr ); if( pItem->pSelect && (pItem->pSelect->selFlags & SF_NestedFrom)!=0 ){ int hit = 0; pEList = pItem->pSelect->pEList; for(j=0; j<pEList->nExpr; j++){ if( sqlite3MatchEName(&pEList->a[j], zCol, zTab, zDb) ){ cnt++; cntTab = 2; |
︙ | ︙ | |||
99526 99527 99528 99529 99530 99531 99532 | if( sqlite3StrICmp(zTabName, zTab)!=0 ){ continue; } if( IN_RENAME_OBJECT && pItem->zAlias ){ sqlite3RenameTokenRemap(pParse, 0, (void*)&pExpr->y.pTab); } } | < < < | > > > > > > | 99424 99425 99426 99427 99428 99429 99430 99431 99432 99433 99434 99435 99436 99437 99438 99439 99440 99441 99442 99443 99444 99445 99446 99447 99448 99449 99450 99451 99452 99453 99454 99455 99456 99457 99458 99459 99460 | if( sqlite3StrICmp(zTabName, zTab)!=0 ){ continue; } if( IN_RENAME_OBJECT && pItem->zAlias ){ sqlite3RenameTokenRemap(pParse, 0, (void*)&pExpr->y.pTab); } } hCol = sqlite3StrIHash(zCol); for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){ if( pCol->hName==hCol && sqlite3StrICmp(pCol->zCnName, zCol)==0 ){ /* If there has been exactly one prior match and this match ** is for the right-hand table of a NATURAL JOIN or is in a ** USING clause, then skip this match. */ if( cnt==1 ){ if( pItem->fg.jointype & JT_NATURAL ) continue; if( nameInUsingClause(pItem->pUsing, zCol) ) continue; } cnt++; pMatch = pItem; /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */ pExpr->iColumn = j==pTab->iPKey ? -1 : (i16)j; break; } } if( 0==cnt && VisibleRowid(pTab) ){ cntTab++; pMatch = pItem; } } if( pMatch ){ pExpr->iTable = pMatch->iCursor; pExpr->y.pTab = pMatch->pTab; /* RIGHT JOIN not (yet) supported */ assert( (pMatch->fg.jointype & JT_RIGHT)==0 ); |
︙ | ︙ | |||
99604 99605 99606 99607 99608 99609 99610 | if( pTab ){ int iCol; u8 hCol = sqlite3StrIHash(zCol); pSchema = pTab->pSchema; cntTab++; for(iCol=0, pCol=pTab->aCol; iCol<pTab->nCol; iCol++, pCol++){ | | > > | 99505 99506 99507 99508 99509 99510 99511 99512 99513 99514 99515 99516 99517 99518 99519 99520 99521 | if( pTab ){ int iCol; u8 hCol = sqlite3StrIHash(zCol); pSchema = pTab->pSchema; cntTab++; for(iCol=0, pCol=pTab->aCol; iCol<pTab->nCol; iCol++, pCol++){ if( pCol->hName==hCol && sqlite3StrICmp(pCol->zCnName, zCol)==0 ){ if( iCol==pTab->iPKey ){ iCol = -1; } break; } } if( iCol>=pTab->nCol && sqlite3IsRowid(zCol) && VisibleRowid(pTab) ){ |
︙ | ︙ | |||
99669 99670 99671 99672 99673 99674 99675 | ** Perhaps the name is a reference to the ROWID */ if( cnt==0 && cntTab==1 && pMatch && (pNC->ncFlags & (NC_IdxExpr|NC_GenCol))==0 && sqlite3IsRowid(zCol) | | | 99572 99573 99574 99575 99576 99577 99578 99579 99580 99581 99582 99583 99584 99585 99586 | ** Perhaps the name is a reference to the ROWID */ if( cnt==0 && cntTab==1 && pMatch && (pNC->ncFlags & (NC_IdxExpr|NC_GenCol))==0 && sqlite3IsRowid(zCol) && ALWAYS(VisibleRowid(pMatch->pTab)) ){ cnt = 1; pExpr->iColumn = -1; pExpr->affExpr = SQLITE_AFF_INTEGER; } /* |
︙ | ︙ | |||
100012 100013 100014 100015 100016 100017 100018 100019 100020 100021 100022 100023 100024 100025 | NameContext *p; int i; for(i=0, p=pNC; p && i<ArraySize(anRef); p=p->pNext, i++){ anRef[i] = p->nRef; } sqlite3WalkExpr(pWalker, pExpr->pLeft); if( 0==sqlite3ExprCanBeNull(pExpr->pLeft) && !IN_RENAME_OBJECT ){ if( pExpr->op==TK_NOTNULL ){ pExpr->u.zToken = "true"; ExprSetProperty(pExpr, EP_IsTrue); }else{ pExpr->u.zToken = "false"; ExprSetProperty(pExpr, EP_IsFalse); } | > | 99915 99916 99917 99918 99919 99920 99921 99922 99923 99924 99925 99926 99927 99928 99929 | NameContext *p; int i; for(i=0, p=pNC; p && i<ArraySize(anRef); p=p->pNext, i++){ anRef[i] = p->nRef; } sqlite3WalkExpr(pWalker, pExpr->pLeft); if( 0==sqlite3ExprCanBeNull(pExpr->pLeft) && !IN_RENAME_OBJECT ){ testcase( ExprHasProperty(pExpr, EP_FromJoin) ); if( pExpr->op==TK_NOTNULL ){ pExpr->u.zToken = "true"; ExprSetProperty(pExpr, EP_IsTrue); }else{ pExpr->u.zToken = "false"; ExprSetProperty(pExpr, EP_IsFalse); } |
︙ | ︙ | |||
100281 100282 100283 100284 100285 100286 100287 100288 | while( pNC2 && !sqlite3FunctionUsesThisSrc(pExpr, pNC2->pSrcList) ){ pExpr->op2++; pNC2 = pNC2->pNext; } assert( pDef!=0 || IN_RENAME_OBJECT ); if( pNC2 && pDef ){ assert( SQLITE_FUNC_MINMAX==NC_MinMaxAgg ); testcase( (pDef->funcFlags & SQLITE_FUNC_MINMAX)!=0 ); | > > | | > | 100185 100186 100187 100188 100189 100190 100191 100192 100193 100194 100195 100196 100197 100198 100199 100200 100201 100202 100203 100204 | while( pNC2 && !sqlite3FunctionUsesThisSrc(pExpr, pNC2->pSrcList) ){ pExpr->op2++; pNC2 = pNC2->pNext; } assert( pDef!=0 || IN_RENAME_OBJECT ); if( pNC2 && pDef ){ assert( SQLITE_FUNC_MINMAX==NC_MinMaxAgg ); assert( SQLITE_FUNC_ANYORDER==NC_OrderAgg ); testcase( (pDef->funcFlags & SQLITE_FUNC_MINMAX)!=0 ); testcase( (pDef->funcFlags & SQLITE_FUNC_ANYORDER)!=0 ); pNC2->ncFlags |= NC_HasAgg | ((pDef->funcFlags^SQLITE_FUNC_ANYORDER) & (SQLITE_FUNC_MINMAX|SQLITE_FUNC_ANYORDER)); } } pNC->ncFlags |= savedAllowFlags; } /* FIX ME: Compute pExpr->affinity based on the expected return ** type of the function */ |
︙ | ︙ | |||
100826 100827 100828 100829 100830 100831 100832 | Select *pSub = p->pSrc->a[0].pSelect; assert( p->pSrc->nSrc==1 && p->pOrderBy ); assert( pSub->pPrior && pSub->pOrderBy==0 ); pSub->pOrderBy = p->pOrderBy; p->pOrderBy = 0; } | | | 100733 100734 100735 100736 100737 100738 100739 100740 100741 100742 100743 100744 100745 100746 100747 | Select *pSub = p->pSrc->a[0].pSelect; assert( p->pSrc->nSrc==1 && p->pOrderBy ); assert( pSub->pPrior && pSub->pOrderBy==0 ); pSub->pOrderBy = p->pOrderBy; p->pOrderBy = 0; } /* Recursively resolve names in all subqueries in the FROM clause */ for(i=0; i<p->pSrc->nSrc; i++){ SrcItem *pItem = &p->pSrc->a[i]; if( pItem->pSelect && (pItem->pSelect->selFlags & SF_Resolved)==0 ){ int nRef = pOuterNC ? pOuterNC->nRef : 0; const char *zSavedContext = pParse->zAuthContext; |
︙ | ︙ | |||
100870 100871 100872 100873 100874 100875 100876 | /* If there are no aggregate functions in the result-set, and no GROUP BY ** expression, do not allow aggregates in any of the other expressions. */ assert( (p->selFlags & SF_Aggregate)==0 ); pGroupBy = p->pGroupBy; if( pGroupBy || (sNC.ncFlags & NC_HasAgg)!=0 ){ assert( NC_MinMaxAgg==SF_MinMaxAgg ); | > | | 100777 100778 100779 100780 100781 100782 100783 100784 100785 100786 100787 100788 100789 100790 100791 100792 | /* If there are no aggregate functions in the result-set, and no GROUP BY ** expression, do not allow aggregates in any of the other expressions. */ assert( (p->selFlags & SF_Aggregate)==0 ); pGroupBy = p->pGroupBy; if( pGroupBy || (sNC.ncFlags & NC_HasAgg)!=0 ){ assert( NC_MinMaxAgg==SF_MinMaxAgg ); assert( NC_OrderAgg==SF_OrderByReqd ); p->selFlags |= SF_Aggregate | (sNC.ncFlags&(NC_MinMaxAgg|NC_OrderAgg)); }else{ sNC.ncFlags &= ~NC_AllowAgg; } /* Add the output column list to the name-context before parsing the ** other expressions in the SELECT statement. This is so that ** expressions in the WHERE clause (etc.) can refer to expressions by |
︙ | ︙ | |||
101053 101054 101055 101056 101057 101058 101059 | NameContext *pNC, /* Namespace to resolve expressions in. */ Expr *pExpr /* The expression to be analyzed. */ ){ int savedHasAgg; Walker w; if( pExpr==0 ) return SQLITE_OK; | | | | 100961 100962 100963 100964 100965 100966 100967 100968 100969 100970 100971 100972 100973 100974 100975 100976 | NameContext *pNC, /* Namespace to resolve expressions in. */ Expr *pExpr /* The expression to be analyzed. */ ){ int savedHasAgg; Walker w; if( pExpr==0 ) return SQLITE_OK; savedHasAgg = pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg); pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg); w.pParse = pNC->pParse; w.xExprCallback = resolveExprStep; w.xSelectCallback = (pNC->ncFlags & NC_NoSelect) ? 0 : resolveSelectStep; w.xSelectCallback2 = 0; w.u.pNC = pNC; #if SQLITE_MAX_EXPR_DEPTH>0 w.pParse->nHeight += pExpr->nHeight; |
︙ | ︙ | |||
101097 101098 101099 101100 101101 101102 101103 | Walker w; if( pList==0 ) return WRC_Continue; w.pParse = pNC->pParse; w.xExprCallback = resolveExprStep; w.xSelectCallback = resolveSelectStep; w.xSelectCallback2 = 0; w.u.pNC = pNC; | | | | | > | | 101005 101006 101007 101008 101009 101010 101011 101012 101013 101014 101015 101016 101017 101018 101019 101020 101021 101022 101023 101024 101025 101026 101027 101028 101029 101030 101031 101032 101033 101034 101035 101036 101037 101038 101039 101040 101041 101042 | Walker w; if( pList==0 ) return WRC_Continue; w.pParse = pNC->pParse; w.xExprCallback = resolveExprStep; w.xSelectCallback = resolveSelectStep; w.xSelectCallback2 = 0; w.u.pNC = pNC; savedHasAgg = pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg); pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg); for(i=0; i<pList->nExpr; i++){ Expr *pExpr = pList->a[i].pExpr; if( pExpr==0 ) continue; #if SQLITE_MAX_EXPR_DEPTH>0 w.pParse->nHeight += pExpr->nHeight; if( sqlite3ExprCheckHeight(w.pParse, w.pParse->nHeight) ){ return WRC_Abort; } #endif sqlite3WalkExpr(&w, pExpr); #if SQLITE_MAX_EXPR_DEPTH>0 w.pParse->nHeight -= pExpr->nHeight; #endif assert( EP_Agg==NC_HasAgg ); assert( EP_Win==NC_HasWin ); testcase( pNC->ncFlags & NC_HasAgg ); testcase( pNC->ncFlags & NC_HasWin ); if( pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg) ){ ExprSetProperty(pExpr, pNC->ncFlags & (NC_HasAgg|NC_HasWin) ); savedHasAgg |= pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg); pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg); } if( w.pParse->nErr>0 ) return WRC_Abort; } pNC->ncFlags |= savedHasAgg; return WRC_Continue; } |
︙ | ︙ | |||
101283 101284 101285 101286 101287 101288 101289 101290 101291 101292 101293 101294 101295 101296 | if( op==TK_CAST ){ assert( !ExprHasProperty(pExpr, EP_IntValue) ); return sqlite3AffinityType(pExpr->u.zToken, 0); } #endif if( op==TK_SELECT_COLUMN ){ assert( pExpr->pLeft->flags&EP_xIsSelect ); return sqlite3ExprAffinity( pExpr->pLeft->x.pSelect->pEList->a[pExpr->iColumn].pExpr ); } if( op==TK_VECTOR ){ return sqlite3ExprAffinity(pExpr->x.pList->a[0].pExpr); } | > > | 101192 101193 101194 101195 101196 101197 101198 101199 101200 101201 101202 101203 101204 101205 101206 101207 | if( op==TK_CAST ){ assert( !ExprHasProperty(pExpr, EP_IntValue) ); return sqlite3AffinityType(pExpr->u.zToken, 0); } #endif if( op==TK_SELECT_COLUMN ){ assert( pExpr->pLeft->flags&EP_xIsSelect ); assert( pExpr->iColumn < pExpr->iTable ); assert( pExpr->iTable==pExpr->pLeft->x.pSelect->pEList->nExpr ); return sqlite3ExprAffinity( pExpr->pLeft->x.pSelect->pEList->a[pExpr->iColumn].pExpr ); } if( op==TK_VECTOR ){ return sqlite3ExprAffinity(pExpr->x.pList->a[0].pExpr); } |
︙ | ︙ | |||
101383 101384 101385 101386 101387 101388 101389 | if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_TRIGGER) && p->y.pTab!=0 ){ /* op==TK_REGISTER && p->y.pTab!=0 happens when pExpr was originally ** a TK_COLUMN but was previously evaluated and cached in a register */ int j = p->iColumn; if( j>=0 ){ | | | 101294 101295 101296 101297 101298 101299 101300 101301 101302 101303 101304 101305 101306 101307 101308 | if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_TRIGGER) && p->y.pTab!=0 ){ /* op==TK_REGISTER && p->y.pTab!=0 happens when pExpr was originally ** a TK_COLUMN but was previously evaluated and cached in a register */ int j = p->iColumn; if( j>=0 ){ const char *zColl = sqlite3ColumnColl(&p->y.pTab->aCol[j]); pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0); } break; } if( op==TK_CAST || op==TK_UPLUS ){ p = p->pLeft; continue; |
︙ | ︙ | |||
101693 101694 101695 101696 101697 101698 101699 | ** A trick to cause a TK_SELECT pVector to be deleted together with ** the returned Expr object is to attach the pVector to the pRight field ** of the returned TK_SELECT_COLUMN Expr object. */ SQLITE_PRIVATE Expr *sqlite3ExprForVectorField( Parse *pParse, /* Parsing context */ Expr *pVector, /* The vector. List of expressions or a sub-SELECT */ | | > | 101604 101605 101606 101607 101608 101609 101610 101611 101612 101613 101614 101615 101616 101617 101618 101619 | ** A trick to cause a TK_SELECT pVector to be deleted together with ** the returned Expr object is to attach the pVector to the pRight field ** of the returned TK_SELECT_COLUMN Expr object. */ SQLITE_PRIVATE Expr *sqlite3ExprForVectorField( Parse *pParse, /* Parsing context */ Expr *pVector, /* The vector. List of expressions or a sub-SELECT */ int iField, /* Which column of the vector to return */ int nField /* Total number of columns in the vector */ ){ Expr *pRet; if( pVector->op==TK_SELECT ){ assert( pVector->flags & EP_xIsSelect ); /* The TK_SELECT_COLUMN Expr node: ** ** pLeft: pVector containing TK_SELECT. Not deleted. |
︙ | ︙ | |||
101716 101717 101718 101719 101720 101721 101722 101723 101724 101725 | ** can be attached to pRight to cause this node to take ownership of ** pVector. Typically there will be multiple TK_SELECT_COLUMN nodes ** with the same pLeft pointer to the pVector, but only one of them ** will own the pVector. */ pRet = sqlite3PExpr(pParse, TK_SELECT_COLUMN, 0, 0); if( pRet ){ pRet->iColumn = iField; pRet->pLeft = pVector; } | > < | 101628 101629 101630 101631 101632 101633 101634 101635 101636 101637 101638 101639 101640 101641 101642 101643 101644 101645 | ** can be attached to pRight to cause this node to take ownership of ** pVector. Typically there will be multiple TK_SELECT_COLUMN nodes ** with the same pLeft pointer to the pVector, but only one of them ** will own the pVector. */ pRet = sqlite3PExpr(pParse, TK_SELECT_COLUMN, 0, 0); if( pRet ){ pRet->iTable = nField; pRet->iColumn = iField; pRet->pLeft = pVector; } }else{ if( pVector->op==TK_VECTOR ) pVector = pVector->x.pList->a[iField].pExpr; pRet = sqlite3ExprDup(pParse->db, pVector, 0); sqlite3RenameTokenRemap(pParse, pRet, pVector); } return pRet; } |
︙ | ︙ | |||
102154 102155 102156 102157 102158 102159 102160 102161 102162 102163 102164 102165 102166 102167 | sqlite3ExprSetHeightAndFlags(pParse, pExpr); }else{ assert( pParse->db->mallocFailed ); sqlite3SelectDelete(pParse->db, pSelect); } } /* ** Join two expressions using an AND operator. If either expression is ** NULL, then just return the other expression. ** ** If one side or the other of the AND is known to be false, then instead ** of returning an AND expression, just return a constant expression with | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 102066 102067 102068 102069 102070 102071 102072 102073 102074 102075 102076 102077 102078 102079 102080 102081 102082 102083 102084 102085 102086 102087 102088 102089 102090 102091 102092 102093 102094 102095 102096 102097 102098 102099 102100 102101 102102 102103 102104 102105 102106 102107 102108 102109 102110 102111 102112 102113 102114 102115 102116 102117 102118 102119 102120 102121 102122 102123 102124 102125 102126 102127 102128 102129 | sqlite3ExprSetHeightAndFlags(pParse, pExpr); }else{ assert( pParse->db->mallocFailed ); sqlite3SelectDelete(pParse->db, pSelect); } } /* ** Expression list pEList is a list of vector values. This function ** converts the contents of pEList to a VALUES(...) Select statement ** returning 1 row for each element of the list. For example, the ** expression list: ** ** ( (1,2), (3,4) (5,6) ) ** ** is translated to the equivalent of: ** ** VALUES(1,2), (3,4), (5,6) ** ** Each of the vector values in pEList must contain exactly nElem terms. ** If a list element that is not a vector or does not contain nElem terms, ** an error message is left in pParse. ** ** This is used as part of processing IN(...) expressions with a list ** of vectors on the RHS. e.g. "... IN ((1,2), (3,4), (5,6))". */ SQLITE_PRIVATE Select *sqlite3ExprListToValues(Parse *pParse, int nElem, ExprList *pEList){ int ii; Select *pRet = 0; assert( nElem>1 ); for(ii=0; ii<pEList->nExpr; ii++){ Select *pSel; Expr *pExpr = pEList->a[ii].pExpr; int nExprElem = (pExpr->op==TK_VECTOR ? pExpr->x.pList->nExpr : 1); if( nExprElem!=nElem ){ sqlite3ErrorMsg(pParse, "IN(...) element has %d term%s - expected %d", nExprElem, nExprElem>1?"s":"", nElem ); break; } pSel = sqlite3SelectNew(pParse, pExpr->x.pList, 0, 0, 0, 0, 0, SF_Values,0); pExpr->x.pList = 0; if( pSel ){ if( pRet ){ pSel->op = TK_ALL; pSel->pPrior = pRet; } pRet = pSel; } } if( pRet && pRet->pPrior ){ pRet->selFlags |= SF_MultiValue; } sqlite3ExprListDelete(pParse->db, pEList); return pRet; } /* ** Join two expressions using an AND operator. If either expression is ** NULL, then just return the other expression. ** ** If one side or the other of the AND is known to be false, then instead ** of returning an AND expression, just return a constant expression with |
︙ | ︙ | |||
102198 102199 102200 102201 102202 102203 102204 | sqlite3 *db = pParse->db; assert( pToken ); pNew = sqlite3ExprAlloc(db, TK_FUNCTION, pToken, 1); if( pNew==0 ){ sqlite3ExprListDelete(db, pList); /* Avoid memory leak when malloc fails */ return 0; } | > | > > | 102160 102161 102162 102163 102164 102165 102166 102167 102168 102169 102170 102171 102172 102173 102174 102175 102176 102177 | sqlite3 *db = pParse->db; assert( pToken ); pNew = sqlite3ExprAlloc(db, TK_FUNCTION, pToken, 1); if( pNew==0 ){ sqlite3ExprListDelete(db, pList); /* Avoid memory leak when malloc fails */ return 0; } if( pList && pList->nExpr > pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] && !pParse->nested ){ sqlite3ErrorMsg(pParse, "too many arguments on function %T", pToken); } pNew->x.pList = pList; ExprSetProperty(pNew, EP_HasFunc); assert( !ExprHasProperty(pNew, EP_xIsSelect) ); sqlite3ExprSetHeightAndFlags(pParse, pNew); if( eDistinct==SF_Distinct ) ExprSetProperty(pNew, EP_Distinct); |
︙ | ︙ | |||
102606 102607 102608 102609 102610 102611 102612 | if( pzBuffer ){ *pzBuffer = zAlloc; } }else{ if( !ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){ if( pNew->op==TK_SELECT_COLUMN ){ pNew->pLeft = p->pLeft; | < | 102571 102572 102573 102574 102575 102576 102577 102578 102579 102580 102581 102582 102583 102584 | if( pzBuffer ){ *pzBuffer = zAlloc; } }else{ if( !ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){ if( pNew->op==TK_SELECT_COLUMN ){ pNew->pLeft = p->pLeft; assert( p->pRight==0 || p->pRight==p->pLeft || ExprHasProperty(p->pLeft, EP_Subquery) ); }else{ pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0); } pNew->pRight = sqlite3ExprDup(db, p->pRight, 0); } |
︙ | ︙ | |||
102704 102705 102706 102707 102708 102709 102710 | assert( flags==0 || flags==EXPRDUP_REDUCE ); return p ? exprDup(db, p, flags, 0) : 0; } SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){ ExprList *pNew; struct ExprList_item *pItem, *pOldItem; int i; | | > < | | | | < | | > | > | | 102668 102669 102670 102671 102672 102673 102674 102675 102676 102677 102678 102679 102680 102681 102682 102683 102684 102685 102686 102687 102688 102689 102690 102691 102692 102693 102694 102695 102696 102697 102698 102699 102700 102701 102702 102703 102704 102705 102706 102707 102708 102709 102710 | assert( flags==0 || flags==EXPRDUP_REDUCE ); return p ? exprDup(db, p, flags, 0) : 0; } SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){ ExprList *pNew; struct ExprList_item *pItem, *pOldItem; int i; Expr *pPriorSelectColOld = 0; Expr *pPriorSelectColNew = 0; assert( db!=0 ); if( p==0 ) return 0; pNew = sqlite3DbMallocRawNN(db, sqlite3DbMallocSize(db, p)); if( pNew==0 ) return 0; pNew->nExpr = p->nExpr; pNew->nAlloc = p->nAlloc; pItem = pNew->a; pOldItem = p->a; for(i=0; i<p->nExpr; i++, pItem++, pOldItem++){ Expr *pOldExpr = pOldItem->pExpr; Expr *pNewExpr; pItem->pExpr = sqlite3ExprDup(db, pOldExpr, flags); if( pOldExpr && pOldExpr->op==TK_SELECT_COLUMN && (pNewExpr = pItem->pExpr)!=0 ){ if( pNewExpr->pRight ){ pPriorSelectColOld = pOldExpr->pRight; pPriorSelectColNew = pNewExpr->pRight; pNewExpr->pLeft = pNewExpr->pRight; }else{ if( pOldExpr->pLeft!=pPriorSelectColOld ){ pPriorSelectColOld = pOldExpr->pLeft; pPriorSelectColNew = sqlite3ExprDup(db, pPriorSelectColOld, flags); pNewExpr->pRight = pPriorSelectColNew; } pNewExpr->pLeft = pPriorSelectColNew; } } pItem->zEName = sqlite3DbStrDup(db, pOldItem->zEName); pItem->sortFlags = pOldItem->sortFlags; pItem->eEName = pOldItem->eEName; pItem->done = 0; pItem->bNulls = pOldItem->bNulls; |
︙ | ︙ | |||
102990 102991 102992 102993 102994 102995 102996 | if( pExpr->op!=TK_SELECT && pColumns->nId!=(n=sqlite3ExprVectorSize(pExpr)) ){ sqlite3ErrorMsg(pParse, "%d columns assigned %d values", pColumns->nId, n); goto vector_append_error; } for(i=0; i<pColumns->nId; i++){ | | < < | 102955 102956 102957 102958 102959 102960 102961 102962 102963 102964 102965 102966 102967 102968 102969 102970 102971 | if( pExpr->op!=TK_SELECT && pColumns->nId!=(n=sqlite3ExprVectorSize(pExpr)) ){ sqlite3ErrorMsg(pParse, "%d columns assigned %d values", pColumns->nId, n); goto vector_append_error; } for(i=0; i<pColumns->nId; i++){ Expr *pSubExpr = sqlite3ExprForVectorField(pParse, pExpr, i, pColumns->nId); assert( pSubExpr!=0 || db->mallocFailed ); if( pSubExpr==0 ) continue; pList = sqlite3ExprListAppend(pParse, pList, pSubExpr); if( pList ){ assert( pList->nExpr==iFirst+i+1 ); pList->a[pList->nExpr-1].zEName = pColumns->a[i].zName; pColumns->a[i].zName = 0; } } |
︙ | ︙ | |||
103671 103672 103673 103674 103675 103676 103677 | if( p->pWhere ) return 0; /* Has no WHERE clause */ pSrc = p->pSrc; assert( pSrc!=0 ); if( pSrc->nSrc!=1 ) return 0; /* Single term in FROM clause */ if( pSrc->a[0].pSelect ) return 0; /* FROM is not a subquery or view */ pTab = pSrc->a[0].pTab; assert( pTab!=0 ); | | | 103634 103635 103636 103637 103638 103639 103640 103641 103642 103643 103644 103645 103646 103647 103648 | if( p->pWhere ) return 0; /* Has no WHERE clause */ pSrc = p->pSrc; assert( pSrc!=0 ); if( pSrc->nSrc!=1 ) return 0; /* Single term in FROM clause */ if( pSrc->a[0].pSelect ) return 0; /* FROM is not a subquery or view */ pTab = pSrc->a[0].pTab; assert( pTab!=0 ); assert( !IsView(pTab) ); /* FROM clause is not a view */ if( IsVirtual(pTab) ) return 0; /* FROM clause not a virtual table */ pEList = p->pEList; assert( pEList!=0 ); /* All SELECT results must be columns. */ for(i=0; i<pEList->nExpr; i++){ Expr *pRes = pEList->a[i].pExpr; if( pRes->op!=TK_COLUMN ) return 0; |
︙ | ︙ | |||
104801 104802 104803 104804 104805 104806 104807 | #ifndef SQLITE_OMIT_GENERATED_COLUMNS /* ** Generate code that will compute the value of generated column pCol ** and store the result in register regOut */ SQLITE_PRIVATE void sqlite3ExprCodeGeneratedColumn( | | > | | | | 104764 104765 104766 104767 104768 104769 104770 104771 104772 104773 104774 104775 104776 104777 104778 104779 104780 104781 104782 104783 104784 104785 104786 104787 104788 104789 104790 104791 104792 | #ifndef SQLITE_OMIT_GENERATED_COLUMNS /* ** Generate code that will compute the value of generated column pCol ** and store the result in register regOut */ SQLITE_PRIVATE void sqlite3ExprCodeGeneratedColumn( Parse *pParse, /* Parsing context */ Table *pTab, /* Table containing the generated column */ Column *pCol, /* The generated column */ int regOut /* Put the result in this register */ ){ int iAddr; Vdbe *v = pParse->pVdbe; assert( v!=0 ); assert( pParse->iSelfTab!=0 ); if( pParse->iSelfTab>0 ){ iAddr = sqlite3VdbeAddOp3(v, OP_IfNullRow, pParse->iSelfTab-1, 0, regOut); }else{ iAddr = 0; } sqlite3ExprCodeCopy(pParse, sqlite3ColumnExpr(pTab,pCol), regOut); if( pCol->affinity>=SQLITE_AFF_TEXT ){ sqlite3VdbeAddOp4(v, OP_Affinity, regOut, 1, 0, &pCol->affinity, 1); } if( iAddr ) sqlite3VdbeJumpHere(v, iAddr); } #endif /* SQLITE_OMIT_GENERATED_COLUMNS */ |
︙ | ︙ | |||
104850 104851 104852 104853 104854 104855 104856 | if( IsVirtual(pTab) ){ op = OP_VColumn; x = iCol; #ifndef SQLITE_OMIT_GENERATED_COLUMNS }else if( (pCol = &pTab->aCol[iCol])->colFlags & COLFLAG_VIRTUAL ){ Parse *pParse = sqlite3VdbeParser(v); if( pCol->colFlags & COLFLAG_BUSY ){ | | > | | 104814 104815 104816 104817 104818 104819 104820 104821 104822 104823 104824 104825 104826 104827 104828 104829 104830 104831 104832 104833 104834 | if( IsVirtual(pTab) ){ op = OP_VColumn; x = iCol; #ifndef SQLITE_OMIT_GENERATED_COLUMNS }else if( (pCol = &pTab->aCol[iCol])->colFlags & COLFLAG_VIRTUAL ){ Parse *pParse = sqlite3VdbeParser(v); if( pCol->colFlags & COLFLAG_BUSY ){ sqlite3ErrorMsg(pParse, "generated column loop on \"%s\"", pCol->zCnName); }else{ int savedSelfTab = pParse->iSelfTab; pCol->colFlags |= COLFLAG_BUSY; pParse->iSelfTab = iTabCur+1; sqlite3ExprCodeGeneratedColumn(pParse, pTab, pCol, regOut); pParse->iSelfTab = savedSelfTab; pCol->colFlags &= ~COLFLAG_BUSY; } return; #endif }else if( !HasRowid(pTab) ){ testcase( iCol!=sqlite3TableColumnToStorage(pTab, iCol) ); |
︙ | ︙ | |||
105123 105124 105125 105126 105127 105128 105129 | }else if( pAggInfo->useSortingIdx ){ Table *pTab = pCol->pTab; sqlite3VdbeAddOp3(v, OP_Column, pAggInfo->sortingIdxPTab, pCol->iSorterColumn, target); if( pCol->iColumn<0 ){ VdbeComment((v,"%s.rowid",pTab->zName)); }else{ | | > | 105088 105089 105090 105091 105092 105093 105094 105095 105096 105097 105098 105099 105100 105101 105102 105103 | }else if( pAggInfo->useSortingIdx ){ Table *pTab = pCol->pTab; sqlite3VdbeAddOp3(v, OP_Column, pAggInfo->sortingIdxPTab, pCol->iSorterColumn, target); if( pCol->iColumn<0 ){ VdbeComment((v,"%s.rowid",pTab->zName)); }else{ VdbeComment((v,"%s.%s", pTab->zName, pTab->aCol[pCol->iColumn].zCnName)); if( pTab->aCol[pCol->iColumn].affinity==SQLITE_AFF_REAL ){ sqlite3VdbeAddOp1(v, OP_RealAffinity, target); } } return target; } /* Otherwise, fall thru into the TK_COLUMN case */ |
︙ | ︙ | |||
105184 105185 105186 105187 105188 105189 105190 | pCol = pTab->aCol + iCol; testcase( iCol!=sqlite3TableColumnToStorage(pTab,iCol) ); iSrc = sqlite3TableColumnToStorage(pTab, iCol) - pParse->iSelfTab; #ifndef SQLITE_OMIT_GENERATED_COLUMNS if( pCol->colFlags & COLFLAG_GENERATED ){ if( pCol->colFlags & COLFLAG_BUSY ){ sqlite3ErrorMsg(pParse, "generated column loop on \"%s\"", | | | | 105150 105151 105152 105153 105154 105155 105156 105157 105158 105159 105160 105161 105162 105163 105164 105165 105166 105167 105168 105169 | pCol = pTab->aCol + iCol; testcase( iCol!=sqlite3TableColumnToStorage(pTab,iCol) ); iSrc = sqlite3TableColumnToStorage(pTab, iCol) - pParse->iSelfTab; #ifndef SQLITE_OMIT_GENERATED_COLUMNS if( pCol->colFlags & COLFLAG_GENERATED ){ if( pCol->colFlags & COLFLAG_BUSY ){ sqlite3ErrorMsg(pParse, "generated column loop on \"%s\"", pCol->zCnName); return 0; } pCol->colFlags |= COLFLAG_BUSY; if( pCol->colFlags & COLFLAG_NOTAVAIL ){ sqlite3ExprCodeGeneratedColumn(pParse, pTab, pCol, iSrc); } pCol->colFlags &= ~(COLFLAG_BUSY|COLFLAG_NOTAVAIL); return iSrc; }else #endif /* SQLITE_OMIT_GENERATED_COLUMNS */ if( pCol->affinity==SQLITE_AFF_REAL ){ sqlite3VdbeAddOp2(v, OP_SCopy, iSrc, target); |
︙ | ︙ | |||
105584 105585 105586 105587 105588 105589 105590 | break; } case TK_SELECT_COLUMN: { int n; if( pExpr->pLeft->iTable==0 ){ pExpr->pLeft->iTable = sqlite3CodeSubselect(pParse, pExpr->pLeft); } | | | | < < | 105550 105551 105552 105553 105554 105555 105556 105557 105558 105559 105560 105561 105562 105563 105564 105565 105566 | break; } case TK_SELECT_COLUMN: { int n; if( pExpr->pLeft->iTable==0 ){ pExpr->pLeft->iTable = sqlite3CodeSubselect(pParse, pExpr->pLeft); } assert( pExpr->pLeft->op==TK_SELECT || pExpr->pLeft->op==TK_ERROR ); n = sqlite3ExprVectorSize(pExpr->pLeft); if( pExpr->iTable!=n ){ sqlite3ErrorMsg(pParse, "%d columns assigned %d values", pExpr->iTable, n); } return pExpr->pLeft->iTable + pExpr->iColumn; } case TK_IN: { int destIfFalse = sqlite3VdbeMakeLabel(pParse); |
︙ | ︙ | |||
105669 105670 105671 105672 105673 105674 105675 | assert( iCol>=-1 && iCol<pTab->nCol ); assert( pTab->iPKey<0 || iCol!=pTab->iPKey ); assert( p1>=0 && p1<(pTab->nCol*2+2) ); sqlite3VdbeAddOp2(v, OP_Param, p1, target); VdbeComment((v, "r[%d]=%s.%s", target, (pExpr->iTable ? "new" : "old"), | | | 105633 105634 105635 105636 105637 105638 105639 105640 105641 105642 105643 105644 105645 105646 105647 | assert( iCol>=-1 && iCol<pTab->nCol ); assert( pTab->iPKey<0 || iCol!=pTab->iPKey ); assert( p1>=0 && p1<(pTab->nCol*2+2) ); sqlite3VdbeAddOp2(v, OP_Param, p1, target); VdbeComment((v, "r[%d]=%s.%s", target, (pExpr->iTable ? "new" : "old"), (pExpr->iColumn<0 ? "rowid" : pExpr->y.pTab->aCol[iCol].zCnName) )); #ifndef SQLITE_OMIT_FLOATING_POINT /* If the column has REAL affinity, it may currently be stored as an ** integer. Use OP_RealAffinity to make sure it is really real. ** ** EVIDENCE-OF: R-60985-57662 SQLite will convert the value back to |
︙ | ︙ | |||
106841 106842 106843 106844 106845 106846 106847 | testcase( pExpr->op==TK_NE ); testcase( pExpr->op==TK_LT ); testcase( pExpr->op==TK_LE ); testcase( pExpr->op==TK_GT ); testcase( pExpr->op==TK_GE ); /* The y.pTab=0 assignment in wherecode.c always happens after the ** impliesNotNullRow() test */ | | | | 106805 106806 106807 106808 106809 106810 106811 106812 106813 106814 106815 106816 106817 106818 106819 106820 106821 | testcase( pExpr->op==TK_NE ); testcase( pExpr->op==TK_LT ); testcase( pExpr->op==TK_LE ); testcase( pExpr->op==TK_GT ); testcase( pExpr->op==TK_GE ); /* The y.pTab=0 assignment in wherecode.c always happens after the ** impliesNotNullRow() test */ if( (pLeft->op==TK_COLUMN && pLeft->y.pTab!=0 && IsVirtual(pLeft->y.pTab)) || (pRight->op==TK_COLUMN && pRight->y.pTab!=0 && IsVirtual(pRight->y.pTab)) ){ return WRC_Prune; } /* no break */ deliberate_fall_through } default: |
︙ | ︙ | |||
107522 107523 107524 107525 107526 107527 107528 | Table *pTab; /* Table being renamed */ char *zName = 0; /* NULL-terminated version of pName */ sqlite3 *db = pParse->db; /* Database connection */ int nTabName; /* Number of UTF-8 characters in zTabName */ const char *zTabName; /* Original name of the table */ Vdbe *v; VTable *pVTab = 0; /* Non-zero if this is a v-tab with an xRename() */ | < < < | 107486 107487 107488 107489 107490 107491 107492 107493 107494 107495 107496 107497 107498 107499 107500 107501 107502 107503 107504 107505 107506 107507 107508 | Table *pTab; /* Table being renamed */ char *zName = 0; /* NULL-terminated version of pName */ sqlite3 *db = pParse->db; /* Database connection */ int nTabName; /* Number of UTF-8 characters in zTabName */ const char *zTabName; /* Original name of the table */ Vdbe *v; VTable *pVTab = 0; /* Non-zero if this is a v-tab with an xRename() */ if( NEVER(db->mallocFailed) ) goto exit_rename_table; assert( pSrc->nSrc==1 ); assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]); if( !pTab ) goto exit_rename_table; iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); zDb = db->aDb[iDb].zDbSName; /* Get a NULL terminated version of the new table name. */ zName = sqlite3NameFromToken(db, pName); if( !zName ) goto exit_rename_table; /* Check that a table or index named 'zName' does not already exist ** in database iDb. If so, this is an error. |
︙ | ︙ | |||
107562 107563 107564 107565 107566 107567 107568 | goto exit_rename_table; } if( SQLITE_OK!=sqlite3CheckObjectName(pParse,zName,"table",zName) ){ goto exit_rename_table; } #ifndef SQLITE_OMIT_VIEW | | | 107523 107524 107525 107526 107527 107528 107529 107530 107531 107532 107533 107534 107535 107536 107537 | goto exit_rename_table; } if( SQLITE_OK!=sqlite3CheckObjectName(pParse,zName,"table",zName) ){ goto exit_rename_table; } #ifndef SQLITE_OMIT_VIEW if( IsView(pTab) ){ sqlite3ErrorMsg(pParse, "view %s may not be altered", pTab->zName); goto exit_rename_table; } #endif #ifndef SQLITE_OMIT_AUTHORIZATION /* Invoke the authorization callback. */ |
︙ | ︙ | |||
107674 107675 107676 107677 107678 107679 107680 | renameReloadSchema(pParse, iDb, INITFLAG_AlterRename); renameTestSchema(pParse, zDb, iDb==1, "after rename", 0); exit_rename_table: sqlite3SrcListDelete(db, pSrc); sqlite3DbFree(db, zName); | < | 107635 107636 107637 107638 107639 107640 107641 107642 107643 107644 107645 107646 107647 107648 | renameReloadSchema(pParse, iDb, INITFLAG_AlterRename); renameTestSchema(pParse, zDb, iDb==1, "after rename", 0); exit_rename_table: sqlite3SrcListDelete(db, pSrc); sqlite3DbFree(db, zName); } /* ** Write code that will raise an error if the table described by ** zDb and zTab is not empty. */ static void sqlite3ErrorIfNotEmpty( |
︙ | ︙ | |||
107724 107725 107726 107727 107728 107729 107730 | assert( pNew ); assert( sqlite3BtreeHoldsAllMutexes(db) ); iDb = sqlite3SchemaToIndex(db, pNew->pSchema); zDb = db->aDb[iDb].zDbSName; zTab = &pNew->zName[16]; /* Skip the "sqlite_altertab_" prefix on the name */ pCol = &pNew->aCol[pNew->nCol-1]; | | | 107684 107685 107686 107687 107688 107689 107690 107691 107692 107693 107694 107695 107696 107697 107698 | assert( pNew ); assert( sqlite3BtreeHoldsAllMutexes(db) ); iDb = sqlite3SchemaToIndex(db, pNew->pSchema); zDb = db->aDb[iDb].zDbSName; zTab = &pNew->zName[16]; /* Skip the "sqlite_altertab_" prefix on the name */ pCol = &pNew->aCol[pNew->nCol-1]; pDflt = sqlite3ColumnExpr(pNew, pCol); pTab = sqlite3FindTable(db, zTab, zDb); assert( pTab ); #ifndef SQLITE_OMIT_AUTHORIZATION /* Invoke the authorization callback. */ if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){ return; |
︙ | ︙ | |||
107758 107759 107760 107761 107762 107763 107764 | ** literal NULL, then set pDflt to 0. This simplifies checking ** for an SQL NULL default below. */ assert( pDflt==0 || pDflt->op==TK_SPAN ); if( pDflt && pDflt->pLeft->op==TK_NULL ){ pDflt = 0; } | | | 107718 107719 107720 107721 107722 107723 107724 107725 107726 107727 107728 107729 107730 107731 107732 | ** literal NULL, then set pDflt to 0. This simplifies checking ** for an SQL NULL default below. */ assert( pDflt==0 || pDflt->op==TK_SPAN ); if( pDflt && pDflt->pLeft->op==TK_NULL ){ pDflt = 0; } if( (db->flags&SQLITE_ForeignKeys) && pNew->u.tab.pFKey && pDflt ){ sqlite3ErrorIfNotEmpty(pParse, zDb, zTab, "Cannot add a REFERENCES column with non-NULL default value"); } if( pCol->notNull && !pDflt ){ sqlite3ErrorIfNotEmpty(pParse, zDb, zTab, "Cannot add a NOT NULL column with default value NULL"); } |
︙ | ︙ | |||
107795 107796 107797 107798 107799 107800 107801 | } /* Modify the CREATE TABLE statement. */ zCol = sqlite3DbStrNDup(db, (char*)pColDef->z, pColDef->n); if( zCol ){ char *zEnd = &zCol[pColDef->n-1]; | < < > | < > > | | | | < < | < | | > > > > > > > > > > > > > > > > | 107755 107756 107757 107758 107759 107760 107761 107762 107763 107764 107765 107766 107767 107768 107769 107770 107771 107772 107773 107774 107775 107776 107777 107778 107779 107780 107781 107782 107783 107784 107785 107786 107787 107788 107789 107790 107791 107792 107793 107794 107795 107796 107797 107798 107799 107800 107801 107802 107803 107804 107805 107806 107807 107808 107809 107810 107811 107812 107813 107814 107815 107816 107817 107818 | } /* Modify the CREATE TABLE statement. */ zCol = sqlite3DbStrNDup(db, (char*)pColDef->z, pColDef->n); if( zCol ){ char *zEnd = &zCol[pColDef->n-1]; while( zEnd>zCol && (*zEnd==';' || sqlite3Isspace(*zEnd)) ){ *zEnd-- = '\0'; } /* substr() operations on characters, but addColOffset is in bytes. So we ** have to use printf() to translate between these units: */ assert( !IsVirtual(pTab) ); sqlite3NestedParse(pParse, "UPDATE \"%w\"." DFLT_SCHEMA_TABLE " SET " "sql = printf('%%.%ds, ',sql) || %Q" " || substr(sql,1+length(printf('%%.%ds',sql))) " "WHERE type = 'table' AND name = %Q", zDb, pNew->u.tab.addColOffset, zCol, pNew->u.tab.addColOffset, zTab ); sqlite3DbFree(db, zCol); } v = sqlite3GetVdbe(pParse); if( v ){ /* Make sure the schema version is at least 3. But do not upgrade ** from less than 3 to 4, as that will corrupt any preexisting DESC ** index. */ r1 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, r1, BTREE_FILE_FORMAT); sqlite3VdbeUsesBtree(v, iDb); sqlite3VdbeAddOp2(v, OP_AddImm, r1, -2); sqlite3VdbeAddOp2(v, OP_IfPos, r1, sqlite3VdbeCurrentAddr(v)+2); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, 3); sqlite3ReleaseTempReg(pParse, r1); /* Reload the table definition */ renameReloadSchema(pParse, iDb, INITFLAG_AlterRename); /* Verify that constraints are still satisfied */ if( pNew->pCheck!=0 || (pCol->notNull && (pCol->colFlags & COLFLAG_GENERATED)!=0) ){ sqlite3NestedParse(pParse, "SELECT CASE WHEN quick_check GLOB 'CHECK*'" " THEN raise(ABORT,'CHECK constraint failed')" " ELSE raise(ABORT,'NOT NULL constraint failed')" " END" " FROM pragma_quick_check(\"%w\",\"%w\")" " WHERE quick_check GLOB 'CHECK*' OR quick_check GLOB 'NULL*'", zTab, zDb ); } } } /* ** This function is called by the parser after the table-name in ** an "ALTER TABLE <table-name> ADD" statement is parsed. Argument ** pSrc is the full-name of the table being altered. ** |
︙ | ︙ | |||
107872 107873 107874 107875 107876 107877 107878 | if( IsVirtual(pTab) ){ sqlite3ErrorMsg(pParse, "virtual tables may not be altered"); goto exit_begin_add_column; } #endif /* Make sure this is not an attempt to ALTER a view. */ | | | | 107845 107846 107847 107848 107849 107850 107851 107852 107853 107854 107855 107856 107857 107858 107859 107860 107861 107862 107863 107864 107865 107866 107867 107868 | if( IsVirtual(pTab) ){ sqlite3ErrorMsg(pParse, "virtual tables may not be altered"); goto exit_begin_add_column; } #endif /* Make sure this is not an attempt to ALTER a view. */ if( IsView(pTab) ){ sqlite3ErrorMsg(pParse, "Cannot add a column to a view"); goto exit_begin_add_column; } if( SQLITE_OK!=isAlterableTable(pParse, pTab) ){ goto exit_begin_add_column; } sqlite3MayAbort(pParse); assert( pTab->u.tab.addColOffset>0 ); iDb = sqlite3SchemaToIndex(db, pTab->pSchema); /* Put a copy of the Table struct in Parse.pNewTable for the ** sqlite3AddColumn() function and friends to modify. But modify ** the name by adding an "sqlite_altertab_" prefix. By adding this ** prefix, we insure that the name will not collide with an existing ** table because user table are not allowed to have the "sqlite_" |
︙ | ︙ | |||
107908 107909 107910 107911 107912 107913 107914 | if( !pNew->aCol || !pNew->zName ){ assert( db->mallocFailed ); goto exit_begin_add_column; } memcpy(pNew->aCol, pTab->aCol, sizeof(Column)*pNew->nCol); for(i=0; i<pNew->nCol; i++){ Column *pCol = &pNew->aCol[i]; | | | < < > > | | | 107881 107882 107883 107884 107885 107886 107887 107888 107889 107890 107891 107892 107893 107894 107895 107896 107897 107898 107899 107900 107901 107902 107903 107904 107905 107906 107907 107908 107909 107910 107911 107912 107913 107914 107915 107916 107917 107918 107919 107920 107921 | if( !pNew->aCol || !pNew->zName ){ assert( db->mallocFailed ); goto exit_begin_add_column; } memcpy(pNew->aCol, pTab->aCol, sizeof(Column)*pNew->nCol); for(i=0; i<pNew->nCol; i++){ Column *pCol = &pNew->aCol[i]; pCol->zCnName = sqlite3DbStrDup(db, pCol->zCnName); pCol->hName = sqlite3StrIHash(pCol->zCnName); } assert( !IsVirtual(pNew) ); pNew->u.tab.pDfltList = sqlite3ExprListDup(db, pTab->u.tab.pDfltList, 0); pNew->pSchema = db->aDb[iDb].pSchema; pNew->u.tab.addColOffset = pTab->u.tab.addColOffset; pNew->nTabRef = 1; exit_begin_add_column: sqlite3SrcListDelete(db, pSrc); return; } /* ** Parameter pTab is the subject of an ALTER TABLE ... RENAME COLUMN ** command. This function checks if the table is a view or virtual ** table (columns of views or virtual tables may not be renamed). If so, ** it loads an error message into pParse and returns non-zero. ** ** Or, if pTab is not a view or virtual table, zero is returned. */ #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) static int isRealTable(Parse *pParse, Table *pTab, int bDrop){ const char *zType = 0; #ifndef SQLITE_OMIT_VIEW if( IsView(pTab) ){ zType = "view"; } #endif #ifndef SQLITE_OMIT_VIRTUALTABLE if( IsVirtual(pTab) ){ zType = "virtual table"; } |
︙ | ︙ | |||
108001 108002 108003 108004 108005 108006 108007 | #endif /* Make sure the old name really is a column name in the table to be ** altered. Set iCol to be the index of the column being renamed */ zOld = sqlite3NameFromToken(db, pOld); if( !zOld ) goto exit_rename_column; for(iCol=0; iCol<pTab->nCol; iCol++){ | | | 107974 107975 107976 107977 107978 107979 107980 107981 107982 107983 107984 107985 107986 107987 107988 | #endif /* Make sure the old name really is a column name in the table to be ** altered. Set iCol to be the index of the column being renamed */ zOld = sqlite3NameFromToken(db, pOld); if( !zOld ) goto exit_rename_column; for(iCol=0; iCol<pTab->nCol; iCol++){ if( 0==sqlite3StrICmp(pTab->aCol[iCol].zCnName, zOld) ) break; } if( iCol==pTab->nCol ){ sqlite3ErrorMsg(pParse, "no such column: \"%s\"", zOld); goto exit_rename_column; } /* Ensure the schema contains no double-quoted strings */ |
︙ | ︙ | |||
108238 108239 108240 108241 108242 108243 108244 | ** Walker callback used by sqlite3RenameExprUnmap(). */ static int renameUnmapSelectCb(Walker *pWalker, Select *p){ Parse *pParse = pWalker->pParse; int i; if( pParse->nErr ) return WRC_Abort; if( p->selFlags & (SF_View|SF_CopyCte) ){ | | | | 108211 108212 108213 108214 108215 108216 108217 108218 108219 108220 108221 108222 108223 108224 108225 108226 | ** Walker callback used by sqlite3RenameExprUnmap(). */ static int renameUnmapSelectCb(Walker *pWalker, Select *p){ Parse *pParse = pWalker->pParse; int i; if( pParse->nErr ) return WRC_Abort; if( p->selFlags & (SF_View|SF_CopyCte) ){ testcase( p->selFlags & SF_View ); testcase( p->selFlags & SF_CopyCte ); return WRC_Prune; } if( ALWAYS(p->pEList) ){ ExprList *pList = p->pEList; for(i=0; i<pList->nExpr; i++){ if( pList->a[i].zEName && pList->a[i].eEName==ENAME_NAME ){ sqlite3RenameTokenRemap(pParse, 0, (void*)pList->a[i].zEName); |
︙ | ︙ | |||
108350 108351 108352 108353 108354 108355 108356 | /* ** This is a Walker select callback. It does nothing. It is only required ** because without a dummy callback, sqlite3WalkExpr() and similar do not ** descend into sub-select statements. */ static int renameColumnSelectCb(Walker *pWalker, Select *p){ if( p->selFlags & (SF_View|SF_CopyCte) ){ | | | | 108323 108324 108325 108326 108327 108328 108329 108330 108331 108332 108333 108334 108335 108336 108337 108338 | /* ** This is a Walker select callback. It does nothing. It is only required ** because without a dummy callback, sqlite3WalkExpr() and similar do not ** descend into sub-select statements. */ static int renameColumnSelectCb(Walker *pWalker, Select *p){ if( p->selFlags & (SF_View|SF_CopyCte) ){ testcase( p->selFlags & SF_View ); testcase( p->selFlags & SF_CopyCte ); return WRC_Prune; } renameWalkWith(pWalker, p); return WRC_Continue; } /* |
︙ | ︙ | |||
108547 108548 108549 108550 108551 108552 108553 | static int renameEditSql( sqlite3_context *pCtx, /* Return result here */ RenameCtx *pRename, /* Rename context */ const char *zSql, /* SQL statement to edit */ const char *zNew, /* New token text */ int bQuote /* True to always quote token */ ){ | | | | | 108520 108521 108522 108523 108524 108525 108526 108527 108528 108529 108530 108531 108532 108533 108534 108535 108536 108537 108538 108539 108540 | static int renameEditSql( sqlite3_context *pCtx, /* Return result here */ RenameCtx *pRename, /* Rename context */ const char *zSql, /* SQL statement to edit */ const char *zNew, /* New token text */ int bQuote /* True to always quote token */ ){ i64 nNew = sqlite3Strlen30(zNew); i64 nSql = sqlite3Strlen30(zSql); sqlite3 *db = sqlite3_context_db_handle(pCtx); int rc = SQLITE_OK; char *zQuot = 0; char *zOut; i64 nQuot = 0; char *zBuf1 = 0; char *zBuf2 = 0; if( zNew ){ /* Set zQuot to point to a buffer containing a quoted copy of the ** identifier zNew. If the corresponding identifier in the original ** ALTER TABLE statement was quoted (bQuote==1), then set zNew to |
︙ | ︙ | |||
108847 108848 108849 108850 108851 108852 108853 | if( iCol<0 ) return; sqlite3BtreeEnterAll(db); pTab = sqlite3FindTable(db, zTable, zDb); if( pTab==0 || iCol>=pTab->nCol ){ sqlite3BtreeLeaveAll(db); return; } | | > | < | < | > > | > | | 108820 108821 108822 108823 108824 108825 108826 108827 108828 108829 108830 108831 108832 108833 108834 108835 108836 108837 108838 108839 108840 108841 108842 108843 108844 108845 108846 108847 108848 108849 108850 108851 108852 108853 108854 108855 108856 108857 108858 108859 108860 108861 108862 108863 108864 108865 108866 108867 108868 108869 108870 108871 108872 108873 108874 108875 108876 108877 108878 108879 108880 108881 108882 108883 108884 108885 108886 108887 108888 108889 108890 108891 108892 108893 108894 | if( iCol<0 ) return; sqlite3BtreeEnterAll(db); pTab = sqlite3FindTable(db, zTable, zDb); if( pTab==0 || iCol>=pTab->nCol ){ sqlite3BtreeLeaveAll(db); return; } zOld = pTab->aCol[iCol].zCnName; memset(&sCtx, 0, sizeof(sCtx)); sCtx.iCol = ((iCol==pTab->iPKey) ? -1 : iCol); #ifndef SQLITE_OMIT_AUTHORIZATION db->xAuth = 0; #endif rc = renameParseSql(&sParse, zDb, db, zSql, bTemp); /* Find tokens that need to be replaced. */ memset(&sWalker, 0, sizeof(Walker)); sWalker.pParse = &sParse; sWalker.xExprCallback = renameColumnExprCb; sWalker.xSelectCallback = renameColumnSelectCb; sWalker.u.pRename = &sCtx; sCtx.pTab = pTab; if( rc!=SQLITE_OK ) goto renameColumnFunc_done; if( sParse.pNewTable ){ if( IsView(sParse.pNewTable) ){ Select *pSelect = sParse.pNewTable->u.view.pSelect; pSelect->selFlags &= ~SF_View; sParse.rc = SQLITE_OK; sqlite3SelectPrep(&sParse, pSelect, 0); rc = (db->mallocFailed ? SQLITE_NOMEM : sParse.rc); if( rc==SQLITE_OK ){ sqlite3WalkSelect(&sWalker, pSelect); } if( rc!=SQLITE_OK ) goto renameColumnFunc_done; }else if( ALWAYS(IsOrdinaryTable(sParse.pNewTable)) ){ /* A regular table */ int bFKOnly = sqlite3_stricmp(zTable, sParse.pNewTable->zName); FKey *pFKey; sCtx.pTab = sParse.pNewTable; if( bFKOnly==0 ){ if( iCol<sParse.pNewTable->nCol ){ renameTokenFind( &sParse, &sCtx, (void*)sParse.pNewTable->aCol[iCol].zCnName ); } if( sCtx.iCol<0 ){ renameTokenFind(&sParse, &sCtx, (void*)&sParse.pNewTable->iPKey); } sqlite3WalkExprList(&sWalker, sParse.pNewTable->pCheck); for(pIdx=sParse.pNewTable->pIndex; pIdx; pIdx=pIdx->pNext){ sqlite3WalkExprList(&sWalker, pIdx->aColExpr); } for(pIdx=sParse.pNewIndex; pIdx; pIdx=pIdx->pNext){ sqlite3WalkExprList(&sWalker, pIdx->aColExpr); } #ifndef SQLITE_OMIT_GENERATED_COLUMNS for(i=0; i<sParse.pNewTable->nCol; i++){ Expr *pExpr = sqlite3ColumnExpr(sParse.pNewTable, &sParse.pNewTable->aCol[i]); sqlite3WalkExpr(&sWalker, pExpr); } #endif } assert( !IsVirtual(sParse.pNewTable) ); for(pFKey=sParse.pNewTable->u.tab.pFKey; pFKey; pFKey=pFKey->pNextFrom){ for(i=0; i<pFKey->nCol; i++){ if( bFKOnly==0 && pFKey->aCol[i].iFrom==iCol ){ renameTokenFind(&sParse, &sCtx, (void*)&pFKey->aCol[i]); } if( 0==sqlite3_stricmp(pFKey->zTo, zTable) && 0==sqlite3_stricmp(pFKey->aCol[i].zCol, zOld) ){ |
︙ | ︙ | |||
109071 109072 109073 109074 109075 109076 109077 | rc = renameParseSql(&sParse, zDb, db, zInput, bTemp); if( rc==SQLITE_OK ){ int isLegacy = (db->flags & SQLITE_LegacyAlter); if( sParse.pNewTable ){ Table *pTab = sParse.pNewTable; | | | | | | > > > | | 109046 109047 109048 109049 109050 109051 109052 109053 109054 109055 109056 109057 109058 109059 109060 109061 109062 109063 109064 109065 109066 109067 109068 109069 109070 109071 109072 109073 109074 109075 109076 109077 109078 109079 109080 109081 109082 109083 109084 | rc = renameParseSql(&sParse, zDb, db, zInput, bTemp); if( rc==SQLITE_OK ){ int isLegacy = (db->flags & SQLITE_LegacyAlter); if( sParse.pNewTable ){ Table *pTab = sParse.pNewTable; if( IsView(pTab) ){ if( isLegacy==0 ){ Select *pSelect = pTab->u.view.pSelect; NameContext sNC; memset(&sNC, 0, sizeof(sNC)); sNC.pParse = &sParse; assert( pSelect->selFlags & SF_View ); pSelect->selFlags &= ~SF_View; sqlite3SelectPrep(&sParse, pTab->u.view.pSelect, &sNC); if( sParse.nErr ){ rc = sParse.rc; }else{ sqlite3WalkSelect(&sWalker, pTab->u.view.pSelect); } } }else{ /* Modify any FK definitions to point to the new table. */ #ifndef SQLITE_OMIT_FOREIGN_KEY if( (isLegacy==0 || (db->flags & SQLITE_ForeignKeys)) && !IsVirtual(pTab) ){ FKey *pFKey; assert( !IsVirtual(pTab) ); for(pFKey=pTab->u.tab.pFKey; pFKey; pFKey=pFKey->pNextFrom){ if( sqlite3_stricmp(pFKey->zTo, zOld)==0 ){ renameTokenFind(&sParse, &sCtx, (void*)pFKey->zTo); } } } #endif |
︙ | ︙ | |||
109232 109233 109234 109235 109236 109237 109238 | memset(&sWalker, 0, sizeof(Walker)); sWalker.pParse = &sParse; sWalker.xExprCallback = renameQuotefixExprCb; sWalker.xSelectCallback = renameColumnSelectCb; sWalker.u.pRename = &sCtx; if( sParse.pNewTable ){ | > | < | > > | 109210 109211 109212 109213 109214 109215 109216 109217 109218 109219 109220 109221 109222 109223 109224 109225 109226 109227 109228 109229 109230 109231 109232 109233 109234 109235 109236 109237 109238 109239 109240 | memset(&sWalker, 0, sizeof(Walker)); sWalker.pParse = &sParse; sWalker.xExprCallback = renameQuotefixExprCb; sWalker.xSelectCallback = renameColumnSelectCb; sWalker.u.pRename = &sCtx; if( sParse.pNewTable ){ if( IsView(sParse.pNewTable) ){ Select *pSelect = sParse.pNewTable->u.view.pSelect; pSelect->selFlags &= ~SF_View; sParse.rc = SQLITE_OK; sqlite3SelectPrep(&sParse, pSelect, 0); rc = (db->mallocFailed ? SQLITE_NOMEM : sParse.rc); if( rc==SQLITE_OK ){ sqlite3WalkSelect(&sWalker, pSelect); } }else{ int i; sqlite3WalkExprList(&sWalker, sParse.pNewTable->pCheck); #ifndef SQLITE_OMIT_GENERATED_COLUMNS for(i=0; i<sParse.pNewTable->nCol; i++){ sqlite3WalkExpr(&sWalker, sqlite3ColumnExpr(sParse.pNewTable, &sParse.pNewTable->aCol[i])); } #endif /* SQLITE_OMIT_GENERATED_COLUMNS */ } }else if( sParse.pNewIndex ){ sqlite3WalkExprList(&sWalker, sParse.pNewIndex->aColExpr); sqlite3WalkExpr(&sWalker, sParse.pNewIndex->pPartIdxWhere); }else{ |
︙ | ︙ | |||
109329 109330 109331 109332 109333 109334 109335 | int rc; Parse sParse; int flags = db->flags; if( bNoDQS ) db->flags &= ~(SQLITE_DqsDML|SQLITE_DqsDDL); rc = renameParseSql(&sParse, zDb, db, zInput, bTemp); db->flags |= (flags & (SQLITE_DqsDML|SQLITE_DqsDDL)); if( rc==SQLITE_OK ){ | | | | 109309 109310 109311 109312 109313 109314 109315 109316 109317 109318 109319 109320 109321 109322 109323 109324 109325 109326 109327 | int rc; Parse sParse; int flags = db->flags; if( bNoDQS ) db->flags &= ~(SQLITE_DqsDML|SQLITE_DqsDDL); rc = renameParseSql(&sParse, zDb, db, zInput, bTemp); db->flags |= (flags & (SQLITE_DqsDML|SQLITE_DqsDDL)); if( rc==SQLITE_OK ){ if( isLegacy==0 && sParse.pNewTable && IsView(sParse.pNewTable) ){ NameContext sNC; memset(&sNC, 0, sizeof(sNC)); sNC.pParse = &sParse; sqlite3SelectPrep(&sParse, sParse.pNewTable->u.view.pSelect, &sNC); if( sParse.nErr ) rc = sParse.rc; } else if( sParse.pNewTrigger ){ if( isLegacy==0 ){ rc = renameResolveTrigger(&sParse); } |
︙ | ︙ | |||
109404 109405 109406 109407 109408 109409 109410 | pTab = sParse.pNewTable; if( pTab==0 || pTab->nCol==1 || iCol>=pTab->nCol ){ /* This can happen if the sqlite_schema table is corrupt */ rc = SQLITE_CORRUPT_BKPT; goto drop_column_done; } | | | > | | 109384 109385 109386 109387 109388 109389 109390 109391 109392 109393 109394 109395 109396 109397 109398 109399 109400 109401 109402 109403 109404 109405 | pTab = sParse.pNewTable; if( pTab==0 || pTab->nCol==1 || iCol>=pTab->nCol ){ /* This can happen if the sqlite_schema table is corrupt */ rc = SQLITE_CORRUPT_BKPT; goto drop_column_done; } pCol = renameTokenFind(&sParse, 0, (void*)pTab->aCol[iCol].zCnName); if( iCol<pTab->nCol-1 ){ RenameToken *pEnd; pEnd = renameTokenFind(&sParse, 0, (void*)pTab->aCol[iCol+1].zCnName); zEnd = (const char*)pEnd->t.z; }else{ assert( !IsVirtual(pTab) ); zEnd = (const char*)&zSql[pTab->u.tab.addColOffset]; while( ALWAYS(pCol->t.z[0]!=0) && pCol->t.z[0]!=',' ) pCol->t.z--; } zNew = sqlite3MPrintf(db, "%.*s%s", pCol->t.z-zSql, zSql, zEnd); sqlite3_result_text(context, zNew, -1, SQLITE_TRANSIENT); sqlite3_free(zNew); |
︙ | ︙ | |||
109545 109546 109547 109548 109549 109550 109551 109552 109553 109554 109555 109556 109557 109558 | if( i==pTab->iPKey ){ sqlite3VdbeAddOp2(v, OP_Null, 0, regOut); }else{ sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, i, regOut); } nField++; } } sqlite3VdbeAddOp3(v, OP_MakeRecord, reg+1, nField, regRec); if( pPk ){ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iCur, regRec, reg+1, pPk->nKeyCol); }else{ sqlite3VdbeAddOp3(v, OP_Insert, iCur, regRec, reg); } | > > > > > > | 109526 109527 109528 109529 109530 109531 109532 109533 109534 109535 109536 109537 109538 109539 109540 109541 109542 109543 109544 109545 | if( i==pTab->iPKey ){ sqlite3VdbeAddOp2(v, OP_Null, 0, regOut); }else{ sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, i, regOut); } nField++; } } if( nField==0 ){ /* dbsqlfuzz 5f09e7bcc78b4954d06bf9f2400d7715f48d1fef */ pParse->nMem++; sqlite3VdbeAddOp2(v, OP_Null, 0, reg+1); nField = 1; } sqlite3VdbeAddOp3(v, OP_MakeRecord, reg+1, nField, regRec); if( pPk ){ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iCur, regRec, reg+1, pPk->nKeyCol); }else{ sqlite3VdbeAddOp3(v, OP_Insert, iCur, regRec, reg); } |
︙ | ︙ | |||
110550 110551 110552 110553 110554 110555 110556 | assert( k>=0 && k<pIdx->nColumn ); i = pIdx->aiColumn[k]; if( NEVER(i==XN_ROWID) ){ VdbeComment((v,"%s.rowid",pIdx->zName)); }else if( i==XN_EXPR ){ VdbeComment((v,"%s.expr(%d)",pIdx->zName, k)); }else{ | | | 110537 110538 110539 110540 110541 110542 110543 110544 110545 110546 110547 110548 110549 110550 110551 | assert( k>=0 && k<pIdx->nColumn ); i = pIdx->aiColumn[k]; if( NEVER(i==XN_ROWID) ){ VdbeComment((v,"%s.rowid",pIdx->zName)); }else if( i==XN_EXPR ){ VdbeComment((v,"%s.expr(%d)",pIdx->zName, k)); }else{ VdbeComment((v,"%s.%s", pIdx->zName, pIdx->pTable->aCol[i].zCnName)); } } #else # define analyzeVdbeCommentIndexWithColumnName(a,b,c) #endif /* SQLITE_DEBUG */ /* |
︙ | ︙ | |||
112303 112304 112305 112306 112307 112308 112309 | } } iCol = pExpr->iColumn; if( pTab==0 ) return; if( iCol>=0 ){ assert( iCol<pTab->nCol ); | | | | 112290 112291 112292 112293 112294 112295 112296 112297 112298 112299 112300 112301 112302 112303 112304 112305 112306 112307 | } } iCol = pExpr->iColumn; if( pTab==0 ) return; if( iCol>=0 ){ assert( iCol<pTab->nCol ); zCol = pTab->aCol[iCol].zCnName; }else if( pTab->iPKey>=0 ){ assert( pTab->iPKey<pTab->nCol ); zCol = pTab->aCol[pTab->iPKey].zCnName; }else{ zCol = "ROWID"; } assert( iDb>=0 && iDb<pParse->db->nDb ); if( SQLITE_IGNORE==sqlite3AuthReadCol(pParse, pTab->zName, zCol, iDb) ){ pExpr->op = TK_NULL; } |
︙ | ︙ | |||
112684 112685 112686 112687 112688 112689 112690 | pParse->rc = SQLITE_ERROR; } } /* ** Run the parser and code generator recursively in order to generate ** code for the SQL statement given onto the end of the pParse context | | > | | | < | | > > > > | 112671 112672 112673 112674 112675 112676 112677 112678 112679 112680 112681 112682 112683 112684 112685 112686 112687 112688 112689 112690 112691 112692 112693 112694 112695 112696 112697 112698 112699 112700 112701 112702 112703 112704 112705 112706 112707 112708 112709 112710 112711 112712 112713 112714 112715 112716 112717 112718 112719 112720 112721 | pParse->rc = SQLITE_ERROR; } } /* ** Run the parser and code generator recursively in order to generate ** code for the SQL statement given onto the end of the pParse context ** currently under construction. Notes: ** ** * The final OP_Halt is not appended and other initialization ** and finalization steps are omitted because those are handling by the ** outermost parser. ** ** * Built-in SQL functions always take precedence over application-defined ** SQL functions. In other words, it is not possible to override a ** built-in function. */ SQLITE_PRIVATE void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){ va_list ap; char *zSql; char *zErrMsg = 0; sqlite3 *db = pParse->db; u32 savedDbFlags = db->mDbFlags; char saveBuf[PARSE_TAIL_SZ]; if( pParse->nErr ) return; assert( pParse->nested<10 ); /* Nesting should only be of limited depth */ va_start(ap, zFormat); zSql = sqlite3VMPrintf(db, zFormat, ap); va_end(ap); if( zSql==0 ){ /* This can result either from an OOM or because the formatted string ** exceeds SQLITE_LIMIT_LENGTH. In the latter case, we need to set ** an error */ if( !db->mallocFailed ) pParse->rc = SQLITE_TOOBIG; pParse->nErr++; return; } pParse->nested++; memcpy(saveBuf, PARSE_TAIL(pParse), PARSE_TAIL_SZ); memset(PARSE_TAIL(pParse), 0, PARSE_TAIL_SZ); db->mDbFlags |= DBFLAG_PreferBuiltin; sqlite3RunParser(pParse, zSql, &zErrMsg); db->mDbFlags = savedDbFlags; sqlite3DbFree(db, zErrMsg); sqlite3DbFree(db, zSql); memcpy(PARSE_TAIL(pParse), saveBuf, PARSE_TAIL_SZ); pParse->nested--; } #if SQLITE_USER_AUTHENTICATION |
︙ | ︙ | |||
112852 112853 112854 112855 112856 112857 112858 112859 112860 112861 112862 112863 112864 112865 | ** can be an eponymous virtual table. */ if( pParse->disableVtab==0 && db->init.busy==0 ){ Module *pMod = (Module*)sqlite3HashFind(&db->aModule, zName); if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){ pMod = sqlite3PragmaVtabRegister(db, zName); } if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){ return pMod->pEpoTab; } } #endif if( flags & LOCATE_NOERR ) return 0; pParse->checkSchema = 1; }else if( IsVirtual(p) && pParse->disableVtab ){ | > | 112843 112844 112845 112846 112847 112848 112849 112850 112851 112852 112853 112854 112855 112856 112857 | ** can be an eponymous virtual table. */ if( pParse->disableVtab==0 && db->init.busy==0 ){ Module *pMod = (Module*)sqlite3HashFind(&db->aModule, zName); if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){ pMod = sqlite3PragmaVtabRegister(db, zName); } if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){ testcase( pMod->pEpoTab==0 ); return pMod->pEpoTab; } } #endif if( flags & LOCATE_NOERR ) return 0; pParse->checkSchema = 1; }else if( IsVirtual(p) && pParse->disableVtab ){ |
︙ | ︙ | |||
113064 113065 113066 113067 113068 113069 113070 113071 113072 113073 113074 113075 113076 113077 113078 113079 113080 113081 | /* ** This routine is called when a commit occurs. */ SQLITE_PRIVATE void sqlite3CommitInternalChanges(sqlite3 *db){ db->mDbFlags &= ~DBFLAG_SchemaChange; } /* ** Delete memory allocated for the column names of a table or view (the ** Table.aCol[] array). */ SQLITE_PRIVATE void sqlite3DeleteColumnNames(sqlite3 *db, Table *pTable){ int i; Column *pCol; assert( pTable!=0 ); if( (pCol = pTable->aCol)!=0 ){ for(i=0; i<pTable->nCol; i++, pCol++){ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | < > | > > > | > > > > > | 113056 113057 113058 113059 113060 113061 113062 113063 113064 113065 113066 113067 113068 113069 113070 113071 113072 113073 113074 113075 113076 113077 113078 113079 113080 113081 113082 113083 113084 113085 113086 113087 113088 113089 113090 113091 113092 113093 113094 113095 113096 113097 113098 113099 113100 113101 113102 113103 113104 113105 113106 113107 113108 113109 113110 113111 113112 113113 113114 113115 113116 113117 113118 113119 113120 113121 113122 113123 113124 113125 113126 113127 113128 113129 113130 113131 113132 113133 113134 113135 113136 113137 113138 113139 113140 113141 113142 113143 113144 113145 113146 113147 113148 113149 113150 113151 113152 113153 113154 113155 113156 113157 113158 113159 113160 113161 113162 113163 113164 113165 113166 113167 113168 113169 113170 113171 113172 | /* ** This routine is called when a commit occurs. */ SQLITE_PRIVATE void sqlite3CommitInternalChanges(sqlite3 *db){ db->mDbFlags &= ~DBFLAG_SchemaChange; } /* ** Set the expression associated with a column. This is usually ** the DEFAULT value, but might also be the expression that computes ** the value for a generated column. */ SQLITE_PRIVATE void sqlite3ColumnSetExpr( Parse *pParse, /* Parsing context */ Table *pTab, /* The table containing the column */ Column *pCol, /* The column to receive the new DEFAULT expression */ Expr *pExpr /* The new default expression */ ){ ExprList *pList; assert( !IsVirtual(pTab) ); pList = pTab->u.tab.pDfltList; if( pCol->iDflt==0 || NEVER(pList==0) || NEVER(pList->nExpr<pCol->iDflt) ){ pCol->iDflt = pList==0 ? 1 : pList->nExpr+1; pTab->u.tab.pDfltList = sqlite3ExprListAppend(pParse, pList, pExpr); }else{ sqlite3ExprDelete(pParse->db, pList->a[pCol->iDflt-1].pExpr); pList->a[pCol->iDflt-1].pExpr = pExpr; } } /* ** Return the expression associated with a column. The expression might be ** the DEFAULT clause or the AS clause of a generated column. ** Return NULL if the column has no associated expression. */ SQLITE_PRIVATE Expr *sqlite3ColumnExpr(Table *pTab, Column *pCol){ if( pCol->iDflt==0 ) return 0; if( NEVER(IsVirtual(pTab)) ) return 0; if( NEVER(pTab->u.tab.pDfltList==0) ) return 0; if( NEVER(pTab->u.tab.pDfltList->nExpr<pCol->iDflt) ) return 0; return pTab->u.tab.pDfltList->a[pCol->iDflt-1].pExpr; } /* ** Set the collating sequence name for a column. */ SQLITE_PRIVATE void sqlite3ColumnSetColl( sqlite3 *db, Column *pCol, const char *zColl ){ int nColl; int n; char *zNew; assert( zColl!=0 ); n = sqlite3Strlen30(pCol->zCnName) + 1; if( pCol->colFlags & COLFLAG_HASTYPE ){ n += sqlite3Strlen30(pCol->zCnName+n) + 1; } nColl = sqlite3Strlen30(zColl) + 1; zNew = sqlite3DbRealloc(db, pCol->zCnName, nColl+n); if( zNew ){ pCol->zCnName = zNew; memcpy(pCol->zCnName + n, zColl, nColl); pCol->colFlags |= COLFLAG_HASCOLL; } } /* ** Return the collating squence name for a column */ SQLITE_PRIVATE const char *sqlite3ColumnColl(Column *pCol){ const char *z; if( (pCol->colFlags & COLFLAG_HASCOLL)==0 ) return 0; z = pCol->zCnName; while( *z ){ z++; } if( pCol->colFlags & COLFLAG_HASTYPE ){ do{ z++; }while( *z ); } return z+1; } /* ** Delete memory allocated for the column names of a table or view (the ** Table.aCol[] array). */ SQLITE_PRIVATE void sqlite3DeleteColumnNames(sqlite3 *db, Table *pTable){ int i; Column *pCol; assert( pTable!=0 ); if( (pCol = pTable->aCol)!=0 ){ for(i=0; i<pTable->nCol; i++, pCol++){ assert( pCol->zCnName==0 || pCol->hName==sqlite3StrIHash(pCol->zCnName) ); sqlite3DbFree(db, pCol->zCnName); } sqlite3DbFree(db, pTable->aCol); if( !IsVirtual(pTable) ){ sqlite3ExprListDelete(db, pTable->u.tab.pDfltList); } if( db==0 || db->pnBytesFreed==0 ){ pTable->aCol = 0; pTable->nCol = 0; if( !IsVirtual(pTable) ){ pTable->u.tab.pDfltList = 0; } } } } /* ** Remove the memory data structures associated with the given ** Table. No changes are made to disk by this routine. ** |
︙ | ︙ | |||
113132 113133 113134 113135 113136 113137 113138 | ); assert( db==0 || sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) ); assert( pOld==pIndex || pOld==0 ); } sqlite3FreeIndex(db, pIndex); } | | | > > > > > > > > > > < < < < | 113210 113211 113212 113213 113214 113215 113216 113217 113218 113219 113220 113221 113222 113223 113224 113225 113226 113227 113228 113229 113230 113231 113232 113233 113234 113235 113236 113237 113238 113239 113240 113241 113242 | ); assert( db==0 || sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) ); assert( pOld==pIndex || pOld==0 ); } sqlite3FreeIndex(db, pIndex); } if( IsOrdinaryTable(pTable) ){ sqlite3FkDelete(db, pTable); } #ifndef SQLITE_OMIT_VIRTUAL_TABLE else if( IsVirtual(pTable) ){ sqlite3VtabClear(db, pTable); } #endif else{ assert( IsView(pTable) ); sqlite3SelectDelete(db, pTable->u.view.pSelect); } /* Delete the Table structure itself. */ sqlite3DeleteColumnNames(db, pTable); sqlite3DbFree(db, pTable->zName); sqlite3DbFree(db, pTable->zColAff); sqlite3ExprListDelete(db, pTable->pCheck); sqlite3DbFree(db, pTable); /* Verify that no lookaside memory was used by schema tables */ assert( nLookaside==0 || nLookaside==sqlite3LookasideUsed(db,0) ); } SQLITE_PRIVATE void sqlite3DeleteTable(sqlite3 *db, Table *pTable){ /* Do not delete the table until the reference count reaches zero. */ |
︙ | ︙ | |||
113670 113671 113672 113673 113674 113675 113676 113677 113678 113679 113680 113681 113682 113683 113684 113685 | } /* Normal (non-error) return. */ return; /* If an error occurs, we jump here */ begin_table_error: sqlite3DbFree(db, zName); return; } /* Set properties of a table column based on the (magical) ** name of the column. */ #if SQLITE_ENABLE_HIDDEN_COLUMNS SQLITE_PRIVATE void sqlite3ColumnPropertiesFromName(Table *pTab, Column *pCol){ | > | | 113754 113755 113756 113757 113758 113759 113760 113761 113762 113763 113764 113765 113766 113767 113768 113769 113770 113771 113772 113773 113774 113775 113776 113777 113778 | } /* Normal (non-error) return. */ return; /* If an error occurs, we jump here */ begin_table_error: pParse->checkSchema = 1; sqlite3DbFree(db, zName); return; } /* Set properties of a table column based on the (magical) ** name of the column. */ #if SQLITE_ENABLE_HIDDEN_COLUMNS SQLITE_PRIVATE void sqlite3ColumnPropertiesFromName(Table *pTab, Column *pCol){ if( sqlite3_strnicmp(pCol->zCnName, "__hidden__", 10)==0 ){ pCol->colFlags |= COLFLAG_HIDDEN; if( pTab ) pTab->tabFlags |= TF_HasHidden; }else if( pTab && pCol!=pTab->aCol && (pCol[-1].colFlags & COLFLAG_HIDDEN) ){ pTab->tabFlags |= TF_OOOHidden; } } #endif |
︙ | ︙ | |||
113770 113771 113772 113773 113774 113775 113776 | ** Add a new column to the table currently being constructed. ** ** The parser calls this routine once for each column declaration ** in a CREATE TABLE statement. sqlite3StartTable() gets called ** first to get things going. Then this routine is called for each ** column. */ | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | | | < < | | | | | | < | | | > | > | | > | | | 113855 113856 113857 113858 113859 113860 113861 113862 113863 113864 113865 113866 113867 113868 113869 113870 113871 113872 113873 113874 113875 113876 113877 113878 113879 113880 113881 113882 113883 113884 113885 113886 113887 113888 113889 113890 113891 113892 113893 113894 113895 113896 113897 113898 113899 113900 113901 113902 113903 113904 113905 113906 113907 113908 113909 113910 113911 113912 113913 113914 113915 113916 113917 113918 113919 113920 113921 113922 113923 113924 113925 113926 113927 113928 113929 113930 113931 113932 113933 113934 113935 113936 113937 113938 113939 113940 113941 113942 113943 113944 113945 113946 113947 113948 113949 113950 113951 113952 113953 113954 113955 113956 113957 113958 113959 113960 113961 113962 113963 113964 113965 113966 | ** Add a new column to the table currently being constructed. ** ** The parser calls this routine once for each column declaration ** in a CREATE TABLE statement. sqlite3StartTable() gets called ** first to get things going. Then this routine is called for each ** column. */ SQLITE_PRIVATE void sqlite3AddColumn(Parse *pParse, Token sName, Token sType){ Table *p; int i; char *z; char *zType; Column *pCol; sqlite3 *db = pParse->db; u8 hName; Column *aNew; u8 eType = COLTYPE_CUSTOM; u8 szEst = 1; char affinity = SQLITE_AFF_BLOB; if( (p = pParse->pNewTable)==0 ) return; if( p->nCol+1>db->aLimit[SQLITE_LIMIT_COLUMN] ){ sqlite3ErrorMsg(pParse, "too many columns on %s", p->zName); return; } if( !IN_RENAME_OBJECT ) sqlite3DequoteToken(&sName); /* Because keywords GENERATE ALWAYS can be converted into indentifiers ** by the parser, we can sometimes end up with a typename that ends ** with "generated always". Check for this case and omit the surplus ** text. */ if( sType.n>=16 && sqlite3_strnicmp(sType.z+(sType.n-6),"always",6)==0 ){ sType.n -= 6; while( ALWAYS(sType.n>0) && sqlite3Isspace(sType.z[sType.n-1]) ) sType.n--; if( sType.n>=9 && sqlite3_strnicmp(sType.z+(sType.n-9),"generated",9)==0 ){ sType.n -= 9; while( sType.n>0 && sqlite3Isspace(sType.z[sType.n-1]) ) sType.n--; } } /* Check for standard typenames. For standard typenames we will ** set the Column.eType field rather than storing the typename after ** the column name, in order to save space. */ if( sType.n>=3 ){ sqlite3DequoteToken(&sType); for(i=0; i<SQLITE_N_STDTYPE; i++){ if( sType.n==sqlite3StdTypeLen[i] && sqlite3_strnicmp(sType.z, sqlite3StdType[i], sType.n)==0 ){ sType.n = 0; eType = i+1; affinity = sqlite3StdTypeAffinity[i]; if( affinity<=SQLITE_AFF_TEXT ) szEst = 5; break; } } } z = sqlite3DbMallocRaw(db, sName.n + 1 + sType.n + (sType.n>0) ); if( z==0 ) return; if( IN_RENAME_OBJECT ) sqlite3RenameTokenMap(pParse, (void*)z, &sName); memcpy(z, sName.z, sName.n); z[sName.n] = 0; sqlite3Dequote(z); hName = sqlite3StrIHash(z); for(i=0; i<p->nCol; i++){ if( p->aCol[i].hName==hName && sqlite3StrICmp(z, p->aCol[i].zCnName)==0 ){ sqlite3ErrorMsg(pParse, "duplicate column name: %s", z); sqlite3DbFree(db, z); return; } } aNew = sqlite3DbRealloc(db,p->aCol,(p->nCol+1)*sizeof(p->aCol[0])); if( aNew==0 ){ sqlite3DbFree(db, z); return; } p->aCol = aNew; pCol = &p->aCol[p->nCol]; memset(pCol, 0, sizeof(p->aCol[0])); pCol->zCnName = z; pCol->hName = hName; sqlite3ColumnPropertiesFromName(p, pCol); if( sType.n==0 ){ /* If there is no type specified, columns have the default affinity ** 'BLOB' with a default size of 4 bytes. */ pCol->affinity = affinity; pCol->eType = eType; pCol->szEst = szEst; #ifdef SQLITE_ENABLE_SORTER_REFERENCES if( affinity==SQLITE_AFF_BLOB ){ if( 4>=sqlite3GlobalConfig.szSorterRef ){ pCol->colFlags |= COLFLAG_SORTERREF; } } #endif }else{ zType = z + sqlite3Strlen30(z) + 1; memcpy(zType, sType.z, sType.n); zType[sType.n] = 0; sqlite3Dequote(zType); pCol->affinity = sqlite3AffinityType(zType, pCol); pCol->colFlags |= COLFLAG_HASTYPE; } p->nCol++; p->nNVCol++; pParse->constraintName.n = 0; |
︙ | ︙ | |||
113981 113982 113983 113984 113985 113986 113987 | sqlite3 *db = pParse->db; p = pParse->pNewTable; if( p!=0 ){ int isInit = db->init.busy && db->init.iDb!=1; pCol = &(p->aCol[p->nCol-1]); if( !sqlite3ExprIsConstantOrFunction(pExpr, isInit) ){ sqlite3ErrorMsg(pParse, "default value of column [%s] is not constant", | | | < | > | 114107 114108 114109 114110 114111 114112 114113 114114 114115 114116 114117 114118 114119 114120 114121 114122 114123 114124 114125 114126 114127 114128 114129 114130 114131 114132 114133 114134 114135 114136 114137 114138 114139 114140 | sqlite3 *db = pParse->db; p = pParse->pNewTable; if( p!=0 ){ int isInit = db->init.busy && db->init.iDb!=1; pCol = &(p->aCol[p->nCol-1]); if( !sqlite3ExprIsConstantOrFunction(pExpr, isInit) ){ sqlite3ErrorMsg(pParse, "default value of column [%s] is not constant", pCol->zCnName); #ifndef SQLITE_OMIT_GENERATED_COLUMNS }else if( pCol->colFlags & COLFLAG_GENERATED ){ testcase( pCol->colFlags & COLFLAG_VIRTUAL ); testcase( pCol->colFlags & COLFLAG_STORED ); sqlite3ErrorMsg(pParse, "cannot use DEFAULT on a generated column"); #endif }else{ /* A copy of pExpr is used instead of the original, as pExpr contains ** tokens that point to volatile memory. */ Expr x, *pDfltExpr; memset(&x, 0, sizeof(x)); x.op = TK_SPAN; x.u.zToken = sqlite3DbSpanDup(db, zStart, zEnd); x.pLeft = pExpr; x.flags = EP_Skip; pDfltExpr = sqlite3ExprDup(db, &x, EXPRDUP_REDUCE); sqlite3DbFree(db, x.u.zToken); sqlite3ColumnSetExpr(pParse, p, pCol, pDfltExpr); } } if( IN_RENAME_OBJECT ){ sqlite3RenameExprUnmap(pParse, pExpr); } sqlite3ExprDelete(db, pExpr); } |
︙ | ︙ | |||
114098 114099 114100 114101 114102 114103 114104 | for(i=0; i<nTerm; i++){ Expr *pCExpr = sqlite3ExprSkipCollate(pList->a[i].pExpr); assert( pCExpr!=0 ); sqlite3StringToId(pCExpr); if( pCExpr->op==TK_ID ){ const char *zCName = pCExpr->u.zToken; for(iCol=0; iCol<pTab->nCol; iCol++){ | | | | 114224 114225 114226 114227 114228 114229 114230 114231 114232 114233 114234 114235 114236 114237 114238 114239 114240 114241 114242 114243 114244 114245 114246 114247 114248 114249 | for(i=0; i<nTerm; i++){ Expr *pCExpr = sqlite3ExprSkipCollate(pList->a[i].pExpr); assert( pCExpr!=0 ); sqlite3StringToId(pCExpr); if( pCExpr->op==TK_ID ){ const char *zCName = pCExpr->u.zToken; for(iCol=0; iCol<pTab->nCol; iCol++){ if( sqlite3StrICmp(zCName, pTab->aCol[iCol].zCnName)==0 ){ pCol = &pTab->aCol[iCol]; makeColumnPartOfPrimaryKey(pParse, pCol); break; } } } } } if( nTerm==1 && pCol && pCol->eType==COLTYPE_INTEGER && sortOrder!=SQLITE_SO_DESC ){ if( IN_RENAME_OBJECT && pList ){ Expr *pCExpr = sqlite3ExprSkipCollate(pList->a[0].pExpr); sqlite3RenameTokenRemap(pParse, &pTab->iPKey, pCExpr); } pTab->iPKey = iCol; |
︙ | ︙ | |||
114189 114190 114191 114192 114193 114194 114195 | i = p->nCol-1; db = pParse->db; zColl = sqlite3NameFromToken(db, pToken); if( !zColl ) return; if( sqlite3LocateCollSeq(pParse, zColl) ){ Index *pIdx; | < | | < < > | | | | 114315 114316 114317 114318 114319 114320 114321 114322 114323 114324 114325 114326 114327 114328 114329 114330 114331 114332 114333 114334 114335 114336 114337 114338 114339 114340 114341 114342 114343 114344 114345 114346 114347 114348 114349 114350 114351 114352 114353 114354 114355 114356 114357 114358 114359 114360 114361 114362 114363 114364 114365 114366 114367 114368 114369 114370 114371 114372 114373 114374 114375 114376 114377 114378 114379 114380 114381 114382 114383 114384 114385 114386 | i = p->nCol-1; db = pParse->db; zColl = sqlite3NameFromToken(db, pToken); if( !zColl ) return; if( sqlite3LocateCollSeq(pParse, zColl) ){ Index *pIdx; sqlite3ColumnSetColl(db, &p->aCol[i], zColl); /* If the column is declared as "<name> PRIMARY KEY COLLATE <type>", ** then an index may have been created on this column before the ** collation type was added. Correct this if it is the case. */ for(pIdx=p->pIndex; pIdx; pIdx=pIdx->pNext){ assert( pIdx->nKeyCol==1 ); if( pIdx->aiColumn[0]==i ){ pIdx->azColl[0] = sqlite3ColumnColl(&p->aCol[i]); } } } sqlite3DbFree(db, zColl); } /* Change the most recently parsed column to be a GENERATED ALWAYS AS ** column. */ SQLITE_PRIVATE void sqlite3AddGenerated(Parse *pParse, Expr *pExpr, Token *pType){ #ifndef SQLITE_OMIT_GENERATED_COLUMNS u8 eType = COLFLAG_VIRTUAL; Table *pTab = pParse->pNewTable; Column *pCol; if( pTab==0 ){ /* generated column in an CREATE TABLE IF NOT EXISTS that already exists */ goto generated_done; } pCol = &(pTab->aCol[pTab->nCol-1]); if( IN_DECLARE_VTAB ){ sqlite3ErrorMsg(pParse, "virtual tables cannot use computed columns"); goto generated_done; } if( pCol->iDflt>0 ) goto generated_error; if( pType ){ if( pType->n==7 && sqlite3StrNICmp("virtual",pType->z,7)==0 ){ /* no-op */ }else if( pType->n==6 && sqlite3StrNICmp("stored",pType->z,6)==0 ){ eType = COLFLAG_STORED; }else{ goto generated_error; } } if( eType==COLFLAG_VIRTUAL ) pTab->nNVCol--; pCol->colFlags |= eType; assert( TF_HasVirtual==COLFLAG_VIRTUAL ); assert( TF_HasStored==COLFLAG_STORED ); pTab->tabFlags |= eType; if( pCol->colFlags & COLFLAG_PRIMKEY ){ makeColumnPartOfPrimaryKey(pParse, pCol); /* For the error message */ } sqlite3ColumnSetExpr(pParse, pTab, pCol, pExpr); pExpr = 0; goto generated_done; generated_error: sqlite3ErrorMsg(pParse, "error in generated column \"%s\"", pCol->zCnName); generated_done: sqlite3ExprDelete(pParse->db, pExpr); #else /* Throw and error for the GENERATED ALWAYS AS clause if the ** SQLITE_OMIT_GENERATED_COLUMNS compile-time option is used. */ sqlite3ErrorMsg(pParse, "generated columns not supported"); sqlite3ExprDelete(pParse->db, pExpr); |
︙ | ︙ | |||
114350 114351 114352 114353 114354 114355 114356 | static char *createTableStmt(sqlite3 *db, Table *p){ int i, k, n; char *zStmt; char *zSep, *zSep2, *zEnd; Column *pCol; n = 0; for(pCol = p->aCol, i=0; i<p->nCol; i++, pCol++){ | | | 114474 114475 114476 114477 114478 114479 114480 114481 114482 114483 114484 114485 114486 114487 114488 | static char *createTableStmt(sqlite3 *db, Table *p){ int i, k, n; char *zStmt; char *zSep, *zSep2, *zEnd; Column *pCol; n = 0; for(pCol = p->aCol, i=0; i<p->nCol; i++, pCol++){ n += identLength(pCol->zCnName) + 5; } n += identLength(p->zName); if( n<50 ){ zSep = ""; zSep2 = ","; zEnd = ")"; }else{ |
︙ | ︙ | |||
114386 114387 114388 114389 114390 114391 114392 | }; int len; const char *zType; sqlite3_snprintf(n-k, &zStmt[k], zSep); k += sqlite3Strlen30(&zStmt[k]); zSep = zSep2; | | | 114510 114511 114512 114513 114514 114515 114516 114517 114518 114519 114520 114521 114522 114523 114524 | }; int len; const char *zType; sqlite3_snprintf(n-k, &zStmt[k], zSep); k += sqlite3Strlen30(&zStmt[k]); zSep = zSep2; identPut(zStmt, &k, pCol->zCnName); assert( pCol->affinity-SQLITE_AFF_BLOB >= 0 ); assert( pCol->affinity-SQLITE_AFF_BLOB < ArraySize(azType) ); testcase( pCol->affinity==SQLITE_AFF_BLOB ); testcase( pCol->affinity==SQLITE_AFF_TEXT ); testcase( pCol->affinity==SQLITE_AFF_NUMERIC ); testcase( pCol->affinity==SQLITE_AFF_INTEGER ); testcase( pCol->affinity==SQLITE_AFF_REAL ); |
︙ | ︙ | |||
114605 114606 114607 114608 114609 114610 114611 | /* Locate the PRIMARY KEY index. Or, if this table was originally ** an INTEGER PRIMARY KEY table, create a new PRIMARY KEY index. */ if( pTab->iPKey>=0 ){ ExprList *pList; Token ipkToken; | | | 114729 114730 114731 114732 114733 114734 114735 114736 114737 114738 114739 114740 114741 114742 114743 | /* Locate the PRIMARY KEY index. Or, if this table was originally ** an INTEGER PRIMARY KEY table, create a new PRIMARY KEY index. */ if( pTab->iPKey>=0 ){ ExprList *pList; Token ipkToken; sqlite3TokenInit(&ipkToken, pTab->aCol[pTab->iPKey].zCnName); pList = sqlite3ExprListAppend(pParse, 0, sqlite3ExprAlloc(db, TK_ID, &ipkToken, 0)); if( pList==0 ){ pTab->tabFlags &= ~TF_WithoutRowid; return; } if( IN_RENAME_OBJECT ){ |
︙ | ︙ | |||
114735 114736 114737 114738 114739 114740 114741 | int nName; /* Length of zName */ Module *pMod; /* Module for the virtual table */ if( !IsVirtual(pTab) ) return 0; nName = sqlite3Strlen30(pTab->zName); if( sqlite3_strnicmp(zName, pTab->zName, nName)!=0 ) return 0; if( zName[nName]!='_' ) return 0; | | | 114859 114860 114861 114862 114863 114864 114865 114866 114867 114868 114869 114870 114871 114872 114873 | int nName; /* Length of zName */ Module *pMod; /* Module for the virtual table */ if( !IsVirtual(pTab) ) return 0; nName = sqlite3Strlen30(pTab->zName); if( sqlite3_strnicmp(zName, pTab->zName, nName)!=0 ) return 0; if( zName[nName]!='_' ) return 0; pMod = (Module*)sqlite3HashFind(&db->aModule, pTab->u.vtab.azArg[0]); if( pMod==0 ) return 0; if( pMod->pModule->iVersion<3 ) return 0; if( pMod->pModule->xShadowName==0 ) return 0; return pMod->pModule->xShadowName(zName+nName+1); } #endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */ |
︙ | ︙ | |||
114896 114897 114898 114899 114900 114901 114902 | if( p->tabFlags & TF_HasGenerated ){ int ii, nNG = 0; testcase( p->tabFlags & TF_HasVirtual ); testcase( p->tabFlags & TF_HasStored ); for(ii=0; ii<p->nCol; ii++){ u32 colFlags = p->aCol[ii].colFlags; if( (colFlags & COLFLAG_GENERATED)!=0 ){ | | | | | 115020 115021 115022 115023 115024 115025 115026 115027 115028 115029 115030 115031 115032 115033 115034 115035 115036 115037 115038 115039 115040 115041 115042 115043 115044 115045 | if( p->tabFlags & TF_HasGenerated ){ int ii, nNG = 0; testcase( p->tabFlags & TF_HasVirtual ); testcase( p->tabFlags & TF_HasStored ); for(ii=0; ii<p->nCol; ii++){ u32 colFlags = p->aCol[ii].colFlags; if( (colFlags & COLFLAG_GENERATED)!=0 ){ Expr *pX = sqlite3ColumnExpr(p, &p->aCol[ii]); testcase( colFlags & COLFLAG_VIRTUAL ); testcase( colFlags & COLFLAG_STORED ); if( sqlite3ResolveSelfReference(pParse, p, NC_GenCol, pX, 0) ){ /* If there are errors in resolving the expression, change the ** expression to a NULL. This prevents code generators that operate ** on the expression from inserting extra parts into the expression ** tree that have been allocated from lookaside memory, which is ** illegal in a schema and will lead to errors or heap corruption ** when the database connection closes. */ sqlite3ColumnSetExpr(pParse, p, &p->aCol[ii], sqlite3ExprAlloc(db, TK_NULL, 0, 0)); } }else{ nNG++; } } if( nNG==0 ){ sqlite3ErrorMsg(pParse, "must have at least one non-generated column"); |
︙ | ︙ | |||
114947 114948 114949 114950 114951 114952 114953 | if( NEVER(v==0) ) return; sqlite3VdbeAddOp1(v, OP_Close, 0); /* ** Initialize zType for the new view or table. */ | | | 115071 115072 115073 115074 115075 115076 115077 115078 115079 115080 115081 115082 115083 115084 115085 | if( NEVER(v==0) ) return; sqlite3VdbeAddOp1(v, OP_Close, 0); /* ** Initialize zType for the new view or table. */ if( IsOrdinaryTable(p) ){ /* A regular table */ zType = "table"; zType2 = "TABLE"; #ifndef SQLITE_OMIT_VIEW }else{ /* A view */ zType = "view"; |
︙ | ︙ | |||
115097 115098 115099 115100 115101 115102 115103 | assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); p->pSchema->pSeqTab = p; } #endif } #ifndef SQLITE_OMIT_ALTERTABLE | | | | 115221 115222 115223 115224 115225 115226 115227 115228 115229 115230 115231 115232 115233 115234 115235 115236 115237 115238 115239 115240 | assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); p->pSchema->pSeqTab = p; } #endif } #ifndef SQLITE_OMIT_ALTERTABLE if( !pSelect && IsOrdinaryTable(p) ){ assert( pCons && pEnd ); if( pCons->z==0 ){ pCons = pEnd; } p->u.tab.addColOffset = 13 + (int)(pCons->z - pParse->sNameToken.z); } #endif } #ifndef SQLITE_OMIT_VIEW /* ** The parser calls this routine in order to create a new VIEW |
︙ | ︙ | |||
115159 115160 115161 115162 115163 115164 115165 | /* Make a copy of the entire SELECT statement that defines the view. ** This will force all the Expr.token.z values to be dynamically ** allocated rather than point to the input string - which means that ** they will persist after the current sqlite3_exec() call returns. */ pSelect->selFlags |= SF_View; if( IN_RENAME_OBJECT ){ | | | > | 115283 115284 115285 115286 115287 115288 115289 115290 115291 115292 115293 115294 115295 115296 115297 115298 115299 115300 115301 115302 115303 | /* Make a copy of the entire SELECT statement that defines the view. ** This will force all the Expr.token.z values to be dynamically ** allocated rather than point to the input string - which means that ** they will persist after the current sqlite3_exec() call returns. */ pSelect->selFlags |= SF_View; if( IN_RENAME_OBJECT ){ p->u.view.pSelect = pSelect; pSelect = 0; }else{ p->u.view.pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE); } p->pCheck = sqlite3ExprListDup(db, pCNames, EXPRDUP_REDUCE); p->eTabType = TABTYP_VIEW; if( db->mallocFailed ) goto create_view_fail; /* Locate the end of the CREATE VIEW statement. Make sEnd point to ** the end. */ sEnd = pParse->sLastToken; assert( sEnd.z[0]!=0 || sEnd.n==0 ); |
︙ | ︙ | |||
115261 115262 115263 115264 115265 115266 115267 | /* If we get this far, it means we need to compute the table names. ** Note that the call to sqlite3ResultSetOfSelect() will expand any ** "*" elements in the results set of the view and will assign cursors ** to the elements of the FROM clause. But we do not want these changes ** to be permanent. So the computation is done on a copy of the SELECT ** statement that defines the view. */ | | | | 115386 115387 115388 115389 115390 115391 115392 115393 115394 115395 115396 115397 115398 115399 115400 115401 | /* If we get this far, it means we need to compute the table names. ** Note that the call to sqlite3ResultSetOfSelect() will expand any ** "*" elements in the results set of the view and will assign cursors ** to the elements of the FROM clause. But we do not want these changes ** to be permanent. So the computation is done on a copy of the SELECT ** statement that defines the view. */ assert( IsView(pTable) ); pSel = sqlite3SelectDup(db, pTable->u.view.pSelect, 0); if( pSel ){ u8 eParseMode = pParse->eParseMode; pParse->eParseMode = PARSE_MODE_NORMAL; n = pParse->nTab; sqlite3SrcListAssignCursors(pParse, pSel->pSrc); pTable->nCol = -1; DisableLookaside; |
︙ | ︙ | |||
115321 115322 115323 115324 115325 115326 115327 | pParse->eParseMode = eParseMode; } else { nErr++; } pTable->pSchema->schemaFlags |= DB_UnresetViews; if( db->mallocFailed ){ sqlite3DeleteColumnNames(db, pTable); | < < | < < | 115446 115447 115448 115449 115450 115451 115452 115453 115454 115455 115456 115457 115458 115459 115460 115461 115462 115463 115464 115465 115466 115467 115468 115469 115470 115471 115472 115473 115474 115475 115476 115477 | pParse->eParseMode = eParseMode; } else { nErr++; } pTable->pSchema->schemaFlags |= DB_UnresetViews; if( db->mallocFailed ){ sqlite3DeleteColumnNames(db, pTable); } #endif /* SQLITE_OMIT_VIEW */ return nErr; } #endif /* !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) */ #ifndef SQLITE_OMIT_VIEW /* ** Clear the column names from every VIEW in database idx. */ static void sqliteViewResetAll(sqlite3 *db, int idx){ HashElem *i; assert( sqlite3SchemaMutexHeld(db, idx, 0) ); if( !DbHasProperty(db, idx, DB_UnresetViews) ) return; for(i=sqliteHashFirst(&db->aDb[idx].pSchema->tblHash); i;i=sqliteHashNext(i)){ Table *pTab = sqliteHashData(i); if( IsView(pTab) ){ sqlite3DeleteColumnNames(db, pTab); } } DbClearProperty(db, idx, DB_UnresetViews); } #else # define sqliteViewResetAll(A,B) #endif /* SQLITE_OMIT_VIEW */ |
︙ | ︙ | |||
115579 115580 115581 115582 115583 115584 115585 115586 115587 115588 115589 115590 115591 115592 | ** context. */ SQLITE_PRIVATE int sqlite3ReadOnlyShadowTables(sqlite3 *db){ #ifndef SQLITE_OMIT_VIRTUALTABLE if( (db->flags & SQLITE_Defensive)!=0 && db->pVtabCtx==0 && db->nVdbeExec==0 ){ return 1; } #endif return 0; } | > | 115700 115701 115702 115703 115704 115705 115706 115707 115708 115709 115710 115711 115712 115713 115714 | ** context. */ SQLITE_PRIVATE int sqlite3ReadOnlyShadowTables(sqlite3 *db){ #ifndef SQLITE_OMIT_VIRTUALTABLE if( (db->flags & SQLITE_Defensive)!=0 && db->pVtabCtx==0 && db->nVdbeExec==0 && !sqlite3VtabInSync(db) ){ return 1; } #endif return 0; } |
︙ | ︙ | |||
115682 115683 115684 115685 115686 115687 115688 | goto exit_drop_table; } #ifndef SQLITE_OMIT_VIEW /* Ensure DROP TABLE is not used on a view, and DROP VIEW is not used ** on a table. */ | | | | 115804 115805 115806 115807 115808 115809 115810 115811 115812 115813 115814 115815 115816 115817 115818 115819 115820 115821 115822 | goto exit_drop_table; } #ifndef SQLITE_OMIT_VIEW /* Ensure DROP TABLE is not used on a view, and DROP VIEW is not used ** on a table. */ if( isView && !IsView(pTab) ){ sqlite3ErrorMsg(pParse, "use DROP TABLE to delete table %s", pTab->zName); goto exit_drop_table; } if( !isView && IsView(pTab) ){ sqlite3ErrorMsg(pParse, "use DROP VIEW to delete view %s", pTab->zName); goto exit_drop_table; } #endif /* Generate code to remove the table from the schema table ** on disk. |
︙ | ︙ | |||
115750 115751 115752 115753 115754 115755 115756 | if( p==0 || IN_DECLARE_VTAB ) goto fk_end; if( pFromCol==0 ){ int iCol = p->nCol-1; if( NEVER(iCol<0) ) goto fk_end; if( pToCol && pToCol->nExpr!=1 ){ sqlite3ErrorMsg(pParse, "foreign key on %s" " should reference only one column of table %T", | | | 115872 115873 115874 115875 115876 115877 115878 115879 115880 115881 115882 115883 115884 115885 115886 | if( p==0 || IN_DECLARE_VTAB ) goto fk_end; if( pFromCol==0 ){ int iCol = p->nCol-1; if( NEVER(iCol<0) ) goto fk_end; if( pToCol && pToCol->nExpr!=1 ){ sqlite3ErrorMsg(pParse, "foreign key on %s" " should reference only one column of table %T", p->aCol[iCol].zCnName, pTo); goto fk_end; } nCol = 1; }else if( pToCol && pToCol->nExpr!=pFromCol->nExpr ){ sqlite3ErrorMsg(pParse, "number of columns in foreign key does not match the number of " "columns in the referenced table"); |
︙ | ︙ | |||
115773 115774 115775 115776 115777 115778 115779 | } } pFKey = sqlite3DbMallocZero(db, nByte ); if( pFKey==0 ){ goto fk_end; } pFKey->pFrom = p; | | | | 115895 115896 115897 115898 115899 115900 115901 115902 115903 115904 115905 115906 115907 115908 115909 115910 115911 115912 115913 115914 115915 115916 115917 115918 115919 115920 115921 115922 115923 115924 115925 115926 | } } pFKey = sqlite3DbMallocZero(db, nByte ); if( pFKey==0 ){ goto fk_end; } pFKey->pFrom = p; pFKey->pNextFrom = p->u.tab.pFKey; z = (char*)&pFKey->aCol[nCol]; pFKey->zTo = z; if( IN_RENAME_OBJECT ){ sqlite3RenameTokenMap(pParse, (void*)z, pTo); } memcpy(z, pTo->z, pTo->n); z[pTo->n] = 0; sqlite3Dequote(z); z += pTo->n+1; pFKey->nCol = nCol; if( pFromCol==0 ){ pFKey->aCol[0].iFrom = p->nCol-1; }else{ for(i=0; i<nCol; i++){ int j; for(j=0; j<p->nCol; j++){ if( sqlite3StrICmp(p->aCol[j].zCnName, pFromCol->a[i].zEName)==0 ){ pFKey->aCol[i].iFrom = j; break; } } if( j>=p->nCol ){ sqlite3ErrorMsg(pParse, "unknown column \"%s\" in foreign key definition", |
︙ | ︙ | |||
115838 115839 115840 115841 115842 115843 115844 | assert( pNextTo->pPrevTo==0 ); pFKey->pNextTo = pNextTo; pNextTo->pPrevTo = pFKey; } /* Link the foreign key to the table as the last step. */ | > | | > > | 115960 115961 115962 115963 115964 115965 115966 115967 115968 115969 115970 115971 115972 115973 115974 115975 115976 115977 115978 115979 115980 115981 115982 115983 115984 115985 115986 115987 115988 115989 115990 115991 115992 115993 115994 115995 115996 115997 115998 | assert( pNextTo->pPrevTo==0 ); pFKey->pNextTo = pNextTo; pNextTo->pPrevTo = pFKey; } /* Link the foreign key to the table as the last step. */ assert( !IsVirtual(p) ); p->u.tab.pFKey = pFKey; pFKey = 0; fk_end: sqlite3DbFree(db, pFKey); #endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */ sqlite3ExprListDelete(db, pFromCol); sqlite3ExprListDelete(db, pToCol); } /* ** This routine is called when an INITIALLY IMMEDIATE or INITIALLY DEFERRED ** clause is seen as part of a foreign key definition. The isDeferred ** parameter is 1 for INITIALLY DEFERRED and 0 for INITIALLY IMMEDIATE. ** The behavior of the most recently created foreign key is adjusted ** accordingly. */ SQLITE_PRIVATE void sqlite3DeferForeignKey(Parse *pParse, int isDeferred){ #ifndef SQLITE_OMIT_FOREIGN_KEY Table *pTab; FKey *pFKey; if( (pTab = pParse->pNewTable)==0 ) return; if( NEVER(IsVirtual(pTab)) ) return; if( (pFKey = pTab->u.tab.pFKey)==0 ) return; assert( isDeferred==0 || isDeferred==1 ); /* EV: R-30323-21917 */ pFKey->isDeferred = (u8)isDeferred; #endif } /* ** Generate code that will erase and refill index *pIdx. This is |
︙ | ︙ | |||
116151 116152 116153 116154 116155 116156 116157 | && sqlite3UserAuthTable(pTab->zName)==0 #endif ){ sqlite3ErrorMsg(pParse, "table %s may not be indexed", pTab->zName); goto exit_create_index; } #ifndef SQLITE_OMIT_VIEW | | | 116276 116277 116278 116279 116280 116281 116282 116283 116284 116285 116286 116287 116288 116289 116290 | && sqlite3UserAuthTable(pTab->zName)==0 #endif ){ sqlite3ErrorMsg(pParse, "table %s may not be indexed", pTab->zName); goto exit_create_index; } #ifndef SQLITE_OMIT_VIEW if( IsView(pTab) ){ sqlite3ErrorMsg(pParse, "views may not be indexed"); goto exit_create_index; } #endif #ifndef SQLITE_OMIT_VIRTUALTABLE if( IsVirtual(pTab) ){ sqlite3ErrorMsg(pParse, "virtual tables may not be indexed"); |
︙ | ︙ | |||
116242 116243 116244 116245 116246 116247 116248 | ** key out of the last column added to the table under construction. ** So create a fake list to simulate this. */ if( pList==0 ){ Token prevCol; Column *pCol = &pTab->aCol[pTab->nCol-1]; pCol->colFlags |= COLFLAG_UNIQUE; | | | 116367 116368 116369 116370 116371 116372 116373 116374 116375 116376 116377 116378 116379 116380 116381 | ** key out of the last column added to the table under construction. ** So create a fake list to simulate this. */ if( pList==0 ){ Token prevCol; Column *pCol = &pTab->aCol[pTab->nCol-1]; pCol->colFlags |= COLFLAG_UNIQUE; sqlite3TokenInit(&prevCol, pCol->zCnName); pList = sqlite3ExprListAppend(pParse, 0, sqlite3ExprAlloc(db, TK_ID, &prevCol, 0)); if( pList==0 ) goto exit_create_index; assert( pList->nExpr==1 ); sqlite3ExprListSetSortOrder(pList, sortOrder, SQLITE_SO_UNDEFINED); }else{ sqlite3ExprListCheckLength(pParse, pList, "index"); |
︙ | ︙ | |||
116363 116364 116365 116366 116367 116368 116369 | nColl = sqlite3Strlen30(zColl) + 1; assert( nExtra>=nColl ); memcpy(zExtra, zColl, nColl); zColl = zExtra; zExtra += nColl; nExtra -= nColl; }else if( j>=0 ){ | | | 116488 116489 116490 116491 116492 116493 116494 116495 116496 116497 116498 116499 116500 116501 116502 | nColl = sqlite3Strlen30(zColl) + 1; assert( nExtra>=nColl ); memcpy(zExtra, zColl, nColl); zColl = zExtra; zExtra += nColl; nExtra -= nColl; }else if( j>=0 ){ zColl = sqlite3ColumnColl(&pTab->aCol[j]); } if( !zColl ) zColl = sqlite3StrBINARY; if( !db->init.busy && !sqlite3LocateCollSeq(pParse, zColl) ){ goto exit_create_index; } pIndex->azColl[i] = zColl; requestedSortOrder = pListItem->sortFlags & sortOrderMask; |
︙ | ︙ | |||
117455 117456 117457 117458 117459 117460 117461 | pParse->db->aLimit[SQLITE_LIMIT_LENGTH]); if( pIdx->aColExpr ){ sqlite3_str_appendf(&errMsg, "index '%q'", pIdx->zName); }else{ for(j=0; j<pIdx->nKeyCol; j++){ char *zCol; assert( pIdx->aiColumn[j]>=0 ); | | | 117580 117581 117582 117583 117584 117585 117586 117587 117588 117589 117590 117591 117592 117593 117594 | pParse->db->aLimit[SQLITE_LIMIT_LENGTH]); if( pIdx->aColExpr ){ sqlite3_str_appendf(&errMsg, "index '%q'", pIdx->zName); }else{ for(j=0; j<pIdx->nKeyCol; j++){ char *zCol; assert( pIdx->aiColumn[j]>=0 ); zCol = pTab->aCol[pIdx->aiColumn[j]].zCnName; if( j ) sqlite3_str_append(&errMsg, ", ", 2); sqlite3_str_appendall(&errMsg, pTab->zName); sqlite3_str_append(&errMsg, ".", 1); sqlite3_str_appendall(&errMsg, zCol); } } zErr = sqlite3StrAccumFinish(&errMsg); |
︙ | ︙ | |||
117482 117483 117484 117485 117486 117487 117488 | int onError, /* Conflict resolution algorithm */ Table *pTab /* The table with the non-unique rowid */ ){ char *zMsg; int rc; if( pTab->iPKey>=0 ){ zMsg = sqlite3MPrintf(pParse->db, "%s.%s", pTab->zName, | | | 117607 117608 117609 117610 117611 117612 117613 117614 117615 117616 117617 117618 117619 117620 117621 | int onError, /* Conflict resolution algorithm */ Table *pTab /* The table with the non-unique rowid */ ){ char *zMsg; int rc; if( pTab->iPKey>=0 ){ zMsg = sqlite3MPrintf(pParse->db, "%s.%s", pTab->zName, pTab->aCol[pTab->iPKey].zCnName); rc = SQLITE_CONSTRAINT_PRIMARYKEY; }else{ zMsg = sqlite3MPrintf(pParse->db, "%s.rowid", pTab->zName); rc = SQLITE_CONSTRAINT_ROWID; } sqlite3HaltConstraint(pParse, rc, onError, zMsg, P4_DYNAMIC, P5_ConstraintUnique); |
︙ | ︙ | |||
118409 118410 118411 118412 118413 118414 118415 | */ SQLITE_PRIVATE int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){ if( tabIsReadOnly(pParse, pTab) ){ sqlite3ErrorMsg(pParse, "table %s may not be modified", pTab->zName); return 1; } #ifndef SQLITE_OMIT_VIEW | | | 118534 118535 118536 118537 118538 118539 118540 118541 118542 118543 118544 118545 118546 118547 118548 | */ SQLITE_PRIVATE int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){ if( tabIsReadOnly(pParse, pTab) ){ sqlite3ErrorMsg(pParse, "table %s may not be modified", pTab->zName); return 1; } #ifndef SQLITE_OMIT_VIEW if( !viewOk && IsView(pTab) ){ sqlite3ErrorMsg(pParse,"cannot modify %s because it is a view",pTab->zName); return 1; } #endif return 0; } |
︙ | ︙ | |||
118513 118514 118515 118516 118517 118518 118519 | pLhs = sqlite3PExpr(pParse, TK_ROW, 0, 0); pEList = sqlite3ExprListAppend( pParse, 0, sqlite3PExpr(pParse, TK_ROW, 0, 0) ); }else{ Index *pPk = sqlite3PrimaryKeyIndex(pTab); if( pPk->nKeyCol==1 ){ | | | | 118638 118639 118640 118641 118642 118643 118644 118645 118646 118647 118648 118649 118650 118651 118652 118653 118654 118655 118656 118657 118658 | pLhs = sqlite3PExpr(pParse, TK_ROW, 0, 0); pEList = sqlite3ExprListAppend( pParse, 0, sqlite3PExpr(pParse, TK_ROW, 0, 0) ); }else{ Index *pPk = sqlite3PrimaryKeyIndex(pTab); if( pPk->nKeyCol==1 ){ const char *zName = pTab->aCol[pPk->aiColumn[0]].zCnName; pLhs = sqlite3Expr(db, TK_ID, zName); pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db, TK_ID, zName)); }else{ int i; for(i=0; i<pPk->nKeyCol; i++){ Expr *p = sqlite3Expr(db, TK_ID, pTab->aCol[pPk->aiColumn[i]].zCnName); pEList = sqlite3ExprListAppend(pParse, pEList, p); } pLhs = sqlite3PExpr(pParse, TK_VECTOR, 0, 0); if( pLhs ){ pLhs->x.pList = sqlite3ExprListDup(db, pEList, 0); } } |
︙ | ︙ | |||
118626 118627 118628 118629 118630 118631 118632 | if( pTab==0 ) goto delete_from_cleanup; /* Figure out if we have any triggers and if the table being ** deleted from is a view */ #ifndef SQLITE_OMIT_TRIGGER pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0); | | | 118751 118752 118753 118754 118755 118756 118757 118758 118759 118760 118761 118762 118763 118764 118765 | if( pTab==0 ) goto delete_from_cleanup; /* Figure out if we have any triggers and if the table being ** deleted from is a view */ #ifndef SQLITE_OMIT_TRIGGER pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0); isView = IsView(pTab); #else # define pTrigger 0 # define isView 0 #endif bComplex = pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0); #ifdef SQLITE_OMIT_VIEW # undef isView |
︙ | ︙ | |||
118876 118877 118878 118879 118880 118881 118882 | /* Set up a loop over the rowids/primary-keys that were found in the ** where-clause loop above. */ if( eOnePass!=ONEPASS_OFF ){ assert( nKey==nPk ); /* OP_Found will use an unpacked key */ if( !IsVirtual(pTab) && aToOpen[iDataCur-iTabCur] ){ | | | 119001 119002 119003 119004 119005 119006 119007 119008 119009 119010 119011 119012 119013 119014 119015 | /* Set up a loop over the rowids/primary-keys that were found in the ** where-clause loop above. */ if( eOnePass!=ONEPASS_OFF ){ assert( nKey==nPk ); /* OP_Found will use an unpacked key */ if( !IsVirtual(pTab) && aToOpen[iDataCur-iTabCur] ){ assert( pPk!=0 || IsView(pTab) ); sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, addrBypass, iKey, nKey); VdbeCoverage(v); } }else if( pPk ){ addrLoop = sqlite3VdbeAddOp1(v, OP_Rewind, iEphCur); VdbeCoverage(v); if( IsVirtual(pTab) ){ sqlite3VdbeAddOp3(v, OP_Column, iEphCur, 0, iKey); |
︙ | ︙ | |||
119110 119111 119112 119113 119114 119115 119116 | ** ** If variable 'count' is non-zero, then this OP_Delete instruction should ** invoke the update-hook. The pre-update-hook, on the other hand should ** be invoked unless table pTab is a system table. The difference is that ** the update-hook is not invoked for rows removed by REPLACE, but the ** pre-update-hook is. */ | | | 119235 119236 119237 119238 119239 119240 119241 119242 119243 119244 119245 119246 119247 119248 119249 | ** ** If variable 'count' is non-zero, then this OP_Delete instruction should ** invoke the update-hook. The pre-update-hook, on the other hand should ** be invoked unless table pTab is a system table. The difference is that ** the update-hook is not invoked for rows removed by REPLACE, but the ** pre-update-hook is. */ if( !IsView(pTab) ){ u8 p5 = 0; sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur,0,iIdxNoSeek); sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, (count?OPFLAG_NCHANGE:0)); if( pParse->nested==0 || 0==sqlite3_stricmp(pTab->zName, "sqlite_stat1") ){ sqlite3VdbeAppendP4(v, (char*)pTab, P4_TABLE); } if( eMode!=ONEPASS_OFF ){ |
︙ | ︙ | |||
119871 119872 119873 119874 119875 119876 119877 | sqlite3_result_int64(context, sqlite3_last_insert_rowid(db)); } /* ** Implementation of the changes() SQL function. ** ** IMP: R-62073-11209 The changes() SQL function is a wrapper | | | | | | | 119996 119997 119998 119999 120000 120001 120002 120003 120004 120005 120006 120007 120008 120009 120010 120011 120012 120013 120014 120015 120016 120017 120018 120019 120020 120021 120022 120023 120024 120025 120026 120027 120028 120029 120030 120031 120032 120033 120034 120035 120036 | sqlite3_result_int64(context, sqlite3_last_insert_rowid(db)); } /* ** Implementation of the changes() SQL function. ** ** IMP: R-62073-11209 The changes() SQL function is a wrapper ** around the sqlite3_changes64() C/C++ function and hence follows the same ** rules for counting changes. */ static void changes( sqlite3_context *context, int NotUsed, sqlite3_value **NotUsed2 ){ sqlite3 *db = sqlite3_context_db_handle(context); UNUSED_PARAMETER2(NotUsed, NotUsed2); sqlite3_result_int64(context, sqlite3_changes64(db)); } /* ** Implementation of the total_changes() SQL function. The return value is ** the same as the sqlite3_total_changes64() API function. */ static void total_changes( sqlite3_context *context, int NotUsed, sqlite3_value **NotUsed2 ){ sqlite3 *db = sqlite3_context_db_handle(context); UNUSED_PARAMETER2(NotUsed, NotUsed2); /* IMP: R-52756-41993 This function was a wrapper around the ** sqlite3_total_changes() C/C++ interface. */ sqlite3_result_int64(context, sqlite3_total_changes64(db)); } /* ** A structure defining how to do GLOB-style comparisons. */ struct compareInfo { u8 matchAll; /* "*" or "%" */ |
︙ | ︙ | |||
120615 120616 120617 120618 120619 120620 120621 | static void trimFunc( sqlite3_context *context, int argc, sqlite3_value **argv ){ const unsigned char *zIn; /* Input string */ const unsigned char *zCharSet; /* Set of characters to trim */ | | | | | | | > | | | | | 120740 120741 120742 120743 120744 120745 120746 120747 120748 120749 120750 120751 120752 120753 120754 120755 120756 120757 120758 120759 120760 120761 120762 120763 120764 120765 120766 120767 120768 120769 120770 120771 120772 120773 120774 120775 120776 120777 120778 120779 120780 120781 120782 120783 120784 120785 120786 120787 120788 120789 120790 120791 120792 120793 120794 120795 120796 120797 120798 120799 120800 120801 120802 120803 120804 120805 120806 120807 120808 120809 120810 120811 120812 | static void trimFunc( sqlite3_context *context, int argc, sqlite3_value **argv ){ const unsigned char *zIn; /* Input string */ const unsigned char *zCharSet; /* Set of characters to trim */ unsigned int nIn; /* Number of bytes in input */ int flags; /* 1: trimleft 2: trimright 3: trim */ int i; /* Loop counter */ unsigned int *aLen = 0; /* Length of each character in zCharSet */ unsigned char **azChar = 0; /* Individual characters in zCharSet */ int nChar; /* Number of characters in zCharSet */ if( sqlite3_value_type(argv[0])==SQLITE_NULL ){ return; } zIn = sqlite3_value_text(argv[0]); if( zIn==0 ) return; nIn = (unsigned)sqlite3_value_bytes(argv[0]); assert( zIn==sqlite3_value_text(argv[0]) ); if( argc==1 ){ static const unsigned lenOne[] = { 1 }; static unsigned char * const azOne[] = { (u8*)" " }; nChar = 1; aLen = (unsigned*)lenOne; azChar = (unsigned char **)azOne; zCharSet = 0; }else if( (zCharSet = sqlite3_value_text(argv[1]))==0 ){ return; }else{ const unsigned char *z; for(z=zCharSet, nChar=0; *z; nChar++){ SQLITE_SKIP_UTF8(z); } if( nChar>0 ){ azChar = contextMalloc(context, ((i64)nChar)*(sizeof(char*)+sizeof(unsigned))); if( azChar==0 ){ return; } aLen = (unsigned*)&azChar[nChar]; for(z=zCharSet, nChar=0; *z; nChar++){ azChar[nChar] = (unsigned char *)z; SQLITE_SKIP_UTF8(z); aLen[nChar] = (unsigned)(z - azChar[nChar]); } } } if( nChar>0 ){ flags = SQLITE_PTR_TO_INT(sqlite3_user_data(context)); if( flags & 1 ){ while( nIn>0 ){ unsigned int len = 0; for(i=0; i<nChar; i++){ len = aLen[i]; if( len<=nIn && memcmp(zIn, azChar[i], len)==0 ) break; } if( i>=nChar ) break; zIn += len; nIn -= len; } } if( flags & 2 ){ while( nIn>0 ){ unsigned int len = 0; for(i=0; i<nChar; i++){ len = aLen[i]; if( len<=nIn && memcmp(&zIn[nIn-len],azChar[i],len)==0 ) break; } if( i>=nChar ) break; nIn -= len; } |
︙ | ︙ | |||
121458 121459 121460 121461 121462 121463 121464 | FUNCTION(rtrim, 1, 2, 0, trimFunc ), FUNCTION(rtrim, 2, 2, 0, trimFunc ), FUNCTION(trim, 1, 3, 0, trimFunc ), FUNCTION(trim, 2, 3, 0, trimFunc ), FUNCTION(min, -1, 0, 1, minmaxFunc ), FUNCTION(min, 0, 0, 1, 0 ), WAGGREGATE(min, 1, 0, 1, minmaxStep, minMaxFinalize, minMaxValue, 0, | | | | 121584 121585 121586 121587 121588 121589 121590 121591 121592 121593 121594 121595 121596 121597 121598 121599 121600 121601 121602 | FUNCTION(rtrim, 1, 2, 0, trimFunc ), FUNCTION(rtrim, 2, 2, 0, trimFunc ), FUNCTION(trim, 1, 3, 0, trimFunc ), FUNCTION(trim, 2, 3, 0, trimFunc ), FUNCTION(min, -1, 0, 1, minmaxFunc ), FUNCTION(min, 0, 0, 1, 0 ), WAGGREGATE(min, 1, 0, 1, minmaxStep, minMaxFinalize, minMaxValue, 0, SQLITE_FUNC_MINMAX|SQLITE_FUNC_ANYORDER ), FUNCTION(max, -1, 1, 1, minmaxFunc ), FUNCTION(max, 0, 1, 1, 0 ), WAGGREGATE(max, 1, 1, 1, minmaxStep, minMaxFinalize, minMaxValue, 0, SQLITE_FUNC_MINMAX|SQLITE_FUNC_ANYORDER ), FUNCTION2(typeof, 1, 0, 0, typeofFunc, SQLITE_FUNC_TYPEOF), FUNCTION2(length, 1, 0, 0, lengthFunc, SQLITE_FUNC_LENGTH), FUNCTION(instr, 2, 0, 0, instrFunc ), FUNCTION(printf, -1, 0, 0, printfFunc ), FUNCTION(unicode, 1, 0, 0, unicodeFunc ), FUNCTION(char, -1, 0, 0, charFunc ), FUNCTION(abs, 1, 0, 0, absFunc ), |
︙ | ︙ | |||
121498 121499 121500 121501 121502 121503 121504 | FUNCTION(substr, 3, 0, 0, substrFunc ), FUNCTION(substring, 2, 0, 0, substrFunc ), FUNCTION(substring, 3, 0, 0, substrFunc ), WAGGREGATE(sum, 1,0,0, sumStep, sumFinalize, sumFinalize, sumInverse, 0), WAGGREGATE(total, 1,0,0, sumStep,totalFinalize,totalFinalize,sumInverse, 0), WAGGREGATE(avg, 1,0,0, sumStep, avgFinalize, avgFinalize, sumInverse, 0), WAGGREGATE(count, 0,0,0, countStep, | | > | | 121624 121625 121626 121627 121628 121629 121630 121631 121632 121633 121634 121635 121636 121637 121638 121639 121640 121641 | FUNCTION(substr, 3, 0, 0, substrFunc ), FUNCTION(substring, 2, 0, 0, substrFunc ), FUNCTION(substring, 3, 0, 0, substrFunc ), WAGGREGATE(sum, 1,0,0, sumStep, sumFinalize, sumFinalize, sumInverse, 0), WAGGREGATE(total, 1,0,0, sumStep,totalFinalize,totalFinalize,sumInverse, 0), WAGGREGATE(avg, 1,0,0, sumStep, avgFinalize, avgFinalize, sumInverse, 0), WAGGREGATE(count, 0,0,0, countStep, countFinalize, countFinalize, countInverse, SQLITE_FUNC_COUNT|SQLITE_FUNC_ANYORDER ), WAGGREGATE(count, 1,0,0, countStep, countFinalize, countFinalize, countInverse, SQLITE_FUNC_ANYORDER ), WAGGREGATE(group_concat, 1, 0, 0, groupConcatStep, groupConcatFinalize, groupConcatValue, groupConcatInverse, 0), WAGGREGATE(group_concat, 2, 0, 0, groupConcatStep, groupConcatFinalize, groupConcatValue, groupConcatInverse, 0), LIKEFUNC(glob, 2, &globInfo, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE), #ifdef SQLITE_CASE_SENSITIVE_LIKE |
︙ | ︙ | |||
121802 121803 121804 121805 121806 121807 121808 | ** 1) There is an INTEGER PRIMARY KEY column and the FK is implicitly ** mapped to the primary key of table pParent, or ** 2) The FK is explicitly mapped to a column declared as INTEGER ** PRIMARY KEY. */ if( pParent->iPKey>=0 ){ if( !zKey ) return 0; | | > > | 121929 121930 121931 121932 121933 121934 121935 121936 121937 121938 121939 121940 121941 121942 121943 121944 121945 | ** 1) There is an INTEGER PRIMARY KEY column and the FK is implicitly ** mapped to the primary key of table pParent, or ** 2) The FK is explicitly mapped to a column declared as INTEGER ** PRIMARY KEY. */ if( pParent->iPKey>=0 ){ if( !zKey ) return 0; if( !sqlite3StrICmp(pParent->aCol[pParent->iPKey].zCnName, zKey) ){ return 0; } } }else if( paiCol ){ assert( nCol>1 ); aiCol = (int *)sqlite3DbMallocRawNN(pParse->db, nCol*sizeof(int)); if( !aiCol ) return 1; *paiCol = aiCol; } |
︙ | ︙ | |||
121844 121845 121846 121847 121848 121849 121850 | char *zIdxCol; /* Name of indexed column */ if( iCol<0 ) break; /* No foreign keys against expression indexes */ /* If the index uses a collation sequence that is different from ** the default collation sequence for the column, this index is ** unusable. Bail out early in this case. */ | | | | 121973 121974 121975 121976 121977 121978 121979 121980 121981 121982 121983 121984 121985 121986 121987 121988 121989 121990 121991 | char *zIdxCol; /* Name of indexed column */ if( iCol<0 ) break; /* No foreign keys against expression indexes */ /* If the index uses a collation sequence that is different from ** the default collation sequence for the column, this index is ** unusable. Bail out early in this case. */ zDfltColl = sqlite3ColumnColl(&pParent->aCol[iCol]); if( !zDfltColl ) zDfltColl = sqlite3StrBINARY; if( sqlite3StrICmp(pIdx->azColl[i], zDfltColl) ) break; zIdxCol = pParent->aCol[iCol].zCnName; for(j=0; j<nCol; j++){ if( sqlite3StrICmp(pFKey->aCol[j].zCol, zIdxCol)==0 ){ if( aiCol ) aiCol[i] = pFKey->aCol[j].iFrom; break; } } if( j==nCol ) break; |
︙ | ︙ | |||
122072 122073 122074 122075 122076 122077 122078 | pExpr = sqlite3Expr(db, TK_REGISTER, 0); if( pExpr ){ if( iCol>=0 && iCol!=pTab->iPKey ){ pCol = &pTab->aCol[iCol]; pExpr->iTable = regBase + sqlite3TableColumnToStorage(pTab,iCol) + 1; pExpr->affExpr = pCol->affinity; | | | 122201 122202 122203 122204 122205 122206 122207 122208 122209 122210 122211 122212 122213 122214 122215 | pExpr = sqlite3Expr(db, TK_REGISTER, 0); if( pExpr ){ if( iCol>=0 && iCol!=pTab->iPKey ){ pCol = &pTab->aCol[iCol]; pExpr->iTable = regBase + sqlite3TableColumnToStorage(pTab,iCol) + 1; pExpr->affExpr = pCol->affinity; zColl = sqlite3ColumnColl(pCol); if( zColl==0 ) zColl = db->pDfltColl->zName; pExpr = sqlite3ExprAddCollateString(pParse, pExpr, zColl); }else{ pExpr->iTable = regBase; pExpr->affExpr = SQLITE_AFF_INTEGER; } } |
︙ | ︙ | |||
122181 122182 122183 122184 122185 122186 122187 | i16 iCol; /* Index of column in child table */ const char *zCol; /* Name of column in child table */ iCol = pIdx ? pIdx->aiColumn[i] : -1; pLeft = exprTableRegister(pParse, pTab, regData, iCol); iCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom; assert( iCol>=0 ); | | | 122310 122311 122312 122313 122314 122315 122316 122317 122318 122319 122320 122321 122322 122323 122324 | i16 iCol; /* Index of column in child table */ const char *zCol; /* Name of column in child table */ iCol = pIdx ? pIdx->aiColumn[i] : -1; pLeft = exprTableRegister(pParse, pTab, regData, iCol); iCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom; assert( iCol>=0 ); zCol = pFKey->pFrom->aCol[iCol].zCnName; pRight = sqlite3Expr(db, TK_ID, zCol); pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight); pWhere = sqlite3ExprAnd(pParse, pWhere, pEq); } /* If the child table is the same as the parent table, then add terms ** to the WHERE clause that prevent this entry from being scanned. |
︙ | ︙ | |||
122216 122217 122218 122219 122220 122221 122222 | }else{ Expr *pEq, *pAll = 0; assert( pIdx!=0 ); for(i=0; i<pIdx->nKeyCol; i++){ i16 iCol = pIdx->aiColumn[i]; assert( iCol>=0 ); pLeft = exprTableRegister(pParse, pTab, regData, iCol); | | | 122345 122346 122347 122348 122349 122350 122351 122352 122353 122354 122355 122356 122357 122358 122359 | }else{ Expr *pEq, *pAll = 0; assert( pIdx!=0 ); for(i=0; i<pIdx->nKeyCol; i++){ i16 iCol = pIdx->aiColumn[i]; assert( iCol>=0 ); pLeft = exprTableRegister(pParse, pTab, regData, iCol); pRight = sqlite3Expr(db, TK_ID, pTab->aCol[iCol].zCnName); pEq = sqlite3PExpr(pParse, TK_IS, pLeft, pRight); pAll = sqlite3ExprAnd(pParse, pAll, pEq); } pNe = sqlite3PExpr(pParse, TK_NOT, pAll, 0); } pWhere = sqlite3ExprAnd(pParse, pWhere, pNe); } |
︙ | ︙ | |||
122310 122311 122312 122313 122314 122315 122316 | SQLITE_PRIVATE void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTab){ sqlite3 *db = pParse->db; if( (db->flags&SQLITE_ForeignKeys) && !IsVirtual(pTab) ){ int iSkip = 0; Vdbe *v = sqlite3GetVdbe(pParse); assert( v ); /* VDBE has already been allocated */ | | > | | 122439 122440 122441 122442 122443 122444 122445 122446 122447 122448 122449 122450 122451 122452 122453 122454 122455 122456 122457 122458 122459 122460 122461 122462 | SQLITE_PRIVATE void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTab){ sqlite3 *db = pParse->db; if( (db->flags&SQLITE_ForeignKeys) && !IsVirtual(pTab) ){ int iSkip = 0; Vdbe *v = sqlite3GetVdbe(pParse); assert( v ); /* VDBE has already been allocated */ assert( !IsView(pTab) ); /* Not a view */ assert( !IsVirtual(pTab) ); if( sqlite3FkReferences(pTab)==0 ){ /* Search for a deferred foreign key constraint for which this table ** is the child table. If one cannot be found, return without ** generating any VDBE code. If one can be found, then jump over ** the entire DELETE if there are no outstanding deferred constraints ** when this statement is run. */ FKey *p; for(p=pTab->u.tab.pFKey; p; p=p->pNextFrom){ if( p->isDeferred || (db->flags & SQLITE_DeferFKs) ) break; } if( !p ) return; iSkip = sqlite3VdbeMakeLabel(pParse); sqlite3VdbeAddOp2(v, OP_FkIfZero, 1, iSkip); VdbeCoverage(v); } |
︙ | ︙ | |||
122407 122408 122409 122410 122411 122412 122413 | for(i=0; i<p->nCol; i++){ char *zKey = p->aCol[i].zCol; int iKey; for(iKey=0; iKey<pTab->nCol; iKey++){ if( aChange[iKey]>=0 || (iKey==pTab->iPKey && bChngRowid) ){ Column *pCol = &pTab->aCol[iKey]; if( zKey ){ | | | 122537 122538 122539 122540 122541 122542 122543 122544 122545 122546 122547 122548 122549 122550 122551 | for(i=0; i<p->nCol; i++){ char *zKey = p->aCol[i].zCol; int iKey; for(iKey=0; iKey<pTab->nCol; iKey++){ if( aChange[iKey]>=0 || (iKey==pTab->iPKey && bChngRowid) ){ Column *pCol = &pTab->aCol[iKey]; if( zKey ){ if( 0==sqlite3StrICmp(pCol->zCnName, zKey) ) return 1; }else if( pCol->colFlags & COLFLAG_PRIMKEY ){ return 1; } } } } return 0; |
︙ | ︙ | |||
122480 122481 122482 122483 122484 122485 122486 | if( (db->flags&SQLITE_ForeignKeys)==0 ) return; iDb = sqlite3SchemaToIndex(db, pTab->pSchema); zDb = db->aDb[iDb].zDbSName; /* Loop through all the foreign key constraints for which pTab is the ** child table (the table that the foreign key definition is part of). */ | > | | 122610 122611 122612 122613 122614 122615 122616 122617 122618 122619 122620 122621 122622 122623 122624 122625 | if( (db->flags&SQLITE_ForeignKeys)==0 ) return; iDb = sqlite3SchemaToIndex(db, pTab->pSchema); zDb = db->aDb[iDb].zDbSName; /* Loop through all the foreign key constraints for which pTab is the ** child table (the table that the foreign key definition is part of). */ assert( !IsVirtual(pTab) ); for(pFKey=pTab->u.tab.pFKey; pFKey; pFKey=pFKey->pNextFrom){ Table *pTo; /* Parent table of foreign key pFKey */ Index *pIdx = 0; /* Index on key columns in pTo */ int *aiFree = 0; int *aiCol; int iCol; int i; int bIgnore = 0; |
︙ | ︙ | |||
122547 122548 122549 122550 122551 122552 122553 | assert( pIdx==0 || pIdx->aiColumn[i]>=0 ); #ifndef SQLITE_OMIT_AUTHORIZATION /* Request permission to read the parent key columns. If the ** authorization callback returns SQLITE_IGNORE, behave as if any ** values read from the parent table are NULL. */ if( db->xAuth ){ int rcauth; | | | 122678 122679 122680 122681 122682 122683 122684 122685 122686 122687 122688 122689 122690 122691 122692 | assert( pIdx==0 || pIdx->aiColumn[i]>=0 ); #ifndef SQLITE_OMIT_AUTHORIZATION /* Request permission to read the parent key columns. If the ** authorization callback returns SQLITE_IGNORE, behave as if any ** values read from the parent table are NULL. */ if( db->xAuth ){ int rcauth; char *zCol = pTo->aCol[pIdx ? pIdx->aiColumn[i] : pTo->iPKey].zCnName; rcauth = sqlite3AuthReadCol(pParse, pTo->zName, zCol, iDb); bIgnore = (rcauth==SQLITE_IGNORE); } #endif } /* Take a shared-cache advisory read-lock on the parent table. Allocate |
︙ | ︙ | |||
122665 122666 122667 122668 122669 122670 122671 | Parse *pParse, /* Parse context */ Table *pTab /* Table being modified */ ){ u32 mask = 0; if( pParse->db->flags&SQLITE_ForeignKeys ){ FKey *p; int i; | > | | 122796 122797 122798 122799 122800 122801 122802 122803 122804 122805 122806 122807 122808 122809 122810 122811 | Parse *pParse, /* Parse context */ Table *pTab /* Table being modified */ ){ u32 mask = 0; if( pParse->db->flags&SQLITE_ForeignKeys ){ FKey *p; int i; assert( !IsVirtual(pTab) ); for(p=pTab->u.tab.pFKey; p; p=p->pNextFrom){ for(i=0; i<p->nCol; i++) mask |= COLUMN_MASK(p->aCol[i].iFrom); } for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){ Index *pIdx = 0; sqlite3FkLocateIndex(pParse, pTab, p, &pIdx, 0); if( pIdx ){ for(i=0; i<pIdx->nKeyCol; i++){ |
︙ | ︙ | |||
122715 122716 122717 122718 122719 122720 122721 | Parse *pParse, /* Parse context */ Table *pTab, /* Table being modified */ int *aChange, /* Non-NULL for UPDATE operations */ int chngRowid /* True for UPDATE that affects rowid */ ){ int eRet = 1; /* Value to return if bHaveFK is true */ int bHaveFK = 0; /* If FK processing is required */ | | | | | 122847 122848 122849 122850 122851 122852 122853 122854 122855 122856 122857 122858 122859 122860 122861 122862 122863 122864 122865 122866 122867 122868 122869 122870 122871 122872 122873 | Parse *pParse, /* Parse context */ Table *pTab, /* Table being modified */ int *aChange, /* Non-NULL for UPDATE operations */ int chngRowid /* True for UPDATE that affects rowid */ ){ int eRet = 1; /* Value to return if bHaveFK is true */ int bHaveFK = 0; /* If FK processing is required */ if( pParse->db->flags&SQLITE_ForeignKeys && !IsVirtual(pTab) ){ if( !aChange ){ /* A DELETE operation. Foreign key processing is required if the ** table in question is either the child or parent table for any ** foreign key constraint. */ bHaveFK = (sqlite3FkReferences(pTab) || pTab->u.tab.pFKey); }else{ /* This is an UPDATE. Foreign key processing is only required if the ** operation modifies one or more child or parent key columns. */ FKey *p; /* Check if any child key columns are being modified. */ for(p=pTab->u.tab.pFKey; p; p=p->pNextFrom){ if( fkChildIsModified(pTab, p, aChange, chngRowid) ){ if( 0==sqlite3_stricmp(pTab->zName, p->zTo) ) eRet = 2; bHaveFK = 1; } } /* Check if any parent key columns are being modified. */ |
︙ | ︙ | |||
122820 122821 122822 122823 122824 122825 122826 | Expr *pEq; /* tFromCol = OLD.tToCol */ iFromCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom; assert( iFromCol>=0 ); assert( pIdx!=0 || (pTab->iPKey>=0 && pTab->iPKey<pTab->nCol) ); assert( pIdx==0 || pIdx->aiColumn[i]>=0 ); sqlite3TokenInit(&tToCol, | | | | 122952 122953 122954 122955 122956 122957 122958 122959 122960 122961 122962 122963 122964 122965 122966 122967 | Expr *pEq; /* tFromCol = OLD.tToCol */ iFromCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom; assert( iFromCol>=0 ); assert( pIdx!=0 || (pTab->iPKey>=0 && pTab->iPKey<pTab->nCol) ); assert( pIdx==0 || pIdx->aiColumn[i]>=0 ); sqlite3TokenInit(&tToCol, pTab->aCol[pIdx ? pIdx->aiColumn[i] : pTab->iPKey].zCnName); sqlite3TokenInit(&tFromCol, pFKey->pFrom->aCol[iFromCol].zCnName); /* Create the expression "OLD.zToCol = zFromCol". It is important ** that the "OLD.zToCol" term is on the LHS of the = operator, so ** that the affinity and collation sequence associated with the ** parent table are used for the comparison. */ pEq = sqlite3PExpr(pParse, TK_EQ, sqlite3PExpr(pParse, TK_DOT, |
︙ | ︙ | |||
122866 122867 122868 122869 122870 122871 122872 | Column *pCol = pFKey->pFrom->aCol + iFromCol; Expr *pDflt; if( pCol->colFlags & COLFLAG_GENERATED ){ testcase( pCol->colFlags & COLFLAG_VIRTUAL ); testcase( pCol->colFlags & COLFLAG_STORED ); pDflt = 0; }else{ | | | 122998 122999 123000 123001 123002 123003 123004 123005 123006 123007 123008 123009 123010 123011 123012 | Column *pCol = pFKey->pFrom->aCol + iFromCol; Expr *pDflt; if( pCol->colFlags & COLFLAG_GENERATED ){ testcase( pCol->colFlags & COLFLAG_VIRTUAL ); testcase( pCol->colFlags & COLFLAG_STORED ); pDflt = 0; }else{ pDflt = sqlite3ColumnExpr(pFKey->pFrom, pCol); } if( pDflt ){ pNew = sqlite3ExprDup(db, pDflt, 0); }else{ pNew = sqlite3ExprAlloc(db, TK_NULL, 0, 0); } }else{ |
︙ | ︙ | |||
123003 123004 123005 123006 123007 123008 123009 | ** table pTab. Remove the deleted foreign keys from the Schema.fkeyHash ** hash table. */ SQLITE_PRIVATE void sqlite3FkDelete(sqlite3 *db, Table *pTab){ FKey *pFKey; /* Iterator variable */ FKey *pNext; /* Copy of pFKey->pNextFrom */ | | > | < | 123135 123136 123137 123138 123139 123140 123141 123142 123143 123144 123145 123146 123147 123148 123149 123150 123151 | ** table pTab. Remove the deleted foreign keys from the Schema.fkeyHash ** hash table. */ SQLITE_PRIVATE void sqlite3FkDelete(sqlite3 *db, Table *pTab){ FKey *pFKey; /* Iterator variable */ FKey *pNext; /* Copy of pFKey->pNextFrom */ assert( !IsVirtual(pTab) ); for(pFKey=pTab->u.tab.pFKey; pFKey; pFKey=pNext){ assert( db==0 || sqlite3SchemaMutexHeld(db, 0, pTab->pSchema) ); /* Remove the FK from the fkeyHash hash table. */ if( !db || db->pnBytesFreed==0 ){ if( pFKey->pPrevTo ){ pFKey->pPrevTo->pNextTo = pFKey->pNextTo; }else{ void *p = (void *)pFKey->pNextTo; |
︙ | ︙ | |||
123155 123156 123157 123158 123159 123160 123161 | return pIdx->zColAff; } /* ** Compute the affinity string for table pTab, if it has not already been ** computed. As an optimization, omit trailing SQLITE_AFF_BLOB affinities. ** | | | 123287 123288 123289 123290 123291 123292 123293 123294 123295 123296 123297 123298 123299 123300 123301 | return pIdx->zColAff; } /* ** Compute the affinity string for table pTab, if it has not already been ** computed. As an optimization, omit trailing SQLITE_AFF_BLOB affinities. ** ** If the affinity exists (if it is not entirely SQLITE_AFF_BLOB values) and ** if iReg>0 then code an OP_Affinity opcode that will set the affinities ** for register iReg and following. Or if affinities exists and iReg==0, ** then just set the P4 operand of the previous opcode (which should be ** an OP_MakeRecord) to the affinity string. ** ** A column affinity string has one character per column: ** |
︙ | ︙ | |||
123335 123336 123337 123338 123339 123340 123341 | pRedo = 0; for(i=0; i<pTab->nCol; i++){ Column *pCol = pTab->aCol + i; if( (pCol->colFlags & COLFLAG_NOTAVAIL)!=0 ){ int x; pCol->colFlags |= COLFLAG_BUSY; w.eCode = 0; | | | | | 123467 123468 123469 123470 123471 123472 123473 123474 123475 123476 123477 123478 123479 123480 123481 123482 123483 123484 123485 123486 123487 123488 123489 123490 123491 123492 123493 123494 123495 123496 | pRedo = 0; for(i=0; i<pTab->nCol; i++){ Column *pCol = pTab->aCol + i; if( (pCol->colFlags & COLFLAG_NOTAVAIL)!=0 ){ int x; pCol->colFlags |= COLFLAG_BUSY; w.eCode = 0; sqlite3WalkExpr(&w, sqlite3ColumnExpr(pTab, pCol)); pCol->colFlags &= ~COLFLAG_BUSY; if( w.eCode & COLFLAG_NOTAVAIL ){ pRedo = pCol; continue; } eProgress = 1; assert( pCol->colFlags & COLFLAG_GENERATED ); x = sqlite3TableColumnToStorage(pTab, i) + iRegStore; sqlite3ExprCodeGeneratedColumn(pParse, pTab, pCol, x); pCol->colFlags &= ~COLFLAG_NOTAVAIL; } } }while( pRedo && eProgress ); if( pRedo ){ sqlite3ErrorMsg(pParse, "generated column loop on \"%s\"", pRedo->zCnName); } pParse->iSelfTab = 0; } #endif /* SQLITE_OMIT_GENERATED_COLUMNS */ #ifndef SQLITE_OMIT_AUTOINCREMENT |
︙ | ︙ | |||
123745 123746 123747 123748 123749 123750 123751 | withoutRowid = !HasRowid(pTab); /* Figure out if we have any triggers and if the table being ** inserted into is a view */ #ifndef SQLITE_OMIT_TRIGGER pTrigger = sqlite3TriggersExist(pParse, pTab, TK_INSERT, 0, &tmask); | | | 123877 123878 123879 123880 123881 123882 123883 123884 123885 123886 123887 123888 123889 123890 123891 | withoutRowid = !HasRowid(pTab); /* Figure out if we have any triggers and if the table being ** inserted into is a view */ #ifndef SQLITE_OMIT_TRIGGER pTrigger = sqlite3TriggersExist(pParse, pTab, TK_INSERT, 0, &tmask); isView = IsView(pTab); #else # define pTrigger 0 # define tmask 0 # define isView 0 #endif #ifdef SQLITE_OMIT_VIEW # undef isView |
︙ | ︙ | |||
123836 123837 123838 123839 123840 123841 123842 | bIdListInOrder = (pTab->tabFlags & (TF_OOOHidden|TF_HasStored))==0; if( pColumn ){ for(i=0; i<pColumn->nId; i++){ pColumn->a[i].idx = -1; } for(i=0; i<pColumn->nId; i++){ for(j=0; j<pTab->nCol; j++){ | | | | 123968 123969 123970 123971 123972 123973 123974 123975 123976 123977 123978 123979 123980 123981 123982 123983 123984 123985 123986 123987 123988 123989 123990 123991 123992 | bIdListInOrder = (pTab->tabFlags & (TF_OOOHidden|TF_HasStored))==0; if( pColumn ){ for(i=0; i<pColumn->nId; i++){ pColumn->a[i].idx = -1; } for(i=0; i<pColumn->nId; i++){ for(j=0; j<pTab->nCol; j++){ if( sqlite3StrICmp(pColumn->a[i].zName, pTab->aCol[j].zCnName)==0 ){ pColumn->a[i].idx = j; if( i!=j ) bIdListInOrder = 0; if( j==pTab->iPKey ){ ipkColumn = i; assert( !withoutRowid ); } #ifndef SQLITE_OMIT_GENERATED_COLUMNS if( pTab->aCol[j].colFlags & (COLFLAG_STORED|COLFLAG_VIRTUAL) ){ sqlite3ErrorMsg(pParse, "cannot INSERT into generated column \"%s\"", pTab->aCol[j].zCnName); goto insert_cleanup; } #endif break; } } if( j>=pTab->nCol ){ |
︙ | ︙ | |||
124031 124032 124033 124034 124035 124036 124037 | if( pUpsert ){ Upsert *pNx; if( IsVirtual(pTab) ){ sqlite3ErrorMsg(pParse, "UPSERT not implemented for virtual table \"%s\"", pTab->zName); goto insert_cleanup; } | | | 124163 124164 124165 124166 124167 124168 124169 124170 124171 124172 124173 124174 124175 124176 124177 | if( pUpsert ){ Upsert *pNx; if( IsVirtual(pTab) ){ sqlite3ErrorMsg(pParse, "UPSERT not implemented for virtual table \"%s\"", pTab->zName); goto insert_cleanup; } if( IsView(pTab) ){ sqlite3ErrorMsg(pParse, "cannot UPSERT a view"); goto insert_cleanup; } if( sqlite3HasExplicitNulls(pParse, pUpsert->pUpsertTarget) ){ goto insert_cleanup; } pTabList->a[0].iCursor = iDataCur; |
︙ | ︙ | |||
124130 124131 124132 124133 124134 124135 124136 | if( tmask & TRIGGER_BEFORE ){ sqlite3VdbeAddOp1(v, OP_SoftNull, iRegStore); } continue; }else if( pColumn==0 ){ /* Hidden columns that are not explicitly named in the INSERT ** get there default value */ | | > > | > > | > > | 124262 124263 124264 124265 124266 124267 124268 124269 124270 124271 124272 124273 124274 124275 124276 124277 124278 124279 124280 124281 124282 124283 124284 124285 124286 124287 124288 124289 124290 124291 124292 124293 124294 124295 124296 124297 | if( tmask & TRIGGER_BEFORE ){ sqlite3VdbeAddOp1(v, OP_SoftNull, iRegStore); } continue; }else if( pColumn==0 ){ /* Hidden columns that are not explicitly named in the INSERT ** get there default value */ sqlite3ExprCodeFactorable(pParse, sqlite3ColumnExpr(pTab, &pTab->aCol[i]), iRegStore); continue; } } if( pColumn ){ for(j=0; j<pColumn->nId && pColumn->a[j].idx!=i; j++){} if( j>=pColumn->nId ){ /* A column not named in the insert column list gets its ** default value */ sqlite3ExprCodeFactorable(pParse, sqlite3ColumnExpr(pTab, &pTab->aCol[i]), iRegStore); continue; } k = j; }else if( nColumn==0 ){ /* This is INSERT INTO ... DEFAULT VALUES. Load the default value. */ sqlite3ExprCodeFactorable(pParse, sqlite3ColumnExpr(pTab, &pTab->aCol[i]), iRegStore); continue; }else{ k = i - nHidden; } if( useTempTable ){ sqlite3VdbeAddOp3(v, OP_Column, srcTab, k, iRegStore); |
︙ | ︙ | |||
124660 124661 124662 124663 124664 124665 124666 | int nReplaceTrig = 0; /* Number of replace triggers coded */ IndexIterator sIdxIter; /* Index iterator */ isUpdate = regOldData!=0; db = pParse->db; v = pParse->pVdbe; assert( v!=0 ); | | | 124798 124799 124800 124801 124802 124803 124804 124805 124806 124807 124808 124809 124810 124811 124812 | int nReplaceTrig = 0; /* Number of replace triggers coded */ IndexIterator sIdxIter; /* Index iterator */ isUpdate = regOldData!=0; db = pParse->db; v = pParse->pVdbe; assert( v!=0 ); assert( !IsView(pTab) ); /* This table is not a VIEW */ nCol = pTab->nCol; /* pPk is the PRIMARY KEY index for WITHOUT ROWID tables and NULL for ** normal rowid tables. nPkField is the number of key fields in the ** pPk index or 1 for a rowid table. In other words, nPkField is the ** number of fields in the true primary key of the table. */ if( HasRowid(pTab) ){ |
︙ | ︙ | |||
124711 124712 124713 124714 124715 124716 124717 | if( overrideError!=OE_Default ){ onError = overrideError; }else if( onError==OE_Default ){ onError = OE_Abort; } if( onError==OE_Replace ){ if( b2ndPass /* REPLACE becomes ABORT on the 2nd pass */ | | | 124849 124850 124851 124852 124853 124854 124855 124856 124857 124858 124859 124860 124861 124862 124863 | if( overrideError!=OE_Default ){ onError = overrideError; }else if( onError==OE_Default ){ onError = OE_Abort; } if( onError==OE_Replace ){ if( b2ndPass /* REPLACE becomes ABORT on the 2nd pass */ || pCol->iDflt==0 /* REPLACE is ABORT if no DEFAULT value */ ){ testcase( pCol->colFlags & COLFLAG_VIRTUAL ); testcase( pCol->colFlags & COLFLAG_STORED ); testcase( pCol->colFlags & COLFLAG_GENERATED ); onError = OE_Abort; }else{ assert( !isGenerated ); |
︙ | ︙ | |||
124733 124734 124735 124736 124737 124738 124739 | iReg = sqlite3TableColumnToStorage(pTab, i) + regNewData + 1; switch( onError ){ case OE_Replace: { int addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, iReg); VdbeCoverage(v); assert( (pCol->colFlags & COLFLAG_GENERATED)==0 ); nSeenReplace++; | | > | | 124871 124872 124873 124874 124875 124876 124877 124878 124879 124880 124881 124882 124883 124884 124885 124886 124887 124888 124889 124890 124891 124892 124893 124894 124895 124896 | iReg = sqlite3TableColumnToStorage(pTab, i) + regNewData + 1; switch( onError ){ case OE_Replace: { int addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, iReg); VdbeCoverage(v); assert( (pCol->colFlags & COLFLAG_GENERATED)==0 ); nSeenReplace++; sqlite3ExprCodeCopy(pParse, sqlite3ColumnExpr(pTab, pCol), iReg); sqlite3VdbeJumpHere(v, addr1); break; } case OE_Abort: sqlite3MayAbort(pParse); /* no break */ deliberate_fall_through case OE_Rollback: case OE_Fail: { char *zMsg = sqlite3MPrintf(db, "%s.%s", pTab->zName, pCol->zCnName); sqlite3VdbeAddOp3(v, OP_HaltIfNull, SQLITE_CONSTRAINT_NOTNULL, onError, iReg); sqlite3VdbeAppendP4(v, zMsg, P4_DYNAMIC); sqlite3VdbeChangeP5(v, P5_ConstraintNotNull); VdbeCoverage(v); break; } |
︙ | ︙ | |||
125161 125162 125163 125164 125165 125166 125167 | x = regNewData; sqlite3VdbeAddOp2(v, OP_IntCopy, x, regIdx+i); VdbeComment((v, "rowid")); }else{ testcase( sqlite3TableColumnToStorage(pTab, iField)!=iField ); x = sqlite3TableColumnToStorage(pTab, iField) + regNewData + 1; sqlite3VdbeAddOp2(v, OP_SCopy, x, regIdx+i); | | | 125300 125301 125302 125303 125304 125305 125306 125307 125308 125309 125310 125311 125312 125313 125314 | x = regNewData; sqlite3VdbeAddOp2(v, OP_IntCopy, x, regIdx+i); VdbeComment((v, "rowid")); }else{ testcase( sqlite3TableColumnToStorage(pTab, iField)!=iField ); x = sqlite3TableColumnToStorage(pTab, iField) + regNewData + 1; sqlite3VdbeAddOp2(v, OP_SCopy, x, regIdx+i); VdbeComment((v, "%s", pTab->aCol[iField].zCnName)); } } sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn, aRegIdx[ix]); VdbeComment((v, "for %s", pIdx->zName)); #ifdef SQLITE_ENABLE_NULL_TRIM if( pIdx->idxType==SQLITE_IDXTYPE_PRIMARYKEY ){ sqlite3SetMakeRecordP5(v, pIdx->pTable); |
︙ | ︙ | |||
125220 125221 125222 125223 125224 125225 125226 | #ifndef SQLITE_ENABLE_PREUPDATE_HOOK if( (ix==0 && pIdx->pNext==0) /* Condition 3 */ && pPk==pIdx /* Condition 2 */ && onError==OE_Replace /* Condition 1 */ && ( 0==(db->flags&SQLITE_RecTriggers) || /* Condition 4 */ 0==sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0)) && ( 0==(db->flags&SQLITE_ForeignKeys) || /* Condition 5 */ | | | 125359 125360 125361 125362 125363 125364 125365 125366 125367 125368 125369 125370 125371 125372 125373 | #ifndef SQLITE_ENABLE_PREUPDATE_HOOK if( (ix==0 && pIdx->pNext==0) /* Condition 3 */ && pPk==pIdx /* Condition 2 */ && onError==OE_Replace /* Condition 1 */ && ( 0==(db->flags&SQLITE_RecTriggers) || /* Condition 4 */ 0==sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0)) && ( 0==(db->flags&SQLITE_ForeignKeys) || /* Condition 5 */ (0==pTab->u.tab.pFKey && 0==sqlite3FkReferences(pTab))) ){ sqlite3VdbeResolveLabel(v, addrUniqueOk); continue; } #endif /* ifndef SQLITE_ENABLE_PREUPDATE_HOOK */ /* Check to see if the new index entry will be unique */ |
︙ | ︙ | |||
125255 125256 125257 125258 125259 125260 125261 | ** store it in registers regR..regR+nPk-1 */ if( pIdx!=pPk ){ for(i=0; i<pPk->nKeyCol; i++){ assert( pPk->aiColumn[i]>=0 ); x = sqlite3TableColumnToIndex(pIdx, pPk->aiColumn[i]); sqlite3VdbeAddOp3(v, OP_Column, iThisCur, x, regR+i); VdbeComment((v, "%s.%s", pTab->zName, | | | 125394 125395 125396 125397 125398 125399 125400 125401 125402 125403 125404 125405 125406 125407 125408 | ** store it in registers regR..regR+nPk-1 */ if( pIdx!=pPk ){ for(i=0; i<pPk->nKeyCol; i++){ assert( pPk->aiColumn[i]>=0 ); x = sqlite3TableColumnToIndex(pIdx, pPk->aiColumn[i]); sqlite3VdbeAddOp3(v, OP_Column, iThisCur, x, regR+i); VdbeComment((v, "%s.%s", pTab->zName, pTab->aCol[pPk->aiColumn[i]].zCnName)); } } if( isUpdate ){ /* If currently processing the PRIMARY KEY of a WITHOUT ROWID ** table, only conflict if the new PRIMARY KEY values are actually ** different from the old. ** |
︙ | ︙ | |||
125454 125455 125456 125457 125458 125459 125460 | u16 i; /* Records with omitted columns are only allowed for schema format ** version 2 and later (SQLite version 3.1.4, 2005-02-20). */ if( pTab->pSchema->file_format<2 ) return; for(i=pTab->nCol-1; i>0; i--){ | | | 125593 125594 125595 125596 125597 125598 125599 125600 125601 125602 125603 125604 125605 125606 125607 | u16 i; /* Records with omitted columns are only allowed for schema format ** version 2 and later (SQLite version 3.1.4, 2005-02-20). */ if( pTab->pSchema->file_format<2 ) return; for(i=pTab->nCol-1; i>0; i--){ if( pTab->aCol[i].iDflt!=0 ) break; if( pTab->aCol[i].colFlags & COLFLAG_PRIMKEY ) break; } sqlite3VdbeChangeP5(v, i+1); } #endif /* |
︙ | ︙ | |||
125519 125520 125521 125522 125523 125524 125525 | assert( update_flags==0 || update_flags==OPFLAG_ISUPDATE || update_flags==(OPFLAG_ISUPDATE|OPFLAG_SAVEPOSITION) ); v = pParse->pVdbe; assert( v!=0 ); | | | 125658 125659 125660 125661 125662 125663 125664 125665 125666 125667 125668 125669 125670 125671 125672 | assert( update_flags==0 || update_flags==OPFLAG_ISUPDATE || update_flags==(OPFLAG_ISUPDATE|OPFLAG_SAVEPOSITION) ); v = pParse->pVdbe; assert( v!=0 ); assert( !IsView(pTab) ); /* This table is not a VIEW */ for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ /* All REPLACE indexes are at the end of the list */ assert( pIdx->onError!=OE_Replace || pIdx->pNext==0 || pIdx->pNext->onError==OE_Replace ); if( aRegIdx[i]==0 ) continue; if( pIdx->pPartIdxWhere ){ |
︙ | ︙ | |||
125821 125822 125823 125824 125825 125826 125827 | if( pSrc->tnum==pDest->tnum && pSrc->pSchema==pDest->pSchema ){ testcase( pSrc!=pDest ); /* Possible due to bad sqlite_schema.rootpage */ return 0; /* tab1 and tab2 may not be the same table */ } if( HasRowid(pDest)!=HasRowid(pSrc) ){ return 0; /* source and destination must both be WITHOUT ROWID or not */ } | < | < < < < | | 125960 125961 125962 125963 125964 125965 125966 125967 125968 125969 125970 125971 125972 125973 125974 125975 | if( pSrc->tnum==pDest->tnum && pSrc->pSchema==pDest->pSchema ){ testcase( pSrc!=pDest ); /* Possible due to bad sqlite_schema.rootpage */ return 0; /* tab1 and tab2 may not be the same table */ } if( HasRowid(pDest)!=HasRowid(pSrc) ){ return 0; /* source and destination must both be WITHOUT ROWID or not */ } if( !IsOrdinaryTable(pSrc) ){ return 0; /* tab2 may not be a view or virtual table */ } if( pDest->nCol!=pSrc->nCol ){ return 0; /* Number of columns must be the same in tab1 and tab2 */ } if( pDest->iPKey!=pSrc->iPKey ){ return 0; /* Both tables must have the same INTEGER PRIMARY KEY */ } |
︙ | ︙ | |||
125871 125872 125873 125874 125875 125876 125877 | return 0; /* Both columns have the same generated-column type */ } /* But the transfer is only allowed if both the source and destination ** tables have the exact same expressions for generated columns. ** This requirement could be relaxed for VIRTUAL columns, I suppose. */ if( (pDestCol->colFlags & COLFLAG_GENERATED)!=0 ){ | | > > | > > > | | | | | | 126005 126006 126007 126008 126009 126010 126011 126012 126013 126014 126015 126016 126017 126018 126019 126020 126021 126022 126023 126024 126025 126026 126027 126028 126029 126030 126031 126032 126033 126034 126035 126036 126037 126038 126039 126040 126041 126042 126043 126044 126045 126046 | return 0; /* Both columns have the same generated-column type */ } /* But the transfer is only allowed if both the source and destination ** tables have the exact same expressions for generated columns. ** This requirement could be relaxed for VIRTUAL columns, I suppose. */ if( (pDestCol->colFlags & COLFLAG_GENERATED)!=0 ){ if( sqlite3ExprCompare(0, sqlite3ColumnExpr(pSrc, pSrcCol), sqlite3ColumnExpr(pDest, pDestCol), -1)!=0 ){ testcase( pDestCol->colFlags & COLFLAG_VIRTUAL ); testcase( pDestCol->colFlags & COLFLAG_STORED ); return 0; /* Different generator expressions */ } } #endif if( pDestCol->affinity!=pSrcCol->affinity ){ return 0; /* Affinity must be the same on all columns */ } if( sqlite3_stricmp(sqlite3ColumnColl(pDestCol), sqlite3ColumnColl(pSrcCol))!=0 ){ return 0; /* Collating sequence must be the same on all columns */ } if( pDestCol->notNull && !pSrcCol->notNull ){ return 0; /* tab2 must be NOT NULL if tab1 is */ } /* Default values for second and subsequent columns need to match. */ if( (pDestCol->colFlags & COLFLAG_GENERATED)==0 && i>0 ){ Expr *pDestExpr = sqlite3ColumnExpr(pDest, pDestCol); Expr *pSrcExpr = sqlite3ColumnExpr(pSrc, pSrcCol); assert( pDestExpr==0 || pDestExpr->op==TK_SPAN ); assert( pSrcExpr==0 || pSrcExpr->op==TK_SPAN ); if( (pDestExpr==0)!=(pSrcExpr==0) || (pDestExpr!=0 && strcmp(pDestExpr->u.zToken, pSrcExpr->u.zToken)!=0) ){ return 0; /* Default values must be the same for all columns */ } } } for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){ if( IsUniqueIndex(pDestIdx) ){ |
︙ | ︙ | |||
125930 125931 125932 125933 125934 125935 125936 | /* Disallow the transfer optimization if the destination table constains ** any foreign key constraints. This is more restrictive than necessary. ** But the main beneficiary of the transfer optimization is the VACUUM ** command, and the VACUUM command disables foreign key constraints. So ** the extra complication to make this rule less restrictive is probably ** not worth the effort. Ticket [6284df89debdfa61db8073e062908af0c9b6118e] */ | | | 126069 126070 126071 126072 126073 126074 126075 126076 126077 126078 126079 126080 126081 126082 126083 | /* Disallow the transfer optimization if the destination table constains ** any foreign key constraints. This is more restrictive than necessary. ** But the main beneficiary of the transfer optimization is the VACUUM ** command, and the VACUUM command disables foreign key constraints. So ** the extra complication to make this rule less restrictive is probably ** not worth the effort. Ticket [6284df89debdfa61db8073e062908af0c9b6118e] */ if( (db->flags & SQLITE_ForeignKeys)!=0 && pDest->u.tab.pFKey!=0 ){ return 0; } #endif if( (db->flags & SQLITE_CountRows)!=0 ){ return 0; /* xfer opt does not play well with PRAGMA count_changes */ } |
︙ | ︙ | |||
126608 126609 126610 126611 126612 126613 126614 126615 126616 126617 126618 126619 126620 126621 | /* Version 3.32.0 and later */ char *(*create_filename)(const char*,const char*,const char*, int,const char**); void (*free_filename)(char*); sqlite3_file *(*database_file_object)(const char*); /* Version 3.34.0 and later */ int (*txn_state)(sqlite3*,const char*); }; /* ** This is the function signature used for all extension entry points. It ** is also defined in the file "loadext.c". */ typedef int (*sqlite3_loadext_entry)( | > > > | 126747 126748 126749 126750 126751 126752 126753 126754 126755 126756 126757 126758 126759 126760 126761 126762 126763 | /* Version 3.32.0 and later */ char *(*create_filename)(const char*,const char*,const char*, int,const char**); void (*free_filename)(char*); sqlite3_file *(*database_file_object)(const char*); /* Version 3.34.0 and later */ int (*txn_state)(sqlite3*,const char*); /* Version 3.36.1 and later */ sqlite3_int64 (*changes64)(sqlite3*); sqlite3_int64 (*total_changes64)(sqlite3*); }; /* ** This is the function signature used for all extension entry points. It ** is also defined in the file "loadext.c". */ typedef int (*sqlite3_loadext_entry)( |
︙ | ︙ | |||
127398 127399 127400 127401 127402 127403 127404 127405 127406 127407 127408 127409 127410 127411 | sqlite3_filename_wal, /* Version 3.32.0 and later */ sqlite3_create_filename, sqlite3_free_filename, sqlite3_database_file_object, /* Version 3.34.0 and later */ sqlite3_txn_state, }; /* True if x is the directory separator character */ #if SQLITE_OS_WIN # define DirSep(X) ((X)=='/'||(X)=='\\') #else | > > > | 127540 127541 127542 127543 127544 127545 127546 127547 127548 127549 127550 127551 127552 127553 127554 127555 127556 | sqlite3_filename_wal, /* Version 3.32.0 and later */ sqlite3_create_filename, sqlite3_free_filename, sqlite3_database_file_object, /* Version 3.34.0 and later */ sqlite3_txn_state, /* Version 3.36.1 and later */ sqlite3_changes64, sqlite3_total_changes64, }; /* True if x is the directory separator character */ #if SQLITE_OS_WIN # define DirSep(X) ((X)=='/'||(X)=='\\') #else |
︙ | ︙ | |||
128187 128188 128189 128190 128191 128192 128193 | /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, /* ColNames: */ 15, 6, /* iArg: */ 1 }, #endif #if !defined(SQLITE_OMIT_INTEGRITY_CHECK) {/* zName: */ "integrity_check", /* ePragTyp: */ PragTyp_INTEGRITY_CHECK, | | | 128332 128333 128334 128335 128336 128337 128338 128339 128340 128341 128342 128343 128344 128345 128346 | /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, /* ColNames: */ 15, 6, /* iArg: */ 1 }, #endif #if !defined(SQLITE_OMIT_INTEGRITY_CHECK) {/* zName: */ "integrity_check", /* ePragTyp: */ PragTyp_INTEGRITY_CHECK, /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_Result1|PragFlg_SchemaOpt, /* ColNames: */ 0, 0, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) {/* zName: */ "journal_mode", /* ePragTyp: */ PragTyp_JOURNAL_MODE, /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq, |
︙ | ︙ | |||
128295 128296 128297 128298 128299 128300 128301 | /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, /* ColNames: */ 0, 0, /* iArg: */ SQLITE_QueryOnly }, #endif #if !defined(SQLITE_OMIT_INTEGRITY_CHECK) {/* zName: */ "quick_check", /* ePragTyp: */ PragTyp_INTEGRITY_CHECK, | | | 128440 128441 128442 128443 128444 128445 128446 128447 128448 128449 128450 128451 128452 128453 128454 | /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, /* ColNames: */ 0, 0, /* iArg: */ SQLITE_QueryOnly }, #endif #if !defined(SQLITE_OMIT_INTEGRITY_CHECK) {/* zName: */ "quick_check", /* ePragTyp: */ PragTyp_INTEGRITY_CHECK, /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_Result1|PragFlg_SchemaOpt, /* ColNames: */ 0, 0, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) {/* zName: */ "read_uncommitted", /* ePragTyp: */ PragTyp_FLAG, /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, |
︙ | ︙ | |||
129614 129615 129616 129617 129618 129619 129620 | if( (pCol->colFlags & COLFLAG_PRIMKEY)==0 ){ k = 0; }else if( pPk==0 ){ k = 1; }else{ for(k=1; k<=pTab->nCol && pPk->aiColumn[k-1]!=i; k++){} } | > > | | > | | 129759 129760 129761 129762 129763 129764 129765 129766 129767 129768 129769 129770 129771 129772 129773 129774 129775 129776 129777 129778 129779 129780 129781 129782 | if( (pCol->colFlags & COLFLAG_PRIMKEY)==0 ){ k = 0; }else if( pPk==0 ){ k = 1; }else{ for(k=1; k<=pTab->nCol && pPk->aiColumn[k-1]!=i; k++){} } assert( sqlite3ColumnExpr(pTab,pCol)==0 || sqlite3ColumnExpr(pTab,pCol)->op==TK_SPAN || isHidden>=2 ); sqlite3VdbeMultiLoad(v, 1, pPragma->iArg ? "issisii" : "issisi", i-nHidden, pCol->zCnName, sqlite3ColumnType(pCol,""), pCol->notNull ? 1 : 0, isHidden>=2 || sqlite3ColumnExpr(pTab,pCol)==0 ? 0 : sqlite3ColumnExpr(pTab,pCol)->u.zToken, k, isHidden); } } } break; |
︙ | ︙ | |||
129687 129688 129689 129690 129691 129692 129693 | } pTab = pIdx->pTable; sqlite3CodeVerifySchema(pParse, iIdxDb); assert( pParse->nMem<=pPragma->nPragCName ); for(i=0; i<mx; i++){ i16 cnum = pIdx->aiColumn[i]; sqlite3VdbeMultiLoad(v, 1, "iisX", i, cnum, | | | 129835 129836 129837 129838 129839 129840 129841 129842 129843 129844 129845 129846 129847 129848 129849 | } pTab = pIdx->pTable; sqlite3CodeVerifySchema(pParse, iIdxDb); assert( pParse->nMem<=pPragma->nPragCName ); for(i=0; i<mx; i++){ i16 cnum = pIdx->aiColumn[i]; sqlite3VdbeMultiLoad(v, 1, "iisX", i, cnum, cnum<0 ? 0 : pTab->aCol[cnum].zCnName); if( pPragma->iArg ){ sqlite3VdbeMultiLoad(v, 4, "isiX", pIdx->aSortOrder[i], pIdx->azColl[i], i<pIdx->nKeyCol); } sqlite3VdbeAddOp2(v, OP_ResultRow, 1, pParse->nMem); |
︙ | ︙ | |||
129794 129795 129796 129797 129798 129799 129800 | #endif /* SQLITE_OMIT_SCHEMA_PRAGMAS */ #ifndef SQLITE_OMIT_FOREIGN_KEY case PragTyp_FOREIGN_KEY_LIST: if( zRight ){ FKey *pFK; Table *pTab; pTab = sqlite3FindTable(db, zRight, zDb); | | | | | 129942 129943 129944 129945 129946 129947 129948 129949 129950 129951 129952 129953 129954 129955 129956 129957 129958 129959 129960 129961 129962 129963 129964 129965 129966 129967 129968 129969 129970 | #endif /* SQLITE_OMIT_SCHEMA_PRAGMAS */ #ifndef SQLITE_OMIT_FOREIGN_KEY case PragTyp_FOREIGN_KEY_LIST: if( zRight ){ FKey *pFK; Table *pTab; pTab = sqlite3FindTable(db, zRight, zDb); if( pTab && !IsVirtual(pTab) ){ pFK = pTab->u.tab.pFKey; if( pFK ){ int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema); int i = 0; pParse->nMem = 8; sqlite3CodeVerifySchema(pParse, iTabDb); while(pFK){ int j; for(j=0; j<pFK->nCol; j++){ sqlite3VdbeMultiLoad(v, 1, "iissssss", i, j, pFK->zTo, pTab->aCol[pFK->aCol[j].iFrom].zCnName, pFK->aCol[j].zCol, actionName(pFK->aAction[1]), /* ON UPDATE */ actionName(pFK->aAction[0]), /* ON DELETE */ "NONE"); } ++i; pFK = pFK->pNextFrom; |
︙ | ︙ | |||
129854 129855 129856 129857 129858 129859 129860 | if( zRight ){ pTab = sqlite3LocateTable(pParse, 0, zRight, zDb); k = 0; }else{ pTab = (Table*)sqliteHashData(k); k = sqliteHashNext(k); } | | > | | 130002 130003 130004 130005 130006 130007 130008 130009 130010 130011 130012 130013 130014 130015 130016 130017 130018 130019 130020 130021 130022 130023 130024 130025 | if( zRight ){ pTab = sqlite3LocateTable(pParse, 0, zRight, zDb); k = 0; }else{ pTab = (Table*)sqliteHashData(k); k = sqliteHashNext(k); } if( pTab==0 || IsVirtual(pTab) || pTab->u.tab.pFKey==0 ) continue; iDb = sqlite3SchemaToIndex(db, pTab->pSchema); zDb = db->aDb[iDb].zDbSName; sqlite3CodeVerifySchema(pParse, iDb); sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); if( pTab->nCol+regRow>pParse->nMem ) pParse->nMem = pTab->nCol + regRow; sqlite3OpenTable(pParse, 0, iDb, pTab, OP_OpenRead); sqlite3VdbeLoadString(v, regResult, pTab->zName); assert( !IsVirtual(pTab) ); for(i=1, pFK=pTab->u.tab.pFKey; pFK; i++, pFK=pFK->pNextFrom){ pParent = sqlite3FindTable(db, pFK->zTo, zDb); if( pParent==0 ) continue; pIdx = 0; sqlite3TableLock(pParse, iDb, pParent->tnum, 0, pParent->zName); x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, 0); if( x==0 ){ if( pIdx==0 ){ |
︙ | ︙ | |||
129884 129885 129886 129887 129888 129889 129890 | break; } } assert( pParse->nErr>0 || pFK==0 ); if( pFK ) break; if( pParse->nTab<i ) pParse->nTab = i; addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, 0); VdbeCoverage(v); | > | > | 130033 130034 130035 130036 130037 130038 130039 130040 130041 130042 130043 130044 130045 130046 130047 130048 130049 130050 130051 130052 130053 130054 130055 130056 130057 130058 130059 130060 130061 130062 | break; } } assert( pParse->nErr>0 || pFK==0 ); if( pFK ) break; if( pParse->nTab<i ) pParse->nTab = i; addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, 0); VdbeCoverage(v); assert( !IsVirtual(pTab) ); for(i=1, pFK=pTab->u.tab.pFKey; pFK; i++, pFK=pFK->pNextFrom){ pParent = sqlite3FindTable(db, pFK->zTo, zDb); pIdx = 0; aiCols = 0; if( pParent ){ x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, &aiCols); assert( x==0 || db->mallocFailed ); } addrOk = sqlite3VdbeMakeLabel(pParse); /* Generate code to read the child key values into registers ** regRow..regRow+n. If any of the child key values are NULL, this ** row cannot cause an FK violation. Jump directly to addrOk in ** this case. */ if( regRow+pFK->nCol>pParse->nMem ) pParse->nMem = regRow+pFK->nCol; for(j=0; j<pFK->nCol; j++){ int iCol = aiCols ? aiCols[j] : pFK->aCol[j].iFrom; sqlite3ExprCodeGetColumnOfTable(v, pTab, 0, iCol, regRow+j); sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk); VdbeCoverage(v); } /* Generate code to query the parent index for a matching parent |
︙ | ︙ | |||
130118 130119 130120 130121 130122 130123 130124 | if( pTab->aCol[j].notNull==0 ) continue; sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, j, 3); if( sqlite3VdbeGetOp(v,-1)->opcode==OP_Column ){ sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG); } jmp2 = sqlite3VdbeAddOp1(v, OP_NotNull, 3); VdbeCoverage(v); zErr = sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName, | | | 130269 130270 130271 130272 130273 130274 130275 130276 130277 130278 130279 130280 130281 130282 130283 | if( pTab->aCol[j].notNull==0 ) continue; sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, j, 3); if( sqlite3VdbeGetOp(v,-1)->opcode==OP_Column ){ sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG); } jmp2 = sqlite3VdbeAddOp1(v, OP_NotNull, 3); VdbeCoverage(v); zErr = sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName, pTab->aCol[j].zCnName); sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC); integrityCheckResultRow(v); sqlite3VdbeJumpHere(v, jmp2); } /* Verify CHECK constraints */ if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){ ExprList *pCheck = sqlite3ExprListDup(db, pTab->pCheck, 0); |
︙ | ︙ | |||
132326 132327 132328 132329 132330 132331 132332 | ** is not contained in the table. */ SQLITE_PRIVATE int sqlite3ColumnIndex(Table *pTab, const char *zCol){ int i; u8 h = sqlite3StrIHash(zCol); Column *pCol; for(pCol=pTab->aCol, i=0; i<pTab->nCol; pCol++, i++){ | | | 132477 132478 132479 132480 132481 132482 132483 132484 132485 132486 132487 132488 132489 132490 132491 | ** is not contained in the table. */ SQLITE_PRIVATE int sqlite3ColumnIndex(Table *pTab, const char *zCol){ int i; u8 h = sqlite3StrIHash(zCol); Column *pCol; for(pCol=pTab->aCol, i=0; i<pTab->nCol; pCol++, i++){ if( pCol->hName==h && sqlite3StrICmp(pCol->zCnName, zCol)==0 ) return i; } return -1; } /* ** Search the first N tables in pSrc, from left to right, looking for a ** table that has a column named zCol. |
︙ | ︙ | |||
132525 132526 132527 132528 132529 132530 132531 | } for(j=0; j<pRightTab->nCol; j++){ char *zName; /* Name of column in the right table */ int iLeft; /* Matching left table */ int iLeftCol; /* Matching column in the left table */ if( IsHiddenColumn(&pRightTab->aCol[j]) ) continue; | | | 132676 132677 132678 132679 132680 132681 132682 132683 132684 132685 132686 132687 132688 132689 132690 | } for(j=0; j<pRightTab->nCol; j++){ char *zName; /* Name of column in the right table */ int iLeft; /* Matching left table */ int iLeftCol; /* Matching column in the left table */ if( IsHiddenColumn(&pRightTab->aCol[j]) ) continue; zName = pRightTab->aCol[j].zCnName; if( tableAndColumnIndex(pSrc, i+1, zName, &iLeft, &iLeftCol, 1) ){ addWhereTerm(pParse, pSrc, iLeft, iLeftCol, i+1, j, isOuter, &p->pWhere); } } } |
︙ | ︙ | |||
132928 132929 132930 132931 132932 132933 132934 | */ static void fixDistinctOpenEph( Parse *pParse, /* Parsing and code generating context */ int eTnctType, /* WHERE_DISTINCT_* value */ int iVal, /* Value returned by codeDistinct() */ int iOpenEphAddr /* Address of OP_OpenEphemeral instruction for iTab */ ){ | > | > | 133079 133080 133081 133082 133083 133084 133085 133086 133087 133088 133089 133090 133091 133092 133093 133094 133095 | */ static void fixDistinctOpenEph( Parse *pParse, /* Parsing and code generating context */ int eTnctType, /* WHERE_DISTINCT_* value */ int iVal, /* Value returned by codeDistinct() */ int iOpenEphAddr /* Address of OP_OpenEphemeral instruction for iTab */ ){ if( pParse->nErr==0 && (eTnctType==WHERE_DISTINCT_UNIQUE || eTnctType==WHERE_DISTINCT_ORDERED) ){ Vdbe *v = pParse->pVdbe; sqlite3VdbeChangeToNoop(v, iOpenEphAddr); if( sqlite3VdbeGetOp(v, iOpenEphAddr+1)->opcode==OP_Explain ){ sqlite3VdbeChangeToNoop(v, iOpenEphAddr+1); } if( eTnctType==WHERE_DISTINCT_ORDERED ){ /* Change the OP_OpenEphemeral to an OP_Null that sets the MEM_Cleared |
︙ | ︙ | |||
133890 133891 133892 133893 133894 133895 133896 | #ifdef SQLITE_ENABLE_COLUMN_METADATA if( iCol<0 ) iCol = pTab->iPKey; assert( iCol==XN_ROWID || (iCol>=0 && iCol<pTab->nCol) ); if( iCol<0 ){ zType = "INTEGER"; zOrigCol = "rowid"; }else{ | | | 134043 134044 134045 134046 134047 134048 134049 134050 134051 134052 134053 134054 134055 134056 134057 | #ifdef SQLITE_ENABLE_COLUMN_METADATA if( iCol<0 ) iCol = pTab->iPKey; assert( iCol==XN_ROWID || (iCol>=0 && iCol<pTab->nCol) ); if( iCol<0 ){ zType = "INTEGER"; zOrigCol = "rowid"; }else{ zOrigCol = pTab->aCol[iCol].zCnName; zType = sqlite3ColumnType(&pTab->aCol[iCol],0); } zOrigTab = pTab->zName; if( pNC->pParse && pTab->pSchema ){ int iDb = sqlite3SchemaToIndex(pNC->pParse->db, pTab->pSchema); zOrigDb = pNC->pParse->db->aDb[iDb].zDbSName; } |
︙ | ︙ | |||
134062 134063 134064 134065 134066 134067 134068 | pTab = p->y.pTab; assert( pTab!=0 ); if( iCol<0 ) iCol = pTab->iPKey; assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) ); if( iCol<0 ){ zCol = "rowid"; }else{ | | | 134215 134216 134217 134218 134219 134220 134221 134222 134223 134224 134225 134226 134227 134228 134229 | pTab = p->y.pTab; assert( pTab!=0 ); if( iCol<0 ) iCol = pTab->iPKey; assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) ); if( iCol<0 ){ zCol = "rowid"; }else{ zCol = pTab->aCol[iCol].zCnName; } if( fullName ){ char *zName = 0; zName = sqlite3MPrintf(db, "%s.%s", pTab->zName, zCol); sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_DYNAMIC); }else{ sqlite3VdbeSetColName(v, i, COLNAME_NAME, zCol, SQLITE_TRANSIENT); |
︙ | ︙ | |||
134147 134148 134149 134150 134151 134152 134153 | pColExpr = pColExpr->pRight; assert( pColExpr!=0 ); } if( pColExpr->op==TK_COLUMN && (pTab = pColExpr->y.pTab)!=0 ){ /* For columns use the column name name */ int iCol = pColExpr->iColumn; if( iCol<0 ) iCol = pTab->iPKey; | | | 134300 134301 134302 134303 134304 134305 134306 134307 134308 134309 134310 134311 134312 134313 134314 | pColExpr = pColExpr->pRight; assert( pColExpr!=0 ); } if( pColExpr->op==TK_COLUMN && (pTab = pColExpr->y.pTab)!=0 ){ /* For columns use the column name name */ int iCol = pColExpr->iColumn; if( iCol<0 ) iCol = pTab->iPKey; zName = iCol>=0 ? pTab->aCol[iCol].zCnName : "rowid"; }else if( pColExpr->op==TK_ID ){ assert( !ExprHasProperty(pColExpr, EP_IntValue) ); zName = pColExpr->u.zToken; }else{ /* Use the original text of the column expression as its name */ zName = pEList->a[i].zEName; } |
︙ | ︙ | |||
134175 134176 134177 134178 134179 134180 134181 | if( nName>0 ){ for(j=nName-1; j>0 && sqlite3Isdigit(zName[j]); j--){} if( zName[j]==':' ) nName = j; } zName = sqlite3MPrintf(db, "%.*z:%u", nName, zName, ++cnt); if( cnt>3 ) sqlite3_randomness(sizeof(cnt), &cnt); } | | | | 134328 134329 134330 134331 134332 134333 134334 134335 134336 134337 134338 134339 134340 134341 134342 134343 134344 134345 134346 134347 134348 134349 134350 134351 134352 | if( nName>0 ){ for(j=nName-1; j>0 && sqlite3Isdigit(zName[j]); j--){} if( zName[j]==':' ) nName = j; } zName = sqlite3MPrintf(db, "%.*z:%u", nName, zName, ++cnt); if( cnt>3 ) sqlite3_randomness(sizeof(cnt), &cnt); } pCol->zCnName = zName; pCol->hName = sqlite3StrIHash(zName); sqlite3ColumnPropertiesFromName(0, pCol); if( zName && sqlite3HashInsert(&ht, zName, pCol)==pCol ){ sqlite3OomFault(db); } } sqlite3HashClear(&ht); if( db->mallocFailed ){ for(j=0; j<i; j++){ sqlite3DbFree(db, aCol[j].zCnName); } sqlite3DbFree(db, aCol); *paCol = 0; *pnCol = 0; return SQLITE_NOMEM_BKPT; } return SQLITE_OK; |
︙ | ︙ | |||
134237 134238 134239 134240 134241 134242 134243 | pTab->tabFlags |= (pCol->colFlags & COLFLAG_NOINSERT); p = a[i].pExpr; zType = columnType(&sNC, p, 0, 0, 0); /* pCol->szEst = ... // Column size est for SELECT tables never used */ pCol->affinity = sqlite3ExprAffinity(p); if( zType ){ m = sqlite3Strlen30(zType); | | | | | | > | | 134390 134391 134392 134393 134394 134395 134396 134397 134398 134399 134400 134401 134402 134403 134404 134405 134406 134407 134408 134409 134410 134411 134412 134413 134414 134415 | pTab->tabFlags |= (pCol->colFlags & COLFLAG_NOINSERT); p = a[i].pExpr; zType = columnType(&sNC, p, 0, 0, 0); /* pCol->szEst = ... // Column size est for SELECT tables never used */ pCol->affinity = sqlite3ExprAffinity(p); if( zType ){ m = sqlite3Strlen30(zType); n = sqlite3Strlen30(pCol->zCnName); pCol->zCnName = sqlite3DbReallocOrFree(db, pCol->zCnName, n+m+2); if( pCol->zCnName ){ memcpy(&pCol->zCnName[n+1], zType, m+1); pCol->colFlags |= COLFLAG_HASTYPE; } } if( pCol->affinity<=SQLITE_AFF_NONE ) pCol->affinity = aff; pColl = sqlite3ExprCollSeq(pParse, p); if( pColl && (pCol->colFlags & COLFLAG_HASCOLL)==0 ){ assert( pTab->pIndex==0 ); sqlite3ColumnSetColl(db, pCol, pColl->zName); } } pTab->szTabRow = 1; /* Any non-zero value works */ } /* ** Given a SELECT statement, generate a Table structure that describes |
︙ | ︙ | |||
135809 135810 135811 135812 135813 135814 135815 | #if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) /* ** Assign new cursor numbers to each of the items in pSrc. For each ** new cursor number assigned, set an entry in the aCsrMap[] array ** to map the old cursor number to the new: ** | | | > | | | > > > > > > > > > > > < | | | | | 135963 135964 135965 135966 135967 135968 135969 135970 135971 135972 135973 135974 135975 135976 135977 135978 135979 135980 135981 135982 135983 135984 135985 135986 135987 135988 135989 135990 135991 135992 135993 135994 135995 135996 135997 135998 135999 136000 136001 136002 136003 136004 136005 136006 136007 136008 136009 136010 136011 136012 136013 136014 136015 136016 136017 136018 136019 136020 136021 136022 136023 136024 136025 136026 136027 136028 136029 | #if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) /* ** Assign new cursor numbers to each of the items in pSrc. For each ** new cursor number assigned, set an entry in the aCsrMap[] array ** to map the old cursor number to the new: ** ** aCsrMap[iOld+1] = iNew; ** ** The array is guaranteed by the caller to be large enough for all ** existing cursor numbers in pSrc. aCsrMap[0] is the array size. ** ** If pSrc contains any sub-selects, call this routine recursively ** on the FROM clause of each such sub-select, with iExcept set to -1. */ static void srclistRenumberCursors( Parse *pParse, /* Parse context */ int *aCsrMap, /* Array to store cursor mappings in */ SrcList *pSrc, /* FROM clause to renumber */ int iExcept /* FROM clause item to skip */ ){ int i; SrcItem *pItem; for(i=0, pItem=pSrc->a; i<pSrc->nSrc; i++, pItem++){ if( i!=iExcept ){ Select *p; assert( pItem->iCursor < aCsrMap[0] ); if( !pItem->fg.isRecursive || aCsrMap[pItem->iCursor+1]==0 ){ aCsrMap[pItem->iCursor+1] = pParse->nTab++; } pItem->iCursor = aCsrMap[pItem->iCursor+1]; for(p=pItem->pSelect; p; p=p->pPrior){ srclistRenumberCursors(pParse, aCsrMap, p->pSrc, -1); } } } } /* ** *piCursor is a cursor number. Change it if it needs to be mapped. */ static void renumberCursorDoMapping(Walker *pWalker, int *piCursor){ int *aCsrMap = pWalker->u.aiCol; int iCsr = *piCursor; if( iCsr < aCsrMap[0] && aCsrMap[iCsr+1]>0 ){ *piCursor = aCsrMap[iCsr+1]; } } /* ** Expression walker callback used by renumberCursors() to update ** Expr objects to match newly assigned cursor numbers. */ static int renumberCursorsCb(Walker *pWalker, Expr *pExpr){ int op = pExpr->op; if( op==TK_COLUMN || op==TK_IF_NULL_ROW ){ renumberCursorDoMapping(pWalker, &pExpr->iTable); } if( ExprHasProperty(pExpr, EP_FromJoin) ){ renumberCursorDoMapping(pWalker, &pExpr->iRightJoinTable); } return WRC_Continue; } /* ** Assign a new cursor number to each cursor in the FROM clause (Select.pSrc) ** of the SELECT statement passed as the second argument, and to each |
︙ | ︙ | |||
136194 136195 136196 136197 136198 136199 136200 | } /* Restriction (23) */ if( (p->selFlags & SF_Recursive) ) return 0; if( pSrc->nSrc>1 ){ if( pParse->nSelect>500 ) return 0; | | > | 136359 136360 136361 136362 136363 136364 136365 136366 136367 136368 136369 136370 136371 136372 136373 136374 | } /* Restriction (23) */ if( (p->selFlags & SF_Recursive) ) return 0; if( pSrc->nSrc>1 ){ if( pParse->nSelect>500 ) return 0; aCsrMap = sqlite3DbMallocZero(db, (pParse->nTab+1)*sizeof(int)); if( aCsrMap ) aCsrMap[0] = pParse->nTab; } } /***** If we reach this point, flattening is permitted. *****/ SELECTTRACE(1,pParse,p,("flatten %u.%p from term %d\n", pSub->selId, pSub, iFrom)); |
︙ | ︙ | |||
136974 136975 136976 136977 136978 136979 136980 | if( p->pWhere || p->pEList->nExpr!=1 || p->pSrc->nSrc!=1 || p->pSrc->a[0].pSelect ){ return 0; } pTab = p->pSrc->a[0].pTab; pExpr = p->pEList->a[0].pExpr; | | | 137140 137141 137142 137143 137144 137145 137146 137147 137148 137149 137150 137151 137152 137153 137154 | if( p->pWhere || p->pEList->nExpr!=1 || p->pSrc->nSrc!=1 || p->pSrc->a[0].pSelect ){ return 0; } pTab = p->pSrc->a[0].pTab; pExpr = p->pEList->a[0].pExpr; assert( pTab && !IsView(pTab) && pExpr ); if( IsVirtual(pTab) ) return 0; if( pExpr->op!=TK_AGG_FUNCTION ) return 0; if( NEVER(pAggInfo->nFunc==0) ) return 0; if( (pAggInfo->aFunc[0].pFunc->funcFlags&SQLITE_FUNC_COUNT)==0 ) return 0; if( ExprHasProperty(pExpr, EP_Distinct|EP_WinFunc) ) return 0; |
︙ | ︙ | |||
137519 137520 137521 137522 137523 137524 137525 | return WRC_Abort; } pTab->nTabRef++; if( !IsVirtual(pTab) && cannotBeFunction(pParse, pFrom) ){ return WRC_Abort; } #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) | | | | | | | | | > > < | | | > < | 137685 137686 137687 137688 137689 137690 137691 137692 137693 137694 137695 137696 137697 137698 137699 137700 137701 137702 137703 137704 137705 137706 137707 137708 137709 137710 137711 137712 137713 137714 137715 137716 137717 137718 137719 137720 137721 137722 137723 | return WRC_Abort; } pTab->nTabRef++; if( !IsVirtual(pTab) && cannotBeFunction(pParse, pFrom) ){ return WRC_Abort; } #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) if( !IsOrdinaryTable(pTab) ){ i16 nCol; u8 eCodeOrig = pWalker->eCode; if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort; assert( pFrom->pSelect==0 ); if( IsView(pTab) ){ if( (db->flags & SQLITE_EnableView)==0 && pTab->pSchema!=db->aDb[1].pSchema ){ sqlite3ErrorMsg(pParse, "access to view \"%s\" prohibited", pTab->zName); } pFrom->pSelect = sqlite3SelectDup(db, pTab->u.view.pSelect, 0); }else #ifndef SQLITE_OMIT_VIRTUALTABLE if( ALWAYS(IsVirtual(pTab)) && pFrom->fg.fromDDL && ALWAYS(pTab->u.vtab.p!=0) && pTab->u.vtab.p->eVtabRisk > ((db->flags & SQLITE_TrustedSchema)!=0) ){ sqlite3ErrorMsg(pParse, "unsafe use of virtual table \"%s\"", pTab->zName); } assert( SQLITE_VTABRISK_Normal==1 && SQLITE_VTABRISK_High==2 ); #endif nCol = pTab->nCol; pTab->nCol = -1; pWalker->eCode = 1; /* Turn on Select.selId renumbering */ sqlite3WalkSelect(pWalker, pFrom->pSelect); pWalker->eCode = eCodeOrig; pTab->nCol = nCol; } |
︙ | ︙ | |||
137642 137643 137644 137645 137646 137647 137648 | if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){ continue; } iDb = sqlite3SchemaToIndex(db, pTab->pSchema); zSchemaName = iDb>=0 ? db->aDb[iDb].zDbSName : "*"; } for(j=0; j<pTab->nCol; j++){ | | | 137809 137810 137811 137812 137813 137814 137815 137816 137817 137818 137819 137820 137821 137822 137823 | if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){ continue; } iDb = sqlite3SchemaToIndex(db, pTab->pSchema); zSchemaName = iDb>=0 ? db->aDb[iDb].zDbSName : "*"; } for(j=0; j<pTab->nCol; j++){ char *zName = pTab->aCol[j].zCnName; char *zColname; /* The computed column name */ char *zToFree; /* Malloced string that needs to be freed */ Token sColname; /* Computed column name as a token */ assert( zName ); if( zTName && pSub && sqlite3MatchEName(&pSub->pEList->a[j], 0, zTName, 0)==0 |
︙ | ︙ | |||
138074 138075 138076 138077 138078 138079 138080 138081 138082 138083 138084 138085 138086 138087 138088 138089 | ** sub-expression matches the criteria for being moved to the WHERE ** clause. If so, add it to the WHERE clause and replace the sub-expression ** within the HAVING expression with a constant "1". */ static int havingToWhereExprCb(Walker *pWalker, Expr *pExpr){ if( pExpr->op!=TK_AND ){ Select *pS = pWalker->u.pSelect; if( sqlite3ExprIsConstantOrGroupBy(pWalker->pParse, pExpr, pS->pGroupBy) && ExprAlwaysFalse(pExpr)==0 ){ sqlite3 *db = pWalker->pParse->db; Expr *pNew = sqlite3Expr(db, TK_INTEGER, "1"); if( pNew ){ Expr *pWhere = pS->pWhere; SWAP(Expr, *pNew, *pExpr); pNew = sqlite3ExprAnd(pWalker->pParse, pWhere, pNew); | > > > > > > > > | 138241 138242 138243 138244 138245 138246 138247 138248 138249 138250 138251 138252 138253 138254 138255 138256 138257 138258 138259 138260 138261 138262 138263 138264 | ** sub-expression matches the criteria for being moved to the WHERE ** clause. If so, add it to the WHERE clause and replace the sub-expression ** within the HAVING expression with a constant "1". */ static int havingToWhereExprCb(Walker *pWalker, Expr *pExpr){ if( pExpr->op!=TK_AND ){ Select *pS = pWalker->u.pSelect; /* This routine is called before the HAVING clause of the current ** SELECT is analyzed for aggregates. So if pExpr->pAggInfo is set ** here, it indicates that the expression is a correlated reference to a ** column from an outer aggregate query, or an aggregate function that ** belongs to an outer query. Do not move the expression to the WHERE ** clause in this obscure case, as doing so may corrupt the outer Select ** statements AggInfo structure. */ if( sqlite3ExprIsConstantOrGroupBy(pWalker->pParse, pExpr, pS->pGroupBy) && ExprAlwaysFalse(pExpr)==0 && pExpr->pAggInfo==0 ){ sqlite3 *db = pWalker->pParse->db; Expr *pNew = sqlite3Expr(db, TK_INTEGER, "1"); if( pNew ){ Expr *pWhere = pS->pWhere; SWAP(Expr, *pNew, *pExpr); pNew = sqlite3ExprAnd(pWalker->pParse, pWhere, pNew); |
︙ | ︙ | |||
138341 138342 138343 138344 138345 138346 138347 | #if SELECTTRACE_ENABLED if( sqlite3SelectTrace & 0x104 ){ SELECTTRACE(0x104,pParse,p, ("after name resolution:\n")); sqlite3TreeViewSelect(0, p, 0); } #endif | | | > > > > > | > > > > > > | 138516 138517 138518 138519 138520 138521 138522 138523 138524 138525 138526 138527 138528 138529 138530 138531 138532 138533 138534 138535 138536 138537 138538 138539 138540 138541 138542 138543 138544 138545 138546 138547 138548 138549 138550 138551 138552 138553 138554 138555 138556 | #if SELECTTRACE_ENABLED if( sqlite3SelectTrace & 0x104 ){ SELECTTRACE(0x104,pParse,p, ("after name resolution:\n")); sqlite3TreeViewSelect(0, p, 0); } #endif /* If the SF_UFSrcCheck flag is set, then this function is being called ** as part of populating the temp table for an UPDATE...FROM statement. ** In this case, it is an error if the target object (pSrc->a[0]) name ** or alias is duplicated within FROM clause (pSrc->a[1..n]). ** ** Postgres disallows this case too. The reason is that some other ** systems handle this case differently, and not all the same way, ** which is just confusing. To avoid this, we follow PG's lead and ** disallow it altogether. */ if( p->selFlags & SF_UFSrcCheck ){ SrcItem *p0 = &p->pSrc->a[0]; for(i=1; i<p->pSrc->nSrc; i++){ SrcItem *p1 = &p->pSrc->a[i]; if( p0->pTab==p1->pTab && 0==sqlite3_stricmp(p0->zAlias, p1->zAlias) ){ sqlite3ErrorMsg(pParse, "target object/alias may not appear in FROM clause: %s", p0->zAlias ? p0->zAlias : p0->pTab->zName ); goto select_end; } } /* Clear the SF_UFSrcCheck flag. The check has already been performed, ** and leaving this flag set can cause errors if a compound sub-query ** in p->pSrc is flattened into this query and this function called ** again as part of compound SELECT processing. */ p->selFlags &= ~SF_UFSrcCheck; } if( pDest->eDest==SRT_Output ){ sqlite3GenerateColumnNames(pParse, p); } #ifndef SQLITE_OMIT_WINDOWFUNC |
︙ | ︙ | |||
138427 138428 138429 138430 138431 138432 138433 138434 138435 138436 138437 138438 138439 138440 | ** Flattening an aggregate subquery is only possible if the outer query ** is not a join. But if the outer query is not a join, then the subquery ** will be implemented as a co-routine and there is no advantage to ** flattening in that case. */ if( (pSub->selFlags & SF_Aggregate)!=0 ) continue; assert( pSub->pGroupBy==0 ); /* If the outer query contains a "complex" result set (that is, ** if the result set of the outer query uses functions or subqueries) ** and if the subquery contains an ORDER BY clause and if ** it will be implemented as a co-routine, then do not flatten. This ** restriction allows SQL constructs like this: ** | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 138613 138614 138615 138616 138617 138618 138619 138620 138621 138622 138623 138624 138625 138626 138627 138628 138629 138630 138631 138632 138633 138634 138635 138636 138637 138638 138639 138640 138641 138642 138643 138644 138645 138646 138647 138648 138649 138650 138651 138652 138653 138654 138655 138656 138657 138658 138659 | ** Flattening an aggregate subquery is only possible if the outer query ** is not a join. But if the outer query is not a join, then the subquery ** will be implemented as a co-routine and there is no advantage to ** flattening in that case. */ if( (pSub->selFlags & SF_Aggregate)!=0 ) continue; assert( pSub->pGroupBy==0 ); /* If a FROM-clause subquery has an ORDER BY clause that is not ** really doing anything, then delete it now so that it does not ** interfere with query flattening. See the discussion at ** https://sqlite.org/forum/forumpost/2d76f2bcf65d256a ** ** Beware of these cases where the ORDER BY clause may not be safely ** omitted: ** ** (1) There is also a LIMIT clause ** (2) The subquery was added to help with window-function ** processing ** (3) The subquery is in the FROM clause of an UPDATE ** (4) The outer query uses an aggregate function other than ** the built-in count(), min(), or max(). ** (5) The ORDER BY isn't going to accomplish anything because ** one of: ** (a) The outer query has a different ORDER BY clause ** (b) The subquery is part of a join ** See forum post 062d576715d277c8 */ if( pSub->pOrderBy!=0 && (p->pOrderBy!=0 || pTabList->nSrc>1) /* Condition (5) */ && pSub->pLimit==0 /* Condition (1) */ && (pSub->selFlags & SF_OrderByReqd)==0 /* Condition (2) */ && (p->selFlags & SF_OrderByReqd)==0 /* Condition (3) and (4) */ && OptimizationEnabled(db, SQLITE_OmitOrderBy) ){ SELECTTRACE(0x100,pParse,p, ("omit superfluous ORDER BY on %r FROM-clause subquery\n",i+1)); sqlite3ExprListDelete(db, pSub->pOrderBy); pSub->pOrderBy = 0; } /* If the outer query contains a "complex" result set (that is, ** if the result set of the outer query uses functions or subqueries) ** and if the subquery contains an ORDER BY clause and if ** it will be implemented as a co-routine, then do not flatten. This ** restriction allows SQL constructs like this: ** |
︙ | ︙ | |||
139875 139876 139877 139878 139879 139880 139881 | sqlite3ErrorMsg(pParse, "cannot create trigger on system table"); goto trigger_cleanup; } /* INSTEAD of triggers are only for views and views only support INSTEAD ** of triggers. */ | | | | 140094 140095 140096 140097 140098 140099 140100 140101 140102 140103 140104 140105 140106 140107 140108 140109 140110 140111 140112 140113 | sqlite3ErrorMsg(pParse, "cannot create trigger on system table"); goto trigger_cleanup; } /* INSTEAD of triggers are only for views and views only support INSTEAD ** of triggers. */ if( IsView(pTab) && tr_tm!=TK_INSTEAD ){ sqlite3ErrorMsg(pParse, "cannot create %s trigger on view: %S", (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", pTableName->a); goto trigger_orphan_error; } if( !IsView(pTab) && tr_tm==TK_INSTEAD ){ sqlite3ErrorMsg(pParse, "cannot create INSTEAD OF" " trigger on table: %S", pTableName->a); goto trigger_orphan_error; } #ifndef SQLITE_OMIT_AUTHORIZATION if( !IN_RENAME_OBJECT ){ |
︙ | ︙ | |||
140533 140534 140535 140536 140537 140538 140539 | Expr *pOldExpr = pList->a[i].pExpr; if( NEVER(pOldExpr==0) ) continue; if( isAsteriskTerm(pParse, pOldExpr) ){ int jj; for(jj=0; jj<pTab->nCol; jj++){ Expr *pNewExpr; if( IsHiddenColumn(pTab->aCol+jj) ) continue; | | | | 140752 140753 140754 140755 140756 140757 140758 140759 140760 140761 140762 140763 140764 140765 140766 140767 140768 140769 140770 | Expr *pOldExpr = pList->a[i].pExpr; if( NEVER(pOldExpr==0) ) continue; if( isAsteriskTerm(pParse, pOldExpr) ){ int jj; for(jj=0; jj<pTab->nCol; jj++){ Expr *pNewExpr; if( IsHiddenColumn(pTab->aCol+jj) ) continue; pNewExpr = sqlite3Expr(db, TK_ID, pTab->aCol[jj].zCnName); pNew = sqlite3ExprListAppend(pParse, pNew, pNewExpr); if( !db->mallocFailed ){ struct ExprList_item *pItem = &pNew->a[pNew->nExpr-1]; pItem->zEName = sqlite3DbStrDup(db, pTab->aCol[jj].zCnName); pItem->eEName = ENAME_NAME; } } }else{ Expr *pNewExpr = sqlite3ExprDup(db, pOldExpr, 0); pNew = sqlite3ExprListAppend(pParse, pNew, pNewExpr); if( !db->mallocFailed && ALWAYS(pList->a[i].zEName!=0) ){ |
︙ | ︙ | |||
140582 140583 140584 140585 140586 140587 140588 140589 140590 140591 140592 140593 140594 140595 | assert( pTrigger == &(pReturning->retTrig) ); memset(&sSelect, 0, sizeof(sSelect)); memset(&sFrom, 0, sizeof(sFrom)); sSelect.pEList = sqlite3ExprListDup(db, pReturning->pReturnEL, 0); sSelect.pSrc = &sFrom; sFrom.nSrc = 1; sFrom.a[0].pTab = pTab; sqlite3SelectPrep(pParse, &sSelect, 0); if( db->mallocFailed==0 && pParse->nErr==0 ){ sqlite3GenerateColumnNames(pParse, &sSelect); } sqlite3ExprListDelete(db, sSelect.pEList); pNew = sqlite3ExpandReturning(pParse, pReturning->pReturnEL, pTab); if( pNew ){ | > | 140801 140802 140803 140804 140805 140806 140807 140808 140809 140810 140811 140812 140813 140814 140815 | assert( pTrigger == &(pReturning->retTrig) ); memset(&sSelect, 0, sizeof(sSelect)); memset(&sFrom, 0, sizeof(sFrom)); sSelect.pEList = sqlite3ExprListDup(db, pReturning->pReturnEL, 0); sSelect.pSrc = &sFrom; sFrom.nSrc = 1; sFrom.a[0].pTab = pTab; sFrom.a[0].iCursor = -1; sqlite3SelectPrep(pParse, &sSelect, 0); if( db->mallocFailed==0 && pParse->nErr==0 ){ sqlite3GenerateColumnNames(pParse, &sSelect); } sqlite3ExprListDelete(db, sSelect.pEList); pNew = sqlite3ExpandReturning(pParse, pReturning->pReturnEL, pTab); if( pNew ){ |
︙ | ︙ | |||
141137 141138 141139 141140 141141 141142 141143 | ** If column as REAL affinity and the table is an ordinary b-tree table ** (not a virtual table) then the value might have been stored as an ** integer. In that case, add an OP_RealAffinity opcode to make sure ** it has been converted into REAL. */ SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){ assert( pTab!=0 ); | | | | > | 141357 141358 141359 141360 141361 141362 141363 141364 141365 141366 141367 141368 141369 141370 141371 141372 141373 141374 141375 141376 141377 141378 | ** If column as REAL affinity and the table is an ordinary b-tree table ** (not a virtual table) then the value might have been stored as an ** integer. In that case, add an OP_RealAffinity opcode to make sure ** it has been converted into REAL. */ SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){ assert( pTab!=0 ); if( !IsView(pTab) ){ sqlite3_value *pValue = 0; u8 enc = ENC(sqlite3VdbeDb(v)); Column *pCol = &pTab->aCol[i]; VdbeComment((v, "%s.%s", pTab->zName, pCol->zCnName)); assert( i<pTab->nCol ); sqlite3ValueFromExpr(sqlite3VdbeDb(v), sqlite3ColumnExpr(pTab,pCol), enc, pCol->affinity, &pValue); if( pValue ){ sqlite3VdbeAppendP4(v, pValue, P4_MEM); } } #ifndef SQLITE_OMIT_FLOATING_POINT if( pTab->aCol[i].affinity==SQLITE_AFF_REAL && !IsVirtual(pTab) ){ |
︙ | ︙ | |||
141313 141314 141315 141316 141317 141318 141319 | if( pLimit ){ pGrp = sqlite3ExprListAppend(pParse, pGrp, sqlite3ExprDup(db, pNew, 0)); } #endif pList = sqlite3ExprListAppend(pParse, pList, pNew); } eDest = IsVirtual(pTab) ? SRT_Table : SRT_Upfrom; | | | 141534 141535 141536 141537 141538 141539 141540 141541 141542 141543 141544 141545 141546 141547 141548 | if( pLimit ){ pGrp = sqlite3ExprListAppend(pParse, pGrp, sqlite3ExprDup(db, pNew, 0)); } #endif pList = sqlite3ExprListAppend(pParse, pList, pNew); } eDest = IsVirtual(pTab) ? SRT_Table : SRT_Upfrom; }else if( IsView(pTab) ){ for(i=0; i<pTab->nCol; i++){ pList = sqlite3ExprListAppend(pParse, pList, exprRowColumn(pParse, i)); } eDest = SRT_Table; }else{ eDest = IsVirtual(pTab) ? SRT_Table : SRT_Upfrom; pList = sqlite3ExprListAppend(pParse, 0, sqlite3PExpr(pParse,TK_ROW,0,0)); |
︙ | ︙ | |||
141336 141337 141338 141339 141340 141341 141342 | for(i=0; i<pChanges->nExpr; i++){ pList = sqlite3ExprListAppend(pParse, pList, sqlite3ExprDup(db, pChanges->a[i].pExpr, 0) ); } } pSelect = sqlite3SelectNew(pParse, pList, | | > | 141557 141558 141559 141560 141561 141562 141563 141564 141565 141566 141567 141568 141569 141570 141571 141572 141573 | for(i=0; i<pChanges->nExpr; i++){ pList = sqlite3ExprListAppend(pParse, pList, sqlite3ExprDup(db, pChanges->a[i].pExpr, 0) ); } } pSelect = sqlite3SelectNew(pParse, pList, pSrc, pWhere2, pGrp, 0, pOrderBy2, SF_UFSrcCheck|SF_IncludeHidden, pLimit2 ); if( pSelect ) pSelect->selFlags |= SF_OrderByReqd; sqlite3SelectDestInit(&dest, eDest, iEph); dest.iSDParm2 = (pPk ? pPk->nKeyCol : -1); sqlite3Select(pParse, pSelect, &dest); sqlite3SelectDelete(db, pSelect); } /* |
︙ | ︙ | |||
141437 141438 141439 141440 141441 141442 141443 | iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); /* Figure out if we have any triggers and if the table being ** updated is a view. */ #ifndef SQLITE_OMIT_TRIGGER pTrigger = sqlite3TriggersExist(pParse, pTab, TK_UPDATE, pChanges, &tmask); | | | 141659 141660 141661 141662 141663 141664 141665 141666 141667 141668 141669 141670 141671 141672 141673 | iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); /* Figure out if we have any triggers and if the table being ** updated is a view. */ #ifndef SQLITE_OMIT_TRIGGER pTrigger = sqlite3TriggersExist(pParse, pTab, TK_UPDATE, pChanges, &tmask); isView = IsView(pTab); assert( pTrigger || tmask==0 ); #else # define pTrigger 0 # define isView 0 # define tmask 0 #endif #ifdef SQLITE_OMIT_VIEW |
︙ | ︙ | |||
141526 141527 141528 141529 141530 141531 141532 141533 141534 141535 141536 141537 141538 | ** of the UPDATE statement. Also find the column index ** for each column to be updated in the pChanges array. For each ** column to be updated, make sure we have authorization to change ** that column. */ chngRowid = chngPk = 0; for(i=0; i<pChanges->nExpr; i++){ /* If this is an UPDATE with a FROM clause, do not resolve expressions ** here. The call to sqlite3Select() below will do that. */ if( nChangeFrom==0 && sqlite3ResolveExprNames(&sNC, pChanges->a[i].pExpr) ){ goto update_cleanup; } for(j=0; j<pTab->nCol; j++){ | > > | > | | 141748 141749 141750 141751 141752 141753 141754 141755 141756 141757 141758 141759 141760 141761 141762 141763 141764 141765 141766 141767 141768 141769 141770 141771 141772 141773 141774 141775 141776 141777 141778 141779 141780 141781 141782 141783 141784 141785 | ** of the UPDATE statement. Also find the column index ** for each column to be updated in the pChanges array. For each ** column to be updated, make sure we have authorization to change ** that column. */ chngRowid = chngPk = 0; for(i=0; i<pChanges->nExpr; i++){ u8 hCol = sqlite3StrIHash(pChanges->a[i].zEName); /* If this is an UPDATE with a FROM clause, do not resolve expressions ** here. The call to sqlite3Select() below will do that. */ if( nChangeFrom==0 && sqlite3ResolveExprNames(&sNC, pChanges->a[i].pExpr) ){ goto update_cleanup; } for(j=0; j<pTab->nCol; j++){ if( pTab->aCol[j].hName==hCol && sqlite3StrICmp(pTab->aCol[j].zCnName, pChanges->a[i].zEName)==0 ){ if( j==pTab->iPKey ){ chngRowid = 1; pRowidExpr = pChanges->a[i].pExpr; iRowidExpr = i; }else if( pPk && (pTab->aCol[j].colFlags & COLFLAG_PRIMKEY)!=0 ){ chngPk = 1; } #ifndef SQLITE_OMIT_GENERATED_COLUMNS else if( pTab->aCol[j].colFlags & COLFLAG_GENERATED ){ testcase( pTab->aCol[j].colFlags & COLFLAG_VIRTUAL ); testcase( pTab->aCol[j].colFlags & COLFLAG_STORED ); sqlite3ErrorMsg(pParse, "cannot UPDATE generated column \"%s\"", pTab->aCol[j].zCnName); goto update_cleanup; } #endif aXRef[j] = i; break; } } |
︙ | ︙ | |||
141570 141571 141572 141573 141574 141575 141576 | goto update_cleanup; } } #ifndef SQLITE_OMIT_AUTHORIZATION { int rc; rc = sqlite3AuthCheck(pParse, SQLITE_UPDATE, pTab->zName, | | | 141795 141796 141797 141798 141799 141800 141801 141802 141803 141804 141805 141806 141807 141808 141809 | goto update_cleanup; } } #ifndef SQLITE_OMIT_AUTHORIZATION { int rc; rc = sqlite3AuthCheck(pParse, SQLITE_UPDATE, pTab->zName, j<0 ? "ROWID" : pTab->aCol[j].zCnName, db->aDb[iDb].zDbSName); if( rc==SQLITE_DENY ){ goto update_cleanup; }else if( rc==SQLITE_IGNORE ){ aXRef[j] = -1; } } |
︙ | ︙ | |||
141602 141603 141604 141605 141606 141607 141608 | testcase( pTab->tabFlags & TF_HasVirtual ); testcase( pTab->tabFlags & TF_HasStored ); do{ bProgress = 0; for(i=0; i<pTab->nCol; i++){ if( aXRef[i]>=0 ) continue; if( (pTab->aCol[i].colFlags & COLFLAG_GENERATED)==0 ) continue; | | > | > | 141827 141828 141829 141830 141831 141832 141833 141834 141835 141836 141837 141838 141839 141840 141841 141842 141843 141844 | testcase( pTab->tabFlags & TF_HasVirtual ); testcase( pTab->tabFlags & TF_HasStored ); do{ bProgress = 0; for(i=0; i<pTab->nCol; i++){ if( aXRef[i]>=0 ) continue; if( (pTab->aCol[i].colFlags & COLFLAG_GENERATED)==0 ) continue; if( sqlite3ExprReferencesUpdatedColumn( sqlite3ColumnExpr(pTab, &pTab->aCol[i]), aXRef, chngRowid) ){ aXRef[i] = 99999; bProgress = 1; } } }while( bProgress ); } #endif |
︙ | ︙ | |||
142695 142696 142697 142698 142699 142700 142701 | pParse->nMem += nPk; for(i=0; i<nPk; i++){ int k; assert( pPk->aiColumn[i]>=0 ); k = sqlite3TableColumnToIndex(pIdx, pPk->aiColumn[i]); sqlite3VdbeAddOp3(v, OP_Column, iCur, k, iPk+i); VdbeComment((v, "%s.%s", pIdx->zName, | | | 142922 142923 142924 142925 142926 142927 142928 142929 142930 142931 142932 142933 142934 142935 142936 | pParse->nMem += nPk; for(i=0; i<nPk; i++){ int k; assert( pPk->aiColumn[i]>=0 ); k = sqlite3TableColumnToIndex(pIdx, pPk->aiColumn[i]); sqlite3VdbeAddOp3(v, OP_Column, iCur, k, iPk+i); VdbeComment((v, "%s.%s", pIdx->zName, pTab->aCol[pPk->aiColumn[i]].zCnName)); } sqlite3VdbeVerifyAbortable(v, OE_Abort); i = sqlite3VdbeAddOp4Int(v, OP_Found, iDataCur, 0, iPk, nPk); VdbeCoverage(v); sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CORRUPT, OE_Abort, 0, "corrupt database", P4_STATIC); sqlite3MayAbort(pParse); |
︙ | ︙ | |||
142877 142878 142879 142880 142881 142882 142883 | sqlite3_value *pOut /* Write results here, if not NULL. VACUUM INTO */ ){ int rc = SQLITE_OK; /* Return code from service routines */ Btree *pMain; /* The database being vacuumed */ Btree *pTemp; /* The temporary database we vacuum into */ u32 saved_mDbFlags; /* Saved value of db->mDbFlags */ u64 saved_flags; /* Saved value of db->flags */ | | | | 143104 143105 143106 143107 143108 143109 143110 143111 143112 143113 143114 143115 143116 143117 143118 143119 | sqlite3_value *pOut /* Write results here, if not NULL. VACUUM INTO */ ){ int rc = SQLITE_OK; /* Return code from service routines */ Btree *pMain; /* The database being vacuumed */ Btree *pTemp; /* The temporary database we vacuum into */ u32 saved_mDbFlags; /* Saved value of db->mDbFlags */ u64 saved_flags; /* Saved value of db->flags */ i64 saved_nChange; /* Saved value of db->nChange */ i64 saved_nTotalChange; /* Saved value of db->nTotalChange */ u32 saved_openFlags; /* Saved value of db->openFlags */ u8 saved_mTrace; /* Saved trace settings */ Db *pDb = 0; /* Database to detach at end of vacuum */ int isMemDb; /* True if vacuuming a :memory: database */ int nRes; /* Bytes of reserved space at the end of each page */ int nDb; /* Number of attached databases */ const char *zDbMain; /* Schema name of database to vacuum */ |
︙ | ︙ | |||
143325 143326 143327 143328 143329 143330 143331 | ** pTab is a pointer to a Table structure representing a virtual-table. ** Return a pointer to the VTable object used by connection db to access ** this virtual-table, if one has been created, or NULL otherwise. */ SQLITE_PRIVATE VTable *sqlite3GetVTable(sqlite3 *db, Table *pTab){ VTable *pVtab; assert( IsVirtual(pTab) ); | | | 143552 143553 143554 143555 143556 143557 143558 143559 143560 143561 143562 143563 143564 143565 143566 | ** pTab is a pointer to a Table structure representing a virtual-table. ** Return a pointer to the VTable object used by connection db to access ** this virtual-table, if one has been created, or NULL otherwise. */ SQLITE_PRIVATE VTable *sqlite3GetVTable(sqlite3 *db, Table *pTab){ VTable *pVtab; assert( IsVirtual(pTab) ); for(pVtab=pTab->u.vtab.p; pVtab && pVtab->db!=db; pVtab=pVtab->pNext); return pVtab; } /* ** Decrement the ref-count on a virtual table object. When the ref-count ** reaches zero, call the xDisconnect() method to delete the object. */ |
︙ | ︙ | |||
143353 143354 143355 143356 143357 143358 143359 | } sqlite3DbFree(db, pVTab); } } /* ** Table p is a virtual table. This function moves all elements in the | | | | | | | | 143580 143581 143582 143583 143584 143585 143586 143587 143588 143589 143590 143591 143592 143593 143594 143595 143596 143597 143598 143599 143600 143601 143602 143603 143604 143605 143606 143607 143608 143609 143610 143611 143612 143613 143614 143615 143616 143617 143618 | } sqlite3DbFree(db, pVTab); } } /* ** Table p is a virtual table. This function moves all elements in the ** p->u.vtab.p list to the sqlite3.pDisconnect lists of their associated ** database connections to be disconnected at the next opportunity. ** Except, if argument db is not NULL, then the entry associated with ** connection db is left in the p->u.vtab.p list. */ static VTable *vtabDisconnectAll(sqlite3 *db, Table *p){ VTable *pRet = 0; VTable *pVTable = p->u.vtab.p; p->u.vtab.p = 0; /* Assert that the mutex (if any) associated with the BtShared database ** that contains table p is held by the caller. See header comments ** above function sqlite3VtabUnlockList() for an explanation of why ** this makes it safe to access the sqlite3.pDisconnect list of any ** database connection that may have an entry in the p->u.vtab.p list. */ assert( db==0 || sqlite3SchemaMutexHeld(db, 0, p->pSchema) ); while( pVTable ){ sqlite3 *db2 = pVTable->db; VTable *pNext = pVTable->pNext; assert( db2 ); if( db2==db ){ pRet = pVTable; p->u.vtab.p = pRet; pRet->pNext = 0; }else{ pVTable->pNext = db2->pDisconnect; db2->pDisconnect = pVTable; } pVTable = pNext; } |
︙ | ︙ | |||
143405 143406 143407 143408 143409 143410 143411 | SQLITE_PRIVATE void sqlite3VtabDisconnect(sqlite3 *db, Table *p){ VTable **ppVTab; assert( IsVirtual(p) ); assert( sqlite3BtreeHoldsAllMutexes(db) ); assert( sqlite3_mutex_held(db->mutex) ); | | | 143632 143633 143634 143635 143636 143637 143638 143639 143640 143641 143642 143643 143644 143645 143646 | SQLITE_PRIVATE void sqlite3VtabDisconnect(sqlite3 *db, Table *p){ VTable **ppVTab; assert( IsVirtual(p) ); assert( sqlite3BtreeHoldsAllMutexes(db) ); assert( sqlite3_mutex_held(db->mutex) ); for(ppVTab=&p->u.vtab.p; *ppVTab; ppVTab=&(*ppVTab)->pNext){ if( (*ppVTab)->db==db ){ VTable *pVTab = *ppVTab; *ppVTab = pVTab->pNext; sqlite3VtabUnlock(pVTab); break; } } |
︙ | ︙ | |||
143469 143470 143471 143472 143473 143474 143475 | ** connection db is decremented immediately (which may lead to the ** structure being xDisconnected and free). Any other VTable structures ** in the list are moved to the sqlite3.pDisconnect list of the associated ** database connection. */ SQLITE_PRIVATE void sqlite3VtabClear(sqlite3 *db, Table *p){ if( !db || db->pnBytesFreed==0 ) vtabDisconnectAll(0, p); | | | | | | | | | | | | 143696 143697 143698 143699 143700 143701 143702 143703 143704 143705 143706 143707 143708 143709 143710 143711 143712 143713 143714 143715 143716 143717 143718 143719 143720 143721 143722 143723 143724 143725 143726 143727 143728 143729 143730 143731 143732 143733 143734 143735 143736 143737 143738 143739 | ** connection db is decremented immediately (which may lead to the ** structure being xDisconnected and free). Any other VTable structures ** in the list are moved to the sqlite3.pDisconnect list of the associated ** database connection. */ SQLITE_PRIVATE void sqlite3VtabClear(sqlite3 *db, Table *p){ if( !db || db->pnBytesFreed==0 ) vtabDisconnectAll(0, p); if( p->u.vtab.azArg ){ int i; for(i=0; i<p->u.vtab.nArg; i++){ if( i!=1 ) sqlite3DbFree(db, p->u.vtab.azArg[i]); } sqlite3DbFree(db, p->u.vtab.azArg); } } /* ** Add a new module argument to pTable->u.vtab.azArg[]. ** The string is not copied - the pointer is stored. The ** string will be freed automatically when the table is ** deleted. */ static void addModuleArgument(Parse *pParse, Table *pTable, char *zArg){ sqlite3_int64 nBytes = sizeof(char *)*(2+pTable->u.vtab.nArg); char **azModuleArg; sqlite3 *db = pParse->db; if( pTable->u.vtab.nArg+3>=db->aLimit[SQLITE_LIMIT_COLUMN] ){ sqlite3ErrorMsg(pParse, "too many columns on %s", pTable->zName); } azModuleArg = sqlite3DbRealloc(db, pTable->u.vtab.azArg, nBytes); if( azModuleArg==0 ){ sqlite3DbFree(db, zArg); }else{ int i = pTable->u.vtab.nArg++; azModuleArg[i] = zArg; azModuleArg[i+1] = 0; pTable->u.vtab.azArg = azModuleArg; } } /* ** The parser calls this routine when it first sees a CREATE VIRTUAL TABLE ** statement. The module name has been parsed, but the optional list ** of parameters that follow the module name are still pending. |
︙ | ︙ | |||
143521 143522 143523 143524 143525 143526 143527 143528 143529 143530 | Table *pTable; /* The new virtual table */ sqlite3 *db; /* Database connection */ sqlite3StartTable(pParse, pName1, pName2, 0, 0, 1, ifNotExists); pTable = pParse->pNewTable; if( pTable==0 ) return; assert( 0==pTable->pIndex ); db = pParse->db; | > | | | | 143748 143749 143750 143751 143752 143753 143754 143755 143756 143757 143758 143759 143760 143761 143762 143763 143764 143765 143766 143767 143768 143769 143770 143771 143772 143773 143774 143775 143776 143777 143778 143779 143780 143781 143782 143783 143784 143785 143786 143787 | Table *pTable; /* The new virtual table */ sqlite3 *db; /* Database connection */ sqlite3StartTable(pParse, pName1, pName2, 0, 0, 1, ifNotExists); pTable = pParse->pNewTable; if( pTable==0 ) return; assert( 0==pTable->pIndex ); pTable->eTabType = TABTYP_VTAB; db = pParse->db; assert( pTable->u.vtab.nArg==0 ); addModuleArgument(pParse, pTable, sqlite3NameFromToken(db, pModuleName)); addModuleArgument(pParse, pTable, 0); addModuleArgument(pParse, pTable, sqlite3DbStrDup(db, pTable->zName)); assert( (pParse->sNameToken.z==pName2->z && pName2->z!=0) || (pParse->sNameToken.z==pName1->z && pName2->z==0) ); pParse->sNameToken.n = (int)( &pModuleName->z[pModuleName->n] - pParse->sNameToken.z ); #ifndef SQLITE_OMIT_AUTHORIZATION /* Creating a virtual table invokes the authorization callback twice. ** The first invocation, to obtain permission to INSERT a row into the ** sqlite_schema table, has already been made by sqlite3StartTable(). ** The second call, to obtain permission to create the table, is made now. */ if( pTable->u.vtab.azArg ){ int iDb = sqlite3SchemaToIndex(db, pTable->pSchema); assert( iDb>=0 ); /* The database the table is being created in */ sqlite3AuthCheck(pParse, SQLITE_CREATE_VTABLE, pTable->zName, pTable->u.vtab.azArg[0], pParse->db->aDb[iDb].zDbSName); } #endif } /* ** This routine takes the module argument that has been accumulating ** in pParse->zArg[] and appends it to the list of arguments on the |
︙ | ︙ | |||
143575 143576 143577 143578 143579 143580 143581 | SQLITE_PRIVATE void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){ Table *pTab = pParse->pNewTable; /* The table being constructed */ sqlite3 *db = pParse->db; /* The database connection */ if( pTab==0 ) return; addArgumentToVtab(pParse); pParse->sArg.z = 0; | | | 143803 143804 143805 143806 143807 143808 143809 143810 143811 143812 143813 143814 143815 143816 143817 | SQLITE_PRIVATE void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){ Table *pTab = pParse->pNewTable; /* The table being constructed */ sqlite3 *db = pParse->db; /* The database connection */ if( pTab==0 ) return; addArgumentToVtab(pParse); pParse->sArg.z = 0; if( pTab->u.vtab.nArg<1 ) return; /* If the CREATE VIRTUAL TABLE statement is being entered for the ** first time (in other words if the virtual table is actually being ** created now instead of just being read out of sqlite_schema) then ** do additional initialization work and store the statement text ** in the sqlite_schema table. */ |
︙ | ︙ | |||
143690 143691 143692 143693 143694 143695 143696 | Module *pMod, int (*xConstruct)(sqlite3*,void*,int,const char*const*,sqlite3_vtab**,char**), char **pzErr ){ VtabCtx sCtx; VTable *pVTable; int rc; | | | | 143918 143919 143920 143921 143922 143923 143924 143925 143926 143927 143928 143929 143930 143931 143932 143933 | Module *pMod, int (*xConstruct)(sqlite3*,void*,int,const char*const*,sqlite3_vtab**,char**), char **pzErr ){ VtabCtx sCtx; VTable *pVTable; int rc; const char *const*azArg = (const char *const*)pTab->u.vtab.azArg; int nArg = pTab->u.vtab.nArg; char *zErr = 0; char *zModuleName; int iDb; VtabCtx *pCtx; /* Check that the virtual-table is not already being initialized */ for(pCtx=db->pVtabCtx; pCtx; pCtx=pCtx->pPrior){ |
︙ | ︙ | |||
143723 143724 143725 143726 143727 143728 143729 | return SQLITE_NOMEM_BKPT; } pVTable->db = db; pVTable->pMod = pMod; pVTable->eVtabRisk = SQLITE_VTABRISK_Normal; iDb = sqlite3SchemaToIndex(db, pTab->pSchema); | | | 143951 143952 143953 143954 143955 143956 143957 143958 143959 143960 143961 143962 143963 143964 143965 | return SQLITE_NOMEM_BKPT; } pVTable->db = db; pVTable->pMod = pMod; pVTable->eVtabRisk = SQLITE_VTABRISK_Normal; iDb = sqlite3SchemaToIndex(db, pTab->pSchema); pTab->u.vtab.azArg[1] = db->aDb[iDb].zDbSName; /* Invoke the virtual table constructor */ assert( &db->pVtabCtx ); assert( xConstruct ); sCtx.pTab = pTab; sCtx.pVTable = pVTable; sCtx.pPrior = db->pVtabCtx; |
︙ | ︙ | |||
143762 143763 143764 143765 143766 143767 143768 | *pzErr = sqlite3MPrintf(db, zFormat, pTab->zName); sqlite3VtabUnlock(pVTable); rc = SQLITE_ERROR; }else{ int iCol; u16 oooHidden = 0; /* If everything went according to plan, link the new VTable structure | | | | | 143990 143991 143992 143993 143994 143995 143996 143997 143998 143999 144000 144001 144002 144003 144004 144005 144006 144007 144008 144009 | *pzErr = sqlite3MPrintf(db, zFormat, pTab->zName); sqlite3VtabUnlock(pVTable); rc = SQLITE_ERROR; }else{ int iCol; u16 oooHidden = 0; /* If everything went according to plan, link the new VTable structure ** into the linked list headed by pTab->u.vtab.p. Then loop through the ** columns of the table to see if any of them contain the token "hidden". ** If so, set the Column COLFLAG_HIDDEN flag and remove the token from ** the type string. */ pVTable->pNext = pTab->u.vtab.p; pTab->u.vtab.p = pVTable; for(iCol=0; iCol<pTab->nCol; iCol++){ char *zType = sqlite3ColumnType(&pTab->aCol[iCol], ""); int nType; int i = 0; nType = sqlite3Strlen30(zType); for(i=0; i<nType; i++){ |
︙ | ︙ | |||
143825 143826 143827 143828 143829 143830 143831 | assert( pTab ); if( !IsVirtual(pTab) || sqlite3GetVTable(db, pTab) ){ return SQLITE_OK; } /* Locate the required virtual table module */ | | | | 144053 144054 144055 144056 144057 144058 144059 144060 144061 144062 144063 144064 144065 144066 144067 144068 144069 144070 144071 | assert( pTab ); if( !IsVirtual(pTab) || sqlite3GetVTable(db, pTab) ){ return SQLITE_OK; } /* Locate the required virtual table module */ zMod = pTab->u.vtab.azArg[0]; pMod = (Module*)sqlite3HashFind(&db->aModule, zMod); if( !pMod ){ const char *zModule = pTab->u.vtab.azArg[0]; sqlite3ErrorMsg(pParse, "no such module: %s", zModule); rc = SQLITE_ERROR; }else{ char *zErr = 0; rc = vtabCallConstructor(db, pTab, pMod, pMod->pModule->xConnect, &zErr); if( rc!=SQLITE_OK ){ sqlite3ErrorMsg(pParse, "%s", zErr); |
︙ | ︙ | |||
143892 143893 143894 143895 143896 143897 143898 | SQLITE_PRIVATE int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, char **pzErr){ int rc = SQLITE_OK; Table *pTab; Module *pMod; const char *zMod; pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zDbSName); | | | | 144120 144121 144122 144123 144124 144125 144126 144127 144128 144129 144130 144131 144132 144133 144134 144135 144136 144137 | SQLITE_PRIVATE int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, char **pzErr){ int rc = SQLITE_OK; Table *pTab; Module *pMod; const char *zMod; pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zDbSName); assert( pTab && IsVirtual(pTab) && !pTab->u.vtab.p ); /* Locate the required virtual table module */ zMod = pTab->u.vtab.azArg[0]; pMod = (Module*)sqlite3HashFind(&db->aModule, zMod); /* If the module has been registered and includes a Create method, ** invoke it now. If the module has not been registered, return an ** error. Otherwise, do nothing. */ if( pMod==0 || pMod->pModule->xCreate==0 || pMod->pModule->xDestroy==0 ){ |
︙ | ︙ | |||
143955 143956 143957 143958 143959 143960 143961 | memset(&sParse, 0, sizeof(sParse)); sParse.eParseMode = PARSE_MODE_DECLARE_VTAB; sParse.db = db; sParse.nQueryLoop = 1; if( SQLITE_OK==sqlite3RunParser(&sParse, zCreateTable, &zErr) && sParse.pNewTable && !db->mallocFailed | < | > | 144183 144184 144185 144186 144187 144188 144189 144190 144191 144192 144193 144194 144195 144196 144197 144198 144199 144200 144201 144202 144203 | memset(&sParse, 0, sizeof(sParse)); sParse.eParseMode = PARSE_MODE_DECLARE_VTAB; sParse.db = db; sParse.nQueryLoop = 1; if( SQLITE_OK==sqlite3RunParser(&sParse, zCreateTable, &zErr) && sParse.pNewTable && !db->mallocFailed && IsOrdinaryTable(sParse.pNewTable) ){ if( !pTab->aCol ){ Table *pNew = sParse.pNewTable; Index *pIdx; pTab->aCol = pNew->aCol; sqlite3ExprListDelete(db, pNew->u.tab.pDfltList); pTab->nNVCol = pTab->nCol = pNew->nCol; pTab->tabFlags |= pNew->tabFlags & (TF_WithoutRowid|TF_NoVisibleRowid); pNew->nCol = 0; pNew->aCol = 0; assert( pTab->pIndex==0 ); assert( HasRowid(pNew) || sqlite3PrimaryKeyIndex(pNew)!=0 ); if( !HasRowid(pNew) |
︙ | ︙ | |||
144016 144017 144018 144019 144020 144021 144022 | ** This call is a no-op if zTab is not a virtual table. */ SQLITE_PRIVATE int sqlite3VtabCallDestroy(sqlite3 *db, int iDb, const char *zTab){ int rc = SQLITE_OK; Table *pTab; pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zDbSName); | | | | | | 144244 144245 144246 144247 144248 144249 144250 144251 144252 144253 144254 144255 144256 144257 144258 144259 144260 144261 144262 144263 144264 144265 144266 144267 144268 144269 144270 144271 144272 144273 144274 144275 144276 144277 | ** This call is a no-op if zTab is not a virtual table. */ SQLITE_PRIVATE int sqlite3VtabCallDestroy(sqlite3 *db, int iDb, const char *zTab){ int rc = SQLITE_OK; Table *pTab; pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zDbSName); if( pTab!=0 && ALWAYS(pTab->u.vtab.p!=0) ){ VTable *p; int (*xDestroy)(sqlite3_vtab *); for(p=pTab->u.vtab.p; p; p=p->pNext){ assert( p->pVtab ); if( p->pVtab->nRef>0 ){ return SQLITE_LOCKED; } } p = vtabDisconnectAll(db, pTab); xDestroy = p->pMod->pModule->xDestroy; if( xDestroy==0 ) xDestroy = p->pMod->pModule->xDisconnect; assert( xDestroy!=0 ); pTab->nTabRef++; rc = xDestroy(p->pVtab); /* Remove the sqlite3_vtab* from the aVTrans[] array, if applicable */ if( rc==SQLITE_OK ){ assert( pTab->u.vtab.p==p && p->pNext==0 ); p->pVtab = 0; pTab->u.vtab.p = 0; sqlite3VtabUnlock(p); } sqlite3DeleteTable(db, pTab); } return rc; } |
︙ | ︙ | |||
144323 144324 144325 144326 144327 144328 144329 | sqlite3OomFault(pToplevel->db); } } /* ** Check to see if virtual table module pMod can be have an eponymous ** virtual table instance. If it can, create one if one does not already | | | > | 144551 144552 144553 144554 144555 144556 144557 144558 144559 144560 144561 144562 144563 144564 144565 144566 144567 | sqlite3OomFault(pToplevel->db); } } /* ** Check to see if virtual table module pMod can be have an eponymous ** virtual table instance. If it can, create one if one does not already ** exist. Return non-zero if either the eponymous virtual table instance ** exists when this routine returns or if an attempt to create it failed ** and an error message was left in pParse. ** ** An eponymous virtual table instance is one that is named after its ** module, and more importantly, does not require a CREATE VIRTUAL TABLE ** statement in order to come into existance. Eponymous virtual table ** instances always exist. They cannot be DROP-ed. ** ** Any virtual table module for which xConnect and xCreate are the same |
︙ | ︙ | |||
144351 144352 144353 144354 144355 144356 144357 144358 | pTab->zName = sqlite3DbStrDup(db, pMod->zName); if( pTab->zName==0 ){ sqlite3DbFree(db, pTab); return 0; } pMod->pEpoTab = pTab; pTab->nTabRef = 1; pTab->pSchema = db->aDb[0].pSchema; | > | < | 144580 144581 144582 144583 144584 144585 144586 144587 144588 144589 144590 144591 144592 144593 144594 144595 144596 144597 144598 144599 144600 144601 144602 144603 144604 144605 144606 | pTab->zName = sqlite3DbStrDup(db, pMod->zName); if( pTab->zName==0 ){ sqlite3DbFree(db, pTab); return 0; } pMod->pEpoTab = pTab; pTab->nTabRef = 1; pTab->eTabType = TABTYP_VTAB; pTab->pSchema = db->aDb[0].pSchema; assert( pTab->u.vtab.nArg==0 ); pTab->iPKey = -1; pTab->tabFlags |= TF_Eponymous; addModuleArgument(pParse, pTab, sqlite3DbStrDup(db, pTab->zName)); addModuleArgument(pParse, pTab, 0); addModuleArgument(pParse, pTab, sqlite3DbStrDup(db, pTab->zName)); rc = vtabCallConstructor(db, pTab, pMod, pModule->xConnect, &zErr); if( rc ){ sqlite3ErrorMsg(pParse, "%s", zErr); sqlite3DbFree(db, zErr); sqlite3VtabEponymousTableClear(db, pMod); } return 1; } /* ** Erase the eponymous virtual table instance associated with ** virtual table module pMod, if it exists. |
︙ | ︙ | |||
145097 145098 145099 145100 145101 145102 145103 | /* ** Return the name of the i-th column of the pIdx index. */ static const char *explainIndexColumnName(Index *pIdx, int i){ i = pIdx->aiColumn[i]; if( i==XN_EXPR ) return "<expr>"; if( i==XN_ROWID ) return "rowid"; | | | 145326 145327 145328 145329 145330 145331 145332 145333 145334 145335 145336 145337 145338 145339 145340 | /* ** Return the name of the i-th column of the pIdx index. */ static const char *explainIndexColumnName(Index *pIdx, int i){ i = pIdx->aiColumn[i]; if( i==XN_EXPR ) return "<expr>"; if( i==XN_ROWID ) return "rowid"; return pIdx->pTable->aCol[i].zCnName; } /* ** This routine is a helper for explainIndexRange() below ** ** pStr holds the text of an expression that we are building up one term ** at a time. This routine adds a new term to the end of the expression. |
︙ | ︙ | |||
146309 146310 146311 146312 146313 146314 146315 | assert( aColExpr->a[iIdxCol].pExpr!=0 ); x.pIdxExpr = aColExpr->a[iIdxCol].pExpr; if( sqlite3ExprIsConstant(x.pIdxExpr) ) continue; w.xExprCallback = whereIndexExprTransNode; #ifndef SQLITE_OMIT_GENERATED_COLUMNS }else if( iRef>=0 && (pTab->aCol[iRef].colFlags & COLFLAG_VIRTUAL)!=0 | | > | | 146538 146539 146540 146541 146542 146543 146544 146545 146546 146547 146548 146549 146550 146551 146552 146553 146554 | assert( aColExpr->a[iIdxCol].pExpr!=0 ); x.pIdxExpr = aColExpr->a[iIdxCol].pExpr; if( sqlite3ExprIsConstant(x.pIdxExpr) ) continue; w.xExprCallback = whereIndexExprTransNode; #ifndef SQLITE_OMIT_GENERATED_COLUMNS }else if( iRef>=0 && (pTab->aCol[iRef].colFlags & COLFLAG_VIRTUAL)!=0 && ((pTab->aCol[iRef].colFlags & COLFLAG_HASCOLL)==0 || sqlite3StrICmp(sqlite3ColumnColl(&pTab->aCol[iRef]), sqlite3StrBINARY)==0) ){ /* Check to see if there are direct references to generated columns ** that are contained in the index. Pulling the generated column ** out of the index is an optimization only - the main table is always ** available if the index cannot be used. To avoid unnecessary ** complication, omit this optimization if the collating sequence for ** the column is non-standard */ |
︙ | ︙ | |||
148729 148730 148731 148732 148733 148734 148735 | pNew->wtFlags |= exprCommute(pParse, pDup); pNew->leftCursor = aiCurCol[0]; pNew->u.x.leftColumn = aiCurCol[1]; testcase( (prereqLeft | extraRight) != prereqLeft ); pNew->prereqRight = prereqLeft | extraRight; pNew->prereqAll = prereqAll; pNew->eOperator = (operatorMask(pDup->op) + eExtraOp) & opMask; | > > > | > | 148959 148960 148961 148962 148963 148964 148965 148966 148967 148968 148969 148970 148971 148972 148973 148974 148975 148976 148977 | pNew->wtFlags |= exprCommute(pParse, pDup); pNew->leftCursor = aiCurCol[0]; pNew->u.x.leftColumn = aiCurCol[1]; testcase( (prereqLeft | extraRight) != prereqLeft ); pNew->prereqRight = prereqLeft | extraRight; pNew->prereqAll = prereqAll; pNew->eOperator = (operatorMask(pDup->op) + eExtraOp) & opMask; }else if( op==TK_ISNULL && !ExprHasProperty(pExpr,EP_FromJoin) && 0==sqlite3ExprCanBeNull(pLeft) ){ pExpr->op = TK_TRUEFALSE; pExpr->u.zToken = "false"; ExprSetProperty(pExpr, EP_IsFalse); pTerm->prereqAll = 0; pTerm->eOperator = 0; } } |
︙ | ︙ | |||
148926 148927 148928 148929 148930 148931 148932 | || (pExpr->pRight->flags & EP_xIsSelect)==0) && pWC->op==TK_AND ){ int i; for(i=0; i<nLeft; i++){ int idxNew; Expr *pNew; | | | | 149160 149161 149162 149163 149164 149165 149166 149167 149168 149169 149170 149171 149172 149173 149174 149175 | || (pExpr->pRight->flags & EP_xIsSelect)==0) && pWC->op==TK_AND ){ int i; for(i=0; i<nLeft; i++){ int idxNew; Expr *pNew; Expr *pLeft = sqlite3ExprForVectorField(pParse, pExpr->pLeft, i, nLeft); Expr *pRight = sqlite3ExprForVectorField(pParse, pExpr->pRight, i, nLeft); pNew = sqlite3PExpr(pParse, pExpr->op, pLeft, pRight); transferJoinMarkings(pNew, pExpr); idxNew = whereClauseInsert(pWC, pNew, TERM_DYNAMIC); exprAnalyze(pSrc, pWC, idxNew); } pTerm = &pWC->a[idxTerm]; |
︙ | ︙ | |||
150016 150017 150018 150019 150020 150021 150022 | int iCol = pTerm->u.x.leftColumn; Bitmask cMask = iCol>=BMS ? MASKBIT(BMS-1) : MASKBIT(iCol); testcase( iCol==BMS ); testcase( iCol==BMS-1 ); if( !sentWarning ){ sqlite3_log(SQLITE_WARNING_AUTOINDEX, "automatic index on %s(%s)", pTable->zName, | | | 150250 150251 150252 150253 150254 150255 150256 150257 150258 150259 150260 150261 150262 150263 150264 | int iCol = pTerm->u.x.leftColumn; Bitmask cMask = iCol>=BMS ? MASKBIT(BMS-1) : MASKBIT(iCol); testcase( iCol==BMS ); testcase( iCol==BMS-1 ); if( !sentWarning ){ sqlite3_log(SQLITE_WARNING_AUTOINDEX, "automatic index on %s(%s)", pTable->zName, pTable->aCol[iCol].zCnName); sentWarning = 1; } if( (idxCols & cMask)==0 ){ if( whereLoopResize(pParse->db, pLoop, nKeyCol+1) ){ goto end_auto_index_create; } pLoop->aLTerm[nKeyCol++] = pTerm; |
︙ | ︙ | |||
151930 151931 151932 151933 151934 151935 151936 | pNew->nOut += pTerm->truthProb; pNew->nOut -= nIn; }else{ #ifdef SQLITE_ENABLE_STAT4 tRowcnt nOut = 0; if( nInMul==0 && pProbe->nSample | | | 152164 152165 152166 152167 152168 152169 152170 152171 152172 152173 152174 152175 152176 152177 152178 | pNew->nOut += pTerm->truthProb; pNew->nOut -= nIn; }else{ #ifdef SQLITE_ENABLE_STAT4 tRowcnt nOut = 0; if( nInMul==0 && pProbe->nSample && ALWAYS(pNew->u.btree.nEq<=pProbe->nSampleCol) && ((eOp & WO_IN)==0 || !ExprHasProperty(pTerm->pExpr, EP_xIsSelect)) && OptimizationEnabled(db, SQLITE_Stat4) ){ Expr *pExpr = pTerm->pExpr; if( (eOp & (WO_EQ|WO_ISNULL|WO_IS))!=0 ){ testcase( eOp & WO_EQ ); testcase( eOp & WO_IS ); |
︙ | ︙ | |||
152195 152196 152197 152198 152199 152200 152201 | SrcList *pTabList; /* The FROM clause */ SrcItem *pSrc; /* The FROM clause btree term to add */ WhereLoop *pNew; /* Template WhereLoop object */ int rc = SQLITE_OK; /* Return code */ int iSortIdx = 1; /* Index number */ int b; /* A boolean value */ LogEst rSize; /* number of rows in the table */ | < | 152429 152430 152431 152432 152433 152434 152435 152436 152437 152438 152439 152440 152441 152442 | SrcList *pTabList; /* The FROM clause */ SrcItem *pSrc; /* The FROM clause btree term to add */ WhereLoop *pNew; /* Template WhereLoop object */ int rc = SQLITE_OK; /* Return code */ int iSortIdx = 1; /* Index number */ int b; /* A boolean value */ LogEst rSize; /* number of rows in the table */ WhereClause *pWC; /* The parsed WHERE clause */ Table *pTab; /* Table being queried */ pNew = pBuilder->pNew; pWInfo = pBuilder->pWInfo; pTabList = pWInfo->pTabList; pSrc = pTabList->a + pNew->iTab; |
︙ | ︙ | |||
152238 152239 152240 152241 152242 152243 152244 | /* The real indices of the table are only considered if the ** NOT INDEXED qualifier is omitted from the FROM clause */ sPk.pNext = pFirst; } pProbe = &sPk; } rSize = pTab->nRowLogEst; | < > > | | 152471 152472 152473 152474 152475 152476 152477 152478 152479 152480 152481 152482 152483 152484 152485 152486 152487 152488 152489 152490 152491 152492 152493 152494 152495 152496 152497 152498 152499 152500 152501 152502 152503 152504 152505 152506 152507 152508 152509 152510 152511 152512 152513 152514 152515 152516 152517 152518 152519 | /* The real indices of the table are only considered if the ** NOT INDEXED qualifier is omitted from the FROM clause */ sPk.pNext = pFirst; } pProbe = &sPk; } rSize = pTab->nRowLogEst; #ifndef SQLITE_OMIT_AUTOMATIC_INDEX /* Automatic indexes */ if( !pBuilder->pOrSet /* Not part of an OR optimization */ && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0 && (pWInfo->pParse->db->flags & SQLITE_AutoIndex)!=0 && !pSrc->fg.isIndexedBy /* Has no INDEXED BY clause */ && !pSrc->fg.notIndexed /* Has no NOT INDEXED clause */ && HasRowid(pTab) /* Not WITHOUT ROWID table. (FIXME: Why not?) */ && !pSrc->fg.isCorrelated /* Not a correlated subquery */ && !pSrc->fg.isRecursive /* Not a recursive common table expression. */ ){ /* Generate auto-index WhereLoops */ LogEst rLogSize; /* Logarithm of the number of rows in the table */ WhereTerm *pTerm; WhereTerm *pWCEnd = pWC->a + pWC->nTerm; rLogSize = estLog(rSize); for(pTerm=pWC->a; rc==SQLITE_OK && pTerm<pWCEnd; pTerm++){ if( pTerm->prereqRight & pNew->maskSelf ) continue; if( termCanDriveIndex(pTerm, pSrc, 0) ){ pNew->u.btree.nEq = 1; pNew->nSkip = 0; pNew->u.btree.pIndex = 0; pNew->nLTerm = 1; pNew->aLTerm[0] = pTerm; /* TUNING: One-time cost for computing the automatic index is ** estimated to be X*N*log2(N) where N is the number of rows in ** the table being indexed and where X is 7 (LogEst=28) for normal ** tables or 0.5 (LogEst=-10) for views and subqueries. The value ** of X is smaller for views and subqueries so that the query planner ** will be more aggressive about generating automatic indexes for ** those objects, since there is no opportunity to add schema ** indexes on subqueries and views. */ pNew->rSetup = rLogSize + rSize; if( !IsView(pTab) && (pTab->tabFlags & TF_Ephemeral)==0 ){ pNew->rSetup += 28; }else{ pNew->rSetup -= 10; } ApplyCostMultiplier(pNew->rSetup, pTab->costMult); if( pNew->rSetup<0 ) pNew->rSetup = 0; /* TUNING: Each index lookup yields 20 rows in the table. This |
︙ | ︙ | |||
154422 154423 154424 154425 154426 154427 154428 | int iDb; /* Index of database containing table/index */ SrcItem *pTabItem; pTabItem = &pTabList->a[pLevel->iFrom]; pTab = pTabItem->pTab; iDb = sqlite3SchemaToIndex(db, pTab->pSchema); pLoop = pLevel->pWLoop; | | | 154656 154657 154658 154659 154660 154661 154662 154663 154664 154665 154666 154667 154668 154669 154670 | int iDb; /* Index of database containing table/index */ SrcItem *pTabItem; pTabItem = &pTabList->a[pLevel->iFrom]; pTab = pTabItem->pTab; iDb = sqlite3SchemaToIndex(db, pTab->pSchema); pLoop = pLevel->pWLoop; if( (pTab->tabFlags & TF_Ephemeral)!=0 || IsView(pTab) ){ /* Do nothing */ }else #ifndef SQLITE_OMIT_VIRTUALTABLE if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 ){ const char *pVTab = (const char *)sqlite3GetVTable(db, pTab); int iCur = pTabItem->iCursor; sqlite3VdbeAddOp4(v, OP_VOpen, iCur, 0, 0, pVTab, P4_VTAB); |
︙ | ︙ | |||
154739 154740 154741 154742 154743 154744 154745 154746 154747 154748 154749 154750 154751 154752 | if( (ws & WHERE_IDX_ONLY)==0 ){ assert( pLevel->iTabCur==pTabList->a[pLevel->iFrom].iCursor ); sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iTabCur); } if( (ws & WHERE_INDEXED) || ((ws & WHERE_MULTI_OR) && pLevel->u.pCovidx) ){ sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iIdxCur); } if( pLevel->op==OP_Return ){ sqlite3VdbeAddOp2(v, OP_Gosub, pLevel->p1, pLevel->addrFirst); }else{ sqlite3VdbeGoto(v, pLevel->addrFirst); } | > > > > > > | 154973 154974 154975 154976 154977 154978 154979 154980 154981 154982 154983 154984 154985 154986 154987 154988 154989 154990 154991 154992 | if( (ws & WHERE_IDX_ONLY)==0 ){ assert( pLevel->iTabCur==pTabList->a[pLevel->iFrom].iCursor ); sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iTabCur); } if( (ws & WHERE_INDEXED) || ((ws & WHERE_MULTI_OR) && pLevel->u.pCovidx) ){ if( ws & WHERE_MULTI_OR ){ Index *pIx = pLevel->u.pCovidx; int iDb = sqlite3SchemaToIndex(db, pIx->pSchema); sqlite3VdbeAddOp3(v, OP_ReopenIdx, pLevel->iIdxCur, pIx->tnum, iDb); sqlite3VdbeSetP4KeyInfo(pParse, pIx); } sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iIdxCur); } if( pLevel->op==OP_Return ){ sqlite3VdbeAddOp2(v, OP_Gosub, pLevel->p1, pLevel->addrFirst); }else{ sqlite3VdbeGoto(v, pLevel->addrFirst); } |
︙ | ︙ | |||
154785 154786 154787 154788 154789 154790 154791 | #ifdef SQLITE_ENABLE_EARLY_CURSOR_CLOSE /* Close all of the cursors that were opened by sqlite3WhereBegin. ** Except, do not close cursors that will be reused by the OR optimization ** (WHERE_OR_SUBCLAUSE). And do not close the OP_OpenWrite cursors ** created for the ONEPASS optimization. */ if( (pTab->tabFlags & TF_Ephemeral)==0 | | | 155025 155026 155027 155028 155029 155030 155031 155032 155033 155034 155035 155036 155037 155038 155039 | #ifdef SQLITE_ENABLE_EARLY_CURSOR_CLOSE /* Close all of the cursors that were opened by sqlite3WhereBegin. ** Except, do not close cursors that will be reused by the OR optimization ** (WHERE_OR_SUBCLAUSE). And do not close the OP_OpenWrite cursors ** created for the ONEPASS optimization. */ if( (pTab->tabFlags & TF_Ephemeral)==0 && !IsView(pTab) && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0 ){ int ws = pLoop->wsFlags; if( pWInfo->eOnePass==ONEPASS_OFF && (ws & WHERE_IDX_ONLY)==0 ){ sqlite3VdbeAddOp1(v, OP_Close, pTabItem->iCursor); } if( (ws & WHERE_INDEXED)!=0 |
︙ | ︙ | |||
155803 155804 155805 155806 155807 155808 155809 | if( db->mallocFailed ){ sqlite3ExprDelete(db, pDup); break; } if( bIntToNull ){ int iDummy; Expr *pSub; | < | < | 156043 156044 156045 156046 156047 156048 156049 156050 156051 156052 156053 156054 156055 156056 156057 | if( db->mallocFailed ){ sqlite3ExprDelete(db, pDup); break; } if( bIntToNull ){ int iDummy; Expr *pSub; pSub = sqlite3ExprSkipCollateAndLikely(pDup); if( sqlite3ExprIsInteger(pSub, &iDummy) ){ pSub->op = TK_NULL; pSub->flags &= ~(EP_IntValue|EP_IsTrue|EP_IsFalse); pSub->u.zToken = 0; } } pList = sqlite3ExprListAppend(pParse, pList, pDup); |
︙ | ︙ | |||
155967 155968 155969 155970 155971 155972 155973 | ("New window-function subquery in FROM clause of (%u/%p)\n", p->selId, p)); p->pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0); if( p->pSrc ){ Table *pTab2; p->pSrc->a[0].pSelect = pSub; sqlite3SrcListAssignCursors(pParse, p->pSrc); | | | 156205 156206 156207 156208 156209 156210 156211 156212 156213 156214 156215 156216 156217 156218 156219 | ("New window-function subquery in FROM clause of (%u/%p)\n", p->selId, p)); p->pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0); if( p->pSrc ){ Table *pTab2; p->pSrc->a[0].pSelect = pSub; sqlite3SrcListAssignCursors(pParse, p->pSrc); pSub->selFlags |= SF_Expanded|SF_OrderByReqd; pTab2 = sqlite3ResultSetOfSelect(pParse, pSub, SQLITE_AFF_NONE); pSub->selFlags |= (selFlags & SF_Aggregate); if( pTab2==0 ){ /* Might actually be some other kind of error, but in that case ** pParse->nErr will be set, so if SQLITE_NOMEM is set, we will get ** the correct error message regardless. */ rc = SQLITE_NOMEM; |
︙ | ︙ | |||
161613 161614 161615 161616 161617 161618 161619 | }else{ yymsp[-1].minor.yy376 = 0; sqlite3ErrorMsg(pParse, "unknown table option: %.*s", yymsp[0].minor.yy0.n, yymsp[0].minor.yy0.z); } } break; case 23: /* columnname ::= nm typetoken */ | | | 161851 161852 161853 161854 161855 161856 161857 161858 161859 161860 161861 161862 161863 161864 161865 | }else{ yymsp[-1].minor.yy376 = 0; sqlite3ErrorMsg(pParse, "unknown table option: %.*s", yymsp[0].minor.yy0.n, yymsp[0].minor.yy0.z); } } break; case 23: /* columnname ::= nm typetoken */ {sqlite3AddColumn(pParse,yymsp[-1].minor.yy0,yymsp[0].minor.yy0);} break; case 24: /* typetoken ::= */ case 63: /* conslist_opt ::= */ yytestcase(yyruleno==63); case 102: /* as ::= */ yytestcase(yyruleno==102); {yymsp[1].minor.yy0.n = 0; yymsp[1].minor.yy0.z = 0;} break; case 25: /* typetoken ::= typename LP signed RP */ |
︙ | ︙ | |||
162417 162418 162419 162420 162421 162422 162423 | ** expr1 NOT IN () ** ** simplify to constants 0 (false) and 1 (true), respectively, ** regardless of the value of expr1. */ sqlite3ExprUnmapAndDelete(pParse, yymsp[-4].minor.yy404); yymsp[-4].minor.yy404 = sqlite3Expr(pParse->db, TK_INTEGER, yymsp[-3].minor.yy376 ? "1" : "0"); | | > | | | | < | | | > | > > > > | > | | > > | 162655 162656 162657 162658 162659 162660 162661 162662 162663 162664 162665 162666 162667 162668 162669 162670 162671 162672 162673 162674 162675 162676 162677 162678 162679 162680 162681 162682 162683 162684 162685 162686 162687 162688 162689 162690 | ** expr1 NOT IN () ** ** simplify to constants 0 (false) and 1 (true), respectively, ** regardless of the value of expr1. */ sqlite3ExprUnmapAndDelete(pParse, yymsp[-4].minor.yy404); yymsp[-4].minor.yy404 = sqlite3Expr(pParse->db, TK_INTEGER, yymsp[-3].minor.yy376 ? "1" : "0"); }else{ Expr *pRHS = yymsp[-1].minor.yy70->a[0].pExpr; if( yymsp[-1].minor.yy70->nExpr==1 && sqlite3ExprIsConstant(pRHS) && yymsp[-4].minor.yy404->op!=TK_VECTOR ){ yymsp[-1].minor.yy70->a[0].pExpr = 0; sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy70); pRHS = sqlite3PExpr(pParse, TK_UPLUS, pRHS, 0); yymsp[-4].minor.yy404 = sqlite3PExpr(pParse, TK_EQ, yymsp[-4].minor.yy404, pRHS); }else{ yymsp[-4].minor.yy404 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy404, 0); if( yymsp[-4].minor.yy404==0 ){ sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy70); }else if( yymsp[-4].minor.yy404->pLeft->op==TK_VECTOR ){ int nExpr = yymsp[-4].minor.yy404->pLeft->x.pList->nExpr; Select *pSelectRHS = sqlite3ExprListToValues(pParse, nExpr, yymsp[-1].minor.yy70); if( pSelectRHS ){ parserDoubleLinkSelect(pParse, pSelectRHS); sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy404, pSelectRHS); } }else{ yymsp[-4].minor.yy404->x.pList = yymsp[-1].minor.yy70; sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy404); } } if( yymsp[-3].minor.yy376 ) yymsp[-4].minor.yy404 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy404, 0); } } break; case 216: /* expr ::= LP select RP */ { |
︙ | ︙ | |||
166149 166150 166151 166152 166153 166154 166155 | db->lastRowid = iRowid; sqlite3_mutex_leave(db->mutex); } /* ** Return the number of changes in the most recent call to sqlite3_exec(). */ | | > > > | > > > | 166395 166396 166397 166398 166399 166400 166401 166402 166403 166404 166405 166406 166407 166408 166409 166410 166411 166412 166413 166414 166415 166416 166417 166418 166419 166420 166421 166422 166423 166424 166425 166426 166427 166428 166429 166430 166431 166432 166433 166434 166435 | db->lastRowid = iRowid; sqlite3_mutex_leave(db->mutex); } /* ** Return the number of changes in the most recent call to sqlite3_exec(). */ SQLITE_API sqlite3_int64 sqlite3_changes64(sqlite3 *db){ #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ){ (void)SQLITE_MISUSE_BKPT; return 0; } #endif return db->nChange; } SQLITE_API int sqlite3_changes(sqlite3 *db){ return (int)sqlite3_changes64(db); } /* ** Return the number of changes since the database handle was opened. */ SQLITE_API sqlite3_int64 sqlite3_total_changes64(sqlite3 *db){ #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ){ (void)SQLITE_MISUSE_BKPT; return 0; } #endif return db->nTotalChange; } SQLITE_API int sqlite3_total_changes(sqlite3 *db){ return (int)sqlite3_total_changes64(db); } /* ** Close all open savepoints. This function only manipulates fields of the ** database handle object, it does not close any savepoints that may be open ** at the b-tree/pager level. */ |
︙ | ︙ | |||
166911 166912 166913 166914 166915 166916 166917 | /* If SQLITE_UTF16 is specified as the encoding type, transform this ** to one of SQLITE_UTF16LE or SQLITE_UTF16BE using the ** SQLITE_UTF16NATIVE macro. SQLITE_UTF16 is not used internally. ** ** If SQLITE_ANY is specified, add three versions of the function ** to the hash table. */ | > | | > | | | | | | | | | | | | | | > > > > > > > > > | 167163 167164 167165 167166 167167 167168 167169 167170 167171 167172 167173 167174 167175 167176 167177 167178 167179 167180 167181 167182 167183 167184 167185 167186 167187 167188 167189 167190 167191 167192 167193 167194 167195 167196 167197 167198 167199 167200 167201 167202 167203 | /* If SQLITE_UTF16 is specified as the encoding type, transform this ** to one of SQLITE_UTF16LE or SQLITE_UTF16BE using the ** SQLITE_UTF16NATIVE macro. SQLITE_UTF16 is not used internally. ** ** If SQLITE_ANY is specified, add three versions of the function ** to the hash table. */ switch( enc ){ case SQLITE_UTF16: enc = SQLITE_UTF16NATIVE; break; case SQLITE_ANY: { int rc; rc = sqlite3CreateFunc(db, zFunctionName, nArg, (SQLITE_UTF8|extraFlags)^SQLITE_FUNC_UNSAFE, pUserData, xSFunc, xStep, xFinal, xValue, xInverse, pDestructor); if( rc==SQLITE_OK ){ rc = sqlite3CreateFunc(db, zFunctionName, nArg, (SQLITE_UTF16LE|extraFlags)^SQLITE_FUNC_UNSAFE, pUserData, xSFunc, xStep, xFinal, xValue, xInverse, pDestructor); } if( rc!=SQLITE_OK ){ return rc; } enc = SQLITE_UTF16BE; break; } case SQLITE_UTF8: case SQLITE_UTF16LE: case SQLITE_UTF16BE: break; default: enc = SQLITE_UTF8; break; } #else enc = SQLITE_UTF8; #endif /* Check if an existing function is being overridden or deleted. If so, ** and there are active VMs, then return SQLITE_BUSY. If a function |
︙ | ︙ | |||
167023 167024 167025 167026 167027 167028 167029 | pArg->xDestroy = xDestroy; pArg->pUserData = p; } rc = sqlite3CreateFunc(db, zFunc, nArg, enc, p, xSFunc, xStep, xFinal, xValue, xInverse, pArg ); if( pArg && pArg->nRef==0 ){ | | | 167286 167287 167288 167289 167290 167291 167292 167293 167294 167295 167296 167297 167298 167299 167300 | pArg->xDestroy = xDestroy; pArg->pUserData = p; } rc = sqlite3CreateFunc(db, zFunc, nArg, enc, p, xSFunc, xStep, xFinal, xValue, xInverse, pArg ); if( pArg && pArg->nRef==0 ){ assert( rc!=SQLITE_OK || (xStep==0 && xFinal==0) ); xDestroy(p); sqlite3_free(pArg); } out: rc = sqlite3ApiExit(db, rc); sqlite3_mutex_leave(db->mutex); |
︙ | ︙ | |||
168206 168207 168208 168209 168210 168211 168212 | ** dealt with in the previous code block. Besides these, the only ** valid input flags for sqlite3_open_v2() are SQLITE_OPEN_READONLY, ** SQLITE_OPEN_READWRITE, SQLITE_OPEN_CREATE, SQLITE_OPEN_SHAREDCACHE, ** SQLITE_OPEN_PRIVATECACHE, and some reserved bits. Silently mask ** off all other flags. */ flags &= ~( SQLITE_OPEN_DELETEONCLOSE | | < | 168469 168470 168471 168472 168473 168474 168475 168476 168477 168478 168479 168480 168481 168482 | ** dealt with in the previous code block. Besides these, the only ** valid input flags for sqlite3_open_v2() are SQLITE_OPEN_READONLY, ** SQLITE_OPEN_READWRITE, SQLITE_OPEN_CREATE, SQLITE_OPEN_SHAREDCACHE, ** SQLITE_OPEN_PRIVATECACHE, and some reserved bits. Silently mask ** off all other flags. */ flags &= ~( SQLITE_OPEN_DELETEONCLOSE | SQLITE_OPEN_MAIN_DB | SQLITE_OPEN_TEMP_DB | SQLITE_OPEN_TRANSIENT_DB | SQLITE_OPEN_MAIN_JOURNAL | SQLITE_OPEN_TEMP_JOURNAL | SQLITE_OPEN_SUBJOURNAL | SQLITE_OPEN_SUPER_JOURNAL | |
︙ | ︙ | |||
168778 168779 168780 168781 168782 168783 168784 | rc = sqlite3Init(db, &zErrMsg); if( SQLITE_OK!=rc ){ goto error_out; } /* Locate the table in question */ pTab = sqlite3FindTable(db, zTableName, zDbName); | | | | 169040 169041 169042 169043 169044 169045 169046 169047 169048 169049 169050 169051 169052 169053 169054 169055 169056 169057 169058 169059 169060 169061 169062 169063 169064 169065 | rc = sqlite3Init(db, &zErrMsg); if( SQLITE_OK!=rc ){ goto error_out; } /* Locate the table in question */ pTab = sqlite3FindTable(db, zTableName, zDbName); if( !pTab || IsView(pTab) ){ pTab = 0; goto error_out; } /* Find the column for which info is requested */ if( zColumnName==0 ){ /* Query for existance of table only */ }else{ for(iCol=0; iCol<pTab->nCol; iCol++){ pCol = &pTab->aCol[iCol]; if( 0==sqlite3StrICmp(pCol->zCnName, zColumnName) ){ break; } } if( iCol==pTab->nCol ){ if( HasRowid(pTab) && sqlite3IsRowid(zColumnName) ){ iCol = pTab->iPKey; pCol = iCol>=0 ? &pTab->aCol[iCol] : 0; |
︙ | ︙ | |||
168816 168817 168818 168819 168820 168821 168822 | ** and there is no explicitly declared IPK column. ** ** 2. The table is not a view and the column name identified an ** explicitly declared column. Copy meta information from *pCol. */ if( pCol ){ zDataType = sqlite3ColumnType(pCol,0); | | | 169078 169079 169080 169081 169082 169083 169084 169085 169086 169087 169088 169089 169090 169091 169092 | ** and there is no explicitly declared IPK column. ** ** 2. The table is not a view and the column name identified an ** explicitly declared column. Copy meta information from *pCol. */ if( pCol ){ zDataType = sqlite3ColumnType(pCol,0); zCollSeq = sqlite3ColumnColl(pCol); notnull = pCol->notNull!=0; primarykey = (pCol->colFlags & COLFLAG_PRIMKEY)!=0; autoinc = pTab->iPKey==iCol && (pTab->tabFlags & TF_Autoincrement)!=0; }else{ zDataType = "INTEGER"; primarykey = 1; } |
︙ | ︙ | |||
169347 169348 169349 169350 169351 169352 169353 | case 1: sqlite3SelectTrace = *ptr; break; case 2: *ptr = sqlite3WhereTrace; break; case 3: sqlite3WhereTrace = *ptr; break; } break; } | | | 169609 169610 169611 169612 169613 169614 169615 169616 169617 169618 169619 169620 169621 169622 169623 | case 1: sqlite3SelectTrace = *ptr; break; case 2: *ptr = sqlite3WhereTrace; break; case 3: sqlite3WhereTrace = *ptr; break; } break; } #if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_WSD) /* sqlite3_test_control(SQLITE_TESTCTRL_TUNE, id, *piValue) ** ** If "id" is an integer between 1 and SQLITE_NTUNE then set the value ** of the id-th tuning parameter to *piValue. If "id" is between -1 ** and -SQLITE_NTUNE, then write the current value of the (-id)-th ** tuning parameter into *piValue. ** |
︙ | ︙ | |||
201249 201250 201251 201252 201253 201254 201255 | *peType = RBU_PK_NOTABLE; *piPk = 0; assert( p->rc==SQLITE_OK ); p->rc = prepareFreeAndCollectError(p->dbMain, &aStmt[0], &p->zErrmsg, sqlite3_mprintf( | | > > | 201511 201512 201513 201514 201515 201516 201517 201518 201519 201520 201521 201522 201523 201524 201525 201526 201527 | *peType = RBU_PK_NOTABLE; *piPk = 0; assert( p->rc==SQLITE_OK ); p->rc = prepareFreeAndCollectError(p->dbMain, &aStmt[0], &p->zErrmsg, sqlite3_mprintf( "SELECT " " (sql COLLATE nocase BETWEEN 'CREATE VIRTUAL' AND 'CREATE VIRTUAM')," " rootpage" " FROM sqlite_schema" " WHERE name=%Q", zTab )); if( p->rc!=SQLITE_OK || sqlite3_step(aStmt[0])!=SQLITE_ROW ){ /* Either an error, or no such table. */ goto rbuTableType_end; } |
︙ | ︙ | |||
202782 202783 202784 202785 202786 202787 202788 | break; case RBU_STATE_COOKIE: pRet->iCookie = (u32)sqlite3_column_int64(pStmt, 1); break; case RBU_STATE_OALSZ: | | | 203046 203047 203048 203049 203050 203051 203052 203053 203054 203055 203056 203057 203058 203059 203060 | break; case RBU_STATE_COOKIE: pRet->iCookie = (u32)sqlite3_column_int64(pStmt, 1); break; case RBU_STATE_OALSZ: pRet->iOalSz = sqlite3_column_int64(pStmt, 1); break; case RBU_STATE_PHASEONESTEP: pRet->nPhaseOneStep = sqlite3_column_int64(pStmt, 1); break; case RBU_STATE_DATATBL: |
︙ | ︙ | |||
213426 213427 213428 213429 213430 213431 213432 213433 213434 213435 213436 213437 213438 213439 | static void sqlite3Fts5IndexCloseReader(Fts5Index*); /* ** This interface is used by the fts5vocab module. */ static const char *sqlite3Fts5IterTerm(Fts5IndexIter*, int*); static int sqlite3Fts5IterNextScan(Fts5IndexIter*); /* ** Insert or remove data to or from the index. Each time a document is ** added to or removed from the index, this function is called one or more ** times. ** | > > > | 213690 213691 213692 213693 213694 213695 213696 213697 213698 213699 213700 213701 213702 213703 213704 213705 213706 | static void sqlite3Fts5IndexCloseReader(Fts5Index*); /* ** This interface is used by the fts5vocab module. */ static const char *sqlite3Fts5IterTerm(Fts5IndexIter*, int*); static int sqlite3Fts5IterNextScan(Fts5IndexIter*); static void *sqlite3Fts5StructureRef(Fts5Index*); static void sqlite3Fts5StructureRelease(void*); static int sqlite3Fts5StructureTest(Fts5Index*, void*); /* ** Insert or remove data to or from the index. Each time a document is ** added to or removed from the index, this function is called one or more ** times. ** |
︙ | ︙ | |||
216221 216222 216223 216224 216225 216226 216227 | int i = *pi; if( i>=n ){ /* EOF */ *piOff = -1; return 1; }else{ i64 iOff = *piOff; | | > | | 216488 216489 216490 216491 216492 216493 216494 216495 216496 216497 216498 216499 216500 216501 216502 216503 216504 216505 216506 216507 216508 216509 216510 216511 216512 216513 216514 216515 216516 216517 216518 216519 216520 216521 216522 216523 216524 | int i = *pi; if( i>=n ){ /* EOF */ *piOff = -1; return 1; }else{ i64 iOff = *piOff; u32 iVal; fts5FastGetVarint32(a, i, iVal); assert( iVal>=0 ); if( iVal<=1 ){ if( iVal==0 ){ *pi = i; return 0; } fts5FastGetVarint32(a, i, iVal); iOff = ((i64)iVal) << 32; assert( iOff>=0 ); fts5FastGetVarint32(a, i, iVal); if( iVal<2 ){ /* This is a corrupt record. So stop parsing it here. */ *piOff = -1; return 1; } *piOff = iOff + ((iVal-2) & 0x7FFFFFFF); }else{ *piOff = (iOff & (i64)0x7FFFFFFF<<32)+((iOff + (iVal-2)) & 0x7FFFFFFF); } *pi = i; assert_nc( *piOff>=iOff ); return 0; } } /* ** Advance the iterator object passed as the only argument. Return true |
︙ | ︙ | |||
217551 217552 217553 217554 217555 217556 217557 217558 217559 217560 217561 217562 217563 217564 | int bPhraseToAnd; /* Convert "a+b" to "a AND b" */ }; static void sqlite3Fts5ParseError(Fts5Parse *pParse, const char *zFmt, ...){ va_list ap; va_start(ap, zFmt); if( pParse->rc==SQLITE_OK ){ pParse->zErr = sqlite3_vmprintf(zFmt, ap); pParse->rc = SQLITE_ERROR; } va_end(ap); } static int fts5ExprIsspace(char t){ | > | 217819 217820 217821 217822 217823 217824 217825 217826 217827 217828 217829 217830 217831 217832 217833 | int bPhraseToAnd; /* Convert "a+b" to "a AND b" */ }; static void sqlite3Fts5ParseError(Fts5Parse *pParse, const char *zFmt, ...){ va_list ap; va_start(ap, zFmt); if( pParse->rc==SQLITE_OK ){ assert( pParse->zErr==0 ); pParse->zErr = sqlite3_vmprintf(zFmt, ap); pParse->rc = SQLITE_ERROR; } va_end(ap); } static int fts5ExprIsspace(char t){ |
︙ | ︙ | |||
219560 219561 219562 219563 219564 219565 219566 | static void sqlite3Fts5ParseSetColset( Fts5Parse *pParse, Fts5ExprNode *pExpr, Fts5Colset *pColset ){ Fts5Colset *pFree = pColset; if( pParse->pConfig->eDetail==FTS5_DETAIL_NONE ){ | < | | | 219829 219830 219831 219832 219833 219834 219835 219836 219837 219838 219839 219840 219841 219842 219843 219844 | static void sqlite3Fts5ParseSetColset( Fts5Parse *pParse, Fts5ExprNode *pExpr, Fts5Colset *pColset ){ Fts5Colset *pFree = pColset; if( pParse->pConfig->eDetail==FTS5_DETAIL_NONE ){ sqlite3Fts5ParseError(pParse, "fts5: column queries are not supported (detail=none)" ); }else{ fts5ParseSetColset(pParse, pExpr, pColset, &pFree); } sqlite3_free(pFree); } |
︙ | ︙ | |||
219736 219737 219738 219739 219740 219741 219742 | if( pParse->pConfig->eDetail!=FTS5_DETAIL_FULL ){ Fts5ExprPhrase *pPhrase = pNear->apPhrase[0]; if( pNear->nPhrase!=1 || pPhrase->nTerm>1 || (pPhrase->nTerm>0 && pPhrase->aTerm[0].bFirst) ){ | < < < | | | 220004 220005 220006 220007 220008 220009 220010 220011 220012 220013 220014 220015 220016 220017 220018 220019 220020 220021 | if( pParse->pConfig->eDetail!=FTS5_DETAIL_FULL ){ Fts5ExprPhrase *pPhrase = pNear->apPhrase[0]; if( pNear->nPhrase!=1 || pPhrase->nTerm>1 || (pPhrase->nTerm>0 && pPhrase->aTerm[0].bFirst) ){ sqlite3Fts5ParseError(pParse, "fts5: %s queries are not supported (detail!=full)", pNear->nPhrase==1 ? "phrase": "NEAR" ); sqlite3_free(pRet); pRet = 0; } } }else{ fts5ExprAddChildren(pRet, pLeft); fts5ExprAddChildren(pRet, pRight); |
︙ | ︙ | |||
221859 221860 221861 221862 221863 221864 221865 221866 221867 221868 221869 221870 221871 221872 | sqlite3_free(pStruct); } } static void fts5StructureRef(Fts5Structure *pStruct){ pStruct->nRef++; } /* ** Deserialize and return the structure record currently stored in serialized ** form within buffer pData/nData. ** ** The Fts5Structure.aLevel[] and each Fts5StructureLevel.aSeg[] array ** are over-allocated by one slot. This allows the structure contents | > > > > > > > > > > > > > > > > | 222124 222125 222126 222127 222128 222129 222130 222131 222132 222133 222134 222135 222136 222137 222138 222139 222140 222141 222142 222143 222144 222145 222146 222147 222148 222149 222150 222151 222152 222153 | sqlite3_free(pStruct); } } static void fts5StructureRef(Fts5Structure *pStruct){ pStruct->nRef++; } static void *sqlite3Fts5StructureRef(Fts5Index *p){ fts5StructureRef(p->pStruct); return (void*)p->pStruct; } static void sqlite3Fts5StructureRelease(void *p){ if( p ){ fts5StructureRelease((Fts5Structure*)p); } } static int sqlite3Fts5StructureTest(Fts5Index *p, void *pStruct){ if( p->pStruct!=(Fts5Structure*)pStruct ){ return SQLITE_ABORT; } return SQLITE_OK; } /* ** Deserialize and return the structure record currently stored in serialized ** form within buffer pData/nData. ** ** The Fts5Structure.aLevel[] and each Fts5StructureLevel.aSeg[] array ** are over-allocated by one slot. This allows the structure contents |
︙ | ︙ | |||
230566 230567 230568 230569 230570 230571 230572 | static void fts5SourceIdFunc( sqlite3_context *pCtx, /* Function call context */ int nArg, /* Number of args */ sqlite3_value **apUnused /* Function arguments */ ){ assert( nArg==0 ); UNUSED_PARAM2(nArg, apUnused); | | | 230847 230848 230849 230850 230851 230852 230853 230854 230855 230856 230857 230858 230859 230860 230861 | static void fts5SourceIdFunc( sqlite3_context *pCtx, /* Function call context */ int nArg, /* Number of args */ sqlite3_value **apUnused /* Function arguments */ ){ assert( nArg==0 ); UNUSED_PARAM2(nArg, apUnused); sqlite3_result_text(pCtx, "fts5: 2021-08-06 20:17:39 087b8b41c6ed76b55c11315e7e95679d67590be20ae21108b593d00bb7d1c57a", -1, SQLITE_TRANSIENT); } /* ** Return true if zName is the extension on one of the shadow tables used ** by this module. */ static int fts5ShadowName(const char *zName){ |
︙ | ︙ | |||
234462 234463 234464 234465 234466 234467 234468 234469 234470 234471 234472 234473 234474 234475 | struct Fts5VocabCursor { sqlite3_vtab_cursor base; sqlite3_stmt *pStmt; /* Statement holding lock on pIndex */ Fts5Table *pFts5; /* Associated FTS5 table */ int bEof; /* True if this cursor is at EOF */ Fts5IndexIter *pIter; /* Term/rowid iterator object */ int nLeTerm; /* Size of zLeTerm in bytes */ char *zLeTerm; /* (term <= $zLeTerm) paramater, or NULL */ /* These are used by 'col' tables only */ int iCol; i64 *aCnt; | > | 234743 234744 234745 234746 234747 234748 234749 234750 234751 234752 234753 234754 234755 234756 234757 | struct Fts5VocabCursor { sqlite3_vtab_cursor base; sqlite3_stmt *pStmt; /* Statement holding lock on pIndex */ Fts5Table *pFts5; /* Associated FTS5 table */ int bEof; /* True if this cursor is at EOF */ Fts5IndexIter *pIter; /* Term/rowid iterator object */ void *pStruct; /* From sqlite3Fts5StructureRef() */ int nLeTerm; /* Size of zLeTerm in bytes */ char *zLeTerm; /* (term <= $zLeTerm) paramater, or NULL */ /* These are used by 'col' tables only */ int iCol; i64 *aCnt; |
︙ | ︙ | |||
234795 234796 234797 234798 234799 234800 234801 234802 234803 234804 234805 234806 234807 234808 | *ppCsr = (sqlite3_vtab_cursor*)pCsr; return rc; } static void fts5VocabResetCursor(Fts5VocabCursor *pCsr){ pCsr->rowid = 0; sqlite3Fts5IterClose(pCsr->pIter); pCsr->pIter = 0; sqlite3_free(pCsr->zLeTerm); pCsr->nLeTerm = -1; pCsr->zLeTerm = 0; pCsr->bEof = 0; } | > > | 235077 235078 235079 235080 235081 235082 235083 235084 235085 235086 235087 235088 235089 235090 235091 235092 | *ppCsr = (sqlite3_vtab_cursor*)pCsr; return rc; } static void fts5VocabResetCursor(Fts5VocabCursor *pCsr){ pCsr->rowid = 0; sqlite3Fts5IterClose(pCsr->pIter); sqlite3Fts5StructureRelease(pCsr->pStruct); pCsr->pStruct = 0; pCsr->pIter = 0; sqlite3_free(pCsr->zLeTerm); pCsr->nLeTerm = -1; pCsr->zLeTerm = 0; pCsr->bEof = 0; } |
︙ | ︙ | |||
234872 234873 234874 234875 234876 234877 234878 | /* ** Advance the cursor to the next row in the table. */ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){ Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor; Fts5VocabTable *pTab = (Fts5VocabTable*)pCursor->pVtab; | < > > > | 235156 235157 235158 235159 235160 235161 235162 235163 235164 235165 235166 235167 235168 235169 235170 235171 235172 235173 235174 | /* ** Advance the cursor to the next row in the table. */ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){ Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor; Fts5VocabTable *pTab = (Fts5VocabTable*)pCursor->pVtab; int nCol = pCsr->pFts5->pConfig->nCol; int rc; rc = sqlite3Fts5StructureTest(pCsr->pFts5->pIndex, pCsr->pStruct); if( rc!=SQLITE_OK ) return rc; pCsr->rowid++; if( pTab->eType==FTS5_VOCAB_INSTANCE ){ return fts5VocabInstanceNext(pCsr); } if( pTab->eType==FTS5_VOCAB_COL ){ |
︙ | ︙ | |||
235048 235049 235050 235051 235052 235053 235054 235055 235056 235057 235058 235059 235060 235061 | } } } if( rc==SQLITE_OK ){ Fts5Index *pIndex = pCsr->pFts5->pIndex; rc = sqlite3Fts5IndexQuery(pIndex, zTerm, nTerm, f, 0, &pCsr->pIter); } if( rc==SQLITE_OK && eType==FTS5_VOCAB_INSTANCE ){ rc = fts5VocabInstanceNewTerm(pCsr); } if( rc==SQLITE_OK && !pCsr->bEof && (eType!=FTS5_VOCAB_INSTANCE || pCsr->pFts5->pConfig->eDetail!=FTS5_DETAIL_NONE) | > > > | 235334 235335 235336 235337 235338 235339 235340 235341 235342 235343 235344 235345 235346 235347 235348 235349 235350 | } } } if( rc==SQLITE_OK ){ Fts5Index *pIndex = pCsr->pFts5->pIndex; rc = sqlite3Fts5IndexQuery(pIndex, zTerm, nTerm, f, 0, &pCsr->pIter); if( rc==SQLITE_OK ){ pCsr->pStruct = sqlite3Fts5StructureRef(pIndex); } } if( rc==SQLITE_OK && eType==FTS5_VOCAB_INSTANCE ){ rc = fts5VocabInstanceNewTerm(pCsr); } if( rc==SQLITE_OK && !pCsr->bEof && (eType!=FTS5_VOCAB_INSTANCE || pCsr->pFts5->pConfig->eDetail!=FTS5_DETAIL_NONE) |
︙ | ︙ | |||
235492 235493 235494 235495 235496 235497 235498 | #endif return rc; } #endif /* SQLITE_CORE */ #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */ /************** End of stmt.c ************************************************/ | < < < < | 235781 235782 235783 235784 235785 235786 235787 235788 235789 235790 | #endif return rc; } #endif /* SQLITE_CORE */ #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */ /************** End of stmt.c ************************************************/ /* Return the source-id for this library */ SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; } /************************** End of sqlite3.c ******************************/ |
Changes to src/sqlite3.h.
︙ | ︙ | |||
39 40 41 42 43 44 45 | */ #ifdef __cplusplus extern "C" { #endif /* | | > > > > > > > > > > > > > > > > > > > > > > > | 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | */ #ifdef __cplusplus extern "C" { #endif /* ** Facilitate override of interface linkage and calling conventions. ** Be aware that these macros may not be used within this particular ** translation of the amalgamation and its associated header file. ** ** The SQLITE_EXTERN and SQLITE_API macros are used to instruct the ** compiler that the target identifier should have external linkage. ** ** The SQLITE_CDECL macro is used to set the calling convention for ** public functions that accept a variable number of arguments. ** ** The SQLITE_APICALL macro is used to set the calling convention for ** public functions that accept a fixed number of arguments. ** ** The SQLITE_STDCALL macro is no longer used and is now deprecated. ** ** The SQLITE_CALLBACK macro is used to set the calling convention for ** function pointers. ** ** The SQLITE_SYSAPI macro is used to set the calling convention for ** functions provided by the operating system. ** ** Currently, the SQLITE_CDECL, SQLITE_APICALL, SQLITE_CALLBACK, and ** SQLITE_SYSAPI macros are used only when building for environments ** that require non-default calling conventions. */ #ifndef SQLITE_EXTERN # define SQLITE_EXTERN extern #endif #ifndef SQLITE_API # define SQLITE_API #endif |
︙ | ︙ | |||
119 120 121 122 123 124 125 | ** been edited in any way since it was last checked in, then the last ** four hexadecimal digits of the hash may be modified. ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ | | | | | 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | ** been edited in any way since it was last checked in, then the last ** four hexadecimal digits of the hash may be modified. ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.37.0" #define SQLITE_VERSION_NUMBER 3037000 #define SQLITE_SOURCE_ID "2021-08-06 20:17:39 087b8b41c6ed76b55c11315e7e95679d67590be20ae21108b593d00bb7d1c57a" /* ** CAPI3REF: Run-Time Library Version Numbers ** KEYWORDS: sqlite3_version sqlite3_sourceid ** ** These interfaces provide the same information as the [SQLITE_VERSION], ** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros |
︙ | ︙ | |||
512 513 514 515 516 517 518 519 520 521 522 523 524 525 | #define SQLITE_BUSY_TIMEOUT (SQLITE_BUSY | (3<<8)) #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8)) #define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8)) #define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8)) #define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8)) #define SQLITE_CANTOPEN_DIRTYWAL (SQLITE_CANTOPEN | (5<<8)) /* Not Used */ #define SQLITE_CANTOPEN_SYMLINK (SQLITE_CANTOPEN | (6<<8)) #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8)) #define SQLITE_CORRUPT_SEQUENCE (SQLITE_CORRUPT | (2<<8)) #define SQLITE_CORRUPT_INDEX (SQLITE_CORRUPT | (3<<8)) #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8)) #define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8)) #define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8)) #define SQLITE_READONLY_DBMOVED (SQLITE_READONLY | (4<<8)) | > | 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 | #define SQLITE_BUSY_TIMEOUT (SQLITE_BUSY | (3<<8)) #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8)) #define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8)) #define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8)) #define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8)) #define SQLITE_CANTOPEN_DIRTYWAL (SQLITE_CANTOPEN | (5<<8)) /* Not Used */ #define SQLITE_CANTOPEN_SYMLINK (SQLITE_CANTOPEN | (6<<8)) #define SQLITE_CANTOPEN_EXISTS (SQLITE_CANTOPEN | (7<<8)) #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8)) #define SQLITE_CORRUPT_SEQUENCE (SQLITE_CORRUPT | (2<<8)) #define SQLITE_CORRUPT_INDEX (SQLITE_CORRUPT | (3<<8)) #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8)) #define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8)) #define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8)) #define SQLITE_READONLY_DBMOVED (SQLITE_READONLY | (4<<8)) |
︙ | ︙ | |||
2460 2461 2462 2463 2464 2465 2466 | */ SQLITE_API void sqlite3_set_last_insert_rowid(sqlite3*,sqlite3_int64); /* ** CAPI3REF: Count The Number Of Rows Modified ** METHOD: sqlite3 ** | | > > > > | < | 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 | */ SQLITE_API void sqlite3_set_last_insert_rowid(sqlite3*,sqlite3_int64); /* ** CAPI3REF: Count The Number Of Rows Modified ** METHOD: sqlite3 ** ** ^These functions return the number of rows modified, inserted or ** deleted by the most recently completed INSERT, UPDATE or DELETE ** statement on the database connection specified by the only parameter. ** The two functions are identical except for the type of the return value ** and that if the number of rows modified by the most recent INSERT, UPDATE ** or DELETE is greater than the maximum value supported by type "int", then ** the return value of sqlite3_changes() is undefined. ^Executing any other ** type of SQL statement does not modify the value returned by these functions. ** ** ^Only changes made directly by the INSERT, UPDATE or DELETE statement are ** considered - auxiliary changes caused by [CREATE TRIGGER | triggers], ** [foreign key actions] or [REPLACE] constraint resolution are not counted. ** ** Changes to a view that are intercepted by ** [INSTEAD OF trigger | INSTEAD OF triggers] are not counted. ^The value |
︙ | ︙ | |||
2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 | ** <li> the [sqlite3_total_changes()] interface ** <li> the [count_changes pragma] ** <li> the [changes() SQL function] ** <li> the [data_version pragma] ** </ul> */ SQLITE_API int sqlite3_changes(sqlite3*); /* ** CAPI3REF: Total Number Of Rows Modified ** METHOD: sqlite3 ** | > | > > > > | | | 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 | ** <li> the [sqlite3_total_changes()] interface ** <li> the [count_changes pragma] ** <li> the [changes() SQL function] ** <li> the [data_version pragma] ** </ul> */ SQLITE_API int sqlite3_changes(sqlite3*); SQLITE_API sqlite3_int64 sqlite3_changes64(sqlite3*); /* ** CAPI3REF: Total Number Of Rows Modified ** METHOD: sqlite3 ** ** ^These functions return the total number of rows inserted, modified or ** deleted by all [INSERT], [UPDATE] or [DELETE] statements completed ** since the database connection was opened, including those executed as ** part of trigger programs. The two functions are identical except for the ** type of the return value and that if the number of rows modified by the ** connection exceeds the maximum value supported by type "int", then ** the return value of sqlite3_total_changes() is undefined. ^Executing ** any other type of SQL statement does not affect the value returned by ** sqlite3_total_changes(). ** ** ^Changes made as part of [foreign key actions] are included in the ** count, but those made as part of REPLACE constraint resolution are ** not. ^Changes to a view that are intercepted by INSTEAD OF triggers ** are not counted. ** ** The [sqlite3_total_changes(D)] interface only reports the number |
︙ | ︙ | |||
2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 | ** <li> the [count_changes pragma] ** <li> the [changes() SQL function] ** <li> the [data_version pragma] ** <li> the [SQLITE_FCNTL_DATA_VERSION] [file control] ** </ul> */ SQLITE_API int sqlite3_total_changes(sqlite3*); /* ** CAPI3REF: Interrupt A Long-Running Query ** METHOD: sqlite3 ** ** ^This function causes any pending database operation to abort and ** return at its earliest opportunity. This routine is typically | > | 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 | ** <li> the [count_changes pragma] ** <li> the [changes() SQL function] ** <li> the [data_version pragma] ** <li> the [SQLITE_FCNTL_DATA_VERSION] [file control] ** </ul> */ SQLITE_API int sqlite3_total_changes(sqlite3*); SQLITE_API sqlite3_int64 sqlite3_total_changes64(sqlite3*); /* ** CAPI3REF: Interrupt A Long-Running Query ** METHOD: sqlite3 ** ** ^This function causes any pending database operation to abort and ** return at its earliest opportunity. This routine is typically |
︙ | ︙ | |||
3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 | ** ^(<dt>[SQLITE_OPEN_PRIVATECACHE]</dt> ** <dd>The database is opened [shared cache] disabled, overriding ** the default shared cache setting provided by ** [sqlite3_enable_shared_cache()].)^ ** ** [[OPEN_NOFOLLOW]] ^(<dt>[SQLITE_OPEN_NOFOLLOW]</dt> ** <dd>The database filename is not allowed to be a symbolic link</dd> ** </dl>)^ ** ** If the 3rd parameter to sqlite3_open_v2() is not one of the ** required combinations shown above optionally combined with other ** [SQLITE_OPEN_READONLY | SQLITE_OPEN_* bits] ** then the behavior is undefined. ** | > > > > > > | 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 | ** ^(<dt>[SQLITE_OPEN_PRIVATECACHE]</dt> ** <dd>The database is opened [shared cache] disabled, overriding ** the default shared cache setting provided by ** [sqlite3_enable_shared_cache()].)^ ** ** [[OPEN_NOFOLLOW]] ^(<dt>[SQLITE_OPEN_NOFOLLOW]</dt> ** <dd>The database filename is not allowed to be a symbolic link</dd> ** ** [[OPEN_EXCLUSIVE]] ^(<dt>[SQLITE_OPEN_EXCLUSIVE]</dt> ** <dd>This flag causes the open to fail if the database file already ** exists. The open will only be success if this flag is used in combination ** with the SQLITE_OPEN_CREATE and SQLITE_OPEN_READWRITE flags and if ** the file does not previously exist.</dd> ** </dl>)^ ** ** If the 3rd parameter to sqlite3_open_v2() is not one of the ** required combinations shown above optionally combined with other ** [SQLITE_OPEN_READONLY | SQLITE_OPEN_* bits] ** then the behavior is undefined. ** |
︙ | ︙ | |||
4154 4155 4156 4157 4158 4159 4160 | ** bound parameter expansions. ^The [SQLITE_OMIT_TRACE] compile-time ** option causes sqlite3_expanded_sql() to always return NULL. ** ** ^The strings returned by sqlite3_sql(P) and sqlite3_normalized_sql(P) ** are managed by SQLite and are automatically freed when the prepared ** statement is finalized. ** ^The string returned by sqlite3_expanded_sql(P), on the other hand, | | > > > > > | 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 | ** bound parameter expansions. ^The [SQLITE_OMIT_TRACE] compile-time ** option causes sqlite3_expanded_sql() to always return NULL. ** ** ^The strings returned by sqlite3_sql(P) and sqlite3_normalized_sql(P) ** are managed by SQLite and are automatically freed when the prepared ** statement is finalized. ** ^The string returned by sqlite3_expanded_sql(P), on the other hand, ** is obtained from [sqlite3_malloc()] and must be freed by the application ** by passing it to [sqlite3_free()]. ** ** ^The sqlite3_normalized_sql() interface is only available if ** the [SQLITE_ENABLE_NORMALIZE] compile-time option is defined. */ SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt); SQLITE_API char *sqlite3_expanded_sql(sqlite3_stmt *pStmt); #ifdef SQLITE_ENABLE_NORMALIZE SQLITE_API const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt); #endif /* ** CAPI3REF: Determine If An SQL Statement Writes The Database ** METHOD: sqlite3_stmt ** ** ^The sqlite3_stmt_readonly(X) interface returns true (non-zero) if ** and only if the [prepared statement] X makes no direct changes to |
︙ | ︙ | |||
4374 4375 4376 4377 4378 4379 4380 | ** terminated. If any NUL characters occurs at byte offsets less than ** the value of the fourth parameter then the resulting string value will ** contain embedded NULs. The result of expressions involving strings ** with embedded NULs is undefined. ** ** ^The fifth argument to the BLOB and string binding interfaces controls ** or indicates the lifetime of the object referenced by the third parameter. | | | | | | 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 | ** terminated. If any NUL characters occurs at byte offsets less than ** the value of the fourth parameter then the resulting string value will ** contain embedded NULs. The result of expressions involving strings ** with embedded NULs is undefined. ** ** ^The fifth argument to the BLOB and string binding interfaces controls ** or indicates the lifetime of the object referenced by the third parameter. ** These three options exist: ** ^ (1) A destructor to dispose of the BLOB or string after SQLite has finished ** with it may be passed. ^It is called to dispose of the BLOB or string even ** if the call to the bind API fails, except the destructor is not called if ** the third parameter is a NULL pointer or the fourth parameter is negative. ** ^ (2) The special constant, [SQLITE_STATIC], may be passsed to indicate that ** the application remains responsible for disposing of the object. ^In this ** case, the object and the provided pointer to it must remain valid until ** either the prepared statement is finalized or the same SQL parameter is ** bound to something else, whichever occurs sooner. ** ^ (3) The constant, [SQLITE_TRANSIENT], may be passed to indicate that the ** object is to be copied prior to the return from sqlite3_bind_*(). ^The ** object and pointer to it must remain valid until then. ^SQLite will then ** manage the lifetime of its private copy. ** ** ^The sixth argument to sqlite3_bind_text64() must be one of ** [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE] ** to specify the encoding of the text in the third parameter. If |
︙ | ︙ | |||
9006 9007 9008 9009 9010 9011 9012 | ** to report an error, though the commit will have still occurred. If the ** callback returns [SQLITE_ROW] or [SQLITE_DONE], or if it returns a value ** that does not correspond to any valid SQLite error code, the results ** are undefined. ** ** A single database handle may have at most a single write-ahead log callback ** registered at one time. ^Calling [sqlite3_wal_hook()] replaces any | | > | | 9050 9051 9052 9053 9054 9055 9056 9057 9058 9059 9060 9061 9062 9063 9064 9065 9066 | ** to report an error, though the commit will have still occurred. If the ** callback returns [SQLITE_ROW] or [SQLITE_DONE], or if it returns a value ** that does not correspond to any valid SQLite error code, the results ** are undefined. ** ** A single database handle may have at most a single write-ahead log callback ** registered at one time. ^Calling [sqlite3_wal_hook()] replaces any ** previously registered write-ahead log callback. ^The return value is ** a copy of the third parameter from the previous call, if any, or 0. ** ^Note that the [sqlite3_wal_autocheckpoint()] interface and the ** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and will ** overwrite any prior [sqlite3_wal_hook()] settings. */ SQLITE_API void *sqlite3_wal_hook( sqlite3*, int(*)(void *,sqlite3*,const char*,int), void* |
︙ | ︙ | |||
9873 9874 9875 9876 9877 9878 9879 9880 9881 9882 9883 9884 9885 9886 | ** connection closes. If the SQLITE_DESERIALIZE_RESIZEABLE bit is set, then ** SQLite will try to increase the buffer size using sqlite3_realloc64() ** if writes on the database cause it to grow larger than M bytes. ** ** The sqlite3_deserialize() interface will fail with SQLITE_BUSY if the ** database is currently in a read transaction or is involved in a backup ** operation. ** ** If sqlite3_deserialize(D,S,P,N,M,F) fails for any reason and if the ** SQLITE_DESERIALIZE_FREEONCLOSE bit is set in argument F, then ** [sqlite3_free()] is invoked on argument P prior to returning. ** ** This interface is omitted if SQLite is compiled with the ** [SQLITE_OMIT_DESERIALIZE] option. | > > > > | 9918 9919 9920 9921 9922 9923 9924 9925 9926 9927 9928 9929 9930 9931 9932 9933 9934 9935 | ** connection closes. If the SQLITE_DESERIALIZE_RESIZEABLE bit is set, then ** SQLite will try to increase the buffer size using sqlite3_realloc64() ** if writes on the database cause it to grow larger than M bytes. ** ** The sqlite3_deserialize() interface will fail with SQLITE_BUSY if the ** database is currently in a read transaction or is involved in a backup ** operation. ** ** It is not possible to deserialized into the TEMP database. If the ** S argument to sqlite3_deserialize(D,S,P,N,M,F) is "temp" then the ** function returns SQLITE_ERROR. ** ** If sqlite3_deserialize(D,S,P,N,M,F) fails for any reason and if the ** SQLITE_DESERIALIZE_FREEONCLOSE bit is set in argument F, then ** [sqlite3_free()] is invoked on argument P prior to returning. ** ** This interface is omitted if SQLite is compiled with the ** [SQLITE_OMIT_DESERIALIZE] option. |
︙ | ︙ |
Changes to src/stash.c.
︙ | ︙ | |||
440 441 442 443 444 445 446 | diff_print_index(zNew, diffFlags, 0); isBin2 = 0; if( fBaseline ){ content_get(rid, &a); isBin1 = fIncludeBinary ? 0 : looks_like_binary(&a); diff_file_mem(&a, &empty, isBin1, isBin2, zOrig, zDiffCmd, zBinGlob, fIncludeBinary, diffFlags); | < | 440 441 442 443 444 445 446 447 448 449 450 451 452 453 | diff_print_index(zNew, diffFlags, 0); isBin2 = 0; if( fBaseline ){ content_get(rid, &a); isBin1 = fIncludeBinary ? 0 : looks_like_binary(&a); diff_file_mem(&a, &empty, isBin1, isBin2, zOrig, zDiffCmd, zBinGlob, fIncludeBinary, diffFlags); } }else{ Blob delta; int isOrigLink = file_islink(zOPath); db_ephemeral_blob(&q, 6, &delta); fossil_print("CHANGED %s\n", zNew); if( !isOrigLink != !isLink ){ |
︙ | ︙ | |||
470 471 472 473 474 475 476 | zBinGlob, fIncludeBinary, diffFlags, 1, 0); } blob_reset(&a); blob_reset(&b); } blob_reset(&delta); } | | | 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 | zBinGlob, fIncludeBinary, diffFlags, 1, 0); } blob_reset(&a); blob_reset(&b); } blob_reset(&delta); } } db_finalize(&q); } /* ** Drop the indicated stash */ static void stash_drop(int stashid){ |
︙ | ︙ |
Changes to src/stat.c.
︙ | ︙ | |||
167 168 169 170 171 172 173 | fsize = file_size(g.zRepositoryName, ExtFILE); @ <tr><th>Repository Size:</th><td>%,lld(fsize) bytes</td> @ </td></tr> if( !brief ){ @ <tr><th>Number Of Artifacts:</th><td> n = db_int(0, "SELECT count(*) FROM blob WHERE content IS NOT NULL"); m = db_int(0, "SELECT count(*) FROM delta"); | | | 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 | fsize = file_size(g.zRepositoryName, ExtFILE); @ <tr><th>Repository Size:</th><td>%,lld(fsize) bytes</td> @ </td></tr> if( !brief ){ @ <tr><th>Number Of Artifacts:</th><td> n = db_int(0, "SELECT count(*) FROM blob WHERE content IS NOT NULL"); m = db_int(0, "SELECT count(*) FROM delta"); @ %,d(n) (%,d(n-m) fulltext and %,d(m) deltas) if( g.perm.Write ){ @ <a href='%R/artifact_stats'>Details</a> } @ </td></tr> if( n>0 ){ int a, b; Stmt q; |
︙ | ︙ | |||
478 479 480 481 482 483 484 | */ void urllist_page(void){ Stmt q; int cnt; int showAll = P("all")!=0; int nOmitted; sqlite3_int64 iNow; | | | | 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 | */ void urllist_page(void){ Stmt q; int cnt; int showAll = P("all")!=0; int nOmitted; sqlite3_int64 iNow; login_check_credentials(); if( !g.perm.Admin ){ login_needed(0); return; } style_set_current_feature("stat"); style_header("URLs and Checkouts"); style_adunit_config(ADUNIT_RIGHT_OK); style_submenu_element("Stat", "stat"); style_submenu_element("Schema", "repo_schema"); iNow = db_int64(0, "SELECT strftime('%%s','now')"); @ <div class="section">URLs used to access</div> @ <table border="0" width='100%%'> db_prepare(&q, "SELECT substr(name,9), datetime(mtime,'unixepoch'), mtime" " FROM config WHERE name GLOB 'baseurl:*' ORDER BY 3 DESC"); cnt = 0; nOmitted = 0; while( db_step(&q)==SQLITE_ROW ){ if( !showAll && db_column_int64(&q,2)<(iNow - 3600*24*30) && cnt>8 ){ |
︙ | ︙ | |||
510 511 512 513 514 515 516 | db_finalize(&q); if( cnt==0 ){ @ <tr><td>(none)</td> }else if( nOmitted ){ @ <tr><td><a href="urllist?all"><i>Show %d(nOmitted) more...</i></a> } @ </table> | < < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | < < | < < < < < < < < < < < | 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 | db_finalize(&q); if( cnt==0 ){ @ <tr><td>(none)</td> }else if( nOmitted ){ @ <tr><td><a href="urllist?all"><i>Show %d(nOmitted) more...</i></a> } @ </table> db_prepare(&q, "SELECT substr(name,7), datetime(mtime,'unixepoch')" " FROM config WHERE name GLOB 'ckout:*' ORDER BY 2 DESC"); cnt = 0; while( db_step(&q)==SQLITE_ROW ){ const char *zPath = db_column_text(&q,0); if( vfile_top_of_checkout(zPath) ){ if( cnt==0 ){ @ <div class="section">Checkouts</div> @ <table border="0" width='100%%'> } @ <tr><td width='100%%'>%h(zPath)</td> @ <td><nobr>%h(db_column_text(&q,1))</nobr></td></tr> cnt++; } } db_finalize(&q); if( cnt ){ @ </table> } cnt = 0; db_prepare(&q, "SELECT substr(name,10), datetime(mtime,'unixepoch')" " FROM config WHERE name GLOB 'syncwith:*' ORDER BY 2 DESC"); while( db_step(&q)==SQLITE_ROW ){ const char *zURL = db_column_text(&q,0); if( cnt==0 ){ @ <div class="section">Sync to these URLs</div> @ <table border='0' width='100%%'> } @ <tr><td width='100%%'><a href='%h(zURL)'>%h(zURL)</a> @ <td><nobr>%h(db_column_text(&q,1))</nobr></td></tr> cnt++; } db_finalize(&q); if( cnt ){ @ </table> } cnt = 0; db_prepare(&q, "SELECT substr(name,9), datetime(mtime,'unixepoch')" " FROM config WHERE name GLOB 'gitpush:*' ORDER BY 2 DESC"); while( db_step(&q)==SQLITE_ROW ){ const char *zURL = db_column_text(&q,0); UrlData x; if( cnt==0 ){ @ <div class="section">Git Mirrors</div> @ <table border='0' width='100%%'> } url_parse_local(zURL, URL_OMIT_USER, &x); @ <tr><td width='100%%'><a href='%h(x.canonical)'>%h(x.canonical)</a> @ <td><nobr>%h(db_column_text(&q,1))</nobr></td></tr> cnt++; } db_finalize(&q); if( cnt ){ @ </table> } style_finish_page(); } /* ** WEBPAGE: repo_schema ** |
︙ | ︙ |
Changes to src/style.c.
︙ | ︙ | |||
105 106 107 108 109 110 111 | /* ** Generate and return a anchor tag like this: ** ** <a href="URL"> ** or <a id="ID"> ** ** The form of the anchor tag is determined by the g.javascriptHyperlink | > > > > > > > > > > | | | | < < | | | | > > > > > > > > > > > > | > > | | 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | /* ** Generate and return a anchor tag like this: ** ** <a href="URL"> ** or <a id="ID"> ** ** The form of the anchor tag is determined by the g.javascriptHyperlink ** and g.perm.Hyperlink variables. ** ** g.perm.Hyperlink g.javascriptHyperlink Returned anchor format ** ---------------- --------------------- ------------------------ ** 0 0 (empty string) ** 0 1 (empty string) ** 1 0 <a href="URL"> ** 1 1 <a id="ID"> ** ** No anchor tag is generated if g.perm.Hyperlink is false. ** The href="URL" form is used if g.javascriptHyperlink is false. ** If g.javascriptHyperlink is true then the id="ID" form is used and ** javascript is generated in the footer to cause href values to be ** inserted after the page has loaded. The use of the id="ID" form ** instead of href="URL" is a defense against bots. ** ** If the user lacks the Hyperlink (h) property and the "auto-hyperlink" ** setting is true, then g.perm.Hyperlink is changed from 0 to 1 and ** g.javascriptHyperlink is set to 1 by login_check_credentials(). Thus ** the g.perm.Hyperlink property will be true even if the user does not ** have the "h" privilege if the "auto-hyperlink" setting is true. ** ** User has "h" auto-hyperlink g.perm.Hyperlink g.javascriptHyperlink ** ------------ -------------- ---------------- --------------------- ** 0 0 0 0 ** 1 0 1 0 ** 0 1 1 1 ** 1 1 1 0 ** ** So, in other words, tracing input configuration to final actions we have: ** ** User has "h" auto-hyperlink Returned anchor format ** ------------ -------------- ---------------------- ** 0 0 (empty string) ** 1 0 <a href="URL"> ** 0 1 <a id="ID"> ** 1 1 (can't happen) ** ** The name of these routines are deliberately kept short so that can be ** easily used within @-lines. Example: ** ** @ %z(href("%R/artifact/%s",zUuid))%h(zFN)</a> ** ** Note %z format. The string returned by this function is always ** obtained from fossil_malloc() so rendering it with %z will reclaim ** that memory space. |
︙ | ︙ | |||
148 149 150 151 152 153 154 | char *xhref(const char *zExtra, const char *zFormat, ...){ char *zUrl; va_list ap; if( !g.perm.Hyperlink ) return fossil_strdup(""); va_start(ap, zFormat); zUrl = vmprintf(zFormat, ap); va_end(ap); | | | 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 | char *xhref(const char *zExtra, const char *zFormat, ...){ char *zUrl; va_list ap; if( !g.perm.Hyperlink ) return fossil_strdup(""); va_start(ap, zFormat); zUrl = vmprintf(zFormat, ap); va_end(ap); if( !g.javascriptHyperlink ){ char *zHUrl; if( zExtra ){ zHUrl = mprintf("<a %s href=\"%h\">", zExtra, zUrl); }else{ zHUrl = mprintf("<a href=\"%h\">", zUrl); } fossil_free(zUrl); |
︙ | ︙ | |||
173 174 175 176 177 178 179 | char *chref(const char *zExtra, const char *zFormat, ...){ char *zUrl; va_list ap; if( !g.perm.Hyperlink ) return fossil_strdup(""); va_start(ap, zFormat); zUrl = vmprintf(zFormat, ap); va_end(ap); | | | | | > > > > > > > > > > > > > > > > > < | < | 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 | char *chref(const char *zExtra, const char *zFormat, ...){ char *zUrl; va_list ap; if( !g.perm.Hyperlink ) return fossil_strdup(""); va_start(ap, zFormat); zUrl = vmprintf(zFormat, ap); va_end(ap); if( !g.javascriptHyperlink ){ char *zHUrl = mprintf("<a class=\"%s\" href=\"%h\">", zExtra, zUrl); fossil_free(zUrl); return zHUrl; } needHrefJs = 1; return mprintf("<a class='%s' data-href='%z' href='%R/honeypot'>", zExtra, zUrl); } char *href(const char *zFormat, ...){ char *zUrl; va_list ap; if( !g.perm.Hyperlink ) return fossil_strdup(""); va_start(ap, zFormat); zUrl = vmprintf(zFormat, ap); va_end(ap); if( !g.javascriptHyperlink ){ char *zHUrl = mprintf("<a href=\"%h\">", zUrl); fossil_free(zUrl); return zHUrl; } needHrefJs = 1; return mprintf("<a data-href='%s' href='%R/honeypot'>", zUrl); } /* ** Generate <form method="post" action=ARG>. The ARG value is determined ** by the arguments. ** ** As a defense against robots, the action=ARG might instead by data-action=ARG ** and javascript (href.js) added to the page so that the data-action= is ** changed into action= after the page loads. Whether or not this happens ** depends on if the user has the "h" privilege and whether or not the ** auto-hyperlink setting is on. These setings determine the values of ** variables g.perm.Hyperlink and g.javascriptHyperlink. ** ** User has "h" auto-hyperlink g.perm.Hyperlink g.javascriptHyperlink ** ------------ -------------- ---------------- --------------------- ** 1: 0 0 0 0 ** 2: 1 0 1 0 ** 3: 0 1 1 1 ** 4: 1 1 1 0 ** ** The data-action=ARG form is used for cases 1 and 3. In case 1, the href.js ** javascript is omitted and so the form is effectively disabled. */ void form_begin(const char *zOtherArgs, const char *zAction, ...){ char *zLink; va_list ap; if( zOtherArgs==0 ) zOtherArgs = ""; va_start(ap, zAction); zLink = vmprintf(zAction, ap); va_end(ap); if( g.perm.Hyperlink ){ @ <form method="POST" action="%z(zLink)" %s(zOtherArgs)> }else{ needHrefJs = 1; @ <form method="POST" data-action='%s(zLink)' action='%R/login' \ @ %s(zOtherArgs)> } } |
︙ | ︙ |
Changes to src/sync.c.
︙ | ︙ | |||
144 145 146 147 148 149 150 151 152 153 154 155 156 157 | } if( find_option("private",0,0)!=0 ){ *pSyncFlags |= SYNC_PRIVATE; } if( find_option("verbose","v",0)!=0 ){ *pSyncFlags |= SYNC_VERBOSE; } url_proxy_options(); clone_ssh_find_options(); if( !uvOnly ) db_find_and_open_repository(0, 0); db_open_config(0, 1); if( g.argc==2 ){ if( db_get_boolean("auto-shun",0) ) configSync = CONFIGSET_SHUN; }else if( g.argc==3 ){ | > > > | 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 | } if( find_option("private",0,0)!=0 ){ *pSyncFlags |= SYNC_PRIVATE; } if( find_option("verbose","v",0)!=0 ){ *pSyncFlags |= SYNC_VERBOSE; } if( find_option("no-http-compression",0,0)!=0 ){ *pSyncFlags |= SYNC_NOHTTPCOMPRESS; } url_proxy_options(); clone_ssh_find_options(); if( !uvOnly ) db_find_and_open_repository(0, 0); db_open_config(0, 1); if( g.argc==2 ){ if( db_get_boolean("auto-shun",0) ) configSync = CONFIGSET_SHUN; }else if( g.argc==3 ){ |
︙ | ︙ | |||
204 205 206 207 208 209 210 211 212 213 214 215 216 217 | ** ** Options: ** ** -B|--httpauth USER:PASS Credentials for the simple HTTP auth protocol, ** if required by the remote website ** --from-parent-project Pull content from the parent project ** --ipv4 Use only IPv4, not IPv6 ** --once Do not remember URL for subsequent syncs ** --private Pull private branches too ** --project-code CODE Use CODE as the project code ** --proxy PROXY Use the specified HTTP proxy ** -R|--repository REPO Local repository to pull into ** --ssl-identity FILE Local SSL credentials, if requested by remote ** --ssh-command SSH Use SSH as the "ssh" command | > | 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 | ** ** Options: ** ** -B|--httpauth USER:PASS Credentials for the simple HTTP auth protocol, ** if required by the remote website ** --from-parent-project Pull content from the parent project ** --ipv4 Use only IPv4, not IPv6 ** --no-http-compression Do not compress HTTP traffic ** --once Do not remember URL for subsequent syncs ** --private Pull private branches too ** --project-code CODE Use CODE as the project code ** --proxy PROXY Use the specified HTTP proxy ** -R|--repository REPO Local repository to pull into ** --ssl-identity FILE Local SSL credentials, if requested by remote ** --ssh-command SSH Use SSH as the "ssh" command |
︙ | ︙ | |||
254 255 256 257 258 259 260 261 262 263 264 265 266 267 | ** details on the URL formats. ** ** Options: ** ** -B|--httpauth USER:PASS Credentials for the simple HTTP auth protocol, ** if required by the remote website ** --ipv4 Use only IPv4, not IPv6 ** --once Do not remember URL for subsequent syncs ** --proxy PROXY Use the specified HTTP proxy ** --private Push private branches too ** -R|--repository REPO Local repository to push from ** --ssl-identity FILE Local SSL credentials, if requested by remote ** --ssh-command SSH Use SSH as the "ssh" command ** -v|--verbose Additional (debugging) output | > | 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 | ** details on the URL formats. ** ** Options: ** ** -B|--httpauth USER:PASS Credentials for the simple HTTP auth protocol, ** if required by the remote website ** --ipv4 Use only IPv4, not IPv6 ** --no-http-compression Do not compress HTTP traffic ** --once Do not remember URL for subsequent syncs ** --proxy PROXY Use the specified HTTP proxy ** --private Push private branches too ** -R|--repository REPO Local repository to push from ** --ssl-identity FILE Local SSL credentials, if requested by remote ** --ssh-command SSH Use SSH as the "ssh" command ** -v|--verbose Additional (debugging) output |
︙ | ︙ | |||
299 300 301 302 303 304 305 306 307 308 309 310 311 312 | ** details on the URL formats. ** ** Options: ** ** -B|--httpauth USER:PASS Credentials for the simple HTTP auth protocol, ** if required by the remote website ** --ipv4 Use only IPv4, not IPv6 ** --once Do not remember URL for subsequent syncs ** --proxy PROXY Use the specified HTTP proxy ** --private Sync private branches too ** -R|--repository REPO Local repository to sync with ** --ssl-identity FILE Local SSL credentials, if requested by remote ** --ssh-command SSH Use SSH as the "ssh" command ** -u|--unversioned Also sync unversioned content | > | 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 | ** details on the URL formats. ** ** Options: ** ** -B|--httpauth USER:PASS Credentials for the simple HTTP auth protocol, ** if required by the remote website ** --ipv4 Use only IPv4, not IPv6 ** --no-http-compression Do not compress HTTP traffic ** --once Do not remember URL for subsequent syncs ** --proxy PROXY Use the specified HTTP proxy ** --private Sync private branches too ** -R|--repository REPO Local repository to sync with ** --ssl-identity FILE Local SSL credentials, if requested by remote ** --ssh-command SSH Use SSH as the "ssh" command ** -u|--unversioned Also sync unversioned content |
︙ | ︙ |
Changes to src/tag.c.
︙ | ︙ | |||
887 888 889 890 891 892 893 | if( PB("brbg")!=0 ) tmFlags |= TIMELINE_BRCOLOR; if( PB("ubg")!=0 ) tmFlags |= TIMELINE_UCOLOR; www_print_timeline(&q, tmFlags, 0, 0, 0, 0, 0, 0); db_finalize(&q); @ <br /> style_finish_page(); } | > > > > > > > > > > > > > > | 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 | if( PB("brbg")!=0 ) tmFlags |= TIMELINE_BRCOLOR; if( PB("ubg")!=0 ) tmFlags |= TIMELINE_UCOLOR; www_print_timeline(&q, tmFlags, 0, 0, 0, 0, 0, 0); db_finalize(&q); @ <br /> style_finish_page(); } /* ** Returns true if the given blob.rid value has the given tag ID ** applied to it, else false. */ int rid_has_tag(int rid, int tagId){ return db_exists( "SELECT tag.tagid FROM tagxref, tag" " WHERE tagxref.rid=%d AND tagtype>0 " " AND tag.tagid=%d" " AND tagxref.tagid=tag.tagid", rid, tagId ); } |
Changes to src/tar.c.
︙ | ︙ | |||
772 773 774 775 776 777 778 779 780 781 782 783 784 785 | if( z==0 ) z = "trunk"; g.zOpenRevision = zRid = fossil_strdup(z); nRid = strlen(zRid); zInclude = P("in"); if( zInclude ) pInclude = glob_create(zInclude); zExclude = P("ex"); if( zExclude ) pExclude = glob_create(zExclude); nName = strlen(zName); if( nName>7 && fossil_strcmp(&zName[nName-7], ".tar.gz")==0 ){ /* Special case: Remove the ".tar.gz" suffix. */ nName -= 7; zName[nName] = 0; }else{ /* If the file suffix is not ".tar.gz" then just remove the | > > > | 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 | if( z==0 ) z = "trunk"; g.zOpenRevision = zRid = fossil_strdup(z); nRid = strlen(zRid); zInclude = P("in"); if( zInclude ) pInclude = glob_create(zInclude); zExclude = P("ex"); if( zExclude ) pExclude = glob_create(zExclude); if( zInclude==0 && zExclude==0 ){ etag_check_for_invariant_name(z); } nName = strlen(zName); if( nName>7 && fossil_strcmp(&zName[nName-7], ".tar.gz")==0 ){ /* Special case: Remove the ".tar.gz" suffix. */ nName -= 7; zName[nName] = 0; }else{ /* If the file suffix is not ".tar.gz" then just remove the |
︙ | ︙ |
Changes to src/th_main.c.
︙ | ︙ | |||
44 45 46 47 48 49 50 | #define TH_INIT_FORBID_MASK (TH_INIT_FORCE_TCL) /* Illegal from a script. */ #endif /* ** Flags set by functions in this file to keep track of integration state ** information. These flags should not be used outside of this file. */ | | | | | 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | #define TH_INIT_FORBID_MASK (TH_INIT_FORCE_TCL) /* Illegal from a script. */ #endif /* ** Flags set by functions in this file to keep track of integration state ** information. These flags should not be used outside of this file. */ #define TH_STATE_CONFIG ((u32)0x00000200) /* We opened the config. */ #define TH_STATE_REPOSITORY ((u32)0x00000400) /* We opened the repository. */ #define TH_STATE_MASK ((u32)0x00000600) /* All possible state flags. */ #ifdef FOSSIL_ENABLE_TH1_HOOKS /* ** These are the "well-known" TH1 error messages that occur when no hook is ** registered to be called prior to executing a command or processing a web ** page, respectively. If one of these errors is seen, it will not be sent ** or displayed to the remote user or local interactive user, respectively. |
︙ | ︙ | |||
359 360 361 362 363 364 365 | /* See Th_SetOutputBlob() */ static Blob * pThOut = 0; /* ** Sets the th1-internal output-redirection blob and returns the ** previous value. That blob is used by certain output-generation ** routines to emit its output. It returns the previous value so that | | | 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 | /* See Th_SetOutputBlob() */ static Blob * pThOut = 0; /* ** Sets the th1-internal output-redirection blob and returns the ** previous value. That blob is used by certain output-generation ** routines to emit its output. It returns the previous value so that ** a routine can temporarily replace the buffer with its own and ** restore it when it's done. */ Blob * Th_SetOutputBlob(Blob * pOut){ Blob * tmp = pThOut; pThOut = pOut; return tmp; } |
︙ | ︙ | |||
1747 1748 1749 1750 1751 1752 1753 | { "content", unversionedContentCmd }, { "list", unversionedListCmd }, { 0, 0 } }; return Th_CallSubCommand(interp, p, argc, argv, argl, aSub); } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | | 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 | { "content", unversionedContentCmd }, { "list", unversionedListCmd }, { 0, 0 } }; return Th_CallSubCommand(interp, p, argc, argv, argl, aSub); } /* ** TH1 command: utime ** ** Return the number of microseconds of CPU time consumed by the current ** process in user space. */ static int utimeCmd( Th_Interp *interp, void *p, int argc, const char **argv, int *argl ){ sqlite3_uint64 x; char zUTime[50]; fossil_cpu_times(&x, 0); sqlite3_snprintf(sizeof(zUTime), zUTime, "%llu", x); Th_SetResult(interp, zUTime, -1); return TH_OK; } /* ** TH1 command: stime ** ** Return the number of microseconds of CPU time consumed by the current ** process in system space. */ static int stimeCmd( Th_Interp *interp, void *p, int argc, const char **argv, int *argl ){ sqlite3_uint64 x; char zUTime[50]; fossil_cpu_times(0, &x); sqlite3_snprintf(sizeof(zUTime), zUTime, "%llu", x); Th_SetResult(interp, zUTime, -1); return TH_OK; } /* |
︙ | ︙ | |||
2832 2833 2834 2835 2836 2837 2838 | ** TH_INIT_MASK. */ #define TH_R2B_MASK ((u32)0x0f000) #define TH_R2B_NO_VARS ((u32)0x01000) /* Disables eval of $vars and $<vars> */ #endif /* | | > | | | | | | | 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 | ** TH_INIT_MASK. */ #define TH_R2B_MASK ((u32)0x0f000) #define TH_R2B_NO_VARS ((u32)0x01000) /* Disables eval of $vars and $<vars> */ #endif /* ** If pOut is NULL, this works identically to Th_Render() and sends ** any TH1-generated output to stdin (in CLI mode) or the CGI buffer ** (in CGI mode), else it works just like that function but appends ** any TH1-generated output to the given blob. A bitmask of TH_R2B_xxx ** and/or TH_INIT_xxx flags may be passed as the 3rd argument, or 0 ** for default options. Note that this function necessarily calls ** Th_FossilInit(), which may unset flags used on previous calls ** unless mFlags is explicitly passed in. */ int Th_RenderToBlob(const char *z, Blob * pOut, u32 mFlags){ int i = 0; int n; int rc = TH_OK; char *zResult; Blob * const origOut = Th_SetOutputBlob(pOut); |
︙ | ︙ | |||
2915 2916 2917 2918 2919 2920 2921 | ** before being inserted. ** ** This routine processes the template and writes the results to one ** of stdout, CGI, or an internal blob which was set up via a prior ** call to Th_SetOutputBlob(). */ int Th_Render(const char *z){ | | > > > > > > > > > > > > | 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 | ** before being inserted. ** ** This routine processes the template and writes the results to one ** of stdout, CGI, or an internal blob which was set up via a prior ** call to Th_SetOutputBlob(). */ int Th_Render(const char *z){ return Th_RenderToBlob(z, pThOut, g.th1Flags) /* Maintenance reminder: on most calls to Th_Render(), e.g. for ** outputing the site skin, pThOut will be 0, which means that ** Th_RenderToBlob() will output directly to the CGI buffer (in ** CGI mode) or stdout (in CLI mode). Recursive calls, however, ** e.g. via the "render" script function binding, need to use the ** pThOut blob in order to avoid out-of-order output if ** Th_SetOutputBlob() has been called. If it has not been called, ** pThOut will be 0, which will redirect the output to CGI/stdout, ** as appropriate. We need to pass on g.th1Flags for the case of ** recursive calls, so that, e.g., TH_INIT_NO_ENCODE does not get ** inadvertently toggled off by a recursive call. */; } /* ** COMMAND: test-th-render ** ** Usage: %fossil test-th-render FILE ** |
︙ | ︙ |
Changes to src/timeline.c.
︙ | ︙ | |||
116 117 118 119 120 121 122 123 124 125 126 127 128 129 | #define TIMELINE_CHPICK 0x0400000 /* Show cherrypick merges */ #define TIMELINE_FILLGAPS 0x0800000 /* Dotted lines for missing nodes */ #define TIMELINE_XMERGE 0x1000000 /* Omit merges from off-graph nodes */ #define TIMELINE_NOTKT 0x2000000 /* Omit extra ticket classes */ #define TIMELINE_FORUMTXT 0x4000000 /* Render all forum messages */ #define TIMELINE_REFS 0x8000000 /* Output intended for References tab */ #define TIMELINE_DELTA 0x10000000 /* Background color shows delta manifests */ #endif /* ** Return a new timelineTable id. */ int timeline_tableid(void){ static int id = 0; | > | 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | #define TIMELINE_CHPICK 0x0400000 /* Show cherrypick merges */ #define TIMELINE_FILLGAPS 0x0800000 /* Dotted lines for missing nodes */ #define TIMELINE_XMERGE 0x1000000 /* Omit merges from off-graph nodes */ #define TIMELINE_NOTKT 0x2000000 /* Omit extra ticket classes */ #define TIMELINE_FORUMTXT 0x4000000 /* Render all forum messages */ #define TIMELINE_REFS 0x8000000 /* Output intended for References tab */ #define TIMELINE_DELTA 0x10000000 /* Background color shows delta manifests */ #define TIMELINE_NOCOLOR 0x20000000 /* No colors except for highlights */ #endif /* ** Return a new timelineTable id. */ int timeline_tableid(void){ static int id = 0; |
︙ | ︙ | |||
361 362 363 364 365 366 367 | zDateLink = chref("timelineHistLink", "%R/timeline?c=%!S&y=a", zUuid); } }else{ zDateLink = mprintf("<a>"); } @ <td class="timelineTime">%z(zDateLink)%s(zTime)</a></td> @ <td class="timelineGraph"> | | > > | 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 | zDateLink = chref("timelineHistLink", "%R/timeline?c=%!S&y=a", zUuid); } }else{ zDateLink = mprintf("<a>"); } @ <td class="timelineTime">%z(zDateLink)%s(zTime)</a></td> @ <td class="timelineGraph"> if( tmFlags & (TIMELINE_UCOLOR|TIMELINE_DELTA|TIMELINE_NOCOLOR) ){ if( tmFlags & TIMELINE_UCOLOR ){ zBgClr = zUser ? user_color(zUser) : 0; }else if( tmFlags & TIMELINE_NOCOLOR ){ zBgClr = 0; }else if( zType[0]=='c' ){ static Stmt qdelta; db_static_prepare(&qdelta, "SELECT baseid IS NULL FROM plink" " WHERE cid=:rid"); db_bind_int(&qdelta, ":rid", rid); if( db_step(&qdelta)!=SQLITE_ROW ){ zBgClr = 0; /* Not a check-in */ |
︙ | ︙ | |||
390 391 392 393 394 395 396 | db_bind_int(&qbranch, ":rid", rid); if( db_step(&qbranch)==SQLITE_ROW ){ zBr = db_column_text(&qbranch, 0); }else{ zBr = "trunk"; } if( zBgClr==0 || (tmFlags & TIMELINE_BRCOLOR)!=0 ){ | | | 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 | db_bind_int(&qbranch, ":rid", rid); if( db_step(&qbranch)==SQLITE_ROW ){ zBr = db_column_text(&qbranch, 0); }else{ zBr = "trunk"; } if( zBgClr==0 || (tmFlags & TIMELINE_BRCOLOR)!=0 ){ if( tmFlags & (TIMELINE_DELTA|TIMELINE_NOCOLOR) ){ }else if( zBr==0 || strcmp(zBr,"trunk")==0 ){ zBgClr = 0; }else{ zBgClr = hash_color(zBr); } } } |
︙ | ︙ | |||
1542 1543 1544 1545 1546 1547 1548 | ** Query parameters: ** ** a=TIMEORTAG Show events after TIMEORTAG ** b=TIMEORTAG Show events before TIMEORTAG ** c=TIMEORTAG Show events that happen "circa" TIMEORTAG ** cf=FILEHASH Show events around the time of the first use of ** the file with FILEHASH | | > > > > > > > | 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 | ** Query parameters: ** ** a=TIMEORTAG Show events after TIMEORTAG ** b=TIMEORTAG Show events before TIMEORTAG ** c=TIMEORTAG Show events that happen "circa" TIMEORTAG ** cf=FILEHASH Show events around the time of the first use of ** the file with FILEHASH ** m=TIMEORTAG Highlight the event at TIMEORTAG, or the closest available ** event if TIMEORTAG is not part of the timeline. If ** the t= or r= is used, the m event is added to the timeline ** if it isn't there already. ** sel1=TIMEORTAG Highlight the check-in at TIMEORTAG if it is part of ** the timeline. Similar to m= except TIMEORTAG must ** match a check-in that is already in the timeline. ** sel2=TIMEORTAG Like sel1= but use the secondary highlight. ** n=COUNT Maximum number of events. "all" for no limit ** n1=COUNT Same as "n" but doesn't set the display-preference cookie ** Use "n1=COUNT" for a one-time display change ** p=CHECKIN Parents and ancestors of CHECKIN ** bt=PRIOR ... going back to PRIOR ** d=CHECKIN Children and descendants of CHECKIN ** dp=CHECKIN Same as 'd=CHECKIN&p=CHECKIN' |
︙ | ︙ | |||
1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 | ** ss=VIEWSTYLE c: "Compact", v: "Verbose", m: "Modern", j: "Columnar", ** x: "Classic". ** advm Use the "Advanced" or "Busy" menu design. ** ng No Graph. ** ncp Omit cherrypick merges ** nd Do not highlight the focus check-in ** nsm Omit the submenu ** v Show details of files changed ** vfx Show complete text of forum messages ** f=CHECKIN Show family (immediate parents and children) of CHECKIN ** from=CHECKIN Path from... ** to=CHECKIN ... to this ** shortest ... show only the shortest path ** rel ... also show related checkins | > | 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 | ** ss=VIEWSTYLE c: "Compact", v: "Verbose", m: "Modern", j: "Columnar", ** x: "Classic". ** advm Use the "Advanced" or "Busy" menu design. ** ng No Graph. ** ncp Omit cherrypick merges ** nd Do not highlight the focus check-in ** nsm Omit the submenu ** nc Omit all graph colors other than highlights ** v Show details of files changed ** vfx Show complete text of forum messages ** f=CHECKIN Show family (immediate parents and children) of CHECKIN ** from=CHECKIN Path from... ** to=CHECKIN ... to this ** shortest ... show only the shortest path ** rel ... also show related checkins |
︙ | ︙ | |||
1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 | } if( PB("ubg") ){ tmFlags |= TIMELINE_UCOLOR; } if( PB("deltabg") ){ tmFlags |= TIMELINE_DELTA; } if( zUses!=0 ){ int ufid = db_int(0, "SELECT rid FROM blob WHERE uuid GLOB '%q*'", zUses); if( ufid ){ zUses = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", ufid); db_multi_exec("CREATE TEMP TABLE usesfile(rid INTEGER PRIMARY KEY)"); compute_uses_file("usesfile", ufid, 0); zType = "ci"; | > > > > | 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 | } if( PB("ubg") ){ tmFlags |= TIMELINE_UCOLOR; } if( PB("deltabg") ){ tmFlags |= TIMELINE_DELTA; } if( PB("nc") ){ tmFlags &= ~(TIMELINE_DELTA|TIMELINE_BRCOLOR|TIMELINE_UCOLOR); tmFlags |= TIMELINE_NOCOLOR; } if( zUses!=0 ){ int ufid = db_int(0, "SELECT rid FROM blob WHERE uuid GLOB '%q*'", zUses); if( ufid ){ zUses = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", ufid); db_multi_exec("CREATE TEMP TABLE usesfile(rid INTEGER PRIMARY KEY)"); compute_uses_file("usesfile", ufid, 0); zType = "ci"; |
︙ | ︙ | |||
2075 2076 2077 2078 2079 2080 2081 | if( d_rid ){ compute_descendants(d_rid, nEntry==0 ? 0 : nEntry+1); nd = db_int(0, "SELECT count(*)-1 FROM ok"); if( nd>=0 ) db_multi_exec("%s", blob_sql_text(&sql)); if( nd>0 || p_rid==0 ){ blob_appendf(&desc, "%d descendant%s", nd,(1==nd)?"":"s"); } | | | | 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 | if( d_rid ){ compute_descendants(d_rid, nEntry==0 ? 0 : nEntry+1); nd = db_int(0, "SELECT count(*)-1 FROM ok"); if( nd>=0 ) db_multi_exec("%s", blob_sql_text(&sql)); if( nd>0 || p_rid==0 ){ blob_appendf(&desc, "%d descendant%s", nd,(1==nd)?"":"s"); } if( useDividers && !selectedRid ) selectedRid = d_rid; db_multi_exec("DELETE FROM ok"); } if( p_rid ){ zBackTo = P("bt"); ridBackTo = zBackTo ? name_to_typed_rid(zBackTo,"ci") : 0; if( ridBackTo && !haveParameterN ) nEntry = 0; compute_ancestors(p_rid, nEntry==0 ? 0 : nEntry+1, 0, ridBackTo); np = db_int(0, "SELECT count(*)-1 FROM ok"); if( np>0 || nd==0 ){ if( nd>0 ) blob_appendf(&desc, " and "); blob_appendf(&desc, "%d ancestor%s", np, (1==np)?"":"s"); db_multi_exec("%s", blob_sql_text(&sql)); } if( useDividers && !selectedRid ) selectedRid = p_rid; } blob_appendf(&desc, " of %z%h</a>", href("%R/info?name=%h", zCiName), zCiName); if( ridBackTo ){ if( np==0 ){ blob_reset(&desc); |
︙ | ︙ | |||
2138 2139 2140 2141 2142 2143 2144 | "INSERT OR IGNORE INTO ok SELECT childid FROM cherrypick" " WHERE parentid=%d;", f_rid, f_rid ); } blob_append_sql(&sql, " AND event.objid IN ok"); db_multi_exec("%s", blob_sql_text(&sql)); | | | 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 | "INSERT OR IGNORE INTO ok SELECT childid FROM cherrypick" " WHERE parentid=%d;", f_rid, f_rid ); } blob_append_sql(&sql, " AND event.objid IN ok"); db_multi_exec("%s", blob_sql_text(&sql)); if( useDividers && !selectedRid ) selectedRid = f_rid; blob_appendf(&desc, "Parents and children of check-in "); zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", f_rid); blob_appendf(&desc, "%z[%S]</a>", href("%R/info/%!S", zUuid), zUuid); tmFlags |= TIMELINE_XMERGE; if( advancedMenu ){ style_submenu_checkbox("unhide", "Unhide", 0, 0); style_submenu_checkbox("v", "Files", (zType[0]!='a' && zType[0]!='c'),0); |
︙ | ︙ | |||
2632 2633 2634 2635 2636 2637 2638 | }else{ style_submenu_element("Advanced", "%s", url_render(&url, "advm", "1", "udc", "1")); } if( PB("showid") ) tmFlags |= TIMELINE_SHOWRID; if( useDividers && zMark && zMark[0] ){ double r = symbolic_name_to_mtime(zMark, 0); | | | 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 | }else{ style_submenu_element("Advanced", "%s", url_render(&url, "advm", "1", "udc", "1")); } if( PB("showid") ) tmFlags |= TIMELINE_SHOWRID; if( useDividers && zMark && zMark[0] ){ double r = symbolic_name_to_mtime(zMark, 0); if( r>0.0 && !selectedRid ) selectedRid = timeline_add_divider(r); } blob_zero(&sql); db_prepare(&q, "SELECT * FROM timeline ORDER BY sortby DESC /*scan*/"); if( fossil_islower(desc.aData[0]) ){ desc.aData[0] = fossil_toupper(desc.aData[0]); } if( zBrName ){ |
︙ | ︙ |
Changes to src/tkt.c.
︙ | ︙ | |||
1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 | /* ** WEBPAGE: tktsrch ** Usage: /tktsrch?s=PATTERN ** ** Full-text search of all current tickets */ void tkt_srchpage(void){ login_check_credentials(); style_set_current_feature("tkt"); style_header("Ticket Search"); ticket_standard_submenu(T_ALL_BUT(T_SRCH)); | > | > > > > > | 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 | /* ** WEBPAGE: tktsrch ** Usage: /tktsrch?s=PATTERN ** ** Full-text search of all current tickets */ void tkt_srchpage(void){ char *defaultReport; login_check_credentials(); style_set_current_feature("tkt"); style_header("Ticket Search"); ticket_standard_submenu(T_ALL_BUT(T_SRCH)); if( !search_screen(SRCH_TKT, 0) ){ defaultReport = db_get("ticket-default-report", 0); if( defaultReport ){ rptview_page_content(defaultReport, 0, 0); } } style_finish_page(); } |
Changes to src/tktsetup.c.
︙ | ︙ | |||
134 135 136 137 138 139 140 | if( z==0 ){ z = db_get(zDbField, zDfltValue); } style_set_current_feature("tktsetup"); style_header("Edit %s", zTitle); if( P("clear")!=0 ){ login_verify_csrf_secret(); | | | | 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | if( z==0 ){ z = db_get(zDbField, zDfltValue); } style_set_current_feature("tktsetup"); style_header("Edit %s", zTitle); if( P("clear")!=0 ){ login_verify_csrf_secret(); db_unset(zDbField/*works-like:"x"*/, 0); if( xRebuild ) xRebuild(); cgi_redirect("tktsetup"); }else if( isSubmit ){ char *zErr = 0; login_verify_csrf_secret(); if( xText && (zErr = xText(z))!=0 ){ @ <p class="tktsetupError">ERROR: %h(zErr)</p> }else{ db_set(zDbField/*works-like:"x"*/, z, 0); if( xRebuild ) xRebuild(); cgi_redirect("tktsetup"); } } @ <form action="%R/%s(g.zPath)" method="post"><div> login_insert_csrf_secret(); @ <p>%s(zDesc)</p> |
︙ | ︙ |
Changes to src/unversioned.c.
︙ | ︙ | |||
60 61 62 63 64 65 66 | ** in exactly the same way. ** ** If debugFlag is set, force the value to be recomputed and write ** the text of the hashed string to stdout. */ const char *unversioned_content_hash(int debugFlag){ const char *zHash = debugFlag ? 0 : db_get("uv-hash", 0); | | > > > | 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | ** in exactly the same way. ** ** If debugFlag is set, force the value to be recomputed and write ** the text of the hashed string to stdout. */ const char *unversioned_content_hash(int debugFlag){ const char *zHash = debugFlag ? 0 : db_get("uv-hash", 0); if( zHash ) return zHash; if( !db_table_exists("repository","unversioned") ){ return "da39a3ee5e6b4b0d3255bfef95601890afd80709"; }else{ Stmt q; db_prepare(&q, "SELECT printf('%%s %%s %%s\n',name,datetime(mtime,'unixepoch'),hash)" " FROM unversioned" " WHERE hash IS NOT NULL" " ORDER BY name" ); |
︙ | ︙ |
Changes to src/update.c.
︙ | ︙ | |||
89 90 91 92 93 94 95 | ** It prints out what would have happened but does not actually make ** any changes to the current checkout or the repository. ** ** The -v or --verbose option prints status information about ** unchanged files in addition to those file that actually do change. ** ** Options: | | | | < | > | < < | > | > | | | | > | | > | 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 | ** It prints out what would have happened but does not actually make ** any changes to the current checkout or the repository. ** ** The -v or --verbose option prints status information about ** unchanged files in addition to those file that actually do change. ** ** Options: ** --case-sensitive BOOL Override case-sensitive setting ** --debug Print debug information on stdout ** -n|--dry-run If given, display instead of run actions ** --force-missing Force update if missing content after sync ** -K|--keep-merge-files On merge conflict, retain the temporary files ** used for merging, named *-baseline, *-original, ** and *-merge. ** --latest Acceptable in place of VERSION, update to ** latest version ** --nosync Do not auto-sync prior to update ** --setmtime Set timestamps of all files to match their ** SCM-side times (the timestamp of the last ** checkin which modified them). ** -v|--verbose Print status information about all files ** -W|--width WIDTH Width of lines (default is to auto-detect). ** Must be more than 20 or 0 (= no limit, ** resulting in a single line per entry). ** ** See also: [[revert]] */ void update_cmd(void){ int vid; /* Current version */ int tid=0; /* Target version - version we are changing to */ Stmt q; int latestFlag; /* --latest. Pick the latest version if true */ int dryRunFlag; /* -n or --dry-run. Do a dry run */ int verboseFlag; /* -v or --verbose. Output extra information */ int forceMissingFlag; /* --force-missing. Continue if missing content */ int debugFlag; /* --debug option */ int setmtimeFlag; /* --setmtime. Set mtimes on files */ int keepMergeFlag; /* True if --keep-merge-files is present */ int nChng; /* Number of file renames */ int *aChng; /* Array of file renames */ int i; /* Loop counter */ int nConflict = 0; /* Number of merge conflicts */ int nOverwrite = 0; /* Number of unmanaged files overwritten */ int nUpdate = 0; /* Number of changes of any kind */ int bNosync = 0; /* --nosync. Omit the auto-sync */ int width; /* Width of printed comment lines */ Stmt mtimeXfer; /* Statement to transfer mtimes */ const char *zWidth; /* Width option string value */ if( !internalUpdate ){ undo_capture_command_line(); url_proxy_options(); |
︙ | ︙ | |||
152 153 154 155 156 157 158 159 160 161 162 163 164 165 | dryRunFlag = find_option("nochange",0,0)!=0; /* deprecated */ } verboseFlag = find_option("verbose","v",0)!=0; forceMissingFlag = find_option("force-missing",0,0)!=0; debugFlag = find_option("debug",0,0)!=0; setmtimeFlag = find_option("setmtime",0,0)!=0; keepMergeFlag = find_option("keep-merge-files", "K",0)!=0; /* We should be done with options.. */ verify_all_options(); db_must_be_within_tree(); vid = db_lget_int("checkout", 0); user_select(); | > | | 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 | dryRunFlag = find_option("nochange",0,0)!=0; /* deprecated */ } verboseFlag = find_option("verbose","v",0)!=0; forceMissingFlag = find_option("force-missing",0,0)!=0; debugFlag = find_option("debug",0,0)!=0; setmtimeFlag = find_option("setmtime",0,0)!=0; keepMergeFlag = find_option("keep-merge-files", "K",0)!=0; bNosync = find_option("nosync",0,0)!=0; /* We should be done with options.. */ verify_all_options(); db_must_be_within_tree(); vid = db_lget_int("checkout", 0); user_select(); if( !dryRunFlag && !internalUpdate && !bNosync ){ if( autosync_loop(SYNC_PULL + SYNC_VERBOSE*verboseFlag, db_get_int("autosync-tries", 1), 1) ){ fossil_fatal("update abandoned due to sync failure"); } } /* Create any empty directories now, as well as after the update, |
︙ | ︙ |
Changes to src/user.c.
︙ | ︙ | |||
110 111 112 113 114 115 116 | void freepass(){ if( !zPwdBuffer ) return; assert( nPwdBuffer>0 ); fossil_secure_free_page(zPwdBuffer, nPwdBuffer); } #endif | < < < < < < < < < | 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | void freepass(){ if( !zPwdBuffer ) return; assert( nPwdBuffer>0 ); fossil_secure_free_page(zPwdBuffer, nPwdBuffer); } #endif /* ** Scramble substitution matrix: */ static char aSubst[256]; /* ** Descramble the password |
︙ | ︙ |
Changes to src/util.c.
︙ | ︙ | |||
34 35 36 37 38 39 40 | # include <sys/time.h> # include <sys/resource.h> # include <unistd.h> # include <fcntl.h> # include <errno.h> #endif | < | 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | # include <sys/time.h> # include <sys/resource.h> # include <unistd.h> # include <fcntl.h> # include <errno.h> #endif /* ** Exit. Take care to close the database first. */ NORETURN void fossil_exit(int rc){ db_close(1); #ifndef _WIN32 if( g.fAnyTrace ){ |
︙ | ︙ | |||
162 163 164 165 166 167 168 | zIn++; } } return zStart; } /* | > | > > > > | | > > > | | 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 | zIn++; } } return zStart; } /* ** This local variable determines the behavior of ** fossil_assert_safe_command_string(): ** ** 0 (default) fossil_panic() on an unsafe command string ** ** 1 Print an error but continue process. Used for ** testing of fossil_assert_safe_command_string(). ** ** 2 No-op. Used to allow any arbitrary command string ** through fossil_system(), such as when invoking ** COMMAND in "fossil bisect run COMMAND". */ static int safeCmdStrTest = 0; /* ** Check the input string to ensure that it is safe to pass into system(). ** A string is unsafe for system() on unix if it contains any of the following: ** ** * Any occurrance of '$' or '`' except single-quoted or after \ ** * Any of the following characters, unquoted: ;|& or \n except ** these characters are allowed as the very last character in the ** string. ** * Unbalanced single or double quotes ** ** This routine is intended as a second line of defense against attack. ** It should never fail. Dangerous shell strings should be detected and |
︙ | ︙ | |||
240 241 242 243 244 245 246 | case '<': case '|': case '&': case '\n': { if( inQuote==0 && z[i+1]!=0 ) unsafe = i+1; break; } | < < < < < < | | > | 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 | case '<': case '|': case '&': case '\n': { if( inQuote==0 && z[i+1]!=0 ) unsafe = i+1; break; } case '"': { if( inQuote==c ){ inQuote = 0; }else{ inQuote = c; } break; } case '^': { if( !inQuote && z[i+1]!=0 ){ i++; } break; } } } if( inQuote ) unsafe = i; #endif if( unsafe && safeCmdStrTest<2 ){ char *zMsg = mprintf("Unsafe command string: %s\n%*shere ----^", z, unsafe+13, ""); if( safeCmdStrTest ){ fossil_print("%z\n", zMsg); fossil_free(zMsg); }else{ fossil_panic("%s", zMsg); } } } /* |
︙ | ︙ | |||
313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 | /* The regular system() call works to get a shell on unix */ fossil_limit_memory(0); rc = system(zOrigCmd); fossil_limit_memory(1); #endif return rc; } /* ** COMMAND: test-fossil-system ** ** Read lines of input and send them to fossil_system() for evaluation. ** Use this command to verify that fossil_system() will not run "unsafe" ** commands. */ void test_fossil_system_cmd(void){ char zLine[10000]; safeCmdStrTest = 1; while(1){ size_t n; printf("system-test> "); fflush(stdout); if( !fgets(zLine, sizeof(zLine), stdin) ) break; n = strlen(zLine); while( n>0 && fossil_isspace(zLine[n-1]) ) n--; zLine[n] = 0; printf("cmd: [%s]\n", zLine); fflush(stdout); | > > > > > > > > > > > > > | > | 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 | /* The regular system() call works to get a shell on unix */ fossil_limit_memory(0); rc = system(zOrigCmd); fossil_limit_memory(1); #endif return rc; } /* ** Like "fossil_system()" but does not check the command-string for ** potential security problems. */ int fossil_unsafe_system(const char *zOrigCmd){ int rc; safeCmdStrTest = 2; rc = fossil_system(zOrigCmd); safeCmdStrTest = 0; return rc; } /* ** COMMAND: test-fossil-system ** ** Read lines of input and send them to fossil_system() for evaluation. ** Use this command to verify that fossil_system() will not run "unsafe" ** commands. */ void test_fossil_system_cmd(void){ char zLine[10000]; safeCmdStrTest = 1; while(1){ size_t n; int rc; printf("system-test> "); fflush(stdout); if( !fgets(zLine, sizeof(zLine), stdin) ) break; n = strlen(zLine); while( n>0 && fossil_isspace(zLine[n-1]) ) n--; zLine[n] = 0; printf("cmd: [%s]\n", zLine); fflush(stdout); rc = fossil_system(zLine); printf("result: %d\n", rc); } } /* ** Like strcmp() except that it accepts NULL pointers. NULL sorts before ** all non-NULL string pointers. Also, this strcmp() is a binary comparison ** that does not consider locale. |
︙ | ︙ |
Changes to src/wiki.c.
︙ | ︙ | |||
544 545 546 547 548 549 550 | Blob wiki; Manifest *pWiki = 0; const char *zPageName; const char *zMimetype = 0; const char *zHashsum = 0; /* of the wiki's corresponding artifact */ int isPopup = P("popup")!=0; char *zBody = mprintf("%s","<i>Empty Page</i>"); | | | 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 | Blob wiki; Manifest *pWiki = 0; const char *zPageName; const char *zMimetype = 0; const char *zHashsum = 0; /* of the wiki's corresponding artifact */ int isPopup = P("popup")!=0; char *zBody = mprintf("%s","<i>Empty Page</i>"); int noSubmenu = P("nsm")!=0 || g.isHome; login_check_credentials(); if( !g.perm.RdWiki ){ login_needed(g.anon.RdWiki); return; } zPageName = P("name"); if( zPageName==0 ){ if( search_restrict(SRCH_WIKI)!=0 ){ wiki_srchpage(); |
︙ | ︙ | |||
583 584 585 586 587 588 589 | if( pWiki ){ zBody = pWiki->zWiki; zMimetype = pWiki->zMimetype; zHashsum = rid_to_uuid(rid); } } zMimetype = wiki_filter_mimetypes(zMimetype); | | | 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 | if( pWiki ){ zBody = pWiki->zWiki; zMimetype = pWiki->zMimetype; zHashsum = rid_to_uuid(rid); } } zMimetype = wiki_filter_mimetypes(zMimetype); if( !noSubmenu ){ if( ((rid && g.perm.WrWiki) || (!rid && g.perm.NewWiki)) && wiki_special_permission(zPageName) ){ style_submenu_element("Edit", "%R/wikiedit?name=%T", zPageName); }else if( rid && g.perm.ApndWiki ){ style_submenu_element("Edit", "%R/wikiappend?name=%T", zPageName); } |
︙ | ︙ | |||
770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 | }else{ zErr = "Cannot happen! Please report this as a bug."; } } ajax_route_error(403, "%s", zErr); return 0; } /* ** Loads the given wiki page, sets the response type to ** application/json, and emits it as a JSON object. If zPageName is a ** sandbox page then a "fake" object is emitted, as the wikiajax API ** does not permit saving the sandbox. ** ** Returns true on success, false on error, and on error it ** queues up a JSON-format error response. ** ** Output JSON format: ** ** { name: "page name", ** type: "normal" | "tag" | "checkin" | "branch" | "sandbox", ** mimetype: "mimetype", ** version: UUID string or null for a sandbox page, ** parent: "parent uuid" or null if no parent, ** isDeleted: true if the page has no content (is "deleted") ** else not set (making it "falsy" in JS), ** content: "page content" (only if includeContent is true) ** } ** ** If includeContent is false then the content member is elided. */ static int wiki_ajax_emit_page_object(const char *zPageName, int includeContent){ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 | }else{ zErr = "Cannot happen! Please report this as a bug."; } } ajax_route_error(403, "%s", zErr); return 0; } /* ** Emits an array of attachment info records for the given wiki page ** artifact. ** ** Output format: ** ** [{ ** "uuid": attachment artifact hash, ** "src": hash of the attachment blob, ** "target": wiki page name or ticket/event ID, ** "filename": filename of attachment, ** "mtime": ISO-8601 timestamp UTC, ** "isLatest": true this is the latest version of this file ** else false, ** }, ...once per attachment] ** ** If there are no matching attachments then it will emit a JSON ** null (if nullIfEmpty) or an empty JSON array. ** ** If latestOnly is true then only the most recent entry for a given ** attachment is emitted, else all versions are emitted in descending ** mtime order. */ static void wiki_ajax_emit_page_attachments(Manifest * pWiki, int latestOnly, int nullIfEmpty){ int i = 0; Stmt q = empty_Stmt; db_prepare(&q, "SELECT datetime(mtime), src, target, filename, isLatest," " (SELECT uuid FROM blob WHERE rid=attachid) uuid" " FROM attachment" " WHERE target=%Q" " AND (isLatest OR %d)" " ORDER BY target, isLatest DESC, mtime DESC", pWiki->zWikiTitle, !latestOnly ); while(SQLITE_ROW == db_step(&q)){ const char * zTime = db_column_text(&q, 0); const char * zSrc = db_column_text(&q, 1); const char * zTarget = db_column_text(&q, 2); const char * zName = db_column_text(&q, 3); const int isLatest = db_column_int(&q, 4); const char * zUuid = db_column_text(&q, 5); if(!i++){ CX("["); }else{ CX(","); } CX("{"); CX("\"uuid\": %!j, \"src\": %!j, \"target\": %!j, " "\"filename\": %!j, \"mtime\": %!j, \"isLatest\": %s}", zUuid, zSrc, zTarget, zName, zTime, isLatest ? "true" : "false"); } db_finalize(&q); if(!i){ if(nullIfEmpty){ CX("null"); }else{ CX("[]"); } }else{ CX("]"); } } /* ** Proxy for wiki_ajax_emit_page_attachments() which attempts to load ** the given wiki page artifact. Returns true if it can load the given ** page, else false. If it returns false then it queues up a 404 ajax ** error response. */ static int wiki_ajax_emit_page_attachments2(const char *zPageName, int latestOnly, int nullIfEmpty){ Manifest * pWiki = 0; if( !wiki_fetch_by_name(zPageName, 0, 0, &pWiki) ){ ajax_route_error(404, "Wiki page could not be loaded: %s", zPageName); return 0; } wiki_ajax_emit_page_attachments(pWiki, latestOnly, nullIfEmpty); manifest_destroy(pWiki); return 1; } /* ** Loads the given wiki page, sets the response type to ** application/json, and emits it as a JSON object. If zPageName is a ** sandbox page then a "fake" object is emitted, as the wikiajax API ** does not permit saving the sandbox. ** ** Returns true on success, false on error, and on error it ** queues up a JSON-format error response. ** ** Output JSON format: ** ** { name: "page name", ** type: "normal" | "tag" | "checkin" | "branch" | "sandbox", ** mimetype: "mimetype", ** version: UUID string or null for a sandbox page, ** parent: "parent uuid" or null if no parent, ** isDeleted: true if the page has no content (is "deleted") ** else not set (making it "falsy" in JS), ** attachments: see wiki_ajax_emit_page_attachments(), ** content: "page content" (only if includeContent is true) ** } ** ** If includeContent is false then the content member is elided. */ static int wiki_ajax_emit_page_object(const char *zPageName, int includeContent){ |
︙ | ︙ | |||
839 840 841 842 843 844 845 846 847 848 849 850 851 852 | } if(!pWiki->zWiki || !pWiki->zWiki[0]){ CX(", \"isEmpty\": true"); } if(includeContent){ CX(", \"content\": %!j", pWiki->zWiki); } CX("}"); fossil_free(zUuid); manifest_destroy(pWiki); return 2; } } | > > | 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 | } if(!pWiki->zWiki || !pWiki->zWiki[0]){ CX(", \"isEmpty\": true"); } if(includeContent){ CX(", \"content\": %!j", pWiki->zWiki); } CX(", \"attachments\": "); wiki_ajax_emit_page_attachments(pWiki, 0, 1); CX("}"); fossil_free(zUuid); manifest_destroy(pWiki); return 2; } } |
︙ | ︙ | |||
930 931 932 933 934 935 936 937 938 939 940 941 942 943 | if( zPageName==0 || zPageName[0]==0 ){ ajax_route_error(400,"Missing page name."); return; } cgi_set_content_type("application/json"); wiki_ajax_emit_page_object(zPageName, 1); } /* ** Ajax route handler for /wikiajax/diff. ** ** URL params: ** ** page = the wiki page name | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 | if( zPageName==0 || zPageName[0]==0 ){ ajax_route_error(400,"Missing page name."); return; } cgi_set_content_type("application/json"); wiki_ajax_emit_page_object(zPageName, 1); } /* ** Ajax route handler for /wikiajax/attachments. ** ** URL params: ** ** page = the wiki page name ** latestOnly = if set, only latest version of each attachment ** is emitted. ** ** Responds with JSON: see wiki_ajax_emit_page_attachments() ** ** If there are no attachments it emits an empty array instead of null ** so that the output can be used as a top-level JSON response. ** ** On error, an object in the form documented by ** ajax_route_error(). On success, an object in the form documented ** for wiki_ajax_emit_page_attachments(). */ static void wiki_ajax_route_attachments(void){ const char * zPageName = P("page"); const int fLatestOnly = P("latestOnly")!=0; if( zPageName==0 || zPageName[0]==0 ){ ajax_route_error(400,"Missing page name."); return; } cgi_set_content_type("application/json"); wiki_ajax_emit_page_attachments2(zPageName, fLatestOnly, 0); } /* ** Ajax route handler for /wikiajax/diff. ** ** URL params: ** ** page = the wiki page name |
︙ | ︙ | |||
1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 | */ void wiki_ajax_page(void){ const char * zName = P("name"); AjaxRoute routeName = {0,0,0,0}; const AjaxRoute * pRoute = 0; const AjaxRoute routes[] = { /* Keep these sorted by zName (for bsearch()) */ {"diff", wiki_ajax_route_diff, 1, 1}, {"fetch", wiki_ajax_route_fetch, 0, 0}, {"list", wiki_ajax_route_list, 0, 0}, {"preview", wiki_ajax_route_preview, 0, 1}, {"save", wiki_ajax_route_save, 1, 1} }; | > | 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 | */ void wiki_ajax_page(void){ const char * zName = P("name"); AjaxRoute routeName = {0,0,0,0}; const AjaxRoute * pRoute = 0; const AjaxRoute routes[] = { /* Keep these sorted by zName (for bsearch()) */ {"attachments", wiki_ajax_route_attachments, 0, 0}, {"diff", wiki_ajax_route_diff, 1, 1}, {"fetch", wiki_ajax_route_fetch, 0, 0}, {"list", wiki_ajax_route_list, 0, 0}, {"preview", wiki_ajax_route_preview, 0, 1}, {"save", wiki_ajax_route_save, 1, 1} }; |
︙ | ︙ | |||
1313 1314 1315 1316 1317 1318 1319 | CX("</div>"/*#wikiedit-tab-diff*/); } /****** The obligatory "Misc" tab ******/ { CX("<div id='wikiedit-tab-misc' " "data-tab-parent='wikiedit-tabs' " | | > > > > | 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 | CX("</div>"/*#wikiedit-tab-diff*/); } /****** The obligatory "Misc" tab ******/ { CX("<div id='wikiedit-tab-misc' " "data-tab-parent='wikiedit-tabs' " "data-tab-label='Misc.' " "class='hidden'" ">"); CX("<fieldset id='attachment-wrapper'>"); CX("<legend>Attachments</legend>"); CX("<div>No attachments for the current page.</div>"); CX("</fieldset>"); CX("<h2>Wiki formatting rules</h2>"); CX("<ul>"); CX("<li><a href='%R/wiki_rules'>Fossil wiki format</a></li>"); CX("<li><a href='%R/md_rules'>Markdown format</a></li>"); CX("<li>Plain-text pages use no special formatting.</li>"); CX("</ul>"); CX("<h2>The \"Sandbox\" Page</h2>"); |
︙ | ︙ | |||
1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 | ** Show the complete change history for a single wiki page. */ void whistory_page(void){ Stmt q; const char *zPageName; double rNow; int showRid; login_check_credentials(); if( !g.perm.RdWiki ){ login_needed(g.anon.RdWiki); return; } zPageName = PD("name",""); style_set_current_feature("wiki"); style_header("History Of %s", zPageName); showRid = P("showid")!=0; db_prepare(&q, | > | 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 | ** Show the complete change history for a single wiki page. */ void whistory_page(void){ Stmt q; const char *zPageName; double rNow; int showRid; char zAuthor[64]; login_check_credentials(); if( !g.perm.RdWiki ){ login_needed(g.anon.RdWiki); return; } zPageName = PD("name",""); style_set_current_feature("wiki"); style_header("History Of %s", zPageName); showRid = P("showid")!=0; db_prepare(&q, |
︙ | ︙ | |||
1640 1641 1642 1643 1644 1645 1646 | @ id="wh-collapser"> ♲</span></th> if( showRid ){ @ <th>RID</th> } @ <th> </th> @ </tr></thead><tbody> rNow = db_double(0.0, "SELECT julianday('now')"); | | | 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 | @ id="wh-collapser"> ♲</span></th> if( showRid ){ @ <th>RID</th> } @ <th> </th> @ </tr></thead><tbody> rNow = db_double(0.0, "SELECT julianday('now')"); memset( zAuthor, 0, sizeof(zAuthor) ); while( db_step(&q)==SQLITE_ROW ){ double rMtime = db_column_double(&q, 0); const char *zUuid = db_column_text(&q, 1); const char *zUser = db_column_text(&q, 2); int wrid = db_column_int(&q, 3); const char *zWhen = db_column_text(&q, 4); /* sqlite3_int64 iMtime = (sqlite3_int64)(rMtime*86400.0); */ |
︙ | ︙ |
Changes to src/wiki.wiki.
︙ | ︙ | |||
83 84 85 86 87 88 89 | and HTML markup through the matching </verbatim>. Text within <tt><verbatim type="pikchr">...</verbatim></tt> is formatted using <a href="https://pikchr.org/home">Pikchr</a>. <a name="intermap"></a> | | | 83 84 85 86 87 88 89 90 | and HTML markup through the matching </verbatim>. Text within <tt><verbatim type="pikchr">...</verbatim></tt> is formatted using <a href="https://pikchr.org/home">Pikchr</a>. <a name="intermap"></a> <h2>Interwiki Tag [/intermap|Map]</h2> |
Changes to src/wikiformat.c.
︙ | ︙ | |||
2765 2766 2767 2768 2769 2770 2771 | ** convert the input into "safe HTML". The following modifications ** are made: ** ** 1. Remove any elements that are not on the AllowedMarkup list. ** (ex: <script>, <form>, etc.) ** ** 2. Remove any attributes that are not on the AllowedMarkup list. | | | | 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 | ** convert the input into "safe HTML". The following modifications ** are made: ** ** 1. Remove any elements that are not on the AllowedMarkup list. ** (ex: <script>, <form>, etc.) ** ** 2. Remove any attributes that are not on the AllowedMarkup list. ** (ex: onload=, etc.) ** ** 3. Omit any surplus close-tags. This prevents the script from ** terminating an <div> or similar in the outer context. ** ** 4. Insert additional close-tags as necessary so that any ** tag in the input that needs a close-tag has one. This ** prevents tags in the embedded script from affecting the ** display of content that follows this script in the enclosing ** context. ** ** These modifications are intended to make the generated HTML safe ** to be embedded in a larger HTML document, such that the embedded ** HTML has no influence on the formatting and operation of the ** larger document. ** ** If safe-html is disabled, then this routine is a no-op. */ void safe_html(Blob *in){ |
︙ | ︙ |
Changes to src/winhttp.c.
︙ | ︙ | |||
538 539 540 541 542 543 544 | blob_zero(&options); if( PB("HTTPS") ){ blob_appendf(&options, " --https"); } if( zBaseUrl ){ blob_appendf(&options, " --baseurl "); | | | | | | | 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 | blob_zero(&options); if( PB("HTTPS") ){ blob_appendf(&options, " --https"); } if( zBaseUrl ){ blob_appendf(&options, " --baseurl "); blob_append_escaped_arg(&options, zBaseUrl, 0); } if( zNotFound ){ blob_appendf(&options, " --notfound "); blob_append_escaped_arg(&options, zNotFound, 1); } if( g.zCkoutAlias ){ blob_appendf(&options, " --ckout-alias "); blob_append_escaped_arg(&options, g.zCkoutAlias, 0); } if( zFileGlob ){ blob_appendf(&options, " --files-urlenc %T", zFileGlob); } if( g.useLocalauth ){ blob_appendf(&options, " --localauth"); } if( g.thTrace ){ blob_appendf(&options, " --th-trace"); } if( flags & HTTP_SERVER_REPOLIST ){ blob_appendf(&options, " --repolist"); } if( g.zExtRoot && g.zExtRoot[0] ){ blob_appendf(&options, " --extroot"); blob_append_escaped_arg(&options, g.zExtRoot, 1); } zSkin = skin_in_use(); if( zSkin ){ blob_appendf(&options, " --skin %s", zSkin); } if( g.zMainMenuFile ){ blob_appendf(&options, " --mainmenu "); blob_append_escaped_arg(&options, g.zMainMenuFile, 1); } #if USE_SEE zSavedKey = db_get_saved_encryption_key(); savedKeySize = db_get_saved_encryption_key_size(); if( zSavedKey!=0 && savedKeySize>0 ){ blob_appendf(&options, " --usepidkey %lu:%p:%u", GetCurrentProcessId(), zSavedKey, savedKeySize); |
︙ | ︙ |
Changes to src/xfer.c.
︙ | ︙ | |||
1059 1060 1061 1062 1063 1064 1065 | ** pXfer is a "pragma uv-hash HASH" card. ** ** If HASH is different from the unversioned content hash on this server, ** then send a bunch of uvigot cards, one for each entry unversioned file ** on this server. */ static void send_unversioned_catalog(Xfer *pXfer){ | < < | | > | | | | | | | | | | | | | | < | 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 | ** pXfer is a "pragma uv-hash HASH" card. ** ** If HASH is different from the unversioned content hash on this server, ** then send a bunch of uvigot cards, one for each entry unversioned file ** on this server. */ static void send_unversioned_catalog(Xfer *pXfer){ int nUvIgot = 0; Stmt uvq; unversioned_schema(); db_prepare(&uvq, "SELECT name, mtime, hash, sz FROM unversioned" ); while( db_step(&uvq)==SQLITE_ROW ){ const char *zName = db_column_text(&uvq,0); sqlite3_int64 mtime = db_column_int64(&uvq,1); const char *zHash = db_column_text(&uvq,2); int sz = db_column_int(&uvq,3); nUvIgot++; if( zHash==0 ){ sz = 0; zHash = "-"; } blob_appendf(pXfer->pOut, "uvigot %s %lld %s %d\n", zName, mtime, zHash, sz); } db_finalize(&uvq); } /* ** Called when there is an attempt to transfer private content to and ** from a server without authorization. */ static void server_private_xfer_not_authorized(void){ |
︙ | ︙ | |||
1614 1615 1616 1617 1618 1619 1620 | ** The client wants to make sure that unversioned files are all synced. ** If the HASH does not match, send a complete catalog of ** "uvigot" cards. */ if( blob_eq(&xfer.aToken[1], "uv-hash") && blob_is_hname(&xfer.aToken[2]) ){ | | > > > | < < > | 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 | ** The client wants to make sure that unversioned files are all synced. ** If the HASH does not match, send a complete catalog of ** "uvigot" cards. */ if( blob_eq(&xfer.aToken[1], "uv-hash") && blob_is_hname(&xfer.aToken[2]) ){ if( !uvCatalogSent && g.perm.Read && !blob_eq_str(&xfer.aToken[2], unversioned_content_hash(0),-1) ){ if( g.perm.WrUnver ){ @ pragma uv-push-ok }else if( g.perm.Read ){ @ pragma uv-pull-only } send_unversioned_catalog(&xfer); } uvCatalogSent = 1; } /* pragma ci-lock CHECKIN-HASH CLIENT-ID ** ** The client wants to make non-branch commit against the check-in |
︙ | ︙ | |||
1811 1812 1813 1814 1815 1816 1817 | */ #define SYNC_PUSH 0x0001 /* push content client to server */ #define SYNC_PULL 0x0002 /* pull content server to client */ #define SYNC_CLONE 0x0004 /* clone the repository */ #define SYNC_PRIVATE 0x0008 /* Also transfer private content */ #define SYNC_VERBOSE 0x0010 /* Extra diagnostics */ #define SYNC_RESYNC 0x0020 /* --verily */ | > | | < | | | | > | 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 | */ #define SYNC_PUSH 0x0001 /* push content client to server */ #define SYNC_PULL 0x0002 /* pull content server to client */ #define SYNC_CLONE 0x0004 /* clone the repository */ #define SYNC_PRIVATE 0x0008 /* Also transfer private content */ #define SYNC_VERBOSE 0x0010 /* Extra diagnostics */ #define SYNC_RESYNC 0x0020 /* --verily */ #define SYNC_FROMPARENT 0x0040 /* Pull from the parent project */ #define SYNC_UNVERSIONED 0x0100 /* Sync unversioned content */ #define SYNC_UV_REVERT 0x0200 /* Copy server unversioned to client */ #define SYNC_UV_TRACE 0x0400 /* Describe UV activities */ #define SYNC_UV_DRYRUN 0x0800 /* Do not actually exchange files */ #define SYNC_IFABLE 0x1000 /* Inability to sync is not fatal */ #define SYNC_CKIN_LOCK 0x2000 /* Lock the current check-in */ #define SYNC_NOHTTPCOMPRESS 0x4000 /* Do not compression HTTP messages */ #endif /* ** Floating-point absolute value */ static double fossil_fabs(double x){ return x>0.0 ? x : -x; |
︙ | ︙ | |||
1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 | int nCardRcvd = 0; /* Number of cards received */ int nCycle = 0; /* Number of round trips to the server */ int size; /* Size of a config value or uvfile */ int origConfigRcvMask; /* Original value of configRcvMask */ int nFileRecv; /* Number of files received */ int mxPhantomReq = 200; /* Max number of phantoms to request per comm */ const char *zCookie; /* Server cookie */ i64 nSent, nRcvd; /* Bytes sent and received (after compression) */ int cloneSeqno = 1; /* Sequence number for clones */ Blob send; /* Text we are sending to the server */ Blob recv; /* Reply we got back from the server */ Xfer xfer; /* Transfer data */ int pctDone; /* Percentage done with a message */ int lastPctDone = -1; /* Last displayed pctDone */ double rArrivalTime; /* Time at which a message arrived */ const char *zSCode = db_get("server-code", "x"); const char *zPCode = db_get("project-code", 0); int nErr = 0; /* Number of errors */ int nRoundtrip= 0; /* Number of HTTP requests */ int nArtifactSent = 0; /* Total artifacts sent */ int nArtifactRcvd = 0; /* Total artifacts received */ const char *zOpType = 0;/* Push, Pull, Sync, Clone */ double rSkew = 0.0; /* Maximum time skew */ int uvHashSent = 0; /* The "pragma uv-hash" message has been sent */ int uvDoPush = 0; /* Generate uvfile messages to send to server */ int nUvGimmeSent = 0; /* Number of uvgimme cards sent on this cycle */ int nUvFileRcvd = 0; /* Number of uvfile cards received on this cycle */ sqlite3_int64 mtime; /* Modification time on a UV file */ int autopushFailed = 0; /* Autopush following commit failed if true */ const char *zCkinLock; /* Name of check-in to lock. NULL for none */ const char *zClientId; /* A unique identifier for this check-out */ unsigned int mHttpFlags;/* Flags for the http_exchange() subsystem */ | > > | 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 | int nCardRcvd = 0; /* Number of cards received */ int nCycle = 0; /* Number of round trips to the server */ int size; /* Size of a config value or uvfile */ int origConfigRcvMask; /* Original value of configRcvMask */ int nFileRecv; /* Number of files received */ int mxPhantomReq = 200; /* Max number of phantoms to request per comm */ const char *zCookie; /* Server cookie */ i64 nUncSent, nUncRcvd; /* Bytes sent and received (before compression) */ i64 nSent, nRcvd; /* Bytes sent and received (after compression) */ int cloneSeqno = 1; /* Sequence number for clones */ Blob send; /* Text we are sending to the server */ Blob recv; /* Reply we got back from the server */ Xfer xfer; /* Transfer data */ int pctDone; /* Percentage done with a message */ int lastPctDone = -1; /* Last displayed pctDone */ double rArrivalTime; /* Time at which a message arrived */ const char *zSCode = db_get("server-code", "x"); const char *zPCode = db_get("project-code", 0); int nErr = 0; /* Number of errors */ int nRoundtrip= 0; /* Number of HTTP requests */ int nArtifactSent = 0; /* Total artifacts sent */ int nArtifactRcvd = 0; /* Total artifacts received */ const char *zOpType = 0;/* Push, Pull, Sync, Clone */ double rSkew = 0.0; /* Maximum time skew */ int uvHashSent = 0; /* The "pragma uv-hash" message has been sent */ int uvDoPush = 0; /* Generate uvfile messages to send to server */ int uvPullOnly = 0; /* 1: pull-only. 2: pull-only warning issued */ int nUvGimmeSent = 0; /* Number of uvgimme cards sent on this cycle */ int nUvFileRcvd = 0; /* Number of uvfile cards received on this cycle */ sqlite3_int64 mtime; /* Modification time on a UV file */ int autopushFailed = 0; /* Autopush following commit failed if true */ const char *zCkinLock; /* Name of check-in to lock. NULL for none */ const char *zClientId; /* A unique identifier for this check-out */ unsigned int mHttpFlags;/* Flags for the http_exchange() subsystem */ |
︙ | ︙ | |||
1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 | blobarray_zero(xfer.aToken, count(xfer.aToken)); blob_zero(&send); blob_zero(&recv); blob_zero(&xfer.err); blob_zero(&xfer.line); origConfigRcvMask = 0; /* Send the send-private pragma if we are trying to sync private data */ if( syncFlags & SYNC_PRIVATE ){ blob_append(&send, "pragma send-private\n", -1); } /* Figure out which check-in to lock */ | > | 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 | blobarray_zero(xfer.aToken, count(xfer.aToken)); blob_zero(&send); blob_zero(&recv); blob_zero(&xfer.err); blob_zero(&xfer.line); origConfigRcvMask = 0; nUncSent = nUncRcvd = 0; /* Send the send-private pragma if we are trying to sync private data */ if( syncFlags & SYNC_PRIVATE ){ blob_append(&send, "pragma send-private\n", -1); } /* Figure out which check-in to lock */ |
︙ | ︙ | |||
2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 | /* Exchange messages with the server */ if( (syncFlags & SYNC_CLONE)!=0 && nCycle==0 ){ /* Do not send a login card on the first round-trip of a clone */ mHttpFlags = 0; }else{ mHttpFlags = HTTP_USE_LOGIN; } if( http_exchange(&send, &recv, mHttpFlags, MAX_REDIRECTS, 0) ){ nErr++; go = 2; break; } /* Output current stats */ if( syncFlags & SYNC_VERBOSE ){ fossil_print(zValueFormat /*works-like:"%s%d%d%d%d"*/, "Sent:", blob_size(&send), nCardSent+xfer.nGimmeSent+xfer.nIGotSent, xfer.nFileSent, xfer.nDeltaSent); }else{ | > > > > > > > > > > > > > > | 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 | /* Exchange messages with the server */ if( (syncFlags & SYNC_CLONE)!=0 && nCycle==0 ){ /* Do not send a login card on the first round-trip of a clone */ mHttpFlags = 0; }else{ mHttpFlags = HTTP_USE_LOGIN; } if( syncFlags & SYNC_NOHTTPCOMPRESS ){ mHttpFlags |= HTTP_NOCOMPRESS; } /* Do the round-trip to the server */ if( http_exchange(&send, &recv, mHttpFlags, MAX_REDIRECTS, 0) ){ nErr++; go = 2; break; } /* Remember the URL of the sync target in the config file on the ** first successful round-trip */ if( nCycle==0 && db_is_writeable("repository") ){ db_unprotect(PROTECT_CONFIG); db_multi_exec("REPLACE INTO config(name,value,mtime)" "VALUES('syncwith:%q',1,now())", g.url.canonical); db_protect_pop(); } /* Output current stats */ if( syncFlags & SYNC_VERBOSE ){ fossil_print(zValueFormat /*works-like:"%s%d%d%d%d"*/, "Sent:", blob_size(&send), nCardSent+xfer.nGimmeSent+xfer.nIGotSent, xfer.nFileSent, xfer.nDeltaSent); }else{ |
︙ | ︙ | |||
2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 | xfer.nFileSent = 0; xfer.nDeltaSent = 0; xfer.nGimmeSent = 0; xfer.nIGotSent = 0; xfer.nPrivIGot = 0; lastPctDone = -1; blob_reset(&send); blob_appendf(&send, "pragma client-version %d %d %d\n", RELEASE_VERSION_NUMBER, MANIFEST_NUMERIC_DATE, MANIFEST_NUMERIC_TIME); rArrivalTime = db_double(0.0, "SELECT julianday('now')"); /* Send the send-private pragma if we are trying to sync private data */ | > | 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 | xfer.nFileSent = 0; xfer.nDeltaSent = 0; xfer.nGimmeSent = 0; xfer.nIGotSent = 0; xfer.nPrivIGot = 0; lastPctDone = -1; nUncSent += blob_size(&send); blob_reset(&send); blob_appendf(&send, "pragma client-version %d %d %d\n", RELEASE_VERSION_NUMBER, MANIFEST_NUMERIC_DATE, MANIFEST_NUMERIC_TIME); rArrivalTime = db_double(0.0, "SELECT julianday('now')"); /* Send the send-private pragma if we are trying to sync private data */ |
︙ | ︙ | |||
2354 2355 2356 2357 2358 2359 2360 | } }else if( iStatus==2 ){ db_multi_exec( "UPDATE unversioned SET mtime=%lld WHERE name=%Q", mtime, zName ); db_unset("uv-hash", 0); } | > > > > > > > > | | 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 | } }else if( iStatus==2 ){ db_multi_exec( "UPDATE unversioned SET mtime=%lld WHERE name=%Q", mtime, zName ); db_unset("uv-hash", 0); } if( iStatus>=4 && uvPullOnly==1 ){ fossil_warning( "Warning: uv-pull-only \n" " Unable to push unversioned content because you lack\n" " sufficient permission on the server\n" ); uvPullOnly = 2; } if( iStatus<=3 || uvPullOnly ){ db_multi_exec("DELETE FROM uv_tosend WHERE name=%Q", zName); }else if( iStatus==4 ){ db_multi_exec("UPDATE uv_tosend SET mtimeOnly=1 WHERE name=%Q",zName); }else if( iStatus==5 ){ db_multi_exec("REPLACE INTO uv_tosend(name,mtimeOnly) VALUES(%Q,0)", zName); } |
︙ | ︙ | |||
2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 | if( xfer.nToken>=5 ){ xfer.remoteDate = atoi(blob_str(&xfer.aToken[3])); xfer.remoteTime = atoi(blob_str(&xfer.aToken[4])); } } /* pragma uv-pull-only ** ** If the server is unwill to accept new unversioned content (because ** this client lacks the necessary permissions) then it sends a ** "uv-pull-only" pragma so that the client will know not to waste ** bandwidth trying to upload unversioned content. If the server ** does accept new unversioned content, it sends "uv-push-ok". */ | > > | < | < < < | | | > | 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 | if( xfer.nToken>=5 ){ xfer.remoteDate = atoi(blob_str(&xfer.aToken[3])); xfer.remoteTime = atoi(blob_str(&xfer.aToken[4])); } } /* pragma uv-pull-only ** pragma uv-push-ok ** ** If the server is unwill to accept new unversioned content (because ** this client lacks the necessary permissions) then it sends a ** "uv-pull-only" pragma so that the client will know not to waste ** bandwidth trying to upload unversioned content. If the server ** does accept new unversioned content, it sends "uv-push-ok". */ if( syncFlags & SYNC_UNVERSIONED ){ if( blob_eq(&xfer.aToken[1], "uv-pull-only") ){ uvPullOnly = 1; if( syncFlags & SYNC_UV_REVERT ) uvDoPush = 1; }else if( blob_eq(&xfer.aToken[1], "uv-push-ok") ){ uvDoPush = 1; } } /* pragma ci-lock-fail USER-HOLDING-LOCK LOCK-TIME ** ** The server generates this message when a "pragma ci-lock" ** is attempted on a check-in for which there is an existing ** lock. USER-HOLDING-LOCK is the name of the user who originated |
︙ | ︙ | |||
2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 | fossil_print(zValueFormat /*works-like:"%s%d%d%d%d"*/, "Received:", blob_size(&recv), nCardRcvd, xfer.nFileRcvd, xfer.nDeltaRcvd + xfer.nDanglingFile); }else{ fossil_print(zBriefFormat /*works-like:"%d%d%d"*/, nRoundtrip, nArtifactSent, nArtifactRcvd); } blob_reset(&recv); nCycle++; /* If we received one or more files on the previous exchange but ** there are still phantoms, then go another round. */ nFileRecv = xfer.nFileRcvd + xfer.nDeltaRcvd + xfer.nDanglingFile; | > | 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 | fossil_print(zValueFormat /*works-like:"%s%d%d%d%d"*/, "Received:", blob_size(&recv), nCardRcvd, xfer.nFileRcvd, xfer.nDeltaRcvd + xfer.nDanglingFile); }else{ fossil_print(zBriefFormat /*works-like:"%d%d%d"*/, nRoundtrip, nArtifactSent, nArtifactRcvd); } nUncRcvd += blob_size(&recv); blob_reset(&recv); nCycle++; /* If we received one or more files on the previous exchange but ** there are still phantoms, then go another round. */ nFileRecv = xfer.nFileRcvd + xfer.nDeltaRcvd + xfer.nDanglingFile; |
︙ | ︙ | |||
2659 2660 2661 2662 2663 2664 2665 | fossil_warning("*** time skew *** server is slow by %s", db_timespan_name(-rSkew)); g.clockSkewSeen = 1; } fossil_force_newline(); fossil_print( | | > > > > | 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 | fossil_warning("*** time skew *** server is slow by %s", db_timespan_name(-rSkew)); g.clockSkewSeen = 1; } fossil_force_newline(); fossil_print( "%s done, wire bytes sent: %lld received: %lld ip: %s\n", zOpType, nSent, nRcvd, g.zIpAddr); if( syncFlags & SYNC_VERBOSE ){ fossil_print( "Uncompressed payload sent: %lld received: %lld\n", nUncSent, nUncRcvd); } transport_close(&g.url); transport_global_shutdown(&g.url); if( nErr && go==2 ){ db_multi_exec("DROP TABLE onremote; DROP TABLE unk;"); manifest_crosslink_end(MC_PERMIT_HOOKS); content_enable_dephantomize(1); db_end_transaction(0); |
︙ | ︙ |
Changes to src/xfersetup.c.
︙ | ︙ | |||
118 119 120 121 122 123 124 | if( z==0 ){ z = db_get(zDbField, zDfltValue); } style_set_current_feature("xfersetup"); style_header("Edit %s", zTitle); if( P("clear")!=0 ){ login_verify_csrf_secret(); | | | | 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | if( z==0 ){ z = db_get(zDbField, zDfltValue); } style_set_current_feature("xfersetup"); style_header("Edit %s", zTitle); if( P("clear")!=0 ){ login_verify_csrf_secret(); db_unset(zDbField/*works-like:"x"*/, 0); if( xRebuild ) xRebuild(); z = zDfltValue; }else if( isSubmit ){ char *zErr = 0; login_verify_csrf_secret(); if( xText && (zErr = xText(z))!=0 ){ @ <p class="xfersetupError">ERROR: %h(zErr)</p> }else{ db_set(zDbField/*works-like:"x"*/, z, 0); if( xRebuild ) xRebuild(); cgi_redirect("xfersetup"); } } @ <form action="%R/%s(g.zPath)" method="post"><div> login_insert_csrf_secret(); @ <p>%s(zDesc)</p> |
︙ | ︙ |
Changes to src/zip.c.
︙ | ︙ | |||
938 939 940 941 942 943 944 945 946 947 948 949 950 951 | nName = strlen(zName); g.zOpenRevision = zRid = fossil_strdup(z); nRid = strlen(zRid); zInclude = P("in"); if( zInclude ) pInclude = glob_create(zInclude); zExclude = P("ex"); if( zExclude ) pExclude = glob_create(zExclude); if( eType==ARCHIVE_ZIP && nName>4 && fossil_strcmp(&zName[nName-4], ".zip")==0 ){ /* Special case: Remove the ".zip" suffix. */ nName -= 4; zName[nName] = 0; | > > > | 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 | nName = strlen(zName); g.zOpenRevision = zRid = fossil_strdup(z); nRid = strlen(zRid); zInclude = P("in"); if( zInclude ) pInclude = glob_create(zInclude); zExclude = P("ex"); if( zExclude ) pExclude = glob_create(zExclude); if( zInclude==0 && zExclude==0 ){ etag_check_for_invariant_name(z); } if( eType==ARCHIVE_ZIP && nName>4 && fossil_strcmp(&zName[nName-4], ".zip")==0 ){ /* Special case: Remove the ".zip" suffix. */ nName -= 4; zName[nName] = 0; |
︙ | ︙ |
Changes to test/tester.tcl.
︙ | ︙ | |||
349 350 351 352 353 354 355 356 357 358 359 360 361 362 | sitemap-extra \ ssh-command \ ssl-ca-location \ ssl-identity \ tclsh \ th1-setup \ th1-uri-regexp \ user-color-map \ uv-sync \ web-browser] fossil test-th-eval "hasfeature legacyMvRm" if {[normalize_result] eq "1"} { | > | 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 | sitemap-extra \ ssh-command \ ssl-ca-location \ ssl-identity \ tclsh \ th1-setup \ th1-uri-regexp \ ticket-default-report \ user-color-map \ uv-sync \ web-browser] fossil test-th-eval "hasfeature legacyMvRm" if {[normalize_result] eq "1"} { |
︙ | ︙ |
Changes to win/Makefile.dmc.
︙ | ︙ | |||
26 27 28 29 30 31 32 | TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL) LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32 dnsapi SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0 SHELL_OPTIONS = -DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0 -Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname -DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen | | | | | 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL) LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32 dnsapi SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0 SHELL_OPTIONS = -DNDEBUG=1 -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_TRUSTED_SCHEMA=0 -Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname -DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen SRC = add_.c ajax_.c alerts_.c allrepo_.c attach_.c backlink_.c backoffice_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c capabilities_.c captcha_.c cgi_.c chat_.c checkin_.c checkout_.c clearsign_.c clone_.c color_.c comformat_.c configure_.c content_.c cookies_.c db_.c delta_.c deltacmd_.c deltafunc_.c descendants_.c diff_.c diffcmd_.c dispatch_.c doc_.c encode_.c etag_.c event_.c export_.c extcgi_.c file_.c fileedit_.c finfo_.c foci_.c forum_.c fshell_.c fusefs_.c fuzz_.c glob_.c graph_.c gzip_.c hname_.c hook_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c interwiki_.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 patch_.c path_.c piechart_.c pikchr_.c pikchrshow_.c pivot_.c popen_.c pqueue_.c printf_.c publish_.c purge_.c rebuild_.c regexp_.c repolist_.c report_.c rss_.c schema_.c search_.c security_audit_.c setup_.c setupuser_.c sha1_.c sha1hard_.c sha3_.c shun_.c sitemap_.c skins_.c smtp_.c sqlcmd_.c stash_.c stat_.c statrep_.c style_.c sync_.c tag_.c tar_.c terminal_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c unversioned_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c xfer_.c xfersetup_.c zip_.c OBJ = $(OBJDIR)\add$O $(OBJDIR)\ajax$O $(OBJDIR)\alerts$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\backlink$O $(OBJDIR)\backoffice$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)\capabilities$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\chat$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\color$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\cookies$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\deltafunc$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\dispatch$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\etag$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\extcgi$O $(OBJDIR)\file$O $(OBJDIR)\fileedit$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\forum$O $(OBJDIR)\fshell$O $(OBJDIR)\fusefs$O $(OBJDIR)\fuzz$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\hname$O $(OBJDIR)\hook$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\interwiki$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)\patch$O $(OBJDIR)\path$O $(OBJDIR)\piechart$O $(OBJDIR)\pikchr$O $(OBJDIR)\pikchrshow$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)\repolist$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\security_audit$O $(OBJDIR)\setup$O $(OBJDIR)\setupuser$O $(OBJDIR)\sha1$O $(OBJDIR)\sha1hard$O $(OBJDIR)\sha3$O $(OBJDIR)\shun$O $(OBJDIR)\sitemap$O $(OBJDIR)\skins$O $(OBJDIR)\smtp$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\statrep$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\terminal$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\unversioned$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)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O RC=$(DMDIR)\bin\rcc RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__ APPNAME = $(OBJDIR)\fossil$(E) all: $(APPNAME) $(APPNAME) : translate$E mkindex$E codecheck1$E headers $(OBJ) $(OBJDIR)\link cd $(OBJDIR) codecheck1$E $(SRC) $(DMDIR)\bin\link @link $(OBJDIR)\fossil.res: $B\win\fossil.rc $(RC) $(RCFLAGS) -o$@ $** $(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res +echo add ajax alerts allrepo attach backlink backoffice bag bisect blob branch browse builtin bundle cache capabilities captcha cgi chat checkin checkout clearsign clone color comformat configure content cookies db delta deltacmd deltafunc descendants diff diffcmd dispatch doc encode etag event export extcgi file fileedit finfo foci forum fshell fusefs fuzz glob graph gzip hname hook http http_socket http_ssl http_transport import info interwiki 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 patch path piechart pikchr pikchrshow pivot popen pqueue printf publish purge rebuild regexp repolist report rss schema search security_audit setup setupuser sha1 sha1hard sha3 shun sitemap skins smtp sqlcmd stash stat statrep style sync tag tar terminal th_main timeline tkt tktsetup undo unicode unversioned update url user utf8 util verify vfile wiki wikiformat winfile winhttp xfer xfersetup zip shell sqlite3 th th_lang > $@ +echo fossil >> $@ +echo fossil >> $@ +echo $(LIBS) >> $@ +echo. >> $@ +echo fossil >> $@ translate$E: $(SRCDIR)\translate.c |
︙ | ︙ | |||
659 660 661 662 663 664 665 666 667 668 669 670 671 672 | +translate$E $** > $@ $(OBJDIR)\name$O : name_.c name.h $(TCC) -o$@ -c name_.c name_.c : $(SRCDIR)\name.c +translate$E $** > $@ $(OBJDIR)\path$O : path_.c path.h $(TCC) -o$@ -c path_.c path_.c : $(SRCDIR)\path.c +translate$E $** > $@ | > > > > > > | 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 | +translate$E $** > $@ $(OBJDIR)\name$O : name_.c name.h $(TCC) -o$@ -c name_.c name_.c : $(SRCDIR)\name.c +translate$E $** > $@ $(OBJDIR)\patch$O : patch_.c patch.h $(TCC) -o$@ -c patch_.c patch_.c : $(SRCDIR)\patch.c +translate$E $** > $@ $(OBJDIR)\path$O : path_.c path.h $(TCC) -o$@ -c path_.c path_.c : $(SRCDIR)\path.c +translate$E $** > $@ |
︙ | ︙ | |||
1003 1004 1005 1006 1007 1008 1009 | $(OBJDIR)\zip$O : zip_.c zip.h $(TCC) -o$@ -c zip_.c zip_.c : $(SRCDIR)\zip.c +translate$E $** > $@ headers: makeheaders$E page_index.h builtin_data.h VERSION.h | | | 1009 1010 1011 1012 1013 1014 1015 1016 1017 | $(OBJDIR)\zip$O : zip_.c zip.h $(TCC) -o$@ -c zip_.c zip_.c : $(SRCDIR)\zip.c +translate$E $** > $@ headers: makeheaders$E page_index.h builtin_data.h VERSION.h +makeheaders$E add_.c:add.h ajax_.c:ajax.h alerts_.c:alerts.h allrepo_.c:allrepo.h attach_.c:attach.h backlink_.c:backlink.h backoffice_.c:backoffice.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 capabilities_.c:capabilities.h captcha_.c:captcha.h cgi_.c:cgi.h chat_.c:chat.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h color_.c:color.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h cookies_.c:cookies.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h deltafunc_.c:deltafunc.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h dispatch_.c:dispatch.h doc_.c:doc.h encode_.c:encode.h etag_.c:etag.h event_.c:event.h export_.c:export.h extcgi_.c:extcgi.h file_.c:file.h fileedit_.c:fileedit.h finfo_.c:finfo.h foci_.c:foci.h forum_.c:forum.h fshell_.c:fshell.h fusefs_.c:fusefs.h fuzz_.c:fuzz.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h hname_.c:hname.h hook_.c:hook.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 interwiki_.c:interwiki.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 patch_.c:patch.h path_.c:path.h piechart_.c:piechart.h pikchr_.c:pikchr.h pikchrshow_.c:pikchrshow.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 repolist_.c:repolist.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h security_audit_.c:security_audit.h setup_.c:setup.h setupuser_.c:setupuser.h sha1_.c:sha1.h sha1hard_.c:sha1hard.h sha3_.c:sha3.h shun_.c:shun.h sitemap_.c:sitemap.h skins_.c:skins.h smtp_.c:smtp.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h statrep_.c:statrep.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h terminal_.c:terminal.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 unversioned_.c:unversioned.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 xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h @copy /Y nul: headers |
Changes to win/Makefile.mingw.
︙ | ︙ | |||
511 512 513 514 515 516 517 518 519 520 521 522 523 524 | $(SRCDIR)/markdown.c \ $(SRCDIR)/markdown_html.c \ $(SRCDIR)/md5.c \ $(SRCDIR)/merge.c \ $(SRCDIR)/merge3.c \ $(SRCDIR)/moderate.c \ $(SRCDIR)/name.c \ $(SRCDIR)/path.c \ $(SRCDIR)/piechart.c \ $(SRCDIR)/pikchr.c \ $(SRCDIR)/pikchrshow.c \ $(SRCDIR)/pivot.c \ $(SRCDIR)/popen.c \ $(SRCDIR)/pqueue.c \ | > | 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 | $(SRCDIR)/markdown.c \ $(SRCDIR)/markdown_html.c \ $(SRCDIR)/md5.c \ $(SRCDIR)/merge.c \ $(SRCDIR)/merge3.c \ $(SRCDIR)/moderate.c \ $(SRCDIR)/name.c \ $(SRCDIR)/patch.c \ $(SRCDIR)/path.c \ $(SRCDIR)/piechart.c \ $(SRCDIR)/pikchr.c \ $(SRCDIR)/pikchrshow.c \ $(SRCDIR)/pivot.c \ $(SRCDIR)/popen.c \ $(SRCDIR)/pqueue.c \ |
︙ | ︙ | |||
768 769 770 771 772 773 774 775 776 777 778 779 780 781 | $(OBJDIR)/markdown_.c \ $(OBJDIR)/markdown_html_.c \ $(OBJDIR)/md5_.c \ $(OBJDIR)/merge_.c \ $(OBJDIR)/merge3_.c \ $(OBJDIR)/moderate_.c \ $(OBJDIR)/name_.c \ $(OBJDIR)/path_.c \ $(OBJDIR)/piechart_.c \ $(OBJDIR)/pikchr_.c \ $(OBJDIR)/pikchrshow_.c \ $(OBJDIR)/pivot_.c \ $(OBJDIR)/popen_.c \ $(OBJDIR)/pqueue_.c \ | > | 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 | $(OBJDIR)/markdown_.c \ $(OBJDIR)/markdown_html_.c \ $(OBJDIR)/md5_.c \ $(OBJDIR)/merge_.c \ $(OBJDIR)/merge3_.c \ $(OBJDIR)/moderate_.c \ $(OBJDIR)/name_.c \ $(OBJDIR)/patch_.c \ $(OBJDIR)/path_.c \ $(OBJDIR)/piechart_.c \ $(OBJDIR)/pikchr_.c \ $(OBJDIR)/pikchrshow_.c \ $(OBJDIR)/pivot_.c \ $(OBJDIR)/popen_.c \ $(OBJDIR)/pqueue_.c \ |
︙ | ︙ | |||
917 918 919 920 921 922 923 924 925 926 927 928 929 930 | $(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)/piechart.o \ $(OBJDIR)/pikchr.o \ $(OBJDIR)/pikchrshow.o \ $(OBJDIR)/pivot.o \ $(OBJDIR)/popen.o \ $(OBJDIR)/pqueue.o \ | > | 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 | $(OBJDIR)/markdown.o \ $(OBJDIR)/markdown_html.o \ $(OBJDIR)/md5.o \ $(OBJDIR)/merge.o \ $(OBJDIR)/merge3.o \ $(OBJDIR)/moderate.o \ $(OBJDIR)/name.o \ $(OBJDIR)/patch.o \ $(OBJDIR)/path.o \ $(OBJDIR)/piechart.o \ $(OBJDIR)/pikchr.o \ $(OBJDIR)/pikchrshow.o \ $(OBJDIR)/pivot.o \ $(OBJDIR)/popen.o \ $(OBJDIR)/pqueue.o \ |
︙ | ︙ | |||
1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 | $(OBJDIR)/markdown_.c:$(OBJDIR)/markdown.h \ $(OBJDIR)/markdown_html_.c:$(OBJDIR)/markdown_html.h \ $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h \ $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h \ $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h \ $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h \ $(OBJDIR)/name_.c:$(OBJDIR)/name.h \ $(OBJDIR)/path_.c:$(OBJDIR)/path.h \ $(OBJDIR)/piechart_.c:$(OBJDIR)/piechart.h \ $(OBJDIR)/pikchr_.c:$(OBJDIR)/pikchr.h \ $(OBJDIR)/pikchrshow_.c:$(OBJDIR)/pikchrshow.h \ $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \ $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \ $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \ | > | 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 | $(OBJDIR)/markdown_.c:$(OBJDIR)/markdown.h \ $(OBJDIR)/markdown_html_.c:$(OBJDIR)/markdown_html.h \ $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h \ $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h \ $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h \ $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h \ $(OBJDIR)/name_.c:$(OBJDIR)/name.h \ $(OBJDIR)/patch_.c:$(OBJDIR)/patch.h \ $(OBJDIR)/path_.c:$(OBJDIR)/path.h \ $(OBJDIR)/piechart_.c:$(OBJDIR)/piechart.h \ $(OBJDIR)/pikchr_.c:$(OBJDIR)/pikchr.h \ $(OBJDIR)/pikchrshow_.c:$(OBJDIR)/pikchrshow.h \ $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \ $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \ $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \ |
︙ | ︙ | |||
2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 | $(OBJDIR)/name_.c: $(SRCDIR)/name.c $(TRANSLATE) $(TRANSLATE) $(SRCDIR)/name.c >$@ $(OBJDIR)/name.o: $(OBJDIR)/name_.c $(OBJDIR)/name.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/name.o -c $(OBJDIR)/name_.c $(OBJDIR)/name.h: $(OBJDIR)/headers $(OBJDIR)/path_.c: $(SRCDIR)/path.c $(TRANSLATE) $(TRANSLATE) $(SRCDIR)/path.c >$@ $(OBJDIR)/path.o: $(OBJDIR)/path_.c $(OBJDIR)/path.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/path.o -c $(OBJDIR)/path_.c | > > > > > > > > | 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 | $(OBJDIR)/name_.c: $(SRCDIR)/name.c $(TRANSLATE) $(TRANSLATE) $(SRCDIR)/name.c >$@ $(OBJDIR)/name.o: $(OBJDIR)/name_.c $(OBJDIR)/name.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/name.o -c $(OBJDIR)/name_.c $(OBJDIR)/name.h: $(OBJDIR)/headers $(OBJDIR)/patch_.c: $(SRCDIR)/patch.c $(TRANSLATE) $(TRANSLATE) $(SRCDIR)/patch.c >$@ $(OBJDIR)/patch.o: $(OBJDIR)/patch_.c $(OBJDIR)/patch.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/patch.o -c $(OBJDIR)/patch_.c $(OBJDIR)/patch.h: $(OBJDIR)/headers $(OBJDIR)/path_.c: $(SRCDIR)/path.c $(TRANSLATE) $(TRANSLATE) $(SRCDIR)/path.c >$@ $(OBJDIR)/path.o: $(OBJDIR)/path_.c $(OBJDIR)/path.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/path.o -c $(OBJDIR)/path_.c |
︙ | ︙ |
Changes to win/Makefile.msc.
︙ | ︙ | |||
454 455 456 457 458 459 460 461 462 463 464 465 466 467 | "$(OX)\markdown_.c" \ "$(OX)\markdown_html_.c" \ "$(OX)\md5_.c" \ "$(OX)\merge_.c" \ "$(OX)\merge3_.c" \ "$(OX)\moderate_.c" \ "$(OX)\name_.c" \ "$(OX)\path_.c" \ "$(OX)\piechart_.c" \ "$(OX)\pikchr_.c" \ "$(OX)\pikchrshow_.c" \ "$(OX)\pivot_.c" \ "$(OX)\popen_.c" \ "$(OX)\pqueue_.c" \ | > | 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 | "$(OX)\markdown_.c" \ "$(OX)\markdown_html_.c" \ "$(OX)\md5_.c" \ "$(OX)\merge_.c" \ "$(OX)\merge3_.c" \ "$(OX)\moderate_.c" \ "$(OX)\name_.c" \ "$(OX)\patch_.c" \ "$(OX)\path_.c" \ "$(OX)\piechart_.c" \ "$(OX)\pikchr_.c" \ "$(OX)\pikchrshow_.c" \ "$(OX)\pivot_.c" \ "$(OX)\popen_.c" \ "$(OX)\pqueue_.c" \ |
︙ | ︙ | |||
710 711 712 713 714 715 716 717 718 719 720 721 722 723 | "$(OX)\markdown$O" \ "$(OX)\markdown_html$O" \ "$(OX)\md5$O" \ "$(OX)\merge$O" \ "$(OX)\merge3$O" \ "$(OX)\moderate$O" \ "$(OX)\name$O" \ "$(OX)\path$O" \ "$(OX)\piechart$O" \ "$(OX)\pikchr$O" \ "$(OX)\pikchrshow$O" \ "$(OX)\pivot$O" \ "$(OX)\popen$O" \ "$(OX)\pqueue$O" \ | > | 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 | "$(OX)\markdown$O" \ "$(OX)\markdown_html$O" \ "$(OX)\md5$O" \ "$(OX)\merge$O" \ "$(OX)\merge3$O" \ "$(OX)\moderate$O" \ "$(OX)\name$O" \ "$(OX)\patch$O" \ "$(OX)\path$O" \ "$(OX)\piechart$O" \ "$(OX)\pikchr$O" \ "$(OX)\pikchrshow$O" \ "$(OX)\pivot$O" \ "$(OX)\popen$O" \ "$(OX)\pqueue$O" \ |
︙ | ︙ | |||
940 941 942 943 944 945 946 947 948 949 950 951 952 953 | echo "$(OX)\markdown.obj" >> $@ echo "$(OX)\markdown_html.obj" >> $@ echo "$(OX)\md5.obj" >> $@ echo "$(OX)\merge.obj" >> $@ echo "$(OX)\merge3.obj" >> $@ echo "$(OX)\moderate.obj" >> $@ echo "$(OX)\name.obj" >> $@ echo "$(OX)\path.obj" >> $@ echo "$(OX)\piechart.obj" >> $@ echo "$(OX)\pikchr.obj" >> $@ echo "$(OX)\pikchrshow.obj" >> $@ echo "$(OX)\pivot.obj" >> $@ echo "$(OX)\popen.obj" >> $@ echo "$(OX)\pqueue.obj" >> $@ | > | 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 | echo "$(OX)\markdown.obj" >> $@ echo "$(OX)\markdown_html.obj" >> $@ echo "$(OX)\md5.obj" >> $@ echo "$(OX)\merge.obj" >> $@ echo "$(OX)\merge3.obj" >> $@ echo "$(OX)\moderate.obj" >> $@ echo "$(OX)\name.obj" >> $@ echo "$(OX)\patch.obj" >> $@ echo "$(OX)\path.obj" >> $@ echo "$(OX)\piechart.obj" >> $@ echo "$(OX)\pikchr.obj" >> $@ echo "$(OX)\pikchrshow.obj" >> $@ echo "$(OX)\pivot.obj" >> $@ echo "$(OX)\popen.obj" >> $@ echo "$(OX)\pqueue.obj" >> $@ |
︙ | ︙ | |||
1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 | "$(OBJDIR)\translate$E" $** > $@ "$(OX)\name$O" : "$(OX)\name_.c" "$(OX)\name.h" $(TCC) /Fo$@ /Fd$(@D)\ -c "$(OX)\name_.c" "$(OX)\name_.c" : "$(SRCDIR)\name.c" "$(OBJDIR)\translate$E" $** > $@ "$(OX)\path$O" : "$(OX)\path_.c" "$(OX)\path.h" $(TCC) /Fo$@ /Fd$(@D)\ -c "$(OX)\path_.c" "$(OX)\path_.c" : "$(SRCDIR)\path.c" "$(OBJDIR)\translate$E" $** > $@ | > > > > > > | 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 | "$(OBJDIR)\translate$E" $** > $@ "$(OX)\name$O" : "$(OX)\name_.c" "$(OX)\name.h" $(TCC) /Fo$@ /Fd$(@D)\ -c "$(OX)\name_.c" "$(OX)\name_.c" : "$(SRCDIR)\name.c" "$(OBJDIR)\translate$E" $** > $@ "$(OX)\patch$O" : "$(OX)\patch_.c" "$(OX)\patch.h" $(TCC) /Fo$@ /Fd$(@D)\ -c "$(OX)\patch_.c" "$(OX)\patch_.c" : "$(SRCDIR)\patch.c" "$(OBJDIR)\translate$E" $** > $@ "$(OX)\path$O" : "$(OX)\path_.c" "$(OX)\path.h" $(TCC) /Fo$@ /Fd$(@D)\ -c "$(OX)\path_.c" "$(OX)\path_.c" : "$(SRCDIR)\path.c" "$(OBJDIR)\translate$E" $** > $@ |
︙ | ︙ | |||
2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 | "$(OX)\markdown_.c":"$(OX)\markdown.h" \ "$(OX)\markdown_html_.c":"$(OX)\markdown_html.h" \ "$(OX)\md5_.c":"$(OX)\md5.h" \ "$(OX)\merge_.c":"$(OX)\merge.h" \ "$(OX)\merge3_.c":"$(OX)\merge3.h" \ "$(OX)\moderate_.c":"$(OX)\moderate.h" \ "$(OX)\name_.c":"$(OX)\name.h" \ "$(OX)\path_.c":"$(OX)\path.h" \ "$(OX)\piechart_.c":"$(OX)\piechart.h" \ "$(OX)\pikchr_.c":"$(OX)\pikchr.h" \ "$(OX)\pikchrshow_.c":"$(OX)\pikchrshow.h" \ "$(OX)\pivot_.c":"$(OX)\pivot.h" \ "$(OX)\popen_.c":"$(OX)\popen.h" \ "$(OX)\pqueue_.c":"$(OX)\pqueue.h" \ | > | 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 | "$(OX)\markdown_.c":"$(OX)\markdown.h" \ "$(OX)\markdown_html_.c":"$(OX)\markdown_html.h" \ "$(OX)\md5_.c":"$(OX)\md5.h" \ "$(OX)\merge_.c":"$(OX)\merge.h" \ "$(OX)\merge3_.c":"$(OX)\merge3.h" \ "$(OX)\moderate_.c":"$(OX)\moderate.h" \ "$(OX)\name_.c":"$(OX)\name.h" \ "$(OX)\patch_.c":"$(OX)\patch.h" \ "$(OX)\path_.c":"$(OX)\path.h" \ "$(OX)\piechart_.c":"$(OX)\piechart.h" \ "$(OX)\pikchr_.c":"$(OX)\pikchr.h" \ "$(OX)\pikchrshow_.c":"$(OX)\pikchrshow.h" \ "$(OX)\pivot_.c":"$(OX)\pivot.h" \ "$(OX)\popen_.c":"$(OX)\popen.h" \ "$(OX)\pqueue_.c":"$(OX)\pqueue.h" \ |
︙ | ︙ |
Changes to www/aboutdownload.wiki.
︙ | ︙ | |||
9 10 11 12 13 14 15 16 17 18 19 20 21 22 | are all stored as unversioned content. The download.html page uses XMLHttpRequest() to retrieve the [/help?cmd=/juvlist|/juvlist] webpage for a list of all unversioned files. Javascript in the [/uv/download.js?mimetype=text/plain|download.js] file (which is sourced by "download.html") then figures out which unversioned files are build products and paints appropriate icons on the displayed download page. When a new version is generated, the developers use the [/help?cmd=uv|fossil uv edit] command to make minor changes to the "[/uv/download.js?mimetype=text/plain|download.js]" file so that it knows about the new version number. Then the developers run the [/help?cmd=uv|fossil uv add] command for each | > > > > | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | are all stored as unversioned content. The download.html page uses XMLHttpRequest() to retrieve the [/help?cmd=/juvlist|/juvlist] webpage for a list of all unversioned files. Javascript in the [/uv/download.js?mimetype=text/plain|download.js] file (which is sourced by "download.html") then figures out which unversioned files are build products and paints appropriate icons on the displayed download page. Except, the "Source Tarball" download products are not stored as unversioned files. They are computed on-demand by the [/help?cmd=/tarball|/tarball web page]. When a new version is generated, the developers use the [/help?cmd=uv|fossil uv edit] command to make minor changes to the "[/uv/download.js?mimetype=text/plain|download.js]" file so that it knows about the new version number. Then the developers run the [/help?cmd=uv|fossil uv add] command for each |
︙ | ︙ |
Changes to www/build.wiki.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <title>Compiling and Installing Fossil</title> <h2>0.0 Using A Pre-compiled Binary</h2> <p>[/uv/download.html|Pre-compiled binaries] are available for recent releases. Just download the appropriate executable for your platform and put it on your $PATH. To uninstall, simply delete the executable. To upgrade from an older release, just overwrite the older binary with the newer one.</p> <h2>0.1 Executive Summary</h2> <p>Building and installing is very simple. Three steps:</p> <ol> <li> Download and unpack a source tarball or ZIP. | > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <title>Compiling and Installing Fossil</title> <h2>0.0 Using A Pre-compiled Binary</h2> <p>[/uv/download.html|Pre-compiled binaries] are available for recent releases. Just download the appropriate executable for your platform and put it on your $PATH. To uninstall, simply delete the executable. To upgrade from an older release, just overwrite the older binary with the newer one.</p> <p>For details about how those binaries are built, see [/wiki?name=Release+Build+How-To | the Release Build How-To wiki page].</p> <h2>0.1 Executive Summary</h2> <p>Building and installing is very simple. Three steps:</p> <ol> <li> Download and unpack a source tarball or ZIP. |
︙ | ︙ | |||
129 130 131 132 133 134 135 | all Unix and Unix-like systems. Simply type "<b>make</b>". <li><p><i>Unix without running "configure"</i> → if you prefer to avoid running configure, you can also use: <b>make -f Makefile.classic</b>. You may want to make minor edits to Makefile.classic to configure the build for your system. | | > | | > > > > > > > > > > > | | > > > | | < < < < | 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 | all Unix and Unix-like systems. Simply type "<b>make</b>". <li><p><i>Unix without running "configure"</i> → if you prefer to avoid running configure, you can also use: <b>make -f Makefile.classic</b>. You may want to make minor edits to Makefile.classic to configure the build for your system. <li><p><i>MinGW / MinGW-w64</i> → The best-supported path is to build via the MinGW specific Makefile under a POSIX build of GNU make: "<b>make -f win/Makefile.mingw</b>". There is limited support for building under MinGW's native Windows port of GNU Make instead by defining the <tt>USE_WINDOWS=1</tt> variable, but it's better to build under MSYS, Cygwin, or WSL on Windows since this mode doesn't take care of cases such as the "openssl" target, which depends on <tt>sed</tt>. We've gone as far down this path as is practical short of breaking cross-compilation under Linux, macOS, and so forth, as we'd have to do to make everything work under <tt>cmd.exe</tt>. Unless you're building under MSYS where commands like "<tt>gcc</tt>" give MinGW's GCC and not some other version, you will need to make minor edits to win/Makefile.mingw to configure the cross-compilation environment. It should suffice to switch to one of the predefined <tt>PREFIX</tt> values, causing the build to be done using "<tt>x86_64-w64-mingw32-gcc</tt>" for example, yielding a 64-bit native Windows binary. To enable the native [./th1.md#tclEval | Tcl integration feature], use a command line like the following (all on one line): <b>make -f win/Makefile.mingw FOSSIL_ENABLE_TCL=1 FOSSIL_ENABLE_TCL_STUBS=1 FOSSIL_ENABLE_TCL_PRIVATE_STUBS=1</b> Alternatively, running <b>./configure</b> under MSYS should give a suitable top-level Makefile. However, options passed to configure that are not applicable on Windows may cause the configuration or compilation to fail (e.g. fusefs, internal-sqlite, etc). <li><p><i>MSVC</i> → Use the MSVC makefile. Run all of the following from a "x64 Native Tools Command Prompt". First change to the "win/" subdirectory ("<b>cd win</b>") then run "<b>nmake /f Makefile.msc</b>".<br><br>Alternatively, the batch |
︙ | ︙ |
Changes to www/caps/index.md.
︙ | ︙ | |||
300 301 302 303 304 305 306 | not just those done over `http[s]://` URLs: * For `ssh://` URLs, Fossil pipes the HTTP conversation through a local SSH client to a remote instance of Fossil running the [`test-http`](/help?name=test-http) command to receive the tunneled HTTP connection. The reason Fossil’s user capability system is bypassed in this case is that [`test-http` gives full capabilities | | < < < < < | | 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 | not just those done over `http[s]://` URLs: * For `ssh://` URLs, Fossil pipes the HTTP conversation through a local SSH client to a remote instance of Fossil running the [`test-http`](/help?name=test-http) command to receive the tunneled HTTP connection. The reason Fossil’s user capability system is bypassed in this case is that [`test-http` gives full capabilities to its users][sxycap]. * For `file://` URLs — as opposed to plain local file paths — the “sending” Fossil instance writes its side of the HTTP conversation out to a temporary file in the same directory as the local repo clone and then calls itself on the “receiving” repository to read that same HTTP transcript file back in to apply those changes to that repository. Presumably Fossil does this instead of using a pipe to ease portability to Windows. Checks for capabilities like [**Read**][o] and [**Write**][i] within the HTTP conversation between two Fossil instances only have a useful effect when done over an `http[s]://` URL. [sxycap]: /file?ci=ec5efceb8aac6cb4&name=src/main.c&ln=2748-2752 ## <a name="pubpg"></a>Public Pages In Admin → Access, there is an option for giving a list of [globs][glob] to name URLs which get treated as if the visitor had [the default cap set](#defcap). For example, you could take the [**Read**][o] capability |
︙ | ︙ |
Changes to www/changes.wiki.
1 2 3 | <title>Change Log</title> <a name='v2_16'></a> | > > > > > > > > > > > > > > > > > > > > > > > > > > | | > > > > | > > > > > > > > > > | | | > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | <title>Change Log</title> <a name='v2_17'></a> <h2>Changes for version 2.17 (pending)</h2> * The --branchcolor option on [/help?cmd=commit|fossil commit] and [/help?cmd=amend|fossil amend] can now take the value "auto" to force Fossil to use its built-in automatic color choosing algorithm. * Fossil now [./concepts.wiki#workflow|autosyncs] prior to running [/help?cmd=open|fossil open]. * Add the [/help?cmd=ticket-default-report|ticket-default-report setting], which if set to the title of a ticket report causes that ticket report to be displayed below the search box in the /ticket page. * The "nc" query parameter to the [/help?cmd=/timeline|/timeline] page causes all graph coloring to be omitted. * Improvements and bug fixes to the new "fossil ui REMOTE" feature so that it works better on a wider variety of platforms. * In [/help?cmd=/wikiedit|/wikiedit], show the list of attachments for the current page and list URLs suitable for pasting them into the page. * Add the --no-http-compression option to [/help?cmd=sync|fossil sync] and similar. * Print total payload bytes on a [/help?cmd=sync|fossil sync] when using the --verbose option. * Add the <tt>close</tt>, <tt>reopen</tt>, <tt>hide</tt>, and </tt>unhide</tt> subcommands to [/help?cmd=branch|the branch command]. * The [/mdrules|Markdown formatter] now interprets the content of block HTML markup (such as <table>) in most cases. Only content of <pre> and <script> is passed through verbatim. <a name='v2_16'></a> <h2>Changes for Version 2.16 (2021-07-02)</h2> * <b>Security:</b> Fix the client-side TLS so that it verifies that the server hostname matches its certificate. * The default "ssh" command on Windows is changed to "ssh" instead of the legacy "plink", as ssh is now generally available on Windows systems. Installations that still need to use the legacy "plink" can make that happen by running: '<tt>fossil set ssh-command "plink -ssh" --global</tt>'. * Added the [./patchcmd.md|fossil patch] command. * The [/help?cmd=ui|fossil ui] command is enhanced in multiple ways:<ol> <li> The REPOSITORY argument can be the name of a check-out directory. <li> If the REPOSITORY argument is prefixed by "HOST:" or "USER@HOST:" then the ui is run on the remote machine and tunnelled back to the local machine using ssh. (The latest version of fossil must be installed on both the local and the remote for this to work correctly.) <li> The new --nobrowser and --fossilcmd options is provided. </ol> * The [/brlist|/brlist web page] allows the user to select multiple branches to be displayed together in a single timeline. * The [./forum.wiki|Forum] provides a hyperlink on the author of each post that goes to a timeline of recent posts by that same author. * Added the "[/help?cmd=bisect|fossil bisect run]" command for improved automation of bisects. * The [/help?cmd=merge|fossil merge] command now does a better job merging branches where files have been renamed between the current branch and the branch being merged. * The [/help?cmd=open|fossil open] command allows the repository file to be inside the working directory without requiring the --force flag. * The [/help?cmd=/wikiedit|/wikiedit] and [/help?cmd=/wikinew|/wikinew] pages now default to markdown format. * The [/help?cmd=/login|/login] page now links to a user's forum post timeline if the repository has forum posts. * Tags may now be propagated for forum posts, wiki pages, and technotes. The [/help?cmd=tag|tag command] can now manipulate and list such tags. * [./caps/login-groups.md|Login-Groups] are now shown on the repository list of the "[/help?cmd=all|fossil all ui]" command. * Administrators can configure [./alerts.md|email alerts] to expire a specific number of days (ex: 365) after the last user contact with the Fossil server. This prevents alert emails being sent to abandoned email accounts forever. * SQL that defines [/tktsetup_tab|database objects for tickets] now [/timeline?c=c717f1ef9a1a4c91|can DROP] a VIEW or an INDEX provided that its name starts with '<code>ticket</code>' or '<code>fx_</code>'. * Update the built-in SQLite to version 3.36.0. * Numerous other minor enhancements. <a name='v2_15'></a> <h2>Changes for Version 2.15 (2021-03-26) and Patch 2.15.1 on (2021-04-07) and 2.15.2 on (2021-06-15)</h2> * <b>Patch 2.15.2:</b> Fix the client-side TLS so that it verifies that the server hostname matches its certificate. <b>Upgrading to the patch is recommended.</b> |
︙ | ︙ | |||
280 281 282 283 284 285 286 | * Added virtual tables "<tt>helptext</tt>" and "<tt>builtin</tt>" to the "[/help?cmd=sql|fossil sql]" command, providing access to the dispatch table including all help text, and the builtin data files, respectively. * [./delta_format.wiki|Delta compression] is now applied to forum edits. * The [/help?cmd=/wikiedit|wiki editor] has been modernized and is now Ajax-based. The WYSIWYG editing option for Fossil-format wiki | | > > > | 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 | * Added virtual tables "<tt>helptext</tt>" and "<tt>builtin</tt>" to the "[/help?cmd=sql|fossil sql]" command, providing access to the dispatch table including all help text, and the builtin data files, respectively. * [./delta_format.wiki|Delta compression] is now applied to forum edits. * The [/help?cmd=/wikiedit|wiki editor] has been modernized and is now Ajax-based. The WYSIWYG editing option for Fossil-format wiki pages was removed. (Please let us know, via the site's Forum menu, if that removal unduly impacts you.) This also changes the semantics of the wiki "Sandbox": that pseudo-page may be freely edited but no longer saved via the UI (the [/help?cmd=wiki|wiki CLI command] can, though). * The [/help?cmd=allow-symlinks|allow-symlinks setting] no longer syncs. It must be activated individually on any clones which require symlinks. * Countless documentation enhancements. <a name='v2_11'></a> <h2>Changes for Version 2.11 (2020-05-25)</h2> * (2.11.2): Backport security fixes from 2.12.1 * (2.11.1): Backport security fix for the "fossil git export" command. |
︙ | ︙ |
Changes to www/customskin.md.
︙ | ︙ | |||
236 237 238 239 240 241 242 | <p>Both the footer.txt and header.txt file are [processed using TH1](#headfoot) prior to being output as part of the overall web page.</dd> <dt><b>js.txt</b></dt><dd> <p>The js.txt file is optional. It is intended to be javascript. | | | 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 | <p>Both the footer.txt and header.txt file are [processed using TH1](#headfoot) prior to being output as part of the overall web page.</dd> <dt><b>js.txt</b></dt><dd> <p>The js.txt file is optional. It is intended to be javascript. The complete text of this javascript might be inserted into the Content Footer, after being processed using TH1, using code like the following in the "footer.txt" file: <blockquote><pre> <script nonce="$nonce"> <th1>styleScript</th1> </script> |
︙ | ︙ | |||
352 353 354 355 356 357 358 | ## <a name="menu"></a>Customizing the ≡ Hamburger Menu The menu bar of the default skin has an entry to open a drop-down menu with additional navigation links, represented by the ≡ button (hence the name "hamburger menu"). The Javascript logic to open and close the hamburger menu when the button is clicked is usually handled by a script named | | | 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 | ## <a name="menu"></a>Customizing the ≡ Hamburger Menu The menu bar of the default skin has an entry to open a drop-down menu with additional navigation links, represented by the ≡ button (hence the name "hamburger menu"). The Javascript logic to open and close the hamburger menu when the button is clicked is usually handled by a script named "hbmenu.js" that is one of the [built-in resource files](/test-builtin-files) that are part of Fossil. The ≡ button for the hamburger menu is added to the menu bar by the following TH1 commands in the `header.txt` file, right before the menu bar links: html "<a id='hbbtn' href='$home/sitemap'>☰</a>" builtin_request_js hbmenu.js |
︙ | ︙ |
Changes to www/defcsp.md.
1 2 3 4 5 | # The Default Content Security Policy (CSP) When Fossil’s web interface generates an HTML page, it normally includes a [Content Security Policy][csp] (CSP) in the `<head>`. The CSP specifies allowed sources for external resources such as images, | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # The Default Content Security Policy (CSP) When Fossil’s web interface generates an HTML page, it normally includes a [Content Security Policy][csp] (CSP) in the `<head>`. The CSP specifies allowed sources for external resources such as images, CSS, javascript, and so forth. The purpose of CSP is to provide an extra layer of protection against [cross-site scripting][xss] (XSS) and code injection attacks. Compatible web browsers will not use external resources unless they are specifically allowed by the CSP, which dramatically reduces the attack surface of the application. Fossil does not rely on CSP for security. A Fossil server should be secure from attack even without CSP. Fossil includes built-in server-side content filtering logic. For example, Fossil purposely breaks `<script>` tags when it finds them in Markdown and Fossil Wiki documents. And the Fossil build process scans the source code for potential injection vulnerabilities and refuses to compile if any problems are found. However, CSP provides an additional layer of defense against undetected bugs that might lead to a vulnerability. |
︙ | ︙ |
Changes to www/embeddeddoc.wiki.
︙ | ︙ | |||
183 184 185 186 187 188 189 | Fossil will substitute the value of [./th1.md | TH1 expressions] within <tt>{</tt> curly braces <tt>}</tt> into the output HTML if you have configured it with the <tt>--with-th1-docs</tt> option, which is disabled by default. Since TH1 is a full scripting language, this feature essential grants | | | | | | 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 | Fossil will substitute the value of [./th1.md | TH1 expressions] within <tt>{</tt> curly braces <tt>}</tt> into the output HTML if you have configured it with the <tt>--with-th1-docs</tt> option, which is disabled by default. Since TH1 is a full scripting language, this feature essential grants the ability to execute code on the server to anyone with check-in privilege for the project. This is a security risk that needs to be carefully managed. The feature is off by default. Administrators should understand and carefully assess the risks before enabling the use of TH1 within embedded documentation. <h1>3.0 Examples</h1> This file that you are currently reading is an example of embedded documentation. The name of this file in the fossil source tree is "<b>www/embeddeddoc.wiki</b>". You are perhaps looking at this file using the URL: [http://fossil-scm.org/home/doc/trunk/www/embeddeddoc.wiki]. The first part of this path, the "[http://fossil-scm.org/home]", is the base URL. You might have originally typed: [http://fossil-scm.org/]. The web server at the fossil-scm.org site automatically redirects such links by appending "home". The "home" file on fossil-scm.org is really a [./server/any/cgi.md|CGI script] which runs the fossil web service in CGI mode. The "home" CGI script looks like this: <blockquote><pre> #!/usr/bin/fossil repository: /fossil/fossil.fossil </pre></blockquote> This is one of the many ways to set up a |
︙ | ︙ |
Changes to www/index.wiki.
︙ | ︙ | |||
22 23 24 25 26 27 28 | <p>Fossil is a simple, high-reliability, distributed software configuration management system with these advanced features: 1. <b>Project Management</b> - In addition to doing [./concepts.wiki | distributed version control] like Git and Mercurial, Fossil also supports [./bugtheory.wiki | bug tracking], | | > | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | <p>Fossil is a simple, high-reliability, distributed software configuration management system with these advanced features: 1. <b>Project Management</b> - In addition to doing [./concepts.wiki | distributed version control] like Git and Mercurial, Fossil also supports [./bugtheory.wiki | bug tracking], [./wikitheory.wiki | wiki], [./forum.wiki | forum], [./alerts.md|email alerts], [./chat.md | chat], and [./event.wiki | technotes]. 2. <b>Built-in Web Interface</b> - Fossil has a built-in, [/skins | themeable], [./serverext.wiki | extensible], and intuitive [./webui.wiki | web interface] with a rich variety of information pages ([./webpage-ex.md|examples]) promoting situational awareness. |
︙ | ︙ | |||
80 81 82 83 84 85 86 | atomic even if interrupted by a power loss or system crash. Automatic [./selfcheck.wiki | self-checks] verify that all aspects of the repository are consistent prior to each commit. 8. <b>Free and Open-Source</b> - [../COPYRIGHT-BSD2.txt|2-clause BSD license]. <hr> | | | | | | | | 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | atomic even if interrupted by a power loss or system crash. Automatic [./selfcheck.wiki | self-checks] verify that all aspects of the repository are consistent prior to each commit. 8. <b>Free and Open-Source</b> - [../COPYRIGHT-BSD2.txt|2-clause BSD license]. <hr> <h3>Latest Release: 2.16 ([/timeline?c=version-2.16|2021-07-02])</h3> * [/uv/download.html|Download] * [./changes.wiki#v2_16|Change Summary] * [/timeline?p=version-2.16&bt=version-2.15&y=ci|Check-ins in version 2.16] * [/timeline?df=version-2.16&y=ci|Check-ins derived from the 2.16 release] * [/timeline?t=release|Timeline of all past releases] <hr> <h3>Quick Start</h3> 1. [/uv/download.html|Download] or install using a package manager or [./build.wiki|compile from sources]. 2. <tt>fossil init</tt> <i>REPOSITORY-DIR/new-repository</i> 3. <tt>fossil open</tt> <i>REPOSITORY-DIR/new-repository</i> 4. <tt>fossil add</tt> <i>files-or-directories</i> 5. <tt>fossil commit -m</tt> "<i>commit message</i>" 6. <tt>fossil ui</tt> 7. Repeat steps 4, 5, and 6, in any order, as necessary. See the [./quickstart.wiki|Quick Start Guide] for more detail. |
Changes to www/mkindex.tcl.
︙ | ︙ | |||
81 82 83 84 85 86 87 88 89 90 91 92 93 94 | javascript.md {Use of JavaScript in Fossil} loadmgmt.md {Managing Server Load} makefile.wiki {The Fossil Build Process} mirrorlimitations.md {Limitations On Git Mirrors} mirrortogithub.md {How To Mirror A Fossil Repository On GitHub} /md_rules {Markdown Formatting Rules} newrepo.wiki {How To Create A New Fossil Repository} password.wiki {Password Management And Authentication} pikchr.md {The Pikchr Diagram Language} pop.wiki {Principles Of Operation} private.wiki {Creating, Syncing, and Deleting Private Branches} qandc.wiki {Questions And Criticisms} quickstart.wiki {Fossil Quick Start Guide} quotes.wiki | > | 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | javascript.md {Use of JavaScript in Fossil} loadmgmt.md {Managing Server Load} makefile.wiki {The Fossil Build Process} mirrorlimitations.md {Limitations On Git Mirrors} mirrortogithub.md {How To Mirror A Fossil Repository On GitHub} /md_rules {Markdown Formatting Rules} newrepo.wiki {How To Create A New Fossil Repository} patchcmd.md {The "fossil patch" Command} password.wiki {Password Management And Authentication} pikchr.md {The Pikchr Diagram Language} pop.wiki {Principles Of Operation} private.wiki {Creating, Syncing, and Deleting Private Branches} qandc.wiki {Questions And Criticisms} quickstart.wiki {Fossil Quick Start Guide} quotes.wiki |
︙ | ︙ |
Added www/patchcmd.md.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | # The "fossil patch" command The "[fossil patch](/help?cmd=patch)" command is designed to transfer uncommitted changes from one check-out to another, including transfering those changes to other machines. For example, if you are working on a Windows desktop and you want to test your changes on a Linux server before you commit, you can use the "fossil patch push" command to make a copy of all your changes on the remote Linux server: > fossil patch push linuxserver:/path/to/checkout In the previous "linuxserver" is the name of the remote machine and "/path/to/checkout" is an existing checkout directory for the same project on the remote machine. The "fossil patch push" command works by first creating a patch file, then transfering that patch file to the remote machine using "ssh", then applying the patch. If you do not have ssh available, you can break these steps apart as follows: 1. On the local machine: `fossil patch create mypatch.patch` 2. Move "mypatch.patch" to the remote machine. 3. On the remote machine: `fossil patch apply mypatch.patch` Step 2 can be accomplished by a variety of means including posting the mypatch.patch file on [chat](./chat.md) or sending it as an email attachment. ## Setup The "fossil patch push" and "fossil patch pull" commands will only work if you have "ssh" available on the local machine and if "fossil" is on the default PATH on the remote machine. To check if Fossil is installed correctly on the remote, try a command like this: > `ssh -T remote "fossil version"` If the command above shows a recent version of Fossil, then you should be set to go. If you get "fossil not found", or if the version shown is too old, put a newer fossil executable on the default PATH. The default PATH can be shown using: > `ssh -T remote 'echo $PATH'` ### Custom PATH Caveat On Unix-like systems, the init script for the user's login shell (e.g. `~/.profile` or `~/.bash_profile`) may be configured to *not do anything* when running under a non-interactive shell. Thus a fossil binary installed to a custom directory might not be found. To allow the patch command to use a fossil binary installed in a directory which is normally added to the PATH via the interactive shell's init script, it may be useful to disable that check. For example, Ubuntu-derived systems sometimes start their default `.bashrc` with something like: ``` # If not running interactively, don't do anything: [ -z "$PS1" ] && return # Or: case $- in *i*) ;; *) return;; esac ``` Commenting out that check will allow the patch command to run, for example, `~/bin/fossil` if `~/bin` is added to the PATH via the init script. To disable that check *only* when the shell is *not* running over an SSH connection, something like the following should suffice: ``` if [ -z "$SSH_CONNECTION" ]; then # ... the is-interactive check goes here ... fi ``` ## Implementation Details The "fossil patch create" command records all of the local, uncommitted changes in an SQLite database file. If the argument to "fossil patch create" is a filename, then the patch-file database is written into that file. If the argument is "-" then the database is written on standard output. The "fossil patch apply" command reads the database that is the patch file and applies it to the local check-out. If a filename is given as an argument, then the database is read from that file. If the argument is "-" then the database is read from standard input. Hence the command: > `fossil patch push remote:projectA` Is equivalent to: > `fossil patch create - | ssh -T remote 'cd projectA;fossil patch apply -'` Likewise, a command like this: > `fossil patch pull remote:projB` Could be entered like this: > `ssh -T remote 'cd projB;fossil patch create -' | fossil patch apply -` The "fossil patch view" command just opens the database file and prints a summary of its contents on standard output. |
Changes to www/permutedindex.html.
︙ | ︙ | |||
104 105 106 107 108 109 110 111 112 113 114 115 116 117 | <li><a href="reviews.wiki">Reviews</a></li> <li><a href="chroot.md">Server Chroot Jail</a></li> <li><a href="shunning.wiki">Shunning: Deleting Content From Fossil</a></li> <li><a href="../../../sitemap">Site Map</a></li> <li><a href="style.wiki">Source Code Style Guidelines</a></li> <li><a href="tech_overview.wiki">SQLite Databases Used By Fossil</a></li> <li><a href="backoffice.md">The "Backoffice" mechanism of Fossil</a></li> <li><a href="blame.wiki">The Annotate/Blame Algorithm Of Fossil</a></li> <li><a href="defcsp.md">The Default Content Security Policy</a></li> <li><a href="fileedit-page.md">The fileedit Page</a></li> <li><a href="makefile.wiki">The Fossil Build Process</a></li> <li><a href="sync.wiki">The Fossil Sync Protocol</a></li> <li><a href="tickets.wiki">The Fossil Ticket System</a></li> <li><a href="webui.wiki">The Fossil Web Interface</a></li> | > | 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 | <li><a href="reviews.wiki">Reviews</a></li> <li><a href="chroot.md">Server Chroot Jail</a></li> <li><a href="shunning.wiki">Shunning: Deleting Content From Fossil</a></li> <li><a href="../../../sitemap">Site Map</a></li> <li><a href="style.wiki">Source Code Style Guidelines</a></li> <li><a href="tech_overview.wiki">SQLite Databases Used By Fossil</a></li> <li><a href="backoffice.md">The "Backoffice" mechanism of Fossil</a></li> <li><a href="patchcmd.md">The "fossil patch" Command</a></li> <li><a href="blame.wiki">The Annotate/Blame Algorithm Of Fossil</a></li> <li><a href="defcsp.md">The Default Content Security Policy</a></li> <li><a href="fileedit-page.md">The fileedit Page</a></li> <li><a href="makefile.wiki">The Fossil Build Process</a></li> <li><a href="sync.wiki">The Fossil Sync Protocol</a></li> <li><a href="tickets.wiki">The Fossil Ticket System</a></li> <li><a href="webui.wiki">The Fossil Web Interface</a></li> |
︙ | ︙ |
Changes to www/selfhost.wiki.
︙ | ︙ | |||
58 59 60 61 62 63 64 | less expensive hosting option compared to shared hosting accounts. So on 2017-07-25, server (3) was moved onto a $5/month "droplet" [https://en.wikipedia.org/wiki/Virtual_private_server|VPS] from [https://www.digitalocean.com|Digital Ocean] located in San Francisco. Server (3) is synchronized with the canonical server (1) by running | | | | 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | less expensive hosting option compared to shared hosting accounts. So on 2017-07-25, server (3) was moved onto a $5/month "droplet" [https://en.wikipedia.org/wiki/Virtual_private_server|VPS] from [https://www.digitalocean.com|Digital Ocean] located in San Francisco. Server (3) is synchronized with the canonical server (1) by running a command similar to the following via cron: <blockquote><pre> /usr/local/bin/fossil all sync -u </pre></blockquote> Server (2) is a <a href="http://www.linode.com/">Linode 4096</a> located in Newark, NJ and set up just like the canonical server (1) with the addition of a cron job for synchronization. The same cron job also runs the [/help?cmd=git|fossil git export] command after each sync in order to |
︙ | ︙ |
Changes to www/server/any/cgi.md.
︙ | ︙ | |||
33 34 35 36 37 38 39 | * *All* directories leading to the CGI script must be readable by the web server. * The repository file *and* the directory containing it must be writable by the same account which executes the Fossil binary. (This might differ from the user the web server normally runs under.) The directory holding the repository file(s) needs to be | | > > > | 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | * *All* directories leading to the CGI script must be readable by the web server. * The repository file *and* the directory containing it must be writable by the same account which executes the Fossil binary. (This might differ from the user the web server normally runs under.) The directory holding the repository file(s) needs to be writable so that SQLite can write its journal files. When using another access control system, such as AppArmor or SELinux, it may be necessary to explicitly permit that account to read and write the necessary files. * Fossil must be able to create temporary files in a [directory that varies by host OS](../../env-opts.md#temp). When the CGI process is operating [within a chroot](../../chroot.md), ensure that this directory exists and is readable/writeable by the user who executes the Fossil binary. |
︙ | ︙ |
Changes to www/server/debian/service.md.
︙ | ︙ | |||
27 28 29 30 31 32 33 | To do this, write the following in `~/.local/share/systemd/user/fossil.service`: ```dosini [Unit] Description=Fossil user server | | < | 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | To do this, write the following in `~/.local/share/systemd/user/fossil.service`: ```dosini [Unit] Description=Fossil user server After=network-online.target [Service] WorkingDirectory=/home/fossil/museum ExecStart=/home/fossil/bin/fossil server --port 9000 repo.fossil Restart=always RestartSec=3 [Install] WantedBy=multi-user.target ``` Unlike with `inetd` and `xinetd`, we don’t need to tell `systemd` which user and group to run this service as, because we’ve installed it under the account we’re logged into, which `systemd` will use as the service’s owner. |
︙ | ︙ | |||
62 63 64 65 66 67 68 | Because we’ve set this up as a user service, the commands you give to manipulate the service vary somewhat from the sort you’re more likely to find online: $ systemctl --user daemon-reload $ systemctl --user enable fossil $ systemctl --user start fossil | | | 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | Because we’ve set this up as a user service, the commands you give to manipulate the service vary somewhat from the sort you’re more likely to find online: $ systemctl --user daemon-reload $ systemctl --user enable fossil $ systemctl --user start fossil $ systemctl --user status fossil -l $ systemctl --user stop fossil That is, we don’t need to talk to `systemd` with `sudo` privileges, but we do need to tell it to look at the user configuration rather than the system-level configuration. This scheme isolates the permissions needed by the Fossil server, which |
︙ | ︙ | |||
87 88 89 90 91 92 93 | You can paste the command just like that into your terminal, since `$USER` will expand to your login name. ### System Service Alternative | > > | > > > | | | > > | 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | You can paste the command just like that into your terminal, since `$USER` will expand to your login name. ### System Service Alternative There are a couple of common reasons that you’d have cause to install Fossil as a system-level service rather than the prior user-level one: * You need Fossil to listen on a TCP port under 1024, such as because you’re running it on a private LAN, and the server has no other HTTP service, so you want Fossil to handle the web traffic directly. * You’re proxying Fossil with a system-level service such as [nginx](./nginx.md), so you need to put Fossil into the system-level service dependency chain to make sure things start up and shut down in the proper order. There are just a small set of changes required: 1. Install the unit file to one of the persistent system-level unit file directories. Typically, these are: /etc/systemd/system |
︙ | ︙ | |||
144 145 146 147 148 149 150 | Next, create the service definition file in that same directory as `fossil@.service`: ```dosini [Unit] Description=Fossil socket server | | < | 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 | Next, create the service definition file in that same directory as `fossil@.service`: ```dosini [Unit] Description=Fossil socket server After=network-online.target [Service] WorkingDirectory=/home/fossil/museum ExecStart=/home/fossil/bin/fossil http repo.fossil StandardInput=socket [Install] WantedBy=multi-user.target ``` We’ll explain the “`@`” in the file name below. Notice that we haven’t told `systemd` which user and group to run Fossil under. Since this is a system-level service definition, that means it |
︙ | ︙ |
Changes to www/serverext.wiki.
1 2 3 4 5 6 7 8 | <title>CGI Server Extensions</title> <h2>1.0 Introduction</h2> If you have a [./server/|Fossil server] for your project, you can add [./aboutcgi.wiki|CGI] extensions to that server. These extensions work like any other CGI program, except that they also have access to the Fossil | | | | > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | <title>CGI Server Extensions</title> <h2>1.0 Introduction</h2> If you have a [./server/|Fossil server] for your project, you can add [./aboutcgi.wiki|CGI] extensions to that server. These extensions work like any other CGI program, except that they also have access to the Fossil login information and can (optionally) leverage the "[./customskin.md|skins]" of Fossil so that they appear to be more tightly integrated into the project. An example of where this is useful is the [https://sqlite.org/src/ext/checklist|checklist application] on the [https://sqlite.org/|SQLite] project. The checklist helps the SQLite developers track which release tests have passed, or failed, or are still to be done. The checklist program began as a stand-alone CGI which kept its own private user database and implemented its own permissions and login system and provided its own CSS. By converting checklist into a Fossil extension, the same login that works for the [https://sqlite.org/src|main SQLite source repository] also works for the checklist. Permission to change elements of the checklist is tied on permission to check-in to the main source repository. And the standard Fossil header menu and footer appear on each page of the checklist. <h2>2.0 How It Works</h2> CGI Extensions are disabled by default. An administrator activates the CGI extension mechanism by specifying an "Extension Root Directory" or "extroot" as part of the [./server/index.html|server setup]. If the Fossil server is itself run as [./server/any/cgi.md|CGI], then add a line to the [./cgi.wiki#extroot|CGI script file] that says: <blockquote><pre> extroot: <i>DIRECTORY</i> </pre></blockquote> |
︙ | ︙ |
Changes to www/ssl.wiki.
︙ | ︙ | |||
175 176 177 178 179 180 181 | The same sort of thing happens with the Windows build of OpenSSL, but for a different core reason: Windows does ship with a stock CA certificate set, but it's not in a format that OpenSSL understands how to use. Rather than try to find a way to convert the data format, you may find it acceptable to use the same Mozilla NSS cert set. I do not know of a way to easily get this from Mozilla themselves, but I did find | | | 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 | The same sort of thing happens with the Windows build of OpenSSL, but for a different core reason: Windows does ship with a stock CA certificate set, but it's not in a format that OpenSSL understands how to use. Rather than try to find a way to convert the data format, you may find it acceptable to use the same Mozilla NSS cert set. I do not know of a way to easily get this from Mozilla themselves, but I did find a [https://curl.se/docs/caextract.html | third party source] for the <tt>cacert.pem</tt> file. I suggest placing the file into your Windows user home directory so that you can then point Fossil at it like so: <pre> fossil set --global ssl-ca-location %userprofile%\cacert.pem </pre> |
︙ | ︙ |
Changes to www/th1.md.
︙ | ︙ | |||
38 39 40 41 42 43 44 | Each command is terminated by the first *unescaped* newline or ";" character. The text of the command (excluding the newline or semicolon terminator) is broken into space-separated tokens. The first token is the command name and subsequent tokens are the arguments. In this sense, TH1 syntax is similar to the familiar command-line shell syntax. A token is any sequence of characters other than whitespace and semicolons. | | | | > | 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | Each command is terminated by the first *unescaped* newline or ";" character. The text of the command (excluding the newline or semicolon terminator) is broken into space-separated tokens. The first token is the command name and subsequent tokens are the arguments. In this sense, TH1 syntax is similar to the familiar command-line shell syntax. A token is any sequence of characters other than whitespace and semicolons. Text inside double-quotes is a single token even if it includes whitespace and semicolons. Text within {...} pairs is also a single token, which is useful because curly braces are easier to “pair” and nest properly than double-quotes. The nested {...} form of tokens is important because it allows TH1 commands to have an appearance similar to C/C++. It is important to remember, though, that a TH1 script is really just a list of text commands, not a context-free language with a grammar like C/C++. This can be confusing to long-time C/C++ programmers because TH1 does look a lot like C/C++, but the semantics of TH1 are closer to FORTH or Lisp than they are to C. |
︙ | ︙ | |||
62 63 64 65 66 67 68 | } The example above is a single command. The first token, and the name of the command, is `if`. The second token is `$current eq "dev"` - an expression. (The outer {...} are removed from each token by the command parser.) The third token is the `puts "hello"`, with its whitespace and newlines. The fourth token | | | 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | } The example above is a single command. The first token, and the name of the command, is `if`. The second token is `$current eq "dev"` - an expression. (The outer {...} are removed from each token by the command parser.) The third token is the `puts "hello"`, with its whitespace and newlines. The fourth token is `else` and the fifth and last token is `puts "world"`. The `if` command evaluates its first argument (the second token) as an expression, and if that expression is true, evaluates its second argument (the third token) as a TH1 script. If the expression is false and the third argument is `else`, then the fourth argument is evaluated as a TH1 expression. |
︙ | ︙ | |||
108 109 110 111 112 113 114 | terminal width while telling the interpreter to consider those three lines as a single command. Summary of Core TH1 Commands ---------------------------- | | | 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | terminal width while telling the interpreter to consider those three lines as a single command. Summary of Core TH1 Commands ---------------------------- The original Tcl language (after which TH1 is modeled) has a very rich repertoire of commands. TH1, as it is designed to be minimalist and embedded has a greatly reduced command set. The following bullets summarize the commands available in TH1: * array exists VARNAME * array names VARNAME * break |
︙ | ︙ | |||
282 283 284 285 286 287 288 | ----------------------------------------------------- Added in Fossil 2.15. * capexpr CAPABILITY-EXPR The capability expression is a list. Each term of the list is a | > | | 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 | ----------------------------------------------------- Added in Fossil 2.15. * capexpr CAPABILITY-EXPR The capability expression is a list. Each term of the list is a cluster of [capability letters](./caps/ref.html). The overall expression is true if any one term is true. A single term is true if all letters within that term are true. Or, if the term begins with "!", then the term is true if none of the terms or true. Or, if the term begins with "@" then the term is true if all of the capability letters in that term are available to the "anonymous" user. Or, if the term is "*" then it is always true. |
︙ | ︙ |